summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ChangeLog.ncr53c8xx36
-rw-r--r--drivers/scsi/ChangeLog.sym53c8xx219
-rw-r--r--drivers/scsi/Config.in17
-rw-r--r--drivers/scsi/Makefile40
-rw-r--r--drivers/scsi/NCR5380.c20
-rw-r--r--drivers/scsi/README.ibmmca979
-rw-r--r--drivers/scsi/README.ncr53c8xx147
-rw-r--r--drivers/scsi/README.st13
-rw-r--r--drivers/scsi/aha152x.c82
-rw-r--r--drivers/scsi/atp870u.c11
-rw-r--r--drivers/scsi/esp.c1332
-rw-r--r--drivers/scsi/esp.h23
-rw-r--r--drivers/scsi/fcal.c307
-rw-r--r--drivers/scsi/fcal.h46
-rw-r--r--drivers/scsi/gdth.c452
-rw-r--r--drivers/scsi/gdth.h283
-rw-r--r--drivers/scsi/gdth_proc.c606
-rw-r--r--drivers/scsi/gdth_proc.h3
-rw-r--r--drivers/scsi/hosts.c23
-rw-r--r--drivers/scsi/i60uscsi.c956
-rw-r--r--drivers/scsi/i60uscsi.h574
-rw-r--r--drivers/scsi/ibmmca.c3541
-rw-r--r--drivers/scsi/ibmmca.h63
-rw-r--r--drivers/scsi/ide-scsi.c20
-rw-r--r--drivers/scsi/imm.c26
-rw-r--r--drivers/scsi/inia100.c952
-rw-r--r--drivers/scsi/inia100.h503
-rw-r--r--drivers/scsi/megaraid.c1655
-rw-r--r--drivers/scsi/megaraid.h274
-rw-r--r--drivers/scsi/ncr53c8xx.c220
-rw-r--r--drivers/scsi/ncr53c8xx.h1085
-rw-r--r--drivers/scsi/pci2000.c343
-rw-r--r--drivers/scsi/pci2000.h105
-rw-r--r--drivers/scsi/pci2220i.c2024
-rw-r--r--drivers/scsi/pci2220i.h259
-rw-r--r--drivers/scsi/pluto.c33
-rw-r--r--drivers/scsi/pluto.h2
-rw-r--r--drivers/scsi/ppa.c5
-rw-r--r--drivers/scsi/ppa.h2
-rw-r--r--drivers/scsi/psi240i.c6
-rw-r--r--drivers/scsi/psi_dale.h169
-rw-r--r--drivers/scsi/psi_roy.h67
-rw-r--r--drivers/scsi/qlogicfas.c4
-rw-r--r--drivers/scsi/qlogicfc.c1921
-rw-r--r--drivers/scsi/qlogicfc.h102
-rw-r--r--drivers/scsi/qlogicfc_asm.c3292
-rw-r--r--drivers/scsi/qlogicisp.c119
-rw-r--r--drivers/scsi/qlogicisp_asm.c3288
-rw-r--r--drivers/scsi/qlogicpti.c121
-rw-r--r--drivers/scsi/qlogicpti.h20
-rw-r--r--drivers/scsi/qlogicpti_asm.c1172
-rw-r--r--drivers/scsi/scsi.c26
-rw-r--r--drivers/scsi/scsi.h2
-rw-r--r--drivers/scsi/scsi_error.c1
-rw-r--r--drivers/scsi/scsi_ioctl.c7
-rw-r--r--drivers/scsi/sd.c20
-rw-r--r--drivers/scsi/sd_ioctl.c5
-rw-r--r--drivers/scsi/sg.c1988
-rw-r--r--drivers/scsi/sr_ioctl.c19
-rw-r--r--drivers/scsi/sr_vendor.c10
-rw-r--r--drivers/scsi/st.c9
-rw-r--r--drivers/scsi/sym53c416.c806
-rw-r--r--drivers/scsi/sym53c416.h91
-rw-r--r--drivers/scsi/sym53c8xx.c11768
-rw-r--r--drivers/scsi/sym53c8xx.h116
-rw-r--r--drivers/scsi/sym53c8xx_defs.h1195
66 files changed, 36427 insertions, 7198 deletions
diff --git a/drivers/scsi/ChangeLog.ncr53c8xx b/drivers/scsi/ChangeLog.ncr53c8xx
index 0f9c85de5..d5fbbd59a 100644
--- a/drivers/scsi/ChangeLog.ncr53c8xx
+++ b/drivers/scsi/ChangeLog.ncr53c8xx
@@ -1,4 +1,38 @@
-Sat Jan 16 17:30 1998 Gerard Roudier (groudier@club-internet.fr)
+Thu Mar 11 23:00 1999 Gerard Roudier (groudier@club-internet.fr)
+ * revision 3.2 (8xx-896 driver bundle)
+ - Only define the host template in ncr53c8xx.h and include the
+ sym53c8xx_defs.h file.
+ - Declare static all symbols that donnot need to be visible from
+ outside the driver code.
+ - Add 'excl' boot command option that allows to pass to the driver
+ io address of devices not to attach.
+ - Add info() function called from the host template to print
+ driver/host information.
+ - Minor documentation additions.
+
+Sat Mar 6 11:00 1999 Gerard Roudier (groudier@club-internet.fr)
+ * revision 3.1h
+ - Fix some oooold bug that hangs the bus if a device rejects a
+ negotiation. Btw, the corresponding stuff also needed some cleanup
+ and thus the change is a bit larger than it could have been.
+ - Still some typo that made compilation fail for 64 bit (trivial fix).
+
+Sun Feb 14:00 1999 Gerard Roudier (groudier@club-internet.fr)
+ * revision 3.1g
+ - Deal correctly with 64 bit PCI address registers on Linux 2.2.
+ Pointed out by Leonard Zubkoff.
+ - Allow to tune request_irq() flags from the boot command line using
+ ncr53c8xx=irqm:??, as follows:
+ a) If bit 0x10 is set in irqm, SA_SHIRQ flag is not used.
+ b) If bit 0x20 is set in irqm, SA_INTERRUPT flag is not used.
+ By default the driver uses both SA_SHIRQ and SA_INTERRUPT.
+ Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by
+ a 53C8XX adapter and a network board.
+ - Tiny mispelling fixed (ABORT instead of ABRT). Was fortunately
+ harmless.
+ - Negotiate SYNC data transfers with CCS devices.
+
+Sat Jan 16 17:30 1999 Gerard Roudier (groudier@club-internet.fr)
* revision 3.1f
- Some PCI fix-ups not needed any more for PPC (from Cort).
- Cache line size set to 16 DWORDS for Sparc (from DSM).
diff --git a/drivers/scsi/ChangeLog.sym53c8xx b/drivers/scsi/ChangeLog.sym53c8xx
new file mode 100644
index 000000000..98656d359
--- /dev/null
+++ b/drivers/scsi/ChangeLog.sym53c8xx
@@ -0,0 +1,219 @@
+Sat Mar 20 21:00 1999 Gerard Roudier (groudier@club-internet.fr)
+ * version sym53c8xx-1.3b
+ - Add support for NCR PQS PDS.
+ James Bottomley <James.Bottomley@columbiasc.ncr.com>
+ - Allow value 0 for host ID.
+ - Support more than 8 controllers (> 40 in fact :-) )
+ - Add 'excl=#ioaddr' boot option: exclude controller.
+ (Version 1.3a driver)
+
+Thu Mar 11 23:00 1999 Gerard Roudier (groudier@club-internet.fr)
+ * version sym53c8xx-1.3 (8xx-896 driver bundle)
+ - Equivalent changes as ncr53c8xx-3.2 due to the driver bundle.
+ (See Changelog.ncr53c8xx)
+ - Do a normal soft reset as first chip reset, since aborting current
+ operation may raise an interrupt we are not able to handle since
+ the interrupt handler is not yet established.
+
+Sat Mar 6 11:00 1999 Gerard Roudier (groudier@club-internet.fr)
+ * version sym53c8xx-1.2b
+ - Fix some oooold bug that hangs the bus if a device rejects a
+ negotiation. Btw, the corresponding stuff also needed some cleanup
+ and thus the change is a bit larger than it could have been.
+ - Still some typo that made compilation fail for 64 bit (trivial fix).
+
+Sun Feb 21 20:00 1999 Gerard Roudier (groudier@club-internet.fr)
+ * version sym53c8xx-1.2a
+ - The rewrite of the interrupt handling broke the SBMC interrupt
+ handling due to a 1 bit mask tiny error. Hopefully fixed.
+ - If INQUIRY came from a scatter list, the driver looked into
+ the scatterlist instead of the data.:) Since this should never
+ happen, we just discard the data if use_sg is not zero.
+
+Fri Feb 12 23:00 1999 Gerard Roudier (groudier@club-internet.fr)
+ * version sym53c8xx-1.2
+ - Major rewrite of the interrupt handling and recovery stuff for
+ the support of non compliant SCSI removal, insertion and all
+ kinds of screw-up that may happen on the SCSI BUS.
+ Hopefully, the driver is now unbreakable or may-be, it is just
+ quite brocken. :-)
+ Many thanks to Johnson Russel (Symbios) for having responded to
+ my questions and for his interesting advices and comments about
+ support of SCSI hot-plug.
+ - Add 'recovery' option to driver set-up.
+ - Negotiate SYNC data transfers with CCS devices.
+ - Deal correctly with 64 bit PCI address registers on Linux 2.2.
+ Pointed out by Leonard Zubkoff.
+
+Sun Jan 31 18:00 1999 Gerard Roudier (groudier@club-internet.fr)
+ * version sym53c8xx-1.1a
+ - Some 896 chip revisions (all for now :-)), may hang-up if the
+ soft reset bit is set at the wrong time while SCRIPTS are running.
+ We need to first abort the current SCRIPTS operation prior to
+ resetting the chip. This fix has been sent to me by SYMBIOS/LSI
+ and I just translated it into ncr53c8xx syntax.
+ Must be considered 100 % trustable, unless I did some mistake
+ when translating it. :-)
+
+Sun Jan 24 18:00 1999 Gerard Roudier (groudier@club-internet.fr)
+ * version sym53c8xx-1.1
+ - Major rewrite of the SCSI parity error handling.
+ The informations contained in the data manuals are incomplete about
+ this feature.
+ I asked SYMBIOS about and got in reply the explanations that are
+ _indeed_ missing in the data manuals.
+ - Allow to tune request_irq() flags from the boot command line using
+ ncr53c8xx=irqm:??, as follows:
+ a) If bit 0x10 is set in irqm, SA_SHIRQ flag is not used.
+ b) If bit 0x20 is set in irqm, SA_INTERRUPT flag is not used.
+ By default the driver uses both SA_SHIRQ and SA_INTERRUPT.
+ Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by
+ a 53C8XX adapter and a network board.
+ - Fix for 64 bit PCI address register calculation. (Lance Robinson)
+ - Fix for big-endian in phase mismatch handling. (Michal Jaegermann)
+
+Fri Jan 1 20:00 1999 Gerard Roudier (groudier@club-internet.fr)
+ * version sym53c8xx-1.0a
+ - Waiting list look-up didn't work for the first command of the list.
+ Hopefully fixed, but tested on paper only. ;)
+ - Remove the most part of PPC specific code for Linux-2.2.
+ Thanks to Cort.
+ - Some other minors changes.
+
+Sat Dec 19 21:00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version sym53c8xx-1.0
+ - Define some new IO registers for the 896 (istat1, mbox0, mbox1)
+ - Revamp slighly the Symbios NVRAM lay-out based on the excerpt of
+ the header file I received from Symbios.
+ - Check the PCI bus number for the boot order (Using a fast
+ PCI controller behing a PCI-PCI bridge seems sub-optimal).
+ - Disable overlapped PCI arbitration for the 896 revision 1.
+ - Reduce a bit the number of IO register reads for phase mismatch
+ by reading DWORDS at a time instead of BYTES.
+
+Thu Dec 3 24:00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version pre-sym53c8xx-0.18
+ - I received this afternoon a 896 from SYMBIOS and started testing
+ the driver with this beast. After having fixed 3 buglets, it worked
+ with all features enabled including the phase mismatch handling
+ from SCRIPTS. Since this feature is not yet tested enough, the
+ boot option 'ncr53c8xx=specf:1' is still required to enable the
+ driver to handle PM from SCRIPTS.
+
+Sun Nov 29 18:00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version pre-sym53c8xx-0.17
+ - The SISL RAID change requires now remap_pci_mem() stuff to be
+ compiled for __i386__ when normal IOs are used.
+ - The PCI memory read from SCRIPTS that should ensure ordering
+ was in fact misplaced. BTW, this may explain why broken PCI
+ device drivers regarding ordering are working so well. ;-)
+ - Rewrite ncr53c8xx_setup (boot command line options) since the
+ binary code was a bit too bloated in my opinion.
+ - Make the code simpler in the wakeup_done routine.
+
+Tue Nov 24 23:00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version pre-sym53c8xx-0.16
+ - Add SCSI_NCR_OPTIMIZE_896_1 compile option and 'optim' boot option.
+ When set, the driver unconditionnaly assumes that the interrupt
+ handler is called for command completion, then clears INTF, scans
+ the done queue and returns if some completed CCB is found. If no
+ completed CCB are found, interrupt handling will proceed normally.
+ With a 896 that handles MA from SCRIPTS, this can be a great win,
+ since the driver will never performs PCI read transactions, but
+ only PCI write transactions that may be posted.
+ If the driver haven't to also raise the SIGP this would be perfect.
+ Even with this penalty, I think that this will work great.
+ Obviously this optimization makes sense only if the IRQ is not
+ shared with another device.
+ - Still a buglet in the tags initial settings that needed to be fixed.
+ It was not possible to disable TGQ at system startup for devices
+ that claim TGQ support. The driver used at least 2 for the queue
+ depth but did'nt keep track of user settings for tags depth lower
+ than 2.
+
+Thu Nov 19 23:00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version pre-sym53c8xx-0.15
+ - Add support for hardware LED control of the 896.
+ - Ignore chips that are driven by SISL RAID (DAC 960).
+ Change sent by Leonard Zubkoff and slightly reworked.
+ - Prevent 810A rev 11 and 860 rev 1 from using cache line based
+ transactions since those early chip revisions may use such on
+ LOAD/STORE instructions (work-around).
+ - Remove some useless and bloat code from the pci init stuff.
+ - Donnot use the readX()/writeX() kernel functions for __i386__,
+ since they perform useless masking operations in order to deal
+ with broken driver in 2.1.X kernel.
+
+Wed Nov 11 10:00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version pre-sym53c8xx-0.14
+ - The driver was unhappy when configured with default_tags > MAX_TAGS
+ Hopefully doubly-fixed.
+ - Set PCI_PARITY in PCI_COMMAND register in not set (PCI fix-up).
+ - Print out some message if phase mismatch is handled from SCRIPTS.
+
+Sun Nov 1 14H00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version pre-sym53c8xx-0.13
+ - Some rewrite of the device detection code. This code had been
+ patched too much and needed to be face-lifted a bit.
+ Remove all platform dependant fix-ups that was not needed or
+ conflicted with some other driver code as work-arounds.
+ Reread the NVRAM before the calling of ncr_attach(). This spares
+ stack space and so allows to handle more boards.
+ Handle 64 bit base addresses under linux-2.0.X.
+ Set MASTER bit in PCI COMMAND register if not set.
+
+Wed Oct 30 22H00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version pre-sym53c8xx-0.12
+ - Damned! I just broke the driver for Alpha by leaving a stale
+ instruction in the source code. Hopefully fixed.
+ - Donnot set PFEN when it is useless. Doing so we are sure that BOF
+ will be active, since the manual appears to be very unclear on what
+ feature is actually used by the chip when both PFEN and BOF are
+ set.
+
+Sat Oct 24 16H00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version pre-sym53c8xx-0.11
+ - LOAD/STORE instructions were miscompiled for register offsets
+ beyond 0x7f. This broke accesses to 896' new registers.
+ - Disable by default Phase Mismatch handling from SCRIPTS, since
+ current 896 rev.1 seems not to operate safely with the driver
+ when this feature is enabled (and above LOAD/STORE fix applied).
+ I will change the default to 'enabled' when this problem will be
+ solved.
+ Using boot option 'ncr53c8xx=specf:1' enables this feature.
+ - Implement a work-around (DEL 472 - ITEM 5) that should allow the
+ driver to safely enable hardware phase mismatch with 896 rev. 1.
+
+Tue Oct 20 22H00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version pre-sym53c8xx-0.10
+ - Add the 53c876 description to the chip table. This is only useful
+ for printing the right name of the controller.
+ - Add additionnal checking of INQUIRY data:
+ Check INQUIRY data received length is at least 7. Byte 7 of
+ inquiry data contains device features bits and the driver might
+ be confused by garbage. Also check peripheral qualifier.
+ - Use a 1,3,5,...MAXTAGS*2+1 tag numbering. Previous driver could
+ use any tag number from 1 to 253 and some non conformant devices
+ might have problems with large tag numbers.
+ - Use NAME53C and NAME53C8XX for chip name prefix chip family name.
+ Just give a try using "sym53c" and "sym53c8xx" instead of "ncr53c"
+ and "ncr53c8xx". :-)
+
+Sun Oct 11 17H00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version pre-sym53c8xx-0.9
+ - DEL-441 Item 2 work-around for the 53c876 rev <= 5 (0x15).
+ - Break ncr_scatter() into 2 functions in order to guarantee best
+ possible code optimization for the case we get a scatter list.
+ - Add the code intended to support up to 1 tera-byte for 64 bit systems.
+ It is probably too early, but I wanted to complete the thing.
+
+Sat Oct 3 14H00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * version pre-sym53c8xx-0.8
+ - Do some testing with io_mapped and fix what needed to be so.
+ - Wait for SCSI selection to complete or time-out immediately after
+ the chip won arbitration, since executing SCRIPTS while the SCSI
+ core is performing SCSI selection breaks the selection procedure
+ at least for some chip revisions.
+ - Interrupt the SCRIPTS if a device does not go to MSG OUT phase after
+ having been selected with ATN. Such a situation is not recoverable,
+ better to fail when we are stuck.
diff --git a/drivers/scsi/Config.in b/drivers/scsi/Config.in
index 686df3085..531222b5c 100644
--- a/drivers/scsi/Config.in
+++ b/drivers/scsi/Config.in
@@ -36,6 +36,9 @@ dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI
dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI
dep_tristate 'AMI MegaRAID support' CONFIG_SCSI_MEGARAID $CONFIG_SCSI
+if [ "$CONFIG_SCSI_MEGARAID" != "n" ]; then
+ bool ' Concurrent IO commands on MegaRAID' CONFIG_MEGARAID_MULTI_IO
+fi
dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI
if [ "$CONFIG_SCSI_BUSLOGIC" != "n" ]; then
@@ -52,9 +55,7 @@ dep_tristate 'EATA-DMA [Obsolete] (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatron
dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
dep_tristate 'Future Domain 16xx SCSI/AHA-2920A support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
if [ "$CONFIG_MCA" = "y" ]; then
- if [ "$CONFIG_SCSI" = "y" ]; then
- bool 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS
- fi
+ dep_tristate 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS $CONFIG_SCSI
fi
dep_tristate 'GDT SCSI Disk Array Controller support' CONFIG_SCSI_GDTH $CONFIG_SCSI
dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
@@ -66,6 +67,7 @@ if [ "$CONFIG_SCSI_GENERIC_NCR5380" != "n" ]; then
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 +78,7 @@ if [ "$CONFIG_PARPORT" != "n" ]; then
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
@@ -86,12 +89,16 @@ if [ "$CONFIG_PCI" = "y" ]; then
fi
if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_NCR53C7xx" != "y" ]; then
dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI
- if [ "$CONFIG_SCSI_NCR53C8XX" != "n" ]; then
+ dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI
+ if [ "$CONFIG_SCSI_NCR53C8XX" != "n" -o "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then
int ' default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8
int ' maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32
int ' synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 20
bool ' enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE
bool ' use normal IO' CONFIG_SCSI_NCR53C8XX_IOMAPPED
+ if [ "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then
+ bool ' include support for the NCR PQS/PDS SCSI card' CONFIG_SCSI_NCR53C8XX_PQS_PDS
+ fi
if [ "$CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS" = "0" ]; then
bool ' not allow targets to disconnect' CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
fi
@@ -117,7 +124,7 @@ dep_tristate 'PSI240i support' CONFIG_SCSI_PSI240I $CONFIG_SCSI
dep_tristate 'Qlogic FAS SCSI support' CONFIG_SCSI_QLOGIC_FAS $CONFIG_SCSI
if [ "$CONFIG_PCI" = "y" ]; then
dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI
-# 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 --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index b7d5c5814..ccbb8af5f 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -298,6 +298,14 @@ else
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
@@ -474,6 +482,14 @@ else
endif
endif
+ifeq ($(CONFIG_SCSI_SYM53C8XX),y)
+L_OBJS += sym53c8xx.o
+else
+ ifeq ($(CONFIG_SCSI_SYM53C8XX),m)
+ M_OBJS += sym53c8xx.o
+ endif
+endif
+
ifeq ($(CONFIG_SCSI_PAS16),y)
L_OBJS += pas16.o
else
@@ -517,9 +533,12 @@ endif
ifeq ($(CONFIG_SCSI_FD_MCS),y)
L_OBJS += fd_mcs.o
+else
+ ifeq ($(CONFIG_SCSI_FD_MCS),m)
+ M_OBJS += fd_mcs.o
+ endif
endif
-
ifeq ($(CONFIG_SCSI_T128),y)
L_OBJS += t128.o
else
@@ -552,6 +571,14 @@ else
endif
endif
+ifeq ($(CONFIG_SCSI_FCAL),y)
+L_OBJS += fcal.o
+else
+ ifeq ($(CONFIG_SCSI_FCAL),m)
+ M_OBJS += fcal.o
+ endif
+endif
+
ifeq ($(CONFIG_SCSI_EATA),y)
L_OBJS += eata.o
else
@@ -576,6 +603,14 @@ else
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
@@ -621,6 +656,9 @@ initio.o: ini9100u.c i91uscsi.c
$(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 --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 3aff27f32..56ae04b72 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -569,10 +569,6 @@ static __inline__ void run_main(void)
if (!main_running) {
main_running = 1;
NCR5380_main();
- /*
- * main_running is cleared in NCR5380_main once it can't do
- * more work, and NCR5380_main exits with interrupts disabled.
- */
}
restore_flags(flags);
}
@@ -702,7 +698,9 @@ void NCR5380_timer_fn(unsigned long surplus_to_requirements)
}
restore_flags(flags);
+ spin_lock_irqsave(&io_request_lock, flags);
run_main();
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
#endif /* def USLEEP */
@@ -1266,6 +1264,7 @@ static void NCR5380_main(void) {
struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata;
int done;
+ unsigned long flags;
/*
* We run (with interrupts disabled) until we're sure that none of
@@ -1279,14 +1278,16 @@ static void NCR5380_main(void) {
* this should prevent any race conditions.
*/
+ spin_unlock_irq(&io_request_lock);
+
+ save_flags(flags);
+
do {
cli(); /* Freeze request queues */
done = 1;
for (instance = first_instance; instance &&
instance->hostt == the_template; instance = instance->next) {
- unsigned long flags;
hostdata = (struct NCR5380_hostdata *) instance->hostdata;
- save_flags(flags);
cli();
#ifdef USLEEP
if (!hostdata->connected && !hostdata->selecting) {
@@ -1365,8 +1366,6 @@ static void NCR5380_main(void) {
TAG_NEXT)) {
break;
} else {
- unsigned long flags;
- save_flags(flags);
cli();
LIST(tmp, hostdata->issue_queue);
tmp->host_scribble = (unsigned char *)
@@ -1393,14 +1392,12 @@ static void NCR5380_main(void) {
}
else
{
- unsigned long flags;
/* RvC: device failed, so we wait a long time
this is needed for Mustek scanners, that
do not respond to commands immediately
after a scan */
printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n",
instance->host_no, tmp->target);
- save_flags(flags);
cli();
LIST(tmp, hostdata->issue_queue);
tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
@@ -1434,7 +1431,8 @@ static void NCR5380_main(void) {
break;
} /* for instance */
} while (!done);
- cli();
+ spin_lock_irq(&io_request_lock);
+ /* cli();*/
main_running = 0;
}
diff --git a/drivers/scsi/README.ibmmca b/drivers/scsi/README.ibmmca
new file mode 100644
index 000000000..61fd18e51
--- /dev/null
+++ b/drivers/scsi/README.ibmmca
@@ -0,0 +1,979 @@
+
+
+ -=< The IBM Microchannel SCSI-Subsystem >=-
+
+ for the IBM PS/2 series
+
+ Low Level Software-Driver for Linux
+
+ Copyright (c) 1995 Strom Systems, Inc. under the terms of the GNU
+ General Public License. Originally written by Martin Kolinek, December 1995.
+ Officially maintained by Michael Lang since January 1999.
+
+ Version 3.1e
+
+
+ Last update: 20 February 1999
+
+
+ Authors of this Driver
+ ----------------------
+ - Chris Beauregard (improvement of the SCSI-device mapping by the driver)
+ - Martin Kolinek (origin, first release of this driver)
+ - Klaus Kudielka (multiple SCSI-host management/detection, adaption to
+ Linux Kernel 2.1.x, module support)
+ - Michael Lang (assigning original pun,lun mapping, dynamical ldn
+ assignment, this file, patch, official driver maintenance)
+
+ Table of Contents
+ -----------------
+ 1 Abstract
+ 2 Driver Description
+ 2.1 IBM SCSI-Subsystem Detection
+ 2.2 Physical Units, Logical Units, and Logical Devices
+ 2.3 SCSI-Device Recognition and dynamical ldn Assignment
+ 2.4 SCSI-Device Order
+ 2.5 Regular SCSI-Command-Processing
+ 2.6 Abort & Reset Commands
+ 2.7 Disk Geometry
+ 2.8 Kernel Boot Option
+ 2.9 Driver Module Support
+ 2.10 Multiple Hostadapter Support
+ 2.11 /proc/scsi-Filesystem Information
+ 2.12 /proc/mca-Filesystem Information
+ 2.13 Supported IBM SCSI-Subsystems
+ 2.14 Linux Kernel Versions
+ 3 Code History
+ 4 To do
+ 5 Users' Manual
+ 5.1 Commandline Parameters
+ 5.2 Troubleshooting
+ 5.3 Bugreports
+ 5.4 Support WWW-page
+ 6 References
+ 7 Trademarks
+
+ * * *
+
+ 1 Abstract
+ ----------
+ This README-file describes the IBM SCSI-subsystem low level driver for
+ Linux. The descriptions which were formerly kept in the source-code have
+ been taken out to this file to easify the codes' readability. The driver
+ description has been updated, as most of the former description was already
+ quite outdated. The history of the driver development is also kept inside
+ here. Multiple historical developments have been summarized to shorten the
+ textsize a bit. At the end of this file you can find a small manual for
+ this driver and hints to get it running even on your machine (hopefully).
+
+ 2 Driver Description
+ --------------------
+ 2.1 IBM SCSI-Subsystem Detection
+ --------------------------------
+ This is done in the ibmmca_detect() function. It first checks, if the
+ Microchannel-bus support is enabled, as the IBM SCSI-subsystem needs the
+ Microchannel. In a next step, a free interrupt is chosen and the main
+ interrupt handler is connected to it to handle answers of the SCSI-
+ subsystem(s). In a further step, it is checked, wether there was a forced
+ detection of the adapter via the kernel commandline, where the I/O port
+ and the SCSI-subsystem id can be specified. The next step checks if there
+ is an integrated SCSI-subsystem installed. This register area is fixed
+ through all IBM PS/2 MCA-machines and appears as something like a virtual
+ slot 10 of the MCA-bus. If POS-register 2 is not 0xff, there must be a SCSI-
+ subsystem present and it will be registered as IBM Integrated SCSI-
+ Subsystem. The next step checks, if there is a slot-adapter installed on
+ the MCA-bus. To get this, the first two POS-registers, that represent the
+ adapter ID are checked. If they fit to one of the ids, stored in the
+ adapter list, a SCSI-subsystem is assumed to be found and will be
+ registered. This check is done through all possible MCA-bus slots to allow
+ more than one SCSI-adapter to be present in the PS/2-system and this is
+ already the first point of problems. Looking into the technical reference
+ manual for the IBM PS/2 common interfaces, the POS2 register must have
+ different interpretation of its single bits. While one can assume, that the
+ integrated subsystem has a fix I/O-address at 0x3540 - 0x3547, further
+ installed IBM SCSI-adapters must use a different I/O-address. This is
+ expressed by bit 1 to 3 of POS2 (multiplied by 8 + 0x3540). Bits 2 and 3
+ are reserved for the integrated subsystem, but not for the adapters! The
+ following list shows, how the bits of POS2 and POS3 should be interpreted.
+
+ The POS2-register of all PS/2 models' integrated SCSI-subsystems has the
+ following interpretation of bits:
+ Bit 7 - 4 : Chip Revision ID (Release)
+ Bit 3 - 2 : Reserved
+ Bit 1 : 8k NVRAM Disabled
+ Bit 0 : Chip Enable (EN-Signal)
+ The POS3-register is interpreted as follows (for ALL IBM SCSI-subsys.):
+ Bit 7 - 5 : SCSI ID
+ Bit 4 - 0 : Reserved = 0
+ (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common
+ Interfaces (1991)").
+ In short words, this means, that IBM PS/2 machines only support 1 single
+ subsystem by default. But (additional) slot-adapters must have another
+ configuration on pos2 in order to be enabled to use more than one IBM SCSI-
+ subsystem, e.g. for a network server. From tests with the IBM SCSI Adapter
+ w/cache, the POS2-register for slot adapters should be interpreted in the
+ following way:
+ Bit 7 - 4 : Chip Revision ID (Release)
+ Bit 3 - 1 : port offset factor ( * 8 + 0x3540 )
+ Bit 0 : Chip Enable (EN-Signal)
+
+ One day I found a patch in ibmmca_detect(), forcing the I/O-address to be
+ 0x3540 for integrated SCSI-subsystems, there was a remark placed, that on
+ integrated IBM SCSI-subsystems of model 56, the POS2 register was showing 5.
+ This means, that really for these models, POS2 has to be interpreted
+ sticking to the technical reference guide. In this case, the bit 2 (4) is
+ a reserved bit and may not be interpreted. These differences between the
+ adapters and the integrated controllers are taken into account by the
+ detection routine of the driver on from version >3.0g.
+
+ Every time, a SCSI-subsystem is discovered, the ibmmca_register() function
+ is called. This function checks first, if the requested area for the I/O-
+ address of this SCSI-subsystem is still available and assigns this I/O-
+ area to the SCSI-subsystem. There are always 8 sequential I/O-addresses
+ taken for each individual SCSI-subsystem found, which are:
+
+ Offset Type Permissions
+ 0 Command Interface Register 1 Read/Write
+ 1 Command Interface Register 2 Read/Write
+ 2 Command Interface Register 3 Read/Write
+ 3 Command Interface Register 4 Read/Write
+ 4 Attention Register Read/Write
+ 5 Basic Control Register Read/Write
+ 6 Interrupt Status Register Read
+ 7 Basic Status Register Read
+
+ After the I/O-address range is assigned, the host-adapter is assigned
+ to a local structure which keeps all adapter information needed for the
+ driver itself and the mid- and higher-level SCSI-drivers. The SCSI pun/lun
+ and the adapters' ldn tables are initialized and get probed afterwards by
+ the check_devices() function. If no further adapters are found,
+ ibmmca_detect() quits.
+
+ 2.2 Physical Units, Logical Units, and Logical Devices
+ ------------------------------------------------------
+ There can be up to 56 devices on the SCSI bus (besides the adapter):
+ there are up to 7 "physical units" (each identified by physical unit
+ number or pun, also called the scsi id, this is the number you select
+ with hardware jumpers), and each physical unit can have up to 8
+ "logical units" (each identified by logical unit number, or lun,
+ between 0 and 7).
+
+ Typically the adapter has pun=7, so puns of other physical units
+ are between 0 and 6. Almost all physical units have only one
+ logical unit, with lun=0. A CD-ROM jukebox would be an example of
+ a physical unit with more than one logical unit.
+
+ The embedded microprocessor of the IBM SCSI-subsystem hides the complex
+ two-dimensional (pun,lun) organization from the operating system.
+ When the machine is powered-up (or rebooted), the embedded microprocessor
+ checks, on its own, all 56 possible (pun,lun) combinations, and the first
+ 15 devices found are assigned into a one-dimensional array of so-called
+ "logical devices", identified by "logical device numbers" or ldn. The last
+ ldn=15 is reserved for the subsystem itself.
+
+ 2.3 SCSI-Device Recognition and dynamical ldn Assignment
+ --------------------------------------------------------
+ One consequence of information hiding is that the real (pun,lun)
+ numbers are also hidden. The two possibilities to get around this problem
+ is to offer fake pun/lun combinations to the operating system or to
+ delete the whole mapping of the adapter and to reassign the ldns, using
+ the immediate assign command of the SCSI-subsystem. At the beginning of the
+ development of this driver, the following approach was used:
+ First, the driver checked the ldn's (0 to 6) to find out which ldn's
+ have devices assigned. This was done by the functions check_devices() and
+ device_exists(). The interrupt handler has a special paragraph of code
+ (see local_checking_phase_flag) to assist in the checking. Assume, for
+ example, that three logical devices were found assigned at ldn 0, 1, 2.
+ These are presented to the upper layer of Linux SCSI driver
+ as devices with bogus (pun, lun) equal to (0,0), (1,0), (2,0).
+ On the other hand, if the upper layer issues a command to device
+ say (4,0), this driver returns DID_NO_CONNECT error.
+
+ In a second step of the driver development, the following improvement has
+ been applied: The first approach limited the number of devices to 7, far
+ fewer than the 15 that it could usem then it just maped ldn ->
+ (ldn/8,ldn%8) for pun,lun. We ended up with a real mishmash of puns
+ and luns, but it all seemed to work.
+
+ The latest development, which is implemented from the driver version 3.0
+ and later, realizes the device recognition in the following way:
+ The physical SCSI-devices on the SCSI-bus are probed via immediate_assign-
+ and device_inquiry-commands, that is all implemented in a completely new
+ made check_devices() subroutine. This delivers a exact map of the physical
+ SCSI-world that is now stored in the get_scsi[][]-array. This means,
+ that the once hidden pun,lun assignment is now known to this driver.
+ It no longer believes in default-settings of the subsystem and maps all
+ ldns to existing pun,lun "by foot". This assures full control of the ldn
+ mapping and allows dynamical remapping of ldns to different pun,lun, if
+ there are more SCSI-devices installed than ldns available (n>15). The
+ ldns from 0 to 6 get 'hardwired' by this driver to puns 0 to 7 at lun=0,
+ excluding the pun of the subsystem. This assures, that at least simple
+ SCSI-installations have optimum access-speed and are not touched by
+ dynamical remapping. The ldns 7 to 14 are put to existing devices with
+ lun>0 or to non-existing devices, in order to satisfy the subsystem, if
+ there are less than 15 SCSI-devices connected. In the case of more than 15
+ devices, the dynamical mapping goes active. If the get_scsi[][] reports a
+ device to be existant, but it has no ldn assigned, it gets a ldn out of 7
+ to 14. The numbers are assigned in cyclic order. Therefore it takes 8
+ dynamical reassignments on the SCSI-devices, until a certain device
+ looses its ldn again. This assures, that dynamical remapping is avoided
+ during intense I/O between up to 15 SCSI-devices (means pun,lun
+ combinations). A further advantage of this method is, that people who
+ build their kernel without probing on all luns will get what they expect,
+ because the driver just won't assign everything with lun>0 when
+ multpile lun probing is inactive.
+
+ 2.4 SCSI-Device Order
+ ---------------------
+ Because of the now correct recognition of physical pun,lun, and
+ their report to mid-level- and higher-level-drivers, the new reported puns
+ can be different from the old, faked puns. Therefore, Linux will eventually
+ change /dev/sdXXX assignments and prompt you for corrupted superblock
+ repair on boottime. In this case DO NOT PANIC, YOUR DISKS ARE STILL OK!!!
+ You have to reboot (CTRL-D) with a old kernel and set the /etc/fstab-file
+ entries right. After that, the system should come up as errorfree as before.
+ If your boot-partition is not coming up, also edit the /etc/lilo.conf-file
+ in a Linux session booted on old kernel and run lilo before reboot. Check
+ lilo.conf anyway to get boot on other partitions with foreign OSes right
+ again. But there exists a feature of this driver that allows you to change
+ the assignment order of the SCSI-devices by flipping the PUN-assignment.
+ See the next paragraph for a description.
+
+ The problem for this is, that Linux does not assign the SCSI-devices in the
+ way as described in the ANSI-SCSI-standard. Linux assigns /dev/sda to
+ the device with at minimum id 0. But the first drive should be at id 6,
+ because for historical reasons, drive at id 6 has, by hardware, the highest
+ priority and a drive at id 0 the lowest. IBM was one of the rare producers,
+ where the BIOS assigns drives belonging to the ANSI-SCSI-standard. Most
+ other producers' BIOS does not (I think even Adaptec-BIOS). The
+ IBMMCA_SCSI_ORDER_STANDARD flag, which you set while configuring the
+ kernel enables to choose the preferred way of SCSI-device-assignment.
+ Defining this flag would result in Linux determining the devices in the
+ same order as DOS and OS/2 does on your MCA-machine. This is also standard
+ on most industrial computers and OSes, like e.g. OS-9. Leaving this flag
+ undefined will get your devices ordered in the default way of Linux. See
+ also the remarks of Chris Beauregard from Dec 15, 1997 and the followups
+ in section 3.
+
+ 2.5 Regular SCSI-Command-Processing
+ -----------------------------------
+ Only three functions get involved: ibmmca_queuecommand(), issue_cmd(),
+ and interrupt_handler().
+
+ The upper layer issues a scsi command by calling function
+ ibmmca_queuecommand(). This function fills a "subsystem control block"
+ (scb) and calls a local function issue_cmd(), which writes a scb
+ command into subsystem I/O ports. Once the scb command is carried out,
+ the interrupt_handler() is invoked. If a device is determined to be
+ existant and it has not assigned any ldn, it gets one dynamically.
+ For this, the whole stuff is done in ibmmca_queuecommand().
+
+ 2.6 Abort & Reset Commands
+ --------------------------
+ These are implemented with busy waiting for interrupt to arrive.
+ ibmmca_reset() and ibmmca_abort() do not work sufficently well
+ up to now and need still a lot of development work. But, this seems
+ to be even a problem with other SCSI-low level drivers, too. However,
+ this should be no excuse.
+
+ 2.7 Disk Geometry
+ -----------------
+ The ibmmca_biosparams() function should return the same disk geometry
+ as the bios. This is needed for fdisk, etc. The returned geometry is
+ certainly correct for disks smaller than 1 gigabyte. In the meantime,
+ it has been proved, that this works fine even with disks larger than
+ 1 gigabyte.
+
+ 2.8 Kernel Boot Option
+ ----------------------
+ The function ibmmca_scsi_setup() is called if option ibmmcascsi=n
+ is passed to the kernel. See file linux/init/main.c for details.
+
+ 2.9 Driver Module Support
+ -------------------------
+ Is implemented and tested by K. Kudielka. This could probably not work
+ on kernels <2.1.0.
+
+ 2.10 Multiple Hostadapter Support
+ ---------------------------------
+ This driver supports up to eight interfaces of type IBM-SCSI-Subsystem.
+ Integrated-, and MCA-adapters are automatically recognized. Unrecognizable
+ IBM-SCSI-Subsystem interfaces can be specified as kernel-parameters.
+
+ 2.11 /proc/scsi-Filesystem Information
+ --------------------------------------
+ Information about the driver condition is given in
+ /proc/scsi/ibmmca/<host_no>. ibmmca_proc_info() provides this information.
+
+ This table is quite informative for interested users. It shows the load
+ of commands on the subsystem and wether you are running the bypassed
+ (software) or integrated (hardware) SCSI-command set (see below). The
+ amount of accesses is shown. Read, write, modeselect is shown seperately
+ in order to help debugging problems with CD-ROMs or tapedrives.
+
+ The following table shows the list of 15 logical device numbers, that are
+ used by the SCSI-subsystem. The load on each ldn is shown in the table,
+ again, read and write commands are split. The last column shows the amount
+ of reassignments, that have been applied to the ldns, if you have more than
+ 15 pun/lun combinations available on the SCSI-bus.
+
+ The last two tables show the pun/lun map and the positions of the ldns
+ on this pun/lun map. This may change during operation, when a ldn is
+ reassigned to another pun/lun combination. If the necessity for dynamical
+ assignments is set to 'no', the ldn structure keeps static.
+
+ 2.12 /proc/mca-Filesystem Information
+ -------------------------------------
+ The slot-file contains all default entries and in addition chip and I/O-
+ address information of the SCSI-subsystem. This information is provided
+ by ibmmca_getinfo().
+
+ 2.13 Supported IBM SCSI-Subsystems
+ ----------------------------------
+ The following IBM SCSI-subsystems are supported by this driver:
+
+ - IBM Fast SCSI-2 Adapter
+ - IBM 7568 Industrial Computer SCSI Adapter w/cache
+ - IBM Expansion Unit SCSI Controller
+ - IBM SCSI Adapter w/Cache
+ - IBM SCSI Adapter
+ - IBM Integrated SCSI Controller
+
+ 2.14 Linux Kernel Versions
+ --------------------------
+ The IBM SCSI-subsystem low level driver is prepared to be used with
+ all versions of Linux between 2.0.x and 2.2.x. The compatibility checks
+ are fully implemented up from version 3.1e of the driver. This means, that
+ you just need the latest ibmmca.h and ibmmca.c file and copy it in the
+ linux/drivers/scsi directory. The code is automatically adapted during
+ kernel compilation.
+
+ 3 Code History
+ --------------
+ Jan 15 1996: First public release.
+ - Martin Kolinek
+
+ Jan 23 1996: Scrapped code which reassigned scsi devices to logical
+ device numbers. Instead, the existing assignment (created
+ when the machine is powered-up or rebooted) is used.
+ A side effect is that the upper layer of Linux SCSI
+ device driver gets bogus scsi ids (this is benign),
+ and also the hard disks are ordered under Linux the
+ same way as they are under dos (i.e., C: disk is sda,
+ D: disk is sdb, etc.).
+ - Martin Kolinek
+
+ I think that the CD-ROM is now detected only if a CD is
+ inside CD_ROM while Linux boots. This can be fixed later,
+ once the driver works on all types of PS/2's.
+ - Martin Kolinek
+
+ Feb 7 1996: Modified biosparam function. Fixed the CD-ROM detection.
+ For now, devices other than harddisk and CD_ROM are
+ ignored. Temporarily modified abort() function
+ to behave like reset().
+ - Martin Kolinek
+
+ Mar 31 1996: The integrated scsi subsystem is correctly found
+ in PS/2 models 56,57, but not in model 76. Therefore
+ the ibmmca_scsi_setup() function has been added today.
+ This function allows the user to force detection of
+ scsi subsystem. The kernel option has format
+ ibmmcascsi=n
+ where n is the scsi_id (pun) of the subsystem. Most likely, n is 7.
+ - Martin Kolinek
+
+ Aug 21 1996: Modified the code which maps ldns to (pun,0). It was
+ insufficient for those of us with CD-ROM changers.
+ - Chris Beauregard
+
+ Dec 14 1996: More improvements to the ldn mapping. See check_devices
+ for details. Did more fiddling with the integrated SCSI detection,
+ but I think it's ultimately hopeless without actually testing the
+ model of the machine. The 56, 57, 76 and 95 (ultimedia) all have
+ different integrated SCSI register configurations. However, the 56
+ and 57 are the only ones that have problems with forced detection.
+ - Chris Beauregard
+
+ Mar 8-16 1997: Modified driver to run as a module and to support
+ multiple adapters. A structure, called ibmmca_hostdata, is now
+ present, containing all the variables, that were once only
+ available for one single adapter. The find_subsystem-routine has vanished.
+ The hardware recognition is now done in ibmmca_detect directly.
+ This routine checks for presence of MCA-bus, checks the interrupt
+ level and continues with checking the installed hardware.
+ Certain PS/2-models do not recognize a SCSI-subsystem automatically.
+ Hence, the setup defined by command-line-parameters is checked first.
+ Thereafter, the routine probes for an integrated SCSI-subsystem.
+ Finally, adapters are checked. This method has the advantage to cover all
+ possible combinations of multiple SCSI-subsystems on one MCA-board. Up to
+ eight SCSI-subsystems can be recognized and announced to the upper-level
+ drivers with this improvement. A set of defines made changes to other
+ routines as small as possible.
+ - Klaus Kudielka
+
+ May 30 1997: (v1.5b)
+ 1) SCSI-command capability enlarged by the recognition of MODE_SELECT.
+ This needs the RD-Bit to be disabled on IM_OTHER_SCSI_CMD_CMD which
+ allows data to be written from the system to the device. It is a
+ necessary step to be allowed to set blocksize of SCSI-tape-drives and
+ the tape-speed, whithout confusing the SCSI-Subsystem.
+ 2) The recognition of a tape is included in the check_devices routine.
+ This is done by checking for TYPE_TAPE, that is already defined in
+ the kernel-scsi-environment. The markup of a tape is done in the
+ global ldn_is_tape[] array. If the entry on index ldn
+ is 1, there is a tapedrive connected.
+ 3) The ldn_is_tape[] array is necessary to distinguish between tape- and
+ other devices. Fixed blocklength devices should not cause a problem
+ with the SCB-command for read and write in the ibmmca_queuecommand
+ subroutine. Therefore, I only derivate the READ_XX, WRITE_XX for
+ the tape-devices, as recommended by IBM in this Technical Reference,
+ mentioned below. (IBM recommends to avoid using the read/write of the
+ subsystem, but the fact was, that read/write causes a command error from
+ the subsystem and this causes kernel-panic.)
+ 4) In addition, I propose to use the ldn instead of a fix char for the
+ display of PS2_DISK_LED_ON(). On 95, one can distinguish between the
+ devices that are accessed. It shows activity and easyfies debugging.
+ The tape-support has been tested with a SONY SDT-5200 and a HP DDS-2
+ (I do not know yet the type). Optimization and CD-ROM audio-support,
+ I am working on ...
+ - Michael Lang
+
+ June 19 1997: (v1.6b)
+ 1) Submitting the extra-array ldn_is_tape[] -> to the local ld[]
+ device-array.
+ 2) CD-ROM Audio-Play seems to work now.
+ 3) When using DDS-2 (120M) DAT-Tapes, mtst shows still density-code
+ 0x13 for ordinary DDS (61000 BPM) instead 0x24 for DDS-2. This appears
+ also on Adaptec 2940 adaptor in a PCI-System. Therefore, I assume that
+ the problem is independent of the low-level-driver/bus-architecture.
+ 4) Hexadecimal ldn on PS/2-95 LED-display.
+ 5) Fixing of the PS/2-LED on/off that it works right with tapedrives and
+ does not confuse the disk_rw_in_progress counter.
+ - Michael Lang
+
+ June 21 1997: (v1.7b)
+ 1) Adding of a proc_info routine to inform in /proc/scsi/ibmmca/<host> the
+ outer-world about operational load statistics on the different ldns,
+ seen by the driver. Everybody that has more than one IBM-SCSI should
+ test this, because I only have one and cannot see what happens with more
+ than one IBM-SCSI hosts.
+ 2) Definition of a driver version-number to have a better recognition of
+ the source when there are existing too much releases that may confuse
+ the user, when reading about release-specific problems. Up to know,
+ I calculated the version-number to be 1.7. Because we are in BETA-test
+ yet, it is today 1.7b.
+ 3) Sorry for the heavy bug I programmed on June 19 1997! After that, the
+ CD-ROM did not work any more! The C7-command was a fake impression
+ I got while programming. Now, the READ and WRITE commands for CD-ROM are
+ no longer running over the subsystem, but just over
+ IM_OTHER_SCSI_CMD_CMD. On my observations (PS/2-95), now CD-ROM mounts
+ much faster(!) and hopefully all fancy multimedia-functions, like direct
+ digital recording from audio-CDs also work. (I tried it with cdda2wav
+ from the cdwtools-package and it filled up the harddisk immediately :-).)
+ To easify boolean logics, a further local device-type in ld[], called
+ is_cdrom has been included.
+ 4) If one uses a SCSI-device of unsupported type/commands, one
+ immediately runs into a kernel-panic caused by Command Error. To better
+ understand which SCSI-command caused the problem, I extended this
+ specific panic-message slightly.
+ - Michael Lang
+
+ June 25 1997: (v1.8b)
+ 1) Some cosmetical changes for the handling of SCSI-device-types.
+ Now, also CD-Burners / WORMs and SCSI-scanners should work. For
+ MO-drives I have no experience, therefore not yet supported.
+ In logical_devices I changed from different type-variables to one
+ called 'device_type' where the values, corresponding to scsi.h,
+ of a SCSI-device are stored.
+ 2) There existed a small bug, that maps a device, coming after a SCSI-tape
+ wrong. Therefore, e.g. a CD-ROM changer would have been mapped wrong
+ -> problem removed.
+ 3) Extension of the logical_device structure. Now it contains also device,
+ vendor and revision-level of a SCSI-device for internal usage.
+ - Michael Lang
+
+ June 26-29 1997: (v2.0b)
+ 1) The release number 2.0b is necessary because of the completely new done
+ recognition and handling of SCSI-devices with the adapter. As I got
+ from Chris the hint, that the subsystem can reassign ldns dynamically,
+ I remembered this immediate_assign-command, I found once in the handbook.
+ Now, the driver first kills all ldn assignments that are set by default
+ on the SCSI-subsystem. After that, it probes on all puns and luns for
+ devices by going through all combinations with immediate_assign and
+ probing for devices, using device_inquiry. The found physical(!) pun,lun
+ structure is stored in get_scsi[][] as device types. This is followed
+ by the assignment of all ldns to existing SCSI-devices. If more ldns
+ than devices are available, they are assigned to non existing pun,lun
+ combinations to satisfy the adapter. With this, the dynamical mapping
+ was possible to implement. (For further info see the text in the
+ source-code and in the description below. Read the description
+ below BEFORE installing this driver on your system!)
+ 2) Changed the name IBMMCA_DRIVER_VERSION to IBMMCA_SCSI_DRIVER_VERSION.
+ 3) The LED-display shows on PS/2-95 no longer the ldn, but the SCSI-ID
+ (pun) of the accessed SCSI-device. This is now senseful, because the
+ pun known within the driver is exactly the pun of the physical device
+ and no longer a fake one.
+ 4) The /proc/scsi/ibmmca/<host_no> consists now of the first part, where
+ hit-statistics of ldns is shown and a second part, where the maps of
+ physical and logical SCSI-devices are displayed. This could be very
+ interesting, when one is using more than 15 SCSI-devices in order to
+ follow the dynamical remapping of ldns.
+ - Michael Lang
+
+ June 26-29 1997: (v2.0b-1)
+ 1) I forgot to switch the local_checking_phase_flag to 1 and back to 0
+ in the dynamical remapping part in ibmmca_queuecommand for the
+ device_exist routine. Sorry.
+ - Michael Lang
+
+ July 1-13 1997: (v3.0b,c)
+ 1) Merging of the driver-developments of Klaus Kudielka and Michael Lang
+ in order to get a optimum and unified driver-release for the
+ IBM-SCSI-Subsystem-Adapter(s).
+ For people, using the Kernel-release >=2.1.0, module-support should
+ be no problem. For users, running under <2.1.0, module-support may not
+ work, because the methods have changed between 2.0.x and 2.1.x.
+ 2) Added some more effective statistics for /proc-output.
+ 3) Change typecasting at necessary points from (unsigned long) to
+ virt_to_bus().
+ 4) Included #if... at special points to have specific adaption of the
+ driver to kernel 2.0.x and 2.1.x. It should therefore also run with
+ later releases.
+ 5) Magneto-Optical drives and medium-changers are also recognized, now.
+ Therefore, we have a completely gapfree recognition of all SCSI-
+ device-types, that are known by Linux up to kernel 2.1.31.
+ 6) The flag SCSI_IBMMCA_DEV_RESET has been inserted. If it is set within
+ the configuration, each connected SCSI-device will get a reset command
+ during boottime. This can be necessary for some special SCSI-devices.
+ This flag should be included in Config.in.
+ (See also the new Config.in file.)
+ Probable next improvement: bad disk handler.
+ - Michael Lang
+
+ Sept 14 1997: (v3.0c)
+ 1) Some debugging and speed optimization applied.
+ - Michael Lang
+
+ Dec 15, 1997
+ - chrisb@truespectra.com
+ - made the front panel display thingy optional, specified from the
+ command-line via ibmmcascsi=display. Along the lines of the /LED
+ option for the OS/2 driver.
+ - fixed small bug in the LED display that would hang some machines.
+ - reversed ordering of the drives (using the
+ IBMMCA_SCSI_ORDER_STANDARD define). This is necessary for two main
+ reasons:
+ - users who've already installed Linux won't be screwed. Keep
+ in mind that not everyone is a kernel hacker.
+ - be consistent with the BIOS ordering of the drives. In the
+ BIOS, id 6 is C:, id 0 might be D:. With this scheme, they'd be
+ backwards. This confuses the crap out of those heathens who've
+ got a impure Linux installation (which, <wince>, I'm one of).
+ This whole problem arises because IBM is actually non-standard with
+ the id to BIOS mappings. You'll find, in fdomain.c, a similar
+ comment about a few FD BIOS revisions. The Linux (and apparently
+ industry) standard is that C: maps to scsi id (0,0). Let's stick
+ with that standard.
+ - Since this is technically a branch of my own, I changed the
+ version number to 3.0e-cpb.
+
+ Jan 17, 1998: (v3.0f)
+ 1) Addition of some statistical info for /proc in proc_info.
+ 2) Taking care of the SCSI-assignment problem, dealed by Chris at Dec 15
+ 1997. In fact, IBM is right, concerning the assignment of SCSI-devices
+ to driveletters. It is conform to the ANSI-definition of the SCSI-
+ standard to assign drive C: to SCSI-id 6, because it is the highest
+ hardware priority after the hostadapter (that has still today by
+ default everywhere id 7). Also realtime-operating systems that I use,
+ like LynxOS and OS9, which are quite industrial systems use top-down
+ numbering of the harddisks, that is also starting at id 6. Now, one
+ sits a bit between two chairs. On one hand side, using the define
+ IBMMCA_SCSI_ORDER_STANDARD makes Linux assigning disks conform to
+ the IBM- and ANSI-SCSI-standard and keeps this driver downward
+ compatible to older releases, on the other hand side, people is quite
+ habituated in believing that C: is assigned to (0,0) and much other
+ SCSI-BIOS do so. Therefore, I moved the IBMMCA_SCSI_ORDER_STANDARD
+ define out of the driver and put it into Config.in as subitem of
+ 'IBM SCSI support'. A help, added to Documentation/Configure.help
+ explains the differences between saying 'y' or 'n' to the user, when
+ IBMMCA_SCSI_ORDER_STANDARD prompts, so the ordinary user is enabled to
+ choose the way of assignment, depending on his own situation and gusto.
+ 3) Adapted SCSI_IBMMCA_DEV_RESET to the local naming convention, so it is
+ now called IBMMCA_SCSI_DEV_RESET.
+ 4) Optimization of proc_info and its subroutines.
+ 5) Added more in-source-comments and extended the driver description by
+ some explanation about the SCSI-device-assignment problem.
+ - Michael Lang
+
+ Jan 18, 1998: (v3.0g)
+ 1) Correcting names to be absolutely conform to the later 2.1.x releases.
+ This is necessary for
+ IBMMCA_SCSI_DEV_RESET -> CONFIG_IBMMCA_SCSI_DEV_RESET
+ IBMMCA_SCSI_ORDER_STANDARD -> CONFIG_IBMMCA_SCSI_ORDER_STANDARD
+ - Michael Lang
+
+ Jan 18, 1999: (v3.1 MCA-team internal)
+ 1) The multiple hosts structure is accessed from every subroutine, so there
+ is no longer the address of the device structure passed from function
+ to function, but only the hostindex. A call by value, nothing more. This
+ should really be understood by the compiler and the subsystem should get
+ the right values and addresses.
+ 2) The SCSI-subsystem detection was not complete and quite hugely buggy up
+ to now, compared to the technical manual. The interpretation of the pos2
+ register is not as assumed by people before, therefore, I dropped a note
+ in the ibmmca_detect function to show the registers' interpretation.
+ The pos-registers of integrated SCSI-subsystems do not contain any
+ information concerning the IO-port offset, really. Instead, they contain
+ some info about the adapter, the chip, the NVRAM .... The I/O-port is
+ fixed to 0x3540 - 0x3547. There can be more than one adapters in the
+ slots and they get an offset for the I/O area in order to get their own
+ I/O-address area. See chapter 2 for detailed description. At least, the
+ detection should now work right, even on models other than 95. The 95ers
+ came happily around the bug, as their pos2 register contains always 0
+ in the critical area. Reserved bits are not allowed to be interpreted,
+ therefore, IBM is allowed to set those bits as they like and they may
+ really vary between different PS/2 models. So, now, no interpretation
+ of reserved bits - hopefully no trouble here anymore.
+ 3) The command error, which you may get on models 55, 56, 57, 70, 77 and
+ P70 may have been caused by the fact, that adapters of older design do
+ not like sending commands to non-existing SCSI-devices and will react
+ with a command error as a sign of protest. While this error is not
+ present on IBM SCSI Adapter w/cache, it appears on IBM Integrated SCSI
+ Adapters. Therefore, I implemented a workarround to forgive those
+ adapters their protests, but it is marked up in the statisctis, so
+ after a successful boot, you can see in /proc/scsi/ibmmca/<host_number>
+ how often the command errors have been forgiven to the SCSI-subsystem.
+ If the number is bigger than 0, you have a SCSI subsystem of older
+ design, what should no longer matter.
+ 4) ibmmca_getinfo() has been adapted very carefully, so it shows in the
+ slotn file really, what is senseful to be presented.
+ 5) ibmmca_register() has been extended in its parameter list in order to
+ pass the right name of the SCSI-adapter to Linux.
+ - Michael Lang
+
+ Feb 6, 1999: (v3.1)
+ 1) Finally, after some 3.1Beta-releases, the 3.1 release. Sorry, for
+ the delayed release, but it was not finished with the release of
+ Kernel 2.2.0.
+ - Michael Lang
+
+ Feb 10, 1999 (v3.1)
+ 1) Added a new commandline parameter called 'bypass' in order to bypass
+ every integrated subsystem SCSI-command consequently in case of
+ troubles.
+ 2) Concatenated read_capacity requests to the harddisks. It gave a lot
+ of troubles with some controllers and after I wanted to apply some
+ extensions, it jumped out in the same situation, on my w/cache, as like
+ on D. Weinehalls' Model 56, having integrated SCSI. This gave me the
+ descissive hint to move the code-part out and declare it global. Now,
+ it seems to work by far much better an more stable. Let us see, what
+ the world thinks of it...
+ 3) By the way, only Sony DAT-drives seem to show density code 0x13. A
+ test with a HP drive gave right results, so the problem is vendor-
+ specific and not a problem of the OS or the driver.
+ - Michael Lang
+
+ Feb 18, 1999 (v3.1d)
+ 1) The abort command and the reset function have been checked for
+ inconsistencies. From the logical point of thinking, they work
+ at their optimum, now, but as the subsystem does not answer with an
+ interrupt, abort never finishes, sigh...
+ 2) Everything, that is accessed by a busmaster request from the adapter
+ is now declared as global variable, even the return-buffer in the
+ local checking phase. This assures, that no accesses to undefined memory
+ areas are performed.
+ 3) In ibmmca.h, the line unchecked_isa_dma is added with 1 in order to
+ avoid memory-pointers for the areas higher than 16MByte in order to
+ be sure, it also works on 16-Bit Microchannel bus systems.
+ 4) A lot of small things have been found, but nothing that endangered the
+ driver operations. Just it should be more stable, now.
+ - Michael Lang
+
+ Feb 20, 1999 (v3.1e)
+ 1) I took the warning from the Linux Kernel Hackers Guide serious and
+ checked the cmd->result return value to the done-function very carefuly.
+ It is obvious, that the IBM SCSI only delivers the tsb.dev_status, if
+ some error appeared, else it is undefined. Now, this is fixed. Before
+ any SCB command gets queued, the tsb.dev_status is set to 0, so the
+ cmd->result won't screw up Linux higher level drivers.
+ 2) The reset-function has slightly improved. This is still planed for
+ abort. During the abort and the reset function, no interrupts are
+ allowed. This is however quite hard to cope with, so the INT-status
+ register is read. When the interrupt gets queued, one can find its
+ status immediately on that register and is enabled to continue in the
+ reset function. I had no chance to test this really, only in a bogus
+ situation, I got this function running, but the situation was too much
+ worse for Linux :-(, so tests will continue.
+ 3) Buffers got now consistent. No open address mapping, as before and
+ therefore no further troubles with the unassigned memory segmentation
+ faults that scrambled probes on 95XX series and even on 85XX series,
+ when the kernel is done in a not so perfectly fitting way.
+ 4) Spontaneous interrupts from the subsystem, appearing without any
+ command previously queued are answered with a DID_BAD_INTR result.
+ 5) Taken into account ZP Gus' proposals to reverse the SCSI-device
+ scan order. As it does not work on Kernel 2.1.x or 2.2.x, as proposed
+ by him, I implemented it in a slightly derived way, which offers in
+ addition more flexibility.
+ - Michael Lang
+
+ 4 To do
+ -------
+ - It seems that the handling of bad disks is really bad -
+ non-existent, in fact.
+ - More testing of the full driver-controlled dynamical ldn
+ (re)mapping for up to 56 SCSI-devices.
+ - Support more of the SCSI-command set.
+ - Support some of the caching abilities, particularly Read Prefetch.
+ This fetches data into the cache, which later gets hit by the
+ regular Read Data. (<--- This is coming soon!!!!)
+ - Abort and Reset functions still slightly buggy or better say,
+ it is the new episode, called SCREAM III.
+
+ 5 Users' Manual
+ ---------------
+ 5.1 Commandline Parameters
+ --------------------------
+ There exist several features for the IBM SCSI-subsystem driver.
+ The commandline parameter format is:
+
+ ibmmcascsi=<command1>,<command2>,<command3>,...
+
+ where commandN can be one of the following:
+
+ display Owners of a model 95 or other PS/2 systems with an
+ alphanumeric LED display may set this to have their
+ display showing the following output of the 8 digits:
+
+ ------DA
+
+ where '-' stays dark, 'D' shows the SCSI-device id
+ and 'A' shows the SCSI hostindex, beeing currently
+ accessed.
+ adisplay This works like display, but gives more optical overview
+ of the activities on the SCSI-bus. The display will have
+ the following output:
+
+ 6543210A
+
+ where the numbers 0 to 6 light up at the shown position,
+ when the SCSI-device is accessed. A shows again the SCSI
+ hostindex. If display nor adisplay is set, the internal
+ PS/2 harddisk LED is used for media-activities. So, if
+ you really do not have a system with a LED-display, you
+ should not set display or adisplay.
+ bypass This commandline parameter forces the driver never to use
+ SCSI-subsystems' integrated SCSI-command set. Except of
+ the immediate assign, which is of vital importance for
+ every IBM SCSI-subsystem to set its ldns right. Instead,
+ the ordinary ANSI-SCSI-commands are used and passed by the
+ controller to the SCSI-devices, therefore 'bypass'. The
+ effort, done by the subsystem is quite bogus and at a
+ minimum and therefore it should work everywhere. This
+ could maybe solve troubles with old or integrated SCSI-
+ controllers and nasty harddisks. Keep in mind, that using
+ this flag will slow-down SCSI-accesses slightly, as the
+ software generated commands are always slower than the
+ hardware. Non-harddisk devices always get read/write-
+ commands in bypass mode.
+ normal This is the parameter, introduced on the 2.0.x development
+ rail by ZP Gu. This parameter defines the SCSI-device
+ scan order in the new industry standard. This means, that
+ the first SCSI-device is the one with the lowest pun.
+ E.g. harddisk at pun=0 is scanned before harddisk at
+ pun=6, which means, that harddisk at pun=0 gets sda
+ and the one at pun=6 gets sdb.
+ ansi The ANSI-standard for the right scan order, as done by
+ IBM, Microware and Microsoft, scans SCSI-devices starting
+ at the highest pun, which means, that e.g. harddisk at
+ pun=6 gets sda and a harddisk at pun=0 gets sdb. If you
+ like to have the same SCSI-device order, as in DOS, OS-9
+ or OS/2, just use this parameter.
+
+ A further option is that you can force the SCSI-driver to accept a SCSI-
+ subsystem at a certain I/O-address with a predefined adapter PUN. This
+ is done by entering
+
+ commandN = I/O-base
+ commandN+1 = adapter PUN
+
+ e.g. ibmmcascsi=0x3540,7 will force the driver to detect a SCSI-subsystem
+ at I/O-address 0x3540 with adapter PUN 7.
+
+ Examples:
+
+ ibmmcascsi=adisplay,bypass
+
+ This will use the advanced display mode for the model 95 LED display and
+ every SCSI-command passed to a attached device will get bypassed in order
+ not to use any of the subsystem built-in commands.
+
+ ibmmcascsi=display,0x3558,7
+
+ This will activate the default display mode for the model 95 LED display
+ and will force the driver to accept a SCSI-subsystem at I/O-base 0x3558
+ with adapter PUN 7.
+
+ 5.2 Troubleshooting
+ -------------------
+ The following FAQs should help you to solve some major problems with this
+ driver.
+
+ Q: "Reset SCSI-devices at boottime" halts the system at boottime, why?
+ A: This is only tested with the IBM SCSI Adapter w/cache. It is not
+ yet prooved to run on other adapters, however you may be lucky.
+ In version 3.1d this has been hugely improved and should work better,
+ now. Normally you really won't need to activate this flag in the
+ kernel configuration, as all post 1989 SCSI-devices should accept
+ the reset-signal, when the computer is switched on. The SCSI-
+ subsystem generates this reset while beeing initialized. This flag
+ is really reserved for users with very old, very strange or self-made
+ SCSI-devices.
+ Q: Why is the SCSI-order of my drives mirrored to the device-order
+ seen from OS/2 or DOS ?
+ A: It depends on the operating system, if it looks at the devices in
+ ANSI-SCSI-standard (starting from pun 6 and going down to pun 0) or
+ if it just starts at pun 0 and counts up. If you want to be conform
+ with OS/2 and DOS, you have to activate this flag in the kernel
+ configuration or you should set 'ansi' as parameter for the kernel.
+ The parameter 'normal' sets the new industry standard, starting
+ from pun 0, scaning up to pun 6. This allows you to change your
+ opinion still after having already compiled the kernel.
+ Q: Why can I not find the IBM MCA SCSI support in the config menue?
+ A: You have to activate MCA bus support, first.
+ Q: Where can I find the latest info about this driver?
+ A: See the file MAINTAINERS for the current WWW-address, which offers
+ updates, info and Q/A lists. At this files' origin, the webaddress
+ was: http://www.uni-mainz.de/~langm000/linux.html
+ Q: My SCSI-adapter is not recognized by the driver, what can I do?
+ A: Just force it to be recognized by kernel parameters. See section 5.1.
+ Q: The driver screws up, if it starts to probe SCSI-devices, is there
+ some way out of it?
+ A: This is based on some problems with the driver. In such cases, send
+ e-mail to the maintainer. If you are owner of a model with the serial
+ number 95XX, just send as subject NOTIFY 95XX PROBLEM and the
+ maintainer immediately knows about your problem. But please:
+ Check your hardware and only if it works fine with other operating
+ systems, send E-Mail to me to notify the troubles. See the homepage
+ for how to send bug-reports or please read the next Q/A, here:
+ Q: I get a message: panic IBM MCA SCSI: command error .... , what can
+ I do against this?
+ A: Previously, I followed the way by ignoring command errors by using
+ ibmmcascsi=forgiveall, but this command no longer exists and is
+ obsolete. If such a problem appears, it is caused by some segmentation
+ fault of the driver, which maps to some unallowed area. The latest
+ version of the driver should be ok, as most bugs have been solved.
+ Q: There are still kernel panics, even after having set
+ ibmmcascsi=forgiveall. Are there other possibilities to prevent
+ such panics?
+ A: No, get just the latest release of the driver and it should work
+ better and better with increasing version number. Forget this
+ ibmmcascsi=forgiveall, as also ignorecmd are obsolete.
+ Q: Linux panics or stops without any comment, but it is probable, that my
+ harddisk(s) have bad blocks.
+ A: Sorry, the bad-block handling is still a feeble point of this driver,
+ but is on the schedule for development in the near future.
+ Q: Linux panics while dynamically assigning SCSI-ids or ldns.
+ A: If you disconnect a SCSI-device from the machine, while Linux is up
+ and the driver uses dynamical reassignment of logical device numbers
+ (ldn), it really gets "angry" if it won't find devices, that were still
+ present at boottime and stops Linux.
+ Q: The system does not recover after an abort-command has been generated.
+ A: This is regrettably true, as it is not yet understood, why the
+ SCSI-adapter does really NOT generate any interrupt at the end of
+ the abort-command. As no interrupt is generated, the abort command
+ cannot get finished and the system hangs, sorry, but checks are
+ running to hunt down this problem. If there is a real pending command,
+ the interrupt MUST get generated after abort. In this case, it
+ should finish well.
+ Q: The system gets in bad shape after a SCSI-reset, is this known?
+ A: Yes, as there are a lot of prescriptions (see the Linux Hackers'
+ Guide) what has to be done for reset, we still share the bad shape of
+ the reset functions with all other low level SCSI-drivers.
+ Astonishingly, reset works in most cases quite ok, but the harddisks
+ won't run in synchonous mode anymore after a reset, until you reboot.
+ Q: Why does my XXX w/Cache adapter not use read-prefetch?
+ A: w/Cache technical manuals are incoming here, so if I understood the
+ command of read-prefetch, it should be an easy thing to get harddisks
+ read in read-prefetch with w/Cache controllers. Some weeks or months,
+ still ahead and a lot of work still to do, sigh ...
+
+ 5.3 Bugreports
+ --------------
+ If you really find bugs in the sourcecode or the driver will successfully
+ refuse to work on your machine, you should send a bug report to me. The
+ best for this is to follow the instructions on the WWW-page for this
+ driver. Fill out the bug-report form, placed on the WWW-page and ship it,
+ so the bugs can be taken into account with maximum efforts. But, please
+ do not send bug reports about this driver to Linus Torvalds or Leonard
+ Zubkoff, as Linus is burried in E-Mail and Leonard is supervising all
+ SCSI-drivers and won't have the time left to look inside every single
+ driver to fix a bug and especially DO NOT send modified code to Linus
+ Torvalds, which has not been checked here!!! Recently, I got a lot of
+ bugreports for errors in the ibmmca.c code, which I could not imagine, but
+ a look inside some Linux-distribution showed me quite often some modified
+ code, which did no longer work on most other machines than the one of the
+ modifier. Ok, so now that there is maintenance service available for this
+ driver, please use this address first in order to keep the level of
+ confusion low. Thank you!
+
+ When you get a SCSI-error message that panics your system, a list of
+ register-entries of the SCSI-subsystem is shown (from Version 3.1d). With
+ this list, it is very easy for the maintainer to localize the problem in
+ the driver or in the configuration of the user. Please write down all the
+ values from this report and send them to the maintainer. This would really
+ help a lot and makes life easier concerning misunderstandings.
+
+ Use the bug-report form (see 5.4 for its address) to send all the bug-
+ stuff to the maintainer or write e-mail with the values from the table.
+
+ 5.4 Support WWW-page
+ --------------------
+ The address of the IBM SCSI-subsystem supporting WWW-page is:
+
+ http://www.uni-mainz.de/~langm000/linux.html
+
+ Here you can find info about the background of this driver, patches,
+ news and a bugreport form.
+
+ 6 References
+ ------------
+ The source of information is "Update for the PS/2 Hardware
+ Interface Technical Reference, Common Interfaces", September 1991,
+ part number 04G3281, available in the U.S. for $21.75 at
+ 1-800-IBM-PCTB, elsewhere call your local friendly IBM
+ representative. E.g. in Germany, "Hallo IBM" works really great.
+ In addition to SCSI subsystem, this update contains fairly detailed
+ (at hardware register level) sections on diskette controller,
+ keyboard controller, serial port controller, VGA, and XGA.
+
+ Additional information from "Personal System/2 Micro Channel SCSI
+ Adapter with Cache Technical Reference", March 1990, PN 68X2365,
+ probably available from the same source (or possibly found buried
+ in officemates desk).
+
+ Friedhelm Schmidt, "SCSI-Bus und IDE-Schnittstelle - Moderne Peripherie-
+ Schnittstellen: Hardware, Protokollbeschreibung und Anwendung", 2. Aufl.
+ Addison Wesley, 1996.
+
+ Michael K. Johnson, "The Linux Kernel Hackers' Guide", Version 0.6, Chapel
+ Hill - North Carolina, 1995
+
+ Andreas Kaiser, "SCSI TAPE BACKUP for OS/2 2.0", Version 2.12, Stuttgart
+ 1993
+
+ Helmut Rompel, "IBM Computerwelt GUIDE", What is what bei IBM., Systeme *
+ Programme * Begriffe, IWT-Verlag GmbH - Muenchen, 1988
+
+ 7 Trademarks
+ ------------
+ IBM, PS/2, OS/2, Microchannel are registered trademarks of International
+ Business Machines Corp.
+
+ MS-DOS is a registered trademark of Microsoft Corporation
+
+ OS-9 is a registered trademark of Microware Systems
+
+------
+Michael Lang
+(langa2@kph.uni-mainz.de)
diff --git a/drivers/scsi/README.ncr53c8xx b/drivers/scsi/README.ncr53c8xx
index 47bbe19ba..2fa1956a2 100644
--- a/drivers/scsi/README.ncr53c8xx
+++ b/drivers/scsi/README.ncr53c8xx
@@ -4,12 +4,14 @@ Written by Gerard Roudier <groudier@club-internet.fr>
21 Rue Carnot
95170 DEUIL LA BARRE - FRANCE
-22 November 1998
+10 March 1999
===============================================================================
1. Introduction
2. Supported chips and SCSI features
-3. Summary of other supported features
+3. Advantages of the enhanced 896 driver
+ 3.1 Optimized SCSI SCRIPTS
+ 3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller)
4. Memory mapped I/O versus normal I/O
5. Tagged command queueing
6. Parity checking
@@ -39,6 +41,7 @@ Written by Gerard Roudier <groudier@club-internet.fr>
14.2 Device names change when another controller is added
14.3 Using only 8 bit devices with a WIDE SCSI controller.
14.4 Possible data corruption during a Memory Write and Invalidate
+ 14.5 IRQ sharing problems
15. SCSI problem troubleshooting
16. Synchonous transfer negotiation tables
16.1 Synchronous timings for 53C875 and 53C860 Ultra-SCSI controllers
@@ -55,21 +58,30 @@ Written by Gerard Roudier <groudier@club-internet.fr>
1. Introduction
-This driver has been ported from FreeBSD to Linux and is currently
-maintained by:
+The initial Linux ncr53c8xx driver has been a port of the ncr driver from
+FreeBSD that has been achieved in November 1995 by:
Gerard Roudier <groudier@club-internet.fr>
The original driver has been written for 386bsd and FreeBSD by:
Wolfgang Stanglmeier <wolf@cologne.de>
Stefan Esser <se@mi.Uni-Koeln.de>
+It is now available as a bundle of 2 drivers:
+
+- ncr53c8xx generic driver that supports all the SYM53C8XX family including
+ the ealiest 810 rev. 1 and the latest 896 2 channels LVD SCSI controller.
+- sym53c8xx enhanced driver (a.k.a. 896 drivers) that drops support of oldest
+ chips in order to gain advantage of new features, as LOAD/STORE intructions
+ available since the 810A and hardware phase mismatch available with the
+ latest 896.
+
You can find technical information about the NCR 8xx family in the
PCI-HOWTO written by Michael Will and in the SCSI-HOWTO written by
Drew Eckhardt.
-Information about new chips is available at SYMBIOS web server:
+Information about new chips is available at LSILOGIC web server:
- http://www.symbios.com/
+ http://www.lsilogic.com/
SCSI standard documentations are available at SYMBIOS ftp server:
@@ -108,34 +120,65 @@ The following features are supported for all chips:
Master parity checking
"Wide negotiation" is supported for chips that allow it. The
-following table shows some characteristics of NCR 8xx family chips:
-
- On board Supported by
-Chip SDMS BIOS Wide SCSI std. Max. sync the driver
----- --------- ---- --------- ---------- ------------
-810 N N FAST10 10 MB/s Y
-810A N N FAST10 10 MB/s Y
-815 Y N FAST10 10 MB/s Y
-825 Y Y FAST10 20 MB/s Y
-825A Y Y FAST10 20 MB/s Y
-860 N N FAST20 20 MB/s Y
-875 Y Y FAST20 40 MB/s Y
-876 Y Y FAST20 40 MB/s Y
-895 Y Y FAST40 80 MB/s Y
-
-
-3. Summary of other supported features.
-
- Module: allow to load the driver
- Memory mapped I/O: increases performance
- Profiling information: read operations from the proc SCSI file system
- Control commands: write operations to the proc SCSI file system
- Debugging information: written to syslog (expert only)
- Scatter / gather
- Shared interrupt
- Boot setup commands
- Serial NVRAM: Symbios and Tekram formats
-
+following table shows some characteristics of NCR 8xx family chips
+and what drivers support them.
+
+ Supported by Supported by
+ On board the generic the enhanced
+Chip SDMS BIOS Wide SCSI std. Max. sync driver driver
+---- --------- ---- --------- ---------- ------------ -------------
+810 N N FAST10 10 MB/s Y N
+810A N N FAST10 10 MB/s Y Y
+815 Y N FAST10 10 MB/s Y N
+825 Y Y FAST10 20 MB/s Y N
+825A Y Y FAST10 20 MB/s Y Y
+860 N N FAST20 20 MB/s Y Y
+875 Y Y FAST20 40 MB/s Y Y
+876 Y Y FAST20 40 MB/s Y Y
+895 Y Y FAST40 80 MB/s Y Y
+896 Y Y FAST40 80 MB/s Y Y
+
+
+Summary of other supported features:
+
+Module: allow to load the driver
+Memory mapped I/O: increases performance
+Profiling information: read operations from the proc SCSI file system
+Control commands: write operations to the proc SCSI file system
+Debugging information: written to syslog (expert only)
+Scatter / gather
+Shared interrupt
+Boot setup commands
+Serial NVRAM: Symbios and Tekram formats
+
+
+3. Advantages of the enhanced 896 driver
+
+3.1 Optimized SCSI SCRIPTS.
+
+The 810A, 825A, 875, 895 and newest 896 support new SCSI SCRIPTS instructions
+named LOAD and STORE that allow to move 1 DWORD from/to an IO register to/from
+memory much faster that the MOVE MEMORY instruction that is supported by the
+53c7xx and 53c8xx family. The LOAD/STORE instructions support absolute and
+DSA relative addressing modes. The SCSI SCRIPTS had been entirely rewritten
+using LOAD/STORE instead of MOVE MEMORY instructions.
+
+3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller)
+
+The 896 allows to handle the phase mismatch context saving from SCRIPTS
+(avoids the phase mismatch interrupt that stops the SCSI processor
+until the C code has saved the context of the transfer).
+Implementing this without using LOAD/STORE instructions would be painfull
+and I did'nt even try it. This chip also supports 64 bit PCI transactions
+and addressing. The SCRIPTS processor is not true 64 bit, but uses segment
+registers for bit 32-63. Another interesting feature is that LOAD/STORE
+instructions that address the on-chip RAM (8k) remain internal to the chip.
+
+Due to the use of LOAD/STORE SCRIPTS instructions, this driver does not
+support the following chips:
+- SYM53C810 revision < 0x10 (16)
+- SYM53C815 all revisions
+- SYM53C825 revision < 0x10 (16)
4. Memory mapped I/O versus normal I/O
@@ -669,6 +712,10 @@ IRQ mode
irqm:0 always open drain
irqm:1 same as initial settings (assumed BIOS settings)
irqm:2 always totem pole
+ irqm:0x10 driver will not use SA_SHIRQ flag when requesting irq
+ irqm:0x20 driver will not use SA_INTERRUPT flag when requesting irq
+
+ (Bits 0x10 and 0x20 can be combined with hardware irq mode option)
Reverse probe
revprob:n probe chip ids from the PCI configuration in this order:
@@ -698,6 +745,13 @@ Check SCSI BUS
0x1: Check and donnot attach the controller on error.
0x2: Check and just warn on error.
+Exclude hosts from being attached
+ excl=<io_address>
+
+ Prevent host at a given io address from being attached.
+ For example 'ncr53c8xx=excl:0xb400,excl:0xc000' indicate to the
+ ncr53c8xx driver not to attach hosts at address 0xb400 and 0xc000.
+
Boot fail safe
safe:y load the following assumed fail safe initial setup
@@ -1027,7 +1081,30 @@ they only refer to system buffers that are well aligned. So, a work around
may only be needed under Linux when a scatter/gather list is not used and
when the SCSI DATA IN phase is reentered after a phase mismatch.
-
+14.5 IRQ sharing problems
+
+When an IRQ is shared by devices that are handled by different drivers, it
+may happen that one driver complains about the request of the IRQ having
+failed. Inder Linux-2.0, this may be due to one driver having requested the
+IRQ using the SA_INTERRUPT flag but some other having requested the same IRQ
+without this flag. Under both Linux-2.0 and linux-2.2, this may be caused by
+one driver not having requested the IRQ with the SA_SHIRQ flag.
+
+By default, the ncr53c8xx and sym53c8xx drivers request IRQs with both the
+SA_INTERRUPT and the SA_SHIRQ flag under Linux-2.0 and with only the SA_SHIRQ
+flag under Linux-2.2.
+
+Under Linux-2.0, you can disable use of SA_INTERRUPT flag from the boot
+command line by using the following option:
+
+ ncr53c8xx=irqm:0x20 (for the generic ncr53c8xx driver)
+ sym53c8xx=irqm:0x20 (for the sym53c8xx driver)
+
+If this does not fix the problem, then you may want to check how all other
+drivers are requesting the IRQ and report the problem. Note that if at least
+a single driver does not request the IRQ with the SA_SHIRQ flag (share IRQ),
+then the request of the IRQ obviously will not succeed for all the drivers.
+
15. SCSI problem troubleshooting
Most SCSI problems are due to a non conformant SCSI bus or to buggy
diff --git a/drivers/scsi/README.st b/drivers/scsi/README.st
index c50bd2793..da8099937 100644
--- a/drivers/scsi/README.st
+++ b/drivers/scsi/README.st
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
The driver is currently maintained by Kai M{kisara (email
Kai.Makisara@metla.fi)
-Last modified: Sun Sep 6 10:03:47 1998 by makisara@home
+Last modified: Sun Jan 17 10:57:41 1999 by makisara@home
BASICS
@@ -60,11 +60,20 @@ scans its database, and sets up the modes using the ioctls. Another
alternative is to make a small script that uses mt to set the defaults
tailored to the system.
-
The driver supports fixed and variable block size (within buffer
limits). Both the auto-rewind (minor equals device number) and
non-rewind devices (minor is 128 + device number) are implemented.
+In variable block mode, the byte count in write() determines the size
+of the physical block on tape. When reading, the drive reads the next
+tape block and returns to the user the data if the read() byte count
+is at least the block size. Otherwise the data is truncated.
+
+In fixed block mode, the data transfer between the drive and the
+driver is in multiples of the block size. The write() byte count must
+be a multiple of the block size. This is not required when reading but
+may be advisable for portability.
+
Support is provided for changing the tape partition and partitioning
of the tape with one or two partitions. By default support for
partitioned tape is disabled for each driver and it can be enabled
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 70d233f37..82d55ada8 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -343,6 +343,7 @@
#include <linux/wait.h>
#include <linux/ioport.h>
#include <linux/proc_fs.h>
+#include <linux/interrupt.h>
#include "aha152x.h"
#include <linux/stat.h>
@@ -489,6 +490,7 @@ struct aha152x_hostdata {
int ext_trans;
int swint;
+ int service;
unsigned char syncrate[8];
@@ -500,7 +502,7 @@ struct aha152x_hostdata {
#endif
};
-void aha152x_intr(int irq, void *dev_id, struct pt_regs *);
+static void aha152x_intr(int irq, void *dev_id, struct pt_regs *);
void aha152x_done(struct Scsi_Host *shpnt, int error);
void aha152x_setup(char *str, int *ints);
int aha152x_checksetup(struct aha152x_setup *setup);
@@ -1550,38 +1552,72 @@ void aha152x_done(struct Scsi_Host *shpnt, int error)
aha152x_panic(shpnt, "done() called outside of command");
}
+
+static void aha152x_complete(struct Scsi_Host *);
+
+static struct tq_struct aha152x_tq;
+
/*
- * Interrupts handler (main routine of the driver)
+ * Run service completions on the card with interrupts enabled.
*/
-void aha152x_intr(int irqno, void *dev_id, struct pt_regs * regs)
+
+static void aha152x_run(void)
{
- struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN];
- unsigned int flags;
- int done=0, phase;
+ int i;
+ for(i=0;i<IRQS;i++)
+ {
+ struct Scsi_Host *shpnt=aha152x_host[i];
+ if(shpnt && HOSTDATA(shpnt)->service)
+ {
+ HOSTDATA(shpnt)->service=0;
+ aha152x_complete(shpnt);
+ }
+ }
+}
+
+/*
+ * Interrupts handler (main routine of the driver)
+ */
+
+static void aha152x_intr(int irqno, void *dev_id, struct pt_regs * regs)
+{
+ struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN];
#if defined(DEBUG_RACE)
- enter_driver("intr");
+ enter_driver("intr");
#else
#if defined(DEBUG_INTR)
- if(HOSTDATA(shpnt)->debug & debug_intr)
- printk("\naha152x: intr(), ");
+ if(HOSTDATA(shpnt)->debug & debug_intr)
+ printk("\naha152x: intr(), ");
#endif
#endif
- if(!shpnt)
- panic("aha152x: catched interrupt for unknown controller.\n");
-
- /* no more interrupts from the controller, while we're busy.
- INTEN has to be restored, when we're ready to leave
- intr(). To avoid race conditions, we have to return
- immediately afterwards. */
- CLRBITS(DMACNTRL0, INTEN);
- /* sti(); FIXME!!! Yes, sti() really needs to be here if we want to lock up */
-
- /* disconnected target is trying to reconnect.
- Only possible, if we have disconnected nexuses and
- nothing is occupying the bus.
- */
+ if(!shpnt)
+ panic("aha152x: catched interrupt for unknown controller.\n");
+
+ /* no more interrupts from the controller, while we're busy.
+ INTEN is restored by the BH handler */
+
+ CLRBITS(DMACNTRL0, INTEN);
+
+ /* Poke the BH handler */
+
+ HOSTDATA(shpnt)->service=1;
+ aha152x_tq.routine = (void *)aha152x_run;
+ queue_task(&aha152x_tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+}
+
+static void aha152x_complete(struct Scsi_Host *shpnt)
+{
+ unsigned int flags;
+ int done=0, phase;
+
+ /* disconnected target is trying to reconnect.
+ Only possible, if we have disconnected nexuses and
+ nothing is occupying the bus.
+ */
+
if(TESTHI(SSTAT0, SELDI) &&
DISCONNECTED_SC &&
(!CURRENT_SC || (CURRENT_SC->SCp.phase & in_selection)) ) {
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 96280a8c3..ada7235b8 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1684,7 +1684,7 @@ int atp870u_detect(Scsi_Host_Template * tpnt)
struct Scsi_Host * shpnt = NULL;
int count = 0;
static unsigned short devid[7]={0x8002,0x8010,0x8020,0x8030,0x8040,0x8050,0};
- static struct pci_dev *pdev = NULL;
+ static struct pci_dev *pdev = NULL, *acard_pdev[3];
printk("aec671x_detect: \n");
if (!pci_present())
@@ -1720,8 +1720,8 @@ int atp870u_detect(Scsi_Host_Template * tpnt)
h=0;
while ( devid[h] != 0 )
{
- pci_find_device(0x1191,devid[h],pdev);
- if (pdev == NULL); {
+ pdev = pci_find_device(0x1191,devid[h],pdev);
+ if (pdev == NULL) {
h++;
index=0;
continue;
@@ -1729,6 +1729,7 @@ int atp870u_detect(Scsi_Host_Template * tpnt)
chip_ver[2]=0;
/* To avoid messing with the things below... */
+ acard_pdev[2] = pdev;
pci_device_fn[2] = pdev->devfn;
pci_bus[2] = pdev->bus->number;
@@ -1746,15 +1747,18 @@ int atp870u_detect(Scsi_Host_Template * tpnt)
}
if ( pci_device_fn[2] < pci_device_fn[0] )
{
+ acard_pdev[1]=acard_pdev[0];
pci_bus[1]=pci_bus[0];
pci_device_fn[1]=pci_device_fn[0];
chip_ver[1]=chip_ver[0];
+ acard_pdev[0]=acard_pdev[2];
pci_bus[0]=pci_bus[2];
pci_device_fn[0]=pci_device_fn[2];
chip_ver[0]=chip_ver[2];
}
else if ( pci_device_fn[2] < pci_device_fn[1] )
{
+ acard_pdev[1]=acard_pdev[2];
pci_bus[1]=pci_bus[2];
pci_device_fn[1]=pci_device_fn[2];
chip_ver[1]=chip_ver[2];
@@ -1774,6 +1778,7 @@ nxt_devfn:
return count;
}
+ pdev = acard_pdev[h];
pdev->devfn = pci_device_fn[h];
pdev->bus->number = pci_bus[h];
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index 526ae3090..351ded85c 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -1,6 +1,6 @@
/* esp.c: EnhancedScsiProcessor Sun SCSI driver code.
*
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
*/
/* TODO:
@@ -162,6 +162,17 @@ enum {
in_tgterror = 0x84, /* Target did something stupid */
};
+enum {
+ /* Zero has special meaning, see skipahead[12]. */
+/*0*/ do_never,
+
+/*1*/ do_phase_determine,
+/*2*/ do_reset_bus,
+/*3*/ do_reset_complete,
+/*4*/ do_work_bus,
+/*5*/ do_intr_end
+};
+
struct proc_dir_entry proc_scsi_esp = {
PROC_SCSI_ESP, 3, "esp",
S_IFDIR | S_IRUGO | S_IXUGO, 2
@@ -354,24 +365,30 @@ static char *phase_string(int phase)
};
}
+#ifdef DEBUG_STATE_MACHINE
static inline void esp_advance_phase(Scsi_Cmnd *s, int newphase)
{
-#ifdef DEBUG_STATE_MACHINE
ESPLOG(("<%s>", phase_string(newphase)));
-#endif
s->SCp.sent_command = s->SCp.phase;
s->SCp.phase = newphase;
}
+#else
+#define esp_advance_phase(__s, __newphase) \
+ (__s)->SCp.sent_command = (__s)->SCp.phase; \
+ (__s)->SCp.phase = (__newphase);
+#endif
+#ifdef DEBUG_ESP_CMDS
extern inline void esp_cmd(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
unchar cmd)
{
-#ifdef DEBUG_ESP_CMDS
esp->espcmdlog[esp->espcmdent] = cmd;
esp->espcmdent = (esp->espcmdent + 1) & 31;
-#endif
eregs->esp_cmd = cmd;
}
+#else
+#define esp_cmd(__esp, __eregs, __cmd) (__eregs)->esp_cmd = (__cmd)
+#endif
/* How we use the various Linux SCSI data structures for operation.
*
@@ -456,14 +473,23 @@ static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun)
}
/* Resetting various pieces of the ESP scsi driver chipset/buses. */
-static inline void esp_reset_dma(struct Sparc_ESP *esp)
+static void esp_reset_dma(struct Sparc_ESP *esp)
{
struct sparc_dma_registers *dregs = esp->dregs;
- unsigned long tmp, flags;
- int can_do_burst16, can_do_burst32;
+ unsigned long flags;
+ int can_do_burst16, can_do_burst32, can_do_burst64;
+ int can_do_sbus64;
can_do_burst16 = esp->bursts & DMA_BURST16;
can_do_burst32 = esp->bursts & DMA_BURST32;
+ can_do_burst64 = 0;
+ can_do_sbus64 = 0;
+#ifdef __sparc_v9__
+ /* XXX Can sun4d do these too? */
+ can_do_burst64 = esp->bursts & DMA_BURST64;
+ can_do_sbus64 = 1;
+ mmu_set_sbus64(esp->edev, esp->bursts);
+#endif
/* Punt the DVMA into a known state. */
if(esp->dma->revision != dvmahme) {
@@ -476,14 +502,19 @@ static inline void esp_reset_dma(struct Sparc_ESP *esp)
save_flags(flags); cli(); /* I really hate this chip. */
- dregs->cond_reg = 0x08000000; /* Reset interface to FAS */
- dregs->cond_reg = DMA_RST_SCSI; /* Reset DVMA itself */
+ dregs->cond_reg = DMA_RESET_FAS366; /* Reset interface to FAS */
+ dregs->cond_reg = DMA_RST_SCSI; /* Reset DVMA itself */
- tmp = (DMA_PARITY_OFF|DMA_2CLKS|DMA_SCSI_DISAB|DMA_INT_ENAB);
- tmp &= ~(DMA_ENABLE|DMA_ST_WRITE|DMA_BRST_SZ);
+ esp->prev_hme_dmacsr = (DMA_PARITY_OFF|DMA_2CLKS|DMA_SCSI_DISAB|DMA_INT_ENAB);
+ esp->prev_hme_dmacsr &= ~(DMA_ENABLE|DMA_ST_WRITE|DMA_BRST_SZ);
if(can_do_burst32)
- tmp |= DMA_BRST32;
+ esp->prev_hme_dmacsr |= DMA_BRST32;
+ else if(can_do_burst64)
+ esp->prev_hme_dmacsr |= DMA_BRST64;
+
+ if(can_do_sbus64)
+ esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64;
/* This chip is horrible. */
while(dregs->cond_reg & DMA_PEND_READ)
@@ -491,8 +522,14 @@ static inline void esp_reset_dma(struct Sparc_ESP *esp)
dregs->cond_reg = 0;
- dregs->cond_reg = tmp; /* bite me */
- restore_flags(flags); /* ugh... */
+ dregs->cond_reg = esp->prev_hme_dmacsr;
+
+ /* This is necessary to avoid having the SCSI channel
+ * engine lock up on us.
+ */
+ dregs->st_addr = 0;
+
+ restore_flags(flags);
break;
case dvmarev2:
/* This is the gate array found in the sun4m
@@ -526,7 +563,7 @@ static inline void esp_reset_dma(struct Sparc_ESP *esp)
}
/* Reset the ESP chip, _not_ the SCSI bus. */
-static inline void esp_reset_esp(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
+static void esp_reset_esp(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
{
int family_code, version, i;
volatile int trash;
@@ -538,8 +575,8 @@ static inline void esp_reset_esp(struct Sparc_ESP *esp, struct Sparc_ESP_regs *e
/* Reload the configuration registers */
eregs->esp_cfact = esp->cfact;
- eregs->esp_stp = 0;
- eregs->esp_soff = 0;
+ eregs->esp_stp = esp->prev_stp = 0;
+ eregs->esp_soff = esp->prev_soff = 0;
eregs->esp_timeo = esp->neg_defp;
/* This is the only point at which it is reliable to read
@@ -555,11 +592,11 @@ static inline void esp_reset_esp(struct Sparc_ESP *esp, struct Sparc_ESP_regs *e
esp->erev = fashme; /* Version is usually '5'. */
else
esp->erev = fas100a;
- printk("esp%d: FAST chip is %s (family=%d, version=%d)\n",
- esp->esp_id,
- (esp->erev == fas236) ? "fas236" :
- ((esp->erev == fas100a) ? "fas100a" :
- "fasHME"), family_code, (version & 7));
+ ESPMISC(("esp%d: FAST chip is %s (family=%d, version=%d)\n",
+ esp->esp_id,
+ (esp->erev == fas236) ? "fas236" :
+ ((esp->erev == fas100a) ? "fas100a" :
+ "fasHME"), family_code, (version & 7)));
esp->min_period = ((4 * esp->ccycle) / 1000);
} else {
@@ -579,7 +616,7 @@ static inline void esp_reset_esp(struct Sparc_ESP *esp, struct Sparc_ESP_regs *e
case esp236:
/* Slow 236 */
eregs->esp_cfg2 = esp->config2;
- eregs->esp_cfg3 = esp->config3[0];
+ eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0];
break;
case fashme:
esp->config2 |= (ESP_CONFIG2_HME32 | ESP_CONFIG2_HMEFENAB);
@@ -588,13 +625,18 @@ static inline void esp_reset_esp(struct Sparc_ESP *esp, struct Sparc_ESP_regs *e
/* Fast 236 or HME */
eregs->esp_cfg2 = esp->config2;
for(i=0; i<8; i++) {
- if(esp->erev == fashme)
- esp->config3[i] |=
- (ESP_CONFIG3_FCLOCK | ESP_CONFIG3_BIGID | ESP_CONFIG3_OBPUSH);
- else
+ if(esp->erev == fashme) {
+ unsigned char cfg3;
+
+ cfg3 = ESP_CONFIG3_FCLOCK | ESP_CONFIG3_OBPUSH;
+ if (esp->scsi_id >= 8)
+ cfg3 |= ESP_CONFIG3_IDBIT3;
+ esp->config3[i] |= cfg3;
+ } else {
esp->config3[i] |= ESP_CONFIG3_FCLK;
+ }
}
- eregs->esp_cfg3 = esp->config3[0];
+ eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0];
if(esp->erev == fashme) {
esp->radelay = 80;
} else {
@@ -609,7 +651,7 @@ static inline void esp_reset_esp(struct Sparc_ESP *esp, struct Sparc_ESP_regs *e
eregs->esp_cfg2 = esp->config2;
for(i=0; i<8; i++)
esp->config3[i] |= ESP_CONFIG3_FCLOCK;
- eregs->esp_cfg3 = esp->config3[0];
+ eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0];
esp->radelay = 32;
break;
default:
@@ -623,7 +665,7 @@ static inline void esp_reset_esp(struct Sparc_ESP *esp, struct Sparc_ESP_regs *e
}
/* This places the ESP into a known state at boot time. */
-static inline void esp_bootup_reset(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
+static void esp_bootup_reset(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
{
volatile unchar trash;
@@ -669,6 +711,10 @@ __initfunc(int detect_one_esp
esp->edev = esp_dev;
esp->esp_id = id;
+#ifdef __sparc_v9__
+ esp_host->unchecked_isa_dma = 1;
+#endif
+
/* Put into the chain of esp chips detected */
if(espchain) {
elink = espchain;
@@ -902,7 +948,7 @@ esp_irq_acquired:
esp->ctick = ESP_TICK(ccf, esp->ccycle);
esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
esp->sync_defp = SYNC_DEFP_SLOW;
- printk("SCSI ID %d Clock %d MHz CCF=%d Time-Out %d ",
+ printk("SCSI ID %d Clk %dMHz CCF=%d TOut %d ",
esp->scsi_id, (fmhz / 1000000),
ccf, (int) esp->neg_defp);
@@ -935,28 +981,28 @@ esp_irq_acquired:
eregs->esp_cfg2 = esp->config2;
if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) !=
(ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
- printk("NCR53C90(esp100) detected\n");
+ printk("NCR53C90(esp100)\n");
esp->erev = esp100;
} else {
eregs->esp_cfg2 = esp->config2 = 0;
eregs->esp_cfg3 = 0;
- eregs->esp_cfg3 = esp->config3[0] = 5;
+ eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0] = 5;
if(eregs->esp_cfg3 != 5) {
- printk("NCR53C90A(esp100a) detected\n");
+ printk("NCR53C90A(esp100a)\n");
esp->erev = esp100a;
} else {
int target;
for(target=0; target<8; target++)
esp->config3[target] = 0;
- eregs->esp_cfg3 = 0;
+ eregs->esp_cfg3 = esp->prev_cfg3 = 0;
if(ccf > ESP_CCF_F5) {
- printk("NCR53C9XF(espfast) detected\n");
+ printk("NCR53C9XF(espfast)\n");
esp->erev = fast;
eregs->esp_cfg2 = esp->config2 = 0;
esp->sync_defp = SYNC_DEFP_FAST;
} else {
- printk("NCR53C9x(esp236) detected\n");
+ printk("NCR53C9x(esp236)\n");
esp->erev = esp236;
eregs->esp_cfg2 = esp->config2 = 0;
}
@@ -983,6 +1029,10 @@ esp_irq_acquired:
esp->prevmsgout = esp->prevmsgin = 0;
esp->msgout_len = esp->msgin_len = 0;
+ /* Clear the one behind caches to hold unmatchable values. */
+ esp->prev_soff = esp->prev_stp = esp->prev_cfg3 = 0xff;
+ esp->prev_hme_dmacsr = 0xffffffff;
+
/* Reset the thing before we try anything... */
esp_bootup_reset(esp, eregs);
@@ -1261,6 +1311,59 @@ int esp_proc_info(char *buffer, char **start, off_t offset, int length,
return esp_host_info(esp, buffer, offset, length);
}
+static void esp_get_dmabufs(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
+{
+ if(sp->use_sg == 0) {
+ sp->SCp.this_residual = sp->request_bufflen;
+ sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
+ sp->SCp.buffers_residual = 0;
+ sp->SCp.have_data_in = mmu_get_scsi_one((char *)sp->SCp.buffer,
+ sp->SCp.this_residual,
+ esp->edev->my_bus);
+ sp->SCp.ptr = (char *) ((unsigned long)sp->SCp.have_data_in);
+ } else {
+ sp->SCp.buffer = (struct scatterlist *) sp->buffer;
+ sp->SCp.buffers_residual = sp->use_sg - 1;
+ sp->SCp.this_residual = sp->SCp.buffer->length;
+ mmu_get_scsi_sgl((struct mmu_sglist *) sp->SCp.buffer,
+ sp->SCp.buffers_residual,
+ esp->edev->my_bus);
+ sp->SCp.ptr = (char *) ((unsigned long)sp->SCp.buffer->dvma_address);
+ }
+}
+
+static void esp_release_dmabufs(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
+{
+ if(sp->use_sg == 0)
+ mmu_release_scsi_one(sp->SCp.have_data_in,
+ sp->request_bufflen,
+ esp->edev->my_bus);
+ else
+ mmu_release_scsi_sgl((struct mmu_sglist *)
+ sp->buffer, sp->use_sg - 1,
+ esp->edev->my_bus);
+}
+
+static void esp_restore_pointers(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
+{
+ struct esp_pointers *ep = &esp->data_pointers[sp->target];
+
+ sp->SCp.ptr = ep->saved_ptr;
+ sp->SCp.buffer = ep->saved_buffer;
+ sp->SCp.this_residual = ep->saved_this_residual;
+ sp->SCp.buffers_residual = ep->saved_buffers_residual;
+}
+
+static void esp_save_pointers(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
+{
+ struct esp_pointers *ep = &esp->data_pointers[sp->target];
+
+ ep->saved_ptr = sp->SCp.ptr;
+ ep->saved_buffer = sp->SCp.buffer;
+ ep->saved_this_residual = sp->SCp.this_residual;
+ ep->saved_buffers_residual = sp->SCp.buffers_residual;
+}
+
/* Some rules:
*
* 1) Never ever panic while something is live on the bus.
@@ -1330,7 +1433,7 @@ static inline void build_wide_nego_msg(struct Sparc_ESP *esp, int size)
esp->msgout_len = 4;
}
-static inline void esp_exec_cmd(struct Sparc_ESP *esp)
+static void esp_exec_cmd(struct Sparc_ESP *esp)
{
struct sparc_dma_registers *dregs = esp->dregs;
struct Sparc_ESP_regs *eregs = esp->eregs;
@@ -1341,15 +1444,18 @@ static inline void esp_exec_cmd(struct Sparc_ESP *esp)
int lun, target;
int i;
- /* Hold off if we've been reselected or an IRQ is showing... */
- if(esp->disconnected_SC || DMA_IRQ_P(dregs))
+ /* Hold off if we have disconnected commands and
+ * an IRQ is showing...
+ */
+ if(esp->disconnected_SC && DMA_IRQ_P(dregs))
return;
/* Grab first member of the issue queue. */
SCptr = esp->current_SC = remove_first_SC(&esp->issue_SC);
/* Safe to panic here because current_SC is null. */
- if(!SCptr) panic("esp: esp_exec_cmd and issue queue is NULL");
+ if(!SCptr)
+ panic("esp: esp_exec_cmd and issue queue is NULL");
SDptr = SCptr->device;
lun = SCptr->lun;
@@ -1425,7 +1531,10 @@ do_sync_known:
SDptr->sync_max_offset = 0;
SDptr->sync_min_period = 0;
} else {
- int toshiba_cdrom_hwbug_wkaround = 0;
+ /* Sorry, I have had way too many problems with
+ * various CDROM devices on ESP. -DaveM
+ */
+ int cdrom_hwbug_wkaround = 0;
/* Never allow disconnects or synchronous transfers on
* SparcStation1 and SparcStation1+. Allowing those
@@ -1452,8 +1561,7 @@ do_sync_known:
*/
if(esp->erev == fashme && !SDptr->wide) {
if(!SDptr->borken &&
- (SDptr->type != TYPE_ROM ||
- strncmp(SDptr->vendor, "TOSHIBA", 7))) {
+ SDptr->type != TYPE_ROM) {
build_wide_nego_msg(esp, 16);
SDptr->wide = 1;
esp->wnip = 1;
@@ -1465,12 +1573,11 @@ do_sync_known:
}
if(!SDptr->borken) {
- if((SDptr->type == TYPE_ROM) &&
- (!strncmp(SDptr->vendor, "TOSHIBA", 7))) {
+ if((SDptr->type == TYPE_ROM)) {
/* Nice try sucker... */
- printk(KERN_INFO "esp%d: Disabling sync for buggy "
- "Toshiba CDROM.\n", esp->esp_id);
- toshiba_cdrom_hwbug_wkaround = 1;
+ ESPMISC(("esp%d: Disabling sync for buggy "
+ "CDROM.\n", esp->esp_id));
+ cdrom_hwbug_wkaround = 1;
build_sync_nego_msg(esp, 0, 0);
} else {
build_sync_nego_msg(esp, esp->sync_defp, 15);
@@ -1506,13 +1613,9 @@ after_nego_msg_built:
* thank you very much. ;-)
*/
if(((SDptr->scsi_level < 3) && (SDptr->type != TYPE_TAPE)) ||
-#if 1 /* Until I find out why HME barfs with disconnects enabled... */
- toshiba_cdrom_hwbug_wkaround || SDptr->borken || esp->erev == fashme) {
-#else
- toshiba_cdrom_hwbug_wkaround || SDptr->borken) {
-#endif
- printk(KERN_INFO "esp%d: Disabling DISCONNECT for target %d "
- "lun %d\n", esp->esp_id, SCptr->target, SCptr->lun);
+ cdrom_hwbug_wkaround || SDptr->borken) {
+ ESPMISC((KERN_INFO "esp%d: Disabling DISCONNECT for target %d "
+ "lun %d\n", esp->esp_id, SCptr->target, SCptr->lun));
SDptr->disconnect = 0;
*cmdp++ = IDENTIFY(0, lun);
} else {
@@ -1540,16 +1643,20 @@ after_nego_msg_built:
(ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT);
else
eregs->esp_busid = (target & 7);
- eregs->esp_soff = SDptr->sync_max_offset;
- eregs->esp_stp = SDptr->sync_min_period;
- if(esp->erev > esp100a)
- eregs->esp_cfg3 = esp->config3[target];
-
+ if (esp->prev_soff != SDptr->sync_max_offset ||
+ esp->prev_stp != SDptr->sync_min_period ||
+ (esp->erev > esp100a &&
+ esp->prev_cfg3 != esp->config3[target])) {
+ eregs->esp_soff = esp->prev_soff = SDptr->sync_max_offset;
+ eregs->esp_stp = esp->prev_stp = SDptr->sync_min_period;
+ if(esp->erev > esp100a)
+ eregs->esp_cfg3 =
+ esp->prev_cfg3 =
+ esp->config3[target];
+ }
i = (cmdp - esp->esp_command);
if(esp->erev == fashme) {
- unsigned long tmp;
-
esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* Grrr! */
/* Set up the DMA and HME counters */
@@ -1560,12 +1667,12 @@ after_nego_msg_built:
esp_cmd(esp, eregs, the_esp_command);
/* Talk about touchy hardware... */
- tmp = dregs->cond_reg;
- tmp |= (DMA_SCSI_DISAB | DMA_ENABLE);
- tmp &= ~(DMA_ST_WRITE);
+ esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr |
+ (DMA_SCSI_DISAB | DMA_ENABLE)) &
+ ~(DMA_ST_WRITE));
dregs->cnt = 16;
dregs->st_addr = esp->esp_command_dvma;
- dregs->cond_reg = tmp;
+ dregs->cond_reg = esp->prev_hme_dmacsr;
} else {
/* Set up the DMA and ESP counters */
eregs->esp_tclow = i;
@@ -1599,35 +1706,10 @@ int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
/* We use the scratch area. */
ESPQUEUE(("esp_queue: target=%d lun=%d ", SCpnt->target, SCpnt->lun));
ESPDISC(("N<%02x,%02x>", SCpnt->target, SCpnt->lun));
- if(!SCpnt->use_sg) {
- ESPQUEUE(("!use_sg\n"));
- SCpnt->SCp.this_residual = SCpnt->request_bufflen;
- SCpnt->SCp.buffer =
- (struct scatterlist *) SCpnt->request_buffer;
- SCpnt->SCp.buffers_residual = 0;
- /* Sneaky. */
- SCpnt->SCp.have_data_in = mmu_get_scsi_one((char *)SCpnt->SCp.buffer,
- SCpnt->SCp.this_residual,
- esp->edev->my_bus);
- /* XXX The casts are extremely gross, but with 64-bit kernel
- * XXX and 32-bit SBUS what am I to do? -DaveM
- */
- SCpnt->SCp.ptr = (char *)((unsigned long)SCpnt->SCp.have_data_in);
- } else {
- ESPQUEUE(("use_sg "));
-#ifdef DEBUG_ESP_SG
- printk("esp%d: sglist at %p with %d buffers\n",
- esp->esp_id, SCpnt->buffer, SCpnt->use_sg);
-#endif
- SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
- SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
- SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
- mmu_get_scsi_sgl((struct mmu_sglist *) SCpnt->SCp.buffer,
- SCpnt->SCp.buffers_residual,
- esp->edev->my_bus);
- /* XXX Again these casts are sick... -DaveM */
- SCpnt->SCp.ptr=(char *)((unsigned long)SCpnt->SCp.buffer->dvma_address);
- }
+
+ esp_get_dmabufs(esp, SCpnt);
+ esp_save_pointers(esp, SCpnt); /* FIXME for tag queueing */
+
SCpnt->SCp.Status = CHECK_CONDITION;
SCpnt->SCp.Message = 0xff;
SCpnt->SCp.sent_command = 0;
@@ -1661,7 +1743,7 @@ int esp_command(Scsi_Cmnd *SCpnt)
}
/* Dump driver state. */
-static inline void esp_dump_cmd(Scsi_Cmnd *SCptr)
+static void esp_dump_cmd(Scsi_Cmnd *SCptr)
{
ESPLOG(("[tgt<%02x> lun<%02x> "
"pphase<%s> cphase<%s>]",
@@ -1670,8 +1752,8 @@ static inline void esp_dump_cmd(Scsi_Cmnd *SCptr)
phase_string(SCptr->SCp.phase)));
}
-static inline void esp_dump_state(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static void esp_dump_state(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
#ifdef DEBUG_ESP_CMDS
@@ -1766,6 +1848,7 @@ int esp_abort(Scsi_Cmnd *SCptr)
if(this == SCptr) {
*prev = (Scsi_Cmnd *) this->host_scribble;
this->host_scribble = NULL;
+ esp_release_dmabufs(esp, this);
this->result = DID_ABORT << 16;
this->done(this);
if(don)
@@ -1780,8 +1863,11 @@ int esp_abort(Scsi_Cmnd *SCptr)
* on the bus at this time. So, we let the SCSI code wait
* a little bit and try again later.
*/
- if(esp->current_SC)
+ if(esp->current_SC) {
+ if(don)
+ DMA_INTSON(dregs);
return SCSI_ABORT_BUSY;
+ }
/* It's disconnected, we have to reconnect to re-establish
* the nexus and tell the device to abort. However, we really
@@ -1790,20 +1876,70 @@ int esp_abort(Scsi_Cmnd *SCptr)
* happens, we are really hung so reset the bus.
*/
+ if(don)
+ DMA_INTSON(dregs);
return SCSI_ABORT_SNOOZE;
}
+/* We've sent ESP_CMD_RS to the ESP, the interrupt had just
+ * arrived indicating the end of the SCSI bus reset. Our job
+ * is to clean out the command queues and begin re-execution
+ * of SCSI commands once more.
+ */
+static int esp_finish_reset(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
+{
+ Scsi_Cmnd *sp = esp->current_SC;
+
+ /* Clean up currently executing command, if any. */
+ if (sp != NULL) {
+ esp_release_dmabufs(esp, sp);
+ sp->result = (DID_RESET << 16);
+ sp->scsi_done(sp);
+ esp->current_SC = NULL;
+ }
+
+ /* Clean up disconnected queue, they have been invalidated
+ * by the bus reset.
+ */
+ if (esp->disconnected_SC) {
+ while((sp = remove_first_SC(&esp->disconnected_SC)) != NULL) {
+ esp_release_dmabufs(esp, sp);
+ sp->result = (DID_RESET << 16);
+ sp->scsi_done(sp);
+ }
+ }
+
+ /* SCSI bus reset is complete. */
+ esp->resetting_bus = 0;
+
+ /* Ok, now it is safe to get commands going once more. */
+ if(esp->issue_SC)
+ esp_exec_cmd(esp);
+
+ return do_intr_end;
+}
+
+static int esp_do_resetbus(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
+{
+ ESPLOG(("esp%d: Resetting scsi bus\n", esp->esp_id));
+ esp->resetting_bus = 1;
+ esp_cmd(esp, eregs, ESP_CMD_RS);
+
+ return do_intr_end;
+}
+
/* Reset ESP chip, reset hanging bus, then kill active and
* disconnected commands for targets without soft reset.
*/
int esp_reset(Scsi_Cmnd *SCptr, unsigned int how)
{
struct Sparc_ESP *esp = (struct Sparc_ESP *) SCptr->host->hostdata;
- struct Sparc_ESP_regs *eregs = esp->eregs;
- ESPLOG(("esp%d: Resetting scsi bus\n", esp->esp_id));
- esp->resetting_bus = 1;
- esp_cmd(esp, eregs, ESP_CMD_RS);
+ (void) esp_do_resetbus(esp, esp->eregs, esp->dregs);
return SCSI_RESET_PENDING;
}
@@ -1817,25 +1953,7 @@ static void esp_done(struct Sparc_ESP *esp, int error)
done_SC = esp->current_SC;
esp->current_SC = NULL;
-
- /* Free dvma entry. */
- if(!done_SC->use_sg) {
- /* Sneaky. */
- mmu_release_scsi_one(done_SC->SCp.have_data_in,
- done_SC->request_bufflen,
- esp->edev->my_bus);
- } else {
-#ifdef DEBUG_ESP_SG
- printk("esp%d: unmapping sg ", esp->esp_id);
-#endif
- mmu_release_scsi_sgl((struct mmu_sglist *) done_SC->buffer,
- done_SC->use_sg - 1,
- esp->edev->my_bus);
-#ifdef DEBUG_ESP_SG
- printk("done.\n");
-#endif
- }
-
+ esp_release_dmabufs(esp, done_SC);
done_SC->result = error;
done_SC->scsi_done(done_SC);
@@ -1857,11 +1975,6 @@ static void esp_done(struct Sparc_ESP *esp, int error)
/* Wheee, ESP interrupt engine. */
-enum {
- do_phase_determine, do_reset_bus, do_reset_complete,
- do_work_bus, do_intr_end,
-};
-
/* Forward declarations. */
static int esp_do_phase_determine(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
struct sparc_dma_registers *dregs);
@@ -1880,29 +1993,29 @@ static int esp_do_msgout(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
struct sparc_dma_registers *dregs);
-static inline int sreg_datainp(unchar sreg)
-{
- return (sreg & ESP_STAT_PMASK) == ESP_DIP;
-}
-
-static inline int sreg_dataoutp(unchar sreg)
-{
- return (sreg & ESP_STAT_PMASK) == ESP_DOP;
-}
+#define sreg_datainp(__sreg) (((__sreg) & ESP_STAT_PMASK) == ESP_DIP)
+#define sreg_dataoutp(__sreg) (((__sreg) & ESP_STAT_PMASK) == ESP_DOP)
-/* Did they drop these fabs on the floor or what?!?!! */
-static inline void hme_fifo_hwbug_workaround(struct Sparc_ESP *esp,
- struct Sparc_ESP_regs *eregs)
+/* Read any bytes found in the FAS366 fifo, storing them into
+ * the ESP driver software state structure.
+ */
+static void hme_fifo_read(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs)
{
+ unsigned long count = 0;
unchar status = esp->sreg;
- /* Cannot safely frob the fifo for these following cases. */
- if(sreg_datainp(status) || sreg_dataoutp(status) ||
- (esp->current_SC && esp->current_SC->SCp.phase == in_data_done)) {
+ /* Cannot safely frob the fifo for these following cases, but
+ * we must always read the fifo when the reselect interrupt
+ * is pending.
+ */
+ if(((esp->ireg & ESP_INTR_RSEL) == 0) &&
+ (sreg_datainp(status) ||
+ sreg_dataoutp(status) ||
+ (esp->current_SC &&
+ esp->current_SC->SCp.phase == in_data_done))) {
ESPHME(("<wkaround_skipped>"));
- return;
} else {
- unsigned long count = 0;
unsigned long fcnt = eregs->esp_fflags & ESP_FF_FBYTES;
/* The HME stores bytes in multiples of 2 in the fifo. */
@@ -1923,9 +2036,9 @@ static inline void hme_fifo_hwbug_workaround(struct Sparc_ESP *esp,
} else {
ESPHME(("no_xtra_byte"));
}
- esp->hme_fifo_workaround_count = count;
- ESPHME(("wkarnd_cnt=%d]", (int)count));
}
+ ESPHME(("wkarnd_cnt=%d]", (int)count));
+ esp->hme_fifo_workaround_count = count;
}
static inline void hme_fifo_push(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
@@ -1950,7 +2063,10 @@ static inline int skipahead1(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs
return 0;
if(DMA_IRQ_P(dregs)) {
/* Yes, we are able to save an interrupt. */
- esp->sreg = eregs->esp_status;
+ if (esp->erev == fashme)
+ esp->sreg2 = eregs->esp_status2;
+ esp->sreg = (eregs->esp_status & ~(ESP_STAT_INTR));
+ esp->ireg = eregs->esp_intrpt;
if(esp->erev == fashme) {
/* This chip is really losing. */
ESPHME(("HME["));
@@ -1960,10 +2076,10 @@ static inline int skipahead1(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs
* Happy Meal indeed....
*/
ESPHME(("fifo_workaround]"));
- hme_fifo_hwbug_workaround(esp, eregs);
+ if(!(esp->sreg2 & ESP_STAT2_FEMPTY) ||
+ (esp->sreg2 & ESP_STAT2_F1BYTE))
+ hme_fifo_read(esp, eregs);
}
- esp->ireg = eregs->esp_intrpt;
- esp->sreg &= ~(ESP_STAT_INTR);
if(!(esp->ireg & ESP_INTR_SR))
return 0;
else
@@ -1984,7 +2100,10 @@ static inline int skipahead2(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs
return 0;
if(DMA_IRQ_P(dregs)) {
/* Yes, we are able to save an interrupt. */
- esp->sreg = eregs->esp_status;
+ if (esp->erev == fashme)
+ esp->sreg2 = eregs->esp_status2;
+ esp->sreg = (eregs->esp_status & ~(ESP_STAT_INTR));
+ esp->ireg = eregs->esp_intrpt;
if(esp->erev == fashme) {
/* This chip is really losing. */
ESPHME(("HME["));
@@ -1995,10 +2114,10 @@ static inline int skipahead2(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs
* Happy Meal indeed....
*/
ESPHME(("fifo_workaround]"));
- hme_fifo_hwbug_workaround(esp, eregs);
+ if(!(esp->sreg2 & ESP_STAT2_FEMPTY) ||
+ (esp->sreg2 & ESP_STAT2_F1BYTE))
+ hme_fifo_read(esp, eregs);
}
- esp->ireg = eregs->esp_intrpt;
- esp->sreg &= ~(ESP_STAT_INTR);
if(!(esp->ireg & ESP_INTR_SR))
return 0;
else
@@ -2049,21 +2168,27 @@ static inline void dma_drain(struct sparc_dma_registers *dregs, enum dvma_rev dr
}
}
-static inline void dma_invalidate(struct sparc_dma_registers *dregs, enum dvma_rev drev)
+static inline void dma_invalidate(struct Sparc_ESP *esp,
+ struct sparc_dma_registers *dregs,
+ enum dvma_rev drev)
{
unsigned int tmp;
if(drev == dvmahme) {
- /* SMCC can bite me. */
- tmp = dregs->cond_reg;
dregs->cond_reg = DMA_RST_SCSI;
- /* This would explain a lot. */
- tmp |= (DMA_PARITY_OFF|DMA_2CLKS|DMA_SCSI_DISAB);
+ esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr |
+ (DMA_PARITY_OFF | DMA_2CLKS |
+ DMA_SCSI_DISAB | DMA_INT_ENAB)) &
+ ~(DMA_ST_WRITE | DMA_ENABLE));
- tmp &= ~(DMA_ENABLE|DMA_ST_WRITE);
dregs->cond_reg = 0;
- dregs->cond_reg = tmp;
+ dregs->cond_reg = esp->prev_hme_dmacsr;
+
+ /* This is necessary to avoid having the SCSI channel
+ * engine lock up on us.
+ */
+ dregs->st_addr = 0;
} else {
while(dregs->cond_reg & DMA_PEND_READ)
udelay(1);
@@ -2076,10 +2201,12 @@ static inline void dma_invalidate(struct sparc_dma_registers *dregs, enum dvma_r
}
}
-static inline void dma_flashclear(struct sparc_dma_registers *dregs, enum dvma_rev drev)
+static inline void dma_flashclear(struct Sparc_ESP *esp,
+ struct sparc_dma_registers *dregs,
+ enum dvma_rev drev)
{
dma_drain(dregs, drev);
- dma_invalidate(dregs, drev);
+ dma_invalidate(esp, dregs, drev);
}
static inline int dma_can_transfer(Scsi_Cmnd *sp, enum dvma_rev drev)
@@ -2101,56 +2228,38 @@ static inline int dma_can_transfer(Scsi_Cmnd *sp, enum dvma_rev drev)
return sz;
}
-/* Misc. esp helper routines. */
-static inline void esp_setcount(struct Sparc_ESP_regs *eregs, int cnt, int hme)
-{
- eregs->esp_tclow = (cnt & 0xff);
- eregs->esp_tcmed = ((cnt >> 8) & 0xff);
- if(hme) {
- eregs->fas_rlo = 0;
- eregs->fas_rhi = 0;
+/* Misc. esp helper macros. */
+#define esp_setcount(__eregs, __cnt, __hme) \
+ (__eregs)->esp_tclow = ((__cnt) & 0xff); \
+ (__eregs)->esp_tcmed = (((__cnt) >> 8) & 0xff); \
+ if(__hme) { \
+ (__eregs)->fas_rlo = 0; \
+ (__eregs)->fas_rhi = 0; \
}
-}
-static inline int esp_getcount(struct Sparc_ESP_regs *eregs)
-{
- return (((eregs->esp_tclow)&0xff) |
- (((eregs->esp_tcmed)&0xff) << 8));
-}
+#define esp_getcount(__eregs) \
+ ((((__eregs)->esp_tclow)&0xff) | \
+ ((((__eregs)->esp_tcmed)&0xff) << 8))
-static inline int fcount(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
-{
- if(esp->erev == fashme)
- return esp->hme_fifo_workaround_count;
- else
- return eregs->esp_fflags & ESP_FF_FBYTES;
-}
+#define fcount(__esp, __eregs) \
+ (((__esp)->erev == fashme) ? \
+ (__esp)->hme_fifo_workaround_count : \
+ (__eregs)->esp_fflags & ESP_FF_FBYTES)
-static inline int fnzero(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
-{
- if(esp->erev == fashme)
- return 0;
- else
- return eregs->esp_fflags & ESP_FF_ONOTZERO;
-}
+#define fnzero(__esp, __eregs) \
+ (((__esp)->erev == fashme) ? 0 : \
+ (__eregs)->esp_fflags & ESP_FF_ONOTZERO)
/* XXX speculative nops unnecessary when continuing amidst a data phase
* XXX even on esp100!!! another case of flooding the bus with I/O reg
* XXX writes...
*/
-static inline void esp_maybe_nop(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
-{
- if(esp->erev == esp100)
- esp_cmd(esp, eregs, ESP_CMD_NULL);
-}
+#define esp_maybe_nop(__esp, __eregs) \
+ if((__esp)->erev == esp100) \
+ esp_cmd((__esp), (__eregs), ESP_CMD_NULL)
-static inline int sreg_to_dataphase(unchar sreg)
-{
- if((sreg & ESP_STAT_PMASK) == ESP_DOP)
- return in_dataout;
- else
- return in_datain;
-}
+#define sreg_to_dataphase(__sreg) \
+ ((((__sreg) & ESP_STAT_PMASK) == ESP_DOP) ? in_dataout : in_datain)
/* The ESP100 when in synchronous data phase, can mistake a long final
* REQ pulse from the target as an extra byte, it places whatever is on
@@ -2242,10 +2351,19 @@ static inline int reconnect_lun(struct Sparc_ESP *esp, struct Sparc_ESP_regs *er
lun = esp->hme_fifo_workaround_buffer[1];
else
lun = eregs->esp_fdata;
+
+ /* Yes, you read this correctly. We report lun of zero
+ * if we see parity error. ESP reports parity error for
+ * the lun byte, and this is the only way to hope to recover
+ * because the target is connected.
+ */
if(esp->sreg & ESP_STAT_PERR)
return 0;
+
+ /* Check for illegal bits being set in the lun. */
if((lun & 0x40) || !(lun & 0x80))
return -1;
+
return lun & 7;
}
@@ -2256,13 +2374,18 @@ static inline void esp_connect(struct Sparc_ESP *esp, struct Sparc_ESP_regs *ere
Scsi_Cmnd *sp)
{
Scsi_Device *dp = sp->device;
- eregs->esp_soff = dp->sync_max_offset;
- eregs->esp_stp = dp->sync_min_period;
- if(esp->erev > esp100a)
- eregs->esp_cfg3 = esp->config3[sp->target];
- if(esp->erev == fashme)
- eregs->esp_busid = (sp->target & 0xf) |
- (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT);
+
+ if(esp->prev_soff != dp->sync_max_offset ||
+ esp->prev_stp != dp->sync_min_period ||
+ (esp->erev > esp100a &&
+ esp->prev_cfg3 != esp->config3[sp->target])) {
+ eregs->esp_soff = esp->prev_soff = dp->sync_max_offset;
+ eregs->esp_stp = esp->prev_stp = dp->sync_min_period;
+ if(esp->erev > esp100a)
+ eregs->esp_cfg3 =
+ esp->prev_cfg3 =
+ esp->config3[sp->target];
+ }
esp->current_SC = sp;
}
@@ -2272,8 +2395,8 @@ static inline void esp_connect(struct Sparc_ESP *esp, struct Sparc_ESP_regs *ere
static inline void esp_reconnect(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
{
if(!esp->disconnected_SC)
- printk("esp%d: Weird, being reselected but disconnected "
- "command queue is empty.\n", esp->esp_id);
+ ESPLOG(("esp%d: Weird, being reselected but disconnected "
+ "command queue is empty.\n", esp->esp_id));
esp->snip = 0;
esp->current_SC = 0;
sp->SCp.phase = not_issued;
@@ -2281,8 +2404,8 @@ static inline void esp_reconnect(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
}
/* Begin message in phase. */
-static inline int esp_do_msgin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static int esp_do_msgin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
/* Must be very careful with the fifo on the HME */
if((esp->erev != fashme) || !(eregs->esp_status2 & ESP_STAT2_FEMPTY))
@@ -2335,8 +2458,8 @@ static inline void advance_sg(Scsi_Cmnd *sp)
* within a buffer or sub-buffer should not upset us at all no matter
* how bad the target and/or ESP fucks things up.
*/
-static inline int esp_do_data(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static int esp_do_data(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
int thisphase, hmuch;
@@ -2350,19 +2473,28 @@ static inline int esp_do_data(struct Sparc_ESP *esp, struct Sparc_ESP_regs *ereg
ESPDATA(("hmuch<%d> ", hmuch));
esp->current_transfer_size = hmuch;
if(esp->erev == fashme) {
- unsigned long tmp = dregs->cond_reg;
+ unsigned long tmp = esp->prev_hme_dmacsr;
- /* Touchy chip, this stupid HME scsi adapter... */
+ /* Always set the ESP count registers first. */
esp_setcount(eregs, hmuch, 1);
- esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
- dregs->cnt = hmuch;
+
+ /* Get the DMA csr computed. */
tmp |= (DMA_SCSI_DISAB | DMA_ENABLE);
- if(thisphase == in_datain)
+ if (thisphase == in_datain)
tmp |= DMA_ST_WRITE;
else
tmp &= ~(DMA_ST_WRITE);
+ esp->prev_hme_dmacsr = tmp;
+
+ if (thisphase == in_datain) {
+ dregs->cnt = hmuch;
+ esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
+ } else {
+ esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
+ dregs->cnt = hmuch;
+ }
dregs->st_addr = ((__u32)((unsigned long)SCptr->SCp.ptr));
- dregs->cond_reg = tmp;
+ dregs->cond_reg = esp->prev_hme_dmacsr;
} else {
esp_setcount(eregs, hmuch, 0);
dma_setup(dregs, esp->dma->revision,
@@ -2375,9 +2507,9 @@ static inline int esp_do_data(struct Sparc_ESP *esp, struct Sparc_ESP_regs *ereg
}
/* See how successful the data transfer was. */
-static inline int esp_do_data_finale(struct Sparc_ESP *esp,
- struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static int esp_do_data_finale(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
int bogus_data = 0, bytes_sent = 0, fifocnt, ecount = 0;
@@ -2398,7 +2530,7 @@ static inline int esp_do_data_finale(struct Sparc_ESP *esp,
}
dma_drain(dregs, esp->dma->revision);
}
- dma_invalidate(dregs, esp->dma->revision);
+ dma_invalidate(esp, dregs, esp->dma->revision);
/* This could happen for the above parity error case. */
if(!(esp->ireg == ESP_INTR_BSERV)) {
@@ -2424,26 +2556,43 @@ static inline int esp_do_data_finale(struct Sparc_ESP *esp,
ecount = esp_getcount(eregs);
bytes_sent = esp->current_transfer_size;
- /* Uhhh, might not want both of these conditionals to run
- * at once on HME due to the fifo problems it has. Consider
- * changing it to:
- *
- * if(!(esp->sreg & ESP_STAT_TCNT)) {
- * bytes_sent -= ecount;
- * } else if(SCptr->SCp.phase == in_dataout) {
- * bytes_sent -= fifocnt;
- * }
- *
- * But only for the HME case, leave the current code alone
- * for all other ESP revisions as we know the existing code
- * works just fine for them.
- */
ESPDATA(("trans_sz=%d, ", bytes_sent));
if(esp->erev == fashme) {
if(!(esp->sreg & ESP_STAT_TCNT)) {
- bytes_sent -= esp_getcount(eregs);
- } else if(SCptr->SCp.phase == in_dataout) {
+ ecount = esp_getcount(eregs);
+ bytes_sent -= ecount;
+ }
+
+ /* Always subtract any cruft remaining in the FIFO. */
+ if(esp->prev_cfg3 & ESP_CONFIG3_EWIDE)
+ fifocnt <<= 1;
+ if(SCptr->SCp.phase == in_dataout)
bytes_sent -= fifocnt;
+
+ /* I have an IBM disk which exhibits the following
+ * behavior during writes to it. It disconnects in
+ * the middle of a partial transfer, the current sglist
+ * buffer is 1024 bytes, the disk stops data transfer
+ * at 512 bytes.
+ *
+ * However the FAS366 reports that 32 more bytes were
+ * transferred than really were. This is precisely
+ * the size of a fully loaded FIFO in wide scsi mode.
+ * The FIFO state recorded indicates that it is empty.
+ *
+ * I have no idea if this is a bug in the FAS366 chip
+ * or a bug in the firmware on this IBM disk. In any
+ * event the following seems to be a good workaround. -DaveM
+ */
+ if (bytes_sent != esp->current_transfer_size &&
+ SCptr->SCp.phase == in_dataout) {
+ int mask = (64 - 1);
+
+ if((esp->prev_cfg3 & ESP_CONFIG3_EWIDE) == 0)
+ mask >>= 1;
+
+ if (bytes_sent & mask)
+ bytes_sent -= (bytes_sent & mask);
}
} else {
if(!(esp->sreg & ESP_STAT_TCNT))
@@ -2479,6 +2628,8 @@ static inline int esp_do_data_finale(struct Sparc_ESP *esp,
* driver. No idea why it happened, but allowing
* this value to be negative caused things to
* lock up. This allows greater chance of recovery.
+ * In fact every time I've seen this, it has been
+ * a driver bug without question.
*/
ESPLOG(("esp%d: yieee, bytes_sent < 0!\n", esp->esp_id));
ESPLOG(("esp%d: csz=%d fifocount=%d ecount=%d\n",
@@ -2495,7 +2646,7 @@ static inline int esp_do_data_finale(struct Sparc_ESP *esp,
SCptr->SCp.this_residual -= bytes_sent;
if(SCptr->SCp.this_residual < 0) {
/* shit */
- printk("esp%d: Data transfer overrun.\n", esp->esp_id);
+ ESPLOG(("esp%d: Data transfer overrun.\n", esp->esp_id));
SCptr->SCp.this_residual = 0;
}
@@ -2526,11 +2677,49 @@ static inline int esp_do_data_finale(struct Sparc_ESP *esp,
return do_intr_end;
}
+/* We received a non-good status return at the end of
+ * running a SCSI command. This is used to decide if
+ * we should clear our synchronous transfer state for
+ * such a device when that happens.
+ *
+ * The idea is that when spinning up a disk or rewinding
+ * a tape, we don't want to go into a loop re-negotiating
+ * synchronous capabilities over and over.
+ */
+static int esp_should_clear_sync(Scsi_Cmnd *sp)
+{
+ unchar cmd1 = sp->cmnd[0];
+ unchar cmd2 = sp->data_cmnd[0];
+
+ /* These cases are for spinning up a disk and
+ * waiting for that spinup to complete.
+ */
+ if(cmd1 == START_STOP ||
+ cmd2 == START_STOP)
+ return 0;
+
+ if(cmd1 == TEST_UNIT_READY ||
+ cmd2 == TEST_UNIT_READY)
+ return 0;
+
+ /* One more special case for SCSI tape drives,
+ * this is what is used to probe the device for
+ * completion of a rewind or tape load operation.
+ */
+ if(sp->device->type == TYPE_TAPE) {
+ if(cmd1 == MODE_SENSE ||
+ cmd2 == MODE_SENSE)
+ return 0;
+ }
+
+ return 1;
+}
+
/* Either a command is completing or a target is dropping off the bus
* to continue the command in the background so we can do other work.
*/
-static inline int esp_do_freebus(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static int esp_do_freebus(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
int rval;
@@ -2549,9 +2738,11 @@ static inline int esp_do_freebus(struct Sparc_ESP *esp, struct Sparc_ESP_regs *e
if(esp->disconnected_SC || (esp->erev == fashme))
esp_cmd(esp, eregs, ESP_CMD_ESEL);
- if(SCptr->SCp.Status != GOOD && SCptr->SCp.Status != CONDITION_GOOD &&
+ if(SCptr->SCp.Status != GOOD &&
+ SCptr->SCp.Status != CONDITION_GOOD &&
((1<<SCptr->target) & esp->targets_present) &&
- SCptr->device->sync && SCptr->device->sync_max_offset) {
+ SCptr->device->sync &&
+ SCptr->device->sync_max_offset) {
/* SCSI standard says that the synchronous capabilities
* should be renegotiated at this point. Most likely
* we are about to request sense from this target
@@ -2568,15 +2759,7 @@ static inline int esp_do_freebus(struct Sparc_ESP *esp, struct Sparc_ESP_regs *e
* can report not ready many times right after
* loading up a tape.
*/
- if(SCptr->cmnd[0] != START_STOP &&
- SCptr->data_cmnd[0] != START_STOP &&
- SCptr->cmnd[0] != TEST_UNIT_READY &&
- SCptr->data_cmnd[0] != TEST_UNIT_READY &&
- !(SCptr->device->type == TYPE_TAPE &&
- (SCptr->cmnd[0] == TEST_UNIT_READY ||
- SCptr->data_cmnd[0] == TEST_UNIT_READY ||
- SCptr->cmnd[0] == MODE_SENSE ||
- SCptr->data_cmnd[0] == MODE_SENSE)))
+ if(esp_should_clear_sync(SCptr) != 0)
SCptr->device->sync = 0;
}
ESPDISC(("F<%02x,%02x>", SCptr->target, SCptr->lun));
@@ -2603,9 +2786,43 @@ static inline int esp_do_freebus(struct Sparc_ESP *esp, struct Sparc_ESP_regs *e
return do_intr_end;
}
+/* When a reselect occurs, and we cannot find the command to
+ * reconnect to in our queues, we do this.
+ */
+static int esp_bad_reconnect(struct Sparc_ESP *esp)
+{
+ Scsi_Cmnd *sp;
+
+ ESPLOG(("esp%d: Eieeee, reconnecting unknown command!\n",
+ esp->esp_id));
+ ESPLOG(("QUEUE DUMP\n"));
+ sp = esp->issue_SC;
+ ESPLOG(("esp%d: issue_SC[", esp->esp_id));
+ while(sp) {
+ ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
+ sp = (Scsi_Cmnd *) sp->host_scribble;
+ }
+ ESPLOG(("]\n"));
+ sp = esp->current_SC;
+ ESPLOG(("esp%d: current_SC[", esp->esp_id));
+ while(sp) {
+ ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
+ sp = (Scsi_Cmnd *) sp->host_scribble;
+ }
+ ESPLOG(("]\n"));
+ sp = esp->disconnected_SC;
+ ESPLOG(("esp%d: disconnected_SC[", esp->esp_id));
+ while(sp) {
+ ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
+ sp = (Scsi_Cmnd *) sp->host_scribble;
+ }
+ ESPLOG(("]\n"));
+ return do_reset_bus;
+}
+
/* Do the needy when a target tries to reconnect to us. */
-static inline int esp_do_reconnect(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static int esp_do_reconnect(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
int lun, target;
Scsi_Cmnd *SCptr;
@@ -2625,12 +2842,8 @@ static inline int esp_do_reconnect(struct Sparc_ESP *esp, struct Sparc_ESP_regs
/* Things look ok... */
ESPDISC(("R<%02x,%02x>", target, lun));
- /* Must flush both FIFO and the DVMA on HME. */
- if(esp->erev == fashme) {
- /* XXX this still doesn't fix the problem... */
- esp_cmd(esp, eregs, ESP_CMD_FLUSH);
- dma_invalidate(esp->dregs, dvmahme);
- } else {
+ /* Must not flush FIFO or DVMA on HME. */
+ if(esp->erev != fashme) {
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
if(esp100_reconnect_hwbug(esp, eregs))
return do_reset_bus;
@@ -2638,39 +2851,19 @@ static inline int esp_do_reconnect(struct Sparc_ESP *esp, struct Sparc_ESP_regs
}
SCptr = remove_SC(&esp->disconnected_SC, (unchar) target, (unchar) lun);
- if(!SCptr) {
- Scsi_Cmnd *sp;
+ if(!SCptr)
+ return esp_bad_reconnect(esp);
- ESPLOG(("esp%d: Eieeee, reconnecting unknown command!\n",
- esp->esp_id));
- ESPLOG(("QUEUE DUMP\n"));
- sp = esp->issue_SC;
- ESPLOG(("esp%d: issue_SC[", esp->esp_id));
- while(sp) {
- ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
- sp = (Scsi_Cmnd *) sp->host_scribble;
- }
- ESPLOG(("]\n"));
- sp = esp->current_SC;
- ESPLOG(("esp%d: current_SC[", esp->esp_id));
- while(sp) {
- ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
- sp = (Scsi_Cmnd *) sp->host_scribble;
- }
- ESPLOG(("]\n"));
- sp = esp->disconnected_SC;
- ESPLOG(("esp%d: disconnected_SC[", esp->esp_id));
- while(sp) {
- ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
- sp = (Scsi_Cmnd *) sp->host_scribble;
- }
- ESPLOG(("]\n"));
- return do_reset_bus;
- }
esp_connect(esp, eregs, SCptr);
esp_cmd(esp, eregs, ESP_CMD_MOK);
- /* No need for explicit restore pointers operation. */
+ if(esp->erev == fashme)
+ eregs->esp_busid = (SCptr->target & 0xf) |
+ (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT);
+
+ /* Reconnect implies a restore pointers operation. */
+ esp_restore_pointers(esp, SCptr);
+
esp->snip = 0;
esp_advance_phase(SCptr, in_the_dark);
return do_intr_end;
@@ -2698,7 +2891,7 @@ static int esp_do_status(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
esp_cmd(esp, eregs, ESP_CMD_MOK);
if(esp->erev != fashme) {
- dma_flashclear(dregs, esp->dma->revision);
+ dma_flashclear(esp, dregs, esp->dma->revision);
/* Wait till the first bits settle. */
while(esp->esp_command[0] == 0xff)
@@ -2800,112 +2993,135 @@ static int esp_do_status(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
}
}
-/* The target has control of the bus and we have to see where it has
- * taken us.
- */
-static int esp_do_phase_determine(struct Sparc_ESP *esp,
- struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static int esp_enter_status(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
- Scsi_Cmnd *SCptr = esp->current_SC;
+ unchar thecmd = ESP_CMD_ICCSEQ;
- ESPPHASE(("esp_do_phase_determine: "));
- if(!(esp->ireg & ESP_INTR_DC)) {
- switch(esp->sreg & ESP_STAT_PMASK) {
- case ESP_DOP:
- case ESP_DIP:
- ESPPHASE(("to data phase\n"));
- return esp_do_data(esp, eregs, dregs);
+ esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+ if(esp->erev != fashme) {
+ esp->esp_command[0] = esp->esp_command[1] = 0xff;
+ eregs->esp_tclow = 2;
+ eregs->esp_tcmed = 0;
+ dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE);
+ if(esp->dma->revision == dvmaesc1)
+ dregs->cnt = 0x100;
+ dregs->st_addr = esp->esp_command_dvma;
+ thecmd |= ESP_CMD_DMA;
+ }
+ esp_cmd(esp, eregs, thecmd);
+ esp_advance_phase(esp->current_SC, in_status);
- case ESP_STATP:
- /* Whee, status phase, finish up the command. */
- ESPPHASE(("to status phase\n"));
- esp_cmd(esp, eregs, ESP_CMD_FLUSH);
- if(esp->erev != fashme) {
- esp->esp_command[0] = 0xff;
- esp->esp_command[1] = 0xff;
- eregs->esp_tclow = 2;
- eregs->esp_tcmed = 0;
- dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE);
- if(esp->dma->revision == dvmaesc1)
- dregs->cnt = 0x1000;
- dregs->st_addr = esp->esp_command_dvma;
- esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_ICCSEQ);
- } else {
- /* Using DVMA for status/message bytes is
- * unreliable on HME, nice job QLogic.
- * Happy Meal indeed....
- */
- esp_cmd(esp, eregs, ESP_CMD_ICCSEQ);
- }
- esp_advance_phase(SCptr, in_status);
- return esp_do_status(esp, eregs, dregs);
+ return esp_do_status(esp, eregs, dregs);
+}
- case ESP_MOP:
- ESPPHASE(("to msgout phase\n"));
- esp_advance_phase(SCptr, in_msgout);
- return esp_do_msgout(esp, eregs, dregs);
-
- case ESP_MIP:
- ESPPHASE(("to msgin phase\n"));
- esp_advance_phase(SCptr, in_msgin);
- return esp_do_msgin(esp, eregs, dregs);
-
- case ESP_CMDP:
- /* Ugh, we're running a non-standard command the
- * ESP doesn't understand, one byte at a time.
- */
- ESPPHASE(("to cmd phase\n"));
- esp_advance_phase(SCptr, in_cmdbegin);
- return esp_do_cmdbegin(esp, eregs, dregs);
- };
- } else {
- Scsi_Device *dp = SCptr->device;
+static int esp_disconnect_amidst_phases(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
+{
+ Scsi_Cmnd *sp = esp->current_SC;
+ Scsi_Device *dp = sp->device;
- /* This means real problems if we see this
- * here. Unless we were actually trying
- * to force the device to abort/reset.
- */
- ESPLOG(("esp%d Disconnect amidst phases, ", esp->esp_id));
- ESPLOG(("pphase<%s> cphase<%s>, ",
- phase_string(SCptr->SCp.phase),
- phase_string(SCptr->SCp.sent_command)));
- if(esp->disconnected_SC || (esp->erev == fashme))
- esp_cmd(esp, eregs, ESP_CMD_ESEL);
+ /* This means real problems if we see this
+ * here. Unless we were actually trying
+ * to force the device to abort/reset.
+ */
+ ESPLOG(("esp%d Disconnect amidst phases, ", esp->esp_id));
+ ESPLOG(("pphase<%s> cphase<%s>, ",
+ phase_string(sp->SCp.phase),
+ phase_string(sp->SCp.sent_command)));
- switch(esp->cur_msgout[0]) {
- default:
- /* We didn't expect this to happen at all. */
- ESPLOG(("device is bolixed\n"));
- esp_advance_phase(SCptr, in_tgterror);
- esp_done(esp, (DID_ERROR << 16));
- break;
+ if(esp->disconnected_SC || (esp->erev == fashme))
+ esp_cmd(esp, eregs, ESP_CMD_ESEL);
- case BUS_DEVICE_RESET:
- ESPLOG(("device reset successful\n"));
- dp->sync_max_offset = 0;
- dp->sync_min_period = 0;
- dp->sync = 0;
- esp_advance_phase(SCptr, in_resetdev);
- esp_done(esp, (DID_RESET << 16));
- break;
+ switch(esp->cur_msgout[0]) {
+ default:
+ /* We didn't expect this to happen at all. */
+ ESPLOG(("device is bolixed\n"));
+ esp_advance_phase(sp, in_tgterror);
+ esp_done(esp, (DID_ERROR << 16));
+ break;
- case ABORT:
- ESPLOG(("device abort successful\n"));
- esp_advance_phase(SCptr, in_abortone);
- esp_done(esp, (DID_ABORT << 16));
- break;
+ case BUS_DEVICE_RESET:
+ ESPLOG(("device reset successful\n"));
+ dp->sync_max_offset = 0;
+ dp->sync_min_period = 0;
+ dp->sync = 0;
+ esp_advance_phase(sp, in_resetdev);
+ esp_done(esp, (DID_RESET << 16));
+ break;
- };
- return do_intr_end;
- }
+ case ABORT:
+ ESPLOG(("device abort successful\n"));
+ esp_advance_phase(sp, in_abortone);
+ esp_done(esp, (DID_ABORT << 16));
+ break;
+
+ };
+ return do_intr_end;
+}
+
+static int esp_enter_msgout(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
+{
+ esp_advance_phase(esp->current_SC, in_msgout);
+ return esp_do_msgout(esp, eregs, dregs);
+}
+
+static int esp_enter_msgin(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
+{
+ esp_advance_phase(esp->current_SC, in_msgin);
+ return esp_do_msgin(esp, eregs, dregs);
+}
+
+static int esp_enter_cmd(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
+{
+ esp_advance_phase(esp->current_SC, in_cmdbegin);
+ return esp_do_cmdbegin(esp, eregs, dregs);
+}
- ESPLOG(("esp%d: to unknown phase\n", esp->esp_id));
- printk("esp%d: Bizarre bus phase %2x.\n", esp->esp_id,
- esp->sreg & ESP_STAT_PMASK);
+static int esp_enter_badphase(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
+{
+ ESPLOG(("esp%d: Bizarre bus phase %2x.\n", esp->esp_id,
+ esp->sreg & ESP_STAT_PMASK));
return do_reset_bus;
}
+typedef int (*espfunc_t)(struct Sparc_ESP *,
+ struct Sparc_ESP_regs *,
+ struct sparc_dma_registers *);
+
+static espfunc_t phase_vector[] = {
+ esp_do_data, /* ESP_DOP */
+ esp_do_data, /* ESP_DIP */
+ esp_enter_cmd, /* ESP_CMDP */
+ esp_enter_status, /* ESP_STATP */
+ esp_enter_badphase, /* ESP_STAT_PMSG */
+ esp_enter_badphase, /* ESP_STAT_PMSG | ESP_STAT_PIO */
+ esp_enter_msgout, /* ESP_MOP */
+ esp_enter_msgin, /* ESP_MIP */
+};
+
+/* The target has control of the bus and we have to see where it has
+ * taken us.
+ */
+static int esp_do_phase_determine(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
+{
+ if ((esp->ireg & ESP_INTR_DC) != 0)
+ return esp_disconnect_amidst_phases(esp, eregs, dregs);
+ return phase_vector[esp->sreg & ESP_STAT_PMASK](esp, eregs, dregs);
+}
+
/* First interrupt after exec'ing a cmd comes here. */
static int esp_select_complete(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
struct sparc_dma_registers *dregs)
@@ -2921,7 +3137,7 @@ static int esp_select_complete(struct Sparc_ESP *esp, struct Sparc_ESP_regs *ere
else
fcnt = (eregs->esp_fflags & ESP_FF_FBYTES);
cmd_bytes_sent = esp_bytes_sent(esp, dregs, fcnt);
- dma_invalidate(dregs, esp->dma->revision);
+ dma_invalidate(esp, dregs, esp->dma->revision);
/* Let's check to see if a reselect happened
* while we we're trying to select. This must
@@ -3094,9 +3310,8 @@ static int esp_select_complete(struct Sparc_ESP *esp, struct Sparc_ESP_regs *ere
SCptr->SCp.phase == in_slct_stop)) {
/* shit */
esp->snip = 0;
- printk("esp%d: Failed synchronous negotiation for target %d "
- "lun %d\n",
- esp->esp_id, SCptr->target, SCptr->lun);
+ ESPLOG(("esp%d: Failed synchronous negotiation for target %d "
+ "lun %d\n", esp->esp_id, SCptr->target, SCptr->lun));
SDptr->sync_max_offset = 0;
SDptr->sync_min_period = 0;
SDptr->sync = 1; /* so we don't negotiate again */
@@ -3123,8 +3338,8 @@ static int esp_select_complete(struct Sparc_ESP *esp, struct Sparc_ESP_regs *ere
* But first make sure that is really what is happening.
*/
if(((1<<SCptr->target) & esp->targets_present)) {
- printk("esp%d: Warning, live target %d not responding to "
- "selection.\n", esp->esp_id, SCptr->target);
+ ESPLOG(("esp%d: Warning, live target %d not responding to "
+ "selection.\n", esp->esp_id, SCptr->target));
/* This _CAN_ happen. The SCSI standard states that
* the target is to _not_ respond to selection if
@@ -3187,15 +3402,15 @@ static int esp_do_msgincont(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
* have miscoded something..... so, try to
* recover as best we can.
*/
- printk("esp%d: message in mis-carriage.\n", esp->esp_id);
+ ESPLOG(("esp%d: message in mis-carriage.\n", esp->esp_id));
}
esp_advance_phase(esp->current_SC, in_the_dark);
return do_phase_determine;
}
-static inline int check_singlebyte_msg(struct Sparc_ESP *esp,
- struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static int check_singlebyte_msg(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
esp->prevmsgin = esp->cur_msgin[0];
if(esp->cur_msgin[0] & 0x80) {
@@ -3224,8 +3439,20 @@ static inline int check_singlebyte_msg(struct Sparc_ESP *esp,
return 0;
case RESTORE_POINTERS:
+ /* In this case we might also have to backup the
+ * "slow command" pointer. It is rare to get such
+ * a save/restore pointer sequence so early in the
+ * bus transition sequences, but cover it.
+ */
+ if(esp->esp_slowcmd) {
+ esp->esp_scmdleft = esp->current_SC->cmd_len;
+ esp->esp_scmdp = &esp->current_SC->cmnd[0];
+ }
+ esp_restore_pointers(esp, esp->current_SC);
+ return 0;
+
case SAVE_POINTERS:
- /* We handle this all automatically. */
+ esp_save_pointers(esp, esp->current_SC);
return 0;
case COMMAND_COMPLETE:
@@ -3260,9 +3487,9 @@ static inline int check_singlebyte_msg(struct Sparc_ESP *esp,
* the SCSI2 standard specifically recommends against targets doing
* this because so many initiators cannot cope with this occuring.
*/
-static inline int target_with_ants_in_pants(struct Sparc_ESP *esp,
- Scsi_Cmnd *SCptr,
- Scsi_Device *SDptr)
+static int target_with_ants_in_pants(struct Sparc_ESP *esp,
+ Scsi_Cmnd *SCptr,
+ Scsi_Device *SDptr)
{
if(SDptr->sync || SDptr->borken) {
/* sorry, no can do */
@@ -3279,7 +3506,7 @@ static inline int target_with_ants_in_pants(struct Sparc_ESP *esp,
return 0;
}
-static inline void sync_report(struct Sparc_ESP *esp)
+static void sync_report(struct Sparc_ESP *esp)
{
int msg3, msg4;
char *type;
@@ -3300,21 +3527,27 @@ static inline void sync_report(struct Sparc_ESP *esp)
} else {
type = "synchronous";
}
- printk(KERN_INFO "esp%d: target %d [period %dns offset %d %d.%02dMHz %s SCSI%s]\n",
- esp->esp_id, esp->current_SC->target,
- (int) msg3 * 4,
- (int) msg4,
- integer, fraction, type,
- (((msg3 * 4) < 200) ? "-II" : ""));
+
+ /* Do not transform this back into one big printk
+ * again, it triggers a bug in our sparc64-gcc272
+ * sibling call optimization. -DaveM
+ */
+ ESPLOG((KERN_INFO "esp%d: target %d ",
+ esp->esp_id, esp->current_SC->target));
+ ESPLOG(("[period %dns offset %d %d.%02dMHz ",
+ (int) msg3 * 4, (int) msg4,
+ integer, fraction));
+ ESPLOG(("%s SCSI%s]\n", type,
+ (((msg3 * 4) < 200) ? "-II" : "")));
} else {
- printk(KERN_INFO "esp%d: target %d asynchronous\n",
- esp->esp_id, esp->current_SC->target);
+ ESPLOG((KERN_INFO "esp%d: target %d asynchronous\n",
+ esp->esp_id, esp->current_SC->target));
}
}
-static inline int check_multibyte_msg(struct Sparc_ESP *esp,
- struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static int check_multibyte_msg(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
Scsi_Device *SDptr = SCptr->device;
@@ -3391,10 +3624,10 @@ static inline int check_multibyte_msg(struct Sparc_ESP *esp,
esp->config3[SCptr->target] |= bit;
else
esp->config3[SCptr->target] &= ~bit;
- eregs->esp_cfg3 = esp->config3[SCptr->target];
+ eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[SCptr->target];
}
- eregs->esp_soff = SDptr->sync_min_period;
- eregs->esp_stp = SDptr->sync_max_offset;
+ eregs->esp_soff = esp->prev_soff = SDptr->sync_min_period;
+ eregs->esp_stp = esp->prev_stp = SDptr->sync_max_offset;
ESPSDTR(("soff=%2x stp=%2x cfg3=%2x\n",
SDptr->sync_max_offset,
@@ -3409,15 +3642,15 @@ static inline int check_multibyte_msg(struct Sparc_ESP *esp,
ESPSDTR(("unaccaptable sync nego, forcing async\n"));
SDptr->sync_max_offset = 0;
SDptr->sync_min_period = 0;
- eregs->esp_soff = 0;
- eregs->esp_stp = 0;
+ eregs->esp_soff = esp->prev_soff = 0;
+ eregs->esp_stp = esp->prev_stp = 0;
if((esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme)) {
if((esp->erev == fas100a) || (esp->erev == fashme))
bit = ESP_CONFIG3_FAST;
else
bit = ESP_CONFIG3_FSCSI;
esp->config3[SCptr->target] &= ~bit;
- eregs->esp_cfg3 = esp->config3[SCptr->target];
+ eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[SCptr->target];
}
}
@@ -3442,32 +3675,30 @@ static inline int check_multibyte_msg(struct Sparc_ESP *esp,
esp->wnip = 0;
if(esp->erev != fashme) {
- printk("esp%d: AIEEE wide msg received and not HME.\n",
- esp->esp_id);
+ ESPLOG(("esp%d: AIEEE wide msg received and not HME.\n",
+ esp->esp_id));
message_out = MESSAGE_REJECT;
} else if(size > 16) {
- printk("esp%d: AIEEE wide transfer for %d size not supported.\n",
- esp->esp_id, size);
+ ESPLOG(("esp%d: AIEEE wide transfer for %d size "
+ "not supported.\n", esp->esp_id, size));
message_out = MESSAGE_REJECT;
} else {
/* Things look good; let's see what we got. */
if(size == 16) {
/* Set config 3 register for this target. */
- printk("esp%d: 16 byte WIDE transfers enabled for target %d.\n",
- esp->esp_id, SCptr->target);
esp->config3[SCptr->target] |= ESP_CONFIG3_EWIDE;
} else {
/* Just make sure it was one byte sized. */
if(size != 8) {
- printk("esp%d: Aieee, wide nego of %d size.\n",
- esp->esp_id, size);
+ ESPLOG(("esp%d: Aieee, wide nego of %d size.\n",
+ esp->esp_id, size));
message_out = MESSAGE_REJECT;
goto finish;
}
/* Pure paranoia. */
esp->config3[SCptr->target] &= ~(ESP_CONFIG3_EWIDE);
}
- eregs->esp_cfg3 = esp->config3[SCptr->target];
+ eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[SCptr->target];
/* Regardless, next try for sync transfers. */
build_sync_nego_msg(esp, esp->sync_defp, 15);
@@ -3597,11 +3828,11 @@ static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
return do_intr_end;
}
-static inline int esp_do_cmddone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static int esp_do_cmddone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
if(esp->erev == fashme)
- dma_invalidate(dregs, dvmahme);
+ dma_invalidate(esp, dregs, dvmahme);
else
esp_cmd(esp, eregs, ESP_CMD_NULL);
if(esp->ireg & ESP_INTR_BSERV) {
@@ -3614,7 +3845,7 @@ static inline int esp_do_cmddone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *e
}
static int esp_do_msgout(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+ struct sparc_dma_registers *dregs)
{
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
switch(esp->msgout_len) {
@@ -3692,8 +3923,8 @@ static int esp_do_msgout(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
return do_intr_end;
}
-static inline int esp_do_msgoutdone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static int esp_do_msgoutdone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
if(esp->msgout_len > 1) {
/* XXX HME/FAS ATN deassert workaround required,
@@ -3704,7 +3935,7 @@ static inline int esp_do_msgoutdone(struct Sparc_ESP *esp, struct Sparc_ESP_regs
while(dregs->cond_reg & DMA_PEND_READ)
udelay(1);
dregs->cond_reg &= ~(DMA_ENABLE);
- dma_invalidate(dregs, esp->dma->revision);
+ dma_invalidate(esp, dregs, esp->dma->revision);
} else {
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
}
@@ -3753,81 +3984,65 @@ static inline int esp_do_msgoutdone(struct Sparc_ESP *esp, struct Sparc_ESP_regs
return esp_do_phase_determine(esp, eregs, dregs);
}
+static int esp_bus_unexpected(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
+{
+ ESPLOG(("esp%d: command in weird state %2x\n",
+ esp->esp_id, esp->current_SC->SCp.phase));
+ return do_reset_bus;
+}
+
+static espfunc_t bus_vector[] = {
+ esp_do_data_finale,
+ esp_do_data_finale,
+ esp_bus_unexpected,
+ esp_do_msgin,
+ esp_do_msgincont,
+ esp_do_msgindone,
+ esp_do_msgout,
+ esp_do_msgoutdone,
+ esp_do_cmdbegin,
+ esp_do_cmddone,
+ esp_do_status,
+ esp_do_freebus,
+ esp_do_phase_determine,
+ esp_bus_unexpected,
+ esp_bus_unexpected,
+ esp_bus_unexpected,
+};
+
/* This is the second tier in our dual-level SCSI state machine. */
-static inline int esp_work_bus(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
- struct sparc_dma_registers *dregs)
+static int esp_work_bus(struct Sparc_ESP *esp,
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
+ unsigned int phase;
ESPBUS(("esp_work_bus: "));
if(!SCptr) {
ESPBUS(("reconnect\n"));
return esp_do_reconnect(esp, eregs, dregs);
}
-
- switch(SCptr->SCp.phase) {
- case in_the_dark:
- ESPBUS(("in the dark\n"));
- return esp_do_phase_determine(esp, eregs, dregs);
-
- case in_slct_norm:
- case in_slct_stop:
- case in_slct_msg:
- case in_slct_tag:
- case in_slct_sneg:
- ESPBUS(("finish selection\n"));
+ phase = SCptr->SCp.phase;
+ if ((phase & 0xf0) == in_phases_mask)
+ return bus_vector[(phase & 0x0f)](esp, eregs, dregs);
+ else if((phase & 0xf0) == in_slct_mask)
return esp_select_complete(esp, eregs, dregs);
-
- case in_datain:
- case in_dataout:
- ESPBUS(("finish data\n"));
- return esp_do_data_finale(esp, eregs, dregs);
-
- case in_msgout:
- ESPBUS(("message out "));
- return esp_do_msgout(esp, eregs, dregs);
-
- case in_msgoutdone:
- ESPBUS(("finish message out "));
- return esp_do_msgoutdone(esp, eregs, dregs);
-
- case in_msgin:
- ESPBUS(("message in "));
- return esp_do_msgin(esp, eregs, dregs);
-
- case in_msgincont:
- ESPBUS(("continue message in "));
- return esp_do_msgincont(esp, eregs, dregs);
-
- case in_msgindone:
- ESPBUS(("finish message in "));
- return esp_do_msgindone(esp, eregs, dregs);
-
- case in_status:
- ESPBUS(("status phase "));
- return esp_do_status(esp, eregs, dregs);
-
- case in_freeing:
- ESPBUS(("freeing the bus "));
- return esp_do_freebus(esp, eregs, dregs);
-
- case in_cmdbegin:
- ESPBUS(("begin slow cmd "));
- return esp_do_cmdbegin(esp, eregs, dregs);
-
- case in_cmdend:
- ESPBUS(("end slow cmd "));
- return esp_do_cmddone(esp, eregs, dregs);
-
- default:
- printk("esp%d: command in weird state %2x\n",
- esp->esp_id, esp->current_SC->SCp.phase);
- return do_reset_bus;
- };
+ else
+ return esp_bus_unexpected(esp, eregs, dregs);
}
+static espfunc_t isvc_vector[] = {
+ 0,
+ esp_do_phase_determine,
+ esp_do_resetbus,
+ esp_finish_reset,
+ esp_work_bus
+};
+
/* Main interrupt handler for an esp adapter. */
-static inline void esp_handle(struct Sparc_ESP *esp)
+static void esp_handle(struct Sparc_ESP *esp)
{
struct sparc_dma_registers *dregs;
struct Sparc_ESP_regs *eregs;
@@ -3872,7 +4087,7 @@ static inline void esp_handle(struct Sparc_ESP *esp)
ESPLOG(("esp%d: No current cmd during gross error, "
"resetting bus\n", esp->esp_id));
what_next = do_reset_bus;
- goto again;
+ goto state_machine;
}
}
@@ -3893,9 +4108,11 @@ static inline void esp_handle(struct Sparc_ESP *esp)
esp_reset_dma(esp);
what_next = do_reset_bus;
- goto again;
+ goto state_machine;
}
+ esp->ireg = eregs->esp_intrpt; /* Unlatch intr and stat regs */
+
if(esp->erev == fashme) {
/* This chip is really losing. */
ESPHME(("HME["));
@@ -3908,17 +4125,12 @@ static inline void esp_handle(struct Sparc_ESP *esp)
if(!(esp->sreg2 & ESP_STAT2_FEMPTY) ||
(esp->sreg2 & ESP_STAT2_F1BYTE)) {
ESPHME(("fifo_workaround]"));
- hme_fifo_hwbug_workaround(esp, eregs);
+ hme_fifo_read(esp, eregs);
} else {
ESPHME(("no_fifo_workaround]"));
}
}
- esp->ireg = eregs->esp_intrpt; /* Unlatch intr and stat regs */
-
- /* This cannot be done until this very moment. -DaveM */
- synchronize_irq();
-
/* No current cmd is only valid at this point when there are
* commands off the bus or we are trying a reset.
*/
@@ -3957,10 +4169,7 @@ static inline void esp_handle(struct Sparc_ESP *esp)
}
what_next = do_reset_bus;
- goto again;
- }
-
- if(!(esp->ireg & ~(ESP_INTR_FDONE | ESP_INTR_BSERV | ESP_INTR_DC))) {
+ } else if(!(esp->ireg & ~(ESP_INTR_FDONE | ESP_INTR_BSERV | ESP_INTR_DC))) {
int phase;
if(SCptr) {
@@ -3972,13 +4181,12 @@ static inline void esp_handle(struct Sparc_ESP *esp)
} else {
ESPLOG(("esp%d: interrupt for no good reason...\n",
esp->esp_id));
- goto esp_handle_done;
+ what_next = do_intr_end;
}
} else {
ESPLOG(("esp%d: BSERV or FDONE or DC while SCptr==NULL\n",
esp->esp_id));
what_next = do_reset_bus;
- goto again;
}
} else if(esp->ireg & ESP_INTR_SR) {
ESPLOG(("esp%d: SCSI bus reset interrupt\n", esp->esp_id));
@@ -3987,7 +4195,6 @@ static inline void esp_handle(struct Sparc_ESP *esp)
ESPLOG(("esp%d: AIEEE we have been selected by another initiator!\n",
esp->esp_id));
what_next = do_reset_bus;
- goto again;
} else if(esp->ireg & ESP_INTR_RSEL) {
if(!SCptr) {
/* This is ok. */
@@ -4002,95 +4209,22 @@ static inline void esp_handle(struct Sparc_ESP *esp)
ESPLOG(("esp%d: Reselected while bus is busy\n",
esp->esp_id));
what_next = do_reset_bus;
- goto again;
}
}
- /* We're trying to fight stack problems, and inline as much as
- * possible without making this driver a mess. hate hate hate
- * This is tier-one in our dual level SCSI state machine.
- */
-again:
- switch(what_next) {
- case do_intr_end:
- goto esp_handle_done;
-
- case do_work_bus:
- what_next = esp_work_bus(esp, eregs, dregs);
- break;
-
- case do_phase_determine:
- what_next = esp_do_phase_determine(esp, eregs, dregs);
- break;
-
- case do_reset_bus:
- ESPLOG(("esp%d: resetting bus...\n", esp->esp_id));
- esp->resetting_bus = 1;
- esp_cmd(esp, eregs, ESP_CMD_RS);
- goto esp_handle_done;
-
- case do_reset_complete:
- /* Tricky, we don't want to cause any more commands to
- * go out until we clear all the live cmds by hand.
- */
- if(esp->current_SC) {
- Scsi_Cmnd *SCptr = esp->current_SC;
- if(!SCptr->use_sg)
- mmu_release_scsi_one(SCptr->SCp.have_data_in,
- SCptr->request_bufflen,
- esp->edev->my_bus);
- else
- mmu_release_scsi_sgl((struct mmu_sglist *)
- SCptr->buffer,
- SCptr->use_sg - 1,
- esp->edev->my_bus);
- SCptr->result = (DID_RESET << 16);
-
- SCptr->scsi_done(SCptr);
- }
- esp->current_SC = NULL;
- if(esp->disconnected_SC) {
- Scsi_Cmnd *SCptr;
- while((SCptr = remove_first_SC(&esp->disconnected_SC))) {
- if(!SCptr->use_sg)
- mmu_release_scsi_one(SCptr->SCp.have_data_in,
- SCptr->request_bufflen,
- esp->edev->my_bus);
- else
- mmu_release_scsi_sgl((struct mmu_sglist *)
- SCptr->buffer,
- SCptr->use_sg - 1,
- esp->edev->my_bus);
- SCptr->result = (DID_RESET << 16);
-
- SCptr->scsi_done(SCptr);
- }
- }
- esp->resetting_bus = 0;
-
- if(esp->current_SC) {
- printk("esp%d: weird weird weird, current_SC not NULL after "
- "SCSI bus reset.\n", esp->esp_id);
- goto esp_handle_done;
+ /* This is tier-one in our dual level SCSI state machine. */
+state_machine:
+ while(what_next != do_intr_end) {
+ if (what_next >= do_phase_determine &&
+ what_next < do_intr_end)
+ what_next = isvc_vector[what_next](esp, eregs, dregs);
+ else {
+ /* state is completely lost ;-( */
+ ESPLOG(("esp%d: interrupt engine loses state, resetting bus\n",
+ esp->esp_id));
+ what_next = do_reset_bus;
}
-
- /* Now it is safe to execute more things. */
- if(esp->issue_SC)
- esp_exec_cmd(esp);
- goto esp_handle_done;
-
- default:
- /* state is completely lost ;-( */
- ESPLOG(("esp%d: interrupt engine loses state, resetting bus\n",
- esp->esp_id));
- what_next = do_reset_bus;
- break;
-
- };
- goto again;
-
-esp_handle_done:
- return;
+ }
}
#ifndef __sparc_v9__
diff --git a/drivers/scsi/esp.h b/drivers/scsi/esp.h
index dcd8d8941..c3e0c50e6 100644
--- a/drivers/scsi/esp.h
+++ b/drivers/scsi/esp.h
@@ -123,10 +123,31 @@ struct Sparc_ESP {
unchar seqreg; /* The ESP sequence register */
unchar sreg2; /* Copy of HME status2 register */
+ /* To save register writes to the ESP, which can be expensive, we
+ * keep track of the previous value that various registers had for
+ * the last target we connected to. If they are the same for the
+ * current target, we skip the register writes as they are not needed.
+ */
+ unchar prev_soff, prev_stp, prev_cfg3, __cache_pad;
+
+ /* We also keep a cache of the previous FAS/HME DMA CSR register value. */
+ unsigned int prev_hme_dmacsr;
+
/* The HME is the biggest piece of shit I have ever seen. */
unchar hme_fifo_workaround_buffer[16 * 2]; /* 16-bit/entry fifo for wide scsi */
unchar hme_fifo_workaround_count;
+ /* For each target we keep track of save/restore data
+ * pointer information. This needs to be updated majorly
+ * when we add support for tagged queueing. -DaveM
+ */
+ struct esp_pointers {
+ char *saved_ptr;
+ struct scatterlist *saved_buffer;
+ int saved_this_residual;
+ int saved_buffers_residual;
+ } data_pointers[16] /*XXX [MAX_TAGS_PER_TARGET]*/;
+
/* Clock periods, frequencies, synchronization, etc. */
unsigned int cfreq; /* Clock frequency in HZ */
unsigned int cfact; /* Clock conversion factor */
@@ -217,7 +238,7 @@ struct Sparc_ESP {
#define ESP_CONFIG3_IDMSG 0x10 /* ID message checking (esp100a/hme) */
#define ESP_CONFIG3_FSCSI 0x10 /* Enable FAST SCSI (esp/fas236) */
#define ESP_CONFIG3_GTM 0x20 /* group2 SCSI2 support (esp/fas236) */
-#define ESP_CONFIG3_BIGID 0x20 /* SCSI-ID's are 4bits (hme) */
+#define ESP_CONFIG3_IDBIT3 0x20 /* Bit 3 of HME SCSI-ID (hme) */
#define ESP_CONFIG3_TBMS 0x40 /* Three-byte msg's ok (esp/fas236) */
#define ESP_CONFIG3_EWIDE 0x40 /* Enable Wide-SCSI (hme) */
#define ESP_CONFIG3_IMS 0x80 /* ID msg chk'ng (esp/fas236) */
diff --git a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c
new file mode 100644
index 000000000..1979e5b36
--- /dev/null
+++ b/drivers/scsi/fcal.c
@@ -0,0 +1,307 @@
+/* fcal.c: Fibre Channel Arbitrated Loop SCSI host adapter driver.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/blk.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+#include <asm/irq.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "../fc4/fcp_impl.h"
+#include "fcal.h"
+
+#include <linux/module.h>
+
+/* #define FCAL_DEBUG */
+
+#define fcal_printk printk ("FCAL %s: ", fc->name); printk
+
+#ifdef FCAL_DEBUG
+#define FCALD(x) fcal_printk x;
+#define FCALND(x) printk ("FCAL: "); printk x;
+#else
+#define FCALD(x)
+#define FCALND(x)
+#endif
+
+static unsigned char alpa2target[] = {
+0x7e, 0x7d, 0x7c, 0xff, 0x7b, 0xff, 0xff, 0xff, 0x7a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79,
+0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x77, 0x76, 0xff, 0xff, 0x75, 0xff, 0x74, 0x73, 0x72,
+0xff, 0xff, 0xff, 0x71, 0xff, 0x70, 0x6f, 0x6e, 0xff, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0xff,
+0xff, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0xff, 0xff, 0x61, 0x60, 0xff, 0x5f, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0x5e, 0xff, 0x5d, 0x5c, 0x5b, 0xff, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0xff,
+0xff, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0xff, 0xff, 0x4e, 0x4d, 0xff, 0x4c, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0x4b, 0xff, 0x4a, 0x49, 0x48, 0xff, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0xff,
+0xff, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0xff, 0xff, 0x3b, 0x3a, 0xff, 0x39, 0xff, 0xff, 0xff,
+0x38, 0x37, 0x36, 0xff, 0x35, 0xff, 0xff, 0xff, 0x34, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33,
+0x32, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0x30, 0xff, 0xff, 0x2f, 0xff, 0x2e, 0x2d, 0x2c,
+0xff, 0xff, 0xff, 0x2b, 0xff, 0x2a, 0x29, 0x28, 0xff, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0xff,
+0xff, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0xff, 0xff, 0x1b, 0x1a, 0xff, 0x19, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0x18, 0xff, 0x17, 0x16, 0x15, 0xff, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0xff,
+0xff, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0xff, 0xff, 0x08, 0x07, 0xff, 0x06, 0xff, 0xff, 0xff,
+0x05, 0x04, 0x03, 0xff, 0x02, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
+};
+
+static unsigned char target2alpa[] = {
+0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
+0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
+0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
+0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
+0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
+0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
+0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
+0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
+};
+
+struct proc_dir_entry proc_scsi_fcal = {
+ PROC_SCSI_FCAL, 4, "fcal",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+
+static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
+
+static void fcal_select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist)
+{
+ Scsi_Device *device;
+
+ for (device = devlist; device; device = device->next) {
+ if (device->host != host) continue;
+ if (device->tagged_supported)
+ device->queue_depth = /* 254 */ 8;
+ else
+ device->queue_depth = 2;
+ }
+}
+
+/* Detect all FC Arbitrated Loops attached to the machine.
+ fc4 module has done all the work for us... */
+__initfunc(int fcal_detect(Scsi_Host_Template *tpnt))
+{
+ int nfcals = 0;
+ fc_channel *fc;
+ int fcalcount;
+ int i;
+
+ tpnt->proc_dir = &proc_scsi_fcal;
+ fcalcount = 0;
+ for_each_online_fc_channel(fc)
+ if (fc->posmap)
+ fcalcount++;
+ FCALND(("%d channels online\n", fcalcount))
+ if (!fcalcount) {
+#if defined(MODULE) && defined(CONFIG_FC4_SOCAL_MODULE) && defined(CONFIG_KMOD)
+ request_module("socal");
+
+ for_each_online_fc_channel(fc)
+ if (fc->posmap)
+ fcalcount++;
+ if (!fcalcount)
+#endif
+ return 0;
+ }
+ for_each_online_fc_channel(fc) {
+ struct Scsi_Host *host;
+ long *ages;
+ struct fcal *fcal;
+
+ if (!fc->posmap) continue;
+
+ /* Strange, this is already registered to some other SCSI host, then it cannot be fcal */
+ if (fc->scsi_name[0]) continue;
+ memcpy (fc->scsi_name, "FCAL", 4);
+
+ fc->can_queue = FCAL_CAN_QUEUE;
+ fc->rsp_size = 64;
+ fc->encode_addr = fcal_encode_addr;
+
+ ages = kmalloc (128 * sizeof(long), GFP_KERNEL);
+ if (!ages) continue;
+
+ host = scsi_register (tpnt, sizeof (struct fcal));
+ if (!host) panic ("Cannot register FCAL host\n");
+
+ nfcals++;
+
+ if (fc->module) __MOD_INC_USE_COUNT(fc->module);
+
+ fcal = (struct fcal *)host->hostdata;
+
+ fc->fcp_register(fc, TYPE_SCSI_FCP, 0);
+
+ for (i = 0; i < fc->posmap->len; i++) {
+ int status, target, alpa;
+
+ alpa = fc->posmap->list[i];
+ FCALD(("Sending PLOGI to %02x\n", alpa))
+ target = alpa2target[alpa];
+ status = fc_do_plogi(fc, alpa, fcal->node_wwn + target,
+ fcal->nport_wwn + target);
+ FCALD(("PLOGI returned with status %d\n", status))
+ if (status != FC_STATUS_OK)
+ continue;
+ FCALD(("Sending PRLI to %02x\n", alpa))
+ status = fc_do_prli(fc, alpa);
+ FCALD(("PRLI returned with status %d\n", status))
+ if (status == FC_STATUS_OK)
+ fcal->map[target] = 1;
+ }
+
+ host->max_id = 127;
+ host->irq = fc->irq;
+#ifdef __sparc_v9__
+ host->unchecked_isa_dma = 1;
+#endif
+ host->select_queue_depths = fcal_select_queue_depths;
+
+ fc->channels = 1;
+ fc->targets = 127;
+ fc->ages = ages;
+ memset (ages, 0, 128 * sizeof(long));
+
+ fcal->fc = fc;
+
+ FCALD(("Found FCAL\n"))
+ }
+ if (nfcals)
+#ifdef __sparc__
+ printk ("FCAL: Total of %d Sun Enterprise Network Array (A5000 or EX500) channels found\n", nfcals);
+#else
+ printk ("FCAL: Total of %d Fibre Channel Arbitrated Loops found\n", nfcals);
+#endif
+ return nfcals;
+}
+
+int fcal_release(struct Scsi_Host *host)
+{
+ struct fcal *fcal = (struct fcal *)host->hostdata;
+ fc_channel *fc = fcal->fc;
+
+ if (fc->module) __MOD_DEC_USE_COUNT(fc->module);
+
+ fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
+ FCALND((" releasing fcal.\n"));
+ kfree (fc->ages);
+ FCALND(("released fcal!\n"));
+ return 0;
+}
+
+#undef SPRINTF
+#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
+
+int fcal_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout)
+{
+ struct Scsi_Host *host = NULL;
+ struct fcal *fcal;
+ fc_channel *fc;
+ char *pos = buffer;
+ int i, j;
+
+ for (host=scsi_hostlist; host; host=host->next)
+ if (host->host_no == hostno)
+ break;
+
+ if (!host) return -ESRCH;
+
+ if (inout) return length;
+
+ fcal = (struct fcal *)host->hostdata;
+ fc = fcal->fc;
+
+#ifdef __sparc__
+ SPRINTF ("Sun Enterprise Network Array (A5000 or E?500) on %s\n", fc->name);
+#else
+ SPRINTF ("Fibre Channel Arbitrated Loop on %s\n", fc->name);
+#endif
+ SPRINTF ("Initiator AL-PA: %02x\n", fc->sid);
+
+ SPRINTF ("\nAttached devices: %s\n", host->host_queue ? "" : "none");
+
+ for (i = 0; i < fc->posmap->len; i++) {
+ unsigned char alpa = fc->posmap->list[i];
+ unsigned char target;
+ u32 *u1, *u2;
+
+ target = alpa2target[alpa];
+ u1 = (u32 *)&fcal->nport_wwn[target];
+ u2 = (u32 *)&fcal->node_wwn[target];
+ if (!u1[0] && !u1[1]) {
+ SPRINTF (" [AL-PA: %02x] Not responded to PLOGI\n", alpa);
+ } else if (!fcal->map[target]) {
+ SPRINTF (" [AL-PA: %02x, Port WWN: %08x%08x, Node WWN: %08x%08x] Not responded to PRLI\n",
+ alpa, u1[0], u1[1], u2[0], u2[1]);
+ } else {
+ Scsi_Device *scd;
+ for (scd = host->host_queue ; scd; scd = scd->next)
+ if (scd->host->host_no == hostno && scd->id == target) {
+ SPRINTF (" [AL-PA: %02x, Id: %02d, Port WWN: %08x%08x, Node WWN: %08x%08x] ",
+ alpa, target, u1[0], u1[1], u2[0], u2[1]);
+ SPRINTF ("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ?
+ scsi_device_types[(short) scd->type] : "Unknown device");
+
+ for (j = 0; (j < 8) && (scd->vendor[j] >= 0x20); j++)
+ SPRINTF ("%c", scd->vendor[j]);
+ SPRINTF (" ");
+
+ for (j = 0; (j < 16) && (scd->model[j] >= 0x20); j++)
+ SPRINTF ("%c", scd->model[j]);
+
+ SPRINTF ("\n");
+ }
+ }
+ }
+ SPRINTF ("\n");
+
+ *start = buffer + offset;
+
+ if ((pos - buffer) < offset)
+ return 0;
+ else if (pos - buffer - offset < length)
+ return pos - buffer - offset;
+ else
+ return length;
+}
+
+/*
+ For FC-AL, we use a simple addressing: we have just one channel 0,
+ and all AL-PAs are mapped to targets 0..0x7e
+ */
+static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd)
+{
+ struct fcal *f;
+
+ /* We don't support LUNs yet - I'm not sure if LUN should be in SCSI fcp_cdb, or in second byte of addr[0] */
+ if (SCpnt->cmnd[1] & 0xe0) return -EINVAL;
+ /* FC-PLDA tells us... */
+ memset(addr, 0, 8);
+ f = (struct fcal *)SCpnt->host->hostdata;
+ if (!f->map[SCpnt->target]) return -EINVAL;
+ /* Now, determine DID: It will be Native Identifier, so we zero upper
+ 2 bytes of the 3 byte DID, lowest byte will be AL-PA */
+ fcmd->did = target2alpa[SCpnt->target];
+ FCALD(("trying DID %06x\n", fcmd->did))
+ return 0;
+}
+
+#ifdef MODULE
+
+Scsi_Host_Template driver_template = FCAL;
+
+#include "scsi_module.c"
+
+EXPORT_NO_SYMBOLS;
+#endif /* MODULE */
diff --git a/drivers/scsi/fcal.h b/drivers/scsi/fcal.h
new file mode 100644
index 000000000..2c8938953
--- /dev/null
+++ b/drivers/scsi/fcal.h
@@ -0,0 +1,46 @@
+/* fcal.h: Generic Fibre Channel Arbitrated Loop SCSI host adapter driver definitions.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#ifndef _FCAL_H
+#define _FCAL_H
+
+#include "../fc4/fcp_impl.h"
+
+struct fcal {
+ /* fc must be first */
+ fc_channel *fc;
+ unsigned char map[128];
+ fc_wwn nport_wwn[128];
+ fc_wwn node_wwn[128];
+};
+
+/* Arbitrary constant. Cannot be too large, as fc4 layer has limitations
+ for a particular channel */
+#define FCAL_CAN_QUEUE 512
+
+int fcal_detect(Scsi_Host_Template *);
+int fcal_release(struct Scsi_Host *);
+int fcal_proc_info (char *, char **, off_t, int, int, int);
+
+#define FCAL { \
+ name: "Fibre Channel Arbitrated Loop",\
+ detect: fcal_detect, \
+ release: fcal_release, \
+ proc_info: fcal_proc_info, \
+ queuecommand: fcp_scsi_queuecommand, \
+ can_queue: FCAL_CAN_QUEUE, \
+ this_id: -1, \
+ sg_tablesize: 1, \
+ cmd_per_lun: 1, \
+ use_clustering: ENABLE_CLUSTERING, \
+ use_new_eh_code: FCP_SCSI_USE_NEW_EH_CODE, \
+ abort: fcp_old_abort, \
+ eh_abort_handler: fcp_scsi_abort, \
+ eh_device_reset_handler:fcp_scsi_dev_reset, \
+ eh_bus_reset_handler: fcp_scsi_bus_reset, \
+ eh_host_reset_handler: fcp_scsi_host_reset, \
+}
+
+#endif /* !(_FCAL_H) */
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 3bc53d5b2..63468443a 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -2,7 +2,7 @@
* GDT ISA/EISA/PCI Disk Array Controller driver for Linux *
* *
* gdth.c *
- * Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner *
+ * Copyright (C) 1995-99 ICP vortex Computersysteme GmbH, Achim Leubner *
* *
* <achim@vortex.de> *
* *
@@ -20,9 +20,34 @@
* along with this kernel; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
- * Tested with Linux 1.2.13, ..., 2.1.131 *
+ * Tested with Linux 1.2.13, ..., 2.2.4 *
* *
* $Log: gdth.c,v $
+ * Revision 1.23 1999/03/26 09:12:31 achim
+ * Default value for hdr_channel set to 0
+ *
+ * Revision 1.22 1999/03/22 16:27:16 achim
+ * Bugfix: gdth_store_event() must not be locked with GDTH_LOCK_HA()
+ *
+ * Revision 1.21 1999/03/16 13:40:34 achim
+ * Problems with reserved drives solved
+ * gdth_eh_bus_reset() implemented
+ *
+ * Revision 1.20 1999/03/10 09:08:13 achim
+ * Bugfix: Corrections in gdth_direction_tab[] made
+ * Bugfix: Increase command timeout (gdth_update_timeout()) NOT in gdth_putq()
+ *
+ * Revision 1.19 1999/03/05 14:38:16 achim
+ * Bugfix: Heads/Sectors mapping for reserved devices possibly wrong
+ * -> gdth_eval_mapping() implemented, changes in gdth_bios_param()
+ * INIT_RETRIES set to 100s to avoid DEINIT-Timeout for controllers
+ * with BIOS disabled and memory test set to Intensive
+ * Enhanced /proc support
+ *
+ * Revision 1.18 1999/02/24 09:54:33 achim
+ * Command line parameter hdr_channel implemented
+ * Bugfix for EISA controllers + Linux 2.2.x
+ *
* Revision 1.17 1998/12/17 15:58:11 achim
* Command line parameters implemented
* Changes for Alpha platforms
@@ -95,7 +120,7 @@
* Initial revision
*
************************************************************************/
-#ident "$Id: gdth.c,v 1.17 1998/12/17 15:58:11 achim Exp $"
+#ident "$Id: gdth.c,v 1.23 1999/03/26 09:12:31 achim Exp $"
/* All GDT Disk Array Controllers are fully supported by this driver.
* This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
@@ -122,9 +147,10 @@
* max_ids:x x - target ID count per channel (1..MAXID)
* rescan:Y rescan all channels/IDs
* rescan:N use all devices found until now
+ * hdr_channel:x x - number of virtual bus for host drives
*
* The default value is: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
- * max_ids:127,rescan:N".
+ * max_ids:127,rescan:N,hdr_channel:0".
* Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y".
*
* When loading the gdth driver as a module, the same options are available.
@@ -134,7 +160,7 @@
* '1' in place of 'Y' and '0' in place of 'N'.
*
* Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0
- * max_ids=127 rescan=0"
+ * max_ids=127 rescan=0 hdr_channel=0"
* The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1".
*/
@@ -179,6 +205,8 @@
#include "gdth.h"
+static void gdth_delay(int milliseconds);
+static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs);
#if LINUX_VERSION_CODE >= 0x010346
static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
#else
@@ -186,7 +214,7 @@ static void gdth_interrupt(int irq,struct pt_regs *regs);
#endif
static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
static int gdth_async_event(int hanum,int service);
-static void gdth_log_event(gdth_evt_data *dvr);
+static void gdth_log_event(gdth_evt_data *dvr, char *buffer);
static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority);
static void gdth_next(int hanum);
@@ -226,6 +254,7 @@ static void gdth_munmap(void *addr);
static const char *gdth_ctr_name(int hanum);
+#if LINUX_VERSION_CODE >= 0x010300
static void gdth_flush(int hanum);
#if LINUX_VERSION_CODE >= 0x020100
static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
@@ -233,6 +262,7 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
static int halt_called = FALSE;
void gdth_halt(void);
#endif
+#endif
#ifdef DEBUG_GDTH
static unchar DebugState = DEBUG_GDTH;
@@ -331,6 +361,7 @@ static struct timer_list gdth_timer;
#define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext)
#define CMDDATA(a) (&((gdth_ext_str *)((a)->hostdata))->cmdext)
+#define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b))
#if LINUX_VERSION_CODE < 0x010300
static void *gdth_mmap(ulong paddr, ulong size)
@@ -429,16 +460,16 @@ static int eoldidx;
static unchar gdth_direction_tab[0x100] = {
DNO,DNO,DIN,DIN,DOU,DIN,DIN,DOU,DIN,DUN,DOU,DOU,DUN,DUN,DUN,DIN,
DNO,DIN,DIN,DOU,DIN,DOU,DNO,DNO,DOU,DNO,DIN,DNO,DIN,DOU,DNO,DUN,
- DIN,DUN,DIN,DUN,DOU,DIN,DUN,DUN,DIN,DIN,DIN,DUN,DUN,DIN,DIN,DIN,
- DIN,DIN,DIN,DNO,DIN,DNO,DNO,DIN,DIN,DIN,DIN,DIN,DIN,DIN,DIN,DIN,
- DIN,DIN,DIN,DIN,DIN,DNO,DUN,DNO,DNO,DNO,DUN,DNO,DIN,DIN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN,
+ DIN,DUN,DIN,DUN,DOU,DIN,DUN,DUN,DIN,DIN,DOU,DNO,DUN,DIN,DOU,DOU,
+ DOU,DOU,DOU,DNO,DIN,DNO,DNO,DIN,DOU,DOU,DOU,DOU,DIN,DOU,DIN,DOU,
+ DOU,DOU,DIN,DIN,DIN,DNO,DUN,DNO,DNO,DNO,DUN,DNO,DOU,DIN,DUN,DUN,
+ DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN,
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DIN,DUN,DNO,DUN,DIN,DIN,
- DIN,DIN,DIN,DNO,DUN,DIN,DIN,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
+ DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DOU,DUN,DNO,DUN,DOU,DOU,
+ DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
@@ -474,25 +505,6 @@ static unchar gdth_direction_tab[0x100] = {
#define GDTH_UNLOCK_SCSI_DOCMD() do {} while (0)
#endif
-/* /proc support */
-#if LINUX_VERSION_CODE >= 0x010300
-#include <linux/stat.h>
-struct proc_dir_entry proc_scsi_gdth = {
- PROC_SCSI_GDTH, 4, "gdth",
- S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-#include "gdth_proc.h"
-#include "gdth_proc.c"
-#endif
-
-#if LINUX_VERSION_CODE >= 0x020100
-/* notifier block to get a notify on system shutdown/halt/reboot */
-static struct notifier_block gdth_notifier = {
- gdth_halt, NULL, 0
-};
-#endif
-
-
/* LILO and modprobe/insmod parameters */
/* IRQ list for GDT3000/3020 EISA controllers */
static int irq[MAXHA] __initdata =
@@ -501,14 +513,16 @@ static int irq[MAXHA] __initdata =
/* disable driver flag */
static int disable __initdata = 0;
/* reserve flag */
-static int reserve_mode __initdata = 1;
+static int reserve_mode = 1;
/* reserve list */
-static int reserve_list[MAX_RES_ARGS] __initdata =
+static int reserve_list[MAX_RES_ARGS] =
{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
/* scan order for PCI controllers */
-static int reverse_scan __initdata = 0;
+static int reverse_scan = 0;
+/* virtual channel for the host drives */
+static int hdr_channel = 0;
/* max. IDs per channel */
static int max_ids = MAXID;
/* rescan all IDs */
@@ -522,12 +536,31 @@ MODULE_PARM(disable, "i");
MODULE_PARM(reserve_mode, "i");
MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i");
MODULE_PARM(reverse_scan, "i");
+MODULE_PARM(hdr_channel, "i");
MODULE_PARM(max_ids, "i");
MODULE_PARM(rescan, "i");
MODULE_AUTHOR("Achim Leubner");
#endif
#endif
+/* /proc support */
+#if LINUX_VERSION_CODE >= 0x010300
+#include <linux/stat.h>
+struct proc_dir_entry proc_scsi_gdth = {
+ PROC_SCSI_GDTH, 4, "gdth",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+#include "gdth_proc.h"
+#include "gdth_proc.c"
+#endif
+
+#if LINUX_VERSION_CODE >= 0x020100
+/* notifier block to get a notify on system shutdown/halt/reboot */
+static struct notifier_block gdth_notifier = {
+ gdth_halt, NULL, 0
+};
+#endif
+
static void gdth_delay(int milliseconds)
{
@@ -544,6 +577,25 @@ static void gdth_delay(int milliseconds)
}
}
+static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs)
+{
+ *cyls = size /HEADS/SECS;
+ if (*cyls <= MAXCYLS) {
+ *heads = HEADS;
+ *secs = SECS;
+ } else { /* too high for 64*32 */
+ *cyls = size /MEDHEADS/MEDSECS;
+ if (*cyls <= MAXCYLS) {
+ *heads = MEDHEADS;
+ *secs = MEDSECS;
+ } else { /* too high for 127*63 */
+ *cyls = size /BIGHEADS/BIGSECS;
+ *heads = BIGHEADS;
+ *secs = BIGSECS;
+ }
+ }
+}
+
/* controller search and initialization functions */
__initfunc (static int gdth_search_eisa(ushort eisa_adr))
@@ -1413,9 +1465,9 @@ static void gdth_release_event(int hanum)
ha->pccb->Service |= 0x80;
if (ha->type == GDT_EISA) {
- outb(ha->pccb->Service, ha->bmic + LDOORREG);
if (ha->pccb->OpCode == GDT_INIT) /* store DMA buffer */
- outl((ulong)ha->pccb, ha->bmic + MAILBOXREG);
+ outl(virt_to_bus(ha->pccb), ha->bmic + MAILBOXREG);
+ outb(ha->pccb->Service, ha->bmic + LDOORREG);
} else if (ha->type == GDT_ISA) {
gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
} else if (ha->type == GDT_PCI) {
@@ -1526,11 +1578,15 @@ __initfunc (static int gdth_search_drives(int hanum))
{
register gdth_ha_str *ha;
ushort cdev_cnt, i;
- ulong32 drv_cyls, drv_hds, drv_secs;
+ int drv_cyls, drv_hds, drv_secs;
ulong32 bus_no;
+ ulong32 drv_cnt, drv_no, j;
gdth_getch_str *chn;
+ gdth_drlist_str *drl;
gdth_iochan_str *ioc;
-
+ gdth_raw_iochan_str *iocr;
+ gdth_arraylist_str *alst;
+
TRACE(("gdth_search_drives() hanum %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
@@ -1565,19 +1621,19 @@ __initfunc (static int gdth_search_drives(int hanum))
cdev_cnt = (ushort)ha->info;
/* detect number of buses - try new IOCTL */
- ioc = (gdth_iochan_str *)ha->pscratch;
- ioc->version = 0xffffffff;
- ioc->list_entries = MAXBUS;
- ioc->first_chan = 0;
- ioc->last_chan = MAXBUS-1;
- ioc->list_offset = GDTOFFSOF(gdth_iochan_str, list[0]);
- if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,GET_IOCHAN_DESC,
- INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
- TRACE2(("GET_IOCHAN_DESC supported!\n"));
- ha->bus_cnt = ioc->chan_count;
+ iocr = (gdth_raw_iochan_str *)ha->pscratch;
+ iocr->hdr.version = 0xffffffff;
+ iocr->hdr.list_entries = MAXBUS;
+ iocr->hdr.first_chan = 0;
+ iocr->hdr.last_chan = MAXBUS-1;
+ iocr->hdr.list_offset = GDTOFFSOF(gdth_raw_iochan_str, list[0]);
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_RAW_DESC,
+ INVALID_CHANNEL,sizeof(gdth_raw_iochan_str))) {
+ TRACE2(("IOCHAN_RAW_DESC supported!\n"));
+ ha->bus_cnt = iocr->hdr.chan_count;
for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
- if (ioc->list[bus_no].proc_id < MAXID)
- ha->bus_id[bus_no] = ioc->list[bus_no].proc_id;
+ if (iocr->list[bus_no].proc_id < MAXID)
+ ha->bus_id[bus_no] = iocr->list[bus_no].proc_id;
else
ha->bus_id[bus_no] = 0xff;
}
@@ -1618,16 +1674,100 @@ __initfunc (static int gdth_search_drives(int hanum))
ha->cpar.version,ha->cpar.state,ha->cpar.strategy,
ha->cpar.write_back,ha->cpar.block_size));
- /* read board info, fill ctr_name[] */
+ /* read board info and features */
+ ha->more_proc = FALSE;
if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO,
INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
- TRACE2(("BOARD_INFO supported!\n"));
- strcpy(ha->ctr_name, ((gdth_binfo_str *)ha->pscratch)->type_string);
+ ha->binfo = *(gdth_binfo_str *)ha->pscratch;
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_FEATURES,
+ INVALID_CHANNEL,sizeof(gdth_bfeat_str))) {
+ TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n"));
+ ha->bfeat = *(gdth_bfeat_str *)ha->pscratch;
+ ha->more_proc = TRUE;
+ }
} else {
- strcpy(ha->ctr_name, gdth_ctr_name(hanum));
- }
- TRACE2(("Controller name: %s\n",ha->ctr_name));
+ TRACE2(("BOARD_INFO requires firmware >= 1.10/2.08\n"));
+ strcpy(ha->binfo.type_string, gdth_ctr_name(hanum));
+ }
+ TRACE2(("Controller name: %s\n",ha->binfo.type_string));
+
+ /* read more informations */
+ if (ha->more_proc) {
+ /* physical drives, channel addresses */
+ ioc = (gdth_iochan_str *)ha->pscratch;
+ ioc->hdr.version = 0xffffffff;
+ ioc->hdr.list_entries = MAXBUS;
+ ioc->hdr.first_chan = 0;
+ ioc->hdr.last_chan = MAXBUS-1;
+ ioc->hdr.list_offset = GDTOFFSOF(gdth_iochan_str, list[0]);
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_DESC,
+ INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
+ for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
+ ha->raw[bus_no].address = ioc->list[bus_no].address;
+ ha->raw[bus_no].local_no = ioc->list[bus_no].local_no;
+ }
+ } else {
+ for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
+ ha->raw[bus_no].address = IO_CHANNEL;
+ ha->raw[bus_no].local_no = bus_no;
+ }
+ }
+ for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
+ chn = (gdth_getch_str *)ha->pscratch;
+ chn->channel_no = ha->raw[bus_no].local_no;
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+ SCSI_CHAN_CNT | L_CTRL_PATTERN,
+ ha->raw[bus_no].address | INVALID_CHANNEL,
+ sizeof(gdth_getch_str))) {
+ ha->raw[bus_no].pdev_cnt = chn->drive_cnt;
+ TRACE2(("Channel %d: %d phys. drives\n",
+ bus_no,chn->drive_cnt));
+ }
+ if (ha->raw[bus_no].pdev_cnt > 0) {
+ drl = (gdth_drlist_str *)ha->pscratch;
+ drl->sc_no = ha->raw[bus_no].local_no;
+ drl->sc_cnt = ha->raw[bus_no].pdev_cnt;
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+ SCSI_DR_LIST | L_CTRL_PATTERN,
+ ha->raw[bus_no].address | INVALID_CHANNEL,
+ sizeof(gdth_drlist_str))) {
+ for (j = 0; j < ha->raw[bus_no].pdev_cnt; ++j)
+ ha->raw[bus_no].id_list[j] = drl->sc_list[j];
+ } else {
+ ha->raw[bus_no].pdev_cnt = 0;
+ }
+ }
+ }
+ /* logical drives */
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_CNT,
+ INVALID_CHANNEL,sizeof(ulong32))) {
+ drv_cnt = *(ulong32 *)ha->pscratch;
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_LIST,
+ INVALID_CHANNEL,drv_cnt * sizeof(ulong32))) {
+ for (j = 0; j < drv_cnt; ++j) {
+ drv_no = ((ulong32 *)ha->pscratch)[j];
+ if (drv_no < MAX_HDRIVES) {
+ ha->hdr[drv_no].is_logdrv = TRUE;
+ TRACE2(("Drive %d is log. drive\n",drv_no));
+ }
+ }
+ }
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+ ARRAY_DRV_LIST | LA_CTRL_PATTERN,
+ 0, 35 * sizeof(gdth_arraylist_str))) {
+ for (j = 0; j < 35; ++j) {
+ alst = &((gdth_arraylist_str *)ha->pscratch)[j];
+ ha->hdr[j].is_arraydrv = alst->is_arrayd;
+ ha->hdr[j].is_master = alst->is_master;
+ ha->hdr[j].is_parity = alst->is_parity;
+ ha->hdr[j].is_hotfix = alst->is_hotfix;
+ ha->hdr[j].master_no = alst->cd_handle;
+ }
+ }
+ }
+ }
+
/* initialize raw service */
if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) {
printk("GDT: Initialization error raw service (code %d)\n",
@@ -1695,21 +1835,7 @@ __initfunc (static int gdth_search_drives(int hanum))
/* evaluate mapping (sectors per head, heads per cylinder) */
ha->hdr[i].size &= ~SECS32;
if (ha->info2 == 0) {
- drv_cyls = ha->hdr[i].size /HEADS/SECS;
- if (drv_cyls <= MAXCYLS) {
- drv_hds = HEADS;
- drv_secs= SECS;
- } else { /* too high for 64*32 */
- drv_cyls = ha->hdr[i].size /MEDHEADS/MEDSECS;
- if (drv_cyls <= MAXCYLS) {
- drv_hds = MEDHEADS;
- drv_secs= MEDSECS;
- } else { /* too high for 127*63 */
- drv_cyls = ha->hdr[i].size /BIGHEADS/BIGSECS;
- drv_hds = BIGHEADS;
- drv_secs= BIGSECS;
- }
- }
+ gdth_eval_mapping(ha->hdr[i].size,&drv_cyls,&drv_hds,&drv_secs);
} else {
drv_hds = ha->info2 & 0xff;
drv_secs = (ha->info2 >> 8) & 0xff;
@@ -1752,7 +1878,6 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
GDTH_LOCK_HA(ha, flags);
scp->SCp.this_residual = (int)priority;
- gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
#if LINUX_VERSION_CODE >= 0x020000
b = scp->channel;
#else
@@ -1761,8 +1886,8 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
t = scp->target;
#if LINUX_VERSION_CODE >= 0x010300
if (priority >= DEFAULT_PRI) {
- if ((b < ha->bus_cnt && ha->raw[b].lock) ||
- (b == ha->bus_cnt && ha->hdr[t].lock)) {
+ if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
+ (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
}
@@ -1825,8 +1950,8 @@ static void gdth_next(int hanum)
#endif
t = nscp->target;
if (nscp->SCp.this_residual >= DEFAULT_PRI) {
- if ((b < ha->bus_cnt && ha->raw[b].lock) ||
- (b == ha->bus_cnt && ha->hdr[t].lock))
+ if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
+ (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
continue;
}
@@ -1843,22 +1968,24 @@ static void gdth_next(int hanum)
firsttime = FALSE;
}
+#if LINUX_VERSION_CODE >= 0x010300
+ if (nscp->done != gdth_scsi_done)
+#endif
+ {
if (nscp->SCp.phase == -1) {
nscp->SCp.phase = SCSIRAWSERVICE; /* default: raw svc. */
if (nscp->cmnd[0] == TEST_UNIT_READY) {
- TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
- nscp->channel, nscp->target, nscp->lun));
+ TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
+ b, t, nscp->lun));
/* TEST_UNIT_READY -> set scan mode */
if ((ha->scan_mode & 0x0f) == 0) {
- if (nscp->channel == 0 && nscp->target == 0 &&
- nscp->lun == 0) {
+ if (b == 0 && t == 0 && nscp->lun == 0) {
ha->scan_mode |= 1;
TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
}
} else if ((ha->scan_mode & 0x0f) == 1) {
- if (nscp->channel == 0 &&
- ((nscp->target == 0 && nscp->lun == 1) ||
- (nscp->target == 1 && nscp->lun == 0))) {
+ if (b == 0 && ((t == 0 && nscp->lun == 1) ||
+ (t == 1 && nscp->lun == 0))) {
nscp->SCp.Status = GDT_SCAN_START;
nscp->SCp.phase |= ((ha->scan_mode & 0x10 ? 1:0) << 8);
ha->scan_mode = 0x12;
@@ -1869,7 +1996,7 @@ static void gdth_next(int hanum)
TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
}
} else if (ha->scan_mode == 0x12) {
- if (b == ha->bus_cnt) {
+ if (b == ha->bus_cnt && t == ha->tid_cnt-1) {
nscp->SCp.Status = GDT_SCAN_END;
ha->scan_mode &= 0x10;
TRACE2(("Scan mode: 0x%x (SCAN_END)\n",
@@ -1878,10 +2005,12 @@ static void gdth_next(int hanum)
}
}
}
+ }
if (nscp->SCp.Status != -1) {
if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) {
- cmd_index=gdth_fill_raw_cmd(hanum,nscp,b);
+ if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
+ this_cmd = FALSE;
next_cmd = FALSE;
}
} else
@@ -1893,13 +2022,15 @@ static void gdth_next(int hanum)
next_cmd = FALSE;
} else
#endif
- if (b < ha->bus_cnt) {
- if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,b))) {
+ if (b != ha->virt_bus) {
+ if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW ||
+ !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
this_cmd = FALSE;
- }
- } else if (!ha->hdr[nscp->target].present || nscp->lun != 0) {
+ else
+ ha->raw[BUS_L2P(ha,b)].io_cnt[t]++;
+ } else if (t >= MAX_HDRIVES || !ha->hdr[t].present || nscp->lun != 0) {
TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
- nscp->cmnd[0], b, nscp->target, nscp->lun));
+ nscp->cmnd[0], b, t, nscp->lun));
nscp->result = DID_BAD_TARGET << 16;
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
@@ -2405,14 +2536,13 @@ static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
ushort idx, gdth_evt_data *evt)
{
gdth_evt_str *e;
- ulong flags;
struct timeval tv;
+ /* no GDTH_LOCK_HA() ! */
TRACE2(("gdth_store_event() source %d idx %d\n", source, idx));
if (source == 0) /* no source -> no event */
return 0;
- GDTH_LOCK_HA(ha, flags);
if (ebuffer[elastidx].event_source == source &&
ebuffer[elastidx].event_idx == idx &&
!memcmp((char *)&ebuffer[elastidx].event_data.eu,
@@ -2440,7 +2570,6 @@ static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
e->same_count = 1;
e->event_data = *evt;
}
- GDTH_UNLOCK_HA(ha, flags);
return e;
}
@@ -2808,9 +2937,12 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
printk("\n");
} else {
- scp->SCp.Message = (int)ha->status;
+ if (scp->SCp.Status == -1 && scp->channel != ha->virt_bus) {
+ ha->raw[BUS_L2P(ha,scp->channel)].io_cnt[scp->target]--;
+ }
/* cache or raw service */
if (ha->status == S_OK) {
+ scp->SCp.Message = S_OK;
if (scp->SCp.Status != -1) {
TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n",
scp->SCp.Status));
@@ -2821,8 +2953,10 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
scp->result = DID_OK << 16;
} else if (ha->status == S_BSY) {
TRACE2(("Controller busy -> retry !\n"));
+ scp->SCp.Message = S_BSY;
return 2;
} else {
+ scp->SCp.Message = (int)((ha->info<<16)|ha->status);
if (scp->SCp.Status != -1) {
TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n",
scp->SCp.Status, ha->status));
@@ -2836,7 +2970,10 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
scp->sense_buffer[2] = NOT_READY;
scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
- if (scp->done != gdth_scsi_done) {
+#if LINUX_VERSION_CODE >= 0x010300
+ if (scp->done != gdth_scsi_done)
+#endif
+ {
dvr.size = sizeof(dvr.eu.sync);
dvr.eu.sync.ionode = hanum;
dvr.eu.sync.service = service;
@@ -2904,7 +3041,7 @@ static char *async_cache_tab[] = {
"GDT HA %u, Array Drive %u: parity build failed",
/*18*/ "\005\000\002\006\002"
"GDT HA %u, Array Drive %u: drive rebuild failed",
-/*19*/ "\007\000\002\010\002"
+/*19*/ "\005\000\002\010\002"
"GDT HA %u, Test of Hot Fix %u failed",
/*20*/ "\005\000\002\006\002"
"GDT HA %u, Array Drive %u: drive build finished successfully",
@@ -3066,12 +3203,12 @@ static int gdth_async_event(int hanum,int service)
dvr.eu.async.info = ha->info;
*(ulong32 *)dvr.eu.async.scsi_coord = ha->info2;
gdth_store_event(ha, ES_ASYNC, service, &dvr);
- gdth_log_event( &dvr );
+ gdth_log_event( &dvr, NULL );
}
return 1;
}
-static void gdth_log_event(gdth_evt_data *dvr)
+static void gdth_log_event(gdth_evt_data *dvr, char *buffer)
{
gdth_stackframe stack;
char *f = NULL;
@@ -3101,12 +3238,22 @@ static void gdth_log_event(gdth_evt_data *dvr)
break;
}
}
-
- printk(&f[(int)f[0]],stack); printk("\n");
+
+ if (buffer == NULL) {
+ printk(&f[(int)f[0]],stack);
+ printk("\n");
+ } else {
+ sprintf(buffer,&f[(int)f[0]],stack);
+ }
} else {
- printk("GDT: Unknown async. event service %d event no. %d\n",
- dvr->eu.async.service,dvr->eu.async.status);
+ if (buffer == NULL) {
+ printk("GDT HA %u, Unknown async. event service %d event no. %d\n",
+ dvr->eu.async.ionode,dvr->eu.async.service,dvr->eu.async.status);
+ } else {
+ sprintf(buffer,"GDT HA %u, Unknown async. event service %d event no. %d",
+ dvr->eu.async.ionode,dvr->eu.async.service,dvr->eu.async.status);
+ }
}
}
@@ -3249,6 +3396,9 @@ __initfunc (int gdth_detect(Scsi_Host_Template *shtp))
scsi_unregister(shp);
continue;
}
+ if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
+ hdr_channel = ha->bus_cnt;
+ ha->virt_bus = hdr_channel;
#if LINUX_VERSION_CODE >= 0x020000
shp->max_id = ha->tid_cnt;
@@ -3333,6 +3483,9 @@ __initfunc (int gdth_detect(Scsi_Host_Template *shtp))
scsi_unregister(shp);
continue;
}
+ if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
+ hdr_channel = ha->bus_cnt;
+ ha->virt_bus = hdr_channel;
#if LINUX_VERSION_CODE >= 0x020000
shp->max_id = ha->tid_cnt;
@@ -3429,6 +3582,9 @@ __initfunc (int gdth_detect(Scsi_Host_Template *shtp))
scsi_unregister(shp);
continue;
}
+ if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
+ hdr_channel = ha->bus_cnt;
+ ha->virt_bus = hdr_channel;
#if LINUX_VERSION_CODE >= 0x020000
shp->max_id = ha->tid_cnt;
@@ -3479,7 +3635,9 @@ int gdth_release(struct Scsi_Host *shp)
if (NUMDATA(shp)->busnum == 0) {
hanum = NUMDATA(shp)->hanum;
ha = HADATA(gdth_ctr_tab[hanum]);
+#if LINUX_VERSION_CODE >= 0x010300
gdth_flush(hanum);
+#endif
if (shp->irq) {
#if LINUX_VERSION_CODE >= 0x010346
@@ -3552,7 +3710,7 @@ const char *gdth_info(struct Scsi_Host *shp)
hanum = NUMDATA(shp)->hanum;
ha = HADATA(gdth_ctr_tab[hanum]);
- return ((const char *)ha->ctr_name);
+ return ((const char *)ha->binfo.type_string);
}
/* old error handling */
@@ -3588,8 +3746,33 @@ int gdth_eh_device_reset(Scsi_Cmnd *scp)
int gdth_eh_bus_reset(Scsi_Cmnd *scp)
{
+ int i, hanum;
+ gdth_ha_str *ha;
+ ulong flags;
+ Scsi_Cmnd *cmnd;
+
TRACE2(("gdth_eh_bus_reset()\n"));
- return FAILED;
+ hanum = NUMDATA(scp->host)->hanum;
+ ha = HADATA(gdth_ctr_tab[hanum]);
+ if (scp->channel == ha->virt_bus)
+ return FAILED;
+
+ GDTH_LOCK_HA(ha, flags);
+ for (i = 0; i < MAXID; ++i)
+ ha->raw[BUS_L2P(ha,scp->channel)].io_cnt[i] = 0;
+ for (i = 0; i < GDTH_MAXCMDS; ++i) {
+ cmnd = ha->cmd_tab[i].cmnd;
+ if (!SPECIAL_SCP(cmnd) && cmnd->channel == scp->channel)
+ ha->cmd_tab[i].cmnd = UNUSED_CMND;
+ }
+ gdth_polling = TRUE;
+ while (gdth_test_busy(hanum))
+ gdth_delay(0);
+ gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS,
+ BUS_L2P(ha,scp->channel), 0, 0);
+ gdth_polling = FALSE;
+ GDTH_UNLOCK_HA(ha, flags);
+ return SUCCESS;
}
int gdth_eh_host_reset(Scsi_Cmnd *scp)
@@ -3608,7 +3791,6 @@ int gdth_bios_param(Disk *disk,int dev,int *ip)
unchar t;
int hanum;
gdth_ha_str *ha;
- int drv_hds, drv_secs;
hanum = NUMDATA(disk->device->host)->hanum;
t = disk->device->id;
@@ -3616,27 +3798,16 @@ int gdth_bios_param(Disk *disk,int dev,int *ip)
hanum, disk->device->channel, t));
ha = HADATA(gdth_ctr_tab[hanum]);
- if (ha->hdr[t].heads == 0) {
- /* raw device: evaluate mapping (sectors per head, heads per cylinder) */
- if (disk->capacity /HEADS/SECS <= MAXCYLS) {
- drv_hds = HEADS;
- drv_secs= SECS;
- } else if (disk->capacity /MEDHEADS/MEDSECS <= MAXCYLS) {
- drv_hds = MEDHEADS;
- drv_secs= MEDSECS;
- } else {
- drv_hds = BIGHEADS;
- drv_secs= BIGSECS;
- }
- ha->hdr[t].heads = drv_hds;
- ha->hdr[t].secs = drv_secs;
- TRACE2(("gdth_bios_param(): raw device -> params evaluated\n"));
+ if (disk->device->channel != ha->virt_bus || ha->hdr[t].heads == 0) {
+ /* raw device or host drive without mapping information */
+ TRACE2(("Evaluate mapping\n"));
+ gdth_eval_mapping(disk->capacity,&ip[2],&ip[0],&ip[1]);
+ } else {
+ ip[0] = ha->hdr[t].heads;
+ ip[1] = ha->hdr[t].secs;
+ ip[2] = disk->capacity / ip[0] / ip[1];
}
- ip[0] = ha->hdr[t].heads;
- ip[1] = ha->hdr[t].secs;
- ip[2] = disk->capacity / ip[0] / ip[1];
-
TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
ip[0],ip[1],ip[2]));
return 0;
@@ -3683,11 +3854,13 @@ int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
if (scp->done == gdth_scsi_done)
priority = scp->SCp.this_residual;
#endif
+ gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
gdth_putq( hanum, scp, priority );
gdth_next( hanum );
return 0;
}
+#if LINUX_VERSION_CODE >= 0x010300
/* flush routine */
static void gdth_flush(int hanum)
{
@@ -3696,7 +3869,6 @@ static void gdth_flush(int hanum)
Scsi_Cmnd scp;
Scsi_Device sdev;
gdth_cmd_str gdtcmd;
- char cmnd[12];
TRACE2(("gdth_flush() hanum %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
@@ -3719,18 +3891,7 @@ static void gdth_flush(int hanum)
gdtcmd.u.cache.BlockNo = 1;
gdtcmd.u.cache.sg_canz = 0;
TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scp.SCp.this_residual = IOCTL_PRI;
- GDTH_LOCK_SCSI_DOCMD();
- scsi_do_cmd(&scp, cmnd, &gdtcmd,
- sizeof(gdth_cmd_str), gdth_scsi_done,
- 30*HZ, 1);
- GDTH_UNLOCK_SCSI_DOCMD();
- down(&sem);
- }
+ gdth_do_cmd(&scp, &gdtcmd, 30);
}
}
}
@@ -3747,7 +3908,6 @@ void gdth_halt(void)
Scsi_Cmnd scp;
Scsi_Device sdev;
gdth_cmd_str gdtcmd;
- char cmnd[12];
#endif
#if LINUX_VERSION_CODE >= 0x020100
@@ -3782,18 +3942,7 @@ void gdth_halt(void)
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_RESET;
TRACE2(("gdth_halt(): reset controller %d\n", hanum));
- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scp.SCp.this_residual = IOCTL_PRI;
- GDTH_LOCK_SCSI_DOCMD();
- scsi_do_cmd(&scp, cmnd, &gdtcmd,
- sizeof(gdth_cmd_str), gdth_scsi_done,
- 10*HZ, 1);
- GDTH_UNLOCK_SCSI_DOCMD();
- down(&sem);
- }
+ gdth_do_cmd(&scp, &gdtcmd, 10);
#endif
}
printk("Done.\n");
@@ -3806,6 +3955,7 @@ void gdth_halt(void)
return NOTIFY_OK;
#endif
}
+#endif
/* called from init/main.c */
@@ -3846,6 +3996,8 @@ __initfunc (void gdth_setup(char *str,int *ints))
reserve_mode = val;
else if (!strncmp(argv, "reverse_scan:", 13))
reverse_scan = val;
+ else if (!strncmp(argv, "hdr_channel:", 12))
+ hdr_channel = val;
else if (!strncmp(argv, "max_ids:", 8))
max_ids = val;
else if (!strncmp(argv, "rescan:", 7))
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
index 93db2e540..340adf5ae 100644
--- a/drivers/scsi/gdth.h
+++ b/drivers/scsi/gdth.h
@@ -4,13 +4,13 @@
/*
* Header file for the GDT ISA/EISA/PCI Disk Array Controller driver for Linux
*
- * gdth.h Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner
+ * gdth.h Copyright (C) 1995-99 ICP vortex Computersysteme GmbH, Achim Leubner
* See gdth.c for further informations and
* below for supported controller types
*
* <achim@vortex.de>
*
- * $Id: gdth.h,v 1.16 1998/12/17 15:54:53 achim Exp $
+ * $Id: gdth.h,v 1.21 1999/03/26 09:12:24 achim Exp $
*/
#include <linux/version.h>
@@ -29,9 +29,9 @@
/* defines, macros */
/* driver version */
-#define GDTH_VERSION_STR "1.10"
+#define GDTH_VERSION_STR "1.14"
#define GDTH_VERSION 1
-#define GDTH_SUBVERSION 10
+#define GDTH_SUBVERSION 14
/* protocol version */
#define PROTOCOL_VERSION 1
@@ -129,6 +129,7 @@
#define GDTH_SCRATCH 4096 /* 4KB scratch buffer */
#define GDTH_MAXCMDS 124
#define GDTH_MAXC_P_L 16 /* max. cmds per lun */
+#define GDTH_MAX_RAW 2 /* max. cmds per raw device */
#define MAXOFFSETS 128
#define MAXHA 16
#define MAXID 127
@@ -199,14 +200,27 @@
#define GDT_SCAN_END 20 /* stop device scan */
/* IOCTL command defines */
-#define SCSI_CHAN_CNT 5 /* subfunctions */
-#define GET_IOCHAN_DESC 0x5e
-#define L_CTRL_PATTERN 0x20000000L
-#define CACHE_INFO 4
-#define CACHE_CONFIG 5
-#define BOARD_INFO 0x28
-#define IO_CHANNEL 0x00020000L /* channels */
-#define INVALID_CHANNEL 0x0000ffffL
+#define SCSI_DR_INFO 0x00 /* SCSI drive info */
+#define SCSI_CHAN_CNT 0x05 /* SCSI channel count */
+#define SCSI_DR_LIST 0x06 /* SCSI drive list */
+#define SCSI_DEF_CNT 0x15 /* grown/primary defects */
+#define DSK_STATISTICS 0x4b /* SCSI disk statistics */
+#define IOCHAN_DESC 0x5d /* description of IO channel */
+#define IOCHAN_RAW_DESC 0x5e /* description of raw IO channel */
+#define L_CTRL_PATTERN 0x20000000L /* SCSI IOCTL mask */
+#define ARRAY_INFO 0x12 /* array drive info */
+#define ARRAY_DRV_LIST 0x0f /* array drive list */
+#define LA_CTRL_PATTERN 0x10000000L /* array IOCTL mask */
+#define CACHE_DRV_CNT 0x01 /* cache drive count */
+#define CACHE_DRV_LIST 0x02 /* cache drive list */
+#define CACHE_INFO 0x04 /* cache info */
+#define CACHE_CONFIG 0x05 /* cache configuration */
+#define CACHE_DRV_INFO 0x07 /* cache drive info */
+#define BOARD_FEATURES 0x15 /* controller features */
+#define BOARD_INFO 0x28 /* controller info */
+#define HOST_GET 0x10001L /* get host drive list */
+#define IO_CHANNEL 0x00020000L /* default IO channel */
+#define INVALID_CHANNEL 0x0000ffffL /* invalid channel */
/* IOCTLs */
#define GDTIOCTL_MASK ('J'<<8)
@@ -225,8 +239,8 @@
#define S_RAW_ILL 0xff /* raw serv.: illegal */
/* timeout values */
-#define INIT_RETRIES 10000 /* 10000 * 1ms = 10s */
-#define INIT_TIMEOUT 100000 /* 1000 * 1ms = 1s */
+#define INIT_RETRIES 100000 /* 100000 * 1ms = 100s */
+#define INIT_TIMEOUT 100000 /* 100000 * 1ms = 100s */
#define POLL_TIMEOUT 10000 /* 10000 * 1ms = 10s */
/* priorities */
@@ -276,29 +290,171 @@ typedef struct {
char msg_text[MSGLEN+2]; /* the message text */
} PACKED gdth_msg_str;
-/* get channel count IOCTL */
+/* IOCTL data structures */
+/* SCSI drive info */
+typedef struct {
+ unchar vendor[8]; /* vendor string */
+ unchar product[16]; /* product string */
+ unchar revision[4]; /* revision */
+ ulong32 sy_rate; /* current rate for sync. tr. */
+ ulong32 sy_max_rate; /* max. rate for sync. tr. */
+ ulong32 no_ldrive; /* belongs to this logical drv.*/
+ ulong32 blkcnt; /* number of blocks */
+ ushort blksize; /* size of block in bytes */
+ unchar available; /* flag: access is available */
+ unchar init; /* medium is initialized */
+ unchar devtype; /* SCSI devicetype */
+ unchar rm_medium; /* medium is removable */
+ unchar wp_medium; /* medium is write protected */
+ unchar ansi; /* SCSI I/II or III? */
+ unchar protocol; /* same as ansi */
+ unchar sync; /* flag: sync. transfer enab. */
+ unchar disc; /* flag: disconnect enabled */
+ unchar queueing; /* flag: command queing enab. */
+ unchar cached; /* flag: caching enabled */
+ unchar target_id; /* target ID of device */
+ unchar lun; /* LUN id of device */
+ unchar orphan; /* flag: drive fragment */
+ ulong32 last_error; /* sense key or drive state */
+ ulong32 last_result; /* result of last command */
+ ulong32 check_errors; /* err. in last surface check */
+ unchar percent; /* progress for surface check */
+ unchar last_check; /* IOCTRL operation */
+ unchar res[2];
+ ulong32 flags; /* from 1.19/2.19: raw reserv.*/
+ unchar multi_bus; /* multi bus dev? (fibre ch.) */
+ unchar mb_status; /* status: available? */
+ unchar res2[2];
+ unchar mb_alt_status; /* status on second bus */
+ unchar mb_alt_bid; /* number of second bus */
+ unchar mb_alt_tid; /* target id on second bus */
+ unchar res3;
+ unchar fc_flag; /* from 1.22/2.22: info valid?*/
+ unchar res4;
+ ushort fc_frame_size; /* frame size (bytes) */
+ char wwn[8]; /* world wide name */
+} PACKED gdth_diskinfo_str;
+
+/* get SCSI channel count */
typedef struct {
ulong32 channel_no; /* number of channel */
- ulong32 drive_cnt; /* number of drives */
+ ulong32 drive_cnt; /* drive count */
unchar siop_id; /* SCSI processor ID */
unchar siop_state; /* SCSI processor state */
} PACKED gdth_getch_str;
-/* get raw channel count IOCTL (NEW!) */
+/* get SCSI drive numbers */
+typedef struct {
+ ulong32 sc_no; /* SCSI channel */
+ ulong32 sc_cnt; /* sc_list[] elements */
+ ulong32 sc_list[MAXID]; /* minor device numbers */
+} PACKED gdth_drlist_str;
+
+/* get grown/primary defect count */
+typedef struct {
+ unchar sddc_type; /* 0x08: grown, 0x10: prim. */
+ unchar sddc_format; /* list entry format */
+ unchar sddc_len; /* list entry length */
+ unchar sddc_res;
+ ulong32 sddc_cnt; /* entry count */
+} PACKED gdth_defcnt_str;
+
+/* disk statistics */
typedef struct {
- ulong32 version; /* version of information (-1UL: newest) */
- unchar list_entries; /* list entry count */
- unchar first_chan; /* first channel number */
- unchar last_chan; /* last channel number */
- unchar chan_count; /* (R) channel count */
- ulong32 list_offset; /* offset of list[0] */
+ ulong32 bid; /* SCSI channel */
+ ulong32 first; /* first SCSI disk */
+ ulong32 entries; /* number of elements */
+ ulong32 count; /* (R) number of init. el. */
+ ulong32 mon_time; /* time stamp */
struct {
- unchar proc_id; /* processor id */
- unchar proc_defect; /* defect ? */
- unchar reserved[2];
+ unchar tid; /* target ID */
+ unchar lun; /* LUN */
+ unchar res[2];
+ ulong32 blk_size; /* block size in bytes */
+ ulong32 rd_count; /* bytes read */
+ ulong32 wr_count; /* bytes written */
+ ulong32 rd_blk_count; /* blocks read */
+ ulong32 wr_blk_count; /* blocks written */
+ ulong32 retries; /* retries */
+ ulong32 reassigns; /* reassigns */
+ } PACKED list[1];
+} PACKED gdth_dskstat_str;
+
+/* IO channel header */
+typedef struct {
+ ulong32 version; /* version (-1UL: newest) */
+ unchar list_entries; /* list entry count */
+ unchar first_chan; /* first channel number */
+ unchar last_chan; /* last channel number */
+ unchar chan_count; /* (R) channel count */
+ ulong32 list_offset; /* offset of list[0] */
+} PACKED gdth_iochan_header;
+
+/* get IO channel description */
+typedef struct {
+ gdth_iochan_header hdr;
+ struct {
+ ulong32 address; /* channel address */
+ unchar type; /* type (SCSI, FCAL) */
+ unchar local_no; /* local number */
+ ushort features; /* channel features */
} PACKED list[MAXBUS];
} PACKED gdth_iochan_str;
+/* get raw IO channel description */
+typedef struct {
+ gdth_iochan_header hdr;
+ struct {
+ unchar proc_id; /* processor id */
+ unchar proc_defect; /* defect ? */
+ unchar reserved[2];
+ } PACKED list[MAXBUS];
+} PACKED gdth_raw_iochan_str;
+
+/* array drive component */
+typedef struct {
+ ulong32 al_controller; /* controller ID */
+ unchar al_cache_drive; /* cache drive number */
+ unchar al_status; /* cache drive state */
+ unchar al_res[2];
+} PACKED gdth_arraycomp_str;
+
+/* array drive information */
+typedef struct {
+ unchar ai_type; /* array type (RAID0,4,5) */
+ unchar ai_cache_drive_cnt; /* active cachedrives */
+ unchar ai_state; /* array drive state */
+ unchar ai_master_cd; /* master cachedrive */
+ ulong32 ai_master_controller; /* ID of master controller */
+ ulong32 ai_size; /* user capacity [sectors] */
+ ulong32 ai_striping_size; /* striping size [sectors] */
+ ulong32 ai_secsize; /* sector size [bytes] */
+ ulong32 ai_err_info; /* failed cache drive */
+ unchar ai_name[8]; /* name of the array drive */
+ unchar ai_controller_cnt; /* number of controllers */
+ unchar ai_removable; /* flag: removable */
+ unchar ai_write_protected; /* flag: write protected */
+ unchar ai_devtype; /* type: always direct access */
+ gdth_arraycomp_str ai_drives[35]; /* drive components: */
+ unchar ai_drive_entries; /* number of drive components */
+ unchar ai_protected; /* protection flag */
+ unchar ai_verify_state; /* state of a parity verify */
+ unchar ai_ext_state; /* extended array drive state */
+ unchar ai_expand_state; /* array expand state (>=2.18)*/
+ unchar ai_reserved[3];
+} PACKED gdth_arrayinf_str;
+
+/* get array drive list */
+typedef struct {
+ ulong32 controller_no; /* controller no. */
+ unchar cd_handle; /* master cachedrive */
+ unchar is_arrayd; /* Flag: is array drive? */
+ unchar is_master; /* Flag: is array master? */
+ unchar is_parity; /* Flag: is parity drive? */
+ unchar is_hotfix; /* Flag: is hotfix drive? */
+ unchar res[3];
+} PACKED gdth_arraylist_str;
+
/* cache info/config IOCTL */
typedef struct {
ulong32 version; /* firmware version */
@@ -322,6 +478,34 @@ typedef struct {
gdth_cstat_str cstat;
} PACKED gdth_cinfo_str;
+/* cache drive info */
+typedef struct {
+ unchar cd_name[8]; /* cache drive name */
+ ulong32 cd_devtype; /* SCSI devicetype */
+ ulong32 cd_ldcnt; /* number of log. drives */
+ ulong32 cd_last_error; /* last error */
+ unchar cd_initialized; /* drive is initialized */
+ unchar cd_removable; /* media is removable */
+ unchar cd_write_protected; /* write protected */
+ unchar cd_flags; /* Pool Hot Fix? */
+ ulong32 ld_blkcnt; /* number of blocks */
+ ulong32 ld_blksize; /* blocksize */
+ ulong32 ld_dcnt; /* number of disks */
+ ulong32 ld_slave; /* log. drive index */
+ ulong32 ld_dtype; /* type of logical drive */
+ ulong32 ld_last_error; /* last error */
+ unchar ld_name[8]; /* log. drive name */
+ unchar ld_error; /* error */
+} PACKED gdth_cdrinfo_str;
+
+/* board features */
+typedef struct {
+ unchar chaining; /* Chaining supported */
+ unchar striping; /* Striping (RAID-0) supp. */
+ unchar mirroring; /* Mirroring (RAID-1) supp. */
+ unchar raid; /* RAID-4/5/10 supported */
+} PACKED gdth_bfeat_str;
+
/* board info IOCTL */
typedef struct {
ulong32 ser_no; /* serial no. */
@@ -351,6 +535,28 @@ typedef struct {
unchar ramparity_pres; /* RAM parity check hardware? */
} PACKED gdth_binfo_str;
+/* get host drive info */
+typedef struct {
+ char name[8]; /* host drive name */
+ ulong32 size; /* size (sectors) */
+ unchar host_drive; /* host drive number */
+ unchar log_drive; /* log. drive (master) */
+ unchar reserved;
+ unchar rw_attribs; /* r/w attribs */
+ ulong32 start_sec; /* start sector */
+} PACKED gdth_hentry_str;
+
+typedef struct {
+ ulong32 entries; /* entry count */
+ ulong32 offset; /* offset of entries */
+ unchar secs_p_head; /* sectors/head */
+ unchar heads_p_cyl; /* heads/cylinder */
+ unchar reserved;
+ unchar clust_drvtype; /* cluster drive type */
+ ulong32 location; /* controller number */
+ gdth_hentry_str entry[MAX_HDRIVES]; /* entries */
+} PACKED gdth_hget_str;
+
/* scatter/gather element */
typedef struct {
ulong32 sg_ptr; /* address */
@@ -642,16 +848,30 @@ typedef struct {
ulong32 info2; /* additional info */
Scsi_Cmnd *req_first; /* top of request queue */
struct {
- unchar present; /* host drive present? */
+ unchar present; /* Flag: host drive present? */
+ unchar is_logdrv; /* Flag: logical drive (master)? */
+ unchar is_arraydrv; /* Flag: array drive? */
+ unchar is_master; /* Flag: array drive master? */
+ unchar is_parity; /* Flag: parity drive? */
+ unchar is_hotfix; /* Flag: hotfix drive? */
+ unchar master_no; /* number of master drive */
unchar lock; /* drive locked? (hot plug) */
unchar heads; /* mapping */
unchar secs;
ushort devtype; /* further information */
ulong32 size; /* capacity */
- } hdr[MAXID]; /* host drives */
+ unchar ldr_no; /* log. drive no. */
+ unchar rw_attribs; /* r/w attributes */
+ ulong32 start_sec; /* start sector */
+ } hdr[MAX_HDRIVES]; /* host drives */
struct {
unchar lock; /* channel locked? (hot plug) */
- } raw[MAXBUS]; /* raw devices */
+ unchar pdev_cnt; /* physical device count */
+ unchar local_no; /* local channel number */
+ unchar io_cnt[MAXID]; /* current IO count */
+ ulong32 address; /* channel address */
+ ulong32 id_list[MAXID]; /* IDs of the phys. devices */
+ } raw[MAXBUS]; /* SCSI channels */
struct {
Scsi_Cmnd *cmnd; /* pending request */
ushort service; /* service */
@@ -659,12 +879,15 @@ typedef struct {
unchar bus_cnt; /* SCSI bus count */
unchar tid_cnt; /* Target ID count */
unchar bus_id[MAXBUS]; /* IOP IDs */
+ unchar virt_bus; /* number of virtual bus */
+ unchar more_proc; /* more /proc info supported */
ushort cmd_cnt; /* command count in DPRAM */
ushort cmd_len; /* length of actual command */
ushort cmd_offs_dpmem; /* actual offset in DPRAM */
ushort ic_all_size; /* sizeof DPRAM interf. area */
gdth_cpar_str cpar; /* controller cache par. */
- char ctr_name[16]; /* controller name */
+ gdth_bfeat_str bfeat; /* controller features */
+ gdth_binfo_str binfo; /* controller info */
#if LINUX_VERSION_CODE >= 0x02015F
spinlock_t smp_lock;
#endif
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index b75bb51cc..8f5a07625 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -1,5 +1,5 @@
/* gdth_proc.c
- * $Id: gdth_proc.c,v 1.11 1998/12/17 15:52:35 achim Exp $
+ * $Id: gdth_proc.c,v 1.13 1999/03/22 16:12:53 achim Exp $
*/
#include "gdth_ioctl.h"
@@ -68,7 +68,6 @@ static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum)
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
{
int orig_length, drive, wb_mode;
- char cmnd[12];
int i, found;
gdth_ha_str *ha;
gdth_cmd_str gdtcmd;
@@ -76,7 +75,6 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
TRACE2(("gdth_set_asc_info() ha %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
- memset(cmnd, 0,10);
orig_length = length + 5;
drive = -1;
wb_mode = 0;
@@ -107,18 +105,7 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdtcmd.u.cache.DeviceNo = i;
gdtcmd.u.cache.BlockNo = 1;
gdtcmd.u.cache.sg_canz = 0;
- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scp.SCp.this_residual = IOCTL_PRI;
- GDTH_LOCK_SCSI_DOCMD();
- scsi_do_cmd(&scp, cmnd, &gdtcmd,
- sizeof(gdth_cmd_str), gdth_scsi_done,
- 30*HZ, 1);
- GDTH_UNLOCK_SCSI_DOCMD();
- down(&sem);
- }
+ gdth_do_cmd(&scp, &gdtcmd, 30);
}
}
if (!found)
@@ -159,13 +146,9 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
}
if (wb_mode) {
- pcpar = (gdth_cpar_str *)kmalloc( sizeof(gdth_cpar_str),
- GFP_ATOMIC | GFP_DMA );
- if (pcpar == NULL) {
- TRACE2(("gdth_set_info(): Unable to allocate memory.\n"));
- printk("Unable to allocate memory.\n");
- return(-EINVAL);
- }
+ if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str)))
+ return(-EBUSY);
+ pcpar = (gdth_cpar_str *)ha->pscratch;
memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) );
gdtcmd.BoardNode = LOCALBOARD;
gdtcmd.Service = CACHESERVICE;
@@ -175,18 +158,8 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdtcmd.u.ioctl.subfunc = CACHE_CONFIG;
gdtcmd.u.ioctl.channel = INVALID_CHANNEL;
pcpar->write_back = wb_mode==1 ? 0:1;
- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scp.SCp.this_residual = IOCTL_PRI;
- GDTH_LOCK_SCSI_DOCMD();
- scsi_do_cmd(&scp, cmnd, &gdtcmd, sizeof(gdth_cmd_str),
- gdth_scsi_done, 30*HZ, 1);
- GDTH_UNLOCK_SCSI_DOCMD();
- down(&sem);
- }
- kfree( pcpar );
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ gdth_ioctl_free(hanum);
printk("Done.\n");
return(orig_length);
}
@@ -197,21 +170,23 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
{
- char cmnd[12];
unchar i, j;
gdth_ha_str *ha;
gdth_iowr_str *piowr;
gdth_iord_str *piord;
gdth_cmd_str *pcmd;
+ gdth_evt_str *pevt;
ulong32 *ppadd, add_size;
+ ulong32 *ppadd2, add_size2;
ulong flags;
TRACE2(("gdth_set_bin_info() ha %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
- memset(cmnd, 0,10);
piowr = (gdth_iowr_str *)buffer;
piord = NULL;
pcmd = NULL;
+ ppadd = ppadd2 = NULL;
+ add_size = add_size2 = 0;
if (length < GDTOFFSOF(gdth_iowr_str,iu))
return(-EINVAL);
@@ -238,6 +213,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
}
} else if (piowr->service == SCSIRAWSERVICE) {
add_size = pcmd->u.raw.sdlen;
+ add_size2 = pcmd->u.raw.sense_len;
if (ha->raw_feat & SCATTER_GATHER) {
ppadd = &pcmd->u.raw.sg_lst[0].sg_ptr;
pcmd->u.raw.sdata = 0xffffffff;
@@ -247,32 +223,26 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
ppadd = &pcmd->u.raw.sdata;
pcmd->u.raw.sg_ranz = 0;
}
+ ppadd2 = &pcmd->u.raw.sense_data;
} else {
return(-EINVAL);
}
- if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) + add_size ))
+ if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2 ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
- piord->size = sizeof(gdth_iord_str) + add_size;
+ piord->size = sizeof(gdth_iord_str) + add_size + add_size2;
if (add_size > 0) {
memcpy(piord->iu.general.data, piowr->iu.general.data, add_size);
*ppadd = virt_to_bus(piord->iu.general.data);
}
- /* do IOCTL */
- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scp.SCp.this_residual = IOCTL_PRI;
- GDTH_LOCK_SCSI_DOCMD();
- scsi_do_cmd(&scp, cmnd, pcmd,
- sizeof(gdth_cmd_str), gdth_scsi_done,
- piowr->timeout*HZ, 1);
- GDTH_UNLOCK_SCSI_DOCMD();
- down(&sem);
- piord->status = (ulong32)scp.SCp.Message;
+ if (add_size2 > 0) {
+ memcpy(piord->iu.general.data+add_size, piowr->iu.general.data, add_size2);
+ *ppadd2 = virt_to_bus(piord->iu.general.data+add_size);
}
+ /* do IOCTL */
+ gdth_do_cmd(&scp, pcmd, piowr->timeout);
+ piord->status = (ulong32)scp.SCp.Message;
break;
case GDTIOCTL_DRVERS:
@@ -381,12 +351,21 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
if (piowr->iu.event.erase == 0xff) {
- gdth_store_event(ha,
- ((gdth_evt_str *)piowr->iu.event.evt)->event_source,
- ((gdth_evt_str *)piowr->iu.event.evt)->event_idx,
- &((gdth_evt_str *)piowr->iu.event.evt)->event_data);
- if (((gdth_evt_str *)piowr->iu.event.evt)->event_source == ES_ASYNC)
- gdth_log_event(&((gdth_evt_str *)piowr->iu.event.evt)->event_data);
+ pevt = (gdth_evt_str *)piowr->iu.event.evt;
+ if (pevt->event_source == ES_TEST)
+ pevt->event_data.size = sizeof(pevt->event_data.eu.test);
+ else if (pevt->event_source == ES_DRIVER)
+ pevt->event_data.size = sizeof(pevt->event_data.eu.driver);
+ else if (pevt->event_source == ES_SYNC)
+ pevt->event_data.size = sizeof(pevt->event_data.eu.sync);
+ else {
+ pevt->event_data.size = sizeof(pevt->event_data.eu.async);
+ gdth_log_event(&pevt->event_data, NULL);
+ }
+ GDTH_LOCK_HA(ha, flags);
+ gdth_store_event(ha, pevt->event_source, pevt->event_idx,
+ &pevt->event_data);
+ GDTH_UNLOCK_HA(ha, flags);
} else if (piowr->iu.event.erase == 0xfe) {
gdth_clear_events();
} else if (piowr->iu.event.erase == 0) {
@@ -416,28 +395,98 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
off_t begin = 0,pos = 0;
gdth_ha_str *ha;
gdth_iord_str *piord;
- int id;
+ int id, i, j, k, sec, flag;
+ int no_mdrv = 0, drv_no, is_mirr;
+ ulong32 cnt;
+
+ gdth_cmd_str gdtcmd;
+ gdth_evt_str estr;
+ Scsi_Cmnd scp;
+ Scsi_Device sdev;
+ char hrec[161];
+ struct timeval tv;
+
+ gdth_dskstat_str *pds;
+ gdth_diskinfo_str *pdi;
+ gdth_arrayinf_str *pai;
+ gdth_defcnt_str *pdef;
+ gdth_cdrinfo_str *pcdi;
+ gdth_hget_str *phg;
TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum));
ha = HADATA(gdth_ctr_tab[hanum]);
id = length;
+ memset(&sdev,0,sizeof(Scsi_Device));
+ memset(&scp, 0,sizeof(Scsi_Cmnd));
+ sdev.host = gdth_ctr_vtab[vh];
+ sdev.id = sdev.host->this_id;
+ scp.cmd_len = 12;
+ scp.host = gdth_ctr_vtab[vh];
+ scp.target = sdev.host->this_id;
+ scp.device = &sdev;
+ scp.use_sg = 0;
+
/* look for buffer ID in length */
if (id > 1) {
-#if LINUX_VERSION_CODE >= 0x020000
+ /* request is i.e. "cat /proc/scsi/gdth/0" */
+ /* format: %-15s\t%-10s\t%-15s\t%s */
+ /* driver parameters */
+ size = sprintf(buffer+len,"Driver Parameters:\n");
+ len += size; pos = begin + len;
+ if (reserve_list[0] == 0xff)
+ strcpy(hrec, "--");
+ else {
+ sprintf(hrec, "%d", reserve_list[0]);
+ for (i = 1; i < MAX_RES_ARGS; i++) {
+ if (reserve_list[i] == 0xff)
+ break;
+ sprintf(hrec,"%s,%d", hrec, reserve_list[i]);
+ }
+ }
size = sprintf(buffer+len,
- "%s Disk Array Controller\n",
- ha->ctr_name);
-#else
+ " reserve_mode: \t%d \treserve_list: \t%s\n",
+ reserve_mode, hrec);
+ len += size; pos = begin + len;
size = sprintf(buffer+len,
- "%s Disk Array Controller (Bus %d)\n",
- ha->ctr_name,busnum);
+ " max_ids: \t%-3d \thdr_channel: \t%d\n",
+ max_ids, hdr_channel);
+ len += size; pos = begin + len;
+
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+
+ /* controller information */
+ size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
+ len += size; pos = begin + len;
+#if LINUX_VERSION_CODE >= 0x020000
+ strcpy(hrec, ha->binfo.type_string);
+#else
+ sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum);
#endif
+ size = sprintf(buffer+len,
+ " Number: \t%d \tName: \t%s\n",
+ hanum, hrec);
len += size; pos = begin + len;
+
+ if (ha->more_proc)
+ sprintf(hrec, "%d.%02d.%02d-%c%03X",
+ (unchar)(ha->binfo.upd_fw_ver>>24),
+ (unchar)(ha->binfo.upd_fw_ver>>16),
+ (unchar)(ha->binfo.upd_fw_ver),
+ ha->bfeat.raid ? 'R':'N',
+ ha->binfo.upd_revision);
+ else
+ sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8),
+ (unchar)(ha->cpar.version));
+
size = sprintf(buffer+len,
- "Firmware Version: %d.%2d\tDriver Version: %s\n",
- (unchar)(ha->cpar.version>>8),
- (unchar)(ha->cpar.version),GDTH_VERSION_STR);
+ " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n",
+ GDTH_VERSION_STR, hrec);
len += size; pos = begin + len;
if (pos < offset) {
@@ -447,7 +496,412 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
if (pos > offset + length)
goto stop_output;
+ if (ha->more_proc) {
+ /* more information: 1. about controller */
+ size = sprintf(buffer+len,
+ " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n",
+ ha->binfo.ser_no, ha->binfo.memsize / 1024);
+ len += size; pos = begin + len;
+
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+
+ /* 2. about physical devices */
+ size = sprintf(buffer+len,"\nPhysical Devices:");
+ len += size; pos = begin + len;
+ flag = FALSE;
+
+ if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
+ goto stop_output;
+ for (i = 0; i < ha->bus_cnt; ++i) {
+ /* 2.a statistics (and retries/reassigns) */
+ TRACE2(("pdr_statistics() chn %d\n",i));
+ pds = (gdth_dskstat_str *)(ha->pscratch + GDTH_SCRATCH/4);
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(pds);
+ gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4;
+ gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
+ gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
+ pds->bid = ha->raw[i].local_no;
+ pds->first = 0;
+ pds->entries = ha->raw[i].pdev_cnt;
+ cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) /
+ sizeof(pds->list[0]);
+ if (pds->entries > cnt)
+ pds->entries = cnt;
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message != S_OK)
+ pds->count = 0;
+ TRACE2(("pdr_statistics() entries %d status %d\n",
+ pds->count, scp.SCp.Message));
+
+ /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
+ for (j = 0; j < ha->raw[i].pdev_cnt; ++j) {
+ /* 2.b drive info */
+ TRACE2(("scsi_drv_info() chn %d dev %d\n",
+ i, ha->raw[i].id_list[j]));
+ pdi = (gdth_diskinfo_str *)ha->pscratch;
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(pdi);
+ gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str);
+ gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
+ gdtcmd.u.ioctl.channel =
+ ha->raw[i].address | ha->raw[i].id_list[j];
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message == S_OK) {
+ strncpy(hrec,pdi->vendor,8);
+ strncpy(hrec+8,pdi->product,16);
+ strncpy(hrec+24,pdi->revision,4);
+ hrec[28] = 0;
+ size = sprintf(buffer+len,
+ "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n",
+ 'A'+i,pdi->target_id,pdi->lun,hrec);
+ len += size; pos = begin + len;
+ flag = TRUE;
+ pdi->no_ldrive &= 0xffff;
+ if (pdi->no_ldrive == 0xffff)
+ strcpy(hrec,"--");
+ else
+ sprintf(hrec,"%d",pdi->no_ldrive);
+ size = sprintf(buffer+len,
+ " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n",
+ pdi->blkcnt/(1024*1024/pdi->blksize),
+ hrec);
+ len += size; pos = begin + len;
+ } else {
+ pdi->devtype = 0xff;
+ }
+
+ if (pdi->devtype == 0) {
+ /* search retries/reassigns */
+ for (k = 0; k < pds->count; ++k) {
+ if (pds->list[k].tid == pdi->target_id &&
+ pds->list[k].lun == pdi->lun) {
+ size = sprintf(buffer+len,
+ " Retries: \t%-6d \tReassigns: \t%d\n",
+ pds->list[k].retries,
+ pds->list[k].reassigns);
+ len += size; pos = begin + len;
+ break;
+ }
+ }
+ /* 2.c grown defects */
+ TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
+ i, ha->raw[i].id_list[j]));
+ pdef = (gdth_defcnt_str *)ha->pscratch;
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(pdef);
+ gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str);
+ gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
+ gdtcmd.u.ioctl.channel =
+ ha->raw[i].address | ha->raw[i].id_list[j];
+ pdef->sddc_type = 0x08;
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message == S_OK) {
+ size = sprintf(buffer+len,
+ " Grown Defects:\t%d\n",
+ pdef->sddc_cnt);
+ len += size; pos = begin + len;
+ }
+ }
+ }
+ }
+ gdth_ioctl_free(hanum);
+
+ if (!flag) {
+ size = sprintf(buffer+len, "\n --\n");
+ len += size; pos = begin + len;
+ }
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+
+ /* 3. about logical drives */
+ size = sprintf(buffer+len,"\nLogical Drives:");
+ len += size; pos = begin + len;
+ flag = FALSE;
+
+ if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
+ goto stop_output;
+ for (i = 0; i < MAX_HDRIVES; ++i) {
+ if (!ha->hdr[i].is_logdrv)
+ continue;
+ drv_no = i;
+ j = k = 0;
+ is_mirr = FALSE;
+ do {
+ /* 3.a log. drive info */
+ TRACE2(("cache_drv_info() drive no %d\n",drv_no));
+ pcdi = (gdth_cdrinfo_str *)ha->pscratch;
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(pcdi);
+ gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
+ gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO;
+ gdtcmd.u.ioctl.channel = drv_no;
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message != S_OK)
+ break;
+ pcdi->ld_dtype >>= 16;
+ j++;
+ if (pcdi->ld_dtype > 2) {
+ strcpy(hrec, "missing");
+ } else if (pcdi->ld_error & 1) {
+ strcpy(hrec, "fault");
+ } else if (pcdi->ld_error & 2) {
+ strcpy(hrec, "invalid");
+ k++; j--;
+ } else {
+ strcpy(hrec, "ok");
+ }
+
+ if (drv_no == i) {
+ size = sprintf(buffer+len,
+ "\n Number: \t%-2d \tStatus: \t%s\n",
+ drv_no, hrec);
+ len += size; pos = begin + len;
+ flag = TRUE;
+ no_mdrv = pcdi->cd_ldcnt;
+ if (no_mdrv > 1 || pcdi->ld_slave != -1) {
+ is_mirr = TRUE;
+ strcpy(hrec, "RAID-1");
+ } else if (pcdi->ld_dtype == 0) {
+ strcpy(hrec, "Disk");
+ } else if (pcdi->ld_dtype == 1) {
+ strcpy(hrec, "RAID-0");
+ } else if (pcdi->ld_dtype == 2) {
+ strcpy(hrec, "Chain");
+ } else {
+ strcpy(hrec, "???");
+ }
+ size = sprintf(buffer+len,
+ " Capacity [MB]:\t%-6d \tType: \t%s\n",
+ pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize),
+ hrec);
+ len += size; pos = begin + len;
+ } else {
+ size = sprintf(buffer+len,
+ " Slave Number: \t%-2d \tStatus: \t%s\n",
+ drv_no & 0x7fff, hrec);
+ len += size; pos = begin + len;
+ }
+ drv_no = pcdi->ld_slave;
+ } while (drv_no != -1);
+
+ if (is_mirr) {
+ size = sprintf(buffer+len,
+ " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n",
+ no_mdrv - j - k, k);
+ len += size; pos = begin + len;
+ }
+
+ if (!ha->hdr[i].is_arraydrv)
+ strcpy(hrec, "--");
+ else
+ sprintf(hrec, "%d", ha->hdr[i].master_no);
+ size = sprintf(buffer+len,
+ " To Array Drv.:\t%s\n", hrec);
+ len += size; pos = begin + len;
+ }
+ gdth_ioctl_free(hanum);
+
+ if (!flag) {
+ size = sprintf(buffer+len, "\n --\n");
+ len += size; pos = begin + len;
+ }
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+
+ /* 4. about array drives */
+ size = sprintf(buffer+len,"\nArray Drives:");
+ len += size; pos = begin + len;
+ flag = FALSE;
+
+ if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
+ goto stop_output;
+ for (i = 0; i < MAX_HDRIVES; ++i) {
+ if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master))
+ continue;
+ /* 4.a array drive info */
+ TRACE2(("array_info() drive no %d\n",i));
+ pai = (gdth_arrayinf_str *)ha->pscratch;
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(pai);
+ gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str);
+ gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
+ gdtcmd.u.ioctl.channel = i;
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message == S_OK) {
+ if (pai->ai_state == 0)
+ strcpy(hrec, "idle");
+ else if (pai->ai_state == 2)
+ strcpy(hrec, "build");
+ else if (pai->ai_state == 4)
+ strcpy(hrec, "ready");
+ else if (pai->ai_state == 6)
+ strcpy(hrec, "fail");
+ else if (pai->ai_state == 8 || pai->ai_state == 10)
+ strcpy(hrec, "rebuild");
+ else
+ strcpy(hrec, "error");
+ if (pai->ai_ext_state & 0x10)
+ strcat(hrec, "/expand");
+ else if (pai->ai_ext_state & 0x1)
+ strcat(hrec, "/patch");
+ size = sprintf(buffer+len,
+ "\n Number: \t%-2d \tStatus: \t%s\n",
+ i,hrec);
+ len += size; pos = begin + len;
+ flag = TRUE;
+
+ if (pai->ai_type == 0)
+ strcpy(hrec, "RAID-0");
+ else if (pai->ai_type == 4)
+ strcpy(hrec, "RAID-4");
+ else if (pai->ai_type == 5)
+ strcpy(hrec, "RAID-5");
+ else
+ strcpy(hrec, "RAID-10");
+ size = sprintf(buffer+len,
+ " Capacity [MB]:\t%-6d \tType: \t%s\n",
+ pai->ai_size/(1024*1024/pai->ai_secsize),
+ hrec);
+ len += size; pos = begin + len;
+ }
+ }
+ gdth_ioctl_free(hanum);
+
+ if (!flag) {
+ size = sprintf(buffer+len, "\n --\n");
+ len += size; pos = begin + len;
+ }
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+
+ /* 5. about host drives */
+ size = sprintf(buffer+len,"\nHost Drives:");
+ len += size; pos = begin + len;
+ flag = FALSE;
+
+ if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
+ goto stop_output;
+ for (i = 0; i < MAX_HDRIVES; ++i) {
+ if (!ha->hdr[i].is_logdrv ||
+ (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master))
+ continue;
+ /* 5.a get host drive list */
+ TRACE2(("host_get() drv_no %d\n",i));
+ phg = (gdth_hget_str *)ha->pscratch;
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_IOCTL;
+ gdtcmd.u.ioctl.p_param = virt_to_bus(phg);
+ gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str);
+ gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
+ gdtcmd.u.ioctl.channel = i;
+ phg->entries = MAX_HDRIVES;
+ phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]);
+ gdth_do_cmd(&scp, &gdtcmd, 30);
+ if (scp.SCp.Message != S_OK) {
+ ha->hdr[i].ldr_no = i;
+ ha->hdr[i].rw_attribs = 0;
+ ha->hdr[i].start_sec = 0;
+ } else {
+ for (j = 0; j < phg->entries; ++j) {
+ k = phg->entry[j].host_drive;
+ if (k >= MAX_HDRIVES)
+ continue;
+ ha->hdr[k].ldr_no = phg->entry[j].log_drive;
+ ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs;
+ ha->hdr[k].start_sec = phg->entry[j].start_sec;
+ }
+ }
+ TRACE2(("host_get entries %d status %d\n",
+ phg->entries, scp.SCp.Message));
+ }
+ gdth_ioctl_free(hanum);
+
+ for (i = 0; i < MAX_HDRIVES; ++i) {
+ if (!(ha->hdr[i].present))
+ continue;
+
+ size = sprintf(buffer+len,
+ "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n",
+ i, ha->hdr[i].ldr_no);
+ len += size; pos = begin + len;
+ flag = TRUE;
+
+ size = sprintf(buffer+len,
+ " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n",
+ ha->hdr[i].size/2048, ha->hdr[i].start_sec);
+ len += size; pos = begin + len;
+ }
+
+ if (!flag) {
+ size = sprintf(buffer+len, "\n --\n");
+ len += size; pos = begin + len;
+ }
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+ }
+
+ /* controller events */
+ size = sprintf(buffer+len,"\nController Events:\n");
+ len += size; pos = begin + len;
+
+ for (id = -1;;) {
+ id = gdth_read_event(ha, id, &estr);
+ if (estr.event_source == 0)
+ break;
+ if (estr.event_data.eu.driver.ionode == hanum &&
+ estr.event_source == ES_ASYNC) {
+ gdth_log_event(&estr.event_data, hrec);
+ do_gettimeofday(&tv);
+ sec = (int)(tv.tv_sec - estr.first_stamp);
+ if (sec < 0) sec = 0;
+ size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n",
+ sec/3600, sec%3600/60, sec%60, hrec);
+ len += size; pos = begin + len;
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto stop_output;
+ }
+ if (id == -1)
+ break;
+ }
} else {
+ /* request from tool (GDTMON,..) */
piord = (gdth_iord_str *)ha->pscratch;
if (piord == NULL)
goto stop_output;
@@ -474,6 +928,22 @@ stop_output:
return(len);
}
+static void gdth_do_cmd(Scsi_Cmnd *scp,gdth_cmd_str *gdtcmd,int timeout)
+{
+ char cmnd[12];
+ struct semaphore sem = MUTEX_LOCKED;
+
+ TRACE2(("gdth_do_cmd()\n"));
+ memset(cmnd, 0, 12);
+ scp->request.rq_status = RQ_SCSI_BUSY;
+ scp->request.sem = &sem;
+ scp->SCp.this_residual = IOCTL_PRI;
+ GDTH_LOCK_SCSI_DOCMD();
+ scsi_do_cmd(scp, cmnd, gdtcmd, sizeof(gdth_cmd_str),
+ gdth_scsi_done, timeout*HZ, 1);
+ GDTH_UNLOCK_SCSI_DOCMD();
+ down(&sem);
+}
void gdth_scsi_done(Scsi_Cmnd *scp)
{
@@ -492,7 +962,7 @@ static int gdth_ioctl_alloc(int hanum, ushort size)
int ret_val;
if (size == 0 || size > GDTH_SCRATCH)
- return -1;
+ return FALSE;
ha = HADATA(gdth_ctr_tab[hanum]);
GDTH_LOCK_HA(ha, flags);
diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h
index 00c18622d..1a6f2d164 100644
--- a/drivers/scsi/gdth_proc.h
+++ b/drivers/scsi/gdth_proc.h
@@ -2,7 +2,7 @@
#define _GDTH_PROC_H
/* gdth_proc.h
- * $Id: gdth_proc.h,v 1.5 1998/12/17 15:43:53 achim Exp $
+ * $Id: gdth_proc.h,v 1.6 1999/03/05 14:32:36 achim Exp $
*/
static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum);
@@ -18,6 +18,7 @@ static void gdth_stop_timeout(int hanum, int busnum, int id);
static void gdth_start_timeout(int hanum, int busnum, int id);
static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout);
+static void gdth_do_cmd(Scsi_Cmnd *scp,gdth_cmd_str *cmd,int timeout);
void gdth_scsi_done(Scsi_Cmnd *scp);
#endif
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 79781bc42..53b1059b7 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -195,6 +195,10 @@
#include "53c7,8xx.h"
#endif
+#ifdef CONFIG_SCSI_SYM53C8XX
+#include "sym53c8xx.h"
+#endif
+
#ifdef CONFIG_SCSI_NCR53C8XX
#include "ncr53c8xx.h"
#endif
@@ -223,6 +227,10 @@
#include "NCR53c406a.h"
#endif
+#ifdef CONFIG_SCSI_SYM53C416
+#include "sym53c416.h"
+#endif
+
#ifdef CONFIG_SCSI_DC390T
#include "dc390.h"
#endif
@@ -287,6 +295,10 @@
#include "ini9100u.h"
#endif
+#ifdef CONFIG_SCSI_INIA100
+#include "inia100.h"
+#endif
+
#ifdef CONFIG_SCSI_DEBUG
#include "scsi_debug.h"
#endif
@@ -460,7 +472,7 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#ifdef CONFIG_SCSI_AIC7XXX
AIC7XXX,
#endif
-#ifdef CONFIG_FD_MCS
+#ifdef CONFIG_SCSI_FD_MCS
FD_MCS,
#endif
#ifdef CONFIG_SCSI_FUTURE_DOMAIN
@@ -475,6 +487,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#ifdef CONFIG_SCSI_NCR53C406A /* 53C406A should come before QLOGIC */
NCR53c406a,
#endif
+#ifdef CONFIG_SCSI_SYM53C416
+ SYM53C416,
+#endif
#ifdef CONFIG_SCSI_QLOGIC_FAS
QLOGICFAS,
#endif
@@ -499,6 +514,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#ifdef CONFIG_SCSI_NCR53C7xx
NCR53c7xx,
#endif
+#ifdef CONFIG_SCSI_SYM53C8XX
+ SYM53C8XX,
+#endif
#ifdef CONFIG_SCSI_NCR53C8XX
NCR53C8XX,
#endif
@@ -541,6 +559,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#ifdef CONFIG_SCSI_INITIO
INI9100U,
#endif
+#ifdef CONFIG_SCSI_INIA100
+ INIA100,
+#endif
#ifdef CONFIG_SCSI_QLOGICPTI
QLOGICPTI,
#endif
diff --git a/drivers/scsi/i60uscsi.c b/drivers/scsi/i60uscsi.c
new file mode 100644
index 000000000..6e8e650b0
--- /dev/null
+++ b/drivers/scsi/i60uscsi.c
@@ -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 <linux/sched.h>
+#include <asm/io.h>
+#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 --git a/drivers/scsi/i60uscsi.h b/drivers/scsi/i60uscsi.h
new file mode 100644
index 000000000..6fff823cc
--- /dev/null
+++ b/drivers/scsi/i60uscsi.h
@@ -0,0 +1,574 @@
+/**************************************************************************
+ * 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.
+ **************************************************************************/
+
+#include <linux/config.h>
+
+#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 --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index bd65b5e84..af2aa49ea 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -3,291 +3,30 @@
*
* Copyright (c) 1995 Strom Systems, Inc. under the terms of the GNU
* General Public License. Written by Martin Kolinek, December 1995.
+ * Further development by: Chris Beauregard, Klaus Kudielka, Michael Lang
+ * See the file README.ibmmca for a detailed description of this driver,
+ * the commandline arguments and the history of its development.
+ * See the WWW-page: http://www.uni-mainz.de/~langm000/linux.html for latest
+ * updates and info.
*/
-/* Update history:
- Jan 15 1996: First public release.
- - Martin Kolinek
-
- Jan 23 1996: Scrapped code which reassigned scsi devices to logical
- device numbers. Instead, the existing assignment (created
- when the machine is powered-up or rebooted) is used.
- A side effect is that the upper layer of Linux SCSI
- device driver gets bogus scsi ids (this is benign),
- and also the hard disks are ordered under Linux the
- same way as they are under dos (i.e., C: disk is sda,
- D: disk is sdb, etc.).
- - Martin Kolinek
-
- I think that the CD-ROM is now detected only if a CD is
- inside CD_ROM while Linux boots. This can be fixed later,
- once the driver works on all types of PS/2's.
- - Martin Kolinek
-
- Feb 7 1996: Modified biosparam function. Fixed the CD-ROM detection.
- For now, devices other than harddisk and CD_ROM are
- ignored. Temporarily modified abort() function
- to behave like reset().
- - Martin Kolinek
-
- Mar 31 1996: The integrated scsi subsystem is correctly found
- in PS/2 models 56,57, but not in model 76. Therefore
- the ibmmca_scsi_setup() function has been added today.
- This function allows the user to force detection of
- scsi subsystem. The kernel option has format
- ibmmcascsi=n
- where n is the scsi_id (pun) of the subsystem. Most likely, n is 7.
- - Martin Kolinek
-
- Aug 21 1996: Modified the code which maps ldns to (pun,0). It was
- insufficient for those of us with CD-ROM changers.
- - Chris Beauregard
-
- Dec 14 1996: More improvements to the ldn mapping. See check_devices
- for details. Did more fiddling with the integrated SCSI detection,
- but I think it's ultimately hopeless without actually testing the
- model of the machine. The 56, 57, 76 and 95 (ultimedia) all have
- different integrated SCSI register configurations. However, the 56
- and 57 are the only ones that have problems with forced detection.
- - Chris Beauregard
-
- Mar 8-16 1997: Modified driver to run as a module and to support
- multiple adapters. A structure, called ibmmca_hostdata, is now
- present, containing all the variables, that were once only
- available for one single adapter. The find_subsystem-routine has vanished.
- The hardware recognition is now done in ibmmca_detect directly.
- This routine checks for presence of MCA-bus, checks the interrupt
- level and continues with checking the installed hardware.
- Certain PS/2-models do not recognize a SCSI-subsystem automatically.
- Hence, the setup defined by command-line-parameters is checked first.
- Thereafter, the routine probes for an integrated SCSI-subsystem.
- Finally, adapters are checked. This method has the advantage to cover all
- possible combinations of multiple SCSI-subsystems on one MCA-board. Up to
- eight SCSI-subsystems can be recognized and announced to the upper-level
- drivers with this improvement. A set of defines made changes to other
- routines as small as possible.
- - Klaus Kudielka
-
- May 30 1997: (v1.5b)
- 1) SCSI-command capability enlarged by the recognition of MODE_SELECT.
- This needs the RD-Bit to be disabled on IM_OTHER_SCSI_CMD_CMD which
- allows data to be written from the system to the device. It is a
- necessary step to be allowed to set blocksize of SCSI-tape-drives and
- the tape-speed, whithout confusing the SCSI-Subsystem.
- 2) The recognition of a tape is included in the check_devices routine.
- This is done by checking for TYPE_TAPE, that is already defined in
- the kernel-scsi-environment. The markup of a tape is done in the
- global ldn_is_tape[] array. If the entry on index ldn
- is 1, there is a tapedrive connected.
- 3) The ldn_is_tape[] array is necessary to distinguish between tape- and
- other devices. Fixed blocklength devices should not cause a problem
- with the SCB-command for read and write in the ibmmca_queuecommand
- subroutine. Therefore, I only derivate the READ_XX, WRITE_XX for
- the tape-devices, as recommended by IBM in this Technical Reference,
- mentioned below. (IBM recommends to avoid using the read/write of the
- subsystem, but the fact was, that read/write causes a command error from
- the subsystem and this causes kernel-panic.)
- 4) In addition, I propose to use the ldn instead of a fix char for the
- display of PS2_DISK_LED_ON(). On 95, one can distinguish between the
- devices that are accessed. It shows activity and easyfies debugging.
- The tape-support has been tested with a SONY SDT-5200 and a HP DDS-2
- (I do not know yet the type). Optimization and CD-ROM audio-support,
- I am working on ...
- - Michael Lang
-
- June 19 1997: (v1.6b)
- 1) Submitting the extra-array ldn_is_tape[] -> to the local ld[]
- device-array.
- 2) CD-ROM Audio-Play seems to work now.
- 3) When using DDS-2 (120M) DAT-Tapes, mtst shows still density-code
- 0x13 for ordinary DDS (61000 BPM) instead 0x24 for DDS-2. This appears
- also on Adaptec 2940 adaptor in a PCI-System. Therefore, I assume that
- the problem is independent of the low-level-driver/bus-architecture.
- 4) Hexadecimal ldn on PS/2-95 LED-display.
- 5) Fixing of the PS/2-LED on/off that it works right with tapedrives and
- does not confuse the disk_rw_in_progress counter.
- - Michael Lang
-
- June 21 1997: (v1.7b)
- 1) Adding of a proc_info routine to inform in /proc/scsi/ibmmca/<host> the
- outer-world about operational load statistics on the different ldns,
- seen by the driver. Everybody that has more than one IBM-SCSI should
- test this, because I only have one and cannot see what happens with more
- than one IBM-SCSI hosts.
- 2) Definition of a driver version-number to have a better recognition of
- the source when there are existing too much releases that may confuse
- the user, when reading about release-specific problems. Up to know,
- I calculated the version-number to be 1.7. Because we are in BETA-test
- yet, it is today 1.7b.
- 3) Sorry for the heavy bug I programmed on June 19 1997! After that, the
- CD-ROM did not work any more! The C7-command was a fake impression
- I got while programming. Now, the READ and WRITE commands for CD-ROM are
- no longer running over the subsystem, but just over
- IM_OTHER_SCSI_CMD_CMD. On my observations (PS/2-95), now CD-ROM mounts
- much faster(!) and hopefully all fancy multimedia-functions, like direct
- digital recording from audio-CDs also work. (I tried it with cdda2wav
- from the cdwtools-package and it filled up the harddisk immediately :-).)
- To easify boolean logics, a further local device-type in ld[], called
- is_cdrom has been included.
- 4) If one uses a SCSI-device of unsupported type/commands, one
- immediately runs into a kernel-panic caused by Command Error. To better
- understand which SCSI-command caused the problem, I extended this
- specific panic-message slightly.
- - Michael Lang
-
- June 25 1997: (v1.8b)
- 1) Some cosmetical changes for the handling of SCSI-device-types.
- Now, also CD-Burners / WORMs and SCSI-scanners should work. For
- MO-drives I have no experience, therefore not yet supported.
- In logical_devices I changed from different type-variables to one
- called 'device_type' where the values, corresponding to scsi.h,
- of a SCSI-device are stored.
- 2) There existed a small bug, that maps a device, coming after a SCSI-tape
- wrong. Therefore, e.g. a CD-ROM changer would have been mapped wrong
- -> problem removed.
- 3) Extension of the logical_device structure. Now it contains also device,
- vendor and revision-level of a SCSI-device for internal usage.
- - Michael Lang
-
- June 26-29 1997: (v2.0b)
- 1) The release number 2.0b is necessary because of the completely new done
- recognition and handling of SCSI-devices with the adapter. As I got
- from Chris the hint, that the subsystem can reassign ldns dynamically,
- I remembered this immediate_assign-command, I found once in the handbook.
- Now, the driver first kills all ldn assignments that are set by default
- on the SCSI-subsystem. After that, it probes on all puns and luns for
- devices by going through all combinations with immediate_assign and
- probing for devices, using device_inquiry. The found physical(!) pun,lun
- structure is stored in get_scsi[][] as device types. This is followed
- by the assignment of all ldns to existing SCSI-devices. If more ldns
- than devices are available, they are assigned to non existing pun,lun
- combinations to satisfy the adapter. With this, the dynamical mapping
- was possible to implement. (For further info see the text in the
- source-code and in the description below. Read the description
- below BEFORE installing this driver on your system!)
- 2) Changed the name IBMMCA_DRIVER_VERSION to IBMMCA_SCSI_DRIVER_VERSION.
- 3) The LED-display shows on PS/2-95 no longer the ldn, but the SCSI-ID
- (pun) of the accessed SCSI-device. This is now senseful, because the
- pun known within the driver is exactly the pun of the physical device
- and no longer a fake one.
- 4) The /proc/scsi/ibmmca/<host_no> consists now of the first part, where
- hit-statistics of ldns is shown and a second part, where the maps of
- physical and logical SCSI-devices are displayed. This could be very
- interesting, when one is using more than 15 SCSI-devices in order to
- follow the dynamical remapping of ldns.
- - Michael Lang
-
- June 26-29 1997: (v2.0b-1)
- 1) I forgot to switch the local_checking_phase_flag to 1 and back to 0
- in the dynamical remapping part in ibmmca_queuecommand for the
- device_exist routine. Sorry.
- - Michael Lang
-
- July 1-13 1997: (v3.0b,c)
- 1) Merging of the driver-developments of Klaus Kudielka and Michael Lang
- in order to get a optimum and unified driver-release for the
- IBM-SCSI-Subsystem-Adapter(s).
- For people, using the Kernel-release >=2.1.0, module-support should
- be no problem. For users, running under <2.1.0, module-support may not
- work, because the methods have changed between 2.0.x and 2.1.x.
- 2) Added some more effective statistics for /proc-output.
- 3) Change typecasting at necessary points from (unsigned long) to
- virt_to_bus().
- 4) Included #if... at special points to have specific adaption of the
- driver to kernel 2.0.x and 2.1.x. It should therefore also run with
- later releases.
- 5) Magneto-Optical drives and medium-changers are also recognized, now.
- Therefore, we have a completely gapfree recognition of all SCSI-
- device-types, that are known by Linux up to kernel 2.1.31.
- 6) The flag SCSI_IBMMCA_DEV_RESET has been inserted. If it is set within
- the configuration, each connected SCSI-device will get a reset command
- during boottime. This can be necessary for some special SCSI-devices.
- This flag should be included in Config.in.
- (See also the new Config.in file.)
- Probable next improvement: bad disk handler.
- - Michael Lang
-
- Sept 14 1997: (v3.0c)
- 1) Some debugging and speed optimization applied.
- - Michael Lang
-
- Dec 15, 1997
- - chrisb@truespectra.com
- - made the front panel display thingy optional, specified from the
- command-line via ibmmcascsi=display. Along the lines of the /LED
- option for the OS/2 driver.
- - fixed small bug in the LED display that would hang some machines.
- - reversed ordering of the drives (using the
- IBMMCA_SCSI_ORDER_STANDARD define). This is necessary for two main
- reasons:
- - users who've already installed Linux won't be screwed. Keep
- in mind that not everyone is a kernel hacker.
- - be consistent with the BIOS ordering of the drives. In the
- BIOS, id 6 is C:, id 0 might be D:. With this scheme, they'd be
- backwards. This confuses the crap out of those heathens who've
- got a impure Linux installation (which, <wince>, I'm one of).
- This whole problem arises because IBM is actually non-standard with
- the id to BIOS mappings. You'll find, in fdomain.c, a similar
- comment about a few FD BIOS revisions. The Linux (and apparently
- industry) standard is that C: maps to scsi id (0,0). Let's stick
- with that standard.
- - Since this is technically a branch of my own, I changed the
- version number to 3.0e-cpb.
-
- Jan 17, 1998: (v3.0f)
- 1) Addition of some statistical info for /proc in proc_info.
- 2) Taking care of the SCSI-assignment problem, dealed by Chris at Dec 15
- 1997. In fact, IBM is right, concerning the assignment of SCSI-devices
- to driveletters. It is conform to the ANSI-definition of the SCSI-
- standard to assign drive C: to SCSI-id 6, because it is the highest
- hardware priority after the hostadapter (that has still today by
- default everywhere id 7). Also realtime-operating systems that I use,
- like LynxOS and OS9, which are quite industrial systems use top-down
- numbering of the harddisks, that is also starting at id 6. Now, one
- sits a bit between two chairs. On one hand side, using the define
- IBMMCA_SCSI_ORDER_STANDARD makes Linux assigning disks conform to
- the IBM- and ANSI-SCSI-standard and keeps this driver downward
- compatible to older releases, on the other hand side, people is quite
- habituated in believing that C: is assigned to (0,0) and much other
- SCSI-BIOS do so. Therefore, I moved the IBMMCA_SCSI_ORDER_STANDARD
- define out of the driver and put it into Config.in as subitem of
- 'IBM SCSI support'. A help, added to Documentation/Configure.help
- explains the differences between saying 'y' or 'n' to the user, when
- IBMMCA_SCSI_ORDER_STANDARD prompts, so the ordinary user is enabled to
- choose the way of assignment, depending on his own situation and gusto.
- 3) Adapted SCSI_IBMMCA_DEV_RESET to the local naming convention, so it is
- now called IBMMCA_SCSI_DEV_RESET.
- 4) Optimization of proc_info and its subroutines.
- 5) Added more in-source-comments and extended the driver description by
- some explanation about the SCSI-device-assignment problem.
- - Michael Lang
-
- Jan 18, 1998: (v3.0g)
- 1) Correcting names to be absolutely conform to the later 2.1.x releases.
- This is necessary for
- IBMMCA_SCSI_DEV_RESET -> CONFIG_IBMMCA_SCSI_DEV_RESET
- IBMMCA_SCSI_ORDER_STANDARD -> CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- - Michael Lang
-
- TODO:
-
- - It seems that the handling of bad disks is really bad -
- non-existent, in fact.
- - More testing of the full driver-controlled dynamical ldn
- (re)mapping for up to 56 SCSI-devices.
- - Support more SCSI-device-types, if Linux defines more.
- - Support more of the SCSI-command set.
- - Support some of the caching abilities, particularly Read Prefetch.
- This fetches data into the cache, which later gets hit by the
- regular Read Data.
- - Abort and Reset functions still slightly buggy. Especially when
- floppydisk(!) operations report errors.
-
-******************************************************************************/
+/******************* HEADER FILE INCLUDES ************************************/
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+/* choose adaption for Kernellevel */
+#define local_LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+#if LINUX_VERSION_CODE < local_LinuxVersionCode(2,1,0)
+#define OLDKERN
+#else
+#undef OLDKERN
+#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/delay.h>
@@ -297,7 +36,9 @@
#include <linux/stat.h>
#include <linux/mca.h>
#include <asm/system.h>
+#ifndef OLDKERN
#include <asm/spinlock.h>
+#endif
#include <asm/io.h>
#include "sd.h"
#include "scsi.h"
@@ -306,199 +47,29 @@
#include <linux/config.h> /* for CONFIG_SCSI_IBMMCA etc. */
-/*--------------------------------------------------------------------*/
+/******************* LOCAL DEFINES *******************************************/
-/* current version of this driver-source: */
-#define IBMMCA_SCSI_DRIVER_VERSION "3.0f"
-
-/* use standard Linux ordering, where C: maps to (0,0), unlike the IBM
-standard which seems to like C: => (6,0) */
-/* #define IBMMCA_SCSI_ORDER_STANDARD is defined/undefined in Config.in
- * now, while configuring the kernel. */
-
-/*
- Driver Description
-
- (A) Subsystem Detection
- This is done in the ibmmca_detect() function and is easy, since
- the information about MCA integrated subsystems and plug-in
- adapters is readily available in structure *mca_info.
-
- (B) Physical Units, Logical Units, and Logical Devices
- There can be up to 56 devices on SCSI bus (besides the adapter):
- there are up to 7 "physical units" (each identified by physical unit
- number or pun, also called the scsi id, this is the number you select
- with hardware jumpers), and each physical unit can have up to 8
- "logical units" (each identified by logical unit number, or lun,
- between 0 and 7).
-
- Typically the adapter has pun=7, so puns of other physical units
- are between 0 and 6. Almost all physical units have only one
- logical unit, with lun=0. A CD-ROM jukebox would be an example of
- a physical unit with more than one logical unit.
-
- The embedded microprocessor of IBM SCSI subsystem hides the complex
- two-dimensional (pun,lun) organization from the operating system.
- When the machine is powered-up (or rebooted, I am not sure), the
- embedded microprocessor checks, on it own, all 56 possible (pun,lun)
- combinations, and first 15 devices found are assigned into a
- one-dimensional array of so-called "logical devices", identified by
- "logical device numbers" or ldn. The last ldn=15 is reserved for
- the subsystem itself.
-
- One consequence of information hiding is that the real (pun,lun)
- numbers are also hidden. Therefore this driver takes the following
- approach: It checks the ldn's (0 to 6) to find out which ldn's
- have devices assigned. This is done by function check_devices() and
- device_exists(). The interrupt handler has a special paragraph of code
- (see local_checking_phase_flag) to assist in the checking. Assume, for
- example, that three logical devices were found assigned at ldn 0, 1, 2.
- These are presented to the upper layer of Linux SCSI driver
- as devices with bogus (pun, lun) equal to (0,0), (1,0), (2,0).
- On the other hand, if the upper layer issues a command to device
- say (4,0), this driver returns DID_NO_CONNECT error.
-
- That last paragraph is no longer correct, but is left for
- historical purposes. It limited the number of devices to 7, far
- fewer than the 15 that it could use. Now it just maps
- ldn -> (ldn/8,ldn%8). We end up with a real mishmash of puns
- and luns, but it all seems to work. - Chris Beaurgard
-
- And that last paragraph is also no longer correct. It uses a
- slightly more complex mapping that will always map hard disks to
- (x,0), for some x, and consecutive none disk devices will usually
- share puns.
-
- Again, the last paragraphs are no longer correct. Now, the physical
- SCSI-devices on the SCSI-bus are probed via immediate_assign- and
- device_inquiry-commands. This delivers a exact map of the physical
- SCSI-world that is now stored in the get_scsi[][]-array. This means,
- that the once hidden pun,lun assignment is now known to this driver.
- It no longer believes in default-settings of the subsystem and maps all
- ldns to existing pun,lun by foot. This assures full control of the ldn
- mapping and allows dynamical remapping of ldns to different pun,lun, if
- there are more SCSI-devices installed than ldns available (n>15). The
- ldns from 0 to 6 get 'hardwired' by this driver to puns 0 to 7 at lun=0,
- excluding the pun of the subsystem. This assures, that at least simple
- SCSI-installations have optimum access-speed and are not touched by
- dynamical remapping. The ldns 7 to 14 are put to existing devices with
- lun>0 or to non-existing devices, in order to satisfy the subsystem, if
- there are less than 15 SCSI-devices connected. In the case of more than 15
- devices, the dynamical mapping goes active. If the get_scsi[][] reports a
- device to be existant, but it has no ldn assigned, it gets a ldn out of 7
- to 14. The numbers are assigned in cyclic order. Therefore it takes 8
- dynamical assignments on SCSI-devices, until a certain device
- looses its ldn again. This assures, that dynamical remapping is avoided
- during intense I/O between up to eight SCSI-devices (means pun,lun
- combinations). A further advantage of this method is, that people who
- build their kernel without probing on all luns will get what they expect.
-
- IMPORTANT: Because of the now correct recognition of physical pun,lun, and
- their report to mid-level- and higher-level-drivers, the new reported puns
- can be different from the old, faked puns. Therefore, Linux will eventually
- change /dev/sdXXX assignments and prompt you for corrupted superblock
- repair on boottime. In this case DO NOT PANIC, YOUR DISKS ARE STILL OK!!!
- You have to reboot (CTRL-D) with a old kernel and set the /etc/fstab-file
- entries right. After that, the system should come up as errorfree as before.
- If your boot-partition is not coming up, also edit the /etc/lilo.conf-file
- in a Linux session booted on old kernel and run lilo before reboot. Check
- lilo.conf anyway to get boot on other partitions with foreign OSes right
- again.
-
- The problem is, that Linux does not assign the SCSI-devices in the
- way as described in the ANSI-SCSI-standard. Linux assigns /dev/sda to
- the device with at minimum id 0. But the first drive should be at id 6,
- because for historical reasons, drive at id 6 has, by hardware, the highest
- priority and a drive at id 0 the lowest. IBM was one of the rare producers,
- where the BIOS assigns drives belonging to the ANSI-SCSI-standard. Most
- other producers' BIOS does not (I think even Adaptec-BIOS). The
- IBMMCA_SCSI_ORDER_STANDARD flag helps to be able to choose the preferred
- way of SCSI-device-assignment. Defining this flag would result in Linux
- determining the devices in the same order as DOS and OS/2 does on your
- MCA-machine. This is also standard on most industrial computers. Leaving
- this flag undefined will get your devices ordered in the default way of
- Linux. See also the remarks of Chris Beauregard from Dec 15, 1997 and
- the followups.
-
- (C) Regular Processing
- Only three functions get involved: ibmmca_queuecommand(), issue_cmd(),
- and interrupt_handler().
-
- The upper layer issues a scsi command by calling function
- ibmmca_queuecommand(). This function fills a "subsystem control block"
- (scb) and calls a local function issue_cmd(), which writes a scb
- command into subsystem I/O ports. Once the scb command is carried out,
- interrupt_handler() is invoked. If a device is determined to be existant
- and it has not assigned any ldn, it gets one dynamically.
-
- (D) Abort, Reset.
- These are implemented with busy waiting for interrupt to arrive.
- The abort does not worked well for me, so I instead call the
- ibmmca_reset() from the ibmmca_abort() function.
-
- (E) Disk Geometry
- The ibmmca_biosparams() function should return same disk geometry
- as bios. This is needed for fdisk, etc. The returned geometry is
- certainly correct for disk smaller than 1 gigabyte, but I am not
- 100% sure that it is correct for larger disks.
-
- (F) Kernel Boot Option
- The function ibmmca_scsi_setup() is called if option ibmmcascsi=n
- is passed to the kernel. See file linux/init/main.c for details.
-
- (G) Driver Module Support
- Is implemented and tested by K. Kudielka. This could probably not work
- on kernels <2.1.0.
-
- (H) Multiple Hostadapter Support
- This driver supports up to eight interfaces of type IBM-SCSI-Subsystem.
- Integrated-, and MCA-adapters are automatically recognized. Unrecognizable
- IBM-SCSI-Subsystem interfaces can be specified as kernel-parameters.
-
- (I) /proc-Filesystem Information
- Information about the driver condition is given in
- /proc/scsi/ibmmca/<host_no>. ibmmca_proc_info provides this information.
- */
+#ifndef mdelay
+#define mdelay(a) udelay((a) * 1000)
+#endif
/*--------------------------------------------------------------------*/
-/* Here are the values and structures specific for the subsystem.
- * The source of information is "Update for the PS/2 Hardware
- * Interface Technical Reference, Common Interfaces", September 1991,
- * part number 04G3281, available in the U.S. for $21.75 at
- * 1-800-IBM-PCTB, elsewhere call your local friendly IBM
- * representative.
- * In addition to SCSI subsystem, this update contains fairly detailed
- * (at hardware register level) sections on diskette controller,
- * keyboard controller, serial port controller, VGA, and XGA.
- *
- * Additional information from "Personal System/2 Micro Channel SCSI
- * Adapter with Cache Technical Reference", March 1990, PN 68X2365,
- * probably available from the same source (or possibly found buried
- * in officemates desk).
- *
- * Further literature/program-sources referred for this driver:
- *
- * Friedhelm Schmidt, "SCSI-Bus und IDE-Schnittstelle - Moderne Peripherie-
- * Schnittstellen: Hardware, Protokollbeschreibung und Anwendung", 2. Aufl.
- * Addison Wesley, 1996.
- *
- * Michael K. Johnson, "The Linux Kernel Hackers' Guide", Version 0.6, Chapel
- * Hill - North Carolina, 1995
- *
- * Andreas Kaiser, "SCSI TAPE BACKUP for OS/2 2.0", Version 2.12, Stuttgart
- * 1993
- */
+
+/* current version of this driver-source: */
+#define IBMMCA_SCSI_DRIVER_VERSION "3.1e"
/*--------------------------------------------------------------------*/
/* driver configuration */
#define IM_MAX_HOSTS 8 /* maximum number of host adapters */
-#define IM_RESET_DELAY 10 /* seconds allowed for a reset */
+#define IM_RESET_DELAY 60 /* seconds allowed for a reset */
/* driver debugging - #undef all for normal operation */
/* if defined: count interrupts and ignore this special one: */
#undef IM_DEBUG_TIMEOUT 50
+#define TIMEOUT_PUN 0
+#define TIMEOUT_LUN 0
/* verbose interrupt: */
#undef IM_DEBUG_INT
/* verbose queuecommand: */
@@ -512,11 +83,11 @@ standard which seems to like C: => (6,0) */
#define IM_DEBUG_CMD_DEVICE TYPE_TAPE
/* relative addresses of hardware registers on a subsystem */
-#define IM_CMD_REG (shpnt->io_port) /*Command Interface, (4 bytes long) */
-#define IM_ATTN_REG (shpnt->io_port+4) /*Attention (1 byte) */
-#define IM_CTR_REG (shpnt->io_port+5) /*Basic Control (1 byte) */
-#define IM_INTR_REG (shpnt->io_port+6) /*Interrupt Status (1 byte, r/o) */
-#define IM_STAT_REG (shpnt->io_port+7) /*Basic Status (1 byte, read only) */
+#define IM_CMD_REG(hi) (hosts[(hi)]->io_port) /*Command Interface, (4 bytes long) */
+#define IM_ATTN_REG(hi) (hosts[(hi)]->io_port+4) /*Attention (1 byte) */
+#define IM_CTR_REG(hi) (hosts[(hi)]->io_port+5) /*Basic Control (1 byte) */
+#define IM_INTR_REG(hi) (hosts[(hi)]->io_port+6) /*Interrupt Status (1 byte, r/o) */
+#define IM_STAT_REG(hi) (hosts[(hi)]->io_port+7) /*Basic Status (1 byte, read only) */
/* basic I/O-port of first adapter */
#define IM_IO_PORT 0x3540
@@ -668,9 +239,15 @@ struct im_tsb
/* use_display is set by the ibmmcascsi=display command line arg */
static int use_display = 0;
+/* use_adisplay is set by ibmmcascsi=adisplay, which offers a higher
+ * level of displayed luxus on PS/2 95 (really fancy! :-))) */
+static int use_adisplay = 0;
+
#define PS2_DISK_LED_ON(ad,id) {\
if( use_display ) { outb((char)(id+48), MOD95_LED_PORT ); \
outb((char)(ad+48), MOD95_LED_PORT+1); } \
+ else if( use_adisplay ) { if (id<7) outb((char)(id+48), \
+ MOD95_LED_PORT+1+id); outb((char)(ad+48), MOD95_LED_PORT); } \
else outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR); \
}
@@ -678,6 +255,11 @@ static int use_display = 0;
#define PS2_DISK_LED_OFF() {\
if( use_display ) { outb( ' ', MOD95_LED_PORT ); \
outb(' ', MOD95_LED_PORT+1); } \
+ if ( use_adisplay ) { outb(' ',MOD95_LED_PORT ); \
+ outb(' ',MOD95_LED_PORT+1); outb(' ',MOD95_LED_PORT+2); \
+ outb(' ',MOD95_LED_PORT+3); outb(' ',MOD95_LED_PORT+4); \
+ outb(' ',MOD95_LED_PORT+5); outb(' ',MOD95_LED_PORT+6); \
+ outb(' ',MOD95_LED_PORT+7); } \
else outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); \
}
@@ -693,18 +275,20 @@ struct subsys_list_struct
/* List of possible IBM-SCSI-adapters */
struct subsys_list_struct subsys_list[] =
{
- {0x8efc, "IBM Fast SCSI-2 Adapter"},
- {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/cache"},
- {0x8ef8, "IBM Expansion Unit SCSI Controller"},
- {0x8eff, "IBM SCSI Adapter w/Cache"},
- {0x8efe, "IBM SCSI Adapter"},
-};
+ {0x8efc, "IBM Fast SCSI-2 Adapter"}, /* special = 0 */
+ {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/cache"}, /* special = 1 */
+ {0x8ef8, "IBM Expansion Unit SCSI Controller"},/* special = 2 */
+ {0x8eff, "IBM SCSI Adapter w/Cache"}, /* special = 3 */
+ {0x8efe, "IBM SCSI Adapter"}, /* special = 4 */
+};
/*for /proc filesystem */
struct proc_dir_entry proc_scsi_ibmmca =
{
PROC_SCSI_IBMMCA, 6, "ibmmca",
- S_IFDIR | S_IRUGO | S_IXUGO, 2
+ S_IFDIR | S_IRUGO | S_IXUGO, 2,
+ 0, 0, 0, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL
};
/* Max number of logical devices (can be up from 0 to 14). 15 is the address
@@ -715,8 +299,9 @@ of the adapter itself. */
struct logical_device
{
struct im_scb scb; /* SCSI-subsystem-control-block structure */
- struct im_tsb tsb;
- struct im_sge sge[16];
+ struct im_tsb tsb; /* SCSI command complete status block structure */
+ struct im_sge sge[16]; /* scatter gather list structure */
+ unsigned char buf[256]; /* SCSI command return data buffer */
Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */
int device_type; /* type of the SCSI-device. See include/scsi/scsi.h
@@ -736,6 +321,7 @@ struct Driver_Statistics
int total_accesses; /* total accesses on all ldns */
int total_interrupts; /* total interrupts (should be
same as total_accesses) */
+ int total_errors; /* command completed with error */
/* dynamical assignment statistics */
int total_scsi_devices; /* number of physical pun,lun */
int dyn_flag; /* flag showing dynamical mode */
@@ -747,44 +333,54 @@ struct Driver_Statistics
/* data structure for each host adapter */
struct ibmmca_hostdata
{
- /* array of logical devices: */
- struct logical_device _ld[MAX_LOG_DEV];
- /* array to convert (pun, lun) into logical device number: */
- unsigned char _get_ldn[8][8];
- /*array that contains the information about the physical SCSI-devices
- attached to this host adapter: */
- unsigned char _get_scsi[8][8];
- /* used only when checking logical devices: */
- int _local_checking_phase_flag;
- /* report received interrupt: */
- int _got_interrupt;
- /* report termination-status of SCSI-command: */
- int _stat_result;
- /* reset status (used only when doing reset): */
- int _reset_status;
- /* code of the last SCSI command (needed for panic info): */
- int _last_scsi_command;
- /* Counter that points on the next reassignable ldn for dynamical
- remapping. The default value is 7, that is the first reassignable
- number in the list at boottime: */
- int _next_ldn;
- /* Statistics-structure for this IBM-SCSI-host: */
- struct Driver_Statistics _IBM_DS;
+ /* array of logical devices: */
+ struct logical_device _ld[MAX_LOG_DEV+1];
+ /* array to convert (pun, lun) into logical device number: */
+ unsigned char _get_ldn[8][8];
+ /*array that contains the information about the physical SCSI-devices
+ attached to this host adapter: */
+ unsigned char _get_scsi[8][8];
+ /* used only when checking logical devices: */
+ int _local_checking_phase_flag;
+ /* report received interrupt: */
+ int _got_interrupt;
+ /* report termination-status of SCSI-command: */
+ int _stat_result;
+ /* reset status (used only when doing reset): */
+ int _reset_status;
+ /* code of the last SCSI command (needed for panic info): */
+ int _last_scsi_command[MAX_LOG_DEV+1];
+ /* identifier of the last SCSI-command type */
+ int _last_scsi_type[MAX_LOG_DEV+1];
+ /* Counter that points on the next reassignable ldn for dynamical
+ remapping. The default value is 7, that is the first reassignable
+ number in the list at boottime: */
+ int _next_ldn;
+ /* Statistics-structure for this IBM-SCSI-host: */
+ struct Driver_Statistics _IBM_DS;
+ /* This hostadapters pos-registers pos2 and pos3 */
+ unsigned _pos2, _pos3;
+ /* assign a special variable, that contains dedicated info about the
+ adaptertype */
+ int _special;
};
/* macros to access host data structure */
-#define HOSTDATA(shpnt) ((struct ibmmca_hostdata *) shpnt->hostdata)
-#define subsystem_pun (shpnt->this_id)
-#define ld (HOSTDATA(shpnt)->_ld)
-#define get_ldn (HOSTDATA(shpnt)->_get_ldn)
-#define get_scsi (HOSTDATA(shpnt)->_get_scsi)
-#define local_checking_phase_flag (HOSTDATA(shpnt)->_local_checking_phase_flag)
-#define got_interrupt (HOSTDATA(shpnt)->_got_interrupt)
-#define stat_result (HOSTDATA(shpnt)->_stat_result)
-#define reset_status (HOSTDATA(shpnt)->_reset_status)
-#define last_scsi_command (HOSTDATA(shpnt)->_last_scsi_command)
-#define next_ldn (HOSTDATA(shpnt)->_next_ldn)
-#define IBM_DS (HOSTDATA(shpnt)->_IBM_DS)
+#define subsystem_pun(hi) (hosts[(hi)]->this_id)
+#define ld(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_ld)
+#define get_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_ldn)
+#define get_scsi(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_scsi)
+#define local_checking_phase_flag(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_local_checking_phase_flag)
+#define got_interrupt(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_got_interrupt)
+#define stat_result(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_stat_result)
+#define reset_status(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_reset_status)
+#define last_scsi_command(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_command)
+#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
+#define next_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_next_ldn)
+#define IBM_DS(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_IBM_DS)
+#define special(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_special)
+#define pos2(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos2)
+#define pos3(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos3)
/* Define a arbitrary number as subsystem-marker-type. This number is, as
described in the ANSI-SCSI-standard, not occupied by other device-types. */
@@ -805,11 +401,23 @@ struct ibmmca_hostdata
#define SET_LDN 0
#define REMOVE_LDN 1
+/* ldn which is used to probe the SCSI devices */
+#define PROBE_LDN 0
+
/* reset status flag contents */
-#define IM_RESET_NOT_IN_PROGRESS 0
-#define IM_RESET_IN_PROGRESS 1
-#define IM_RESET_FINISHED_OK 2
-#define IM_RESET_FINISHED_FAIL 3
+#define IM_RESET_NOT_IN_PROGRESS 0
+#define IM_RESET_IN_PROGRESS 1
+#define IM_RESET_FINISHED_OK 2
+#define IM_RESET_FINISHED_FAIL 3
+#define IM_RESET_NOT_IN_PROGRESS_NO_INT 4
+#define IM_RESET_FINISHED_OK_NO_INT 5
+
+/* special flags for hostdata structure */
+#define FORCED_DETECTION 100
+#define INTEGRATED_SCSI 101
+
+/* define undefined SCSI-command */
+#define NO_SCSI 0xffff
/*-----------------------------------------------------------------------*/
@@ -823,277 +431,517 @@ static int scsi_id[IM_MAX_HOSTS] = { 7, 7, 7, 7, 7, 7, 7, 7 };
MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
MODULE_PARM(display, "1i");
+MODULE_PARM(adisplay, "1i");
+MODULE_PARM(bypass, "1i");
+MODULE_PARM(normal, "1i");
+MODULE_PARM(ansi, "1i");
#endif
/*counter of concurrent disk read/writes, to turn on/off disk led */
static int disk_rw_in_progress = 0;
+/* spinlock handling to avoid command clash while in operation */
+#ifndef OLDKERN
+spinlock_t info_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t proc_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t abort_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t reset_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t issue_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t intr_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
/* host information */
static int found = 0;
static struct Scsi_Host *hosts[IM_MAX_HOSTS+1] = { NULL };
+static unsigned int pos[8]; /* whole pos register-line */
+/* Taking into account the additions, made by ZP Gu.
+ * This selects now the preset value from the configfile and
+ * offers the 'normal' commandline option to be accepted */
+#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
+static char ibm_ansi_order = 1;
+#else
+static char ibm_ansi_order = 0;
+#endif
+
/*-----------------------------------------------------------------------*/
-/*local functions in forward declaration */
-static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs);
-static void do_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs);
-static void issue_cmd (struct Scsi_Host *shpnt, unsigned long cmd_reg,
- unsigned char attn_reg);
+/******************* FUNCTIONS IN FORWARD DECLARATION ************************/
+
+static void interrupt_handler (int, void *, struct pt_regs *);
+#ifndef OLDKERN
+static void do_interrupt_handler (int, void *, struct pt_regs *);
+#endif
+static void issue_cmd (int, unsigned long, unsigned char);
static void internal_done (Scsi_Cmnd * cmd);
-static void check_devices (struct Scsi_Host *shpnt);
-static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun,
- unsigned int lun, unsigned int ldn,
- unsigned int operation);
-static int device_inquiry(struct Scsi_Host *shpnt, int ldn,
- unsigned char *buf);
-static char *ti_p(int value);
-static char *ti_l(int value);
-static int device_exists (struct Scsi_Host *shpnt, int ldn, int *block_length,
- int *device_type);
-static struct Scsi_Host *ibmmca_register(Scsi_Host_Template * template,
- int port, int id);
+static void check_devices (int);
+static int immediate_assign(int, unsigned int, unsigned int, unsigned int,
+ unsigned int);
+#ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
+static int immediate_reset(int, unsigned int);
+#endif
+static int device_inquiry(int, int);
+static int read_capacity(int, int);
+static char *ti_p(int);
+static char *ti_l(int);
+static int device_exists (int, int, int *, int *);
+static struct Scsi_Host *ibmmca_register(Scsi_Host_Template *,
+ int, int, char *);
/* local functions needed for proc_info */
-static int ldn_access_load(struct Scsi_Host *shpnt, int ldn);
-static int ldn_access_total_read_write(struct Scsi_Host *shpnt);
+static int ldn_access_load(int, int);
+static int ldn_access_total_read_write(int);
+static int bypass_controller = 0; /* bypass integrated SCSI-cmd set flag */
/*--------------------------------------------------------------------*/
-static void
-do_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
+/******************* LOCAL FUNCTIONS IMPLEMENTATION *************************/
+
+#ifndef OLDKERN
+/* newer Kernels need the spinlock interrupt handler */
+static void do_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
spin_lock_irqsave(&io_request_lock, flags);
interrupt_handler(irq, dev_id, regs);
spin_unlock_irqrestore(&io_request_lock, flags);
+ return;
}
+#endif
-static void
-interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
+static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
{
- int i = 0;
- struct Scsi_Host *shpnt;
- unsigned int intr_reg;
- unsigned int cmd_result;
- unsigned int ldn;
- unsigned long flags;
-
- /* search for one adapter-response on shared interrupt */
- do
- shpnt = hosts[i++];
- while (shpnt && !(inb(IM_STAT_REG) & IM_INTR_REQUEST));
-
- /* return if some other device on this IRQ caused the interrupt */
- if (!shpnt) return;
-
- /*get command result and logical device */
- intr_reg = inb (IM_INTR_REG);
- cmd_result = intr_reg & 0xf0;
- ldn = intr_reg & 0x0f;
-
- /*must wait for attention reg not busy, then send EOI to subsystem */
- save_flags(flags);
- while (1) {
- cli ();
- if (!(inb (IM_STAT_REG) & IM_BUSY))
- break;
- restore_flags(flags);
- }
- outb (IM_EOI | ldn, IM_ATTN_REG);
- restore_flags (flags);
-
- /*these should never happen (hw fails, or a local programming bug) */
- if (cmd_result == IM_ADAPTER_HW_FAILURE)
- panic ("IBM MCA SCSI: subsystem hardware failure. Last SCSI_CMD=0x%X. \n",
- last_scsi_command);
- if (cmd_result == IM_CMD_ERROR)
- panic ("IBM MCA SCSI: command error. Last SCSI_CMD=0x%X. \n",
- last_scsi_command);
- if (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR)
- panic ("IBM MCA SCSI: software sequencing error. Last SCSI_CMD=0x%X. \n",
- last_scsi_command);
-
- /* if no panic appeared, increase the interrupt-counter */
- IBM_DS.total_interrupts++;
-
- /*only for local checking phase */
- if (local_checking_phase_flag)
- {
- stat_result = cmd_result;
- got_interrupt = 1;
- reset_status = IM_RESET_FINISHED_OK;
- return;
- }
-
- /*handling of commands coming from upper level of scsi driver */
- else
- {
- Scsi_Cmnd *cmd;
-
- /*verify ldn, and may handle rare reset immediate command */
- if (ldn >= MAX_LOG_DEV)
- {
- if (ldn == 0xf && reset_status == IM_RESET_IN_PROGRESS)
- {
- if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
- {
- reset_status = IM_RESET_FINISHED_FAIL;
- }
- else
- {
- /*reset disk led counter, turn off disk led */
- disk_rw_in_progress = 0;
- PS2_DISK_LED_OFF ();
- reset_status = IM_RESET_FINISHED_OK;
- }
- return;
- }
- else
- panic ("IBM MCA SCSI: invalid logical device number.\n");
- }
+ int host_index;
+ unsigned int intr_reg;
+ unsigned int cmd_result;
+ unsigned int ldn;
+ static unsigned long flags;
+ Scsi_Cmnd *cmd;
+ int errorflag;
+ int interror;
+
+ host_index=0; /* make sure, host_index is 0, else this won't work and
+ never dare to ask, what happens, if an interrupt-handler
+ does not work :-((( .... */
+
+ /* search for one adapter-response on shared interrupt */
+ while (hosts[host_index]
+ && !(inb(IM_STAT_REG(host_index)) & IM_INTR_REQUEST))
+ host_index++;
+
+ /* return if some other device on this IRQ caused the interrupt */
+ if (!hosts[host_index]) return;
-#ifdef IM_DEBUG_TIMEOUT
- {
- static int count = 0;
+ /* the reset-function already did all the job, even ints got
+ renabled on the subsystem, so just return */
+ if ((reset_status(host_index) == IM_RESET_NOT_IN_PROGRESS_NO_INT)||
+ (reset_status(host_index) == IM_RESET_FINISHED_OK_NO_INT))
+ {
+ reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS;
+ return;
+ }
+
+ /*get command result and logical device */
+ intr_reg = inb (IM_INTR_REG(host_index));
+ cmd_result = intr_reg & 0xf0;
+ ldn = intr_reg & 0x0f;
- if (++count == IM_DEBUG_TIMEOUT) {
- printk("IBM MCA SCSI: Ignoring interrupt.\n");
- return;
- }
- }
+ /*must wait for attention reg not busy, then send EOI to subsystem */
+ while (1)
+ {
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&intr_lock, flags);
+#endif
+ if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
+ break;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&intr_lock, flags);
#endif
+ }
+ outb (IM_EOI | ldn, IM_ATTN_REG(host_index));
+ /* get the last_scsi_command here */
+ interror = last_scsi_command(host_index)[ldn];
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&intr_lock, flags);
+#endif
+ errorflag = 0; /* no errors by default */
+ /*these should never happen (hw fails, or a local programming bug) */
+ if (cmd_result == IM_ADAPTER_HW_FAILURE)
+ {
+ printk("\n");
+ printk("IBM MCA SCSI: ERROR - subsystem hardware failure!\n");
+ printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n",
+ last_scsi_command(host_index)[ldn],ldn,host_index);
+ errorflag = 1;
+ }
+ if (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR)
+ {
+ printk("\n");
+ printk("IBM MCA SCSI: ERROR - software sequencing error!\n");
+ printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n",
+ last_scsi_command(host_index)[ldn],ldn,host_index);
+ errorflag = 1;
+ }
+ if (cmd_result == IM_CMD_ERROR)
+ {
+ printk("\n");
+ printk("IBM MCA SCSI: ERROR - command error!\n");
+ printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n",
+ last_scsi_command(host_index)[ldn],ldn,host_index);
+ errorflag = 1;
+ }
+ if (errorflag)
+ { /* if errors appear, enter this section to give detailed info */
+ printk("IBM MCA SCSI: Subsystem Error-Status follows:\n");
+ printk(" Command Type................: %x\n",
+ last_scsi_type(host_index)[ldn]);
+ printk(" Attention Register..........: %x\n",
+ inb (IM_ATTN_REG(host_index)));
+ printk(" Basic Control Register......: %x\n",
+ inb (IM_CTR_REG(host_index)));
+ printk(" Interrupt Status Register...: %x\n",
+ intr_reg);
+ printk(" Basic Status Register.......: %x\n",
+ inb (IM_STAT_REG(host_index)));
+ if ((last_scsi_type(host_index)[ldn]==IM_SCB)||
+ (last_scsi_type(host_index)[ldn]==IM_LONG_SCB))
+ {
+ printk(" SCB End Status Word.........: %x\n",
+ ld(host_index)[ldn].tsb.end_status);
+ printk(" Command Status..............: %x\n",
+ ld(host_index)[ldn].tsb.cmd_status);
+ printk(" Device Status...............: %x\n",
+ ld(host_index)[ldn].tsb.dev_status);
+ printk(" Command Error...............: %x\n",
+ ld(host_index)[ldn].tsb.cmd_error);
+ printk(" Device Error................: %x\n",
+ ld(host_index)[ldn].tsb.dev_error);
+ printk(" Last SCB Address (LSW)......: %x\n",
+ ld(host_index)[ldn].tsb.low_of_last_scb_adr);
+ printk(" Last SCB Address (MSW)......: %x\n",
+ ld(host_index)[ldn].tsb.high_of_last_scb_adr);
+ }
+ printk(" Send report to the maintainer.\n");
+ panic("IBM MCA SCSI: Fatal errormessage from the subsystem!\n");
+ }
+
+ /* if no panic appeared, increase the interrupt-counter */
+ IBM_DS(host_index).total_interrupts++;
- /*if no command structure, just return, else clear cmd */
- cmd = ld[ldn].cmd;
- if (!cmd)
+ /*only for local checking phase */
+ if (local_checking_phase_flag(host_index))
+ {
+ stat_result(host_index) = cmd_result;
+ got_interrupt(host_index) = 1;
+ reset_status(host_index) = IM_RESET_FINISHED_OK;
+ last_scsi_command(host_index)[ldn] = NO_SCSI;
return;
- ld[ldn].cmd = 0;
-
+ }
+ /*handling of commands coming from upper level of scsi driver */
+ else
+ {
+ if (last_scsi_type(host_index)[ldn] == IM_IMM_CMD)
+ {
+ /*verify ldn, and may handle rare reset immediate command */
+ if ((reset_status(host_index) == IM_RESET_IN_PROGRESS)&&
+ (last_scsi_command(host_index)[ldn] == IM_RESET_IMM_CMD))
+ {
+ if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
+ {
+ disk_rw_in_progress = 0;
+ PS2_DISK_LED_OFF ();
+ reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+ }
+ else
+ {
+ /*reset disk led counter, turn off disk led */
+ disk_rw_in_progress = 0;
+ PS2_DISK_LED_OFF ();
+ reset_status(host_index) = IM_RESET_FINISHED_OK;
+ }
+ stat_result(host_index) = cmd_result;
+ last_scsi_command(host_index)[ldn] = NO_SCSI;
+ return;
+ }
+ else if (last_scsi_command(host_index)[ldn] == IM_ABORT_IMM_CMD)
+ { /* react on SCSI abort command */
+#ifdef IM_DEBUG_PROBE
+ printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n");
+#endif
+ disk_rw_in_progress = 0;
+ PS2_DISK_LED_OFF();
+ cmd = ld(host_index)[ldn].cmd;
+ if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
+ cmd->result = DID_NO_CONNECT << 16;
+ else
+ cmd->result = DID_ABORT << 16;
+ stat_result(host_index) = cmd_result;
+ last_scsi_command(host_index)[ldn] = NO_SCSI;
+ if (cmd->scsi_done)
+ (cmd->scsi_done) (cmd); /* should be the internal_done */
+ return;
+ }
+ else
+ {
+ disk_rw_in_progress = 0;
+ PS2_DISK_LED_OFF ();
+ reset_status(host_index) = IM_RESET_FINISHED_OK;
+ stat_result(host_index) = cmd_result;
+ last_scsi_command(host_index)[ldn] = NO_SCSI;
+ return;
+ }
+ }
+ last_scsi_command(host_index)[ldn] = NO_SCSI;
+ cmd = ld(host_index)[ldn].cmd;
+#ifdef IM_DEBUG_TIMEOUT
+ if (cmd)
+ {
+ if ((cmd->target == TIMEOUT_PUN)&&(cmd->lun == TIMEOUT_LUN))
+ {
+ printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n",
+ cmd->target, cmd->lun);
+ return;
+ }
+ }
+#endif
+ /*if no command structure, just return, else clear cmd */
+ if (!cmd)
+ return;
+ ld(host_index)[ldn].cmd = NULL;
+
#ifdef IM_DEBUG_INT
- printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n",
- cmd->cmnd[0], intr_reg,
- ld[ldn].tsb.dev_status, ld[ldn].tsb.cmd_status,
- ld[ldn].tsb.dev_error, ld[ldn].tsb.cmd_error);
+ printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n",
+ cmd->cmnd[0], intr_reg,
+ ld(host_index)[ldn].tsb.dev_status,
+ ld(host_index)[ldn].tsb.cmd_status,
+ ld(host_index)[ldn].tsb.dev_error,
+ ld(host_index)[ldn].tsb.cmd_error);
#endif
+
+ /*if this is end of media read/write, may turn off PS/2 disk led */
+ if ((ld(host_index)[ldn].device_type!=TYPE_NO_LUN)&&
+ (ld(host_index)[ldn].device_type!=TYPE_NO_DEVICE))
+ { /* only access this, if there was a valid device addressed */
+ switch (cmd->cmnd[0])
+ {
+ case READ_6:
+ case WRITE_6:
+ case READ_10:
+ case WRITE_10:
+ case READ_12:
+ case WRITE_12:
+ if (--disk_rw_in_progress == 0)
+ PS2_DISK_LED_OFF ();
+ }
+ }
- /*if this is end of media read/write, may turn off PS/2 disk led */
- if ((ld[ldn].device_type!=TYPE_NO_LUN)&&
- (ld[ldn].device_type!=TYPE_NO_DEVICE))
- { /* only access this, if there was a valid device addressed */
- switch (cmd->cmnd[0])
- {
- case READ_6:
- case WRITE_6:
- case READ_10:
- case WRITE_10:
- case READ_12:
- case WRITE_12:
- if (--disk_rw_in_progress == 0)
- PS2_DISK_LED_OFF ();
- }
- }
-
- /*write device status into cmd->result, and call done function */
- if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
- cmd->result = ld[ldn].tsb.dev_status & 0x1e;
- else
- cmd->result = 0;
- (cmd->scsi_done) (cmd);
- }
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-issue_cmd (struct Scsi_Host *shpnt, unsigned long cmd_reg,
- unsigned char attn_reg)
-{
- unsigned long flags;
- /*must wait for attention reg not busy */
- save_flags(flags);
- while (1)
- {
- cli ();
- if (!(inb (IM_STAT_REG) & IM_BUSY))
- break;
- restore_flags (flags);
- }
-
- /*write registers and enable system interrupts */
- outl (cmd_reg, IM_CMD_REG);
- outb (attn_reg, IM_ATTN_REG);
- restore_flags (flags);
+ /* IBM describes the status-mask to be 0x1e, but this is not conform
+ * with SCSI-defintion, I suppose, it is a printing error in the
+ * technical reference and assume as mask 0x3e. (ML) */
+ cmd->result = (ld(host_index)[ldn].tsb.dev_status & 0x3e);
+ /* write device status into cmd->result, and call done function */
+ if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
+ IBM_DS(host_index).total_errors++;
+ if (interror == NO_SCSI) /* unexpected interrupt :-( */
+ cmd->result |= DID_BAD_INTR << 16;
+ else
+ cmd->result |= DID_OK << 16;
+ (cmd->scsi_done) (cmd);
+ }
+ if (interror == NO_SCSI)
+ printk("IBM MCA SCSI: WARNING - Interrupt from non-pending SCSI-command!\n");
+ return;
}
/*--------------------------------------------------------------------*/
-static void
-internal_done (Scsi_Cmnd * cmd)
+static void issue_cmd (int host_index, unsigned long cmd_reg,
+ unsigned char attn_reg)
{
- cmd->SCp.Status++;
+ static unsigned long flags;
+ /* must wait for attention reg not busy */
+ while (1)
+ {
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&issue_lock, flags);
+#endif
+ if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
+ break;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&issue_lock, flags);
+#endif
+ }
+ /*write registers and enable system interrupts */
+ outl (cmd_reg, IM_CMD_REG(host_index));
+ outb (attn_reg, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&issue_lock, flags);
+#endif
}
/*--------------------------------------------------------------------*/
-static int ibmmca_getinfo (char *buf, int slot, void *dev)
+static void internal_done (Scsi_Cmnd * cmd)
{
- struct Scsi_Host *shpnt = dev;
- int len = 0;
-
- len += sprintf (buf + len, "Subsystem PUN: %d\n", subsystem_pun);
- len += sprintf (buf + len, "I/O base address: 0x%lx\n", IM_CMD_REG);
- return len;
+ cmd->SCp.Status++;
}
/*--------------------------------------------------------------------*/
/* SCSI-SCB-command for device_inquiry */
-static int device_inquiry(struct Scsi_Host *shpnt, int ldn, unsigned char *buf)
+static int device_inquiry(int host_index, int ldn)
{
- struct im_scb scb;
- struct im_tsb tsb;
- int retries;
-
- for (retries = 0; retries < 3; retries++)
- {
- /*fill scb with inquiry command */
- scb.command = IM_DEVICE_INQUIRY_CMD;
- scb.enable = IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
- scb.sys_buf_adr = virt_to_bus(buf);
- scb.sys_buf_length = 255;
- scb.tsb_adr = virt_to_bus(&tsb);
-
- /*issue scb to passed ldn, and busy wait for interrupt */
- got_interrupt = 0;
- issue_cmd (shpnt, virt_to_bus(&scb), IM_SCB | ldn);
- while (!got_interrupt)
- barrier ();
-
- /*if command succesful, break */
- if (stat_result == IM_SCB_CMD_COMPLETED)
- break;
- }
+ int retries;
+ Scsi_Cmnd cmd;
+ struct im_scb *scb;
+ struct im_tsb *tsb;
+ unsigned char *buf;
+
+ scb = &(ld(host_index)[ldn].scb);
+ tsb = &(ld(host_index)[ldn].tsb);
+ buf = (unsigned char *)(&(ld(host_index)[ldn].buf));
+ ld(host_index)[ldn].tsb.dev_status = 0; /* prepare stusblock */
+
+ if (bypass_controller)
+ { /* fill the commonly known field for device-inquiry SCSI cmnd */
+ cmd.cmd_len = 6;
+ memset (&(cmd.cmnd), 0x0, sizeof(char) * cmd.cmd_len);
+ cmd.cmnd[0] = INQUIRY; /* device inquiry */
+ cmd.cmnd[4] = 0xff; /* return buffer size = 255 */
+ }
+ for (retries = 0; retries < 3; retries++)
+ {
+ if (bypass_controller)
+ { /* bypass the hardware integrated command set */
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ scb->u1.scsi_cmd_length = cmd.cmd_len;
+ memcpy (scb->u2.scsi_command, &(cmd.cmnd), cmd.cmd_len);
+ last_scsi_command(host_index)[ldn] = INQUIRY;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
+ }
+ else
+ {
+ /*fill scb with inquiry command */
+ scb->command = IM_DEVICE_INQUIRY_CMD;
+ scb->enable = IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
+ }
+ scb->sys_buf_adr = virt_to_bus(buf);
+ scb->sys_buf_length = 0xff; /* maximum bufferlength gives max info */
+ scb->tsb_adr = virt_to_bus(tsb);
+
+ /*issue scb to passed ldn, and busy wait for interrupt */
+ got_interrupt(host_index) = 0;
+ issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+ while (!got_interrupt(host_index))
+ barrier ();
+
+ /*if command succesful, break */
+ if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)||
+ (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+ {
+ return 1;
+ }
+ }
+
+ /*if all three retries failed, return "no device at this ldn" */
+ if (retries >= 3)
+ return 0;
+ else
+ return 1;
+}
- /*if all three retries failed, return "no device at this ldn" */
- if (retries >= 3)
- return 0;
- else
- return 1;
+static int read_capacity(int host_index, int ldn)
+{
+ int retries;
+ Scsi_Cmnd cmd;
+ struct im_scb *scb;
+ struct im_tsb *tsb;
+ unsigned char *buf;
+
+ scb = &(ld(host_index)[ldn].scb);
+ tsb = &(ld(host_index)[ldn].tsb);
+ buf = (unsigned char *)(&(ld(host_index)[ldn].buf));
+ ld(host_index)[ldn].tsb.dev_status = 0;
+
+ if (bypass_controller)
+ { /* read capacity in commonly known default SCSI-format */
+ cmd.cmd_len = 10;
+ memset (&(cmd.cmnd), 0x0, sizeof(char) * cmd.cmd_len);
+ cmd.cmnd[0] = READ_CAPACITY; /* read capacity */
+ }
+ for (retries = 0; retries < 3; retries++)
+ {
+ /*fill scb with read capacity command */
+ if (bypass_controller)
+ { /* bypass the SCSI-command */
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL;
+ scb->u1.scsi_cmd_length = cmd.cmd_len;
+ memcpy (scb->u2.scsi_command, &(cmd.cmnd), cmd.cmd_len);
+ last_scsi_command(host_index)[ldn] = READ_CAPACITY;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
+ }
+ else
+ {
+ scb->command = IM_READ_CAPACITY_CMD;
+ scb->enable = IM_READ_CONTROL;
+ last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
+ }
+ scb->sys_buf_adr = virt_to_bus(buf);
+ scb->sys_buf_length = 8;
+ scb->tsb_adr = virt_to_bus(tsb);
+
+ /*issue scb to passed ldn, and busy wait for interrupt */
+ got_interrupt(host_index) = 0;
+ issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+ while (!got_interrupt(host_index))
+ barrier ();
+
+ /*if got capacity, get block length and return one device found */
+ if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)||
+ (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+ {
+ return 1;
+ }
+ }
+ /*if all three retries failed, return "no device at this ldn" */
+ if (retries >= 3)
+ return 0;
+ else
+ return 1;
}
/* SCSI-immediate-command for assign. This functions maps/unmaps specific
- ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the
- subsystem and for dynamical remapping od ldns. */
-static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun,
+ ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the
+ subsystem and for dynamical remapping od ldns. */
+static int immediate_assign(int host_index, unsigned int pun,
unsigned int lun, unsigned int ldn,
unsigned int operation)
{
int retries;
unsigned long imm_command;
-
+
for (retries=0; retries<3; retries ++)
- {
- imm_command = inl(IM_CMD_REG);
+ {
+ imm_command = inl(IM_CMD_REG(host_index));
imm_command &= (unsigned long)(0xF8000000); /* keep reserved bits */
imm_command |= (unsigned long)(IM_ASSIGN_IMM_CMD);
imm_command |= (unsigned long)((lun & 7) << 24);
@@ -1101,14 +949,64 @@ static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun,
imm_command |= (unsigned long)((pun & 7) << 20);
imm_command |= (unsigned long)((ldn & 15) << 16);
- got_interrupt = 0;
- issue_cmd (shpnt, (unsigned long)(imm_command), IM_IMM_CMD | 0xf);
- while (!got_interrupt)
- barrier ();
-
+ last_scsi_command(host_index)[0xf] = IM_ASSIGN_IMM_CMD;
+ last_scsi_type(host_index)[0xf] = IM_IMM_CMD;
+ got_interrupt(host_index) = 0;
+ issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | 0xf);
+ while (!got_interrupt(host_index))
+ barrier ();
+
+ /*if command succesful, break */
+ if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+ {
+ return 1;
+ }
+ }
+
+ if (retries >= 3)
+ return 0;
+ else
+ return 1;
+}
+
+#ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
+static int immediate_reset(int host_index, unsigned int ldn)
+{
+ int retries;
+ int ticks;
+ unsigned long imm_command;
+
+ for (retries=0; retries<3; retries ++)
+ {
+ imm_command = inl(IM_CMD_REG(host_index));
+ imm_command &= (unsigned long)(0xFFFF0000); /* keep reserved bits */
+ imm_command |= (unsigned long)(IM_RESET_IMM_CMD);
+ last_scsi_command(host_index)[ldn] = IM_RESET_IMM_CMD;
+ last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
+
+ got_interrupt(host_index) = 0;
+ reset_status(host_index) = IM_RESET_IN_PROGRESS;
+ issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | ldn);
+ ticks = IM_RESET_DELAY*HZ;
+ while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks)
+ {
+ mdelay(1+999/HZ);
+ barrier();
+ }
+ /* if reset did not complete, just claim */
+ if (!ticks)
+ {
+ printk("IBM MCA SCSI: reset did not complete within %d seconds.\n",
+ IM_RESET_DELAY);
+ reset_status(host_index) = IM_RESET_FINISHED_OK;
+ /* did not work, finish */
+ return 1;
+ }
/*if command succesful, break */
- if (stat_result == IM_IMMEDIATE_CMD_COMPLETED)
- break;
+ if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+ {
+ return 1;
+ }
}
if (retries >= 3)
@@ -1116,24 +1014,25 @@ static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun,
else
return 1;
}
+#endif
/* type-interpreter for physical device numbers */
static char *ti_p(int value)
{
switch (value)
{
- case TYPE_IBM_SCSI_ADAPTER: return("A"); break;
- case TYPE_DISK: return("D"); break;
- case TYPE_TAPE: return("T"); break;
- case TYPE_PROCESSOR: return("P"); break;
- case TYPE_WORM: return("W"); break;
- case TYPE_ROM: return("R"); break;
- case TYPE_SCANNER: return("S"); break;
- case TYPE_MOD: return("M"); break;
- case TYPE_MEDIUM_CHANGER: return("C"); break;
- case TYPE_NO_LUN: return("+"); break; /* show NO_LUN */
- case TYPE_NO_DEVICE:
- default: return("-"); break;
+ case TYPE_IBM_SCSI_ADAPTER: return("A"); break;
+ case TYPE_DISK: return("D"); break;
+ case TYPE_TAPE: return("T"); break;
+ case TYPE_PROCESSOR: return("P"); break;
+ case TYPE_WORM: return("W"); break;
+ case TYPE_ROM: return("R"); break;
+ case TYPE_SCANNER: return("S"); break;
+ case TYPE_MOD: return("M"); break;
+ case TYPE_MEDIUM_CHANGER: return("C"); break;
+ case TYPE_NO_LUN: return("+"); break; /* show NO_LUN */
+ case TYPE_NO_DEVICE:
+ default: return("-"); break;
}
return("-");
}
@@ -1141,9 +1040,9 @@ static char *ti_p(int value)
/* interpreter for logical device numbers (ldn) */
static char *ti_l(int value)
{
- const char hex[16] = ("0123456789abcdef");
+ const char hex[16] = "0123456789abcdef";
static char answer[2];
-
+
answer[1] = (char)(0x0);
if (value<=MAX_LOG_DEV)
answer[0] = hex[value];
@@ -1154,182 +1053,181 @@ static char *ti_l(int value)
}
/*
- The following routine probes the SCSI-devices in four steps:
- 1. The current ldn -> pun,lun mapping is removed on the SCSI-adapter.
- 2. ldn 0 is used to go through all possible combinations of pun,lun and
- a device_inquiry is done to fiddle out whether there is a device
- responding or not. This physical map is stored in get_scsi[][].
- 3. The 15 available ldns (0-14) are mapped to existing pun,lun.
- If there are more devices than ldns, it stops at 14 for the boot
- time. Dynamical remapping will be done in ibmmca_queuecommand.
- 4. If there are less than 15 valid pun,lun, the remaining ldns are
- mapped to NON-existing pun,lun to satisfy the adapter. Information
- about pun,lun -> ldn is stored as before in get_ldn[][].
- This method leads to the result, that the SCSI-pun,lun shown to Linux
- mid-level- and higher-level-drivers is exactly corresponding to the
- physical reality on the SCSI-bus. Therefore, it is possible that users
- of older releases of this driver have to rewrite their fstab-file, because
- the /dev/sdXXX could have changed due to the right pun,lun report, now.
- The assignment of ALL ldns avoids dynamical remapping by the adapter
- itself.
+ The following routine probes the SCSI-devices in four steps:
+ 1. The current ldn -> pun,lun mapping is removed on the SCSI-adapter.
+ 2. ldn 0 is used to go through all possible combinations of pun,lun and
+ a device_inquiry is done to fiddle out whether there is a device
+ responding or not. This physical map is stored in get_scsi[][].
+ 3. The 15 available ldns (0-14) are mapped to existing pun,lun.
+ If there are more devices than ldns, it stops at 14 for the boot
+ time. Dynamical remapping will be done in ibmmca_queuecommand.
+ 4. If there are less than 15 valid pun,lun, the remaining ldns are
+ mapped to NON-existing pun,lun to satisfy the adapter. Information
+ about pun,lun -> ldn is stored as before in get_ldn[][].
+ This method leads to the result, that the SCSI-pun,lun shown to Linux
+ mid-level- and higher-level-drivers is exactly corresponding to the
+ physical reality on the SCSI-bus. Therefore, it is possible that users
+ of older releases of this driver have to rewrite their fstab-file, because
+ the /dev/sdXXX could have changed due to the right pun,lun report, now.
+ The assignment of ALL ldns avoids dynamical remapping by the adapter
+ itself.
*/
-static void check_devices (struct Scsi_Host *shpnt)
+static void check_devices (int host_index)
{
- int id, lun, ldn;
- unsigned char buf[256];
- int count_devices = 0; /* local counter for connected device */
-
- /* assign default values to certain variables */
-
- IBM_DS.dyn_flag = 0; /* normally no need for dynamical ldn management */
- next_ldn = 7; /* next ldn to be assigned is 7, because 0-6 is 'hardwired'*/
- last_scsi_command = 0; /* emptify last SCSI-command storage */
-
- /* initialize the very important driver-informational arrays/structs */
- memset (ld, 0, sizeof ld);
- memset (get_ldn, TYPE_NO_DEVICE, sizeof get_ldn); /* this is essential ! */
- memset (get_scsi, TYPE_NO_DEVICE, sizeof get_scsi); /* this is essential ! */
-
- for (lun=0; lun<8; lun++) /* mark the adapter at its pun on all luns*/
- {
- get_scsi[subsystem_pun][lun] = TYPE_IBM_SCSI_ADAPTER;
- get_ldn[subsystem_pun][lun] = MAX_LOG_DEV; /* make sure, the subsystem
- ldn is active for all
- luns. */
- }
-
- /* STEP 1: */
- printk("IBM MCA SCSI: Removing current logical SCSI-device mapping.");
- for (ldn=0; ldn<MAX_LOG_DEV; ldn++)
- {
+ int id, lun, ldn, ticks;
+ int count_devices; /* local counter for connected device */
+
+ /* assign default values to certain variables */
+
+ ticks = 0;
+ count_devices = 0;
+ IBM_DS(host_index).dyn_flag = 0; /* normally no need for dynamical ldn management */
+ IBM_DS(host_index).total_errors = 0; /* set errorcounter to 0 */
+ next_ldn(host_index) = 7; /* next ldn to be assigned is 7, because 0-6 is 'hardwired'*/
+ for (ldn=0; ldn<=MAX_LOG_DEV; ldn++)
+ {
+ last_scsi_command(host_index)[ldn] = NO_SCSI; /* emptify last SCSI-command storage */
+ last_scsi_type(host_index)[ldn] = 0;
+ }
+
+ /* initialize the very important driver-informational arrays/structs */
+ memset (ld(host_index), 0,
+ sizeof(ld(host_index)));
+ memset (get_ldn(host_index), TYPE_NO_DEVICE,
+ sizeof(get_ldn(host_index))); /* this is essential ! */
+ memset (get_scsi(host_index), TYPE_NO_DEVICE,
+ sizeof(get_scsi(host_index))); /* this is essential ! */
+
+ for (lun=0; lun<8; lun++) /* mark the adapter at its pun on all luns*/
+ {
+ get_scsi(host_index)[subsystem_pun(host_index)][lun] = TYPE_IBM_SCSI_ADAPTER;
+ get_ldn(host_index)[subsystem_pun(host_index)][lun] = MAX_LOG_DEV; /* make sure, the subsystem
+ ldn is active for all
+ luns. */
+ }
+
+ /* STEP 1: */
#ifdef IM_DEBUG_PROBE
- printk(".");
+ printk("IBM MCA SCSI: Current SCSI-host index: %d\n",host_index);
#endif
- immediate_assign(shpnt,0,0,ldn,REMOVE_LDN); /* remove ldn (wherever)*/
- }
-
- lun = 0; /* default lun is 0 */
+ printk("IBM MCA SCSI: Removing default logical SCSI-device mapping.");
+ for (ldn=0; ldn<MAX_LOG_DEV; ldn++)
+ {
+#ifdef IM_DEBUG_PROBE
+ printk(".");
+#endif
+ immediate_assign(host_index,0,0,ldn,REMOVE_LDN); /* remove ldn (wherever)*/
+ }
- /* STEP 2: */
- printk("\nIBM MCA SCSI: Probing SCSI-devices.");
- for (id=0; id<8; id++)
+ lun = 0; /* default lun is 0 */
+
+ /* STEP 2: */
+ printk("\nIBM MCA SCSI: Probing SCSI-devices.");
+ for (id=0; id<8; id++)
#ifdef CONFIG_SCSI_MULTI_LUN
- for (lun=0; lun<8; lun++)
+ for (lun=0; lun<8; lun++)
#endif
- {
+ {
#ifdef IM_DEBUG_PROBE
printk(".");
#endif
- if (id != subsystem_pun)
+ if (id != subsystem_pun(host_index))
{ /* if pun is not the adapter: */
- immediate_assign(shpnt,id,lun,0,SET_LDN); /*set ldn=0 to pun,lun*/
- if (device_inquiry(shpnt, 0, buf)) /* probe device */
- {
- get_scsi[id][lun]=(unsigned char)buf[0]; /* entry, even
- for NO_LUN */
- if (buf[0] != TYPE_NO_LUN)
- count_devices++; /* a existing device is found */
- }
- immediate_assign(shpnt,id,lun,0,REMOVE_LDN); /* remove ldn */
+ /*set ldn=0 to pun,lun*/
+ immediate_assign(host_index,id,lun,PROBE_LDN,SET_LDN);
+ if (device_inquiry(host_index, PROBE_LDN)) /* probe device */
+ {
+ get_scsi(host_index)[id][lun]=
+ (unsigned char)(ld(host_index)[PROBE_LDN].buf[0]);
+ /* entry, even for NO_LUN */
+ if (ld(host_index)[PROBE_LDN].buf[0] != TYPE_NO_LUN)
+ count_devices++; /* a existing device is found */
+ }
+ /* remove ldn */
+ immediate_assign(host_index,id,lun,PROBE_LDN,REMOVE_LDN);
}
- }
-
- /* STEP 3: */
- printk("\nIBM MCA SCSI: Mapping SCSI-devices.");
+ }
+
+ /* STEP 3: */
+ printk("\nIBM MCA SCSI: Mapping SCSI-devices.");
+
+ ldn = 0;
+ lun = 0;
- ldn = 0;
- lun = 0;
-
#ifdef CONFIG_SCSI_MULTI_LUN
- for (lun=0; lun<8 && ldn<MAX_LOG_DEV; lun++)
+ for (lun=0; lun<8 && ldn<MAX_LOG_DEV; lun++)
#endif
- for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
- {
+ for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
+ {
#ifdef IM_DEBUG_PROBE
printk(".");
#endif
- if (id != subsystem_pun)
+ if (id != subsystem_pun(host_index))
{
- if (get_scsi[id][lun] != TYPE_NO_LUN &&
- get_scsi[id][lun] != TYPE_NO_DEVICE)
- {
- /* Only map if accepted type. Always enter for
+ if (get_scsi(host_index)[id][lun] != TYPE_NO_LUN &&
+ get_scsi(host_index)[id][lun] != TYPE_NO_DEVICE)
+ {
+ /* Only map if accepted type. Always enter for
lun == 0 to get no gaps into ldn-mapping for ldn<7. */
- immediate_assign(shpnt,id,lun,ldn,SET_LDN);
- get_ldn[id][lun]=ldn; /* map ldn */
- if (device_exists (shpnt, ldn, &ld[ldn].block_length,
- &ld[ldn].device_type))
- {
+ immediate_assign(host_index,id,lun,ldn,SET_LDN);
+ get_ldn(host_index)[id][lun]=ldn; /* map ldn */
+ if (device_exists (host_index, ldn,
+ &ld(host_index)[ldn].block_length,
+ &ld(host_index)[ldn].device_type))
+ {
#ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
- int ticks;
- printk("(resetting)");
- ticks = IM_RESET_DELAY*HZ;
- reset_status = IM_RESET_IN_PROGRESS;
- issue_cmd (shpnt, IM_RESET_IMM_CMD, IM_IMM_CMD | ldn);
- while (reset_status == IM_RESET_IN_PROGRESS && --ticks)
- {
- mdelay(1+999/HZ);
- barrier();
- }
- /* if reset did not complete, just claim */
- if (!ticks)
- {
- printk("IBM MCA SCSI: reset did not complete within %d seconds.\n",
- IM_RESET_DELAY);
- reset_status = IM_RESET_FINISHED_OK;
- /* did not work, finish */
- }
+ printk("resetting device at ldn=%x ... ",ldn);
+ immediate_reset(host_index,ldn);
#endif
- ldn++;
- }
- else
- {
- /* device vanished, probably because we don't know how to
- * handle it or because it has problems */
- if (lun > 0)
- {
- /* remove mapping */
- get_ldn[id][lun]=TYPE_NO_DEVICE;
- immediate_assign(shpnt,0,0,ldn,REMOVE_LDN);
- }
- else ldn++;
- }
- }
- else if (lun == 0)
- {
- /* map lun == 0, even if no device exists */
- immediate_assign(shpnt,id,lun,ldn,SET_LDN);
- get_ldn[id][lun]=ldn; /* map ldn */
- ldn++;
- }
+ ldn++;
+ }
+ else
+ {
+ /* device vanished, probably because we don't know how to
+ * handle it or because it has problems */
+ if (lun > 0)
+ {
+ /* remove mapping */
+ get_ldn(host_index)[id][lun]=TYPE_NO_DEVICE;
+ immediate_assign(host_index,0,0,ldn,REMOVE_LDN);
+ }
+ else ldn++;
+ }
+ }
+ else if (lun == 0)
+ {
+ /* map lun == 0, even if no device exists */
+ immediate_assign(host_index,id,lun,ldn,SET_LDN);
+ get_ldn(host_index)[id][lun]=ldn; /* map ldn */
+ ldn++;
+ }
}
- }
-
+ }
+
/* STEP 4: */
/* map remaining ldns to non-existing devices */
for (lun=1; lun<8 && ldn<MAX_LOG_DEV; lun++)
for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
{
- if (get_scsi[id][lun] == TYPE_NO_LUN ||
- get_scsi[id][lun] == TYPE_NO_DEVICE)
+ if (get_scsi(host_index)[id][lun] == TYPE_NO_LUN ||
+ get_scsi(host_index)[id][lun] == TYPE_NO_DEVICE)
{
/* Map remaining ldns only to NON-existing pun,lun
- combinations to make sure an inquiry will fail.
- For MULTI_LUN, it is needed to avoid adapter autonome
- SCSI-remapping. */
- immediate_assign(shpnt,id,lun,ldn,SET_LDN);
- get_ldn[id][lun]=ldn;
+ combinations to make sure an inquiry will fail.
+ For MULTI_LUN, it is needed to avoid adapter autonome
+ SCSI-remapping. */
+ immediate_assign(host_index,id,lun,ldn,SET_LDN);
+ get_ldn(host_index)[id][lun]=ldn;
ldn++;
}
}
-
+
printk("\n");
-#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- printk("IBM MCA SCSI: SCSI-access-order: IBM/ANSI.\n");
-#else
- printk("IBM MCA SCSI: SCSI-access-order: Linux.\n");
-#endif
+ if (ibm_ansi_order)
+ printk("IBM MCA SCSI: Device order: IBM/ANSI (pun=7 is first).\n");
+ else
+ printk("IBM MCA SCSI: Device order: New Industry Standard (pun=0 is first).\n");
#ifdef IM_DEBUG_PROBE
/* Show the physical and logical mapping during boot. */
@@ -1338,336 +1236,525 @@ static void check_devices (struct Scsi_Host *shpnt)
printk("ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n");
for (id=0; id<8; id++)
{
- printk("%2d %2s %2s %2s %2s %2s %2s %2s %2s",
- id, ti_p(get_scsi[id][0]), ti_p(get_scsi[id][1]),
- ti_p(get_scsi[id][2]), ti_p(get_scsi[id][3]),
- ti_p(get_scsi[id][4]), ti_p(get_scsi[id][5]),
- ti_p(get_scsi[id][6]), ti_p(get_scsi[id][7]));
-
- printk(" %2d ",id);
+ printk("%2d ",id);
+ for (lun=0; lun<8; lun++)
+ printk("%2s ",ti_p(get_scsi(host_index)[id][lun]));
+ printk(" %2d ",id);
for (lun=0; lun<8; lun++)
- printk("%2s ",ti_l(get_ldn[id][lun]));
+ printk("%2s ",ti_l(get_ldn(host_index)[id][lun]));
printk("\n");
}
#endif
-
+
/* assign total number of found SCSI-devices to the statistics struct */
- IBM_DS.total_scsi_devices = count_devices;
-
+ IBM_DS(host_index).total_scsi_devices = count_devices;
+
/* decide for output in /proc-filesystem, if the configuration of
- SCSI-devices makes dynamical reassignment of devices necessary */
+ SCSI-devices makes dynamical reassignment of devices necessary */
if (count_devices>=MAX_LOG_DEV)
- IBM_DS.dyn_flag = 1; /* dynamical assignment is necessary */
+ IBM_DS(host_index).dyn_flag = 1; /* dynamical assignment is necessary */
else
- IBM_DS.dyn_flag = 0; /* dynamical assignment is not necessary */
-
+ IBM_DS(host_index).dyn_flag = 0; /* dynamical assignment is not necessary */
+
/* If no SCSI-devices are assigned, return 1 in order to cause message. */
if (ldn == 0)
- printk("IBM MCA SCSI: Warning: No SCSI-devices found/assignable!\n");
-
- /* reset the counters for statistics on the current adapter */
- IBM_DS.total_accesses = 0;
- IBM_DS.total_interrupts = 0;
- IBM_DS.dynamical_assignments = 0;
- memset (IBM_DS.ldn_access, 0x0, sizeof (IBM_DS.ldn_access));
- memset (IBM_DS.ldn_read_access, 0x0, sizeof (IBM_DS.ldn_read_access));
- memset (IBM_DS.ldn_write_access, 0x0, sizeof (IBM_DS.ldn_write_access));
- memset (IBM_DS.ldn_inquiry_access, 0x0, sizeof (IBM_DS.ldn_inquiry_access));
- memset (IBM_DS.ldn_modeselect_access, 0x0, sizeof (IBM_DS.ldn_modeselect_access));
- memset (IBM_DS.ldn_assignments, 0x0, sizeof (IBM_DS.ldn_assignments));
-
- return;
+ printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n");
+
+ /* reset the counters for statistics on the current adapter */
+ IBM_DS(host_index).total_accesses = 0;
+ IBM_DS(host_index).total_interrupts = 0;
+ IBM_DS(host_index).dynamical_assignments = 0;
+ memset (IBM_DS(host_index).ldn_access, 0x0,
+ sizeof (IBM_DS(host_index).ldn_access));
+ memset (IBM_DS(host_index).ldn_read_access, 0x0,
+ sizeof (IBM_DS(host_index).ldn_read_access));
+ memset (IBM_DS(host_index).ldn_write_access, 0x0,
+ sizeof (IBM_DS(host_index).ldn_write_access));
+ memset (IBM_DS(host_index).ldn_inquiry_access, 0x0,
+ sizeof (IBM_DS(host_index).ldn_inquiry_access));
+ memset (IBM_DS(host_index).ldn_modeselect_access, 0x0,
+ sizeof (IBM_DS(host_index).ldn_modeselect_access));
+ memset (IBM_DS(host_index).ldn_assignments, 0x0,
+ sizeof (IBM_DS(host_index).ldn_assignments));
+
+ return;
}
/*--------------------------------------------------------------------*/
-static int
-device_exists (struct Scsi_Host *shpnt, int ldn, int *block_length,
- int *device_type)
+static int device_exists (int host_index, int ldn, int *block_length,
+ int *device_type)
{
- struct im_scb scb;
- struct im_tsb tsb;
- unsigned char buf[256];
- int retries;
-
- /* if no valid device found, return immediately with 0 */
- if (!(device_inquiry(shpnt, ldn, buf))) return 0;
-
- /*if device is CD_ROM, assume block size 2048 and return */
- if (buf[0] == TYPE_ROM)
- {
- *device_type = TYPE_ROM;
- *block_length = 2048; /* (standard blocksize for yellow-/red-book) */
- return 1;
- }
-
- if (buf[0] == TYPE_WORM) /* CD-burner, WORM, Linux handles this as CD-ROM
- therefore, the block_length is also 2048. */
- {
- *device_type = TYPE_WORM;
- *block_length = 2048;
- return 1;
- }
-
- /* if device is disk, use "read capacity" to find its block size */
- if (buf[0] == TYPE_DISK)
- {
- *device_type = TYPE_DISK;
-
- for (retries = 0; retries < 3; retries++)
- {
- /*fill scb with read capacity command */
- scb.command = IM_READ_CAPACITY_CMD;
- scb.enable = IM_READ_CONTROL;
- scb.sys_buf_adr = virt_to_bus(buf);
- scb.sys_buf_length = 8;
- scb.tsb_adr = virt_to_bus(&tsb);
-
- /*issue scb to passed ldn, and busy wait for interrupt */
- got_interrupt = 0;
- issue_cmd (shpnt, virt_to_bus(&scb), IM_SCB | ldn);
- while (!got_interrupt)
- barrier ();
-
- /*if got capacity, get block length and return one device found */
- if (stat_result == IM_SCB_CMD_COMPLETED)
- {
- *block_length = buf[7] + (buf[6] << 8) + (buf[5] << 16) + (buf[4] << 24);
- return 1;
- }
- }
-
- /*if all three retries failed, return "no device at this ldn" */
- if (retries >= 3)
- return 0;
- }
-
- /* if this is a magneto-optical drive, treat it like a harddisk */
- if (buf[0] == TYPE_MOD)
- {
- *device_type = TYPE_MOD;
-
- for (retries = 0; retries < 3; retries++)
- {
- /*fill scb with read capacity command */
- scb.command = IM_READ_CAPACITY_CMD;
- scb.enable = IM_READ_CONTROL;
- scb.sys_buf_adr = virt_to_bus(buf);
- scb.sys_buf_length = 8;
- scb.tsb_adr = virt_to_bus(&tsb);
-
- /*issue scb to passed ldn, and busy wait for interrupt */
- got_interrupt = 0;
- issue_cmd (shpnt, virt_to_bus(&scb), IM_SCB | ldn);
- while (!got_interrupt)
- barrier ();
-
- /*if got capacity, get block length and return one device found */
- if (stat_result == IM_SCB_CMD_COMPLETED)
- {
- *block_length = buf[7] + (buf[6] << 8) + (buf[5] << 16) + (buf[4] << 24);
- return 1;
- }
- }
-
- /*if all three retries failed, return "no device at this ldn" */
- if (retries >= 3)
- return 0;
- }
-
- if (buf[0] == TYPE_TAPE) /* TAPE-device found */
- {
- *device_type = TYPE_TAPE;
- *block_length = 0; /* not in use (setting by mt and mtst in op.) */
- return 1;
- }
-
- if (buf[0] == TYPE_PROCESSOR) /* HP-Scanners, diverse SCSI-processing units*/
- {
- *device_type = TYPE_PROCESSOR;
- *block_length = 0; /* they set their stuff on drivers */
- return 1;
- }
-
- if (buf[0] == TYPE_SCANNER) /* other SCSI-scanners */
- {
- *device_type = TYPE_SCANNER;
- *block_length = 0; /* they set their stuff on drivers */
- return 1;
- }
-
- if (buf[0] == TYPE_MEDIUM_CHANGER) /* Medium-Changer */
- {
- *device_type = TYPE_MEDIUM_CHANGER;
- *block_length = 0; /* One never knows, what to expect on a medium
- changer device. */
- return 1;
- }
+ unsigned char *buf;
+
+ /* if no valid device found, return immediately with 0 */
+ if (!(device_inquiry(host_index, ldn)))
+ return 0;
+
+ buf = (unsigned char *)(&(ld(host_index)[ldn].buf));
- /* Up to now, no SCSI-devices that are known up to kernel 2.1.31 are
- ignored! MO-drives are now supported and treated as harddisk. */
- return 0;
+ /*if device is CD_ROM, assume block size 2048 and return */
+ if (*buf == TYPE_ROM)
+ {
+ *device_type = TYPE_ROM;
+ *block_length = 2048; /* (standard blocksize for yellow-/red-book) */
+ return 1;
+ }
+
+ if (*buf == TYPE_WORM) /* CD-burner, WORM, Linux handles this as CD-ROM
+ therefore, the block_length is also 2048. */
+ {
+ *device_type = TYPE_WORM;
+ *block_length = 2048;
+ return 1;
+ }
+
+ /* if device is disk, use "read capacity" to find its block size */
+ if (*buf == TYPE_DISK)
+ {
+ *device_type = TYPE_DISK;
+ if (read_capacity( host_index, ldn))
+ {
+ *block_length = *(buf+7) + (*(buf+6) << 8) +
+ (*(buf+5) << 16) + (*(buf+4) << 24);
+ return 1;
+ }
+ else
+ return 0;
+ }
+
+ /* if this is a magneto-optical drive, treat it like a harddisk */
+ if (*buf == TYPE_MOD)
+ {
+ *device_type = TYPE_MOD;
+ if (read_capacity( host_index, ldn))
+ {
+ *block_length = *(buf+7) + (*(buf+6) << 8) +
+ (*(buf+5) << 16) + (*(buf+4) << 24);
+ return 1;
+ }
+ else
+ return 0;
+ }
+
+ if (*buf == TYPE_TAPE) /* TAPE-device found */
+ {
+ *device_type = TYPE_TAPE;
+ *block_length = 0; /* not in use (setting by mt and mtst in op.) */
+ return 1;
+ }
+
+ if (*buf == TYPE_PROCESSOR) /* HP-Scanners, diverse SCSI-processing units*/
+ {
+ *device_type = TYPE_PROCESSOR;
+ *block_length = 0; /* they set their stuff on drivers */
+ return 1;
+ }
+
+ if (*buf == TYPE_SCANNER) /* other SCSI-scanners */
+ {
+ *device_type = TYPE_SCANNER;
+ *block_length = 0; /* they set their stuff on drivers */
+ return 1;
+ }
+
+ if (*buf == TYPE_MEDIUM_CHANGER) /* Medium-Changer */
+ {
+ *device_type = TYPE_MEDIUM_CHANGER;
+ *block_length = 0; /* One never knows, what to expect on a medium
+ changer device. */
+ return 1;
+ }
+
+ /* Up to now, no SCSI-devices that are known up to kernel 2.1.31 are
+ ignored! MO-drives are now supported and treated as harddisk. */
+ return 0;
}
/*--------------------------------------------------------------------*/
-
+
#ifdef CONFIG_SCSI_IBMMCA
-void
-ibmmca_scsi_setup (char *str, int *ints)
+void ibmmca_scsi_setup (char *str, int *ints)
{
- if( str && !strcmp( str, "display" ) ) {
- use_display = 1;
- } else if( ints ) {
- int i;
- for (i = 0; i < IM_MAX_HOSTS && 2*i+2 < ints[0]; i++) {
- io_port[i] = ints[2*i+2];
- scsi_id[i] = ints[2*i+2];
- }
- }
+ int i, j, io_base, id_base;
+ char *token;
+
+ io_base = 0;
+ id_base = 0;
+
+ if (str)
+ {
+ token = strtok(str,",");
+ j = 0;
+ while (token)
+ {
+ if (!strcmp(token,"display"))
+ {
+ use_display = 1;
+ }
+ if (!strcmp(token,"adisplay"))
+ {
+ use_adisplay = 1;
+ }
+ if (!strcmp(token,"bypass"))
+ {
+ bypass_controller = 1;
+ }
+ if (!strcmp(token,"normal"))
+ {
+ ibm_ansi_order = 0;
+ }
+ if (!strcmp(token,"ansi"))
+ {
+ ibm_ansi_order = 1;
+ }
+ if ( (*token == '-') || (isdigit(*token)) )
+ {
+ if (!(j%2) && (io_base < IM_MAX_HOSTS))
+ {
+ io_port[io_base++] = simple_strtoul(token,NULL,0);
+ }
+ if ((j%2) && (id_base < IM_MAX_HOSTS))
+ {
+ scsi_id[id_base++] = simple_strtoul(token,NULL,0);
+ }
+ j++;
+ }
+ token = strtok(NULL,",");
+ }
+ }
+ else if (ints)
+ {
+ for (i = 0; i < IM_MAX_HOSTS && 2*i+2 < ints[0]; i++)
+ {
+ io_port[i] = ints[2*i+2];
+ scsi_id[i] = ints[2*i+2];
+ }
+ }
+ return;
}
#endif
/*--------------------------------------------------------------------*/
-int
-ibmmca_detect (Scsi_Host_Template * template)
+static int ibmmca_getinfo (char *buf, int slot, void *dev)
{
- struct Scsi_Host *shpnt;
- int port, id, i, list_size, slot;
- unsigned pos2, pos3;
-
- /* if this is not MCA machine, return "nothing found" */
- if (!MCA_bus)
- return 0;
-
- /* get interrupt request level */
- if (request_irq (IM_IRQ, do_interrupt_handler, SA_SHIRQ, "ibmmca", hosts))
- {
- printk("IBM MCA SCSI: Unable to get IRQ %d.\n", IM_IRQ);
- return 0;
- }
-
- /* if ibmmcascsi setup option was passed to kernel, return "found" */
- for (i = 0; i < IM_MAX_HOSTS; i++)
- if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8)
- {
- printk("IBM MCA SCSI: forced detection, io=0x%x, scsi id=%d.\n",
- io_port[i], scsi_id[i]);
- ibmmca_register(template, io_port[i], scsi_id[i]);
- }
- if (found) return found;
-
- /*
- * Patched by ZP Gu to work with the 9556 as well; the 9556 has
- * pos2 = 05, but it should be 00, as it should be interfaced
- * via port = 0x3540.
- */
-
- /* first look for the SCSI integrated on the motherboard */
- pos2 = mca_read_stored_pos(MCA_INTEGSCSI, 2);
-// if (pos2 != 0xff) {
- if ((pos2 & 1) == 0) {
- port = IM_IO_PORT + ((pos2 & 0x0e) << 2);
- } else {
- port = IM_IO_PORT;
- }
- pos3 = mca_read_stored_pos(MCA_INTEGSCSI, 3);
- id = (pos3 & 0xe0) >> 5;
-
- printk("IBM MCA SCSI: integrated SCSI found, io=0x%x, scsi id=%d.\n",
- port, id);
- if ((shpnt = ibmmca_register(template, port, id)))
- {
- mca_set_adapter_name(MCA_INTEGSCSI, "PS/2 Integrated SCSI");
- mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo,
- shpnt);
- }
-// }
-
- /* now look for other adapters */
- list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct);
- for (i = 0; i < list_size; i++)
- {
- slot = 0;
- while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot))
- != MCA_NOTFOUND)
- {
- pos2 = mca_read_stored_pos(slot, 2);
- pos3 = mca_read_stored_pos(slot, 3);
- port = IM_IO_PORT + ((pos2 & 0x0e) << 2);
- id = (pos3 & 0xe0) >> 5;
- printk ("IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d.\n",
- subsys_list[i].description, slot + 1, port, id);
- if ((shpnt = ibmmca_register(template, port, id)))
- {
- mca_set_adapter_name (slot, subsys_list[i].description);
- mca_set_adapter_procfn (slot, (MCA_ProcFn) ibmmca_getinfo,
- shpnt);
- }
- slot++;
- }
- }
-
- if (!found) {
- free_irq (IM_IRQ, hosts);
- printk("IBM MCA SCSI: No adapter attached.\n");
- }
-
- return found;
+ struct Scsi_Host *shpnt;
+ int len, special;
+ unsigned int pos2, pos3;
+ static unsigned long flags;
+
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&info_lock, flags);
+#endif
+
+ shpnt = dev; /* assign host-structure to local pointer */
+ len = 0; /* set filled text-buffer index to 0 */
+ /* get the _special contents of the hostdata structure */
+ special = ((struct ibmmca_hostdata *)shpnt->hostdata)->_special;
+ pos2 = ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2;
+ pos3 = ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3;
+
+ if (special == FORCED_DETECTION) /* forced detection */
+ {
+ len += sprintf (buf + len, "Adapter cathegory: forced detected\n");
+ len += sprintf(buf + len, "***************************************\n");
+ len += sprintf(buf + len, "*** Forced detected SCSI Adapter ***\n");
+ len += sprintf(buf + len, "*** No chip-information available ***\n");
+ len += sprintf(buf + len, "***************************************\n");
+ }
+ else if (special == INTEGRATED_SCSI)
+ { /* if the integrated subsystem has been found automatically: */
+ len += sprintf (buf + len, "Adapter cathegory: integrated\n");
+ len += sprintf (buf + len, "Chip revision level: %d\n",
+ ((pos2 & 0xf0) >> 4));
+ len += sprintf (buf + len, "Chip status: %s\n",
+ (pos2 & 1) ? "enabled" : "disabled");
+ len += sprintf (buf + len, "8 kByte NVRAM status: %s\n",
+ (pos2 & 2) ? "locked" : "accessible");
+ }
+ else if ((special>=0)&&
+ (special<(sizeof(subsys_list)/sizeof(struct subsys_list_struct))))
+ { /* if the subsystem is a slot adapter */
+ len += sprintf (buf + len, "Adapter cathegory: slot-card\n");
+ len += sprintf (buf + len, "Chip revision level: %d\n",
+ ((pos2 & 0xf0) >> 4));
+ len += sprintf (buf + len, "Chip status: %s\n",
+ (pos2 & 1) ? "enabled" : "disabled");
+ len += sprintf (buf + len, "Port offset: 0x%x\n",
+ ((pos2 & 0x0e) << 2));
+ }
+ else
+ {
+ len += sprintf (buf + len, "Adapter cathegory: unknown\n");
+ }
+ /* common subsystem information to write to the slotn file */
+ len += sprintf (buf + len, "Subsystem PUN: %d\n", shpnt->this_id);
+ len += sprintf (buf + len, "I/O base address range: 0x%x-0x%x",
+ (unsigned int)(shpnt->io_port),
+ (unsigned int)(shpnt->io_port+7));
+ /* Now make sure, the bufferlength is devideable by 4 to avoid
+ * paging problems of the buffer. */
+ while ( len % sizeof( int ) != ( sizeof ( int ) - 1 ) )
+ {
+ len += sprintf (buf + len, " ");
+ }
+ len += sprintf (buf + len, "\n");
+
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&info_lock, flags);
+#endif
+ return len;
+}
+
+int ibmmca_detect (Scsi_Host_Template * scsi_template)
+{
+ struct Scsi_Host *shpnt;
+ int port, id, i, j, list_size, slot;
+
+ found = 0; /* make absolutely sure, that found is set to 0 */
+
+ /* if this is not MCA machine, return "nothing found" */
+ if (!MCA_bus)
+ {
+ printk("IBM MCA SCSI: No Microchannel-bus support present -> Aborting.\n");
+ return 0;
+ }
+ else
+ printk("IBM MCA SCSI: Version %s\n",IBMMCA_SCSI_DRIVER_VERSION);
+
+ /* get interrupt request level */
+#ifdef OLDKERN
+ if (request_irq (IM_IRQ, interrupt_handler, SA_SHIRQ, "ibmmcascsi",
+ hosts))
+#else
+ if (request_irq (IM_IRQ, do_interrupt_handler, SA_SHIRQ, "ibmmcascsi",
+ hosts))
+#endif
+ {
+ printk("IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ);
+ return 0;
+ }
+
+ /* if ibmmcascsi setup option was passed to kernel, return "found" */
+ for (i = 0; i < IM_MAX_HOSTS; i++)
+ if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8)
+ {
+ printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n",
+ io_port[i], scsi_id[i]);
+ if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i],
+ "forced detected SCSI Adapter")))
+ {
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = 0;
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = 0;
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_special =
+ FORCED_DETECTION;
+ mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter");
+ mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo,
+ shpnt);
+ mca_mark_as_used(MCA_INTEGSCSI);
+ }
+ }
+ if (found) return found;
+
+ /* The POS2-register of all PS/2 model SCSI-subsystems has the following
+ * interpretation of bits:
+ * Bit 7 - 4 : Chip Revision ID (Release)
+ * Bit 3 - 2 : Reserved
+ * Bit 1 : 8k NVRAM Disabled
+ * Bit 0 : Chip Enable (EN-Signal)
+ * The POS3-register is interpreted as follows:
+ * Bit 7 - 5 : SCSI ID
+ * Bit 4 : Reserved = 0
+ * Bit 3 - 0 : Reserved = 0
+ * (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common
+ * Interfaces (1991)").
+ * In short words, this means, that IBM PS/2 machines only support
+ * 1 single subsystem by default. The slot-adapters must have another
+ * configuration on pos2. Here, one has to assume the following
+ * things for POS2-register:
+ * Bit 7 - 4 : Chip Revision ID (Release)
+ * Bit 3 - 1 : port offset factor
+ * Bit 0 : Chip Enable (EN-Signal)
+ * As I found a patch here, setting the IO-registers to 0x3540 forced,
+ * as there was a 0x05 in POS2 on a model 56, I assume, that the
+ * port 0x3540 must be fix for integrated SCSI-controllers.
+ * Ok, this discovery leads to the following implementation: (M.Lang) */
+
+ /* first look for the IBM SCSI integrated subsystem on the motherboard */
+ for (j=0;j<8;j++) /* read the pos-information */
+ pos[j] = mca_read_stored_pos(MCA_INTEGSCSI,j);
+ /* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present */
+ if (( pos[2] != 0xff) || (pos[3] != 0xff ))
+ {
+ if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */
+ {
+ port = IM_IO_PORT;
+ }
+ else
+ { /* if disabled, no IRQs will be generated, as the chip won't
+ * listen to the incomming commands and will do really nothing,
+ * except for listening to the pos-register settings. If this
+ * happens, I need to hugely think about it, as one has to
+ * write something to the MCA-Bus pos register in order to
+ * enable the chip. Normally, IBM-SCSI won't pass the POST,
+ * when the chip is disabled (see IBM tech. ref.). */
+ port = IM_IO_PORT; /* anyway, set the portnumber and warn */
+ printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
+ printk(" SCSI-operations may not work.\n");
+ }
+ id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */
+
+ /* give detailed information on the subsystem. This helps me
+ * additionally during debugging and analyzing bug-reports. */
+ printk("IBM MCA SCSI: IBM Integrated SCSI Controller found, io=0x%x, scsi id=%d,\n",
+ port, id);
+ printk(" chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n",
+ ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible",
+ (pos[2] & 1) ? "enabled." : "disabled.");
+
+ /* register the found integrated SCSI-subsystem */
+ if ((shpnt = ibmmca_register(scsi_template, port, id,
+ "IBM Integrated SCSI Controller")))
+ {
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = pos[2];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = pos[3];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_special =
+ INTEGRATED_SCSI;
+ mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller");
+ mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo,
+ shpnt);
+ mca_mark_as_used(MCA_INTEGSCSI);
+ }
+ }
+
+ /* now look for other adapters in MCA slots, */
+ /* determine the number of known IBM-SCSI-subsystem types */
+ /* see the pos[2] dependence to get the adapter port-offset. */
+ list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct);
+ for (i = 0; i < list_size; i++)
+ { /* scan each slot for a fitting adapter id */
+ slot = 0; /* start at slot 0 */
+ while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot))
+ != MCA_NOTFOUND)
+ { /* scan through all slots */
+ for (j=0;j<8;j++) /* read the pos-information */
+ pos[j] = mca_read_stored_pos(slot, j);
+ if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */
+ { /* (explanations see above) */
+ port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
+ }
+ else
+ { /* anyway, set the portnumber and warn */
+ port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
+ printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
+ printk(" SCSI-operations may not work.\n");
+ }
+ id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */
+ printk("IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n",
+ subsys_list[i].description, slot + 1, port, id);
+ printk(" chip rev.=%d, port-offset=0x%x, subsystem=%s\n",
+ ((pos[2] & 0xf0) >> 4),
+ ((pos[2] & 0x0e) << 2),
+ (pos[2] & 1) ? "enabled." : "disabled.");
+
+ /* register the hostadapter */
+ if ((shpnt = ibmmca_register(scsi_template, port, id,
+ subsys_list[i].description)))
+ {
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = pos[2];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = pos[3];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = i;
+
+ mca_set_adapter_name (slot, subsys_list[i].description);
+ mca_set_adapter_procfn (slot, (MCA_ProcFn) ibmmca_getinfo,
+ shpnt);
+ mca_mark_as_used(slot);
+ }
+ slot++; /* advance to next slot */
+ } /* advance to next adapter id in the list of IBM-SCSI-subsystems*/
+ }
+
+ if (!found)
+ { /* maybe ESDI, or other producers' SCSI-hosts */
+ free_irq (IM_IRQ, hosts);
+ printk("IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n");
+ }
+ return found; /* return the number of found SCSI hosts. Should be 1 or 0. */
}
static struct Scsi_Host *
-ibmmca_register(Scsi_Host_Template * template, int port, int id)
+ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id,
+ char *hostname)
{
- struct Scsi_Host *shpnt;
- int i, j;
-
- /* check I/O region */
- if (check_region(port, IM_N_IO_PORT))
- {
- printk("IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x.\n",
- port, port + IM_N_IO_PORT);
- return NULL;
- }
-
- /* register host */
- shpnt = scsi_register(template, sizeof(struct ibmmca_hostdata));
- if (!shpnt)
- {
- printk("IBM MCA SCSI: Unable to register host.\n");
- return NULL;
- }
-
- /* request I/O region */
- request_region(port, IM_N_IO_PORT, "ibmmca");
-
- hosts[found++] = shpnt;
- shpnt->irq = IM_IRQ;
- shpnt->io_port = port;
- shpnt->n_io_port = IM_N_IO_PORT;
- shpnt->this_id = id;
-
- reset_status = IM_RESET_NOT_IN_PROGRESS;
-
- for (i = 0; i < 8; i++)
- for (j = 0; j < 8; j++)
- get_ldn[i][j] = MAX_LOG_DEV;
-
- /* check which logical devices exist */
- local_checking_phase_flag = 1;
- check_devices(shpnt);
- local_checking_phase_flag = 0;
-
- /* an ibm mca subsystem has been detected */
- return shpnt;
+ struct Scsi_Host *shpnt;
+ int i, j;
+ unsigned int ctrl;
+
+ /* check I/O region */
+ if (check_region(port, IM_N_IO_PORT))
+ {
+ printk("IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x (%d ports).\n",
+ port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT);
+ return NULL;
+ }
+
+ /* register host */
+ shpnt = scsi_register(scsi_template, sizeof(struct ibmmca_hostdata));
+ if (!shpnt)
+ {
+ printk("IBM MCA SCSI: Unable to register host.\n");
+ return NULL;
+ }
+
+ /* request I/O region */
+ request_region(port, IM_N_IO_PORT, hostname);
+
+ hosts[found] = shpnt; /* add new found hostadapter to the list */
+ shpnt->irq = IM_IRQ; /* assign necessary stuff for the adapter */
+ shpnt->io_port = port;
+ shpnt->n_io_port = IM_N_IO_PORT;
+ shpnt->this_id = id;
+ /* now, the SCSI-subsystem is connected to Linux */
+
+ ctrl = (unsigned int)(inb(IM_CTR_REG(found))); /* get control-register status */
+#ifdef IM_DEBUG_PROBE
+ printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n",
+ ctrl,inb(IM_STAT_REG(found)));
+ printk("IBM MCA SCSI: This adapters' POS-registers: ");
+ for (i=0;i<8;i++)
+ printk("%x ",pos[i]);
+ printk("\n");
+ if (bypass_controller)
+ printk("IBM MCA SCSI: Subsystem SCSI-commands get bypassed.\n");
+#endif
+
+ reset_status(found) = IM_RESET_NOT_IN_PROGRESS;
+
+ for (i = 0; i < 8; i++) /* reset the tables */
+ for (j = 0; j < 8; j++)
+ get_ldn(found)[i][j] = MAX_LOG_DEV;
+
+ /* check which logical devices exist */
+ local_checking_phase_flag(found) = 1;
+ check_devices(found); /* call by value, using the global variable hosts*/
+ local_checking_phase_flag(found) = 0;
+
+ found++; /* now increase index to be prepared for next found subsystem */
+ /* an ibm mca subsystem has been detected */
+ return shpnt;
}
/*--------------------------------------------------------------------*/
-int
-ibmmca_command (Scsi_Cmnd * cmd)
+int ibmmca_command (Scsi_Cmnd * cmd)
{
ibmmca_queuecommand (cmd, internal_done);
cmd->SCp.Status = 0;
@@ -1678,8 +1765,7 @@ ibmmca_command (Scsi_Cmnd * cmd)
/*--------------------------------------------------------------------*/
-int
-ibmmca_release(struct Scsi_Host *shpnt)
+int ibmmca_release(struct Scsi_Host *shpnt)
{
release_region(shpnt->io_port, shpnt->n_io_port);
if (!(--found))
@@ -1708,231 +1794,267 @@ ibmmca_release(struct Scsi_Host *shpnt)
are sufficient. (The adapter uses always ldn=15, at whatever pun it is.) */
int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
{
- unsigned int ldn;
- unsigned int scsi_cmd;
- struct im_scb *scb;
- struct Scsi_Host *shpnt = cmd->host;
-
- int current_ldn;
- int id,lun;
-
- /* use industry standard ordering of the IDs */
-#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- int target = 6 - cmd->target;
-#else
- int target = cmd->target;
-#endif
-
- /*if (target,lun) is NO LUN or not existing at all, return error */
- if ((get_scsi[target][cmd->lun] == TYPE_NO_LUN)||
- (get_scsi[target][cmd->lun] == TYPE_NO_DEVICE))
+ unsigned int ldn;
+ unsigned int scsi_cmd;
+ struct im_scb *scb;
+ struct Scsi_Host *shpnt;
+ int current_ldn;
+ int id,lun;
+ int target;
+ int host_index;
+
+ if (ibm_ansi_order)
+ target = 6 - cmd->target;
+ else
+ target = cmd->target;
+
+ shpnt = cmd->host;
+
+ /* search for the right hostadapter */
+ for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
+
+ if (!hosts[host_index])
+ { /* invalid hostadapter descriptor address */
+ cmd->result = DID_NO_CONNECT << 16;
+ done (cmd);
+ return 0;
+ }
+
+ /*if (target,lun) is NO LUN or not existing at all, return error */
+ if ((get_scsi(host_index)[target][cmd->lun] == TYPE_NO_LUN)||
+ (get_scsi(host_index)[target][cmd->lun] == TYPE_NO_DEVICE))
{
cmd->result = DID_NO_CONNECT << 16;
done (cmd);
return 0;
}
- /*if (target,lun) unassigned, do further checks... */
- ldn = get_ldn[target][cmd->lun];
- if (ldn >= MAX_LOG_DEV) /* on invalid ldn do special stuff */
- {
- if (ldn > MAX_LOG_DEV) /* dynamical remapping if ldn unassigned */
- {
- current_ldn = next_ldn; /* stop-value for one circle */
- while (ld[next_ldn].cmd) /* search for a occupied, but not in */
- { /* command-processing ldn. */
- next_ldn ++;
- if (next_ldn>=MAX_LOG_DEV)
- next_ldn = 7;
- if (current_ldn == next_ldn) /* One circle done ? */
- { /* no non-processing ldn found */
- printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n");
- printk(" On ldn 7-14 SCSI-commands everywhere in progress.\n");
- printk(" Reporting DID_NO_CONNECT for device (%d,%d).\n",
- target, cmd->lun);
- cmd->result = DID_NO_CONNECT << 16;/* return no connect*/
- done (cmd);
- return 0;
- }
- }
-
- /* unmap non-processing ldn */
- for (id=0; id<8; id ++)
- for (lun=0; lun<8; lun++)
- {
- if (get_ldn[id][lun] == next_ldn)
- {
- get_ldn[id][lun] = TYPE_NO_DEVICE; /* unmap entry */
- goto DYN_ASSIGN; /* jump out as fast as possible */
- }
- }
-
-DYN_ASSIGN:
- /* unassign found ldn (pun,lun does not matter for remove) */
- immediate_assign(shpnt,0,0,next_ldn,REMOVE_LDN);
- /* assign found ldn to aimed pun,lun */
- immediate_assign(shpnt,target,cmd->lun,next_ldn,SET_LDN);
- /* map found ldn to pun,lun */
- get_ldn[target][cmd->lun] = next_ldn;
- /* change ldn to the right value, that is now next_ldn */
- ldn = next_ldn;
- /* set reduced interrupt_handler-mode for checking */
- local_checking_phase_flag = 1;
- /* get device information for ld[ldn] */
- if (device_exists (shpnt, ldn, &ld[ldn].block_length,
- &ld[ldn].device_type))
+ /*if (target,lun) unassigned, do further checks... */
+ ldn = get_ldn(host_index)[target][cmd->lun];
+ if (ldn >= MAX_LOG_DEV) /* on invalid ldn do special stuff */
+ {
+ if (ldn > MAX_LOG_DEV) /* dynamical remapping if ldn unassigned */
+ {
+ current_ldn = next_ldn(host_index); /* stop-value for one circle */
+ while (ld(host_index)[next_ldn(host_index)].cmd) /* search for a occupied, but not in */
+ { /* command-processing ldn. */
+ next_ldn(host_index)++;
+ if (next_ldn(host_index)>=MAX_LOG_DEV)
+ next_ldn(host_index) = 7;
+ if (current_ldn == next_ldn(host_index)) /* One circle done ? */
+ { /* no non-processing ldn found */
+ printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n");
+ printk(" On ldn 7-14 SCSI-commands everywhere in progress.\n");
+ printk(" Reporting DID_NO_CONNECT for device (%d,%d).\n",
+ target, cmd->lun);
+ cmd->result = DID_NO_CONNECT << 16;/* return no connect*/
+ done (cmd);
+ return 0;
+ }
+ }
+
+ /* unmap non-processing ldn */
+ for (id=0; id<8; id ++)
+ for (lun=0; lun<8; lun++)
+ {
+ if (get_ldn(host_index)[id][lun] == next_ldn(host_index))
+ {
+ get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
+ /* unmap entry */
+ }
+ }
+ /* set reduced interrupt_handler-mode for checking */
+ local_checking_phase_flag(host_index) = 1;
+ /* unassign found ldn (pun,lun does not matter for remove) */
+ immediate_assign(host_index,0,0,next_ldn(host_index),REMOVE_LDN);
+ /* assign found ldn to aimed pun,lun */
+ immediate_assign(host_index,target,cmd->lun,next_ldn(host_index),SET_LDN);
+ /* map found ldn to pun,lun */
+ get_ldn(host_index)[target][cmd->lun] = next_ldn(host_index);
+ /* change ldn to the right value, that is now next_ldn */
+ ldn = next_ldn(host_index);
+ /* get device information for ld[ldn] */
+ if (device_exists (host_index, ldn,
+ &ld(host_index)[ldn].block_length,
+ &ld(host_index)[ldn].device_type))
{
- ld[ldn].cmd = 0; /* To prevent panic set 0, because
- devices that were not assigned,
- should have nothing in progress. */
+ ld(host_index)[ldn].cmd = 0; /* To prevent panic set 0, because
+ devices that were not assigned,
+ should have nothing in progress. */
- /* increase assignment counters for statistics in /proc */
- IBM_DS.dynamical_assignments++;
- IBM_DS.ldn_assignments[ldn]++;
+ /* increase assignment counters for statistics in /proc */
+ IBM_DS(host_index).dynamical_assignments++;
+ IBM_DS(host_index).ldn_assignments[ldn]++;
}
- else
- /* panic here, because a device, found at boottime has
- vanished */
- panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n",
- ldn, target, cmd->lun);
-
- /* set back to normal interrupt_handling */
- local_checking_phase_flag = 0;
-
- /* Information on syslog terminal */
- printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n",
- ldn, target, cmd->lun);
-
- /* increase next_ldn for next dynamical assignment */
- next_ldn ++;
- if (next_ldn>=MAX_LOG_DEV) next_ldn = 7;
- }
- else
- { /* wall against Linux accesses to the subsystem adapter */
- cmd->result = DID_NO_CONNECT << 16;
- done (cmd);
- return 0;
- }
- }
-
- /*verify there is no command already in progress for this log dev */
- if (ld[ldn].cmd)
- panic ("IBM MCA SCSI: cmd already in progress for this ldn.\n");
-
- /*save done in cmd, and save cmd for the interrupt handler */
- cmd->scsi_done = done;
- ld[ldn].cmd = cmd;
-
- /*fill scb information independent of the scsi command */
- scb = &(ld[ldn].scb);
- scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR;
- scb->tsb_adr = virt_to_bus(&(ld[ldn].tsb));
- if (cmd->use_sg)
- {
- int i = cmd->use_sg;
- struct scatterlist *sl = (struct scatterlist *) cmd->request_buffer;
- if (i > 16)
- panic ("IBM MCA SCSI: scatter-gather list too long.\n");
- while (--i >= 0)
- {
- ld[ldn].sge[i].address = (void *) virt_to_bus(sl[i].address);
- ld[ldn].sge[i].byte_length = sl[i].length;
- }
- scb->enable |= IM_POINTER_TO_LIST;
- scb->sys_buf_adr = virt_to_bus(&(ld[ldn].sge[0]));
- scb->sys_buf_length = cmd->use_sg * sizeof (struct im_sge);
- }
- else
- {
- scb->sys_buf_adr = virt_to_bus(cmd->request_buffer);
- scb->sys_buf_length = cmd->request_bufflen;
- }
-
- /*fill scb information dependent on scsi command */
- scsi_cmd = cmd->cmnd[0];
+ else
+ /* panic here, because a device, found at boottime has
+ vanished */
+ panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n",
+ ldn, target, cmd->lun);
+
+ /* set back to normal interrupt_handling */
+ local_checking_phase_flag(host_index) = 0;
+
+ /* Information on syslog terminal */
+ printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n",
+ ldn, target, cmd->lun);
+
+ /* increase next_ldn for next dynamical assignment */
+ next_ldn(host_index)++;
+ if (next_ldn(host_index)>=MAX_LOG_DEV)
+ next_ldn(host_index) = 7;
+ }
+ else
+ { /* wall against Linux accesses to the subsystem adapter */
+ cmd->result = DID_BAD_TARGET << 16;
+ done (cmd);
+ return 0;
+ }
+ }
+
+ /*verify there is no command already in progress for this log dev */
+ if (ld(host_index)[ldn].cmd)
+ panic ("IBM MCA SCSI: cmd already in progress for this ldn.\n");
+
+ /*save done in cmd, and save cmd for the interrupt handler */
+ cmd->scsi_done = done;
+ ld(host_index)[ldn].cmd = cmd;
+
+ /*fill scb information independent of the scsi command */
+ scb = &(ld(host_index)[ldn].scb);
+ ld(host_index)[ldn].tsb.dev_status = 0;
+ scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR;
+ scb->tsb_adr = virt_to_bus(&(ld(host_index)[ldn].tsb));
+ if (cmd->use_sg)
+ {
+ int i = cmd->use_sg;
+ struct scatterlist *sl = (struct scatterlist *) cmd->request_buffer;
+ if (i > 16)
+ panic ("IBM MCA SCSI: scatter-gather list too long.\n");
+ while (--i >= 0)
+ {
+ ld(host_index)[ldn].sge[i].address = (void *) virt_to_bus(sl[i].address);
+ ld(host_index)[ldn].sge[i].byte_length = sl[i].length;
+ }
+ scb->enable |= IM_POINTER_TO_LIST;
+ scb->sys_buf_adr = virt_to_bus(&(ld(host_index)[ldn].sge[0]));
+ scb->sys_buf_length = cmd->use_sg * sizeof (struct im_sge);
+ }
+ else
+ {
+ scb->sys_buf_adr = virt_to_bus(cmd->request_buffer);
+ scb->sys_buf_length = cmd->request_bufflen;
+ }
+
+ /*fill scb information dependent on scsi command */
+ scsi_cmd = cmd->cmnd[0];
#ifdef IM_DEBUG_CMD
- printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn);
+ printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn);
#endif
-
- /* for specific device-type debugging: */
+
+ /* for specific device-type debugging: */
#ifdef IM_DEBUG_CMD_SPEC_DEV
- if (ld[ldn].device_type==IM_DEBUG_CMD_DEVICE)
+ if (ld(host_index)[ldn].device_type==IM_DEBUG_CMD_DEVICE)
printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n",
- ld[ldn].device_type, scsi_cmd, ldn);
+ ld(host_index)[ldn].device_type, scsi_cmd, ldn);
#endif
-
- /* for possible panics store current command */
- last_scsi_command = scsi_cmd;
-
- /* update statistical info */
- IBM_DS.total_accesses++;
- IBM_DS.ldn_access[ldn]++;
-
- switch (scsi_cmd)
- {
- case READ_6:
- case WRITE_6:
- case READ_10:
- case WRITE_10:
- case READ_12:
- case WRITE_12:
- /* statistics for proc_info */
- if ((scsi_cmd == READ_6)||(scsi_cmd == READ_10)||(scsi_cmd == READ_12))
- IBM_DS.ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */
- else if ((scsi_cmd == WRITE_6)||(scsi_cmd == WRITE_10)||
- (scsi_cmd == WRITE_12))
- IBM_DS.ldn_write_access[ldn]++; /* increase write-count on ldn stat.*/
-
- /* Distinguish between disk and other devices. Only disks (that are the
- most frequently accessed devices) should be supported by the
+
+ /* for possible panics store current command */
+ last_scsi_command(host_index)[ldn] = scsi_cmd;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
+
+ /* update statistical info */
+ IBM_DS(host_index).total_accesses++;
+ IBM_DS(host_index).ldn_access[ldn]++;
+
+ switch (scsi_cmd)
+ {
+ case READ_6:
+ case WRITE_6:
+ case READ_10:
+ case WRITE_10:
+ case READ_12:
+ case WRITE_12:
+ /* statistics for proc_info */
+ if ((scsi_cmd == READ_6)||(scsi_cmd == READ_10)||(scsi_cmd == READ_12))
+ IBM_DS(host_index).ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */
+ else if ((scsi_cmd == WRITE_6)||(scsi_cmd == WRITE_10)||
+ (scsi_cmd == WRITE_12))
+ IBM_DS(host_index).ldn_write_access[ldn]++; /* increase write-count on ldn stat.*/
+
+ /* Distinguish between disk and other devices. Only disks (that are the
+ most frequently accessed devices) should be supported by the
IBM-SCSI-Subsystem commands. */
- switch (ld[ldn].device_type)
- {
- case TYPE_DISK: /* for harddisks enter here ... */
- case TYPE_MOD: /* ... try it also for MO-drives (send flames as */
- /* you like, if this won't work.) */
- if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
- scsi_cmd == READ_12)
- {
- scb->command = IM_READ_DATA_CMD;
- scb->enable |= IM_READ_CONTROL;
- }
- else
- {
- scb->command = IM_WRITE_DATA_CMD;
- }
- if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6)
- {
- scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[3]) << 0) |
- (((unsigned) cmd->cmnd[2]) << 8) |
- ((((unsigned) cmd->cmnd[1]) & 0x1f) << 16);
- scb->u2.blk.count = (unsigned) cmd->cmnd[4];
- }
- else
- {
- scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) |
- (((unsigned) cmd->cmnd[4]) << 8) |
- (((unsigned) cmd->cmnd[3]) << 16) |
- (((unsigned) cmd->cmnd[2]) << 24);
- scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) |
- (((unsigned) cmd->cmnd[7]) << 8);
- }
- scb->u2.blk.length = ld[ldn].block_length;
- if (++disk_rw_in_progress == 1)
- PS2_DISK_LED_ON (shpnt->host_no, target);
- break;
-
- /* for other devices, enter here. Other types are not known by
- Linux! TYPE_NO_LUN is forbidden as valid device. */
- case TYPE_ROM:
- case TYPE_TAPE:
- case TYPE_PROCESSOR:
- case TYPE_WORM:
- case TYPE_SCANNER:
- case TYPE_MEDIUM_CHANGER:
-
- /* If there is a sequential-device, IBM recommends to use
+ switch (ld(host_index)[ldn].device_type)
+ {
+ case TYPE_DISK: /* for harddisks enter here ... */
+ case TYPE_MOD: /* ... try it also for MO-drives (send flames as */
+ /* you like, if this won't work.) */
+ if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
+ scsi_cmd == READ_12)
+ { /* read command preparations */
+ if (bypass_controller)
+ {
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL;
+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy(scb->u2.scsi_command,cmd->cmnd,cmd->cmd_len);
+ }
+ else
+ {
+ scb->command = IM_READ_DATA_CMD;
+ scb->enable |= IM_READ_CONTROL;
+ }
+ }
+ else
+ { /* write command preparations */
+ if (bypass_controller)
+ {
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy(scb->u2.scsi_command,cmd->cmnd,cmd->cmd_len);
+ }
+ else
+ {
+ scb->command = IM_WRITE_DATA_CMD;
+ }
+ }
+
+ if (!bypass_controller)
+ {
+ if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6)
+ {
+ scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[3]) << 0) |
+ (((unsigned) cmd->cmnd[2]) << 8) |
+ ((((unsigned) cmd->cmnd[1]) & 0x1f) << 16);
+ scb->u2.blk.count = (unsigned) cmd->cmnd[4];
+ }
+ else
+ {
+ scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) |
+ (((unsigned) cmd->cmnd[4]) << 8) |
+ (((unsigned) cmd->cmnd[3]) << 16) |
+ (((unsigned) cmd->cmnd[2]) << 24);
+ scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) |
+ (((unsigned) cmd->cmnd[7]) << 8);
+ }
+ scb->u2.blk.length = ld(host_index)[ldn].block_length;
+ }
+ if (++disk_rw_in_progress == 1)
+ PS2_DISK_LED_ON (shpnt->host_no, target);
+ break;
+
+ /* for other devices, enter here. Other types are not known by
+ Linux! TYPE_NO_LUN is forbidden as valid device. */
+ case TYPE_ROM:
+ case TYPE_TAPE:
+ case TYPE_PROCESSOR:
+ case TYPE_WORM:
+ case TYPE_SCANNER:
+ case TYPE_MEDIUM_CHANGER:
+
+ /* If there is a sequential-device, IBM recommends to use
IM_OTHER_SCSI_CMD_CMD instead of subsystem READ/WRITE.
Good/modern CD-ROM-drives are capable of
reading sequential AND random-access. This leads to the problem,
@@ -1943,241 +2065,422 @@ DYN_ASSIGN:
to have a stable state. In addition, data-access on CD-ROMs
works faster like that. Strange, but obvious. */
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
- scsi_cmd == READ_12) /* enable READ */
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
- else
- scb->enable |= IM_SUPRESS_EXCEPTION_SHORT; /* assume WRITE */
-
- scb->u1.scsi_cmd_length = cmd->cmd_len;
- memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
-
- /* Read/write on this non-disk devices is also displayworthy,
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
+ scsi_cmd == READ_12) /* enable READ */
+ {
+ scb->enable |= IM_READ_CONTROL;
+ }
+
+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+
+ /* Read/write on this non-disk devices is also displayworthy,
so flash-up the LED/display. */
- if (++disk_rw_in_progress == 1)
- PS2_DISK_LED_ON (shpnt->host_no, target);
- break;
- }
- break;
- case INQUIRY:
- IBM_DS.ldn_inquiry_access[ldn]++;
- scb->command = IM_DEVICE_INQUIRY_CMD;
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
- break;
-
- case READ_CAPACITY:
- scb->command = IM_READ_CAPACITY_CMD;
- scb->enable |= IM_READ_CONTROL;
- /* the length of system memory buffer must be exactly 8 bytes */
- if (scb->sys_buf_length >= 8)
- scb->sys_buf_length = 8;
- break;
-
- /* Commands that need read-only-mode (system <- device): */
- case REQUEST_SENSE:
- scb->command = IM_REQUEST_SENSE_CMD;
- scb->enable |= IM_READ_CONTROL;
- break;
-
- /* Commands that need write-only-mode (system -> device): */
- case MODE_SELECT:
- case MODE_SELECT_10:
- IBM_DS.ldn_modeselect_access[ldn]++;
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_SUPRESS_EXCEPTION_SHORT; /*Select needs WRITE-enabled*/
- scb->u1.scsi_cmd_length = cmd->cmd_len;
- memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
- break;
-
- /* For other commands, read-only is useful. Most other commands are
- running without an input-data-block. */
- default:
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
- scb->u1.scsi_cmd_length = cmd->cmd_len;
- memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
- break;
- }
-
- /*issue scb command, and return */
- issue_cmd (shpnt, virt_to_bus(scb), IM_SCB | ldn);
- return 0;
+ if (++disk_rw_in_progress == 1)
+ PS2_DISK_LED_ON (shpnt->host_no, target);
+ break;
+ }
+ break;
+ case INQUIRY:
+ IBM_DS(host_index).ldn_inquiry_access[ldn]++;
+ if (bypass_controller)
+ {
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ }
+ else
+ {
+ scb->command = IM_DEVICE_INQUIRY_CMD;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ }
+ break;
+
+ case READ_CAPACITY:
+ /* the length of system memory buffer must be exactly 8 bytes */
+ if (scb->sys_buf_length > 8)
+ scb->sys_buf_length = 8;
+ if (bypass_controller)
+ {
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL;
+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ }
+ else
+ {
+ scb->command = IM_READ_CAPACITY_CMD;
+ scb->enable |= IM_READ_CONTROL;
+ }
+ break;
+
+ /* Commands that need read-only-mode (system <- device): */
+ case REQUEST_SENSE:
+ if (bypass_controller)
+ {
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL;
+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ }
+ else
+ {
+ scb->command = IM_REQUEST_SENSE_CMD;
+ scb->enable |= IM_READ_CONTROL;
+ }
+ break;
+
+ /* Commands that need write-only-mode (system -> device): */
+ case MODE_SELECT:
+ case MODE_SELECT_10:
+ IBM_DS(host_index).ldn_modeselect_access[ldn]++;
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_SUPRESS_EXCEPTION_SHORT; /*Select needs WRITE-enabled*/
+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ break;
+
+ /* For other commands, read-only is useful. Most other commands are
+ running without an input-data-block. */
+ default:
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ break;
+ }
+
+ /*issue scb command, and return */
+ issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+ return 0;
}
/*--------------------------------------------------------------------*/
-int
-ibmmca_abort (Scsi_Cmnd * cmd)
+int ibmmca_abort (Scsi_Cmnd * cmd)
{
- /* The code below doesn't work right now, so we tell the upper layer
- that we can't abort. This eventually causes a reset.
- */
- return SCSI_ABORT_SNOOZE ;
+ /* Abort does not work, as the adapter never generates an interrupt on
+ * whatever situation is simulated, even when really pending commands
+ * are running on the adapters' hardware ! */
+
+ struct Scsi_Host *shpnt;
+ unsigned int ldn;
+ void (*saved_done) (Scsi_Cmnd *);
+ int target;
+ int host_index;
+ static unsigned long flags;
+ unsigned long imm_command;
-#if 0
- struct Scsi_host *shpnt = cmd->host;
- unsigned int ldn;
- void (*saved_done) (Scsi_Cmnd *);
+ /* return SCSI_ABORT_SNOOZE ; */
-#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- int target = 6 - cmd->target;
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
#else
- int target = cmd->target;
-#endif
+ spin_lock_irqsave(&abort_lock, flags);
+#endif
+ if (ibm_ansi_order)
+ target = 6 - cmd->target;
+ else
+ target = cmd->target;
+
+ shpnt = cmd->host;
- /*get logical device number, and disable system interrupts */
- printk ("IBM MCA SCSI: sending abort to device id=%d lun=%d.\n",
- target, cmd->lun);
- ldn = get_ldn[target][cmd->lun];
- cli ();
-
- /*if cmd for this ldn has already finished, no need to abort */
- if (!ld[ldn].cmd)
- {
- /* sti (); */
- return SCSI_ABORT_NOT_RUNNING;
- }
-
- /* Clear ld.cmd, save done function, install internal done,
- * send abort immediate command (this enables sys. interrupts),
- * and wait until the interrupt arrives.
- */
- ld[ldn].cmd = 0;
- saved_done = cmd->scsi_done;
- cmd->scsi_done = internal_done;
- cmd->SCp.Status = 0;
- issue_cmd (shpnt, T_IMM_CMD, IM_IMM_CMD | ldn);
- while (!cmd->SCp.Status)
- barrier ();
+ /* search for the right hostadapter */
+ for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
+
+ if (!hosts[host_index])
+ { /* invalid hostadapter descriptor address */
+ cmd->result = DID_NO_CONNECT << 16;
+ if (cmd->scsi_done)
+ (cmd->done) (cmd);
+ return SCSI_ABORT_SNOOZE;
+ }
+
+ /*get logical device number, and disable system interrupts */
+ printk ("IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n",
+ target, cmd->lun);
+ ldn = get_ldn(host_index)[target][cmd->lun];
+
+ /*if cmd for this ldn has already finished, no need to abort */
+ if (!ld(host_index)[ldn].cmd)
+ {
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&abort_lock, flags);
+#endif
+ return SCSI_ABORT_NOT_RUNNING;
+ }
- /*if abort went well, call saved done, then return success or error */
- if (cmd->result == 0)
- {
- cmd->result |= DID_ABORT << 16;
- saved_done (cmd);
- return SCSI_ABORT_SUCCESS;
- }
- else
- return SCSI_ABORT_ERROR;
+ /* Clear ld.cmd, save done function, install internal done,
+ * send abort immediate command (this enables sys. interrupts),
+ * and wait until the interrupt arrives.
+ */
+ saved_done = cmd->scsi_done;
+ cmd->scsi_done = internal_done;
+ cmd->SCp.Status = 0;
+ last_scsi_command(host_index)[ldn] = IM_ABORT_IMM_CMD;
+ last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
+ imm_command = inl(IM_CMD_REG(host_index));
+ imm_command &= (unsigned long)(0xffff0000); /* mask reserved stuff */
+ imm_command |= (unsigned long)(IM_ABORT_IMM_CMD);
+ /* must wait for attention reg not busy */
+ while (1)
+ {
+ if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
+ break;
+#ifdef OLDKERN
+ restore_flags (flags);
+#else
+ spin_unlock_irqrestore(&abort_lock, flags);
+#endif
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&abort_lock, flags);
+#endif
+ }
+ /*write registers and enable system interrupts */
+ outl (imm_command, IM_CMD_REG(host_index));
+ outb (IM_IMM_CMD | ldn, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags (flags);
+#else
+ spin_unlock_irqrestore(&abort_lock, flags);
#endif
+
+#ifdef IM_DEBUG_PROBE
+ printk("IBM MCA SCSI: Abort submitted, waiting for adapter response...\n");
+#endif
+ while (!cmd->SCp.Status)
+ barrier ();
+ cmd->scsi_done = saved_done;
+ /*if abort went well, call saved done, then return success or error */
+ if (cmd->result == (DID_ABORT << 16))
+ {
+ cmd->result |= DID_ABORT << 16;
+ if (cmd->scsi_done)
+ (cmd->scsi_done) (cmd);
+ ld(host_index)[ldn].cmd = NULL;
+#ifdef IM_DEBUG_PROBE
+ printk("IBM MCA SCSI: Abort finished with success.\n");
+#endif
+ return SCSI_ABORT_SUCCESS;
+ }
+ else
+ {
+ cmd->result |= DID_NO_CONNECT << 16;
+ if (cmd->scsi_done)
+ (cmd->scsi_done) (cmd);
+ ld(host_index)[ldn].cmd = NULL;
+#ifdef IM_DEBUG_PROBE
+ printk("IBM MCA SCSI: Abort failed.\n");
+#endif
+ return SCSI_ABORT_ERROR;
+ }
}
/*--------------------------------------------------------------------*/
-int
-ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags)
+int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags)
{
- struct Scsi_Host *shpnt = cmd->host;
- int ticks = IM_RESET_DELAY*HZ;
-
- if (local_checking_phase_flag) {
- printk("IBM MCA SCSI: unable to reset while checking devices.\n");
- return SCSI_RESET_SNOOZE;
- }
-
- /* issue reset immediate command to subsystem, and wait for interrupt */
- printk("IBM MCA SCSI: resetting all devices.\n");
- cli ();
- reset_status = IM_RESET_IN_PROGRESS;
- issue_cmd (shpnt, IM_RESET_IMM_CMD, IM_IMM_CMD | 0xf);
- while (reset_status == IM_RESET_IN_PROGRESS && --ticks) {
- mdelay(1+999/HZ);
- barrier();
- }
- /* if reset did not complete, just return an error*/
- if (!ticks) {
- printk("IBM MCA SCSI: reset did not complete within %d seconds.\n",
- IM_RESET_DELAY);
- reset_status = IM_RESET_FINISHED_FAIL;
- return SCSI_RESET_ERROR;
- }
-
- /* if reset failed, just return an error */
- if (reset_status == IM_RESET_FINISHED_FAIL) {
- printk("IBM MCA SCSI: reset failed.\n");
- return SCSI_RESET_ERROR;
- }
-
- /* so reset finished ok - call outstanding done's, and return success */
- printk ("IBM MCA SCSI: reset completed without error.\n");
- {
- int i;
- for (i = 0; i < MAX_LOG_DEV; i++)
- {
- Scsi_Cmnd *cmd = ld[i].cmd;
- if (cmd && cmd->scsi_done)
- {
- ld[i].cmd = 0;
- cmd->result = DID_RESET;
- (cmd->scsi_done) (cmd);
- }
- }
- }
- return SCSI_RESET_SUCCESS;
+ struct Scsi_Host *shpnt;
+ Scsi_Cmnd *cmd_aid;
+ int ticks,i;
+ int host_index;
+ static unsigned long flags;
+ unsigned long imm_command;
+
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&reset_lock, flags);
+#endif
+ ticks = IM_RESET_DELAY*HZ;
+ shpnt = cmd->host;
+ /* search for the right hostadapter */
+ for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
+
+ if (!hosts[host_index])
+ { /* invalid hostadapter descriptor address */
+ if (!local_checking_phase_flag(host_index))
+ {
+ cmd->result = DID_NO_CONNECT << 16;
+ if (cmd->scsi_done)
+ (cmd->done) (cmd);
+ }
+ return SCSI_ABORT_SNOOZE;
+ }
+
+ if (local_checking_phase_flag(host_index))
+ {
+ printk("IBM MCA SCSI: unable to reset while checking devices.\n");
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&reset_lock, flags);
+#endif
+ return SCSI_RESET_SNOOZE;
+ }
+
+ /* issue reset immediate command to subsystem, and wait for interrupt */
+ printk("IBM MCA SCSI: resetting all devices.\n");
+ reset_status(host_index) = IM_RESET_IN_PROGRESS;
+ last_scsi_command(host_index)[0xf] = IM_RESET_IMM_CMD;
+ last_scsi_type(host_index)[0xf] = IM_IMM_CMD;
+ imm_command = inl(IM_CMD_REG(host_index));
+ imm_command &= (unsigned long)(0xffff0000); /* mask reserved stuff */
+ imm_command |= (unsigned long)(IM_RESET_IMM_CMD);
+ /* must wait for attention reg not busy */
+ while (1)
+ {
+ if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
+ break;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&reset_lock, flags);
+#endif
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&reset_lock, flags);
+#endif
+ }
+ /*write registers and enable system interrupts */
+ outl (imm_command, IM_CMD_REG(host_index));
+ outb (IM_IMM_CMD | 0xf, IM_ATTN_REG(host_index));
+ /* wait for interrupt finished or intr_stat register to be set, as the
+ * interrupt will not be executed, while we are in here! */
+ while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks
+ && ((inb(IM_INTR_REG(host_index)) & 0x8f)!=0x8f)) {
+ mdelay(1+999/HZ);
+ barrier();
+ }
+ /* if reset did not complete, just return an error*/
+ if (!ticks) {
+ printk("IBM MCA SCSI: reset did not complete within %d seconds.\n",
+ IM_RESET_DELAY);
+ reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&reset_lock, flags);
+#endif
+ return SCSI_RESET_ERROR;
+ }
+
+ if ((inb(IM_INTR_REG(host_index)) & 0x8f)==0x8f)
+ { /* analysis done by this routine and not by the intr-routine */
+ if (inb(IM_INTR_REG(host_index))==0xaf)
+ reset_status(host_index) = IM_RESET_FINISHED_OK_NO_INT;
+ else if (inb(IM_INTR_REG(host_index))==0xcf)
+ reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+ else /* failed, 4get it */
+ reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
+ outb (IM_EOI | 0xf, IM_ATTN_REG(host_index));
+ }
+
+ /* if reset failed, just return an error */
+ if (reset_status(host_index) == IM_RESET_FINISHED_FAIL) {
+ printk("IBM MCA SCSI: reset failed.\n");
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&reset_lock, flags);
+#endif
+ return SCSI_RESET_ERROR;
+ }
+
+ /* so reset finished ok - call outstanding done's, and return success */
+ printk ("IBM MCA SCSI: Reset completed without known error.\n");
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&reset_lock, flags);
+#endif
+ for (i = 0; i < MAX_LOG_DEV; i++)
+ {
+ cmd_aid = ld(host_index)[i].cmd;
+ if (cmd_aid && cmd_aid->scsi_done)
+ {
+ ld(host_index)[i].cmd = NULL;
+ cmd_aid->result = DID_RESET << 16;
+ (cmd_aid->scsi_done) (cmd_aid);
+ }
+ }
+ return SCSI_RESET_SUCCESS;
}
/*--------------------------------------------------------------------*/
-int
-ibmmca_biosparam (Disk * disk, kdev_t dev, int *info)
+int ibmmca_biosparam (Disk * disk, kdev_t dev, int *info)
{
- info[0] = 64;
- info[1] = 32;
- info[2] = disk->capacity / (info[0] * info[1]);
- if (info[2] >= 1024)
- {
- info[0] = 128;
- info[1] = 63;
- info[2] = disk->capacity / (info[0] * info[1]);
- if (info[2] >= 1024)
- {
- info[0] = 255;
- info[1] = 63;
- info[2] = disk->capacity / (info[0] * info[1]);
- if (info[2] >= 1024)
- info[2] = 1023;
- }
- }
- return 0;
+ info[0] = 64;
+ info[1] = 32;
+ info[2] = disk->capacity / (info[0] * info[1]);
+ if (info[2] >= 1024)
+ {
+ info[0] = 128;
+ info[1] = 63;
+ info[2] = disk->capacity / (info[0] * info[1]);
+ if (info[2] >= 1024)
+ {
+ info[0] = 255;
+ info[1] = 63;
+ info[2] = disk->capacity / (info[0] * info[1]);
+ if (info[2] >= 1024)
+ info[2] = 1023;
+ }
+ }
+ return 0;
}
/* calculate percentage of total accesses on a ldn */
-static int ldn_access_load(struct Scsi_Host *shpnt, int ldn)
+static int ldn_access_load(int host_index, int ldn)
{
- if (IBM_DS.total_accesses == 0) return (0);
- if (IBM_DS.ldn_access[ldn] == 0) return (0);
- return (IBM_DS.ldn_access[ldn] * 100) / IBM_DS.total_accesses;
+ if (IBM_DS(host_index).total_accesses == 0) return (0);
+ if (IBM_DS(host_index).ldn_access[ldn] == 0) return (0);
+ return (IBM_DS(host_index).ldn_access[ldn] * 100) / IBM_DS(host_index).total_accesses;
}
/* calculate total amount of r/w-accesses */
-static int ldn_access_total_read_write(struct Scsi_Host *shpnt)
+static int ldn_access_total_read_write(int host_index)
{
- int a = 0;
+ int a;
int i;
+ a = 0;
for (i=0; i<=MAX_LOG_DEV; i++)
- a+=IBM_DS.ldn_read_access[i]+IBM_DS.ldn_write_access[i];
+ a+=IBM_DS(host_index).ldn_read_access[i]+IBM_DS(host_index).ldn_write_access[i];
return(a);
}
-static int ldn_access_total_inquiry(struct Scsi_Host *shpnt)
+static int ldn_access_total_inquiry(int host_index)
{
- int a = 0;
+ int a;
int i;
+ a = 0;
for (i=0; i<=MAX_LOG_DEV; i++)
- a+=IBM_DS.ldn_inquiry_access[i];
+ a+=IBM_DS(host_index).ldn_inquiry_access[i];
return(a);
}
-static int ldn_access_total_modeselect(struct Scsi_Host *shpnt)
+static int ldn_access_total_modeselect(int host_index)
{
- int a = 0;
+ int a;
int i;
+ a = 0;
for (i=0; i<=MAX_LOG_DEV; i++)
- a+=IBM_DS.ldn_modeselect_access[i];
+ a+=IBM_DS(host_index).ldn_modeselect_access[i];
return(a);
}
@@ -2186,28 +2489,30 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length,
int hostno, int inout)
{
int len=0;
- int i,id,lun;
+ int i,id,lun,host_index;
struct Scsi_Host *shpnt;
unsigned long flags;
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&proc_lock, flags);
+#endif
+
for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++);
shpnt = hosts[i];
+ host_index = i;
if (!shpnt) {
len += sprintf(buffer+len, "\nCan't find adapter for host number %d\n", hostno);
return len;
}
- save_flags(flags);
- cli();
-
len += sprintf(buffer+len, "\n IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n",
IBMMCA_SCSI_DRIVER_VERSION);
len += sprintf(buffer+len, " SCSI Access-Statistics:\n");
-#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- len += sprintf(buffer+len, " ANSI-SCSI-standard order.: Yes\n");
-#else
- len += sprintf(buffer+len, " ANSI-SCSI-standard order.: No\n");
-#endif
+ len += sprintf(buffer+len, " Device Scanning Order....: %s\n",
+ (ibm_ansi_order) ? "IBM/ANSI" : "New Industry Standard");
#ifdef CONFIG_SCSI_MULTI_LUN
len += sprintf(buffer+len, " Multiple LUN probing.....: Yes\n");
#else
@@ -2215,72 +2520,74 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length,
#endif
len += sprintf(buffer+len, " This Hostnumber..........: %d\n",
hostno);
- len += sprintf(buffer+len, " Base I/O-Port............: 0x%lx\n",
- IM_CMD_REG);
+ len += sprintf(buffer+len, " Base I/O-Port............: 0x%x\n",
+ (unsigned int)(IM_CMD_REG(host_index)));
len += sprintf(buffer+len, " (Shared) IRQ.............: %d\n",
IM_IRQ);
+ len += sprintf(buffer+len, " SCSI-command set used....: %s\n",
+ (bypass_controller) ? "software" : "hardware integrated");
len += sprintf(buffer+len, " Total Interrupts.........: %d\n",
- IBM_DS.total_interrupts);
+ IBM_DS(host_index).total_interrupts);
len += sprintf(buffer+len, " Total SCSI Accesses......: %d\n",
- IBM_DS.total_accesses);
+ IBM_DS(host_index).total_accesses);
len += sprintf(buffer+len, " Total SCSI READ/WRITE..: %d\n",
- ldn_access_total_read_write(shpnt));
+ ldn_access_total_read_write(host_index));
len += sprintf(buffer+len, " Total SCSI Inquiries...: %d\n",
- ldn_access_total_inquiry(shpnt));
+ ldn_access_total_inquiry(host_index));
len += sprintf(buffer+len, " Total SCSI Modeselects.: %d\n",
- ldn_access_total_modeselect(shpnt));
- len += sprintf(buffer+len, " Total SCSI other cmds..: %d\n\n",
- IBM_DS.total_accesses - ldn_access_total_read_write(shpnt)
- - ldn_access_total_modeselect(shpnt)
- - ldn_access_total_inquiry(shpnt));
-
+ ldn_access_total_modeselect(host_index));
+ len += sprintf(buffer+len, " Total SCSI other cmds..: %d\n",
+ IBM_DS(host_index).total_accesses - ldn_access_total_read_write(host_index)
+ - ldn_access_total_modeselect(host_index)
+ - ldn_access_total_inquiry(host_index));
+ len += sprintf(buffer+len, " Total SCSI command fails.: %d\n\n",
+ IBM_DS(host_index).total_errors);
len += sprintf(buffer+len, " Logical-Device-Number (LDN) Access-Statistics:\n");
len += sprintf(buffer+len, " LDN | Accesses [%%] | READ | WRITE | ASSIGNMENTS\n");
len += sprintf(buffer+len, " -----|--------------|-----------|-----------|--------------\n");
for (i=0; i<=MAX_LOG_DEV; i++)
len += sprintf(buffer+len, " %2X | %3d | %8d | %8d | %8d\n",
- i, ldn_access_load(shpnt, i), IBM_DS.ldn_read_access[i],
- IBM_DS.ldn_write_access[i], IBM_DS.ldn_assignments[i]);
+ i, ldn_access_load(host_index, i), IBM_DS(host_index).ldn_read_access[i],
+ IBM_DS(host_index).ldn_write_access[i], IBM_DS(host_index).ldn_assignments[i]);
len += sprintf(buffer+len, " -----------------------------------------------------------\n\n");
len += sprintf(buffer+len, " Dynamical-LDN-Assignment-Statistics:\n");
len += sprintf(buffer+len, " Number of physical SCSI-devices..: %d (+ Adapter)\n",
- IBM_DS.total_scsi_devices);
+ IBM_DS(host_index).total_scsi_devices);
len += sprintf(buffer+len, " Dynamical Assignment necessaray..: %s\n",
- IBM_DS.dyn_flag ? "Yes" : "No ");
+ IBM_DS(host_index).dyn_flag ? "Yes" : "No ");
len += sprintf(buffer+len, " Next LDN to be assigned..........: 0x%x\n",
- next_ldn);
+ next_ldn(host_index));
len += sprintf(buffer+len, " Dynamical assignments done yet...: %d\n",
- IBM_DS.dynamical_assignments);
+ IBM_DS(host_index).dynamical_assignments);
len += sprintf(buffer+len, "\n Current SCSI-Device-Mapping:\n");
len += sprintf(buffer+len, " Physical SCSI-Device Map Logical SCSI-Device Map\n");
len += sprintf(buffer+len, " ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n");
for (id=0; id<=7; id++)
{
- len += sprintf(buffer+len, " %2d %2s %2s %2s %2s %2s %2s %2s %2s",
- id, ti_p(get_scsi[id][0]), ti_p(get_scsi[id][1]),
- ti_p(get_scsi[id][2]), ti_p(get_scsi[id][3]),
- ti_p(get_scsi[id][4]), ti_p(get_scsi[id][5]),
- ti_p(get_scsi[id][6]), ti_p(get_scsi[id][7]));
-
- len += sprintf(buffer+len, " %2d ",id);
+ len += sprintf(buffer+len, " %2d ",id);
for (lun=0; lun<8; lun++)
- len += sprintf(buffer+len,"%2s ",ti_l(get_ldn[id][lun]));
+ len += sprintf(buffer+len,"%2s ",ti_p(get_scsi(host_index)[id][lun]));
+ len += sprintf(buffer+len, " %2d ",id);
+ for (lun=0; lun<8; lun++)
+ len += sprintf(buffer+len,"%2s ",ti_l(get_ldn(host_index)[id][lun]));
len += sprintf(buffer+len,"\n");
}
len += sprintf(buffer+len, "(A = IBM-Subsystem, D = Harddisk, T = Tapedrive, P = Processor, W = WORM,\n");
len += sprintf(buffer+len, " R = CD-ROM, S = Scanner, M = MO-Drive, C = Medium-Changer, + = unprovided LUN,\n");
- len += sprintf(buffer+len, " - = nothing found)\n\n");
+ len += sprintf(buffer+len, " - = nothing found, nothing assigned or unprobed LUN)\n\n");
*start = buffer + offset;
len -= offset;
if (len > length)
len = length;
-
+#ifdef OLDKERN
restore_flags(flags);
-
+#else
+ spin_unlock_irqrestore(&proc_lock, flags);
+#endif
return len;
}
@@ -2293,5 +2600,3 @@ Scsi_Host_Template driver_template = IBMMCA;
/*--------------------------------------------------------------------*/
-
-
diff --git a/drivers/scsi/ibmmca.h b/drivers/scsi/ibmmca.h
index 0bf4b3517..58b3094b8 100644
--- a/drivers/scsi/ibmmca.h
+++ b/drivers/scsi/ibmmca.h
@@ -1,24 +1,37 @@
#ifndef _IBMMCA_H
#define _IBMMCA_H
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#ifndef ibmmca_header_linux_version
+#define ibmmca_header_linux_version(v,p,s) (((v)<<16)+((p)<<8)+(s))
+#endif
+
/*
* Low Level Driver for the IBM Microchannel SCSI Subsystem
+ * (Headerfile, see README.ibmmca for description of the IBM MCA SCSI-driver)
*/
+/* Common forward declarations for all Linux-versions: */
+
/*services provided to the higher level of Linux SCSI driver */
-int ibmmca_proc_info (char *, char **, off_t, int, int, int);
-int ibmmca_detect (Scsi_Host_Template *);
-int ibmmca_release (struct Scsi_Host *);
-int ibmmca_command (Scsi_Cmnd *);
-int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
-int ibmmca_abort (Scsi_Cmnd *);
-int ibmmca_reset (Scsi_Cmnd *, unsigned int);
-int ibmmca_biosparam (Disk *, kdev_t, int *);
+extern int ibmmca_proc_info (char *, char **, off_t, int, int, int);
+extern int ibmmca_detect (Scsi_Host_Template *);
+extern int ibmmca_release (struct Scsi_Host *);
+extern int ibmmca_command (Scsi_Cmnd *);
+extern int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
+extern int ibmmca_abort (Scsi_Cmnd *);
+extern int ibmmca_reset (Scsi_Cmnd *, unsigned int);
+extern int ibmmca_biosparam (Disk *, kdev_t, int *);
/*structure for /proc filesystem */
extern struct proc_dir_entry proc_scsi_ibmmca;
-/*initialization for Scsi_host_template type */
+#if LINUX_VERSION_CODE >= ibmmca_header_linux_version(2,1,0)
+/* Stuff for Linux >= 2.1.0: */
+/*initialization for Scsi_host_template type (Linux >= 2.1.0) */
/*
* 2/8/98
* Note to maintainer of IBMMCA. Do not change this initializer back to
@@ -28,7 +41,7 @@ extern struct proc_dir_entry proc_scsi_ibmmca;
#define IBMMCA { \
proc_dir: &proc_scsi_ibmmca, /*proc_dir*/ \
proc_info: ibmmca_proc_info, /*proc info fn*/ \
- name: "IBMMCA", /*name*/ \
+ name: "IBM SCSI-Subsystem", /*name*/ \
detect: ibmmca_detect, /*detect fn*/ \
release: ibmmca_release, /*release fn*/ \
command: ibmmca_command, /*command fn*/ \
@@ -40,9 +53,37 @@ extern struct proc_dir_entry proc_scsi_ibmmca;
this_id: 7, /*set by detect*/ \
sg_tablesize: 16, /*sg_tablesize*/ \
cmd_per_lun: 1, /*cmd_per_lun*/ \
+ unchecked_isa_dma: 0, /*32-Bit Busmaster */ \
use_clustering: ENABLE_CLUSTERING /*use_clustering*/ \
}
-#endif /* _IBMMCA_H */
+#else
+/* Stuff for Linux < 2.1.0: */
+/*initialization for Scsi_host_template type (Linux < 2.1.0) */
+#define IBMMCA { \
+ NULL, /*next*/ \
+ NULL, /*usage_count*/ \
+ &proc_scsi_ibmmca, /*proc_dir*/ \
+ ibmmca_proc_info, /*proc info fn*/ \
+ "IBM SCSI-Subsystem", /*name*/ \
+ ibmmca_detect, /*detect fn*/ \
+ ibmmca_release, /*release fn*/ \
+ NULL, /*info fn*/ \
+ ibmmca_command, /*command fn*/ \
+ ibmmca_queuecommand, /*queuecommand fn*/ \
+ ibmmca_abort, /*abort fn*/ \
+ ibmmca_reset, /*reset fn*/ \
+ NULL, /*slave_attach fn*/ \
+ ibmmca_biosparam, /*bios fn*/ \
+ 16, /*can_queue*/ \
+ 7, /*set by detect*/ \
+ 16, /*sg_tablesize*/ \
+ 1, /*cmd_per_lun*/ \
+ 0, /*present*/ \
+ 0, /*unchecked_isa_dma*/ \
+ ENABLE_CLUSTERING /*use_clustering*/ \
+ }
+#endif /* kernelversion selection */
+#endif /* _IBMMCA_H */
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 4f7315e04..18b2d5e9c 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -23,8 +23,9 @@
* Ver 0.6 Jan 27 98 Allow disabling of SCSI command translation layer
* for access through /dev/sg.
* Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.
- * Ver 0.7 Dev 04 98 Ignore commands where lun != 0 to avoid multiple
+ * Ver 0.7 Dec 04 98 Ignore commands where lun != 0 to avoid multiple
* detection of devices with CONFIG_SCSI_MULTI_LUN
+ * Ver 0.8 Feb 05 99 Optical media need translation too.
*/
#define IDESCSI_VERSION "0.6"
@@ -66,7 +67,7 @@ typedef struct idescsi_pc_s {
int b_count; /* Bytes transferred from current entry */
Scsi_Cmnd *scsi_cmd; /* SCSI command */
void (*done)(Scsi_Cmnd *); /* Scsi completion routine */
- unsigned int flags; /* Status/Action flags */
+ unsigned long flags; /* Status/Action flags */
unsigned long timeout; /* Command timeout */
} idescsi_pc_t;
@@ -91,9 +92,9 @@ typedef struct idescsi_pc_s {
typedef struct {
ide_drive_t *drive;
idescsi_pc_t *pc; /* Current packet command */
- unsigned int flags; /* Status/Action flags */
- int transform; /* SCSI cmd translation layer */
- int log; /* log flags */
+ unsigned long flags; /* Status/Action flags */
+ unsigned long transform; /* SCSI cmd translation layer */
+ unsigned long log; /* log flags */
} idescsi_scsi_t;
/*
@@ -178,7 +179,7 @@ static inline void idescsi_transform_pc1 (ide_drive_t *drive, idescsi_pc_t *pc)
if (!test_bit(PC_TRANSFORM, &pc->flags))
return;
- if (drive->media == ide_cdrom) {
+ if (drive->media == ide_cdrom || drive->media == ide_optical) {
if (c[0] == READ_6 || c[0] == WRITE_6) {
c[8] = c[4]; c[5] = c[3]; c[4] = c[2];
c[3] = c[1] & 0x1f; c[2] = 0; c[1] &= 0xe0;
@@ -217,7 +218,7 @@ static inline void idescsi_transform_pc2 (ide_drive_t *drive, idescsi_pc_t *pc)
if (!test_bit(PC_TRANSFORM, &pc->flags))
return;
- if (drive->media == ide_cdrom) {
+ if (drive->media == ide_cdrom || drive->media == ide_optical) {
if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) {
scsi_buf[0] = atapi_buf[1]; /* Mode data length */
scsi_buf[1] = atapi_buf[2]; /* Medium type */
@@ -730,9 +731,6 @@ int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
printk (KERN_ERR "ide-scsi: drive id %d not present\n", cmd->target);
goto abort;
}
- if (cmd->lun != 0) { /* Only respond to LUN 0. Drop others */
- goto abort;
- }
scsi = drive->driver_data;
pc = kmalloc (sizeof (idescsi_pc_t), GFP_ATOMIC);
rq = kmalloc (sizeof (struct request), GFP_ATOMIC);
@@ -794,7 +792,7 @@ int idescsi_abort (Scsi_Cmnd *cmd)
int idescsi_reset (Scsi_Cmnd *cmd, unsigned int resetflags)
{
- return SCSI_RESET_PUNT;
+ return SCSI_RESET_SUCCESS;
}
int idescsi_bios (Disk *disk, kdev_t dev, int *parm)
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index deddc28ba..fa8844b67 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -881,6 +881,7 @@ static void imm_interrupt(void *data)
{
imm_struct *tmp = (imm_struct *) data;
Scsi_Cmnd *cmd = tmp->cur_cmd;
+ unsigned long flags;
if (!cmd) {
printk("IMM: bug in imm_interrupt\n");
@@ -931,8 +932,10 @@ static void imm_interrupt(void *data)
if (cmd->SCp.phase > 0)
imm_pb_release(cmd->host->unique_id);
+ spin_lock_irqsave(&io_request_lock, flags);
tmp->cur_cmd = 0;
cmd->scsi_done(cmd);
+ spin_unlock_irqrestore(&io_request_lock, flags);
return;
}
@@ -1204,19 +1207,16 @@ static int device_check(int host_no)
status = imm_out(host_no, &cmd[l << 1], 2);
if (!status) {
- imm_disconnect(host_no);
- imm_connect(host_no, CONNECT_EPP_MAYBE);
- w_dtr(ppb, 0x40);
- w_ctr(ppb, 0x08);
- udelay(30);
- w_ctr(ppb, 0x0c);
- udelay(1000);
- imm_disconnect(host_no);
- udelay(1000);
- if (imm_hosts[host_no].mode == IMM_EPP_32) {
- imm_hosts[host_no].mode = old_mode;
- goto second_pass;
- }
+ imm_disconnect(host_no);
+ imm_connect(host_no, CONNECT_EPP_MAYBE);
+ imm_reset_pulse(IMM_BASE(host_no));
+ udelay(1000);
+ imm_disconnect(host_no);
+ udelay(1000);
+ if (imm_hosts[host_no].mode == IMM_EPP_32) {
+ imm_hosts[host_no].mode = old_mode;
+ goto second_pass;
+ }
printk("imm: Unable to establish communication, aborting driver load.\n");
return 1;
}
diff --git a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c
new file mode 100644
index 000000000..b6f4eb34f
--- /dev/null
+++ b/drivers/scsi/inia100.c
@@ -0,0 +1,952 @@
+/**************************************************************************
+ * 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 <linux/version.h>
+#endif
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+#include <stdarg.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92)
+#include <linux/bios32.h>
+#endif
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23)
+#include <linux/init.h>
+#endif
+#include <linux/blk.h>
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+#include <asm/spinlock.h>
+#endif
+#include "sd.h"
+#include "scsi.h"
+#include "hosts.h"
+#include "inia100.h"
+#include <linux/stat.h>
+#include <linux/malloc.h>
+
+
+#else
+
+#include <linux/kernel.h>
+#include <linux/head.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include "../block/blk.h"
+#include "scsi.h"
+#include "sd.h"
+#include "hosts.h"
+#include <linux/malloc.h>
+#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 --git a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h
new file mode 100644
index 000000000..e269ea7bc
--- /dev/null
+++ b/drivers/scsi/inia100.h
@@ -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 <linux/version.h>
+#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 --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 13882a253..05f95e626 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -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 : 1.00
*
* Description: Linux device driver for AMI MegaRAID controller
*
+ * Supported controllers: MegaRAID 418, 428, 438, 466, 762
+ *
+ * Maintainer: Jeff L Jones <jeffreyj@ami.com>
+ *
* 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,43 +38,79 @@
* 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 <alan.cox@linux.org>
+ * 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 <alan.cox@linux.org>
*
* Merged with 2.1.131 source tree.
- * 12 Dec 98 K. Baranowski <kgb@knm.org.pl>
+ * 12 Dec 98 K. Baranowski <kgb@knm.org.pl>
+ *
+ * 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.
+ *
+ * Version 0.94:
+ * Got rid of some excess locking/unlocking
+ * Fixed slight memory corruption problem while memcpy'ing into mailbox
+ * Changed logical drives to be reported as luns rather than targets
+ * Changed max_id to 16 since it is now max targets/chan again.
+ * Improved ioctl interface for upcoming megamgr
+ *
+ * Version 0.95:
+ * Fixed problem of queueing multiple commands to adapter;
+ * still has some strange problems on some setups, so still
+ * defaults to single. To enable parallel commands change
+ * #define MULTI_IO in megaraid.h
+ * Changed kmalloc allocation to be done in beginning.
+ * Got rid of C++ style comments
+ *
+ * Version 0.96:
+ * 762 fully supported.
+ * Version 0.97:
+ * Changed megaraid_command to use wait_queue.
+ * Fixed bug of undesirably detecting HP onboard controllers which
+ * are disabled.
+ *
+ * Version 1.00:
+ * Checks to see if an irq ocurred while in isr, and runs through
+ * routine again.
+ * Copies mailbox to temp area before processing in isr
+ * Added barrier() in busy wait to fix volatility bug
+ * Uses separate list for freed Scbs, keeps track of cmd state
+ * Put spinlocks around entire queue function for now...
+ * Full multi-io commands working stablely without previous problems
+ * Added skipXX LILO option for Madrona motherboard support
+ *
*
* 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.
+ *
+ * Timeout period for mid scsi layer is too short for
+ * this controller. Must be increased or Aborts will occur.
*
*===================================================================*/
-#define QISR 1
#define CRLFSTR "\n"
-#define MULTIQ 1
-
#include <linux/version.h>
#ifdef MODULE
+#include <linux/modversions.h>
#include <linux/module.h>
#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
@@ -112,14 +151,18 @@ MODULE_DESCRIPTION("AMI MegaRAID driver");
*
* #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);\
@@ -143,7 +186,15 @@ typedef struct {volatile char lock;} spinlock_t;
(*node) = obj; \
(*node)->##next = NULL; \
spin_unlock_irqrestore(&mega_lock,cpuflag);\
-};
+}
+
+/* a non-locking version (if we already have the lock) */
+#define ENQUEUE_NL(obj,type,list,next) \
+{ type **node; \
+ for(node=&(list); *node; node=(type **)&(*node)->##next); \
+ (*node) = obj; \
+ (*node)->##next = NULL; \
+}
#define DEQUEUE(obj,type,list,next) \
{ long cpuflag; \
@@ -154,125 +205,146 @@ typedef struct {volatile char lock;} spinlock_t;
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,
+ *================================================================
+ */
+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 int mega_busyWaitMbox(mega_host_config *);
+static void mega_runpendq (mega_host_config *);
+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);
+static inline void freeSgList(mega_host_config *megaCfg);
/* 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 };
+ *================================================================
+ */
+
+/* Use "megaraid=skipXX" to prohibit driver from scanning XX scsi id
+ on each channel. Used for Madrona motherboard, where SAF_TE
+ processor id cannot be scanned */
+static char *megaraid;
+#if LINUX_VERSION_CODE > 0x20100
+#ifdef MODULE
+MODULE_PARM(megaraid, "s");
+#endif
+#endif
+static int skip_id;
+
+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;
+#if DEBUG
+static u_long maxCmdTime = 0;
+#endif
+
+static mega_scb *pLastScb = NULL;
/* Queue of pending/completed SCBs */
-static mega_scb *qPending = NULL;
static Scsi_Cmnd *qCompleted = NULL;
+#if SERDEBUG
+volatile static spinlock_t serial_lock;
+#endif
volatile static spinlock_t mega_lock;
-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;
-
- 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);
+ 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);
}
-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;
-
- while ((inb(port+5) & 0x20)==0);
- outb(c,port);
- if (c==0x0a)
- {
- while ((inb(port+5) & 0x20)==0);
- outb(0x0d,port);
- }
+ 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);
+ }
}
-static int ser_printk(const char *fmt, ...)
+static int ser_printk (const char *fmt,...)
{
- 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_list args;
+ int i;
+ long flags;
+
+ spin_lock_irqsave(&serial_lock,flags);
+ va_start (args, fmt);
+ i = vsprintf (strbuf, fmt, args);
+ ser_puts (strbuf);
+ va_end (args);
+ spin_unlock_irqrestore(&serial_lock,flags);
- return i;
+ return i;
}
#define TRACE(a) { ser_printk a;}
@@ -281,14 +353,14 @@ static int ser_printk(const char *fmt, ...)
#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,165 +369,164 @@ void callDone(Scsi_Cmnd *SCpnt)
*
*-------------------------------------------------------------------------*/
-/*================================================
- * Initialize SCB structures
- *================================================*/
-static void initSCB(mega_host_config *megaCfg)
+/*=======================
+ * Free a SCB structure
+ *=======================
+ */
+static void freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
{
- int idx;
+ mega_scb **ppScb;
- 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;
+ /* Unlink from pending queue */
+ for(ppScb=&megaCfg->qPending; *ppScb; ppScb=&(*ppScb)->next) {
+ if (*ppScb == pScb) {
+ *ppScb = pScb->next;
+ break;
+ }
}
+
+ /* Link back into list */
+ pScb->state = SCB_FREE;
+ pScb->SCpnt = NULL;
+
+ pScb->next = megaCfg->qFree;
+ megaCfg->qFree = pScb;
}
/*===========================
* Allocate a SCB structure
- *===========================*/
-static mega_scb *allocateSCB(mega_host_config *megaCfg,Scsi_Cmnd *SCpnt)
+ *===========================
+ */
+static mega_scb * allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
{
- int idx;
- long flags;
+ mega_scb *pScb;
- 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;
- megaCfg->scbList[idx].SCpnt = SCpnt;
- 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);
- }
+ /* Unlink command from Free List */
+ if ((pScb = megaCfg->qFree) != NULL) {
+ megaCfg->qFree = pScb->next;
+
+ pScb->isrcount = jiffies;
+ pScb->next = NULL;
+ pScb->state = SCB_ACTIVE;
+ pScb->SCpnt = SCpnt;
- return &megaCfg->scbList[idx];
- }
+ return pScb;
}
- 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)
+/*================================================
+ * Initialize SCB structures
+ *================================================
+ */
+static int initSCB (mega_host_config * megaCfg)
{
- long flags;
+ int idx;
- spin_lock_irqsave(&mega_lock,flags);
- scb->flag = 0;
- scb->idx = -1;
- scb->next = NULL;
- scb->SCpnt = NULL;
- spin_unlock_irqrestore(&mega_lock,flags);
+ megaCfg->qFree = NULL;
+ for (idx = megaCfg->max_cmds-1; idx >= 0; idx--) {
+ megaCfg->scbList[idx].idx = idx;
+ megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist) * MAX_SGLIST,
+ GFP_ATOMIC | GFP_DMA);
+ if (megaCfg->scbList[idx].sgList == NULL) {
+ printk(KERN_WARNING "Can't allocate sglist for id %d\n",idx);
+ freeSgList(megaCfg);
+ return -1;
+ }
+
+ if (idx < MAX_COMMANDS) {
+ /* Link to free list */
+ freeSCB(megaCfg, &megaCfg->scbList[idx]);
+ }
+ }
+ return 0;
}
/* Run through the list of completed requests */
-static void mega_rundoneq()
+static void mega_rundoneq ()
{
- mega_host_config *megaCfg;
- Scsi_Cmnd *SCpnt;
- long islogical;
-
- while(1) {
- DEQUEUE(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
- if (SCpnt == NULL) return;
-
- 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
- * if use_raid == 0 and this was a disk on the max channel
- * then fail.
- */
- islogical = (SCpnt->channel == megaCfg->host->max_channel) ? 1 : 0;
- if (SCpnt->cmnd[0] == INQUIRY &&
- ((((u_char*)SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) &&
- (islogical != use_raid)) {
- SCpnt->result = 0xF0;
- }
+ Scsi_Cmnd *SCpnt;
- /* Convert result to error */
- switch(SCpnt->result) {
- case 0x00: case 0x02:
- SCpnt->result |= (DID_OK << 16);
- break;
- case 0x8:
- SCpnt->result |= (DID_BUS_BUSY << 16);
- break;
- default:
- SCpnt->result |= (DID_BAD_TARGET << 16);
- break;
- }
+ while (1) {
+ DEQUEUE (SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+ if (SCpnt == NULL)
+ return;
/* 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)
+/*
+ Runs through the list of pending requests
+ Assumes that mega_lock spin_lock has been acquired.
+*/
+static void mega_runpendq(mega_host_config *megaCfg)
{
- pScb->SCpnt->result = status;
- ENQUEUE(pScb->SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
- freeSCB(pScb);
+ mega_scb *pScb;
+
+ /* Issue any pending commands to the card */
+ for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+ if (pScb->state == SCB_ACTIVE) {
+ megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1);
+ }
+ }
}
-/*----------------------------------------------------
- * Process pending queue list
- *
- * Run as a scheduled task
- *----------------------------------------------------*/
-static void mega_runque(void *dummy)
+/* Add command to the list of completed requests */
+static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb,
+ int status)
{
- mega_host_config *megaCfg;
- mega_scb *pScb;
- long flags;
+ int islogical;
+ Scsi_Cmnd *SCpnt;
- /* Take care of any completed requests */
- mega_rundoneq();
+ if (pScb == NULL) {
+ TRACE(("NULL pScb in mega_cmd_done!"));
+ printk("NULL pScb in mega_cmd_done!");
+ }
- DEQUEUE(pScb,mega_scb,qPending,next);
-
- if (pScb) {
- 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));
- }
+ SCpnt = pScb->SCpnt;
+ freeSCB(megaCfg, pScb);
- if (MegaIssueCmd(megaCfg, pScb->mboxData, pScb, 1)) {
- /* We're BUSY... come back later */
- spin_lock_irqsave(&mega_lock,flags);
- pScb->next = qPending;
- qPending = pScb;
- spin_unlock_irqrestore(&mega_lock,flags);
+ if (SCpnt == NULL) {
+ TRACE(("NULL SCpnt in mega_cmd_done!"));
+ TRACE(("pScb->idx = ",pScb->idx));
+ TRACE(("pScb->state = ",pScb->state));
+ TRACE(("pScb->state = ",pScb->state));
+ printk("Problem...!\n");
+ while(1);
+ }
- if (!(megaCfg->flag & PENDING)) { /* If PENDING, irq will schedule task */
- queue_task(&runq, &tq_scheduler);
- }
- }
+ islogical = (SCpnt->channel == megaCfg->host->max_channel &&
+ SCpnt->target == 0);
+ if (SCpnt->cmnd[0] == INQUIRY &&
+ ((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) &&
+ !islogical) {
+ status = 0xF0;
}
+
+ SCpnt->result = 0; /* clear result; otherwise, success returns corrupt
+ value */
+
+ /* Convert MegaRAID status to Linux error code */
+ switch (status) {
+ case 0x00: /* SUCCESS */
+ case 0x02: /* ERROR_ABORTED */
+ SCpnt->result |= (DID_OK << 16);
+ break;
+ case 0x8: /* ERR_DEST_DRIVE_FAILED */
+ SCpnt->result |= (DID_BUS_BUSY << 16);
+ break;
+ default:
+ SCpnt->result |= (DID_BAD_TARGET << 16);
+ break;
+ }
+
+ /* Add Scsi_Command to end of completed queue */
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
}
/*-------------------------------------------------------------------
@@ -466,64 +537,82 @@ static void mega_runque(void *dummy)
* 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;
+ char islogical;
+
+ if (SCpnt == NULL) {
+ printk("NULL SCpnt in mega_build_cmd!\n");
+ while(1);
+ }
+
+ if (SCpnt->cmnd[0] & 0x80) /* ioctl from megamgr */
+ return mega_ioctl (megaCfg, SCpnt);
+
+ islogical = (SCpnt->channel == megaCfg->host->max_channel && SCpnt->target == 0);
- /* We don't support multi-luns */
- if (SCpnt->lun != 0) {
+ if (!islogical && SCpnt->lun != 0) {
SCpnt->result = (DID_BAD_TARGET << 16);
- callDone(SCpnt);
+ callDone (SCpnt);
return NULL;
}
+ if (!islogical && SCpnt->target == skip_id) {
+ SCpnt->result = (DID_BAD_TARGET << 16);
+ callDone (SCpnt);
+ return NULL;
+ }
+
/*-----------------------------------------------------
*
* Logical drive commands
*
*-----------------------------------------------------*/
- if (SCpnt->channel == megaCfg->host->max_channel) {
- switch(SCpnt->cmnd[0]) {
+ if (islogical) {
+ 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;
-
- 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);
+ mbox = (mega_mailbox *) & pScb->mboxData;
+
+ memset (mbox, 0, sizeof (pScb->mboxData));
+ memset (pthru, 0, sizeof (mega_passthru));
+ pthru->timeout = 0;
+ pthru->ars = 1;
+ pthru->reqsenselen = 14;
+ pthru->islogical = 1;
+ pthru->logdrv = SCpnt->lun;
+ 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 +621,51 @@ static mega_scb *mega_build_cmd(mega_host_config *megaCfg, Scsi_Cmnd *SCpnt)
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));
- mbox->logdrv = SCpnt->target;
- mbox->cmd = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ?
+ memset (mbox, 0, sizeof (pScb->mboxData));
+ mbox->logdrv = SCpnt->lun;
+ 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 +676,32 @@ static mega_scb *mega_build_cmd(mega_host_config *megaCfg, Scsi_Cmnd *SCpnt)
*-----------------------------------------------------*/
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 = 1;
+ pthru->reqsenselen = 14;
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,105 +709,229 @@ static mega_scb *mega_build_cmd(mega_host_config *megaCfg, Scsi_Cmnd *SCpnt)
}
/*--------------------------------------------------------------------
+ * 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;
+ unsigned char *data = (unsigned char *)SCpnt->request_buffer;
+ int i;
+
+ if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+ SCpnt->result = (DID_ERROR << 16);
+ callDone (SCpnt);
+ return NULL;
+ }
+
+#if 0
+ printk("\nBUF: ");
+ for (i=0;i<18;i++) {
+ printk(" %x",data[i]);
+ }
+ printk("......\n");
+#endif
+
+ mbox = (mega_ioctl_mbox *) & pScb->mboxData;
+ mailbox = (mega_mailbox *) & pScb->mboxData;
+ memset (mailbox, 0, sizeof (pScb->mboxData));
+
+ if (data[0] == 0x03) { /* passthrough command */
+ unsigned char cdblen = data[2];
+
+ pthru = &pScb->pthru;
+ memset (pthru, 0, sizeof (mega_passthru));
+ pthru->islogical = (data[cdblen+3] & 0x80) ? 1:0;
+ pthru->timeout = data[cdblen+3] & 0x07;
+ pthru->reqsenselen = 14;
+ pthru->ars = (data[cdblen+3] & 0x08) ? 1:0;
+ pthru->logdrv = data[cdblen+4];
+ pthru->channel = data[cdblen+5];
+ pthru->target = data[cdblen+6];
+ pthru->cdblen = cdblen;
+ memcpy (pthru->cdb, &data[3], cdblen);
+
+ 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);
+
+ for (i=0;i<(SCpnt->request_bufflen-cdblen-7);i++) {
+ data[i] = data[i+cdblen+7];
+ }
+
+ return pScb;
+ }
+ /* else normal (nonpassthru) command */
+
+ mbox->cmd = data[0];
+ mbox->channel = data[1];
+ mbox->param = data[2];
+ mbox->pad[0] = data[3];
+ mbox->logdrv = data[4];
+
+ mbox->numsgelements = build_sglist (megaCfg, pScb,
+ (u_long *) & mbox->xferaddr,
+ (u_long *) & seg);
+
+ for (i=0;i<(SCpnt->request_bufflen-6);i++) {
+ data[i] = data[i+6];
+ }
+
+ return (pScb);
+}
+
+#if DEBUG
+static void showMbox(mega_scb *pScb)
+{
+ mega_mailbox *mbox;
+
+ if (pScb == NULL) return;
+
+ mbox = (mega_mailbox *)pScb->mboxData;
+ printk("%u cmd:%x id:%x #scts:%x lba:%x addr:%x logdrv:%x #sg:%x\n",
+ pScb->SCpnt->pid,
+ mbox->cmd, mbox->cmdid, mbox->numsectors,
+ mbox->lba, mbox->xferaddr, mbox->logdrv,
+ mbox->numsgelements);
+}
+#endif
+
+/*--------------------------------------------------------------------
* 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, tmpBox[MAILBOX_SIZE];
+ 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 *)tmpBox;
- if (megaCfg->host->irq == irq) {
- spin_lock_irqsave(&mega_lock,flags);
+#if LINUX_VERSION_CODE >= 0x20100
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif
+
+ while (megaCfg->host->irq == irq) {
+
+ 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;
+ if (mega_busyWaitMbox(megaCfg)) {
+ printk(KERN_WARNING "Error: mailbox busy in isr!\n");
+ }
+
+
/* 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);
+ break;
+ }
+ WROUTDOOR (megaCfg, dword);
+
+ /* Copy to temp location */
+ memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
+
+ /* Acknowledge interrupt */
+ WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
+ while (RDINDOOR (megaCfg) & 0x02);
}
-
- qCnt = mbox->numstatus;
- qStatus = mbox->status;
+ 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);
+ break;
+ }
+ WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
- if (qCnt > 1) {TRACE(("ISR: Received %d status\n", qCnt))
- printk(KERN_DEBUG "Got numstatus = %d\n",qCnt);
+ /* Copy to temp location */
+ memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
+
+ /* Acknowledge interrupt */
+ CLEAR_INTR (megaCfg->host->io_port);
}
-
- for(idx=0; idx<qCnt; idx++) {
+
+ qCnt = mbox->numstatus;
+ qStatus = mbox->status;
+
+ for (idx = 0; idx < qCnt; idx++) {
sIdx = mbox->completed[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];
+
+ /* ASSERT(pScb->state == SCB_ISSUED); */
+
+#if DEBUG
+ if (((jiffies) - pScb->isrcount) > maxCmdTime) {
+ maxCmdTime = (jiffies) - pScb->isrcount;
+ printk("cmd time = %u\n", maxCmdTime);
+ }
+#endif
+
+ if (pScb->state == SCB_ABORTED) {
+ printk("Received aborted SCB! %u\n", (int)((jiffies)-pScb->isrcount));
+ }
+
+ /* Mark command as completed */
+ mega_cmd_done(megaCfg, pScb, qStatus);
}
+
}
- if (megaCfg->flag & BOARD_QUARTZ) {
- WRINDOOR(megaCfg,virt_to_bus(megaCfg->mbox)|0x2);
- while (RDINDOOR(megaCfg) & 0x02);
- } else {
- CLEAR_INTR(megaCfg->host->io_port);
- }
+ spin_unlock_irqrestore (&mega_lock, flags);
megaCfg->flag &= ~IN_ISR;
- megaCfg->flag &= ~PENDING;
-
- spin_unlock_irqrestore(&mega_lock,flags);
- spin_lock_irqsave(&io_request_lock, flags);
- mega_runque(NULL);
- spin_unlock_irqrestore(&io_request_lock,flags);
+ mega_rundoneq();
-#if 0
- /* Queue as a delayed ISR routine */
- queue_task_irq_off(&runq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ /* Loop through any pending requests */
+ spin_lock_irqsave(&mega_lock, flags);
+ mega_runpendq(megaCfg);
spin_unlock_irqrestore(&mega_lock,flags);
-#endif
-
}
+
+#if LINUX_VERSION_CODE >= 0x20100
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif
}
/*==================================================*/
/* Wait until the controller's mailbox is available */
/*==================================================*/
-static int busyWaitMbox(mega_host_config *megaCfg)
+static int mega_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 < 10000; counter++) {
+ if (!mbox->busy) {
+ return 0;
+ }
+ udelay (100);
+ barrier();
}
- return -1;
+ return -1; /* give up after 1 second */
}
/*=====================================================
@@ -728,93 +942,113 @@ static int busyWaitMbox(mega_host_config *megaCfg)
* 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)
+ *=====================================================
+ */
+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 */
+ mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
+ u_char byte;
+ u_long cmdDone;
+ Scsi_Cmnd *SCpnt;
+
+ mboxData[0x1] = (pScb ? pScb->idx + 1: 0x0); /* Set cmdid */
+ mboxData[0xF] = 1; /* Set busy */
- /* 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) {
- return -1;
+#if 0
+ if (intr && mbox->busy) {
+ return 0;
}
+#endif
/* Wait until mailbox is free */
- 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));
+ while (mega_busyWaitMbox (megaCfg)) {
+ printk("Blocked mailbox!!\n");
+ udelay(1000);
+
+#if DEBUG
+ showMbox(pLastScb);
+#endif
+
+ /* Abort command */
+ if (pScb == NULL) {
+ printk("NULL pScb in megaIssue\n");
+ TRACE(("NULL pScb in megaIssue\n"));
}
- return -1;
+ SCpnt = pScb->SCpnt;
+ freeSCB(megaCfg, pScb);
+
+ SCpnt->result = (DID_ABORT << 16);
+ callDone(SCpnt);
+ return 0;
}
+ pLastScb = pScb;
+
/* 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);
+ 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);
}
+ pScb->state = SCB_ISSUED;
}
- else { /* Issue non-ISR (blocking) command */
-
+ else { /* Issue non-ISR (blocking) command */
+ disable_irq(megaCfg->host->irq);
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);
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);
+
if (pScb) {
- mega_cmd_done(megaCfg,pScb, mbox->status);
- mega_rundoneq();
+ mega_cmd_done (megaCfg, pScb, mbox->status);
+ mega_rundoneq ();
+ }
+ else {
+ TRACE (("Error: NULL pScb!\n"));
}
- megaCfg->flag &= ~PENDING;
+
}
+ enable_irq(megaCfg->host->irq);
+ }
+ while (mega_busyWaitMbox (megaCfg)) {
+ printk("Blocked mailbox on exit!\n");
+ udelay(1000);
}
return 0;
@@ -823,42 +1057,42 @@ static int MegaIssueCmd(mega_host_config *megaCfg,
/*-------------------------------------------------------------------
* 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->request_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; 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;
+ 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 +1107,25 @@ static int build_sglist(mega_host_config *megaCfg, mega_scb *scb,
* 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 +1133,80 @@ static int mega_register_mailbox(mega_host_config *megaCfg, u_long paddr)
/*-------------------------------------------------------------------
* 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 = 16; /* max targets/chan */
+ megaCfg->numldrv = adapterInfo->LogdrvInfo.NumLDrv;
#if 0
- printk(KERN_DEBUG "---- Logical drive info ----\n");
- for(i=0; i<megaCfg->numldrv; 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 ---- 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 (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,56 +1219,72 @@ static int mega_i_query_adapter(mega_host_config *megaCfg)
/*----------------------------------------------------------
* 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 host_no, 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 jdx,pciIdx = 0;
+ u_short numFound = 0;
#if LINUX_VERSION_CODE < 0x20100
- while(!pcibios_find_device(pciVendor, pciDev, pciIdx,&pciBus,&pciDevFun)) {
-#else
- struct pci_dev *pdev=pci_devices;
+ while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
- while((pdev = pci_find_device(pciVendor, pciDev, pdev))) {
+#if 0
+ } /* keep auto-indenters happy */
+#endif
+#else
+
+ struct pci_dev *pdev = pci_devices;
+
+ 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));
-
+ if (flag & BOARD_QUARTZ) {
+ u_short magic;
+ pcibios_read_config_word (pciBus, pciDevFun,
+ PCI_CONF_AMISIG,
+ &magic);
+ if (magic != AMI_SIGNATURE) {
+ pciIdx++;
+ continue; /* not an AMI board */
+ }
+ }
+ 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;
+ megaIrq = pdev->irq;
#endif
pciIdx++;
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,72 +1292,92 @@ int findCard(Scsi_Host_Template *pHostTmpl,
}
/* 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));
+ host = scsi_register (pHostTmpl, sizeof (mega_host_config));
+ megaCfg = (mega_host_config *) host->hostdata;
+ memset (megaCfg, 0, sizeof (mega_host_config));
+
+ printk (" scsi%d: Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR,
+ host->host_no, (u_int) megaBase, megaIrq);
- 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->qPending = NULL;
+ megaCfg->qFree = NULL;
+ 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);
+
+ for(jdx=0; jdx<MAX_LOGICAL_DRIVES; jdx++) {
+ megaCfg->nReads[jdx] = 0;
+ megaCfg->nWrites[jdx] = 0;
+ }
/* Initialize SCBs */
- initSCB(megaCfg);
+ if (initSCB (megaCfg)) {
+ scsi_unregister (host);
+ continue;
+ }
+ numFound++;
}
- return pciIdx;
+ return numFound;
}
/*---------------------------------------------------------
* 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
+ skip_id = -1;
+ if (megaraid && !strncmp(megaraid,"skip",strlen("skip"))) {
+ if (megaraid[4] != '\0') {
+ skip_id = megaraid[4] - '0';
+ if (megaraid[5] != '\0') {
+ skip_id = (skip_id * 10) + (megaraid[5] - '0');
+ }
+ }
+ skip_id = (skip_id > 15) ? -1 : skip_id;
+ }
- 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,54 +1385,66 @@ int megaraid_detect(Scsi_Host_Template *pHostTmpl)
/*---------------------------------------------------------------------
* 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];
- 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);
+ free_irq (megaCfg->host->irq, megaCfg);/* Must be freed first, otherwise
+ extra interrupt is generated */
- schedule();
+ /* Issue a blocking (interrupts disabled) command to the card */
+ megaIssueCmd (megaCfg, mboxData, NULL, 0);
/* Free our resources */
if (megaCfg->flag & BOARD_QUARTZ) {
- iounmap((void *)megaCfg->base);
- } else {
- release_region(megaCfg->host->io_port, 16);
+ 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);
+
+ freeSgList(megaCfg);
+ scsi_unregister (pSHost);
return 0;
}
+static inline void freeSgList(mega_host_config *megaCfg)
+{
+ int i;
+
+ for (i = 0; i < megaCfg->max_cmds; i++) {
+ if (megaCfg->scbList[i].sgList)
+ kfree (megaCfg->scbList[i].sgList); /* free sgList */
+ }
+}
+
/*----------------------------------------------
* 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,67 +1463,86 @@ const char *megaraid_info(struct Scsi_Host *pSHost)
* 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;
+ long flags;
+
+ spin_lock_irqsave(&mega_lock,flags);
- 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;
+ /* If driver in abort or reset.. cancel this command */
+ if (megaCfg->flag & IN_ABORT) {
+ SCpnt->result = (DID_ABORT << 16);
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+
+ spin_unlock_irqrestore(&mega_lock,flags);
+ return 0;
+ }
+ else if (megaCfg->flag & IN_RESET) {
+ SCpnt->result = (DID_RESET << 16);
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+
+ spin_unlock_irqrestore(&mega_lock,flags);
+ return 0;
+ }
+
/* 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_NL (pScb, mega_scb, megaCfg->qPending, next);
- /* Issue the command to the card */
- mega_runque(NULL);
+ /* Issue any pending command to the card if not in ISR */
+ if (!(megaCfg->flag & IN_ISR)) {
+ mega_runpendq(megaCfg);
+ }
+ else {
+ printk("IRQ pend...\n");
+ }
}
+ spin_unlock_irqrestore(&mega_lock,flags);
+
return 0;
}
/*----------------------------------------------------------------------
* 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 struct wait_queue *internal_wait = NULL;
-static void internal_done(Scsi_Cmnd *SCpnt)
+static void internal_done (Scsi_Cmnd * SCpnt)
{
internal_done_errcode = SCpnt->result;
internal_done_flag++;
+ wake_up(&internal_wait);
}
-/*
- * 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
- */
-
-int megaraid_command(Scsi_Cmnd *SCpnt)
+/* shouldn't be used, but included for completeness */
+
+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) {
+ interruptible_sleep_on(&internal_wait);
+ }
return internal_done_errcode;
}
@@ -1246,67 +1550,122 @@ int megaraid_command(Scsi_Cmnd *SCpnt)
/*---------------------------------------------------------------------
* 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 rc, idx;
+ long flags;
+ mega_scb *pScb;
- spin_lock_irqsave(&mega_lock,flags);
+ rc = SCSI_ABORT_SUCCESS;
+
+ spin_lock_irqsave (&mega_lock, flags);
+
+ megaCfg = (mega_host_config *) SCpnt->host->hostdata;
- megaCfg = (mega_host_config *)SCpnt->host->hostdata;
+ megaCfg->flag |= IN_ABORT;
+
+ for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+ if (pScb->SCpnt == SCpnt) {
+ /* Found an aborting command */
+#if DEBUG
+ showMbox(pScb);
+#endif
+
+ printk("Abort: %d %u\n",
+ SCpnt->timeout_per_command,
+ (uint)((jiffies) - pScb->isrcount));
+
+ switch(pScb->state) {
+ case SCB_ABORTED: /* Already aborted */
+ rc = SCSI_ABORT_SNOOZE;
+ break;
+ case SCB_ISSUED: /* Waiting on ISR result */
+ rc = SCSI_ABORT_PENDING;
+ pScb->state = SCB_ABORTED;
+ break;
+ }
+ }
+ }
+
+#if 0
+ TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
+ SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+ SCpnt->lun));
+ for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+ if (pScb->SCpnt == SCpnt) {
+ ser_printk("** %d<%x> %c\n", pScb->SCpnt->pid, pScb->idx+1,
+ pScb->state == SCB_ACTIVE ? 'A' : 'I');
+#if DEBUG
+ showMbox(pScb);
+#endif
+ }
+ }
+#endif
- 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; idx<megaCfg->max_cmds; idx++) {
- if (megaCfg->scbList[idx].idx >= 0) {
+ for (idx = 0; idx < megaCfg->max_cmds; idx++) {
+ if (megaCfg->scbList[idx].state != SCB_FREE) {
if (megaCfg->scbList[idx].SCpnt == SCpnt) {
- freeSCB(&megaCfg->scbList[idx]);
+ freeSCB (megaCfg, &megaCfg->scbList[idx]);
- SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY<<24);
- callDone(SCpnt);
+ SCpnt->result = (DID_ABORT << 16) | (SUGGEST_RETRY << 24);
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
}
}
}
- spin_unlock_irqrestore(&mega_lock,flags);
- return SCSI_ABORT_SNOOZE;
+
+ megaCfg->flag &= ~IN_ABORT;
+
+ spin_unlock_irqrestore (&mega_lock, flags);
+
+ mega_rundoneq();
+
+ return rc;
}
/*---------------------------------------------------------------------
* 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;
+ megaCfg->flag |= IN_RESET;
- 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; idx<megaCfg->max_cmds; idx++) {
- if (megaCfg->scbList[idx].idx >= 0) {
+ for (idx = 0; idx < megaCfg->max_cmds; idx++) {
+ if (megaCfg->scbList[idx].state != SCB_FREE) {
SCpnt = megaCfg->scbList[idx].SCpnt;
- freeSCB(&megaCfg->scbList[idx]);
- SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY<<24);
- callDone(SCpnt);
+ if (SCpnt != NULL) {
+ freeSCB (megaCfg, &megaCfg->scbList[idx]);
+ SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+ }
}
}
- spin_unlock_irqrestore(&mega_lock,flags);
+
+ megaCfg->flag &= ~IN_RESET;
+
+ spin_unlock_irqrestore (&mega_lock, flags);
+
+ mega_rundoneq();
return SCSI_RESET_PUNT;
-}
+}
/*-------------------------------------------------------------
* Return the disk geometry for a particular disk
@@ -1318,23 +1677,23 @@ int megaraid_reset(Scsi_Cmnd *SCpnt, unsigned int rstflags)
* 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 --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index b020d1b78..7f0909ded 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -1,27 +1,28 @@
#ifndef __MEGARAID_H__
#define __MEGARAID_H__
+#ifndef LINUX_VERSION_CODE
#include <linux/version.h>
+#endif
#define IN_ISR 0x80000000L
-#define NO_INTR 0x40000000L
-#define IN_TIMEOUT 0x20000000L
-#define PENDING 0x10000000L
+#define IN_ABORT 0x40000000L
+#define IN_RESET 0x20000000L
#define BOARD_QUARTZ 0x08000000L
-#define SCB_ACTIVE 0x1
-#define SCB_WAITQ 0x2
-#define SCB_ISSUED 0x4
-
-#define SCB_FREE -1
-#define SCB_RESET -2
-#define SCB_ABORT -3
-#define SCB_LOCKED -4
+#define SCB_FREE 0x0
+#define SCB_ACTIVE 0x1
+#define SCB_WAITQ 0x2
+#define SCB_ISSUED 0x3
+#define SCB_COMPLETE 0x4
+#define SCB_ABORTED 0x5
+#define SCB_RESET 0x6
#define MEGA_CMD_TIMEOUT 10
-#define MAX_SGLIST 20
-#define MAX_COMMANDS 254
+#define MAX_SGLIST 17
+#define MAX_COMMANDS 250
+#define MAX_CMD_PER_LUN 63
#define MAX_LOGICAL_DRIVES 8
#define MAX_CHANNEL 5
@@ -56,7 +57,7 @@
#define I_TOGGLE_PORT 0x01
#define INTR_PORT 0x0a
-#define MAILBOX_SIZE 70
+#define MAILBOX_SIZE (sizeof(mega_mailbox)-16)
#define MBOX_BUSY_PORT 0x00
#define MBOX_PORT0 0x04
#define MBOX_PORT1 0x05
@@ -96,6 +97,8 @@
#define PCI_CONF_BASE_ADDR_OFFSET 0x10
#define PCI_CONF_IRQ_OFFSET 0x3c
+#define PCI_CONF_AMISIG 0xa0
+#define AMI_SIGNATURE 0x3344
#if LINUX_VERSION_CODE < 0x20100
#define MEGARAID \
@@ -113,14 +116,14 @@
megaraid_reset, /* Reset Command Function */\
NULL, /* Slave Attach Function */\
megaraid_biosparam, /* Disk BIOS Parameters */\
- 1, /* # of cmds that can be\
+ MAX_COMMANDS, /* # of cmds that can be\
outstanding at any time */\
7, /* HBA Target ID */\
MAX_SGLIST, /* Scatter/Gather Table Size */\
- 1, /* SCSI Commands per LUN */\
+ MAX_CMD_PER_LUN, /* SCSI Commands per LUN */\
0, /* Present */\
0, /* Default Unchecked ISA DMA */\
- ENABLE_CLUSTERING } /* Enable Clustering */
+ ENABLE_CLUSTERING } /* Enable Clustering */
#else
#define MEGARAID \
{\
@@ -134,10 +137,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: MAX_COMMANDS, /* 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: MAX_CMD_PER_LUN, /* SCSI Commands per LUN */\
present: 0, /* Present */\
unchecked_isa_dma:0, /* Default Unchecked ISA DMA */\
use_clustering: ENABLE_CLUSTERING /* Enable Clustering */\
@@ -145,140 +148,155 @@
#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 state;
+ u_long isrcount;
+ u_char mboxData[16];
+ mega_passthru pthru;
+ Scsi_Cmnd *SCpnt;
+ 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];
-
- u_char max_cmds;
- mega_scb scbList[MAX_COMMANDS];
+typedef struct _mega_host_config {
+ u_char numldrv;
+ u_long flag;
+ u_long base;
+
+ mega_scb *qFree;
+ mega_scb *qPending;
+
+ u_long nReads[MAX_LOGICAL_DRIVES];
+ u_long nWrites[MAX_LOGICAL_DRIVES];
+
+ /* 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];
} 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 --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index 45ae0eaf8..040c05453 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -73,7 +73,7 @@
*/
/*
-** January 16 1998, version 3.1f
+** March 7 1999, version 3.2
**
** Supported SCSI-II features:
** Synchronous negotiation
@@ -98,6 +98,11 @@
** Shared IRQ (since linux-1.3.72)
*/
+/*
+** Name and version of the driver
+*/
+#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2"
+
#define SCSI_NCR_DEBUG_FLAGS (0)
/*==========================================================
@@ -724,12 +729,12 @@ static Scsi_Host_Template *the_template = NULL;
** /proc directory entry and proc_info function
*/
-struct proc_dir_entry proc_scsi_ncr53c8xx = {
+static struct proc_dir_entry proc_scsi_ncr53c8xx = {
PROC_SCSI_NCR53C8XX, 9, "ncr53c8xx",
S_IFDIR | S_IRUGO | S_IXUGO, 2
};
#ifdef SCSI_NCR_PROC_INFO_SUPPORT
-int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
+static int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int func);
#endif
@@ -739,6 +744,7 @@ int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
** This structure is initialized from linux config options.
** It can be overridden at boot-up by the boot command line.
*/
+#define SCSI_NCR_MAX_EXCLUDES 8
struct ncr_driver_setup {
u_char master_parity;
u_char scsi_parity;
@@ -760,6 +766,9 @@ struct ncr_driver_setup {
u_char diff_support;
u_char irqm;
u_char bus_check;
+ u_char optimize;
+ u_char recovery;
+ u_int excludes[SCSI_NCR_MAX_EXCLUDES];
char tag_ctrl[100];
};
@@ -2088,6 +2097,7 @@ struct scripth {
ncrcmd msg_ext_3 [ 10];
ncrcmd msg_sdtr [ 14];
ncrcmd send_sdtr [ 7];
+ ncrcmd nego_bad_phase [ 4];
ncrcmd msg_out_abort [ 10];
ncrcmd hdata_in [MAX_SCATTERH * 4];
ncrcmd hdata_in2 [ 2];
@@ -3192,16 +3202,15 @@ static struct scripth scripth0 __initdata = {
/*
** If a negotiation was in progress,
** negotiation failed.
+ ** Otherwise, let the C code print
+ ** some message.
*/
SCR_FROM_REG (HS_REG),
0,
- SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
- SIR_NEGO_FAILED,
- /*
- ** else make host log this message
- */
SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)),
SIR_REJECT_RECEIVED,
+ SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
+ SIR_NEGO_FAILED,
SCR_JUMP,
PADDR (clrack),
@@ -3311,10 +3320,9 @@ static struct scripth scripth0 __initdata = {
0,
SCR_CLR (SCR_ACK),
0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ PADDRH (nego_bad_phase),
-/* CHECK THE SOURCE FOR 'send_wdtr' IF YOU INTEND TO CHANGE SOMETHING HERE */
- SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
- SIR_NEGO_PROTO,
}/*-------------------------< SEND_WDTR >----------------*/,{
/*
** Send the M_X_WIDE_REQ
@@ -3367,10 +3375,9 @@ static struct scripth scripth0 __initdata = {
0,
SCR_CLR (SCR_ACK),
0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ PADDRH (nego_bad_phase),
-/* CHECK THE SOURCE FOR 'send_sdtr' IF YOU INTEND TO CHANGE SOMETHING HERE */
- SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
- SIR_NEGO_PROTO,
}/*-------------------------< SEND_SDTR >-------------*/,{
/*
** Send the M_X_SYNC_REQ
@@ -3383,6 +3390,12 @@ static struct scripth scripth0 __initdata = {
SCR_JUMP,
PADDR (msg_out_done),
+}/*-------------------------< NEGO_BAD_PHASE >------------*/,{
+ SCR_INT,
+ SIR_NEGO_PROTO,
+ SCR_JUMP,
+ PADDR (dispatch),
+
}/*-------------------------< MSG_OUT_ABORT >-------------*/,{
/*
** After ABORT message,
@@ -4283,7 +4296,7 @@ static int ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
/*
** Set irq mode.
*/
- switch(driver_setup.irqm) {
+ switch(driver_setup.irqm & 3) {
case 2:
np->rv_dcntl |= IRQM;
break;
@@ -4674,21 +4687,15 @@ printk(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n",
/*
** Install the interrupt handler.
*/
-#ifdef SCSI_NCR_SHARE_IRQ
-#define NCR_SA_INTERRUPT_FLAGS (SA_INTERRUPT | SA_SHIRQ)
- if (bootverbose > 1)
-#ifdef __sparc__
- printk(KERN_INFO "%s: requesting shared irq %s (dev_id=0x%lx)\n",
- ncr_name(np), __irq_itoa(device->slot.irq), (u_long) np);
-#else
- printk(KERN_INFO "%s: requesting shared irq %d (dev_id=0x%lx)\n",
- ncr_name(np), device->slot.irq, (u_long) np);
-#endif
+
+ if (request_irq(device->slot.irq, ncr53c8xx_intr,
+ ((driver_setup.irqm & 0x10) ? 0 : SA_SHIRQ) |
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,2,0)
+ ((driver_setup.irqm & 0x20) ? 0 : SA_INTERRUPT),
#else
-#define NCR_SA_INTERRUPT_FLAGS SA_INTERRUPT
+ 0,
#endif
- if (request_irq(device->slot.irq, ncr53c8xx_intr,
- NCR_SA_INTERRUPT_FLAGS, "ncr53c8xx", np)) {
+ "ncr53c8xx", np)) {
#ifdef __sparc__
printk(KERN_ERR "%s: request irq %s failure\n",
ncr_name(np), __irq_itoa(device->slot.irq));
@@ -4698,6 +4705,7 @@ printk(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n",
#endif
goto attach_error;
}
+
np->irq = device->slot.irq;
/*
@@ -4845,7 +4853,7 @@ static inline void ncr_flush_done_cmds(Scsi_Cmnd *lcmd)
**
**==========================================================
*/
-int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd)
+static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd)
{
/* Scsi_Device *device = cmd->device; */
tcb_p tp = &np->target[cmd->target];
@@ -4965,9 +4973,8 @@ int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd)
nego = NS_SYNC;
} else {
tp->period =0xffff;
- tp->sval = 0xe0;
PRINT_TARGET(np, cmd->target);
- printk ("SYNC transfers not supported.\n");
+ printk ("device did not report SYNC.\n");
};
};
@@ -5416,7 +5423,7 @@ out:
**
**==========================================================
*/
-int ncr_reset_bus (ncb_p np, Scsi_Cmnd *cmd, int sync_reset)
+static int ncr_reset_bus (ncb_p np, Scsi_Cmnd *cmd, int sync_reset)
{
/* Scsi_Device *device = cmd->device; */
ccb_p cp;
@@ -5839,7 +5846,7 @@ void ncr_complete (ncb_p np, ccb_p cp)
** announced capabilities (we need the 1rst 7 bytes).
*/
if (cmd->cmnd[0] == 0x12 && !(cmd->cmnd[1] & 0x3) &&
- cmd->cmnd[4] >= 7) {
+ cmd->cmnd[4] >= 7 && !cmd->use_sg) {
ncr_setup_lcb (np, cmd->target, cmd->lun,
(char *) cmd->request_buffer);
}
@@ -5986,7 +5993,7 @@ void ncr_complete (ncb_p np, ccb_p cp)
** This CCB has been skipped by the NCR.
** Queue it in the correponding unit queue.
*/
-void ncr_ccb_skipped(ncb_p np, ccb_p cp)
+static void ncr_ccb_skipped(ncb_p np, ccb_p cp)
{
tcb_p tp = &np->target[cp->target];
lcb_p lp = tp->lp[cp->lun];
@@ -7070,7 +7077,7 @@ flush_cache_all();
OUTONB (nc_ctest3, CLF);
if ((sist & (SGE)) ||
- (dstat & (MDPE|BF|ABORT|IID))) {
+ (dstat & (MDPE|BF|ABRT|IID))) {
ncr_start_reset(np);
return;
};
@@ -7549,7 +7556,7 @@ unexpected_phase:
}
else if (dsp == NCB_SCRIPTH_PHYS (np, send_wdtr) ||
dsp == NCB_SCRIPTH_PHYS (np, send_sdtr)) {
- nxtdsp = dsp - 8; /* Should raise SIR_NEGO_PROTO */
+ nxtdsp = NCB_SCRIPTH_PHYS (np, nego_bad_phase);
}
break;
#if 0
@@ -7911,9 +7918,7 @@ flush_cache_all(); // ???
np->msgout[0] = M_NOOP;
cp->nego_status = 0;
flush_cache_all();
- OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch));
- return;
-/* break; */
+ break;
case SIR_NEGO_SYNC:
/*
@@ -8692,10 +8697,15 @@ static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln, u_char *inq_data)
** Evaluate trustable target/unit capabilities.
** We only believe device version >= SCSI-2 that
** use appropriate response data format (2).
+ ** But it seems that some CCS devices also
+ ** support SYNC and I donnot want to frustrate
+ ** anybody. ;-)
*/
inq_byte7 = 0;
- if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2)
+ if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2)
inq_byte7 = inq_data[7];
+ else if ((inq_data[2] & 0x7) == 1 && (inq_data[3] & 0xf) == 1)
+ inq_byte7 = INQ7_SYNC;
/*
** Throw away announced LUN capabilities if we are told
@@ -9284,6 +9294,7 @@ void ncr53c8xx_setup(char *str, int *ints)
int val;
int base;
int c;
+ int xi = 0;
while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
char *pe;
@@ -9355,6 +9366,10 @@ void ncr53c8xx_setup(char *str, int *ints)
else if (!strncmp(cur, "safe:", 5) && val)
memcpy(&driver_setup, &driver_safe_setup, sizeof(driver_setup));
+ else if (!strncmp(cur, "excl:", 5)) {
+ if (xi < SCSI_NCR_MAX_EXCLUDES)
+ driver_setup.excludes[xi++] = val;
+ }
else
printk("ncr53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
@@ -9632,6 +9647,50 @@ if (ncr53c8xx)
}
/*
+** Generically read a base address from the PCI configuration space.
+** Return the offset immediately after the base address that has
+** been read. Btw, we blindly assume that the high 32 bits of 64 bit
+** base addresses are set to zero on 32 bit architectures.
+**
+*/
+#if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92)
+__initfunc(
+static int
+pci_read_base_address(u_char bus, u_char device_fn, int offset, u_long *base)
+)
+{
+ u_int32 tmp;
+
+ pcibios_read_config_dword(bus, device_fn, offset, &tmp);
+ *base = tmp;
+ offset += sizeof(u_int32);
+ if ((tmp & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+ pcibios_read_config_dword(bus, device_fn, offset, &tmp);
+ *base |= (((u_long)tmp) << 32);
+#endif
+ offset += sizeof(u_int32);
+ }
+ return offset;
+}
+#else /* LINUX_VERSION_CODE > LinuxVersionCode(2,1,92) */
+__initfunc(
+static int
+pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
+)
+{
+ *base = pdev->base_address[index++];
+ if ((*base & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+ *base |= (((u_long)pdev->base_address[index]) << 32);
+#endif
+ ++index;
+ }
+ return index;
+}
+#endif
+
+/*
** Read and check the PCI configuration for any detected NCR
** boards and save data for attaching after all boards have
** been detected.
@@ -9647,61 +9706,56 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
uchar revision;
#if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
struct pci_dev *pdev;
- ulong base, base_2, io_port;
uint irq;
#else
uchar irq;
- uint base, base_2, io_port;
#endif
+ ulong base, base_2, io_port;
int i;
-
#ifdef SCSI_NCR_NVRAM_SUPPORT
ncr_nvram *nvram = device->nvram;
#endif
ncr_chip *chip;
/*
- * Read info from the PCI config space.
- * pcibios_read_config_xxx() functions are assumed to be used for
- * successfully detected PCI devices.
- * Expecting error conditions from them is just paranoia,
- * thus void cast.
- */
- (void) pcibios_read_config_word(bus, device_fn,
- PCI_VENDOR_ID, &vendor_id);
- (void) pcibios_read_config_word(bus, device_fn,
- PCI_DEVICE_ID, &device_id);
- (void) pcibios_read_config_word(bus, device_fn,
- PCI_COMMAND, &command);
+ ** Read info from the PCI config space.
+ ** pcibios_read_config_xxx() functions are assumed to be used for
+ ** successfully detected PCI devices.
+ */
#if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
pdev = pci_find_slot(bus, device_fn);
- io_port = pdev->base_address[0];
- base = pdev->base_address[1];
- base_2 = pdev->base_address[2];
+ vendor_id = pdev->vendor;
+ device_id = pdev->device;
irq = pdev->irq;
+ i = 0;
+ i = pci_get_base_address(pdev, i, &io_port);
+ i = pci_get_base_address(pdev, i, &base);
+ (void) pci_get_base_address(pdev, i, &base_2);
#else
- (void) pcibios_read_config_dword(bus, device_fn,
- PCI_BASE_ADDRESS_0, &io_port);
- (void) pcibios_read_config_dword(bus, device_fn,
- PCI_BASE_ADDRESS_1, &base);
- (void) pcibios_read_config_dword(bus, device_fn,
- PCI_BASE_ADDRESS_2, &base_2);
-
- /* Handle 64bit base addresses for 53C896. */
- if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
- (void) pcibios_read_config_dword(bus, device_fn,
- PCI_BASE_ADDRESS_3, &base_2);
- (void) pcibios_read_config_byte(bus, device_fn,
- PCI_INTERRUPT_LINE, &irq);
-#endif
- (void) pcibios_read_config_byte(bus, device_fn,
- PCI_CLASS_REVISION,&revision);
- (void) pcibios_read_config_byte(bus, device_fn,
- PCI_CACHE_LINE_SIZE, &cache_line_size);
- (void) pcibios_read_config_byte(bus, device_fn,
- PCI_LATENCY_TIMER, &latency_timer);
+ pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id);
+ pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID, &device_id);
+ pcibios_read_config_byte(bus, device_fn, PCI_INTERRUPT_LINE, &irq);
+ i = PCI_BASE_ADDRESS_0;
+ i = pci_read_base_address(bus, device_fn, i, &io_port);
+ i = pci_read_base_address(bus, device_fn, i, &base);
+ (void) pci_read_base_address(bus, device_fn, i, &base_2);
+#endif
+ pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+ pcibios_read_config_byte(bus, device_fn, PCI_CLASS_REVISION, &revision);
+ pcibios_read_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE,
+ &cache_line_size);
+ pcibios_read_config_byte(bus, device_fn, PCI_LATENCY_TIMER,
+ &latency_timer);
/*
+ ** If user excludes this chip, donnot initialize it.
+ */
+ for (i = 0 ; i < SCSI_NCR_MAX_EXCLUDES ; i++) {
+ if (driver_setup.excludes[i] ==
+ (io_port & PCI_BASE_ADDRESS_IO_MASK))
+ return -1;
+ }
+ /*
* Check if the chip is supported
*/
chip = 0;
@@ -10187,6 +10241,14 @@ printk("ncr53c8xx_select_queue_depth: host=%d, id=%d, lun=%d, depth=%d\n",
}
/*
+** Linux entry point for info() function
+*/
+const char *ncr53c8xx_info (struct Scsi_Host *host)
+{
+ return SCSI_NCR_DRIVER_NAME;
+}
+
+/*
** Linux entry point of queuecommand() function
*/
@@ -10813,7 +10875,7 @@ static int ncr_host_info(ncb_p np, char *ptr, off_t offset, int len)
** - func = 1 means write (parse user control command)
*/
-int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
+static int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int func)
{
struct Scsi_Host *host;
diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h
index 72b7ad4da..40d3533c2 100644
--- a/drivers/scsi/ncr53c8xx.h
+++ b/drivers/scsi/ncr53c8xx.h
@@ -42,216 +42,7 @@
#ifndef NCR53C8XX_H
#define NCR53C8XX_H
-/*
-** Name and revision of the driver
-*/
-#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 3.1f"
-
-/*
-** Check supported Linux versions
-*/
-
-#if !defined(LINUX_VERSION_CODE)
-#include <linux/version.h>
-#endif
-#include <linux/config.h>
-
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-
-/*
- * No more an option, enabled by default.
- */
-#ifndef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
-#define CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
-#endif
-#undef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT /* XXX */
-
-/*
-** These options are not tunable from 'make config'
-*/
-#define SCSI_NCR_PROC_INFO_SUPPORT
-#define SCSI_NCR_SHARE_IRQ
-
-/*
-** If you want a driver as small as possible, donnot define the
-** following options.
-*/
-#define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
-#define SCSI_NCR_DEBUG_INFO_SUPPORT
-#define SCSI_NCR_PCI_FIX_UP_SUPPORT
-#ifdef SCSI_NCR_PROC_INFO_SUPPORT
-# ifdef CONFIG_SCSI_NCR53C8XX_PROFILE
-# define SCSI_NCR_PROFILE_SUPPORT
-# endif
-# define SCSI_NCR_USER_COMMAND_SUPPORT
-# define SCSI_NCR_USER_INFO_SUPPORT
-#endif
-
-/*==========================================================
-**
-** nvram settings - #define SCSI_NCR_NVRAM_SUPPORT to enable
-**
-**==========================================================
-*/
-
-#ifdef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
-#define SCSI_NCR_NVRAM_SUPPORT
-/* #define SCSI_NCR_DEBUG_NVRAM */
-#endif
-
-/* ---------------------------------------------------------------------
-** Take into account kernel configured parameters.
-** Most of these options can be overridden at startup by a command line.
-** ---------------------------------------------------------------------
-*/
-
-/*
- * For Ultra2 SCSI support option, use special features and allow 40Mhz
- * synchronous data transfers.
- */
-#define SCSI_NCR_SETUP_SPECIAL_FEATURES (3)
-#define SCSI_NCR_SETUP_ULTRA_SCSI (2)
-#define SCSI_NCR_MAX_SYNC (40)
-
-/*
- * Allow tags from 2 to 64, default 8
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_MAX_TAGS
-#if CONFIG_SCSI_NCR53C8XX_MAX_TAGS < 2
-#define SCSI_NCR_MAX_TAGS (2)
-#elif CONFIG_SCSI_NCR53C8XX_MAX_TAGS > 64
-#define SCSI_NCR_MAX_TAGS (64)
-#else
-#define SCSI_NCR_MAX_TAGS CONFIG_SCSI_NCR53C8XX_MAX_TAGS
-#endif
-#else
-#define SCSI_NCR_MAX_TAGS (8)
-#endif
-
-/*
- * Allow tagged command queuing support if configured with default number
- * of tags set to max (see above).
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
-#define SCSI_NCR_SETUP_DEFAULT_TAGS CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
-#elif defined CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE
-#define SCSI_NCR_SETUP_DEFAULT_TAGS SCSI_NCR_MAX_TAGS
-#else
-#define SCSI_NCR_SETUP_DEFAULT_TAGS (0)
-#endif
-
-/*
- * Use normal IO if configured. Forced for alpha and ppc.
- */
-#if defined(CONFIG_SCSI_NCR53C8XX_IOMAPPED)
-#define SCSI_NCR_IOMAPPED
-#elif defined(__alpha__) || defined(__powerpc__)
-#define SCSI_NCR_IOMAPPED
-#elif defined(__sparc__)
-#undef SCSI_NCR_IOMAPPED
-#endif
-
-/*
- * Sync transfer frequency at startup.
- * Allow from 5Mhz to 40Mhz default 20 Mhz.
- */
-#ifndef CONFIG_SCSI_NCR53C8XX_SYNC
-#define CONFIG_SCSI_NCR53C8XX_SYNC (20)
-#elif CONFIG_SCSI_NCR53C8XX_SYNC > SCSI_NCR_MAX_SYNC
-#undef CONFIG_SCSI_NCR53C8XX_SYNC
-#define CONFIG_SCSI_NCR53C8XX_SYNC SCSI_NCR_MAX_SYNC
-#endif
-
-#if CONFIG_SCSI_NCR53C8XX_SYNC == 0
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (255)
-#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 5
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (50)
-#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 20
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (250/(CONFIG_SCSI_NCR53C8XX_SYNC))
-#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 33
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (11)
-#else
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (10)
-#endif
-
-/*
- * Disallow disconnections at boot-up
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
-#define SCSI_NCR_SETUP_DISCONNECTION (0)
-#else
-#define SCSI_NCR_SETUP_DISCONNECTION (1)
-#endif
-
-/*
- * Force synchronous negotiation for all targets
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO
-#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO (1)
-#else
-#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO (0)
-#endif
-
-/*
- * Disable master parity checking (flawed hardwares need that)
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_MPARITY_CHECK
-#define SCSI_NCR_SETUP_MASTER_PARITY (0)
-#else
-#define SCSI_NCR_SETUP_MASTER_PARITY (1)
-#endif
-
-/*
- * Disable scsi parity checking (flawed devices may need that)
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_PARITY_CHECK
-#define SCSI_NCR_SETUP_SCSI_PARITY (0)
-#else
-#define SCSI_NCR_SETUP_SCSI_PARITY (1)
-#endif
-
-/*
- * Vendor specific stuff
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
-#define SCSI_NCR_SETUP_LED_PIN (1)
-#define SCSI_NCR_SETUP_DIFF_SUPPORT (3)
-#else
-#define SCSI_NCR_SETUP_LED_PIN (0)
-#define SCSI_NCR_SETUP_DIFF_SUPPORT (0)
-#endif
-
-/*
- * Settle time after reset at boot-up
- */
-#define SCSI_NCR_SETUP_SETTLE_TIME (2)
-
-/*
-** Other parameters not configurable with "make config"
-** Avoid to change these constants, unless you know what you are doing.
-*/
-
-#define SCSI_NCR_ALWAYS_SIMPLE_TAG
-#define SCSI_NCR_MAX_SCATTER (127)
-#define SCSI_NCR_MAX_TARGET (16)
-
-/* No need to use a too large adapter queue */
-#if SCSI_NCR_MAX_TAGS <= 32
-#define SCSI_NCR_CAN_QUEUE (7*SCSI_NCR_MAX_TAGS)
-#else
-#define SCSI_NCR_CAN_QUEUE (250)
-#endif
-
-#define SCSI_NCR_CMD_PER_LUN (SCSI_NCR_MAX_TAGS)
-#define SCSI_NCR_SG_TABLESIZE (SCSI_NCR_MAX_SCATTER)
-
-#define SCSI_NCR_TIMER_INTERVAL (HZ)
-
-#if 1 /* defined CONFIG_SCSI_MULTI_LUN */
-#define SCSI_NCR_MAX_LUN (8)
-#else
-#define SCSI_NCR_MAX_LUN (1)
-#endif
+#include "sym53c8xx_defs.h"
/*
** Define Scsi_Host_Template parameters
@@ -265,6 +56,7 @@
int ncr53c8xx_abort(Scsi_Cmnd *);
int ncr53c8xx_detect(Scsi_Host_Template *tpnt);
+const char *ncr53c8xx_info(struct Scsi_Host *host);
int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int);
@@ -274,11 +66,13 @@ int ncr53c8xx_release(struct Scsi_Host *);
#define ncr53c8xx_release NULL
#endif
+
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75)
-#define NCR53C8XX { name: SCSI_NCR_DRIVER_NAME, \
+#define NCR53C8XX { name: "", \
detect: ncr53c8xx_detect, \
release: ncr53c8xx_release, \
+ info: ncr53c8xx_info, \
queuecommand: ncr53c8xx_queue_command,\
abort: ncr53c8xx_abort, \
reset: ncr53c8xx_reset, \
@@ -292,8 +86,8 @@ int ncr53c8xx_release(struct Scsi_Host *);
#else
#define NCR53C8XX { NULL, NULL, NULL, NULL, \
- SCSI_NCR_DRIVER_NAME, ncr53c8xx_detect, \
- ncr53c8xx_release, NULL, NULL, \
+ NULL, ncr53c8xx_detect, \
+ ncr53c8xx_release, ncr53c8xx_info, NULL, \
ncr53c8xx_queue_command,ncr53c8xx_abort, \
ncr53c8xx_reset, NULL, scsicam_bios_param, \
SCSI_NCR_CAN_QUEUE, 7, \
@@ -304,867 +98,4 @@ int ncr53c8xx_release(struct Scsi_Host *);
#endif /* defined(HOSTS_C) || defined(MODULE) */
-#ifndef HOSTS_C
-
-/*
-** IO functions definition for big/little endian support.
-** For now, the NCR is only supported in little endian addressing mode,
-** and big endian byte ordering is only supported for the PPC.
-** MMIO is not used on PPC.
-*/
-
-#ifdef __BIG_ENDIAN
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0)
-#error "BIG ENDIAN byte ordering needs kernel version >= 2.1.0"
-#endif
-
-#if defined(__powerpc__)
-#define inw_l2b inw
-#define inl_l2b inl
-#define outw_b2l outw
-#define outl_b2l outl
-#elif defined(__sparc__)
-#define readw_l2b readw
-#define readl_l2b readl
-#define writew_b2l writew
-#define writel_b2l writel
-#else
-#error "Support for BIG ENDIAN is only available for PowerPC and SPARC"
-#endif
-
-#else /* Assumed x86 or alpha */
-
-#define inw_raw inw
-#define inl_raw inl
-#define outw_raw outw
-#define outl_raw outl
-#define readw_raw readw
-#define readl_raw readl
-#define writew_raw writew
-#define writel_raw writel
-
-#endif
-
-#ifdef SCSI_NCR_BIG_ENDIAN
-#error "The NCR in BIG ENDIAN addressing mode is not (yet) supported"
-#endif
-
-/*
-** NCR53C8XX Device Ids
-*/
-
-#ifndef PCI_DEVICE_ID_NCR_53C810
-#define PCI_DEVICE_ID_NCR_53C810 1
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C810AP
-#define PCI_DEVICE_ID_NCR_53C810AP 5
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C815
-#define PCI_DEVICE_ID_NCR_53C815 4
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C820
-#define PCI_DEVICE_ID_NCR_53C820 2
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C825
-#define PCI_DEVICE_ID_NCR_53C825 3
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C860
-#define PCI_DEVICE_ID_NCR_53C860 6
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C875
-#define PCI_DEVICE_ID_NCR_53C875 0xf
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C875J
-#define PCI_DEVICE_ID_NCR_53C875J 0x8f
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C885
-#define PCI_DEVICE_ID_NCR_53C885 0xd
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C895
-#define PCI_DEVICE_ID_NCR_53C895 0xc
-#endif
-
-#ifndef PCI_DEVICE_ID_NCR_53C896
-#define PCI_DEVICE_ID_NCR_53C896 0xb
-#endif
-
-/*
-** NCR53C8XX devices features table.
-*/
-typedef struct {
- unsigned short device_id;
- unsigned short revision_id;
- char *name;
- unsigned char burst_max;
- unsigned char offset_max;
- unsigned char nr_divisor;
- unsigned int features;
-#define FE_LED0 (1<<0)
-#define FE_WIDE (1<<1)
-#define FE_ULTRA (1<<2)
-#define FE_ULTRA2 (1<<3)
-#define FE_DBLR (1<<4)
-#define FE_QUAD (1<<5)
-#define FE_ERL (1<<6)
-#define FE_CLSE (1<<7)
-#define FE_WRIE (1<<8)
-#define FE_ERMP (1<<9)
-#define FE_BOF (1<<10)
-#define FE_DFS (1<<11)
-#define FE_PFEN (1<<12)
-#define FE_LDSTR (1<<13)
-#define FE_RAM (1<<14)
-#define FE_CLK80 (1<<15)
-#define FE_RAM8K (1<<16)
-#define FE_64BIT (1<<17)
-#define FE_IO256 (1<<18)
-#define FE_NOPM (1<<19)
-#define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP)
-#define FE_SCSI_SET (FE_WIDE|FE_ULTRA|FE_ULTRA2|FE_DBLR|FE_QUAD|F_CLK80)
-#define FE_SPECIAL_SET (FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM)
-} ncr_chip;
-
-/*
-** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 3.
-** Memory Read transaction terminated by a retry followed by
-** Memory Read Line command.
-*/
-#define FE_CACHE0_SET (FE_CACHE_SET & ~FE_ERL)
-
-/*
-** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 5.
-** On paper, this errata is harmless. But it is a good reason for
-** using a shorter programmed burst length (64 DWORDS instead of 128).
-*/
-
-#define SCSI_NCR_CHIP_TABLE \
-{ \
- {PCI_DEVICE_ID_NCR_53C810, 0x0f, "810", 4, 8, 4, \
- FE_ERL} \
- , \
- {PCI_DEVICE_ID_NCR_53C810, 0xff, "810a", 4, 8, 4, \
- FE_CACHE_SET|FE_LDSTR|FE_PFEN|FE_BOF} \
- , \
- {PCI_DEVICE_ID_NCR_53C815, 0xff, "815", 4, 8, 4, \
- FE_ERL|FE_BOF} \
- , \
- {PCI_DEVICE_ID_NCR_53C820, 0xff, "820", 4, 8, 4, \
- FE_WIDE|FE_ERL} \
- , \
- {PCI_DEVICE_ID_NCR_53C825, 0x0f, "825", 4, 8, 4, \
- FE_WIDE|FE_ERL|FE_BOF} \
- , \
- {PCI_DEVICE_ID_NCR_53C825, 0xff, "825a", 6, 8, 4, \
- FE_WIDE|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} \
- , \
- {PCI_DEVICE_ID_NCR_53C860, 0xff, "860", 4, 8, 5, \
- FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_BOF|FE_LDSTR|FE_PFEN} \
- , \
- {PCI_DEVICE_ID_NCR_53C875, 0x01, "875", 6, 16, 5, \
- FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C875, 0x0f, "875", 6, 16, 5, \
- FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C875, 0xff, "876", 6, 16, 5, \
- FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C875J,0xff, "875J", 6, 16, 5, \
- FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C885, 0xff, "885", 6, 16, 5, \
- FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C895, 0xff, "895", 7, 31, 7, \
- FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
- , \
- {PCI_DEVICE_ID_NCR_53C896, 0xff, "896", 7, 31, 7, \
- FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|\
- FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM}\
-}
-
-/*
- * List of supported NCR chip ids
- */
-#define SCSI_NCR_CHIP_IDS \
-{ \
- PCI_DEVICE_ID_NCR_53C810, \
- PCI_DEVICE_ID_NCR_53C815, \
- PCI_DEVICE_ID_NCR_53C820, \
- PCI_DEVICE_ID_NCR_53C825, \
- PCI_DEVICE_ID_NCR_53C860, \
- PCI_DEVICE_ID_NCR_53C875, \
- PCI_DEVICE_ID_NCR_53C875J, \
- PCI_DEVICE_ID_NCR_53C885, \
- PCI_DEVICE_ID_NCR_53C895, \
- PCI_DEVICE_ID_NCR_53C896 \
-}
-
-/*
-** Initial setup.
-** Can be overriden at startup by a command line.
-*/
-#define SCSI_NCR_DRIVER_SETUP \
-{ \
- SCSI_NCR_SETUP_MASTER_PARITY, \
- SCSI_NCR_SETUP_SCSI_PARITY, \
- SCSI_NCR_SETUP_DISCONNECTION, \
- SCSI_NCR_SETUP_SPECIAL_FEATURES, \
- SCSI_NCR_SETUP_ULTRA_SCSI, \
- SCSI_NCR_SETUP_FORCE_SYNC_NEGO, \
- 0, \
- 0, \
- 1, \
- 1, \
- SCSI_NCR_SETUP_DEFAULT_TAGS, \
- SCSI_NCR_SETUP_DEFAULT_SYNC, \
- 0x00, \
- 7, \
- SCSI_NCR_SETUP_LED_PIN, \
- 1, \
- SCSI_NCR_SETUP_SETTLE_TIME, \
- SCSI_NCR_SETUP_DIFF_SUPPORT, \
- 0, \
- 1 \
-}
-
-/*
-** Boot fail safe setup.
-** Override initial setup from boot command line:
-** ncr53c8xx=safe:y
-*/
-#define SCSI_NCR_DRIVER_SAFE_SETUP \
-{ \
- 0, \
- 1, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 1, \
- 2, \
- 0, \
- 255, \
- 0x00, \
- 255, \
- 0, \
- 0, \
- 10, \
- 1, \
- 1, \
- 1 \
-}
-
-/**************** ORIGINAL CONTENT of ncrreg.h from FreeBSD ******************/
-
-/*-----------------------------------------------------------------
-**
-** The ncr 53c810 register structure.
-**
-**-----------------------------------------------------------------
-*/
-
-struct ncr_reg {
-/*00*/ u_char nc_scntl0; /* full arb., ena parity, par->ATN */
-
-/*01*/ u_char nc_scntl1; /* no reset */
- #define ISCON 0x10 /* connected to scsi */
- #define CRST 0x08 /* force reset */
-
-/*02*/ u_char nc_scntl2; /* no disconnect expected */
- #define SDU 0x80 /* cmd: disconnect will raise error */
- #define CHM 0x40 /* sta: chained mode */
- #define WSS 0x08 /* sta: wide scsi send [W]*/
- #define WSR 0x01 /* sta: wide scsi received [W]*/
-
-/*03*/ u_char nc_scntl3; /* cnf system clock dependent */
- #define EWS 0x08 /* cmd: enable wide scsi [W]*/
- #define ULTRA 0x80 /* cmd: ULTRA enable */
-
-/*04*/ u_char nc_scid; /* cnf host adapter scsi address */
- #define RRE 0x40 /* r/w:e enable response to resel. */
- #define SRE 0x20 /* r/w:e enable response to select */
-
-/*05*/ u_char nc_sxfer; /* ### Sync speed and count */
-
-/*06*/ u_char nc_sdid; /* ### Destination-ID */
-
-/*07*/ u_char nc_gpreg; /* ??? IO-Pins */
-
-/*08*/ u_char nc_sfbr; /* ### First byte in phase */
-
-/*09*/ u_char nc_socl;
- #define CREQ 0x80 /* r/w: SCSI-REQ */
- #define CACK 0x40 /* r/w: SCSI-ACK */
- #define CBSY 0x20 /* r/w: SCSI-BSY */
- #define CSEL 0x10 /* r/w: SCSI-SEL */
- #define CATN 0x08 /* r/w: SCSI-ATN */
- #define CMSG 0x04 /* r/w: SCSI-MSG */
- #define CC_D 0x02 /* r/w: SCSI-C_D */
- #define CI_O 0x01 /* r/w: SCSI-I_O */
-
-/*0a*/ u_char nc_ssid;
-
-/*0b*/ u_char nc_sbcl;
-
-/*0c*/ u_char nc_dstat;
- #define DFE 0x80 /* sta: dma fifo empty */
- #define MDPE 0x40 /* int: master data parity error */
- #define BF 0x20 /* int: script: bus fault */
- #define ABRT 0x10 /* int: script: command aborted */
- #define SSI 0x08 /* int: script: single step */
- #define SIR 0x04 /* int: script: interrupt instruct. */
- #define IID 0x01 /* int: script: illegal instruct. */
-
-/*0d*/ u_char nc_sstat0;
- #define ILF 0x80 /* sta: data in SIDL register lsb */
- #define ORF 0x40 /* sta: data in SODR register lsb */
- #define OLF 0x20 /* sta: data in SODL register lsb */
- #define AIP 0x10 /* sta: arbitration in progress */
- #define LOA 0x08 /* sta: arbitration lost */
- #define WOA 0x04 /* sta: arbitration won */
- #define IRST 0x02 /* sta: scsi reset signal */
- #define SDP 0x01 /* sta: scsi parity signal */
-
-/*0e*/ u_char nc_sstat1;
- #define FF3210 0xf0 /* sta: bytes in the scsi fifo */
-
-/*0f*/ u_char nc_sstat2;
- #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/
- #define ORF1 0x40 /* sta: data in SODR register msb[W]*/
- #define OLF1 0x20 /* sta: data in SODL register msb[W]*/
- #define DM 0x04 /* sta: DIFFSENS mismatch (895/6 only) */
- #define LDSC 0x02 /* sta: disconnect & reconnect */
-
-/*10*/ u_int32 nc_dsa; /* --> Base page */
-
-/*14*/ u_char nc_istat; /* --> Main Command and status */
- #define CABRT 0x80 /* cmd: abort current operation */
- #define SRST 0x40 /* mod: reset chip */
- #define SIGP 0x20 /* r/w: message from host to ncr */
- #define SEM 0x10 /* r/w: message between host + ncr */
- #define CON 0x08 /* sta: connected to scsi */
- #define INTF 0x04 /* sta: int on the fly (reset by wr)*/
- #define SIP 0x02 /* sta: scsi-interrupt */
- #define DIP 0x01 /* sta: host/script interrupt */
-
-/*15*/ u_char nc_15_;
-/*16*/ u_char nc_16_;
-/*17*/ u_char nc_17_;
-
-/*18*/ u_char nc_ctest0;
-/*19*/ u_char nc_ctest1;
-
-/*1a*/ u_char nc_ctest2;
- #define CSIGP 0x40
-
-/*1b*/ u_char nc_ctest3;
- #define FLF 0x08 /* cmd: flush dma fifo */
- #define CLF 0x04 /* cmd: clear dma fifo */
- #define FM 0x02 /* mod: fetch pin mode */
- #define WRIE 0x01 /* mod: write and invalidate enable */
-
-/*1c*/ u_int32 nc_temp; /* ### Temporary stack */
-
-/*20*/ u_char nc_dfifo;
-/*21*/ u_char nc_ctest4;
- #define BDIS 0x80 /* mod: burst disable */
- #define MPEE 0x08 /* mod: master parity error enable */
-
-/*22*/ u_char nc_ctest5;
- #define DFS 0x20 /* mod: dma fifo size */
-/*23*/ u_char nc_ctest6;
-
-/*24*/ u_int32 nc_dbc; /* ### Byte count and command */
-/*28*/ u_int32 nc_dnad; /* ### Next command register */
-/*2c*/ u_int32 nc_dsp; /* --> Script Pointer */
-/*30*/ u_int32 nc_dsps; /* --> Script pointer save/opcode#2 */
-
-/*34*/ u_char nc_scratcha; /* Temporary register a */
-/*35*/ u_char nc_scratcha1;
-/*36*/ u_char nc_scratcha2;
-/*37*/ u_char nc_scratcha3;
-
-/*38*/ u_char nc_dmode;
- #define BL_2 0x80 /* mod: burst length shift value +2 */
- #define BL_1 0x40 /* mod: burst length shift value +1 */
- #define ERL 0x08 /* mod: enable read line */
- #define ERMP 0x04 /* mod: enable read multiple */
- #define BOF 0x02 /* mod: burst op code fetch */
-
-/*39*/ u_char nc_dien;
-/*3a*/ u_char nc_dwt;
-
-/*3b*/ u_char nc_dcntl; /* --> Script execution control */
-
- #define CLSE 0x80 /* mod: cache line size enable */
- #define PFF 0x40 /* cmd: pre-fetch flush */
- #define PFEN 0x20 /* mod: pre-fetch enable */
- #define SSM 0x10 /* mod: single step mode */
- #define IRQM 0x08 /* mod: irq mode (1 = totem pole !) */
- #define STD 0x04 /* cmd: start dma mode */
- #define IRQD 0x02 /* mod: irq disable */
- #define NOCOM 0x01 /* cmd: protect sfbr while reselect */
-
-/*3c*/ u_int32 nc_adder;
-
-/*40*/ u_short nc_sien; /* -->: interrupt enable */
-/*42*/ u_short nc_sist; /* <--: interrupt status */
- #define SBMC 0x1000/* sta: SCSI Bus Mode Change (895/6 only) */
- #define STO 0x0400/* sta: timeout (select) */
- #define GEN 0x0200/* sta: timeout (general) */
- #define HTH 0x0100/* sta: timeout (handshake) */
- #define MA 0x80 /* sta: phase mismatch */
- #define CMP 0x40 /* sta: arbitration complete */
- #define SEL 0x20 /* sta: selected by another device */
- #define RSL 0x10 /* sta: reselected by another device*/
- #define SGE 0x08 /* sta: gross error (over/underflow)*/
- #define UDC 0x04 /* sta: unexpected disconnect */
- #define RST 0x02 /* sta: scsi bus reset detected */
- #define PAR 0x01 /* sta: scsi parity error */
-
-/*44*/ u_char nc_slpar;
-/*45*/ u_char nc_swide;
-/*46*/ u_char nc_macntl;
-/*47*/ u_char nc_gpcntl;
-/*48*/ u_char nc_stime0; /* cmd: timeout for select&handshake*/
-/*49*/ u_char nc_stime1; /* cmd: timeout user defined */
-/*4a*/ u_short nc_respid; /* sta: Reselect-IDs */
-
-/*4c*/ u_char nc_stest0;
-
-/*4d*/ u_char nc_stest1;
- #define DBLEN 0x08 /* clock doubler running */
- #define DBLSEL 0x04 /* clock doubler selected */
-
-
-/*4e*/ u_char nc_stest2;
- #define ROF 0x40 /* reset scsi offset (after gross error!) */
- #define EXT 0x02 /* extended filtering */
-
-/*4f*/ u_char nc_stest3;
- #define TE 0x80 /* c: tolerAnt enable */
- #define HSC 0x20 /* c: Halt SCSI Clock */
- #define CSF 0x02 /* c: clear scsi fifo */
-
-/*50*/ u_short nc_sidl; /* Lowlevel: latched from scsi data */
-/*52*/ u_char nc_stest4;
- #define SMODE 0xc0 /* SCSI bus mode (895/6 only) */
- #define SMODE_HVD 0x40 /* High Voltage Differential */
- #define SMODE_SE 0x80 /* Single Ended */
- #define SMODE_LVD 0xc0 /* Low Voltage Differential */
- #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */
-
-/*53*/ u_char nc_53_;
-/*54*/ u_short nc_sodl; /* Lowlevel: data out to scsi data */
-/*56*/ u_char nc_ccntl0; /* Chip Control 0 (896) */
- #define ENPMJ 0x80 /* Enable Phase Mismatch Jump */
- #define PMJCTL 0x40 /* Phase Mismatch Jump Control */
- #define ENNDJ 0x20 /* Enable Non Data PM Jump */
- #define DISFC 0x10 /* Disable Auto FIFO Clear */
- #define DILS 0x02 /* Disable Internal Load/Store */
- #define DPR 0x01 /* Disable Pipe Req */
-
-/*57*/ u_char nc_ccntl1; /* Chip Control 1 (896) */
- #define ZMOD 0x80 /* High Impedance Mode */
- #define DDAC 0x08 /* Disable Dual Address Cycle */
- #define XTIMOD 0x04 /* 64-bit Table Ind. Indexing Mode */
- #define EXTIBMV 0x02 /* Enable 64-bit Table Ind. BMOV */
- #define EXDBMV 0x01 /* Enable 64-bit Direct BMOV */
-/*58*/ u_short nc_sbdl; /* Lowlevel: data from scsi data */
-/*5a*/ u_short nc_5a_;
-/*5c*/ u_char nc_scr0; /* Working register B */
-/*5d*/ u_char nc_scr1; /* */
-/*5e*/ u_char nc_scr2; /* */
-/*5f*/ u_char nc_scr3; /* */
-/*60*/
-};
-
-/*-----------------------------------------------------------
-**
-** Utility macros for the script.
-**
-**-----------------------------------------------------------
-*/
-
-#define REGJ(p,r) (offsetof(struct ncr_reg, p ## r))
-#define REG(r) REGJ (nc_, r)
-
-#ifndef TARGET_MODE
-#define TARGET_MODE 0
-#endif
-
-typedef u_int32 ncrcmd;
-
-/*-----------------------------------------------------------
-**
-** SCSI phases
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_DATA_OUT 0x00000000
-#define SCR_DATA_IN 0x01000000
-#define SCR_COMMAND 0x02000000
-#define SCR_STATUS 0x03000000
-#define SCR_ILG_OUT 0x04000000
-#define SCR_ILG_IN 0x05000000
-#define SCR_MSG_OUT 0x06000000
-#define SCR_MSG_IN 0x07000000
-
-/*-----------------------------------------------------------
-**
-** Data transfer via SCSI.
-**
-**-----------------------------------------------------------
-**
-** MOVE_ABS (LEN)
-** <<start address>>
-**
-** MOVE_IND (LEN)
-** <<dnad_offset>>
-**
-** MOVE_TBL
-** <<dnad_offset>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_MOVE_ABS(l) ((0x08000000 ^ (TARGET_MODE << 1ul)) | (l))
-#define SCR_MOVE_IND(l) ((0x28000000 ^ (TARGET_MODE << 1ul)) | (l))
-#define SCR_MOVE_TBL (0x18000000 ^ (TARGET_MODE << 1ul))
-
-struct scr_tblmove {
- u_int32 size;
- u_int32 addr;
-};
-
-/*-----------------------------------------------------------
-**
-** Selection
-**
-**-----------------------------------------------------------
-**
-** SEL_ABS | SCR_ID (0..7) [ | REL_JMP]
-** <<alternate_address>>
-**
-** SEL_TBL | << dnad_offset>> [ | REL_JMP]
-** <<alternate_address>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_SEL_ABS 0x40000000
-#define SCR_SEL_ABS_ATN 0x41000000
-#define SCR_SEL_TBL 0x42000000
-#define SCR_SEL_TBL_ATN 0x43000000
-
-struct scr_tblsel {
- u_char sel_0;
- u_char sel_sxfer;
- u_char sel_id;
- u_char sel_scntl3;
-};
-
-#define SCR_JMP_REL 0x04000000
-#define SCR_ID(id) (((u_int32)(id)) << 16)
-
-/*-----------------------------------------------------------
-**
-** Waiting for Disconnect or Reselect
-**
-**-----------------------------------------------------------
-**
-** WAIT_DISC
-** dummy: <<alternate_address>>
-**
-** WAIT_RESEL
-** <<alternate_address>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_WAIT_DISC 0x48000000
-#define SCR_WAIT_RESEL 0x50000000
-
-/*-----------------------------------------------------------
-**
-** Bit Set / Reset
-**
-**-----------------------------------------------------------
-**
-** SET (flags {|.. })
-**
-** CLR (flags {|.. })
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_SET(f) (0x58000000 | (f))
-#define SCR_CLR(f) (0x60000000 | (f))
-
-#define SCR_CARRY 0x00000400
-#define SCR_TRG 0x00000200
-#define SCR_ACK 0x00000040
-#define SCR_ATN 0x00000008
-
-
-
-
-/*-----------------------------------------------------------
-**
-** Memory to memory move
-**
-**-----------------------------------------------------------
-**
-** COPY (bytecount)
-** << source_address >>
-** << destination_address >>
-**
-** SCR_COPY sets the NO FLUSH option by default.
-** SCR_COPY_F does not set this option.
-**
-** For chips which do not support this option,
-** ncr_copy_and_bind() will remove this bit.
-**-----------------------------------------------------------
-*/
-
-#define SCR_NO_FLUSH 0x01000000
-
-#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n))
-#define SCR_COPY_F(n) (0xc0000000 | (n))
-
-/*-----------------------------------------------------------
-**
-** Register move and binary operations
-**
-**-----------------------------------------------------------
-**
-** SFBR_REG (reg, op, data) reg = SFBR op data
-** << 0 >>
-**
-** REG_SFBR (reg, op, data) SFBR = reg op data
-** << 0 >>
-**
-** REG_REG (reg, op, data) reg = reg op data
-** << 0 >>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_REG_OFS(ofs) ((ofs) << 16ul)
-
-#define SCR_SFBR_REG(reg,op,data) \
- (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul))
-
-#define SCR_REG_SFBR(reg,op,data) \
- (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul))
-
-#define SCR_REG_REG(reg,op,data) \
- (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul))
-
-
-#define SCR_LOAD 0x00000000
-#define SCR_SHL 0x01000000
-#define SCR_OR 0x02000000
-#define SCR_XOR 0x03000000
-#define SCR_AND 0x04000000
-#define SCR_SHR 0x05000000
-#define SCR_ADD 0x06000000
-#define SCR_ADDC 0x07000000
-
-/*-----------------------------------------------------------
-**
-** FROM_REG (reg) SFBR = reg
-** << 0 >>
-**
-** TO_REG (reg) reg = SFBR
-** << 0 >>
-**
-** LOAD_REG (reg, data) reg = <data>
-** << 0 >>
-**
-** LOAD_SFBR(data) SFBR = <data>
-** << 0 >>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_FROM_REG(reg) \
- SCR_REG_SFBR(reg,SCR_OR,0)
-
-#define SCR_TO_REG(reg) \
- SCR_SFBR_REG(reg,SCR_OR,0)
-
-#define SCR_LOAD_REG(reg,data) \
- SCR_REG_REG(reg,SCR_LOAD,data)
-
-#define SCR_LOAD_SFBR(data) \
- (SCR_REG_SFBR (gpreg, SCR_LOAD, data))
-
-/*-----------------------------------------------------------
-**
-** LOAD from memory to register.
-** STORE from register to memory.
-**
-**-----------------------------------------------------------
-**
-** LOAD_ABS (LEN)
-** <<start address>>
-**
-** LOAD_REL (LEN) (DSA relative)
-** <<dsa_offset>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_NO_FLUSH2 0x02000000
-#define SCR_DSA_REL2 0x10000000
-
-#define SCR_LOAD_R(reg, how, n) \
- (0xe1000000 | how | (SCR_REG_OFS(REG(reg))) | (n))
-
-#define SCR_STORE_R(reg, how, n) \
- (0xe0000000 | how | (SCR_REG_OFS(REG(reg))) | (n))
-
-#define SCR_LOAD_ABS(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2, n)
-#define SCR_LOAD_REL(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n)
-#define SCR_LOAD_ABS_F(reg, n) SCR_LOAD_R(reg, 0, n)
-#define SCR_LOAD_REL_F(reg, n) SCR_LOAD_R(reg, SCR_DSA_REL2, n)
-
-#define SCR_STORE_ABS(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2, n)
-#define SCR_STORE_REL(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n)
-#define SCR_STORE_ABS_F(reg, n) SCR_STORE_R(reg, 0, n)
-#define SCR_STORE_REL_F(reg, n) SCR_STORE_R(reg, SCR_DSA_REL2, n)
-
-
-/*-----------------------------------------------------------
-**
-** Waiting for Disconnect or Reselect
-**
-**-----------------------------------------------------------
-**
-** JUMP [ | IFTRUE/IFFALSE ( ... ) ]
-** <<address>>
-**
-** JUMPR [ | IFTRUE/IFFALSE ( ... ) ]
-** <<distance>>
-**
-** CALL [ | IFTRUE/IFFALSE ( ... ) ]
-** <<address>>
-**
-** CALLR [ | IFTRUE/IFFALSE ( ... ) ]
-** <<distance>>
-**
-** RETURN [ | IFTRUE/IFFALSE ( ... ) ]
-** <<dummy>>
-**
-** INT [ | IFTRUE/IFFALSE ( ... ) ]
-** <<ident>>
-**
-** INT_FLY [ | IFTRUE/IFFALSE ( ... ) ]
-** <<ident>>
-**
-** Conditions:
-** WHEN (phase)
-** IF (phase)
-** CARRY
-** DATA (data, mask)
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_NO_OP 0x80000000
-#define SCR_JUMP 0x80080000
-#define SCR_JUMPR 0x80880000
-#define SCR_CALL 0x88080000
-#define SCR_CALLR 0x88880000
-#define SCR_RETURN 0x90080000
-#define SCR_INT 0x98080000
-#define SCR_INT_FLY 0x98180000
-
-#define IFFALSE(arg) (0x00080000 | (arg))
-#define IFTRUE(arg) (0x00000000 | (arg))
-
-#define WHEN(phase) (0x00030000 | (phase))
-#define IF(phase) (0x00020000 | (phase))
-
-#define DATA(D) (0x00040000 | ((D) & 0xff))
-#define MASK(D,M) (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff))
-
-#define CARRYSET (0x00200000)
-
-/*-----------------------------------------------------------
-**
-** SCSI constants.
-**
-**-----------------------------------------------------------
-*/
-
-/*
-** Messages
-*/
-
-#define M_COMPLETE (0x00)
-#define M_EXTENDED (0x01)
-#define M_SAVE_DP (0x02)
-#define M_RESTORE_DP (0x03)
-#define M_DISCONNECT (0x04)
-#define M_ID_ERROR (0x05)
-#define M_ABORT (0x06)
-#define M_REJECT (0x07)
-#define M_NOOP (0x08)
-#define M_PARITY (0x09)
-#define M_LCOMPLETE (0x0a)
-#define M_FCOMPLETE (0x0b)
-#define M_RESET (0x0c)
-#define M_ABORT_TAG (0x0d)
-#define M_CLEAR_QUEUE (0x0e)
-#define M_INIT_REC (0x0f)
-#define M_REL_REC (0x10)
-#define M_TERMINATE (0x11)
-#define M_SIMPLE_TAG (0x20)
-#define M_HEAD_TAG (0x21)
-#define M_ORDERED_TAG (0x22)
-#define M_IGN_RESIDUE (0x23)
-#define M_IDENTIFY (0x80)
-
-#define M_X_MODIFY_DP (0x00)
-#define M_X_SYNC_REQ (0x01)
-#define M_X_WIDE_REQ (0x03)
-
-/*
-** Status
-*/
-
-#define S_GOOD (0x00)
-#define S_CHECK_COND (0x02)
-#define S_COND_MET (0x04)
-#define S_BUSY (0x08)
-#define S_INT (0x10)
-#define S_INT_COND_MET (0x14)
-#define S_CONFLICT (0x18)
-#define S_TERMINATED (0x20)
-#define S_QUEUE_FULL (0x28)
-#define S_ILLEGAL (0xff)
-#define S_SENSE (0x80)
-
-/*
- * End of ncrreg from FreeBSD
- */
-
-#endif /* !defined HOSTS_C */
-
-#endif /* defined NCR53C8XX_H */
+#endif /* NCR53C8XX_H */
diff --git a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c
index a2a04d77a..066201094 100644
--- a/drivers/scsi/pci2000.c
+++ b/drivers/scsi/pci2000.c
@@ -1,26 +1,36 @@
-/*+M*************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver proc support for Linux.
+/****************************************************************************
+ * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
*
- * Copyright (c) 1997 Perceptive Solutions, Inc.
+ * pci2000.c - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
*
- * This program is free software; you can redistribute 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.
+ * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
+ * All Rights Reserved.
*
- * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
*
- * 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.
+ * Technical updates and product information at:
+ * http://www.psidisk.com
*
+ * Please send questions, comments, bug reports to:
+ * tech@psidisk.com Technical Support
*
- * File Name: pci2000i.c
*
- *-M*************************************************************************/
+ * Revisions 1.10 Jan-21-1999
+ * - Fixed sign on message to reflect proper controller name.
+ * - Added support for RAID status monitoring and control.
+ *
+ * Revisions 1.11 Mar-22-1999
+ * - Fixed control timeout to not lock up the entire system if
+ * controller goes offline completely.
+ *
+ * Revisions 1.12 Mar-26-1999
+ * - Fixed spinlock and PCI configuration.
+ *
+ ****************************************************************************/
+#define PCI2000_VERSION "1.12"
#include <linux/module.h>
@@ -34,16 +44,21 @@
#include <linux/proc_fs.h>
#include <asm/dma.h>
#include <asm/system.h>
-#include <asm/spinlock.h>
#include <asm/io.h>
#include <linux/blk.h>
#include "scsi.h"
#include "hosts.h"
+#include <linux/stat.h>
#include "pci2000.h"
#include "psi_roy.h"
-#include<linux/stat.h>
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
+#include <asm/spinlock.h>
+#endif
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,93)
+#include <linux/bios32.h>
+#endif
struct proc_dir_entry Proc_Scsi_Pci2000 =
{ PROC_SCSI_PCI2000, 7, "pci2000", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
@@ -81,6 +96,7 @@ typedef struct
USHORT mb4;
USHORT cmd;
USHORT tag;
+ ULONG irqOwned;
DEV2000 dev[MAX_BUS][MAX_UNITS];
} ADAPTER2000, *PADAPTER2000;
@@ -89,7 +105,6 @@ typedef struct
static struct Scsi_Host *PsiHost[MAXADAPTER] = {NULL,}; // One for each adapter
static int NumAdapters = 0;
-
/****************************************************************
* Name: WaitReady :LOCAL
*
@@ -102,13 +117,14 @@ static int NumAdapters = 0;
****************************************************************/
static int WaitReady (PADAPTER2000 padapter)
{
- ULONG timer;
+ ULONG z;
- timer = jiffies + TIMEOUT_COMMAND; // calculate the timeout value
- do {
+ for ( z = 0; z < (TIMEOUT_COMMAND * 4); z++ )
+ {
if ( !inb_p (padapter->cmd) )
return FALSE;
- } while ( timer > jiffies ); // test for timeout
+ udelay (250);
+ };
return TRUE;
}
/****************************************************************
@@ -180,6 +196,26 @@ static int BuildSgList (Scsi_Cmnd *SCpnt, PADAPTER2000 padapter, PDEV2000 pdev)
outl (SCpnt->request_bufflen, padapter->mb3);
return TRUE;
}
+/*********************************************************************
+ * Name: PsiRaidCmd
+ *
+ * Description: Execute a simple command.
+ *
+ * Parameters: padapter - Pointer to adapter control structure.
+ * cmd - Roy command byte.
+ *
+ * Returns: Return error status.
+ *
+ ********************************************************************/
+static int PsiRaidCmd (PADAPTER2000 padapter, char cmd)
+ {
+ if ( WaitReady (padapter) ) // test for command register ready
+ return DID_TIME_OUT;
+ outb_p (cmd, padapter->cmd); // issue command
+ if ( WaitReady (padapter) ) // wait for adapter ready
+ return DID_TIME_OUT;
+ return DID_OK;
+ }
/****************************************************************
* Name: Irq_Handler :LOCAL
*
@@ -204,6 +240,23 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
int pun;
int bus;
int z;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ int flags;
+#else /* version >= v2.1.95 */
+ unsigned long flags;
+#endif /* version >= v2.1.95 */
+
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /* Disable interrupts, if they aren't already disabled. */
+ save_flags (flags);
+ cli ();
+#else /* version >= v2.1.95 */
+ /*
+ * Disable interrupts, if they aren't already disabled and acquire
+ * the I/O spinlock.
+ */
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
DEB(printk ("\npci2000 recieved interrupt "));
for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
@@ -222,7 +275,7 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
if ( !shost )
{
DEB (printk ("\npci2000: not my interrupt"));
- return;
+ goto irq_return;
}
padapter = HOSTDATA(shost);
@@ -246,7 +299,7 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
outb_p (0xFF, padapter->tag); // clear the op interrupt
outb_p (CMD_DONE, padapter->cmd); // complete the op
- return; // done, but, with what?
+ goto irq_return;; // done, but, with what?
irqProceed:;
if ( tag & ERR08_TAGGED ) // is there an error here?
@@ -254,7 +307,7 @@ irqProceed:;
if ( WaitReady (padapter) )
{
OpDone (SCpnt, DID_TIME_OUT << 16);
- return;
+ goto irq_return;;
}
outb_p (tag0, padapter->mb0); // get real error code
@@ -262,7 +315,7 @@ irqProceed:;
if ( WaitReady (padapter) ) // wait for controller to suck up the op
{
OpDone (SCpnt, DID_TIME_OUT << 16);
- return;
+ goto irq_return;;
}
error = inl (padapter->mb0); // get error data
@@ -275,24 +328,40 @@ irqProceed:;
if ( bus ) // are we doint SCSI commands?
{
OpDone (SCpnt, (DID_OK << 16) | 2);
- return;
+ goto irq_return;;
}
if ( *SCpnt->cmnd == SCSIOP_TEST_UNIT_READY )
OpDone (SCpnt, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2); // test caller we have sense data too
else
OpDone (SCpnt, DID_ERROR << 16);
- return;
+ goto irq_return;;
}
OpDone (SCpnt, DID_ERROR << 16);
- return;
+ goto irq_return;;
}
outb_p (0xFF, padapter->tag); // clear the op interrupt
outb_p (CMD_DONE, padapter->cmd); // complete the op
OpDone (SCpnt, DID_OK << 16);
+
+irq_return:;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /*
+ * Restore the original flags which will enable interrupts
+ * if and only if they were enabled on entry.
+ */
+ restore_flags (flags);
+#else /* version >= v2.1.95 */
+ /*
+ * Release the I/O spinlock and restore the original flags
+ * which will enable interrupts if and only if they were
+ * enabled on entry.
+ */
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
}
/****************************************************************
- * Name: Pci2220i_QueueCommand
+ * Name: Pci2000_QueueCommand
*
* Description: Process a queued command from the SCSI manager.
*
@@ -366,7 +435,35 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
switch ( *cdb )
{
case SCSIOP_INQUIRY: // inquiry CDB
- {
+ if ( cdb[2] == SC_MY_RAID )
+ {
+ switch ( cdb[3] )
+ {
+ case MY_SCSI_REBUILD:
+ OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16);
+ return 0;
+ case MY_SCSI_ALARMMUTE:
+ OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16);
+ return 0;
+ case MY_SCSI_DEMOFAIL:
+ OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16);
+ return 0;
+ default:
+ if ( SCpnt->use_sg )
+ {
+ rc = DID_ERROR;
+ goto finished;
+ }
+ else
+ outl (virt_to_bus (SCpnt->request_buffer), padapter->mb2);
+ outl (cdb[5], padapter->mb0);
+ outl (cdb[3], padapter->mb3);
+ cmd = CMD_DASD_RAID_RQ;
+ break;
+ }
+ break;
+ }
+
if ( SCpnt->use_sg )
{
outl (virt_to_bus (((struct scatterlist *)(SCpnt->request_buffer))->address), padapter->mb2);
@@ -378,7 +475,6 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
outl (SCpnt->request_bufflen, padapter->mb3);
cmd = CMD_DASD_SCSI_INQ;
break;
- }
case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
outl (virt_to_bus (SCpnt->sense_buffer), padapter->mb2);
@@ -454,7 +550,7 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
if ( cmd )
break;
default:
- DEB (printk ("pci2220i_queuecommand: Unsupported command %02X\n", *cdb));
+ DEB (printk ("pci2000_queuecommand: Unsupported command %02X\n", *cdb));
OpDone (SCpnt, DID_ERROR << 16);
return 0;
}
@@ -466,14 +562,6 @@ finished:;
OpDone (SCpnt, rc << 16);
return 0;
}
-static void do_Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
- {
- unsigned long flags;
-
- spin_lock_irqsave(&io_request_lock, flags);
- Irq_Handler(irq, dev_id, regs);
- spin_unlock_irqrestore(&io_request_lock, flags);
- }
/****************************************************************
* Name: internal_done :LOCAL
*
@@ -489,7 +577,7 @@ static void internal_done (Scsi_Cmnd * SCpnt)
SCpnt->SCp.Status++;
}
/****************************************************************
- * Name: Pci2220i_Command
+ * Name: Pci2000_Command
*
* Description: Process a command from the SCSI manager.
*
@@ -510,79 +598,121 @@ int Pci2000_Command (Scsi_Cmnd *SCpnt)
return SCpnt->result;
}
/****************************************************************
- * Name: Pci2220i_Detect
+ * Name: Pci2000_Detect
*
* Description: Detect and initialize our boards.
*
* Parameters: tpnt - Pointer to SCSI host template structure.
*
- * Returns: Number of adapters found.
+ * Returns: Number of adapters installed.
*
****************************************************************/
int Pci2000_Detect (Scsi_Host_Template *tpnt)
{
- int pci_index = 0;
+ int found = 0;
+ int installed = 0;
struct Scsi_Host *pshost;
PADAPTER2000 padapter;
- int z;
+ int z, zz;
int setirq;
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
struct pci_dev *pdev = NULL;
+#else
+ UCHAR pci_bus, pci_device_fn;
+#endif
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ if ( !pci_present () )
+#else
+ if ( !pcibios_present () )
+#endif
+ {
+ printk ("pci2000: PCI BIOS not present\n");
+ return 0;
+ }
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
+#else
+ while ( !pcibios_find_device (VENDOR_PSI, DEVICE_ROY_1, found, &pci_bus, &pci_device_fn) )
+#endif
+ {
+ pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
+ padapter = HOSTDATA(pshost);
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ padapter->basePort = pdev->base_address[1] & 0xFFFE;
+#else
+ pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &padapter->basePort);
+ padapter->basePort &= 0xFFFE;
+#endif
+ DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address
+ padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes
+ padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4;
+ padapter->mb2 = padapter->basePort + RTR_MAILBOX + 8;
+ padapter->mb3 = padapter->basePort + RTR_MAILBOX + 12;
+ padapter->mb4 = padapter->basePort + RTR_MAILBOX + 16;
+ padapter->cmd = padapter->basePort + RTR_LOCAL_DOORBELL; // command register
+ padapter->tag = padapter->basePort + RTR_PCI_DOORBELL; // tag/response register
- if ( pci_present () )
- while ((pdev = pci_find_device(VENDOR_PSI, DEVICE_ROY_1, pdev)))
+ if ( WaitReady (padapter) )
+ goto unregister;
+ outb_p (0x84, padapter->mb0);
+ outb_p (CMD_SPECIFY, padapter->cmd);
+ if ( WaitReady (padapter) )
+ goto unregister;
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ pshost->irq = pdev->irq;
+#else
+ pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
+#endif
+ setirq = 1;
+ padapter->irqOwned = 0;
+ for ( z = 0; z < installed; z++ ) // scan for shared interrupts
{
- pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
- padapter = HOSTDATA(pshost);
-
- padapter->basePort = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
- DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address
- padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes
- padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4;
- padapter->mb2 = padapter->basePort + RTR_MAILBOX + 8;
- padapter->mb3 = padapter->basePort + RTR_MAILBOX + 12;
- padapter->mb4 = padapter->basePort + RTR_MAILBOX + 16;
- padapter->cmd = padapter->basePort + RTR_LOCAL_DOORBELL; // command register
- padapter->tag = padapter->basePort + RTR_PCI_DOORBELL; // tag/response register
-
- if ( WaitReady (padapter) )
- goto unregister;
- outb_p (0x84, padapter->mb0);
- outb_p (CMD_SPECIFY, padapter->cmd);
- if ( WaitReady (padapter) )
- goto unregister;
-
- pshost->irq = pdev->irq;
- setirq = 1;
- for ( z = 0; z < pci_index; z++ ) // scan for shared interrupts
- {
- if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
- setirq = 0;
- }
- if ( setirq ) // if not shared, posses
+ if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
+ setirq = 0;
+ }
+ if ( setirq ) // if not shared, posses
+ {
+ if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2000", padapter) < 0 )
{
- if ( request_irq (pshost->irq, do_Irq_Handler, 0, "pci2000", NULL) )
+ if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 )
{
- printk ("Unable to allocate IRQ for PSI-2000 controller.\n");
+ printk ("Unable to allocate IRQ for PCI-2000 controller.\n");
goto unregister;
}
}
- PsiHost[pci_index] = pshost; // save SCSI_HOST pointer
-
- pshost->unique_id = padapter->basePort;
- pshost->max_id = 16;
- pshost->max_channel = 1;
-
- printk("\nPSI-2000 EIDE CONTROLLER: at I/O = %X IRQ = %d\n", padapter->basePort, pshost->irq);
- printk("(C) 1997 Perceptive Solutions, Inc. All rights reserved\n\n");
- NumAdapters++;
+ padapter->irqOwned = pshost->irq; // set IRQ as owned
+ }
+ PsiHost[installed] = pshost; // save SCSI_HOST pointer
+
+ pshost->io_port = padapter->basePort;
+ pshost->n_io_port = 0xFF;
+ pshost->unique_id = padapter->basePort;
+ pshost->max_id = 16;
+ pshost->max_channel = 1;
+
+ for ( zz = 0; zz < MAX_BUS; zz++ )
+ for ( z = 0; z < MAX_UNITS; z++ )
+ padapter->dev[zz][z].tag = 0;
+
+ printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %X IRQ = %d\n", padapter->basePort, pshost->irq);
+ printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION, __DATE__, __TIME__);
+ found++;
+ if ( ++installed < MAXADAPTER )
continue;
+ break;
unregister:;
- scsi_unregister (pshost);
- }
- return NumAdapters;
+ scsi_unregister (pshost);
+ found++;
+ }
+ NumAdapters = installed;
+ return installed;
}
/****************************************************************
- * Name: Pci2220i_Abort
+ * Name: Pci2000_Abort
*
* Description: Process the Abort command from the SCSI manager.
*
@@ -597,7 +727,7 @@ int Pci2000_Abort (Scsi_Cmnd *SCpnt)
return SCSI_ABORT_SNOOZE;
}
/****************************************************************
- * Name: Pci2220i_Reset
+ * Name: Pci2000_Reset
*
* Description: Process the Reset command from the SCSI manager.
*
@@ -615,11 +745,34 @@ int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
{
return SCSI_RESET_PUNT;
}
+/****************************************************************
+ * Name: Pci2000_Release
+ *
+ * Description: Release resources allocated for a single each adapter.
+ *
+ * Parameters: pshost - Pointer to SCSI command structure.
+ *
+ * Returns: zero.
+ *
+ ****************************************************************/
+int Pci2000_Release (struct Scsi_Host *pshost)
+ {
+ PADAPTER2000 padapter = HOSTDATA (pshost);
+
+ if ( padapter->irqOwned )
+#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
+ free_irq (pshost->irq);
+#else /* version >= v1.3.70 */
+ free_irq (pshost->irq, padapter);
+#endif /* version >= v1.3.70 */
+ release_region (pshost->io_port, pshost->n_io_port);
+ scsi_unregister(pshost);
+ return 0;
+ }
#include "sd.h"
-
/****************************************************************
- * Name: Pci2220i_BiosParam
+ * Name: Pci2000_BiosParam
*
* Description: Process the biosparam request from the SCSI manager to
* return C/H/S data.
diff --git a/drivers/scsi/pci2000.h b/drivers/scsi/pci2000.h
index ab8458d1d..a3daa5f76 100644
--- a/drivers/scsi/pci2000.h
+++ b/drivers/scsi/pci2000.h
@@ -1,29 +1,23 @@
-/*+M*************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver proc support for Linux.
+/****************************************************************************
+ * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
*
- * Copyright (c) 1997 Perceptive Solutions, Inc.
+ * pci2000.h - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
*
- * This program is free software; you can redistribute 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.
+ * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
+ * All Rights Reserved.
*
- * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
*
- * 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.
+ * Technical updates and product information at:
+ * http://www.psidisk.com
*
+ * Please send questions, comments, bug reports to:
+ * tech@psidisk.com Technical Support
*
- * File Name: pci2000.h
- *
- * Description: Header file for the SCSI driver for the PCI-2000
- * interface card.
- *
- *-M*************************************************************************/
+ ****************************************************************************/
#ifndef _PCI2000_H
#define _PCI2000_H
@@ -33,6 +27,11 @@
#ifndef PSI_EIDE_SCSIOP
#define PSI_EIDE_SCSIOP 1
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+#define LINUXVERSION(v,p,s) (((v)<<16) + ((p)<<8) + (s))
+
/************************************************/
/* definition of standard data types */
/************************************************/
@@ -194,6 +193,7 @@ int Pci2000_Command (Scsi_Cmnd *SCpnt);
int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
int Pci2000_Abort (Scsi_Cmnd *SCpnt);
int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int flags);
+int Pci2000_Release (struct Scsi_Host *pshost);
int Pci2000_BiosParam (Disk *disk, kdev_t dev, int geom[]);
#ifndef NULL
@@ -202,18 +202,57 @@ int Pci2000_BiosParam (Disk *disk, kdev_t dev, int geom[]);
extern struct proc_dir_entry Proc_Scsi_Pci2000;
-#define PCI2000 { proc_dir: &Proc_Scsi_Pci2000,/* proc_dir_entry */ \
- name: "PCI-2000 SCSI Intelligent Disk Controller",\
- detect: Pci2000_Detect, \
- command: Pci2000_Command, \
- queuecommand: Pci2000_QueueCommand, \
- abort: Pci2000_Abort, \
- reset: Pci2000_Reset, \
- bios_param: Pci2000_BiosParam, \
- can_queue: 16, \
- this_id: -1, \
- sg_tablesize: 16, \
- cmd_per_lun: 1, \
- use_clustering: DISABLE_CLUSTERING }
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,75)
+#define PCI2000 { \
+ next: NULL, \
+ module: NULL, \
+ proc_dir: &Proc_Scsi_Pci2000, \
+ proc_info: NULL, /* let's not bloat the kernel */ \
+ name: "PCI-2000 SCSI Intelligent Disk Controller",\
+ detect: Pci2000_Detect, \
+ release: Pci2000_Release, \
+ info: NULL, /* let's not bloat the kernel */ \
+ command: Pci2000_Command, \
+ queuecommand: Pci2000_QueueCommand, \
+ eh_strategy_handler: NULL, \
+ eh_abort_handler: NULL, \
+ eh_device_reset_handler: NULL, \
+ eh_bus_reset_handler: NULL, \
+ eh_host_reset_handler: NULL, \
+ abort: Pci2000_Abort, \
+ reset: Pci2000_Reset, \
+ slave_attach: NULL, \
+ bios_param: Pci2000_BiosParam, \
+ can_queue: 16, \
+ this_id: -1, \
+ sg_tablesize: 16, \
+ cmd_per_lun: 1, \
+ present: 0, \
+ unchecked_isa_dma: 0, \
+ use_clustering: DISABLE_CLUSTERING, \
+ use_new_eh_code: 0 \
+ }
+#else
+#define PCI2000 { NULL, NULL, \
+ &Proc_Scsi_Pci2000,/* proc_dir_entry */ \
+ NULL, \
+ "PCI-2000 SCSI Intelligent Disk Controller",\
+ Pci2000_Detect, \
+ Pci2000_Release, \
+ NULL, \
+ Pci2000_Command, \
+ Pci2000_QueueCommand, \
+ Pci2000_Abort, \
+ Pci2000_Reset, \
+ NULL, \
+ Pci2000_BiosParam, \
+ 16, \
+ -1, \
+ 16, \
+ 1, \
+ 0, \
+ 0, \
+ DISABLE_CLUSTERING }
+#endif
#endif
diff --git a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c
index 130f59bd7..bcbd30913 100644
--- a/drivers/scsi/pci2220i.c
+++ b/drivers/scsi/pci2220i.c
@@ -1,80 +1,83 @@
-/*+M*************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver proc support for Linux.
+/****************************************************************************
+ * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
*
- * Copyright (c) 1997 Perceptive Solutions, Inc.
+ * pci2220i.c - Linux Host Driver for PCI-2220I EIDE RAID Adapters
*
- * This program is free software; you can redistribute 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.
+ * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
+ * All Rights Reserved.
*
- * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
*
- * 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.
+ * Technical updates and product information at:
+ * http://www.psidisk.com
*
+ * Please send questions, comments, bug reports to:
+ * tech@psidisk.com Technical Support
*
- * File Name: pci2220i.c
*
- * Description: SCSI driver for the PCI2220I EIDE interface card.
+ * Revisions 1.10 Mar-26-1999
+ * - Updated driver for RAID and hot reconstruct support.
*
- *-M*************************************************************************/
+ * Revisions 1.11 Mar-26-1999
+ * - Fixed spinlock and PCI configuration.
+ *
+ ****************************************************************************/
#include <linux/module.h>
-
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/string.h>
+#include <linux/malloc.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/kdev_t.h>
+#include <linux/blk.h>
+#include <linux/timer.h>
#include <asm/dma.h>
#include <asm/system.h>
-#include <asm/spinlock.h>
#include <asm/io.h>
-#include <linux/blk.h>
#include "scsi.h"
#include "hosts.h"
-
#include "pci2220i.h"
-#include "psi_dale.h"
-#include<linux/stat.h>
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
+#include <asm/spinlock.h>
+#endif
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,93)
+#include <linux/bios32.h>
+#endif
+
+#define PCI2220I_VERSION "1.11"
+//#define READ_CMD IDE_COMMAND_READ
+//#define WRITE_CMD IDE_COMMAND_WRITE
+//#define MAX_BUS_MASTER_BLOCKS 1 // This is the maximum we can bus master
+#define READ_CMD IDE_CMD_READ_MULTIPLE
+#define WRITE_CMD IDE_CMD_WRITE_MULTIPLE
+#define MAX_BUS_MASTER_BLOCKS SECTORSXFER // This is the maximum we can bus master
+
struct proc_dir_entry Proc_Scsi_Pci2220i =
- { PROC_SCSI_PCI2220I, 7, "pci2220i", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
+ { PROC_SCSI_PCI2220I, 8, "pci2220i", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
//#define DEBUG 1
#ifdef DEBUG
#define DEB(x) x
-#define STOP_HERE {int st;for(st=0;st<100;st++){st=1;}}
+#define STOP_HERE() {int st;for(st=0;st<100;st++){st=1;}}
#else
#define DEB(x)
-#define STOP_HERE
+#define STOP_HERE()
#endif
-#define MAXADAPTER 4 /* Increase this and the sizes of the arrays below, if you need more. */
-
-#define MAX_BUS_MASTER_BLOCKS 1 // This is the maximum we can bus master for (1024 bytes)
+#define MAXADAPTER 4 // Increase this and the sizes of the arrays below, if you need more.
-#define PORT_DATA 0
-#define PORT_ERROR 1
-#define PORT_SECTOR_COUNT 2
-#define PORT_LBA_0 3
-#define PORT_LBA_8 4
-#define PORT_LBA_16 5
-#define PORT_LBA_24 6
-#define PORT_STAT_CMD 7
-#define PORT_STAT_SEL 8
-#define PORT_FAIL 9
-#define PORT_ALT_STAT 10
typedef struct
{
@@ -87,44 +90,245 @@ typedef struct
USHORT cylinders; // number of cylinders for this device
USHORT spareword; // placeholder
ULONG blocks; // number of blocks on device
- } OUR_DEVICE, *POUR_DEVICE;
+ DISK_MIRROR DiskMirror[2]; // RAID status and control
+ ULONG lastsectorlba[2]; // last addressable sector on the drive
+ USHORT raid; // RAID active flag
+ USHORT mirrorRecon;
+ UCHAR hotRecon;
+ USHORT reconCount;
+ } OUR_DEVICE, *POUR_DEVICE;
typedef struct
{
- USHORT ports[12];
- USHORT regDmaDesc; // address of the DMA discriptor register for direction of transfer
- USHORT regDmaCmdStat; // Byte #1 of DMA command status register
- USHORT regDmaAddrPci; // 32 bit register for PCI address of DMA
- USHORT regDmaAddrLoc; // 32 bit register for local bus address of DMA
- USHORT regDmaCount; // 32 bit register for DMA transfer count
- USHORT regDmaMode; // 32 bit register for DMA mode control
- USHORT regRemap; // 32 bit local space remap
- USHORT regDesc; // 32 bit local region descriptor
- USHORT regRange; // 32 bit local range
- USHORT regIrqControl; // 16 bit Interrupt enable/disable and status
- USHORT regScratchPad; // scratch pad I/O base address
- USHORT regBase; // Base I/O register for data space
- USHORT basePort; // PLX base I/O port
- USHORT timingMode; // timing mode currently set for adapter
- ULONG timingAddress; // address to use on adapter for current timing mode
- OUR_DEVICE device[4];
- IDE_STRUCT ide;
+ USHORT regDmaDesc; // address of the DMA discriptor register for direction of transfer
+ USHORT regDmaCmdStat; // Byte #1 of DMA command status register
+ USHORT regDmaAddrPci; // 32 bit register for PCI address of DMA
+ USHORT regDmaAddrLoc; // 32 bit register for local bus address of DMA
+ USHORT regDmaCount; // 32 bit register for DMA transfer count
+ USHORT regDmaMode; // 32 bit register for DMA mode control
+ USHORT regRemap; // 32 bit local space remap
+ USHORT regDesc; // 32 bit local region descriptor
+ USHORT regRange; // 32 bit local range
+ USHORT regIrqControl; // 16 bit Interrupt enable/disable and status
+ USHORT regScratchPad; // scratch pad I/O base address
+ USHORT regBase; // Base I/O register for data space
+ USHORT regData; // data register I/O address
+ USHORT regError; // error register I/O address
+ USHORT regSectCount; // sector count register I/O address
+ USHORT regLba0; // least significant byte of LBA
+ USHORT regLba8; // next least significant byte of LBA
+ USHORT regLba16; // next most significan byte of LBA
+ USHORT regLba24; // head and most 4 significant bits of LBA
+ USHORT regStatCmd; // status on read and command on write register
+ USHORT regStatSel; // board status on read and spigot select on write register
+ USHORT regFail; // fail bits control register
+ USHORT regAltStat; // alternate status and drive control register
+ USHORT basePort; // PLX base I/O port
+ USHORT timingMode; // timing mode currently set for adapter
+ USHORT timingPIO; // TRUE if PIO timing is active
+ ULONG timingAddress; // address to use on adapter for current timing mode
+ ULONG irqOwned; // owned IRQ or zero if shared
+ OUR_DEVICE device[DALE_MAXDRIVES];
+ DISK_MIRROR *raidData[8];
ULONG startSector;
USHORT sectorCount;
+ UCHAR cmd;
Scsi_Cmnd *SCpnt;
VOID *buffer;
+ POUR_DEVICE pdev; // current device opearating on
USHORT expectingIRQ;
- USHORT readPhase;
+ USHORT reconIsStarting; // indicate hot reconstruct is starting
+ USHORT reconOn; // Hot reconstruct is to be done.
+ USHORT reconPhase; // Hot reconstruct operation is in progress.
+ ULONG reconSize;
+ USHORT demoFail; // flag for RAID failure demonstration
+ USHORT survivor;
+ USHORT failinprog;
+ struct timer_list reconTimer;
+ struct timer_list timer;
+ UCHAR *kBuffer;
} ADAPTER2220I, *PADAPTER2220I;
#define HOSTDATA(host) ((PADAPTER2220I)&host->hostdata)
+#define RECON_PHASE_READY 0x01
+#define RECON_PHASE_COPY 0x02
+#define RECON_PHASE_UPDATE 0x03
+#define RECON_PHASE_LAST 0x04
+#define RECON_PHASE_END 0x07
+#define RECON_PHASE_MARKING 0x80
+#define RECON_PHASE_FAILOVER 0xFF
static struct Scsi_Host *PsiHost[MAXADAPTER] = {NULL,}; // One for each adapter
static int NumAdapters = 0;
-static IDENTIFY_DATA identifyData;
static SETUP DaleSetup;
+static DISK_MIRROR DiskMirror[2];
+static ULONG ModeArray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE4P};
+
+static void ReconTimerExpiry (unsigned long data);
+
+/****************************************************************
+ * Name: MuteAlarm :LOCAL
+ *
+ * Description: Mute the audible alarm.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static void MuteAlarm (PADAPTER2220I padapter)
+ {
+ UCHAR old;
+
+ old = (inb_p (padapter->regStatSel) >> 3) | (inb_p (padapter->regStatSel) & 0x83);
+ outb_p (old | 0x40, padapter->regFail);
+ }
+/****************************************************************
+ * Name: WaitReady :LOCAL
+ *
+ * Description: Wait for device ready.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static int WaitReady (PADAPTER2220I padapter)
+ {
+ ULONG z;
+ UCHAR status;
+ for ( z = 0; z < (TIMEOUT_READY * 4); z++ )
+ {
+ status = inb_p (padapter->regStatCmd);
+ if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
+ return 0;
+ udelay (250);
+ }
+ return status;
+ }
+/****************************************************************
+ * Name: WaitReadyReset :LOCAL
+ *
+ * Description: Wait for device ready.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static int WaitReadyReset (PADAPTER2220I padapter)
+ {
+ ULONG z;
+ UCHAR status;
+
+ for ( z = 0; z < (250 * 4); z++ ) // wait up to 1/4 second
+ {
+ status = inb_p (padapter->regStatCmd);
+ if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
+ {
+ DEB (printk ("\nPCI2220I: Reset took %ld mSec to be ready", z / 4));
+ return 0;
+ }
+ udelay (250);
+ }
+ DEB (printk ("\nPCI2220I: Reset took more than 1 Second to come ready, Disk Failure"));
+ return status;
+ }
+/****************************************************************
+ * Name: WaitDrq :LOCAL
+ *
+ * Description: Wait for device ready for data transfer.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static int WaitDrq (PADAPTER2220I padapter)
+ {
+ ULONG z;
+ UCHAR status;
+
+ for ( z = 0; z < (TIMEOUT_DRQ * 4); z++ )
+ {
+ status = inb_p (padapter->regStatCmd);
+ if ( status & IDE_STATUS_DRQ )
+ return 0;
+ udelay (250);
+ }
+ return status;
+ }
+/****************************************************************
+ * Name: HardReset :LOCAL
+ *
+ * Description: Wait for device ready for data transfer.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ * pdev - Pointer to device.
+ * spigot - Spigot number.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static int HardReset (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot)
+ {
+ SelectSpigot (padapter, spigot | 0x80);
+
+ outb_p (0x0E, padapter->regAltStat); // reset the suvivor
+ udelay (100); // wait a little
+ outb_p (0x08, padapter->regAltStat); // clear the reset
+ udelay (100);
+ outb_p (0xA0, padapter->regLba24); //Specify drive
+
+ outb_p (pdev->byte6, padapter->regLba24); // select the drive
+ if ( WaitReadyReset (padapter) )
+ return TRUE;
+ outb_p (SECTORSXFER, padapter->regSectCount);
+ WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);
+ if ( WaitReady (padapter) )
+ return TRUE;
+ return FALSE;
+ }
+/****************************************************************
+ * Name: BusMaster :LOCAL
+ *
+ * Description: Do a bus master I/O.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ * datain - TRUE if data read.
+ * irq - TRUE if bus master interrupt expected.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static void BusMaster (PADAPTER2220I padapter, UCHAR datain, UCHAR irq)
+ {
+ ULONG zl;
+
+ outl (padapter->timingAddress, padapter->regDmaAddrLoc);
+ outl (virt_to_bus (padapter->buffer), padapter->regDmaAddrPci);
+ zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
+ padapter->sectorCount -= zl;
+ zl *= (ULONG)BYTES_PER_SECTOR;
+ padapter->buffer += zl;
+ outl (zl, padapter->regDmaCount);
+ if ( datain )
+ {
+ outb_p (8, padapter->regDmaDesc); // read operation
+ if ( irq && !padapter->sectorCount )
+ outb_p (5, padapter->regDmaMode); // interrupt on
+ else
+ outb_p (1, padapter->regDmaMode); // no interrupt
+ }
+ else
+ {
+ outb_p (0, padapter->regDmaDesc); // write operation
+ outb_p (1, padapter->regDmaMode); // no interrupt
+ }
+ outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
+ }
/****************************************************************
* Name: WriteData :LOCAL
*
@@ -137,114 +341,265 @@ static SETUP DaleSetup;
****************************************************************/
static int WriteData (PADAPTER2220I padapter)
{
- ULONG timer;
- USHORT *pports = padapter->ports;
+ ULONG zl;
+
+ if ( !WaitDrq (padapter) )
+ {
+ if ( padapter->timingPIO )
+ {
+ zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
+ outsw (padapter->regData, padapter->buffer, zl * (BYTES_PER_SECTOR / 2));
+ padapter->sectorCount -= zl;
+ padapter->buffer += zl * BYTES_PER_SECTOR;
+ }
+ else
+ BusMaster (padapter, 0, 0);
+ return 0;
+ }
+ padapter->cmd = 0; // null out the command byte
+ return 1;
+ }
+/****************************************************************
+ * Name: WriteDataBoth :LOCAL
+ *
+ * Description: Write data to device.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static int WriteDataBoth (PADAPTER2220I padapter)
+ {
+ ULONG zl;
+ UCHAR status0, status1;
- timer = jiffies + TIMEOUT_DRQ; // calculate the timeout value
- do {
- if ( inb_p (pports[PORT_STAT_CMD]) & IDE_STATUS_DRQ )
+ SelectSpigot (padapter, 1);
+ status0 = WaitDrq (padapter);
+ if ( !status0 )
+ {
+ SelectSpigot (padapter, 2);
+ status1 = WaitDrq (padapter);
+ if ( !status1 )
{
- outb_p (0, padapter->regDmaDesc); // write operation
- outl (padapter->timingAddress, padapter->regDmaAddrLoc);
- outl (virt_to_bus (padapter->buffer), padapter->regDmaAddrPci);
- outl ((ULONG)padapter->ide.ide.ide[2] * (ULONG)512, padapter->regDmaCount);
- outb_p (1, padapter->regDmaMode); // interrupts off
- outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
+ SelectSpigot (padapter, 3);
+ if ( padapter->timingPIO )
+ {
+ zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
+ outsw (padapter->regData, padapter->buffer, zl * (BYTES_PER_SECTOR / 2));
+ padapter->sectorCount -= zl;
+ padapter->buffer += zl * BYTES_PER_SECTOR;
+ }
+ else
+ BusMaster (padapter, 0, 0);
return 0;
}
- } while ( timer > jiffies ); // test for timeout
-
- padapter->ide.ide.ides.cmd = 0; // null out the command byte
- return 1;
+ }
+ padapter->cmd = 0; // null out the command byte
+ if ( status0 )
+ return 1;
+ return 2;
}
/****************************************************************
* Name: IdeCmd :LOCAL
*
- * Description: Process a queued command from the SCSI manager.
+ * Description: Process an IDE command.
*
* Parameters: padapter - Pointer adapter data structure.
+ * pdev - Pointer to device.
*
* Returns: Zero if no error or status register contents on error.
*
****************************************************************/
-static UCHAR IdeCmd (PADAPTER2220I padapter)
+static UCHAR IdeCmd (PADAPTER2220I padapter, POUR_DEVICE pdev)
{
- ULONG timer;
- USHORT *pports = padapter->ports;
UCHAR status;
- outb_p (padapter->ide.ide.ides.spigot, pports[PORT_STAT_SEL]); // select the spigot
- outb_p (padapter->ide.ide.ide[6], pports[PORT_LBA_24]); // select the drive
- timer = jiffies + TIMEOUT_READY; // calculate the timeout value
- DEB(printk ("\npci2220i Issueing new command: 0x%X",padapter->ide.ide.ides.cmd));
- do {
- status = inb_p (padapter->ports[PORT_STAT_CMD]);
- if ( status & IDE_STATUS_DRDY )
- {
- outb_p (padapter->ide.ide.ide[2], pports[PORT_SECTOR_COUNT]);
- outb_p (padapter->ide.ide.ide[3], pports[PORT_LBA_0]);
- outb_p (padapter->ide.ide.ide[4], pports[PORT_LBA_8]);
- outb_p (padapter->ide.ide.ide[5], pports[PORT_LBA_16]);
- padapter->expectingIRQ = 1;
- outb_p (padapter->ide.ide.ide[7], pports[PORT_STAT_CMD]);
-
- if ( padapter->ide.ide.ides.cmd == IDE_CMD_WRITE_MULTIPLE )
- return (WriteData (padapter));
- return 0;
- }
- } while ( timer > jiffies ); // test for timeout
+ SelectSpigot (padapter, pdev->spigot); // select the spigot
+ outb_p (pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24); // select the drive
+ status = WaitReady (padapter);
+ if ( !status )
+ {
+ outb_p (padapter->sectorCount, padapter->regSectCount);
+ outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
+ outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
+ outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
+ padapter->expectingIRQ = TRUE;
+ WriteCommand (padapter, padapter->cmd);
+ return 0;
+ }
- padapter->ide.ide.ides.cmd = 0; // null out the command byte
+ padapter->cmd = 0; // null out the command byte
return status;
}
/****************************************************************
- * Name: SetupTransfer :LOCAL
+ * Name: IdeCmdBoth :LOCAL
*
- * Description: Setup a data transfer command.
+ * Description: Process an IDE command to both drivers.
*
* Parameters: padapter - Pointer adapter data structure.
- * drive - Drive/head register upper nibble only.
*
- * Returns: TRUE if no data to transfer.
+ * Returns: Zero if no error or spigot of error.
*
****************************************************************/
-static int SetupTransfer (PADAPTER2220I padapter, UCHAR drive)
+static UCHAR IdeCmdBoth (PADAPTER2220I padapter)
{
- if ( padapter->sectorCount )
+ UCHAR status0;
+ UCHAR status1;
+
+ SelectSpigot (padapter, 3); // select the spigots
+ outb_p (padapter->pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24);// select the drive
+ SelectSpigot (padapter, 1);
+ status0 = WaitReady (padapter);
+ if ( !status0 )
{
- *(ULONG *)padapter->ide.ide.ides.lba = padapter->startSector;
- padapter->ide.ide.ide[6] |= drive;
-// padapter->ide.ide.ides.sectors = ( padapter->sectorCount > SECTORSXFER ) ? SECTORSXFER : padapter->sectorCount;
- padapter->ide.ide.ides.sectors = ( padapter->sectorCount > MAX_BUS_MASTER_BLOCKS ) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
- padapter->sectorCount -= padapter->ide.ide.ides.sectors; // bump the start and count for next xfer
- padapter->startSector += padapter->ide.ide.ides.sectors;
- return 0;
+ SelectSpigot (padapter, 2);
+ status1 = WaitReady (padapter);
+ if ( !status1 )
+ {
+ SelectSpigot (padapter, 3);
+ outb_p (padapter->sectorCount, padapter->regSectCount);
+ outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
+ outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
+ outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
+ padapter->expectingIRQ = TRUE;
+ WriteCommand (padapter, padapter->cmd);
+ return 0;
+ }
+ }
+ padapter->cmd = 0; // null out the command byte
+ if ( status0 )
+ return 1;
+ return 2;
+ }
+/****************************************************************
+ * Name: OpDone :LOCAL
+ *
+ * Description: Complete an operatoin done sequence.
+ *
+ * Parameters: padapter - Pointer to host data block.
+ * spigot - Spigot select code.
+ * device - Device byte code.
+ *
+ * Returns: Nothing.
+ *
+ ****************************************************************/
+static void OpDone (PADAPTER2220I padapter, ULONG result)
+ {
+ Scsi_Cmnd *SCpnt = padapter->SCpnt;
+
+ if ( padapter->reconPhase )
+ {
+ padapter->reconPhase = 0;
+ if ( padapter->SCpnt )
+ {
+ Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
+ }
+ else
+ {
+ if ( padapter->reconOn )
+ {
+ ReconTimerExpiry ((unsigned long)padapter);
+ }
+ }
}
else
{
- padapter->ide.ide.ides.cmd = 0; // null out the command byte
- padapter->SCpnt = NULL;
- return 1;
+ padapter->cmd = 0;
+ padapter->SCpnt = NULL;
+ SCpnt->result = result;
+ SCpnt->scsi_done (SCpnt);
+ if ( padapter->reconOn && !padapter->reconTimer.data )
+ {
+ padapter->reconTimer.expires = jiffies + (HZ / 4); // start in 1/4 second
+ padapter->reconTimer.data = (unsigned long)padapter;
+ add_timer (&padapter->reconTimer);
+ }
}
}
/****************************************************************
+ * Name: InlineIdentify :LOCAL
+ *
+ * Description: Do an intline inquiry on a drive.
+ *
+ * Parameters: padapter - Pointer to host data block.
+ * spigot - Spigot select code.
+ * device - Device byte code.
+ *
+ * Returns: Last addressable sector or zero if none.
+ *
+ ****************************************************************/
+static ULONG InlineIdentify (PADAPTER2220I padapter, UCHAR spigot, UCHAR device)
+ {
+ PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
+
+ SelectSpigot (padapter, spigot | 0x80); // select the spigot
+ outb_p (device << 4, padapter->regLba24); // select the drive
+ if ( WaitReady (padapter) )
+ return 0;
+ WriteCommand (padapter, IDE_COMMAND_IDENTIFY);
+ if ( WaitDrq (padapter) )
+ return 0;
+ insw (padapter->regData, padapter->kBuffer, sizeof (IDENTIFY_DATA) >> 1);
+ return (pid->LBATotalSectors - 1);
+ }
+/****************************************************************
+ * Name: InlineReadSignature :LOCAL
+ *
+ * Description: Do an inline read RAID sigature.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ * pdev - Pointer to device.
+ * index - index of data to read.
+ *
+ * Returns: Zero if no error or status register contents on error.
+ *
+ ****************************************************************/
+static UCHAR InlineReadSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, int index)
+ {
+ UCHAR status;
+ UCHAR spigot = 1 << index;
+ ULONG zl = pdev->lastsectorlba[index];
+
+ SelectSpigot (padapter, spigot | 0x80); // select the spigot without interrupts
+ outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);
+ status = WaitReady (padapter);
+ if ( !status )
+ {
+ outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
+ outb_p (((UCHAR *)&zl)[1], padapter->regLba8);
+ outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
+ outb_p (1, padapter->regSectCount);
+ WriteCommand (padapter, IDE_COMMAND_READ);
+ status = WaitDrq (padapter);
+ if ( !status )
+ {
+ insw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
+ ((ULONG *)(&pdev->DiskMirror[index]))[0] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0];
+ ((ULONG *)(&pdev->DiskMirror[index]))[1] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1];
+ // some drives assert DRQ before IRQ so let's make sure we clear the IRQ
+ WaitReady (padapter);
+ return 0;
+ }
+ }
+ return status;
+ }
+/****************************************************************
* Name: DecodeError :LOCAL
*
* Description: Decode and process device errors.
*
- * Parameters: pshost - Pointer to host data block.
+ * Parameters: padapter - Pointer to adapter data.
* status - Status register code.
*
* Returns: The driver status code.
*
****************************************************************/
-static ULONG DecodeError (struct Scsi_Host *pshost, UCHAR status)
+static ULONG DecodeError (PADAPTER2220I padapter, UCHAR status)
{
- PADAPTER2220I padapter = HOSTDATA(pshost);
UCHAR error;
padapter->expectingIRQ = 0;
- padapter->SCpnt = NULL;
if ( status & IDE_STATUS_WRITE_FAULT )
{
return DID_PARITY << 16;
@@ -252,7 +607,7 @@ static ULONG DecodeError (struct Scsi_Host *pshost, UCHAR status)
if ( status & IDE_STATUS_BUSY )
return DID_BUS_BUSY << 16;
- error = inb_p (padapter->ports[PORT_ERROR]);
+ error = inb_p (padapter->regError);
DEB(printk ("\npci2220i error register: %x", error));
switch ( error )
{
@@ -268,6 +623,531 @@ static ULONG DecodeError (struct Scsi_Host *pshost, UCHAR status)
return DID_ERROR << 16;
}
/****************************************************************
+ * Name: StartTimer :LOCAL
+ *
+ * Description: Start the timer.
+ *
+ * Parameters: ipadapter - Pointer adapter data structure.
+ *
+ * Returns: Nothing.
+ *
+ ****************************************************************/
+static void StartTimer (PADAPTER2220I padapter)
+ {
+ padapter->timer.expires = jiffies + TIMEOUT_DATA;
+ add_timer (&padapter->timer);
+ }
+/****************************************************************
+ * Name: WriteSignature :LOCAL
+ *
+ * Description: Start the timer.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ * pdev - Pointer to our device.
+ * spigot - Selected spigot.
+ * index - index of mirror signature on device.
+ *
+ * Returns: TRUE on any error.
+ *
+ ****************************************************************/
+static int WriteSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot, int index)
+ {
+ ULONG zl;
+
+ SelectSpigot (padapter, spigot);
+ zl = pdev->lastsectorlba[index];
+ outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);
+ outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
+ outb_p (((UCHAR *)&zl)[1], padapter->regLba8);
+ outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
+ outb_p (1, padapter->regSectCount);
+
+ WriteCommand (padapter, IDE_COMMAND_WRITE);
+ if ( WaitDrq (padapter) )
+ return TRUE;
+ StartTimer (padapter);
+ padapter->expectingIRQ = TRUE;
+
+ ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0] = ((ULONG *)(&pdev->DiskMirror[index]))[0];
+ ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1] = ((ULONG *)(&pdev->DiskMirror[index]))[1];
+ outsw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
+ return FALSE;
+ }
+/*******************************************************************************************************
+ * Name: InitFailover
+ *
+ * Description: This is the beginning of the failover routine
+ *
+ * Parameters: SCpnt - Pointer to SCSI command structure.
+ * padapter - Pointer adapter data structure.
+ * pdev - Pointer to our device.
+ *
+ * Returns: TRUE on error.
+ *
+ ******************************************************************************************************/
+static int InitFailover (PADAPTER2220I padapter, POUR_DEVICE pdev)
+ {
+ UCHAR spigot;
+
+ DEB (printk ("\npci2220i: Initialize failover process - survivor = %d", padapter->survivor));
+ pdev->raid = FALSE; //initializes system for non raid mode
+ pdev->hotRecon = 0;
+ padapter->reconOn = FALSE;
+ spigot = (padapter->survivor) ? 2 : 1;
+
+ if ( pdev->DiskMirror[padapter->survivor].status & UCBF_REBUILD )
+ return (TRUE);
+
+ if ( HardReset (padapter, pdev, spigot) )
+ return TRUE;
+
+ outb_p (0x3C | spigot, padapter->regFail); // sound alarm and set fail light
+ pdev->DiskMirror[padapter->survivor].status = UCBF_MIRRORED | UCBF_SURVIVOR; //clear present status
+
+ if ( WriteSignature (padapter, pdev, spigot, padapter->survivor) )
+ return TRUE;
+ padapter->failinprog = TRUE;
+ return FALSE;
+ }
+/****************************************************************
+ * Name: TimerExpiry :LOCAL
+ *
+ * Description: Timer expiry routine.
+ *
+ * Parameters: data - Pointer adapter data structure.
+ *
+ * Returns: Nothing.
+ *
+ ****************************************************************/
+static void TimerExpiry (unsigned long data)
+ {
+ PADAPTER2220I padapter = (PADAPTER2220I)data;
+ POUR_DEVICE pdev = padapter->pdev;
+ UCHAR status = IDE_STATUS_BUSY;
+ UCHAR temp, temp1;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ int flags;
+#else /* version >= v2.1.95 */
+ unsigned long flags;
+#endif /* version >= v2.1.95 */
+
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /* Disable interrupts, if they aren't already disabled. */
+ save_flags (flags);
+ cli ();
+#else /* version >= v2.1.95 */
+ /*
+ * Disable interrupts, if they aren't already disabled and acquire
+ * the I/O spinlock.
+ */
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
+ DEB (printk ("\nPCI2220I: Timeout expired "));
+
+ if ( padapter->failinprog )
+ {
+ DEB (printk ("in failover process"));
+ OpDone (padapter, DecodeError (padapter, inb_p (padapter->regStatCmd)));
+ goto timerExpiryDone;
+ }
+
+ while ( padapter->reconPhase )
+ {
+ DEB (printk ("in recon phase %X", padapter->reconPhase));
+ switch ( padapter->reconPhase )
+ {
+ case RECON_PHASE_MARKING:
+ case RECON_PHASE_LAST:
+ padapter->survivor = (pdev->spigot ^ 3) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 1"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DID_ERROR << 16);
+ goto timerExpiryDone;
+
+ case RECON_PHASE_READY:
+ OpDone (padapter, DID_ERROR << 16);
+ goto timerExpiryDone;
+
+ case RECON_PHASE_COPY:
+ padapter->survivor = (pdev->spigot) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 2"));
+ DEB (printk ("\n spig/stat = %X", inb_p (padapter->regStatSel));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DID_ERROR << 16);
+ goto timerExpiryDone;
+
+ case RECON_PHASE_UPDATE:
+ padapter->survivor = (pdev->spigot) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 3")));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DID_ERROR << 16);
+ goto timerExpiryDone;
+
+ case RECON_PHASE_END:
+ padapter->survivor = (pdev->spigot) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 4"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DID_ERROR << 16);
+ goto timerExpiryDone;
+
+ default:
+ goto timerExpiryDone;
+ }
+ }
+
+ while ( padapter->cmd )
+ {
+ outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
+ if ( pdev->raid )
+ {
+ if ( padapter->cmd == WRITE_CMD )
+ {
+ DEB (printk ("in RAID write operation"));
+ if ( inb_p (padapter->regStatSel) & 1 )
+ {
+ SelectSpigot (padapter, 0x81 ); // Masking the interrupt during spigot select
+ temp = inb_p (padapter->regStatCmd);
+ }
+ else
+ temp = IDE_STATUS_BUSY;
+
+ if ( inb (padapter->regStatSel) & 2 )
+ {
+ SelectSpigot (padapter, 0x82 ); // Masking the interrupt during spigot select
+ temp1 = inb_p (padapter->regStatCmd);
+ }
+ else
+ temp1 = IDE_STATUS_BUSY;
+
+ if ( (temp & IDE_STATUS_BUSY) || (temp1 & IDE_STATUS_BUSY) )
+ {
+ if ( (temp & IDE_STATUS_BUSY) && (temp1 & IDE_STATUS_BUSY) )
+ {
+ status = temp;
+ break;
+ }
+ else
+ {
+ if (temp & IDE_STATUS_BUSY)
+ padapter->survivor = 1;
+ else
+ padapter->survivor = 0;
+ DEB (printk ("\npci2220i: FAILURE 5"));
+ if ( InitFailover (padapter, pdev) )
+ {
+ status = inb_p (padapter->regStatCmd);
+ break;
+ }
+ goto timerExpiryDone;
+ }
+ }
+ }
+ else
+ {
+ DEB (printk ("in RAID read operation"));
+ padapter->survivor = (pdev->spigot ^ 3) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 6"));
+ if ( InitFailover (padapter, pdev) )
+ {
+ status = inb_p (padapter->regStatCmd);
+ break;
+ }
+ goto timerExpiryDone;
+ }
+ }
+ else
+ {
+ DEB (printk ("in I/O operation"));
+ status = inb_p (padapter->regStatCmd);
+ }
+ break;
+ }
+
+ OpDone (padapter, DecodeError (padapter, status));
+
+timerExpiryDone:;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /*
+ * Restore the original flags which will enable interrupts
+ * if and only if they were enabled on entry.
+ */
+ restore_flags (flags);
+#else /* version >= v2.1.95 */
+ /*
+ * Release the I/O spinlock and restore the original flags
+ * which will enable interrupts if and only if they were
+ * enabled on entry.
+ */
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
+ }
+/****************************************************************
+ * Name: SetReconstruct :LOCAL
+ *
+ * Description: Set the reconstruct up.
+ *
+ * Parameters: pdev - Pointer to device structure.
+ * index - Mirror index number.
+ *
+ * Returns: Number of sectors on new disk required.
+ *
+ ****************************************************************/
+static LONG SetReconstruct (POUR_DEVICE pdev, int index)
+ {
+ pdev->DiskMirror[index].status = UCBF_MIRRORED; // setup the flags
+ pdev->DiskMirror[index ^ 1].status = UCBF_MIRRORED | UCBF_REBUILD;
+ pdev->DiskMirror[index ^ 1].reconstructPoint = 0; // start the reconstruct
+ pdev->reconCount = 1990; // mark target drive early
+ pdev->hotRecon = 1 >> index;
+ return pdev->DiskMirror[index].reconstructPoint;
+ }
+/****************************************************************
+ * Name: ReconTimerExpiry :LOCAL
+ *
+ * Description: Reconstruct timer expiry routine.
+ *
+ * Parameters: data - Pointer adapter data structure.
+ *
+ * Returns: Nothing.
+ *
+ ****************************************************************/
+static void ReconTimerExpiry (unsigned long data)
+ {
+ PADAPTER2220I padapter;
+ POUR_DEVICE pdev;
+ ULONG testsize = 0;
+ PIDENTIFY_DATA pid;
+ USHORT minmode;
+ ULONG zl;
+ UCHAR zc;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ int flags;
+#else /* version >= v2.1.95 */
+ unsigned long flags;
+#endif /* version >= v2.1.95 */
+
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /* Disable interrupts, if they aren't already disabled. */
+ save_flags (flags);
+ cli ();
+#else /* version >= v2.1.95 */
+ /*
+ * Disable interrupts, if they aren't already disabled and acquire
+ * the I/O spinlock.
+ */
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
+
+ padapter = (PADAPTER2220I)data;
+ if ( padapter->SCpnt )
+ goto reconTimerExpiry;
+
+ pdev = padapter->device;
+ pid = (PIDENTIFY_DATA)padapter->kBuffer;
+ padapter->reconTimer.data = 0;
+ padapter->pdev = pdev;
+ if ( padapter->reconIsStarting )
+ {
+ padapter->reconIsStarting = FALSE;
+ padapter->reconOn = FALSE;
+ pdev->hotRecon = FALSE;
+
+ if ( (pdev->DiskMirror[0].signature == SIGNATURE) && (pdev->DiskMirror[1].signature == SIGNATURE) &&
+ (pdev->DiskMirror[0].pairIdentifier == (pdev->DiskMirror[1].pairIdentifier ^ 1)) )
+ {
+ if ( (pdev->DiskMirror[0].status & UCBF_MATCHED) && (pdev->DiskMirror[1].status & UCBF_MATCHED) )
+ {
+ goto reconTimerExpiry;
+ }
+
+ if ( pdev->DiskMirror[0].status & UCBF_SURVIVOR ) // is first drive survivor?
+ testsize = SetReconstruct (pdev, 0);
+ else
+ if ( pdev->DiskMirror[1].status & UCBF_SURVIVOR ) // is second drive survivor?
+ testsize = SetReconstruct (pdev, 1);
+
+ if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
+ {
+ if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
+ {
+ pdev->hotRecon = 1;
+ pdev->mirrorRecon = 0;
+ }
+ else
+ {
+ pdev->hotRecon = 2;
+ pdev->mirrorRecon = 1;
+ }
+ }
+ }
+
+ if ( !pdev->hotRecon )
+ goto reconTimerExpiry;
+
+ zc = ((inb_p (padapter->regStatSel) >> 3) | inb_p (padapter->regStatSel)) & 0x83; // mute the alarm
+ outb_p (zc | pdev->hotRecon | 0x40, padapter->regFail);
+
+ while ( 1 )
+ {
+ if ( HardReset (padapter, pdev, pdev->hotRecon) )
+ {
+ DEB (printk ("\npci2220i: sub 1"));
+ break;
+ }
+
+ pdev->lastsectorlba[pdev->mirrorRecon] = InlineIdentify (padapter, pdev->hotRecon, 0);
+
+ if ( pdev->lastsectorlba[pdev->mirrorRecon] < testsize )
+ {
+ DEB (printk ("\npci2220i: sub 2 %ld %ld", pdev->lastsectorlba[pdev->mirrorRecon], testsize));
+ break;
+ }
+
+ // test LBA and multiper sector transfer compatability
+ if (!pid->SupportLBA || (pid->NumSectorsPerInt < SECTORSXFER) || !pid->Valid_64_70 )
+ {
+ DEB (printk ("\npci2220i: sub 3"));
+ break;
+ }
+
+ // test PIO/bus matering mode compatability
+ if ( (pid->MinPIOCycleWithoutFlow > 240) && !pid->SupportIORDYDisable && !padapter->timingPIO )
+ {
+ DEB (printk ("\npci2220i: sub 4"));
+ break;
+ }
+
+ if ( pid->MinPIOCycleWithoutFlow <= 120 ) // setup timing mode of drive
+ minmode = 5;
+ else
+ {
+ if ( pid->MinPIOCylceWithFlow <= 150 )
+ minmode = 4;
+ else
+ {
+ if ( pid->MinPIOCylceWithFlow <= 180 )
+ minmode = 3;
+ else
+ {
+ if ( pid->MinPIOCylceWithFlow <= 240 )
+ minmode = 2;
+ else
+ {
+ DEB (printk ("\npci2220i: sub 5"));
+ break;
+ }
+ }
+ }
+ }
+
+ if ( padapter->timingMode > minmode ) // set minimum timing mode
+ padapter->timingMode = minmode;
+ if ( padapter->timingMode >= 2 )
+ padapter->timingAddress = ModeArray[padapter->timingMode - 2];
+ else
+ padapter->timingPIO = TRUE;
+
+ padapter->reconOn = TRUE;
+ break;
+ }
+
+ if ( !padapter->reconOn )
+ {
+ pdev->hotRecon = FALSE;
+ padapter->survivor = pdev->mirrorRecon ^ 1;
+ padapter->reconPhase = RECON_PHASE_FAILOVER;
+ DEB (printk ("\npci2220i: FAILURE 7"));
+ InitFailover (padapter, pdev);
+ goto reconTimerExpiry;
+ }
+
+ pdev->raid = TRUE;
+
+ if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
+ goto reconTimerExpiry;
+ padapter->reconPhase = RECON_PHASE_MARKING;
+ goto reconTimerExpiry;
+ }
+
+ //**********************************
+ // reconstruct copy starts here
+ //**********************************
+ if ( pdev->reconCount++ > 2000 )
+ {
+ pdev->reconCount = 0;
+ if ( WriteSignature (padapter, pdev, pdev->hotRecon, pdev->mirrorRecon) )
+ {
+ padapter->survivor = pdev->mirrorRecon ^ 1;
+ padapter->reconPhase = RECON_PHASE_FAILOVER;
+ DEB (printk ("\npci2220i: FAILURE 8"));
+ InitFailover (padapter, pdev);
+ goto reconTimerExpiry;
+ }
+ padapter->reconPhase = RECON_PHASE_UPDATE;
+ goto reconTimerExpiry;
+ }
+
+ zl = pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint;
+ padapter->reconSize = pdev->DiskMirror[pdev->mirrorRecon ^ 1].reconstructPoint - zl;
+ if ( padapter->reconSize > MAX_BUS_MASTER_BLOCKS )
+ padapter->reconSize = MAX_BUS_MASTER_BLOCKS;
+
+ if ( padapter->reconSize )
+ {
+ SelectSpigot (padapter, 3); // select the spigots
+ outb_p (pdev->byte6 | ((UCHAR *)(&zl))[3], padapter->regLba24);// select the drive
+ SelectSpigot (padapter, pdev->spigot);
+ if ( WaitReady (padapter) )
+ goto reconTimerExpiry;
+
+ SelectSpigot (padapter, pdev->hotRecon);
+ if ( WaitReady (padapter) )
+ {
+ padapter->survivor = pdev->mirrorRecon ^ 1;
+ padapter->reconPhase = RECON_PHASE_FAILOVER;
+ DEB (printk ("\npci2220i: FAILURE 9"));
+ InitFailover (padapter, pdev);
+ goto reconTimerExpiry;
+ }
+
+ SelectSpigot (padapter, 3);
+ outb_p (padapter->reconSize & 0xFF, padapter->regSectCount);
+ outb_p (((UCHAR *)(&zl))[0], padapter->regLba0);
+ outb_p (((UCHAR *)(&zl))[1], padapter->regLba8);
+ outb_p (((UCHAR *)(&zl))[2], padapter->regLba16);
+ padapter->expectingIRQ = TRUE;
+ padapter->reconPhase = RECON_PHASE_READY;
+ SelectSpigot (padapter, pdev->hotRecon);
+ WriteCommand (padapter, WRITE_CMD);
+ StartTimer (padapter);
+ SelectSpigot (padapter, pdev->spigot);
+ WriteCommand (padapter, READ_CMD);
+ goto reconTimerExpiry;
+ }
+
+ pdev->DiskMirror[pdev->mirrorRecon].status = UCBF_MIRRORED | UCBF_MATCHED;
+ pdev->DiskMirror[pdev->mirrorRecon ^ 1].status = UCBF_MIRRORED | UCBF_MATCHED;
+ if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
+ goto reconTimerExpiry;
+ padapter->reconPhase = RECON_PHASE_LAST;
+
+reconTimerExpiry:;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /*
+ * Restore the original flags which will enable interrupts
+ * if and only if they were enabled on entry.
+ */
+ restore_flags (flags);
+#else /* version >= v2.1.95 */
+ /*
+ * Release the I/O spinlock and restore the original flags
+ * which will enable interrupts if and only if they were
+ * enabled on entry.
+ */
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
+ }
+/****************************************************************
* Name: Irq_Handler :LOCAL
*
* Description: Interrupt handler.
@@ -283,12 +1163,31 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
{
struct Scsi_Host *shost = NULL; // Pointer to host data block
PADAPTER2220I padapter; // Pointer to adapter control structure
- USHORT *pports; // I/O port array
+ POUR_DEVICE pdev;
Scsi_Cmnd *SCpnt;
UCHAR status;
+ UCHAR status1;
int z;
-
-// DEB(printk ("\npci2220i recieved interrupt\n"));
+ ULONG zl;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ int flags;
+#else /* version >= v2.1.95 */
+ unsigned long flags;
+#endif /* version >= v2.1.95 */
+
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /* Disable interrupts, if they aren't already disabled. */
+ save_flags (flags);
+ cli ();
+#else /* version >= v2.1.95 */
+ /*
+ * Disable interrupts, if they aren't already disabled and acquire
+ * the I/O spinlock.
+ */
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
+
+// DEB (printk ("\npci2220i recieved interrupt\n"));
for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
{
@@ -305,86 +1204,267 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
if ( !shost )
{
DEB (printk ("\npci2220i: not my interrupt"));
- return;
+ goto irq_return;
}
padapter = HOSTDATA(shost);
- pports = padapter->ports;
+ pdev = padapter->pdev;
SCpnt = padapter->SCpnt;
- if ( !padapter->expectingIRQ )
+ if ( !padapter->expectingIRQ || !(SCpnt || padapter->reconPhase) )
{
DEB(printk ("\npci2220i Unsolicited interrupt\n"));
- return;
+ STOP_HERE ();
+ goto irq_return;
}
padapter->expectingIRQ = 0;
+ outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
- status = inb_p (padapter->ports[PORT_STAT_CMD]); // read the device status
- if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
- goto irqerror;
+ if ( padapter->failinprog )
+ {
+ DEB (printk ("\npci2220i interrupt failover complete"));
+ padapter->failinprog = FALSE;
+ status = inb_p (padapter->regStatCmd); // read the device status
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ DEB (printk ("\npci2220i: interrupt failover error from drive %X", status));
+ padapter->cmd = 0;
+ }
+ else
+ {
+ DEB (printk ("\npci2220i: restarting failed opertation."));
+ pdev->spigot = (padapter->survivor) ? 2 : 1;
+ del_timer (&padapter->timer);
+ if ( padapter->reconPhase )
+ OpDone (padapter, DID_OK << 16);
+ else
+ Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
+ goto irq_return;
+ }
+ }
- switch ( padapter->ide.ide.ides.cmd ) // decide how to handle the interrupt
+ if ( padapter->reconPhase )
{
- case IDE_CMD_READ_MULTIPLE:
- if ( padapter->readPhase == 1 ) // is this a bus master channel complete?
- {
- DEB(printk ("\npci2220i processing read interrupt cleanup"));
- outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
- padapter->buffer += padapter->ide.ide.ides.sectors * 512;
- if ( SetupTransfer (padapter, padapter->ide.ide.ide[6] & 0xF0) )
+ switch ( padapter->reconPhase )
+ {
+ case RECON_PHASE_MARKING:
+ case RECON_PHASE_LAST:
+ status = inb_p (padapter->regStatCmd); // read the device status
+ del_timer (&padapter->timer);
+ if ( padapter->reconPhase == RECON_PHASE_LAST )
{
- SCpnt->result = DID_OK << 16;
- padapter->SCpnt = NULL;
- SCpnt->scsi_done (SCpnt);
- return;
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ padapter->survivor = (pdev->spigot ^ 3) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 10"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DecodeError (padapter, status));
+ goto irq_return;
+ }
+ if ( WriteSignature (padapter, pdev, pdev->hotRecon, pdev->mirrorRecon) )
+ {
+ padapter->survivor = (pdev->spigot) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 11"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DecodeError (padapter, status));
+ goto irq_return;
+ }
+ padapter->reconPhase = RECON_PHASE_END;
+ goto irq_return;
}
- padapter->readPhase = 0;
- if ( !(status = IdeCmd (padapter)) )
+ OpDone (padapter, DID_OK << 16);
+ goto irq_return;
+
+ case RECON_PHASE_READY:
+ status = inb_p (padapter->regStatCmd); // read the device status
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
{
- DEB (printk ("\npci2220i interrupt complete, waiting for another"));
- return;
+ del_timer (&padapter->timer);
+ OpDone (padapter, DecodeError (padapter, status));
+ goto irq_return;
}
- }
- if ( status & IDE_STATUS_DRQ )
+ SelectSpigot (padapter, pdev->hotRecon);
+ if ( WaitDrq (padapter) )
+ {
+ del_timer (&padapter->timer);
+ padapter->survivor = (pdev->spigot) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 12"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DecodeError (padapter, status));
+ goto irq_return;
+ }
+ SelectSpigot (padapter, pdev->spigot | 0x40);
+ padapter->reconPhase = RECON_PHASE_COPY;
+ padapter->expectingIRQ = TRUE;
+ if ( padapter->timingPIO )
+ {
+ insw (padapter->regData, padapter->kBuffer, padapter->reconSize * (BYTES_PER_SECTOR / 2));
+ }
+ else
+ {
+ outl (padapter->timingAddress, padapter->regDmaAddrLoc);
+ outl (virt_to_bus (padapter->kBuffer), padapter->regDmaAddrPci);
+ outl (padapter->reconSize * BYTES_PER_SECTOR, padapter->regDmaCount);
+ outb_p (8, padapter->regDmaDesc); // read operation
+ outb_p (1, padapter->regDmaMode); // no interrupt
+ outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
+ }
+ goto irq_return;
+
+ case RECON_PHASE_COPY:
+ pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint += padapter->reconSize;
+
+ case RECON_PHASE_UPDATE:
+ SelectSpigot (padapter, pdev->hotRecon | 0x80);
+ status = inb_p (padapter->regStatCmd); // read the device status
+ del_timer (&padapter->timer);
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ padapter->survivor = (pdev->spigot) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 13"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DecodeError (padapter, status));
+ goto irq_return;
+ }
+ OpDone (padapter, DID_OK << 16);
+ goto irq_return;
+
+ case RECON_PHASE_END:
+ status = inb_p (padapter->regStatCmd); // read the device status
+ del_timer (&padapter->timer);
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ padapter->survivor = (pdev->spigot) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 14"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DecodeError (padapter, status));
+ goto irq_return;
+ }
+ padapter->reconOn = FALSE;
+ pdev->hotRecon = 0;
+ OpDone (padapter, DID_OK << 16);
+ goto irq_return;
+
+ default:
+ goto irq_return;
+ }
+ }
+
+ switch ( padapter->cmd ) // decide how to handle the interrupt
+ {
+ case READ_CMD:
+ if ( padapter->sectorCount )
{
- DEB(printk ("\npci2220i processing read interrupt start bus master cycle"));
- outb_p (8, padapter->regDmaDesc); // read operation
- padapter->readPhase = 1;
- padapter->expectingIRQ = 1;
- outl (padapter->timingAddress, padapter->regDmaAddrLoc);
- outl (virt_to_bus (padapter->buffer), padapter->regDmaAddrPci);
- outl ((ULONG)padapter->ide.ide.ides.sectors * (ULONG)512, padapter->regDmaCount);
- outb_p (5, padapter->regDmaMode); // interrupt enable/disable
- outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
- return;
+ status = inb_p (padapter->regStatCmd); // read the device status
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ if ( pdev->raid )
+ {
+ padapter->survivor = (pdev->spigot ^ 3) >> 1;
+ del_timer (&padapter->timer);
+ DEB (printk ("\npci2220i: FAILURE 15"));
+ if ( !InitFailover (padapter, pdev) )
+ goto irq_return;
+ }
+ break;
+ }
+ if ( padapter->timingPIO )
+ {
+ zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
+ insw (padapter->regData, padapter->buffer, zl * (BYTES_PER_SECTOR / 2));
+ padapter->sectorCount -= zl;
+ padapter->buffer += zl * BYTES_PER_SECTOR;
+ if ( !padapter->sectorCount )
+ {
+ status = 0;
+ break;
+ }
+ }
+ else
+ BusMaster (padapter, 1, 1);
+ padapter->expectingIRQ = TRUE;
+ goto irq_return;
}
+ status = 0;
break;
- case IDE_CMD_WRITE_MULTIPLE:
- DEB(printk ("\npci2220i processing write interrupt cleanup"));
- padapter->buffer += padapter->ide.ide.ides.sectors * 512;
- if ( SetupTransfer (padapter, padapter->ide.ide.ide[6] & 0xF0) )
+ case WRITE_CMD:
+ SelectSpigot (padapter, pdev->spigot | 0x80);
+ status = inb_p (padapter->regStatCmd); // read the device status
+ if ( pdev->raid )
{
- SCpnt->result = DID_OK << 16;
- padapter->SCpnt = NULL;
- SCpnt->scsi_done (SCpnt);
- return;
+ SelectSpigot (padapter, (pdev->spigot ^ 3) | 0x80);
+ status1 = inb_p (padapter->regStatCmd); // read the device status
+ }
+ else
+ status1 = 0;
+
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ if ( pdev->raid && !(status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT)) )
+ {
+ padapter->survivor = (pdev->spigot ^ 3) >> 1;
+ del_timer (&padapter->timer);
+ SelectSpigot (padapter, pdev->spigot | 0x80);
+ DEB (printk ("\npci2220i: FAILURE 16 status = %X error = %X", status, inb_p (padapter->regError)));
+ if ( !InitFailover (padapter, pdev) )
+ goto irq_return;
+ }
+ break;
}
- if ( !(status = IdeCmd (padapter)) )
+ if ( pdev->raid )
{
- DEB (printk ("\npci2220i interrupt complete, waiting for another"));
- return;
+ if ( status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ padapter->survivor = pdev->spigot >> 1;
+ del_timer (&padapter->timer);
+ DEB (printk ("\npci2220i: FAILURE 17 status = %X error = %X", status1, inb_p (padapter->regError)));
+ if ( !InitFailover (padapter, pdev) )
+ goto irq_return;
+ status = status1;
+ break;
+ }
+ if ( padapter->sectorCount )
+ {
+ status = WriteDataBoth (padapter);
+ if ( status )
+ {
+ padapter->survivor = (status ^ 3) >> 1;
+ del_timer (&padapter->timer);
+ DEB (printk ("\npci2220i: FAILURE 18"));
+ if ( !InitFailover (padapter, pdev) )
+ goto irq_return;
+ SelectSpigot (padapter, status | 0x80);
+ status = inb_p (padapter->regStatCmd); // read the device status
+ break;
+ }
+ padapter->expectingIRQ = TRUE;
+ goto irq_return;
+ }
+ status = 0;
+ break;
}
+ if ( padapter->sectorCount )
+ {
+ SelectSpigot (padapter, pdev->spigot);
+ status = WriteData (padapter);
+ if ( status )
+ break;
+ padapter->expectingIRQ = TRUE;
+ goto irq_return;
+ }
+ status = 0;
break;
case IDE_COMMAND_IDENTIFY:
{
PINQUIRYDATA pinquiryData = SCpnt->request_buffer;
+ PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
- DEB(printk ("\npci2220i processing verify interrupt cleanup"));
+ status = inb_p (padapter->regStatCmd);
if ( status & IDE_STATUS_DRQ )
{
- insw (pports[PORT_DATA], &identifyData, sizeof (identifyData) >> 1);
+ insw (padapter->regData, pid, sizeof (IDENTIFY_DATA) >> 1);
memset (pinquiryData, 0, SCpnt->request_bufflen); // Zero INQUIRY data structure.
pinquiryData->DeviceType = 0;
@@ -394,8 +1474,8 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
// Fill in vendor identification fields.
for ( z = 0; z < 20; z += 2 )
{
- pinquiryData->VendorId[z] = ((UCHAR *)identifyData.ModelNumber)[z + 1];
- pinquiryData->VendorId[z + 1] = ((UCHAR *)identifyData.ModelNumber)[z];
+ pinquiryData->VendorId[z] = ((UCHAR *)pid->ModelNumber)[z + 1];
+ pinquiryData->VendorId[z + 1] = ((UCHAR *)pid->ModelNumber)[z];
}
// Initialize unused portion of product id.
@@ -406,38 +1486,47 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
// product revision in INQUIRY data.
for ( z = 0; z < 4; z += 2 )
{
- pinquiryData->ProductRevisionLevel[z] = ((UCHAR *)identifyData.FirmwareRevision)[z + 1];
- pinquiryData->ProductRevisionLevel[z + 1] = ((UCHAR *)identifyData.FirmwareRevision)[z];
+ pinquiryData->ProductRevisionLevel[z] = ((UCHAR *)pid->FirmwareRevision)[z + 1];
+ pinquiryData->ProductRevisionLevel[z + 1] = ((UCHAR *)pid->FirmwareRevision)[z];
}
-
- SCpnt->result = DID_OK << 16;
- padapter->SCpnt = NULL;
- SCpnt->scsi_done (SCpnt);
- return;
+ if ( pdev == padapter->device )
+ *((USHORT *)(&pinquiryData->VendorSpecific)) = DEVICE_DALE_1;
+
+ status = 0;
}
break;
}
default:
- DEB(printk ("\npci2220i no real process here!"));
- SCpnt->result = DID_OK << 16;
- padapter->SCpnt = NULL;
- SCpnt->scsi_done (SCpnt);
- return;
+ status = 0;
+ break;
}
-irqerror:;
- DEB(printk ("\npci2220i error Device Status: %X\n", status));
- SCpnt->result = DecodeError (shost, status);
- SCpnt->scsi_done (SCpnt);
- }
-static void do_Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
- {
- unsigned long flags;
-
- spin_lock_irqsave(&io_request_lock, flags);
- Irq_Handler(irq, dev_id, regs);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ del_timer (&padapter->timer);
+ if ( status )
+ {
+ DEB (printk ("\npci2220i Interupt hanlder return error"));
+ zl = DecodeError (padapter, status);
+ }
+ else
+ zl = DID_OK << 16;
+
+ OpDone (padapter, zl);
+irq_return:;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /*
+ * Restore the original flags which will enable interrupts
+ * if and only if they were enabled on entry.
+ */
+ restore_flags (flags);
+#else /* version >= v2.1.95 */
+ /*
+ * Release the I/O spinlock and restore the original flags
+ * which will enable interrupts if and only if they were
+ * enabled on entry.
+ */
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
}
/****************************************************************
* Name: Pci2220i_QueueCommand
@@ -456,121 +1545,182 @@ int Pci2220i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
PADAPTER2220I padapter = HOSTDATA(SCpnt->host); // Pointer to adapter control structure
POUR_DEVICE pdev = &padapter->device[SCpnt->target];// Pointer to device information
UCHAR rc; // command return code
+ int z;
+ PDEVICE_RAID1 pdr;
SCpnt->scsi_done = done;
- padapter->ide.ide.ides.spigot = pdev->spigot;
padapter->buffer = SCpnt->request_buffer;
- if (done)
+ padapter->SCpnt = SCpnt; // Save this command data
+ if ( !done )
{
- if ( !pdev->device )
- {
- SCpnt->result = DID_BAD_TARGET << 16;
- done (SCpnt);
- return 0;
- }
+ printk("pci2220i_queuecommand: %02X: done can't be NULL\n", *cdb);
+ return 0;
}
- else
+
+ if ( padapter->reconPhase )
+ return 0;
+ if ( padapter->reconTimer.data )
{
- printk("pci2220i_queuecommand: %02X: done can't be NULL\n", *cdb);
+ del_timer (&padapter->reconTimer);
+ padapter->reconTimer.data = 0;
+ }
+
+ if ( !pdev->device || SCpnt->lun )
+ {
+ OpDone (padapter, DID_BAD_TARGET << 16);
return 0;
}
- DEB (if(*cdb) printk ("\nCDB: %X- %X %X %X %X %X %X %X %X %X %X ", SCpnt->cmd_len, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]));
+
switch ( *cdb )
{
case SCSIOP_INQUIRY: // inquiry CDB
{
- padapter->ide.ide.ide[6] = pdev->byte6;
- padapter->ide.ide.ides.cmd = IDE_COMMAND_IDENTIFY;
+ if ( cdb[2] == SC_MY_RAID )
+ {
+ switch ( cdb[3] )
+ {
+ case MY_SCSI_REBUILD:
+ padapter->reconOn = padapter->reconIsStarting = TRUE;
+ OpDone (padapter, DID_OK << 16);
+ break;
+ case MY_SCSI_ALARMMUTE:
+ MuteAlarm (padapter);
+ OpDone (padapter, DID_OK << 16);
+ break;
+ case MY_SCSI_DEMOFAIL:
+ padapter->demoFail = TRUE;
+ OpDone (padapter, DID_OK << 16);
+ break;
+ default:
+ z = cdb[5]; // get index
+ pdr = (PDEVICE_RAID1)SCpnt->request_buffer;
+ if ( padapter->raidData[z] )
+ {
+ memcpy (&pdr->DiskRaid1, padapter->raidData[z], sizeof (DISK_MIRROR));
+ pdr->TotalSectors = padapter->device[0].blocks;
+ }
+ else
+ memset (pdr, 0, sizeof (DEVICE_RAID1));
+ OpDone (padapter, DID_OK << 16);
+ break;
+ }
+ return 0;
+ }
+ padapter->cmd = IDE_COMMAND_IDENTIFY;
break;
}
case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
- SCpnt->result = DID_OK << 16;
- done (SCpnt);
+ OpDone (padapter, DID_OK << 16);
return 0;
-
case SCSIOP_READ_CAPACITY: // read capctiy CDB
{
PREAD_CAPACITY_DATA pdata = (PREAD_CAPACITY_DATA)SCpnt->request_buffer;
pdata->blksiz = 0x20000;
XANY2SCSI ((UCHAR *)&pdata->blks, pdev->blocks);
- SCpnt->result = DID_OK << 16;
- done (SCpnt);
+ OpDone (padapter, DID_OK << 16);
return 0;
}
-
case SCSIOP_VERIFY: // verify CDB
- *(ULONG *)padapter->ide.ide.ides.lba = XSCSI2LONG (&cdb[2]);
- padapter->ide.ide.ide[6] |= pdev->byte6;
- padapter->ide.ide.ide[2] = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8));
- padapter->ide.ide.ides.cmd = IDE_COMMAND_VERIFY;
+ padapter->startSector = XSCSI2LONG (&cdb[2]);
+ padapter->sectorCount = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8));
+ padapter->cmd = IDE_COMMAND_VERIFY;
break;
-
case SCSIOP_READ: // read10 CDB
padapter->startSector = XSCSI2LONG (&cdb[2]);
padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
- SetupTransfer (padapter, pdev->byte6);
- padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE;
- padapter->readPhase = 0;
+ padapter->cmd = READ_CMD;
break;
-
case SCSIOP_READ6: // read6 CDB
padapter->startSector = SCSI2LONG (&cdb[1]);
padapter->sectorCount = cdb[4];
- SetupTransfer (padapter, pdev->byte6);
- padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE;
- padapter->readPhase = 0;
+ padapter->cmd = READ_CMD;
break;
-
case SCSIOP_WRITE: // write10 CDB
padapter->startSector = XSCSI2LONG (&cdb[2]);
padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
- SetupTransfer (padapter, pdev->byte6);
- padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE;
+ padapter->cmd = WRITE_CMD;
break;
case SCSIOP_WRITE6: // write6 CDB
padapter->startSector = SCSI2LONG (&cdb[1]);
padapter->sectorCount = cdb[4];
- SetupTransfer (padapter, pdev->byte6);
- padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE;
+ padapter->cmd = WRITE_CMD;
break;
-
default:
DEB (printk ("pci2220i_queuecommand: Unsupported command %02X\n", *cdb));
- SCpnt->result = DID_ERROR << 16;
- done (SCpnt);
+ OpDone (padapter, DID_ERROR << 16);
return 0;
}
- padapter->SCpnt = SCpnt; // Save this command data
+ if ( padapter->reconPhase )
+ return 0;
+
+ padapter->pdev = pdev;
- rc = IdeCmd (padapter);
- if ( rc )
+ while ( padapter->demoFail )
{
- padapter->expectingIRQ = 0;
- DEB (printk ("pci2220i_queuecommand: %02X, %02X: Device failed to respond for command\n", *cdb, padapter->ide.ide.ides.cmd));
- SCpnt->result = DID_ERROR << 16;
- done (SCpnt);
+ padapter->demoFail = FALSE;
+ if ( !pdev->raid ||
+ (pdev->DiskMirror[0].status & UCBF_SURVIVOR) ||
+ (pdev->DiskMirror[1].status & UCBF_SURVIVOR) )
+ {
+ break;
+ }
+ if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
+ padapter->survivor = 1;
+ else
+ padapter->survivor = 0;
+ DEB (printk ("\npci2220i: FAILURE 19"));
+ if ( InitFailover (padapter, pdev ) )
+ break;
return 0;
}
- if ( padapter->ide.ide.ides.cmd == IDE_CMD_WRITE_MULTIPLE )
+
+ StartTimer (padapter);
+ if ( pdev->raid && (padapter->cmd == WRITE_CMD) )
+ {
+ rc = IdeCmdBoth (padapter);
+ if ( !rc )
+ rc = WriteDataBoth (padapter);
+ if ( rc )
+ {
+ del_timer (&padapter->timer);
+ padapter->expectingIRQ = 0;
+ padapter->survivor = (rc ^ 3) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 20"));
+ if ( InitFailover (padapter, pdev) )
+ {
+ OpDone (padapter, DID_ERROR << 16);
+ return 0;
+ }
+ }
+ }
+ else
{
- if ( WriteData (padapter) )
+ rc = IdeCmd (padapter, pdev);
+ if ( (padapter->cmd == WRITE_CMD) && !rc )
+ rc = WriteData (padapter);
+ if ( rc )
{
+ del_timer (&padapter->timer);
padapter->expectingIRQ = 0;
- DEB (printk ("pci2220i_queuecommand: %02X, %02X: Device failed to accept data\n", *cdb, padapter->ide.ide.ides.cmd));
- SCpnt->result = DID_ERROR << 16;
- done (SCpnt);
+ if ( pdev->raid )
+ {
+ padapter->survivor = (pdev->spigot ^ 3) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 21"));
+ if ( !InitFailover (padapter, pdev) )
+ return 0;
+ }
+ OpDone (padapter, DID_ERROR << 16);
return 0;
}
}
- DEB (printk(" now waiting for initial interrupt "));
return 0;
}
-static void internal_done(Scsi_Cmnd * SCpnt)
+static void internal_done(Scsi_Cmnd *SCpnt)
{
SCpnt->SCp.Status++;
}
@@ -586,10 +1736,7 @@ static void internal_done(Scsi_Cmnd * SCpnt)
****************************************************************/
int Pci2220i_Command (Scsi_Cmnd *SCpnt)
{
- DEB(printk("pci2220i_command: ..calling pci2220i_queuecommand\n"));
-
Pci2220i_QueueCommand (SCpnt, internal_done);
-
SCpnt->SCp.Status = 0;
while (!SCpnt->SCp.Status)
barrier ();
@@ -600,7 +1747,7 @@ int Pci2220i_Command (Scsi_Cmnd *SCpnt)
*
* Description: Read information from controller Flash memory.
*
- * Parameters: hostdata - Pointer to host interface data structure.
+ * Parameters: padapter - Pointer to host interface data structure.
* pdata - Pointer to data structures.
* base - base address in Flash.
* length - lenght of data space in bytes.
@@ -608,25 +1755,24 @@ int Pci2220i_Command (Scsi_Cmnd *SCpnt)
* Returns: Nothing.
*
****************************************************************/
-VOID ReadFlash (PADAPTER2220I hostdata, VOID *pdata, ULONG base, ULONG length)
+VOID ReadFlash (PADAPTER2220I padapter, VOID *pdata, ULONG base, ULONG length)
{
ULONG oldremap;
UCHAR olddesc;
ULONG z;
UCHAR *pd = (UCHAR *)pdata;
- oldremap = inl (hostdata->regRemap); // save values to restore later
- olddesc = inb_p (hostdata->regDesc);
+ oldremap = inl (padapter->regRemap); // save values to restore later
+ olddesc = inb_p (padapter->regDesc);
- outl (base | 1, hostdata->regRemap); // remap to Flash space as specified
- outb_p (0x40, hostdata->regDesc); // describe remap region as 8 bit
+ outl (base | 1, padapter->regRemap); // remap to Flash space as specified
+ outb_p (0x40, padapter->regDesc); // describe remap region as 8 bit
for ( z = 0; z < length; z++) // get "length" data count
- *pd++ = inb_p (hostdata->regBase + z); // read in the data
+ *pd++ = inb_p (padapter->regBase + z); // read in the data
- outl (oldremap, hostdata->regRemap); // restore remap register values
- outb_p (olddesc, hostdata->regDesc);
+ outl (oldremap, padapter->regRemap); // restore remap register values
+ outb_p (olddesc, padapter->regDesc);
}
-
/****************************************************************
* Name: Pci2220i_Detect
*
@@ -634,115 +1780,239 @@ VOID ReadFlash (PADAPTER2220I hostdata, VOID *pdata, ULONG base, ULONG length)
*
* Parameters: tpnt - Pointer to SCSI host template structure.
*
- * Returns: Number of adapters found.
+ * Returns: Number of adapters installed.
*
****************************************************************/
int Pci2220i_Detect (Scsi_Host_Template *tpnt)
{
- struct pci_dev *pdev = NULL;
+ int found = 0;
+ int installed = 0;
struct Scsi_Host *pshost;
- PADAPTER2220I hostdata;
- ULONG modearray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE4P};
+ PADAPTER2220I padapter;
int unit;
int z;
+ USHORT zs;
+ USHORT raidon = FALSE;
int setirq;
+ UCHAR spigot1 = FALSE;
+ UCHAR spigot2 = FALSE;
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ struct pci_dev *pdev = NULL;
+#else
+ UCHAR pci_bus, pci_device_fn;
+#endif
- if ( pci_present () )
- while ((pdev = pci_find_device(VENDOR_PSI, DEVICE_DALE_1, pdev)))
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ if ( !pci_present () )
+#else
+ if ( !pcibios_present () )
+#endif
+ {
+ printk ("pci2220i: PCI BIOS not present\n");
+ return 0;
+ }
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pdev)) != NULL )
+#else
+ while ( !pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, found, &pci_bus, &pci_device_fn) )
+#endif
+ {
+ pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
+ padapter = HOSTDATA(pshost);
+ memset (padapter, 0, sizeof (ADAPTER2220I));
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ zs = pdev->base_address[1] & 0xFFFE;
+#else
+ pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &zs);
+ zs &= 0xFFFE;
+#endif
+ padapter->basePort = zs;
+ padapter->regRemap = zs + RTR_LOCAL_REMAP; // 32 bit local space remap
+ padapter->regDesc = zs + RTR_REGIONS; // 32 bit local region descriptor
+ padapter->regRange = zs + RTR_LOCAL_RANGE; // 32 bit local range
+ padapter->regIrqControl = zs + RTR_INT_CONTROL_STATUS; // 16 bit interupt control and status
+ padapter->regScratchPad = zs + RTR_MAILBOX; // 16 byte scratchpad I/O base address
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ zs = pdev->base_address[2] & 0xFFFE;
+#else
+ pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &zs);
+ zs &= 0xFFFE;
+#endif
+ padapter->regBase = zs;
+ padapter->regData = zs + REG_DATA; // data register I/O address
+ padapter->regError = zs + REG_ERROR; // error register I/O address
+ padapter->regSectCount = zs + REG_SECTOR_COUNT; // sector count register I/O address
+ padapter->regLba0 = zs + REG_LBA_0; // least significant byte of LBA
+ padapter->regLba8 = zs + REG_LBA_8; // next least significant byte of LBA
+ padapter->regLba16 = zs + REG_LBA_16; // next most significan byte of LBA
+ padapter->regLba24 = zs + REG_LBA_24; // head and most 4 significant bits of LBA
+ padapter->regStatCmd = zs + REG_STAT_CMD; // status on read and command on write register
+ padapter->regStatSel = zs + REG_STAT_SEL; // board status on read and spigot select on write register
+ padapter->regFail = zs + REG_FAIL;
+ padapter->regAltStat = zs + REG_ALT_STAT;
+
+ padapter->regDmaDesc = zs + RTL_DMA1_DESC_PTR; // address of the DMA discriptor register for direction of transfer
+ padapter->regDmaCmdStat = zs + RTL_DMA_COMMAND_STATUS + 1; // Byte #1 of DMA command status register
+ padapter->regDmaAddrPci = zs + RTL_DMA1_PCI_ADDR; // 32 bit register for PCI address of DMA
+ padapter->regDmaAddrLoc = zs + RTL_DMA1_LOCAL_ADDR; // 32 bit register for local bus address of DMA
+ padapter->regDmaCount = zs + RTL_DMA1_COUNT; // 32 bit register for DMA transfer count
+ padapter->regDmaMode = zs + RTL_DMA1_MODE + 1; // 32 bit register for DMA mode control
+
+ if ( !inb_p (padapter->regScratchPad + DALE_NUM_DRIVES) ) // if no devices on this board
+ goto unregister;
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ pshost->irq = pdev->irq;
+#else
+ pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
+#endif
+ setirq = 1;
+ for ( z = 0; z < installed; z++ ) // scan for shared interrupts
{
- pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
- hostdata = HOSTDATA(pshost);
-
- hostdata->basePort = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
- DEB (printk ("\nBase Regs = %#04X", hostdata->basePort));
- hostdata->regRemap = hostdata->basePort + RTR_LOCAL_REMAP; // 32 bit local space remap
- DEB (printk (" %#04X", hostdata->regRemap));
- hostdata->regDesc = hostdata->basePort + RTR_REGIONS; // 32 bit local region descriptor
- DEB (printk (" %#04X", hostdata->regDesc));
- hostdata->regRange = hostdata->basePort + RTR_LOCAL_RANGE; // 32 bit local range
- DEB (printk (" %#04X", hostdata->regRange));
- hostdata->regIrqControl = hostdata->basePort + RTR_INT_CONTROL_STATUS; // 16 bit interupt control and status
- DEB (printk (" %#04X", hostdata->regIrqControl));
- hostdata->regScratchPad = hostdata->basePort + RTR_MAILBOX; // 16 byte scratchpad I/O base address
- DEB (printk (" %#04X", hostdata->regScratchPad));
-
- hostdata->regBase = pdev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK;
- for ( z = 0; z < 9; z++ ) // build regester address array
- hostdata->ports[z] = hostdata->regBase + 0x80 + (z * 4);
- hostdata->ports[PORT_FAIL] = hostdata->regBase + REG_FAIL;
- hostdata->ports[PORT_ALT_STAT] = hostdata->regBase + REG_ALT_STAT;
- DEB (printk ("\nPorts ="));
- DEB (for (z=0;z<11;z++) printk(" %#04X", hostdata->ports[z]););
-
- hostdata->regDmaDesc = hostdata->regBase + RTL_DMA1_DESC_PTR; // address of the DMA discriptor register for direction of transfer
- DEB (printk ("\nDMA Regs = %#04X", hostdata->regDmaDesc));
- hostdata->regDmaCmdStat = hostdata->regBase + RTL_DMA_COMMAND_STATUS + 1; // Byte #1 of DMA command status register
- DEB (printk (" %#04X", hostdata->regDmaCmdStat));
- hostdata->regDmaAddrPci = hostdata->regBase + RTL_DMA1_PCI_ADDR; // 32 bit register for PCI address of DMA
- DEB (printk (" %#04X", hostdata->regDmaAddrPci));
- hostdata->regDmaAddrLoc = hostdata->regBase + RTL_DMA1_LOCAL_ADDR; // 32 bit register for local bus address of DMA
- DEB (printk (" %#04X", hostdata->regDmaAddrLoc));
- hostdata->regDmaCount = hostdata->regBase + RTL_DMA1_COUNT; // 32 bit register for DMA transfer count
- DEB (printk (" %#04X", hostdata->regDmaCount));
- hostdata->regDmaMode = hostdata->regBase + RTL_DMA1_MODE + 1; // 32 bit register for DMA mode control
- DEB (printk (" %#04X", hostdata->regDmaMode));
-
- if ( !inb_p (hostdata->regScratchPad + DALE_NUM_DRIVES) ) // if no devices on this board
- goto unregister;
-
- pshost->irq = pdev->irq;
- setirq = 1;
- for ( z = 0; z < NumAdapters; z++ ) // scan for shared interrupts
- {
- if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
- setirq = 0;
- }
- if ( setirq ) // if not shared, posses
+ if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
+ setirq = 0;
+ }
+ if ( setirq ) // if not shared, posses
+ {
+ if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2220i", padapter) < 0 )
{
- if ( request_irq (pshost->irq, do_Irq_Handler, 0, "pci2220i", NULL) )
+ if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2220i", padapter) < 0 )
{
- printk ("Unable to allocate IRQ for PSI-2220I controller.\n");
+ printk ("Unable to allocate IRQ for PCI-2220I controller.\n");
goto unregister;
}
}
- PsiHost[NumAdapters] = pshost; // save SCSI_HOST pointer
-
- pshost->unique_id = hostdata->regBase;
- pshost->max_id = 4;
-
- outb_p (0x01, hostdata->regRange); // fix our range register because other drivers want to tromp on it
-
- hostdata->timingMode = inb_p (hostdata->regScratchPad + DALE_TIMING_MODE);
- hostdata->timingAddress = modearray[hostdata->timingMode - 2];
- ReadFlash (hostdata, &DaleSetup, DALE_FLASH_SETUP, sizeof (SETUP));
-
- for ( z = 0; z < inb_p (hostdata->regScratchPad + DALE_NUM_DRIVES); ++z )
+ padapter->irqOwned = pshost->irq; // set IRQ as owned
+ }
+ padapter->kBuffer = kmalloc (SECTORSXFER * BYTES_PER_SECTOR, GFP_DMA | GFP_ATOMIC);
+ if ( !padapter->kBuffer )
+ {
+ printk ("Unable to allocate DMA buffer for PCI-2220I controller.\n");
+#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
+ free_irq (pshost->irq);
+#else /* version >= v1.3.70 */
+ free_irq (pshost->irq, padapter);
+#endif /* version >= v1.3.70 */
+ goto unregister;
+ }
+ PsiHost[installed] = pshost; // save SCSI_HOST pointer
+
+ pshost->io_port = padapter->basePort;
+ pshost->n_io_port = 0xFF;
+ pshost->unique_id = padapter->regBase;
+ pshost->max_id = 4;
+
+ outb_p (0x01, padapter->regRange); // fix our range register because other drivers want to tromp on it
+
+ padapter->timingMode = inb_p (padapter->regScratchPad + DALE_TIMING_MODE);
+ if ( padapter->timingMode >= 2 )
+ padapter->timingAddress = ModeArray[padapter->timingMode - 2];
+ else
+ padapter->timingPIO = TRUE;
+
+ ReadFlash (padapter, &DaleSetup, DALE_FLASH_SETUP, sizeof (SETUP));
+ for ( z = 0; z < inb_p (padapter->regScratchPad + DALE_NUM_DRIVES); ++z )
+ {
+ unit = inb_p (padapter->regScratchPad + DALE_CHANNEL_DEVICE_0 + z) & 0x0F;
+ padapter->device[z].device = inb_p (padapter->regScratchPad + DALE_SCRATH_DEVICE_0 + unit);
+ padapter->device[z].byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
+ padapter->device[z].spigot = (UCHAR)(1 << (unit >> 1));
+ padapter->device[z].sectors = DaleSetup.setupDevice[unit].sectors;
+ padapter->device[z].heads = DaleSetup.setupDevice[unit].heads;
+ padapter->device[z].cylinders = DaleSetup.setupDevice[unit].cylinders;
+ padapter->device[z].blocks = DaleSetup.setupDevice[unit].blocks;
+
+ if ( !z )
{
- unit = inb_p (hostdata->regScratchPad + DALE_CHANNEL_DEVICE_0 + z) & 0x0F;
- hostdata->device[unit].device = inb_p (hostdata->regScratchPad + DALE_SCRATH_DEVICE_0 + unit);
- hostdata->device[unit].byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
- hostdata->device[unit].spigot = (UCHAR)(1 << (unit >> 1));
- hostdata->device[unit].sectors = DaleSetup.setupDevice[unit].sectors;
- hostdata->device[unit].heads = DaleSetup.setupDevice[unit].heads;
- hostdata->device[unit].cylinders = DaleSetup.setupDevice[unit].cylinders;
- hostdata->device[unit].blocks = DaleSetup.setupDevice[unit].blocks;
- DEB (printk ("\nHOSTDATA->device = %X", hostdata->device[unit].device));
- DEB (printk ("\n byte6 = %X", hostdata->device[unit].byte6));
- DEB (printk ("\n spigot = %X", hostdata->device[unit].spigot));
- DEB (printk ("\n sectors = %X", hostdata->device[unit].sectors));
- DEB (printk ("\n heads = %X", hostdata->device[unit].heads));
- DEB (printk ("\n cylinders = %X", hostdata->device[unit].cylinders));
- DEB (printk ("\n blocks = %lX", hostdata->device[unit].blocks));
+ ReadFlash (padapter, &DiskMirror, DALE_FLASH_RAID, sizeof (DiskMirror));
+ DiskMirror[0].status = inb_p (padapter->regScratchPad + DALE_RAID_0_STATUS);
+ DiskMirror[1].status = inb_p (padapter->regScratchPad + DALE_RAID_1_STATUS);
+ if ( (DiskMirror[0].signature == SIGNATURE) && (DiskMirror[1].signature == SIGNATURE) &&
+ (DiskMirror[0].pairIdentifier == (DiskMirror[1].pairIdentifier ^ 1)) )
+ {
+ raidon = TRUE;
+ }
+
+ memcpy (padapter->device[z].DiskMirror, DiskMirror, sizeof (DiskMirror));
+ padapter->raidData[0] = &padapter->device[z].DiskMirror[0];
+ padapter->raidData[2] = &padapter->device[z].DiskMirror[1];
+
+ if ( raidon )
+ {
+ padapter->device[z].lastsectorlba[0] = InlineIdentify (padapter, 1, 0);
+ padapter->device[z].lastsectorlba[1] = InlineIdentify (padapter, 2, 0);
+
+ if ( !(DiskMirror[1].status & UCBF_SURVIVOR) && padapter->device[z].lastsectorlba[0] )
+ spigot1 = TRUE;
+ if ( !(DiskMirror[0].status & UCBF_SURVIVOR) && padapter->device[z].lastsectorlba[1] )
+ spigot2 = TRUE;
+ if ( DiskMirror[0].status & UCBF_SURVIVOR & DiskMirror[1].status & UCBF_SURVIVOR )
+ spigot1 = TRUE;
+
+ if ( spigot1 && (DiskMirror[0].status & UCBF_REBUILD) )
+ InlineReadSignature (padapter, &padapter->device[z], 0);
+ if ( spigot2 && (DiskMirror[1].status & UCBF_REBUILD) )
+ InlineReadSignature (padapter, &padapter->device[z], 1);
+
+ if ( spigot1 && spigot2 )
+ {
+ padapter->device[z].raid = 1;
+ if ( DiskMirror[0].status & UCBF_REBUILD )
+ padapter->device[z].spigot = 2;
+ else
+ padapter->device[z].spigot = 1;
+ if ( (DiskMirror[0].status & UCBF_REBUILD) || (DiskMirror[1].status & UCBF_REBUILD) )
+ {
+ padapter->reconOn = padapter->reconIsStarting = TRUE;
+ }
+ }
+ else
+ {
+ if ( spigot1 )
+ {
+ if ( DiskMirror[0].status & UCBF_REBUILD )
+ goto unregister;
+ DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
+ padapter->device[z].spigot = 1;
+ }
+ else
+ {
+ if ( DiskMirror[1].status & UCBF_REBUILD )
+ goto unregister;
+ DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
+ padapter->device[z].spigot = 2;
+ }
+ if ( DaleSetup.rebootRebuil )
+ padapter->reconOn = padapter->reconIsStarting = TRUE;
+ }
+
+ break;
+ }
}
-
- printk("\nPSI-2220I EIDE CONTROLLER: at I/O = %X/%X IRQ = %d\n", hostdata->basePort, hostdata->regBase, pshost->irq);
- printk("(C) 1997 Perceptive Solutions, Inc. All rights reserved\n\n");
- continue;
-unregister:
- scsi_unregister (pshost);
- NumAdapters++;
}
- return NumAdapters;
+
+ init_timer (&padapter->timer);
+ padapter->timer.function = TimerExpiry;
+ padapter->timer.data = (unsigned long)padapter;
+ init_timer (&padapter->reconTimer);
+ padapter->reconTimer.function = ReconTimerExpiry;
+ padapter->reconTimer.data = (unsigned long)padapter;
+ printk("\nPCI-2220I EIDE CONTROLLER: at I/O = %X/%X IRQ = %d\n", padapter->basePort, padapter->regBase, pshost->irq);
+ printk("Version %s, Compiled %s %s\n\n", PCI2220I_VERSION, __DATE__, __TIME__);
+ found++;
+ if ( ++installed < MAXADAPTER )
+ continue;
+ break;;
+unregister:;
+ scsi_unregister (pshost);
+ found++;
+ }
+
+ NumAdapters = installed;
+ return installed;
}
/****************************************************************
* Name: Pci2220i_Abort
@@ -756,7 +2026,6 @@ unregister:
****************************************************************/
int Pci2220i_Abort (Scsi_Cmnd *SCpnt)
{
- DEB (printk ("pci2220i_abort\n"));
return SCSI_ABORT_SNOOZE;
}
/****************************************************************
@@ -778,6 +2047,47 @@ int Pci2220i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
{
return SCSI_RESET_PUNT;
}
+/****************************************************************
+ * Name: Pci2220i_Release
+ *
+ * Description: Release resources allocated for a single each adapter.
+ *
+ * Parameters: pshost - Pointer to SCSI command structure.
+ *
+ * Returns: zero.
+ *
+ ****************************************************************/
+int Pci2220i_Release (struct Scsi_Host *pshost)
+ {
+ PADAPTER2220I padapter = HOSTDATA (pshost);
+
+ if ( padapter->reconOn )
+ {
+ padapter->reconOn = FALSE; // shut down the hot reconstruct
+ if ( padapter->reconPhase )
+ udelay (300000);
+ if ( padapter->reconTimer.data ) // is the timer running?
+ {
+ del_timer (&padapter->reconTimer);
+ padapter->reconTimer.data = 0;
+ }
+ }
+
+ // save RAID status on the board
+ outb_p (DiskMirror[0].status, padapter->regScratchPad + DALE_RAID_0_STATUS);
+ outb_p (DiskMirror[1].status, padapter->regScratchPad + DALE_RAID_1_STATUS);
+
+ if ( padapter->irqOwned )
+#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
+ free_irq (pshost->irq);
+#else /* version >= v1.3.70 */
+ free_irq (pshost->irq, padapter);
+#endif /* version >= v1.3.70 */
+ release_region (pshost->io_port, pshost->n_io_port);
+ kfree (padapter->kBuffer);
+ scsi_unregister(pshost);
+ return 0;
+ }
#include "sd.h"
diff --git a/drivers/scsi/pci2220i.h b/drivers/scsi/pci2220i.h
index 1a9bd6cad..25735bdb5 100644
--- a/drivers/scsi/pci2220i.h
+++ b/drivers/scsi/pci2220i.h
@@ -1,39 +1,34 @@
-/*+M*************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver proc support for Linux.
+/****************************************************************************
+ * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
*
- * Copyright (c) 1997 Perceptive Solutions, Inc.
+ * pci2220i.h - Linux Host Driver for PCI-2220i EIDE Adapters
*
- * This program is free software; you can redistribute 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.
+ * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
+ * All Rights Reserved.
*
- * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
*
- * 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.
+ * Technical updates and product information at:
+ * http://www.psidisk.com
*
+ * Please send questions, comments, bug reports to:
+ * tech@psidisk.com Technical Support
*
- * File Name: pci2220i.h
- *
- * Description: Header file for the SCSI driver for the PCI2220I
- * EIDE interface card.
- *
- *-M*************************************************************************/
-
+ ****************************************************************************/
#ifndef _PCI2220I_H
#define _PCI2220I_H
-#include <linux/types.h>
-#include <linux/kdev_t.h>
-
#ifndef PSI_EIDE_SCSIOP
#define PSI_EIDE_SCSIOP 1
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+#define LINUXVERSION(v,p,s) (((v)<<16) + ((p)<<8) + (s))
+
/************************************************/
/* Some defines that we like */
/************************************************/
@@ -46,11 +41,14 @@
#define ULONG unsigned long
#define VOID void
+#include "psi_dale.h"
+
/************************************************/
/* Timeout konstants */
/************************************************/
-#define TIMEOUT_READY 10 // 100 mSec
-#define TIMEOUT_DRQ 40 // 400 mSec
+#define TIMEOUT_READY 100 // 100 mSec
+#define TIMEOUT_DRQ 300 // 300 mSec
+#define TIMEOUT_DATA (3 * HZ) // 3 seconds
/************************************************/
/* Misc. macros */
@@ -76,6 +74,9 @@
+ (((long)(((UCHAR *)up)[2])) << 8) \
+ ((long)(((UCHAR *)up)[3])) )
+#define SelectSpigot(padapter,spigot) outb_p (spigot, padapter->regStatSel)
+#define WriteCommand(padapter,cmd) outb_p (cmd, padapter->regStatCmd)
+
/************************************************/
/* SCSI CDB operation codes */
/************************************************/
@@ -163,8 +164,6 @@
#define IDE_CMD_READ_MULTIPLE 0xC4
#define IDE_CMD_WRITE_MULTIPLE 0xC5
#define IDE_CMD_SET_MULTIPLE 0xC6
-#define IDE_COMMAND_WRITE_DMA 0xCA
-#define IDE_COMMAND_READ_DMA 0xC8
#define IDE_COMMAND_IDENTIFY 0xEC
// IDE status definitions
@@ -187,23 +186,6 @@
#define IDE_ERROR_UNC 0x40
#define IDE_ERROR_BBK 0x80
-// IDE interface structure
-typedef struct _IDE_STRUCT
- {
- union
- {
- UCHAR ide[9];
- struct
- {
- USHORT data;
- UCHAR sectors;
- UCHAR lba[4];
- UCHAR cmd;
- UCHAR spigot;
- } ides;
- } ide;
- } IDE_STRUCT;
-
// SCSI read capacity structure
typedef struct _READ_CAPACITY_DATA
{
@@ -238,81 +220,73 @@ typedef struct _INQUIRYDATA
} INQUIRYDATA, *PINQUIRYDATA;
// IDE IDENTIFY data
+#pragma pack (1)
+#pragma align 1
typedef struct _IDENTIFY_DATA
{
- USHORT GeneralConfiguration; // 00
- USHORT NumberOfCylinders; // 02
- USHORT Reserved1; // 04
- USHORT NumberOfHeads; // 06
- USHORT UnformattedBytesPerTrack; // 08
- USHORT UnformattedBytesPerSector; // 0A
- USHORT SectorsPerTrack; // 0C
- USHORT VendorUnique1[3]; // 0E
- USHORT SerialNumber[10]; // 14
- USHORT BufferType; // 28
- USHORT BufferSectorSize; // 2A
- USHORT NumberOfEccBytes; // 2C
- USHORT FirmwareRevision[4]; // 2E
- USHORT ModelNumber[20]; // 36
- UCHAR MaximumBlockTransfer; // 5E
- UCHAR VendorUnique2; // 5F
- USHORT DoubleWordIo; // 60
- USHORT Capabilities; // 62
- USHORT Reserved2; // 64
- UCHAR VendorUnique3; // 66
- UCHAR PioCycleTimingMode; // 67
- UCHAR VendorUnique4; // 68
- UCHAR DmaCycleTimingMode; // 69
- USHORT TranslationFieldsValid:1; // 6A
- USHORT Reserved3:15;
- USHORT NumberOfCurrentCylinders; // 6C
- USHORT NumberOfCurrentHeads; // 6E
- USHORT CurrentSectorsPerTrack; // 70
- ULONG CurrentSectorCapacity; // 72
- USHORT Reserved4[197]; // 76
+ USHORT GeneralConfiguration; // 0
+ USHORT NumberOfCylinders; // 1
+ USHORT Reserved1; // 2
+ USHORT NumberOfHeads; // 3
+ USHORT UnformattedBytesPerTrack; // 4
+ USHORT UnformattedBytesPerSector; // 5
+ USHORT SectorsPerTrack; // 6
+ USHORT NumBytesISG; // 7 Byte Len - inter-sector gap
+ USHORT NumBytesSync; // 8 - sync field
+ USHORT NumWordsVUS; // 9 Len - Vendor Unique Info
+ USHORT SerialNumber[10]; // 10
+ USHORT BufferType; // 20
+ USHORT BufferSectorSize; // 21
+ USHORT NumberOfEccBytes; // 22
+ USHORT FirmwareRevision[4]; // 23
+ USHORT ModelNumber[20]; // 27
+ USHORT NumSectorsPerInt :8; // 47 Multiple Mode - Sec/Blk
+ USHORT Reserved2 :8; // 47
+ USHORT DoubleWordMode; // 48 flag for double word mode capable
+ USHORT VendorUnique1 :8; // 49
+ USHORT SupportDMA :1; // 49 DMA supported
+ USHORT SupportLBA :1; // 49 LBA supported
+ USHORT SupportIORDYDisable :1; // 49 IORDY can be disabled
+ USHORT SupportIORDY :1; // 49 IORDY supported
+ USHORT ReservedPsuedoDMA :1; // 49 reserved for pseudo DMA mode support
+ USHORT Reserved3 :3; // 49
+ USHORT Reserved4; // 50
+ USHORT Reserved5 :8; // 51 Transfer Cycle Timing - PIO
+ USHORT PIOCycleTime :8; // 51 Transfer Cycle Timing - PIO
+ USHORT Reserved6 :8; // 52 - DMA
+ USHORT DMACycleTime :8; // 52 - DMA
+ USHORT Valid_54_58 :1; // 53 words 54 - 58 are vaild
+ USHORT Valid_64_70 :1; // 53 words 64 - 70 are valid
+ USHORT Reserved7 :14; // 53
+ USHORT LogNumCyl; // 54 Current Translation - Num Cyl
+ USHORT LogNumHeads; // 55 Num Heads
+ USHORT LogSectorsPerTrack; // 56 Sec/Trk
+ ULONG LogTotalSectors; // 57 Total Sec
+ USHORT CurrentNumSecPerInt :8; // 59 current setting for number of sectors per interrupt
+ USHORT ValidNumSecPerInt :1; // 59 Current setting is valid for number of sectors per interrupt
+ USHORT Reserved8 :7; // 59
+ ULONG LBATotalSectors; // 60 LBA Mode - Sectors
+ USHORT DMASWordFlags; // 62
+ USHORT DMAMWordFlags; // 63
+ USHORT AdvancedPIOSupport :8; // 64 Flow control PIO transfer modes supported
+ USHORT Reserved9 :8; // 64
+ USHORT MinMultiDMACycle; // 65 minimum multiword DMA transfer cycle time per word
+ USHORT RecomendDMACycle; // 66 Manufacturer's recommende multiword DMA transfer cycle time
+ USHORT MinPIOCycleWithoutFlow; // 67 Minimum PIO transfer cycle time without flow control
+ USHORT MinPIOCylceWithFlow; // 68 Minimum PIO transfer cycle time with IORDY flow control
+ USHORT ReservedSpace[256-69]; // 69
} IDENTIFY_DATA, *PIDENTIFY_DATA;
-
-// Identify data without the Reserved4.
-typedef struct _IDENTIFY_DATA2 {
- USHORT GeneralConfiguration; // 00
- USHORT NumberOfCylinders; // 02
- USHORT Reserved1; // 04
- USHORT NumberOfHeads; // 06
- USHORT UnformattedBytesPerTrack; // 08
- USHORT UnformattedBytesPerSector; // 0A
- USHORT SectorsPerTrack; // 0C
- USHORT VendorUnique1[3]; // 0E
- USHORT SerialNumber[10]; // 14
- USHORT BufferType; // 28
- USHORT BufferSectorSize; // 2A
- USHORT NumberOfEccBytes; // 2C
- USHORT FirmwareRevision[4]; // 2E
- USHORT ModelNumber[20]; // 36
- UCHAR MaximumBlockTransfer; // 5E
- UCHAR VendorUnique2; // 5F
- USHORT DoubleWordIo; // 60
- USHORT Capabilities; // 62
- USHORT Reserved2; // 64
- UCHAR VendorUnique3; // 66
- UCHAR PioCycleTimingMode; // 67
- UCHAR VendorUnique4; // 68
- UCHAR DmaCycleTimingMode; // 69
- USHORT TranslationFieldsValid:1; // 6A
- USHORT Reserved3:15;
- USHORT NumberOfCurrentCylinders; // 6C
- USHORT NumberOfCurrentHeads; // 6E
- USHORT CurrentSectorsPerTrack; // 70
- ULONG CurrentSectorCapacity; // 72
- } IDENTIFY_DATA2, *PIDENTIFY_DATA2;
-
+#pragma pack ()
+#pragma align 0
#endif // PSI_EIDE_SCSIOP
// function prototypes
int Pci2220i_Detect (Scsi_Host_Template *tpnt);
-int Pci2220i_Command (Scsi_Cmnd *SCpnt);
+int Pci2220i_Command (Scsi_Cmnd *SCpnt);
int Pci2220i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
int Pci2220i_Abort (Scsi_Cmnd *SCpnt);
int Pci2220i_Reset (Scsi_Cmnd *SCpnt, unsigned int flags);
+int Pci2220i_Release (struct Scsi_Host *pshost);
int Pci2220i_BiosParam (Disk *disk, kdev_t dev, int geom[]);
#ifndef NULL
@@ -321,18 +295,57 @@ int Pci2220i_BiosParam (Disk *disk, kdev_t dev, int geom[]);
extern struct proc_dir_entry Proc_Scsi_Pci2220i;
-#define PCI2220I { proc_dir: &Proc_Scsi_Pci2220i,/* proc_dir_entry */ \
- name: "PCI-2220I EIDE Disk Controller",\
- detect: Pci2220i_Detect, \
- command: Pci2220i_Command, \
- queuecommand: Pci2220i_QueueCommand, \
- abort: Pci2220i_Abort, \
- reset: Pci2220i_Reset, \
- bios_param: Pci2220i_BiosParam, \
- can_queue: 1, \
- this_id: -1, \
- sg_tablesize: SG_NONE, \
- cmd_per_lun: 1, \
- use_clustering: DISABLE_CLUSTERING }
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,75)
+#define PCI2220I { \
+ next: NULL, \
+ module: NULL, \
+ proc_dir: &Proc_Scsi_Pci2220i, \
+ proc_info: NULL, /* let's not bloat the kernel */\
+ name: "PCI-2220I EIDE Disk Controller", \
+ detect: Pci2220i_Detect, \
+ release: Pci2220i_Release, \
+ info: NULL, /* let's not bloat the kernel */\
+ command: Pci2220i_Command, \
+ queuecommand: Pci2220i_QueueCommand, \
+ eh_strategy_handler: NULL, \
+ eh_abort_handler: NULL, \
+ eh_device_reset_handler: NULL, \
+ eh_bus_reset_handler: NULL, \
+ eh_host_reset_handler: NULL, \
+ abort: Pci2220i_Abort, \
+ reset: Pci2220i_Reset, \
+ slave_attach: NULL, \
+ bios_param: Pci2220i_BiosParam, \
+ can_queue: 1, \
+ this_id: -1, \
+ sg_tablesize: SG_NONE, \
+ cmd_per_lun: 1, \
+ present: 0, \
+ unchecked_isa_dma: 0, \
+ use_clustering: DISABLE_CLUSTERING, \
+ use_new_eh_code: 0 \
+ }
+#else
+#define PCI2220I { NULL, NULL, \
+ &Proc_Scsi_Pci2220i,/* proc_dir_entry */\
+ NULL, \
+ "PCI-2220I EIDE Disk Controller", \
+ Pci2220i_Detect, \
+ Pci2220i_Release, \
+ NULL, \
+ Pci2220i_Command, \
+ Pci2220i_QueueCommand, \
+ Pci2220i_Abort, \
+ Pci2220i_Reset, \
+ NULL, \
+ Pci2220i_BiosParam, \
+ 1, \
+ -1, \
+ SG_NONE, \
+ 1, \
+ 0, \
+ 0, \
+ DISABLE_CLUSTERING }
+#endif
#endif
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index 9b2aad5c2..09cfbeb87 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -1,6 +1,6 @@
/* pluto.c: SparcSTORAGE Array SCSI host adapter driver.
*
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*
*/
@@ -22,7 +22,7 @@
#include "scsi.h"
#include "hosts.h"
-#include "../fc4/fcp_scsi.h"
+#include "../fc4/fcp_impl.h"
#include "pluto.h"
#include <linux/module.h>
@@ -56,7 +56,7 @@ static atomic_t fcss __initdata = ATOMIC_INIT(0);
static struct timer_list fc_timer __initdata = { 0 };
struct semaphore fc_sem __initdata = MUTEX_LOCKED;
-static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr);
+static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
__initfunc(static void pluto_detect_timeout(unsigned long data))
{
@@ -100,15 +100,19 @@ __initfunc(int pluto_detect(Scsi_Host_Template *tpnt))
tpnt->proc_dir = &proc_scsi_pluto;
fcscount = 0;
- for_each_online_fc_channel(fc)
- fcscount++;
+ for_each_online_fc_channel(fc) {
+ if (!fc->posmap)
+ fcscount++;
+ }
PLND(("%d channels online\n", fcscount))
if (!fcscount) {
#if defined(MODULE) && defined(CONFIG_FC4_SOC_MODULE) && defined(CONFIG_KMOD)
request_module("soc");
- for_each_online_fc_channel(fc)
- fcscount++;
+ for_each_online_fc_channel(fc) {
+ if (!fc->posmap)
+ fcscount++;
+ }
if (!fcscount)
#endif
return 0;
@@ -129,8 +133,9 @@ __initfunc(int pluto_detect(Scsi_Host_Template *tpnt))
Scsi_Cmnd *SCpnt;
struct Scsi_Host *host;
struct pluto *pluto;
-
+
if (i == fcscount) break;
+ if (fc->posmap) continue;
PLD(("trying to find SSA\n"))
@@ -233,9 +238,13 @@ __initfunc(int pluto_detect(Scsi_Host_Template *tpnt))
host->max_id = inq->targets;
host->max_channel = inq->channels;
host->irq = fc->irq;
-
+
+#ifdef __sparc_v9__
+ host->unchecked_isa_dma = 1;
+#endif
+
host->select_queue_depths = pluto_select_queue_depths;
-
+
fc->channels = inq->channels + 1;
fc->targets = inq->targets;
fc->ages = ages;
@@ -304,7 +313,7 @@ const char *pluto_info(struct Scsi_Host *host)
channel 0 id 0 lun 0 for CONTROLLER
and channels 1 .. max_channel are normal single disks.
*/
-static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr)
+static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd)
{
PLND(("encode addr %d %d %d\n", SCpnt->channel, SCpnt->target, SCpnt->cmnd[1] & 0xe0))
/* We don't support LUNs - neither does SSA :) */
@@ -318,6 +327,8 @@ static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr)
addr[2] = SCpnt->target;
addr[3] = 0;
}
+ /* We're Point-to-Point, so target it to the default DID */
+ fcmd->did = fc->did;
PLND(("trying %04x%04x%04x%04x\n", addr[0], addr[1], addr[2], addr[3]))
return 0;
}
diff --git a/drivers/scsi/pluto.h b/drivers/scsi/pluto.h
index e1d267054..d965f5cd8 100644
--- a/drivers/scsi/pluto.h
+++ b/drivers/scsi/pluto.h
@@ -6,7 +6,7 @@
#ifndef _PLUTO_H
#define _PLUTO_H
-#include "../fc4/fcp_scsi.h"
+#include "../fc4/fcp_impl.h"
struct pluto {
/* This must be first */
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index de54daef6..5904c881c 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -48,7 +48,6 @@ typedef struct {
}
#include "ppa.h"
-#include <linux/parport.h>
#define NO_HOSTS 4
static ppa_struct ppa_hosts[NO_HOSTS] =
@@ -742,6 +741,7 @@ static void ppa_interrupt(void *data)
{
ppa_struct *tmp = (ppa_struct *) data;
Scsi_Cmnd *cmd = tmp->cur_cmd;
+ unsigned long flags;
if (!cmd) {
printk("PPA: bug in ppa_interrupt\n");
@@ -793,7 +793,10 @@ static void ppa_interrupt(void *data)
ppa_pb_release(cmd->host->unique_id);
tmp->cur_cmd = 0;
+
+ spin_lock_irqsave(&io_request_lock, flags);
cmd->scsi_done(cmd);
+ spin_unlock_irqrestore(&io_request_lock, flags);
return;
}
diff --git a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h
index b3beb9f5d..58aba3473 100644
--- a/drivers/scsi/ppa.h
+++ b/drivers/scsi/ppa.h
@@ -10,7 +10,7 @@
#ifndef _PPA_H
#define _PPA_H
-#define PPA_VERSION "2.03 (for Linux 2.0.0)"
+#define PPA_VERSION "2.03 (for Linux 2.2.x)"
/*
* this driver has been hacked by Matteo Frigo (athena@theory.lcs.mit.edu)
diff --git a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c
index d07f72875..cca528fee 100644
--- a/drivers/scsi/psi240i.c
+++ b/drivers/scsi/psi240i.c
@@ -129,7 +129,7 @@ static int WriteData (PADAPTER240I padapter)
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 @@ static UCHAR IdeCmd (PADAPTER240I 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;
@@ -264,7 +264,7 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
UCHAR status;
int z;
- DEB(printk ("\npsi240i recieved interrupt\n"));
+ DEB(printk ("\npsi240i received interrupt\n"));
shost = PsiHost[irq - 10];
if ( !shost )
diff --git a/drivers/scsi/psi_dale.h b/drivers/scsi/psi_dale.h
index d8a407f3d..bb7c8006b 100644
--- a/drivers/scsi/psi_dale.h
+++ b/drivers/scsi/psi_dale.h
@@ -1,32 +1,23 @@
-/*+M*************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver proc support for Linux.
+/****************************************************************************
+ * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
*
- * Copyright (c) 1997 Perceptive Solutions, Inc.
+ * psi_dalei.h - Linux Host Driver for PCI-2220i EIDE Adapters
*
- * This program is free software; you can redistribute 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.
+ * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
+ * All Rights Reserved.
*
- * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
*
- * 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.
+ * Technical updates and product information at:
+ * http://www.psidisk.com
*
+ * Please send questions, comments, bug reports to:
+ * tech@psidisk.com Technical Support
*
- * File Name: psi_dale.h
- *
- * Description: This file contains the interface defines and
- * error codes.
- *
- *-M*************************************************************************/
-
-#ifndef PSI_DALE
-#define PSI_DALE
+ ****************************************************************************/
/************************************************/
/* Dale PCI setup */
@@ -58,24 +49,24 @@
/************************************************/
/* DALE Register address offsets */
/************************************************/
-#define REG_DATA 0x80
-#define REG_ERROR 0x84
-#define REG_SECTOR_COUNT 0x88
-#define REG_LBA_0 0x8C
-#define REG_LBA_8 0x90
-#define REG_LBA_16 0x94
-#define REG_LBA_24 0x98
-#define REG_STAT_CMD 0x9C
-#define REG_STAT_SEL 0xA0
-#define REG_FAIL 0xB0
-#define REG_ALT_STAT 0xB8
-#define REG_DRIVE_ADRS 0xBC
-
-#define DALE_DATA_SLOW 0x00040000L
-#define DALE_DATA_MODE2 0x00040000L
-#define DALE_DATA_MODE3 0x00050000L
-#define DALE_DATA_MODE4 0x00060000L
-#define DALE_DATA_MODE4P 0x00070000L
+#define REG_DATA 0x80
+#define REG_ERROR 0x84
+#define REG_SECTOR_COUNT 0x88
+#define REG_LBA_0 0x8C
+#define REG_LBA_8 0x90
+#define REG_LBA_16 0x94
+#define REG_LBA_24 0x98
+#define REG_STAT_CMD 0x9C
+#define REG_STAT_SEL 0xA0
+#define REG_FAIL 0xB0
+#define REG_ALT_STAT 0xB8
+#define REG_DRIVE_ADRS 0xBC
+
+#define DALE_DATA_SLOW 0x00040000L
+#define DALE_DATA_MODE2 0x00040000L
+#define DALE_DATA_MODE3 0x00050000L
+#define DALE_DATA_MODE4 0x00060000L
+#define DALE_DATA_MODE4P 0x00070000L
#define RTR_LOCAL_RANGE 0x000
#define RTR_LOCAL_REMAP 0x004
@@ -110,52 +101,52 @@
/************************************************/
/* Dale Scratchpad locations */
/************************************************/
-#define DALE_CHANNEL_DEVICE_0 0 // device channel locations
-#define DALE_CHANNEL_DEVICE_1 1
-#define DALE_CHANNEL_DEVICE_2 2
-#define DALE_CHANNEL_DEVICE_3 3
+#define DALE_CHANNEL_DEVICE_0 0 // device channel locations
+#define DALE_CHANNEL_DEVICE_1 1
+#define DALE_CHANNEL_DEVICE_2 2
+#define DALE_CHANNEL_DEVICE_3 3
-#define DALE_SCRATH_DEVICE_0 4 // device type codes
-#define DALE_SCRATH_DEVICE_1 5
-#define DALE_SCRATH_DEVICE_2 6
-#define DALE_SCRATH_DEVICE_3 7
+#define DALE_SCRATH_DEVICE_0 4 // device type codes
+#define DALE_SCRATH_DEVICE_1 5
+#define DALE_SCRATH_DEVICE_2 6
+#define DALE_SCRATH_DEVICE_3 7
-#define DALE_RAID_0_STATUS 8
-#define DALE_RAID_1_STATUS 9
+#define DALE_RAID_0_STATUS 8
+#define DALE_RAID_1_STATUS 9
-#define DALE_TIMING_MODE 12 // bus master timing mode (2, 3, 4, 5)
-#define DALE_NUM_DRIVES 13 // number of addressable drives on this board
-#define DALE_RAID_ON 14 // RAID status On
-#define DALE_LAST_ERROR 15 // Last error code from BIOS
+#define DALE_TIMING_MODE 12 // bus master timing mode (2, 3, 4, 5)
+#define DALE_NUM_DRIVES 13 // number of addressable drives on this board
+#define DALE_RAID_ON 14 // RAID status On
+#define DALE_LAST_ERROR 15 // Last error code from BIOS
/************************************************/
/* Dale cable select bits */
/************************************************/
-#define SEL_NONE 0x00
-#define SEL_1 0x01
-#define SEL_2 0x02
+#define SEL_NONE 0x00
+#define SEL_1 0x01
+#define SEL_2 0x02
/************************************************/
/* Programmable Interrupt Controller */
/************************************************/
-#define PIC1 0x20 // first 8259 base port address
-#define PIC2 0xA0 // second 8259 base port address
-#define INT_OCW1 1 // Operation Control Word 1: IRQ mask
-#define EOI 0x20 // non-specific end-of-interrupt
+#define PIC1 0x20 // first 8259 base port address
+#define PIC2 0xA0 // second 8259 base port address
+#define INT_OCW1 1 // Operation Control Word 1: IRQ mask
+#define EOI 0x20 // non-specific end-of-interrupt
/************************************************/
/* Device/Geometry controls */
/************************************************/
-#define GEOMETRY_NONE 0x0 // No device
-#define GEOMETRY_SET 0x1 // Geometry set
-#define GEOMETRY_LBA 0x2 // Geometry set in default LBA mode
-#define GEOMETRY_PHOENIX 0x3 // Geometry set in Pheonix BIOS compatibility mode
+#define GEOMETRY_NONE 0x0 // No device
+#define GEOMETRY_SET 0x1 // Geometry set
+#define GEOMETRY_LBA 0x2 // Geometry set in default LBA mode
+#define GEOMETRY_PHOENIX 0x3 // Geometry set in Pheonix BIOS compatibility mode
-#define DEVICE_NONE 0x0 // No device present
-#define DEVICE_INACTIVE 0x1 // device present but not registered active
-#define DEVICE_ATAPI 0x2 // ATAPI device (CD_ROM, Tape, Etc...)
-#define DEVICE_DASD_NONLBA 0x3 // Non LBA incompatible device
-#define DEVICE_DASD_LBA 0x4 // LBA compatible device
+#define DEVICE_NONE 0x0 // No device present
+#define DEVICE_INACTIVE 0x1 // device present but not registered active
+#define DEVICE_ATAPI 0x2 // ATAPI device (CD_ROM, Tape, Etc...)
+#define DEVICE_DASD_NONLBA 0x3 // Non LBA incompatible device
+#define DEVICE_DASD_LBA 0x4 // LBA compatible device
/************************************************/
/* Setup Structure Definitions */
@@ -184,4 +175,38 @@ typedef struct // master setup structure
SETUP_DEVICE setupDevice[4];
} SETUP, *PSETUP;
-#endif
+/************************************************/
+/* RAID Structure Definitions */
+/************************************************/
+typedef struct
+ {
+ UCHAR signature; // 0x55 our mirror signature
+ UCHAR status; // current status bits
+ UCHAR pairIdentifier; // unique identifier for pair
+ ULONG reconstructPoint; // recontruction point for hot reconstruct
+ } DISK_MIRROR;
+
+typedef struct DEVICE_RAID1
+ {
+ long TotalSectors;
+ DISK_MIRROR DiskRaid1;
+ } DEVICE_RAID1, *PDEVICE_RAID1;
+
+#define DISK_MIRROR_POSITION 0x01A8
+#define SIGNATURE 0x55
+
+#define MASK_SERIAL_NUMBER 0x0FFE // mask for serial number matching
+#define MASK_SERIAL_UNIT 0x0001 // mask for unit portion of serial number
+
+// Status bits
+#define UCBF_MIRRORED 0x0010 // drive has a pair
+#define UCBF_MATCHED 0x0020 // drive pair is matched
+#define UCBF_SURVIVOR 0x0040 // this unit is a survivor of a pair
+#define UCBF_REBUILD 0x0080 // rebuild in progress on this device
+
+// SCSI controls for RAID
+#define SC_MY_RAID 0xBF // our special CDB command byte for Win95... interface
+#define MY_SCSI_QUERY1 0x32 // byte 1 subcommand to query driver for RAID 1 informatation
+#define MY_SCSI_REBUILD 0x40 // byte 1 subcommand to reconstruct a mirrored pair
+#define MY_SCSI_DEMOFAIL 0x54 // byte 1 subcommand for RAID failure demonstration
+#define MY_SCSI_ALARMMUTE 0x60 // byte 1 subcommand to mute any alarm currently on
diff --git a/drivers/scsi/psi_roy.h b/drivers/scsi/psi_roy.h
index 36a0341a9..c55b9c04c 100644
--- a/drivers/scsi/psi_roy.h
+++ b/drivers/scsi/psi_roy.h
@@ -1,29 +1,23 @@
-/*+M*************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver proc support for Linux.
+/****************************************************************************
+ * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
*
- * Copyright (c) 1997 Perceptive Solutions, Inc.
+ * psi_roy.h - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
*
- * This program is free software; you can redistribute 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.
+ * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
+ * All Rights Reserved.
*
- * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
*
- * 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.
+ * Technical updates and product information at:
+ * http://www.psidisk.com
*
+ * Please send questions, comments, bug reports to:
+ * tech@psidisk.com Technical Support
*
- * File Name: psi_roy.h
- *
- * Description: This file contains the host interface command and
- * error codes.
- *
- *-M*************************************************************************/
+ ****************************************************************************/
#ifndef ROY_HOST
#define ROY_HOST
@@ -40,7 +34,7 @@
#define MAXADAPTER 4 // Increase this and the sizes of the arrays below, if you need more.
#define MAX_BUS 2
#define MAX_UNITS 16
-#define TIMEOUT_COMMAND 30 // number of jiffies for command busy timeout
+#define TIMEOUT_COMMAND 400 // number of milliSecondos for command busy timeout
/************************************************/
/* I/O address offsets */
@@ -64,6 +58,8 @@
#define CMD_WRITE_CHS_SG 0x08 /* write sectors using scatter/gather list (CHS mode) */
#define CMD_VERIFY_CHS 0x09 /* verify data on sectors as specified (CHS mode) */
#define CMD_VERIFY 0x0A /* verify data on sectors as specified (RBA mode) */
+#define CMD_DASD_CDB 0x0B /* process CDB for a DASD device */
+#define CMD_DASD_CDB_SG 0x0C /* process CDB for a DASD device with scatter/gather */
#define CMD_READ_ABS 0x10 /* read absolute disk */
#define CMD_WRITE_ABS 0x11 /* write absolute disk */
@@ -80,9 +76,14 @@
#define CMD_SCSI_THRU_SG 0x31 /* SCSI pass through CDB with scatter/gather */
#define CMD_SCSI_REQ_SENSE 0x32 /* SCSI pass through request sense after check condition */
-#define CMD_DASD_SCSI_INQ 0x36 /* to DASD inquire for DASD info in SCSI inquiry format */
+#define CMD_DASD_RAID_RQ 0x35 /* request DASD RAID drive data */
+#define CMD_DASD_RAID_RQ0 0x31 /* byte 1 subcommand to query for RAID 0 informatation */
+#define CMD_DASD_RAID_RQ1 0x32 /* byte 1 subcommand to query for RAID 1 informatation */
+#define CMD_DASD_RAID_RQ5 0x33 /* byte 1 subcommand to query for RAID 5 informatation */
+
+#define CMD_DASD_SCSI_INQ 0x36 /* do DASD inquire and return in SCSI format */
#define CMD_DASD_CAP 0x37 /* read DASD capacity */
-#define CMD_DASD_INQ 0x38 /* do DASD inquire for type data */
+#define CMD_DASD_INQ 0x38 /* do DASD inquire for type data and return SCSI/EIDE inquiry */
#define CMD_SCSI_INQ 0x39 /* do SCSI inquire */
#define CMD_READ_SETUP 0x3A /* Get setup structures from controller */
#define CMD_WRITE_SETUP 0x3B /* Put setup structures in controller and burn in flash */
@@ -121,6 +122,12 @@
#define CMD_RAID_STATUS 0x57 /* get status of RAID pair */
#define CMD_RAID_STOP 0x58 /* stop any reconstruct in progress */
#define CMD_RAID_START 0x59 /* start reconstruct */
+#define CMD_RAID0_READ 0x5A /* read RAID 0 parameter block */
+#define CMD_RAID0_WRITE 0x5B /* write RAID 0 parameter block */
+#define CMD_RAID5_READ 0x5C /* read RAID 5 parameter block */
+#define CMD_RAID5_WRITE 0x5D /* write RAID 5 parameter block */
+
+#define CMD_ERASE_TABLES 0x5F /* erase partition table and RAID signatutures */
#define CMD_SCSI_GET 0x60 /* get SCSI pass through devices */
#define CMD_SCSI_TIMEOUT 0x61 /* set SCSI pass through timeout */
@@ -223,13 +230,13 @@
/* Host Operating System specification codes */
/* */
/************************************************/
-
#define SPEC_INTERRUPT 0x80 /* specification requires host interrupt */
#define SPEC_BACKWARD_SG 0x40 /* specification requires scatter/gather items reversed */
#define SPEC_DOS_BLOCK 0x01 /* DOS DASD blocking on pass through */
#define SPEC_OS2_V3 0x02 /* OS/2 Warp */
#define SPCE_SCO_3242 0x04 /* SCO 3.4.2.2 */
-
+#define SPEC_QNX_4X 0x05 /* QNX 4.XX */
+#define SPEC_NOVELL_NWPA 0x08 /* Novell NWPA scatter/gather support */
/************************************************/
/* */
@@ -310,5 +317,15 @@ typedef struct _DASD_INQUIRE
#define DEVC_DASD_REMOVABLE 0x80 /* Direct-access storage device, Removable */
#define DEVC_NONE 0xFF /* no device */
+// SCSI controls for RAID
+#define SC_MY_RAID 0xBF // our special CDB command byte for Win95... interface
+#define MY_SCSI_QUERY0 0x31 // byte 1 subcommand to query driver for RAID 0 informatation
+#define MY_SCSI_QUERY1 0x32 // byte 1 subcommand to query driver for RAID 1 informatation
+#define MY_SCSI_QUERY5 0x33 // byte 1 subcommand to query driver for RAID 5 informatation
+#define MY_SCSI_REBUILD 0x40 // byte 1 subcommand to reconstruct a mirrored pair
+#define MY_SCSI_DEMOFAIL 0x54 // byte 1 subcommand for RAID failure demonstration
+#define MY_SCSI_ALARMMUTE 0x60 // byte 1 subcommand to mute any alarm currently on
+
+
#endif
diff --git a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c
index 4279ee6f3..cbf6a375c 100644
--- a/drivers/scsi/qlogicfas.c
+++ b/drivers/scsi/qlogicfas.c
@@ -5,8 +5,8 @@
these silly disclaimers.
Copyright 1994, Tom Zerucha.
- zerucha@shell.portal.com
-
+ tz@execpc.com
+
Additional Code, and much appreciated help by
Michael A. Griffith
grif@cs.ucr.edu
diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
new file mode 100644
index 000000000..e82d8f4ff
--- /dev/null
+++ b/drivers/scsi/qlogicfc.c
@@ -0,0 +1,1921 @@
+/*
+ * 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 <grif@cs.ucr.edu> */
+
+/* This is a version of the isp1020 driver which was modified by
+ * Chris Loveland <cwl@iol.unh.edu> 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 <linux/blk.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/unistd.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/spinlock.h>
+
+#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.15.19 of the firmware. */
+
+#define RELOAD_FIRMWARE 1
+
+#define USE_NVRAM_DEFAULTS 1
+
+#define ISP2100_PORTDB 1
+
+/* Set the following to 1 to include fabric support, fabric support is
+ * currently not as well tested as the other aspects of the driver */
+
+#define ISP2100_FABRIC 0
+
+/* 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 10000000
+
+/* End Configuration section ************************************************ */
+
+#include <linux/module.h>
+
+#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_DMA_ERROR 0x0002
+#define CS_RESET_OCCURRED 0x0004
+#define CS_ABORTED 0x0005
+#define CS_TIMEOUT 0x0006
+#define CS_DATA_OVERRUN 0x0007
+#define CS_DATA_UNDERRUN 0x0015
+#define CS_QUEUE_FULL 0x001c
+#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
+
+static void isp2100_print_status_entry(struct Status_Entry *);
+
+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 = 0;
+
+ 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 + 10 * 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) {
+ hostdata->port_id = ((u_int) param[3]) << 16;
+ hostdata->port_id |= param[2];
+ temp[0].loop_id = param[1];
+ temp[0].wwn = hostdata->wwn;
+ }
+ else {
+ printk("qlogicfc: error getting scsi id.\n");
+ }
+
+ for (i = 1, j = 1; i <= QLOGICFC_MAX_ID; i++) {
+ temp[i].loop_id = temp[0].loop_id;
+
+ 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 = temp[0].loop_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) {
+ DEBUG(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;
+ DEBUG(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;
+#if ISP2100_PORTDB
+ cmd->target_id = hostdata->port_db[Cmnd->target].loop_id;
+#else
+ cmd->target_id = Cmnd->target;
+#endif
+ cmd->total_byte_cnt = (u_int) Cmnd->request_bufflen;
+ cmd->time_out = (SCSI_TIMEOUT / HZ) * 5;
+ 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) {
+ DEBUG(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) {
+ if ((jiffies - hostdata->tag_ages[Cmnd->target]) > (2 * SCSI_TIMEOUT)) {
+ cmd->control_flags |= CFLAG_ORDERED_TAG;
+ hostdata->tag_ages[Cmnd->target] = jiffies;
+ } else
+ switch (Cmnd->tag) {
+ case HEAD_OF_QUEUE_TAG:
+ cmd->control_flags |= CFLAG_HEAD_TAG;
+ break;
+ case ORDERED_QUEUE_TAG:
+ cmd->control_flags |= CFLAG_ORDERED_TAG;
+ break;
+ default:
+ cmd->control_flags |= CFLAG_SIMPLE_TAG;
+ break;
+ }
+ }
+ 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) ? num_free - 2 : 0;
+ 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)
+ DEBUG(printk("qlogicfc.c crosses its fingers.\n"));
+ host->can_queue = host->host_busy + 1;
+ }
+
+ 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:
+ case PORT_DB_CHANGED:
+ case LIP_RECEIVED:
+ 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;
+
+ TRACE("done", out_ptr, Cmnd);
+ DEBUG_INTR(isp2100_print_status_entry(sts));
+ if (sts->hdr.entry_type == ENTRY_STATUS) {
+ Cmnd = hostdata->handle_ptrs[sts->handle];
+ Cmnd->result = isp2100_return_status(sts);
+ hostdata->handle_ptrs[sts->handle] = NULL;
+ hostdata->queued--;
+ if (hostdata->handle_serials[sts->handle] != Cmnd->serial_number) {
+ hostdata->handle_serials[sts->handle] = 0;
+ outw(out_ptr, host->io_port + MBOX5);
+ continue;
+ }
+ hostdata->handle_serials[sts->handle] = 0;
+ } 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;
+
+ memset(Cmnd->sense_buffer, 0, sizeof(Cmnd->sense_buffer));
+ if (sts->scsi_status & 0x0200)
+ memcpy(Cmnd->sense_buffer, sts->req_sense_data,
+ sizeof(Cmnd->sense_buffer));
+
+ outw(out_ptr, host->io_port + MBOX5);
+
+ 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) ? num_free - 2 : 0;
+ 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);
+
+ if (host->can_queue <= host->host_busy){
+ if (host->can_queue+2 < host->host_busy)
+ DEBUG(printk("qlogicfc crosses its fingers.\n"));
+ host->can_queue = host->host_busy + 1;
+ }
+
+ 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_DMA_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:
+ 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;
+ case CS_QUEUE_FULL:
+ host_status = DID_ERROR;
+ 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]);
+ }
+ 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;
+ }
+
+ 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;
+
+ value = isp2100_read_nvram_word(host, 8);
+ control_block->node_name[0] = isp2100_read_nvram_word(host, 9);
+ control_block->node_name[1] = isp2100_read_nvram_word(host, 10);
+ control_block->node_name[2] = isp2100_read_nvram_word(host, 11);
+ control_block->node_name[3] = isp2100_read_nvram_word(host, 12);
+ control_block->hard_addr = isp2100_read_nvram_word(host, 13);
+
+ 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;
+}
+
+
+void isp2100_print_status_entry(struct Status_Entry *status)
+{
+ 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]);
+
+}
+
+
+
+#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 --git a/drivers/scsi/qlogicfc.h b/drivers/scsi/qlogicfc.h
new file mode 100644
index 000000000..ad3532962
--- /dev/null
+++ b/drivers/scsi/qlogicfc.h
@@ -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 <grif@cs.ucr.edu> */
+
+/* This is a version of the isp1020 driver which was modified by
+ * Chris Loveland <cwl@iol.unh.edu> 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 --git a/drivers/scsi/qlogicfc_asm.c b/drivers/scsi/qlogicfc_asm.c
new file mode 100644
index 000000000..4823af170
--- /dev/null
+++ b/drivers/scsi/qlogicfc_asm.c
@@ -0,0 +1,3292 @@
+/************************************************************************
+ * *
+ * --- ISP2100 Fabric Initiator/Target Firmware --- *
+ * *
+ * *
+ ************************************************************************
+ * *
+ * NOTICE *
+ * *
+ * COPYRIGHT 1998 QLOGIC CORPORATION *
+ * ALL RIGHTS RESERVED *
+ * *
+ ************************************************************************
+ */
+
+/*
+ * Firmware Version 1.15.19 (14:58 Jan 19, 1999)
+ */
+
+unsigned short risc_code_version = 1*1024+15;
+
+unsigned char firmware_version[] = {1,15,19};
+
+#define FW_VERSION_STRING "1.15.19"
+
+unsigned short risc_code_addr01 = 0x1000 ;
+
+unsigned short risc_code01[] = {
+ 0x0078, 0x1029, 0x0000, 0x65e6, 0x0000, 0x2043, 0x4f50, 0x5952,
+ 0x4947, 0x4854, 0x2031, 0x3939, 0x3620, 0x514c, 0x4f47, 0x4943,
+ 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350,
+ 0x3231, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056,
+ 0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3135, 0x2020, 0x2020,
+ 0x2400, 0x20c1, 0x0021, 0x20a1, 0x75e6, 0x2009, 0x0000, 0x20a9,
+ 0x071a, 0x41a4, 0x3400, 0x20c9, 0x7aff, 0x2091, 0x2000, 0x2059,
+ 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x20a0, 0x2051, 0x7600,
+ 0x2a70, 0x705b, 0x9500, 0x705f, 0xffff, 0x7057, 0x94f9, 0x7063,
+ 0x0300, 0x1078, 0x1282, 0x20a1, 0x7d00, 0x715c, 0x810d, 0x810d,
+ 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0007, 0xa112, 0xa00e,
+ 0x21a8, 0x41a4, 0x3400, 0x8211, 0x00c0, 0x1058, 0x715c, 0x3400,
+ 0xa102, 0x0040, 0x1068, 0x0048, 0x1068, 0x20a8, 0xa00e, 0x41a4,
+ 0x1078, 0x1249, 0x1078, 0x136e, 0x1078, 0x14f3, 0x1078, 0x19c8,
+ 0x1078, 0x3615, 0x1078, 0x5b94, 0x1078, 0x12f9, 0x1078, 0x242f,
+ 0x1078, 0x3c56, 0x1078, 0x3a2e, 0x1078, 0x4494, 0x1078, 0x1e5b,
+ 0x1078, 0x46d3, 0x1078, 0x4174, 0x1078, 0x1d7a, 0x1078, 0x1e3a,
+ 0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x109d, 0x7820, 0xa086,
+ 0x0002, 0x00c0, 0x109d, 0x7823, 0x4000, 0x0068, 0x1095, 0x781b,
+ 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000,
+ 0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000, 0xa08e, 0x0003,
+ 0x00c0, 0x10bd, 0x1078, 0x2d8d, 0x1078, 0x2457, 0x1078, 0x3ca6,
+ 0x1078, 0x3b19, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048,
+ 0x10c1, 0x1078, 0x44ac, 0x0078, 0x10a4, 0x1079, 0x10c5, 0x0078,
+ 0x10aa, 0x1078, 0x5866, 0x0078, 0x10b9, 0x10cf, 0x10d0, 0x114b,
+ 0x10cd, 0x11c6, 0x1246, 0x1247, 0x1248, 0x1078, 0x12d5, 0x007c,
+ 0x127e, 0x0f7e, 0x2091, 0x8000, 0x1078, 0x2eb2, 0x2079, 0x0100,
+ 0x7844, 0xa005, 0x00c0, 0x113c, 0x2011, 0x3542, 0x1078, 0x456e,
+ 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010,
+ 0x73b8, 0x1078, 0x2d4a, 0x1078, 0x56b1, 0x2011, 0x0004, 0x1078,
+ 0x6953, 0x1078, 0x39c8, 0x70c7, 0x0000, 0x70bf, 0x0000, 0x70c3,
+ 0x0000, 0x1078, 0x113f, 0x2011, 0x0000, 0x2079, 0x7651, 0x7804,
+ 0xd0ac, 0x0040, 0x1104, 0xc295, 0x70a4, 0xa005, 0x0040, 0x1109,
+ 0xc29d, 0x72be, 0xa296, 0x0004, 0x0040, 0x112a, 0x2011, 0x0001,
+ 0x1078, 0x6953, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002,
+ 0x0f7f, 0x1078, 0x2150, 0x2011, 0x0005, 0x1078, 0x57c0, 0x1078,
+ 0x4c7a, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x127f,
+ 0x0078, 0x113e, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002,
+ 0x2011, 0x0005, 0x1078, 0x57c0, 0x1078, 0x4c7a, 0x0c7e, 0x2061,
+ 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x0f7f, 0x127f, 0x007c, 0x0c7e,
+ 0x20a9, 0x0082, 0x2009, 0x007e, 0x1078, 0x380d, 0x8108, 0x00f0,
+ 0x1144, 0x0c7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x708c, 0xa086,
+ 0xffff, 0x0040, 0x1159, 0x1078, 0x2150, 0x1078, 0x4c7a, 0x0078,
+ 0x11c4, 0x70bc, 0xd09c, 0x0040, 0x1181, 0xd084, 0x0040, 0x1181,
+ 0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c,
+ 0x0040, 0x1181, 0x70c0, 0xa086, 0xffff, 0x0040, 0x117d, 0x1078,
+ 0x2245, 0x1078, 0x4c7a, 0x2011, 0x0001, 0x2019, 0x0000, 0x1078,
+ 0x227d, 0x1078, 0x4c7a, 0x0078, 0x11c4, 0x70c4, 0xa005, 0x00c0,
+ 0x11c4, 0x7088, 0xa005, 0x00c0, 0x11c4, 0x2001, 0x7652, 0x2004,
+ 0xd0ac, 0x0040, 0x11a7, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009,
+ 0x0000, 0x017e, 0x1078, 0x3825, 0x00c0, 0x119a, 0x6000, 0xd0ec,
+ 0x00c0, 0x11a2, 0x017f, 0x8108, 0x00f0, 0x1191, 0x0c7f, 0x157f,
+ 0x0078, 0x11a7, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x11c4, 0x7003,
+ 0x0003, 0x708f, 0xffff, 0x2001, 0x0000, 0x1078, 0x202b, 0x1078,
+ 0x2dc8, 0x2001, 0x7837, 0x2004, 0xa086, 0x0005, 0x00c0, 0x11bc,
+ 0x2011, 0x0000, 0x1078, 0x57c0, 0x2011, 0x0000, 0x1078, 0x57ca,
+ 0x1078, 0x4c7a, 0x1078, 0x4d3a, 0x127f, 0x007c, 0x017e, 0x0f7e,
+ 0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x7940, 0xa18c, 0x0010,
+ 0x7942, 0x7924, 0xd1b4, 0x0040, 0x11d7, 0x7827, 0x0040, 0xd19c,
+ 0x0040, 0x11dc, 0x7827, 0x0008, 0x007e, 0x037e, 0x157e, 0x7900,
+ 0xa18a, 0x0003, 0x0050, 0x1202, 0x7954, 0xd1ac, 0x00c0, 0x1202,
+ 0x2009, 0x00f8, 0x1078, 0x35e4, 0x7843, 0x0090, 0x7843, 0x0010,
+ 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x11fa, 0x7824, 0xd0ac,
+ 0x00c0, 0x1236, 0x00f0, 0x11f2, 0x2001, 0x0001, 0x1078, 0x202b,
+ 0x0078, 0x123f, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0008,
+ 0x00e0, 0x1208, 0x2091, 0x6000, 0x00f0, 0x1208, 0x7853, 0x0400,
+ 0x782f, 0x0000, 0x2009, 0x00f8, 0x1078, 0x35e4, 0x20a9, 0x000e,
+ 0x0005, 0x00f0, 0x1218, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843,
+ 0x0010, 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040,
+ 0x122d, 0x7824, 0xd0ac, 0x00c0, 0x1236, 0x8319, 0x00c0, 0x1223,
+ 0x2001, 0x0001, 0x1078, 0x202b, 0x0078, 0x123d, 0x7828, 0xc09d,
+ 0x782a, 0x7827, 0x0008, 0x7827, 0x0040, 0x7853, 0x0400, 0x157f,
+ 0x037f, 0x007f, 0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c,
+ 0x007c, 0x2a70, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048,
+ 0x1255, 0x704f, 0xffff, 0x0078, 0x1257, 0x704f, 0x0000, 0x7053,
+ 0xffff, 0x7067, 0x0000, 0x706b, 0x0000, 0x2061, 0x7820, 0x6003,
+ 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013,
+ 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061,
+ 0x7828, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f,
+ 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f,
+ 0x0000, 0x007c, 0x1078, 0x12a8, 0x2011, 0x0000, 0x81ff, 0x0040,
+ 0x12a7, 0xa186, 0x0001, 0x00c0, 0x1297, 0x705f, 0x8fff, 0x7057,
+ 0x8501, 0x7063, 0x0100, 0x705b, 0x8500, 0x0078, 0x12a5, 0xa186,
+ 0x0002, 0x00c0, 0x129f, 0x2011, 0x0000, 0x0078, 0x12a5, 0xa186,
+ 0x0005, 0x00c0, 0x12a5, 0x2011, 0x0001, 0x1078, 0x12cf, 0x007c,
+ 0x2009, 0x0000, 0x2011, 0x0000, 0x1078, 0x12cf, 0x2019, 0xaaaa,
+ 0x2061, 0xffff, 0x2362, 0x2c24, 0x2061, 0x7fff, 0x2c04, 0xa406,
+ 0x0040, 0x12bd, 0xc18d, 0x0078, 0x12ca, 0xc185, 0x2011, 0x0001,
+ 0x1078, 0x12cf, 0x2061, 0xffff, 0x2362, 0x2c04, 0xa306, 0x00c0,
+ 0x12ca, 0xc195, 0x2011, 0x0001, 0x1078, 0x12cf, 0x007c, 0x3800,
+ 0xa084, 0xfffc, 0xa205, 0x20c0, 0x007c, 0x2091, 0x8000, 0x0068,
+ 0x12d7, 0x007e, 0x017e, 0x2079, 0x0000, 0x7818, 0xa084, 0x0000,
+ 0x00c0, 0x12dd, 0x017f, 0x792e, 0x007f, 0x782a, 0x007f, 0x7826,
+ 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000,
+ 0x2091, 0x4080, 0x2079, 0x7600, 0x7803, 0x0005, 0x0078, 0x12f6,
+ 0x007c, 0x2071, 0x7600, 0x7158, 0x712e, 0x2021, 0x0001, 0xa190,
+ 0x002d, 0xa298, 0x002d, 0x0048, 0x130f, 0x705c, 0xa302, 0x00c8,
+ 0x130f, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078, 0x1301, 0x200b,
+ 0x0000, 0x749e, 0x74a2, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000,
+ 0x2071, 0x7600, 0x70a0, 0xa0ea, 0x0010, 0x00c8, 0x1322, 0xa06e,
+ 0x0078, 0x132c, 0x8001, 0x70a2, 0x702c, 0x2068, 0x2d04, 0x702e,
+ 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e,
+ 0x2071, 0x7600, 0x127e, 0x2091, 0x8000, 0x70a0, 0x8001, 0x00c8,
+ 0x133c, 0xa06e, 0x0078, 0x1345, 0x70a2, 0x702c, 0x2068, 0x2d04,
+ 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c,
+ 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7600, 0x702c, 0x206a,
+ 0x2d00, 0x702e, 0x70a0, 0x8000, 0x70a2, 0x127f, 0x0e7f, 0x007c,
+ 0x8dff, 0x0040, 0x1364, 0x6804, 0x6807, 0x0000, 0x007e, 0x1078,
+ 0x1348, 0x0d7f, 0x0078, 0x1358, 0x007c, 0x0e7e, 0x2071, 0x7600,
+ 0x70a0, 0xa08a, 0x0010, 0xa00d, 0x0e7f, 0x007c, 0x0e7e, 0x2071,
+ 0x7859, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071,
+ 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x0e7f, 0x007c, 0x0e7e,
+ 0x2270, 0x700b, 0x0000, 0x2071, 0x7859, 0x7018, 0xa088, 0x7862,
+ 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x00c0,
+ 0x1397, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a8, 0x0f7f, 0x0e7f,
+ 0x007c, 0x0e7e, 0x2071, 0x7859, 0x7004, 0xa005, 0x00c0, 0x13a6,
+ 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a8, 0x0f7f, 0x0e7f, 0x007c,
+ 0x7000, 0x0079, 0x13ab, 0x13af, 0x1419, 0x1436, 0x1436, 0x7018,
+ 0x711c, 0xa106, 0x00c0, 0x13b7, 0x7007, 0x0000, 0x007c, 0x0d7e,
+ 0xa180, 0x7862, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007,
+ 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c,
+ 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804,
+ 0x0d7f, 0xd084, 0x0040, 0x13d9, 0x7007, 0x0001, 0x1078, 0x13de,
+ 0x007c, 0x7007, 0x0002, 0x1078, 0x13f4, 0x007c, 0x017e, 0x027e,
+ 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x13e9, 0x2110,
+ 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803,
+ 0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e, 0x137e, 0x147e,
+ 0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c,
+ 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1408, 0x2110, 0xa006,
+ 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803,
+ 0x0001, 0x3300, 0x7016, 0x157f, 0x147f, 0x137f, 0x027f, 0x017f,
+ 0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0x76e5, 0x20a1, 0x0018,
+ 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000,
+ 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b,
+ 0x76e0, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x137e, 0x147e,
+ 0x157e, 0x2001, 0x7714, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026,
+ 0x2001, 0x7715, 0x20ac, 0x53a6, 0x2099, 0x7716, 0x20a1, 0x0018,
+ 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000,
+ 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b,
+ 0x7711, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x017e, 0x0e7e,
+ 0x2071, 0x7859, 0x0f7e, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002,
+ 0xd1fc, 0x0040, 0x1479, 0xa18c, 0x0700, 0x0040, 0x1476, 0x7008,
+ 0xa080, 0x0002, 0x2003, 0x0200, 0x0078, 0x1479, 0x7004, 0x1079,
+ 0x147d, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x13a8, 0x1485, 0x14a7,
+ 0x14c1, 0x14ea, 0x1483, 0x0078, 0x1483, 0x137e, 0x147e, 0x157e,
+ 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8,
+ 0x53a5, 0x3400, 0x7016, 0x157f, 0x147f, 0x137f, 0x700c, 0xa005,
+ 0x0040, 0x14ae, 0x1078, 0x13de, 0x007c, 0x7008, 0xa080, 0x0002,
+ 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x13a8, 0x007c, 0x700c,
+ 0xa005, 0x0040, 0x14ae, 0x1078, 0x13f4, 0x007c, 0x0d7e, 0x7008,
+ 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c,
+ 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x13a8,
+ 0x007c, 0x137e, 0x147e, 0x157e, 0x2001, 0x76e3, 0x2004, 0xa080,
+ 0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020,
+ 0x53a5, 0x2001, 0x76e5, 0x2004, 0xd0bc, 0x0040, 0x14e0, 0x2001,
+ 0x76ee, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5,
+ 0x157f, 0x147f, 0x137f, 0x7007, 0x0000, 0x1078, 0x3d4f, 0x1078,
+ 0x13a8, 0x007c, 0x2001, 0x7713, 0x2003, 0x0100, 0x7007, 0x0000,
+ 0x1078, 0x13a8, 0x007c, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030,
+ 0x2071, 0x786a, 0x7003, 0x0000, 0x700f, 0x7870, 0x7013, 0x7870,
+ 0x780f, 0x0070, 0x127f, 0x007c, 0x6934, 0xa184, 0x0007, 0x0079,
+ 0x1509, 0x1511, 0x1557, 0x1511, 0x1511, 0x1511, 0x153c, 0x1520,
+ 0x1515, 0xa085, 0x0001, 0x0078, 0x1571, 0x684c, 0xd0bc, 0x0040,
+ 0x1511, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x155f,
+ 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1511, 0x684c, 0xd0bc,
+ 0x0040, 0x1511, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a,
+ 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004,
+ 0x6832, 0x6858, 0x0078, 0x1567, 0xa18c, 0x00ff, 0xa186, 0x0015,
+ 0x00c0, 0x1511, 0x684c, 0xd0ac, 0x0040, 0x1511, 0x6804, 0x681a,
+ 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004,
+ 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, 0x1567, 0x684c,
+ 0xd0ac, 0x0040, 0x1511, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c,
+ 0x000f, 0xa188, 0x1c84, 0x210c, 0x6932, 0x2d08, 0x691a, 0x6826,
+ 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980,
+ 0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a,
+ 0x2004, 0x82ff, 0x0040, 0x158c, 0xa280, 0x0004, 0x0d7e, 0x206c,
+ 0x684c, 0xd0dc, 0x00c0, 0x1588, 0x1078, 0x1504, 0x10c0, 0x12d5,
+ 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, 0x037e, 0x027e,
+ 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, 0xa005, 0x00c0,
+ 0x15a0, 0x7206, 0x2001, 0x15b4, 0x007e, 0x2260, 0x0078, 0x16cc,
+ 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182,
+ 0x788b, 0x0048, 0x15ad, 0x2009, 0x7870, 0x710e, 0x7000, 0xa005,
+ 0x00c0, 0x15b4, 0x1078, 0x16b5, 0x127f, 0x007c, 0x127e, 0x027e,
+ 0x037e, 0x0c7e, 0x007e, 0x2091, 0x2100, 0x007f, 0x047f, 0x037f,
+ 0x027f, 0x0d7e, 0x0c7e, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e,
+ 0xa005, 0x0040, 0x1608, 0x6808, 0xa005, 0x0040, 0x166e, 0x7000,
+ 0xa005, 0x00c0, 0x15d5, 0x0078, 0x1602, 0x700c, 0x7110, 0xa106,
+ 0x00c0, 0x1672, 0x7004, 0xa406, 0x00c0, 0x1602, 0x2001, 0x0005,
+ 0x2004, 0xd08c, 0x0040, 0x15eb, 0x047e, 0x1078, 0x178d, 0x047f,
+ 0x2460, 0x0078, 0x15cb, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0,
+ 0x15de, 0x7804, 0xa084, 0x6000, 0x0040, 0x15fc, 0xa086, 0x6000,
+ 0x0040, 0x15fc, 0x0078, 0x15de, 0x7803, 0x0004, 0x7003, 0x0000,
+ 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x5c29, 0x0078, 0x1672,
+ 0x6808, 0xa005, 0x0040, 0x166e, 0x7000, 0xa005, 0x00c0, 0x1612,
+ 0x0078, 0x166e, 0x700c, 0x7110, 0xa106, 0x00c0, 0x161b, 0x7004,
+ 0xa406, 0x00c0, 0x166e, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040,
+ 0x1628, 0x047e, 0x1078, 0x178d, 0x047f, 0x2460, 0x0078, 0x1608,
+ 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x161b, 0x2001, 0x0005,
+ 0x2004, 0xd08c, 0x00c0, 0x1621, 0x7804, 0xa084, 0x6000, 0x0040,
+ 0x163f, 0xa086, 0x6000, 0x0040, 0x163f, 0x0078, 0x161b, 0x7007,
+ 0x0000, 0xa016, 0x2218, 0x7000, 0xa08e, 0x0001, 0x0040, 0x1660,
+ 0xa08e, 0x0002, 0x00c0, 0x166e, 0x0c7e, 0x0e7e, 0x6818, 0x2060,
+ 0x1078, 0x1c59, 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, 0x165c,
+ 0x7308, 0x720c, 0x0078, 0x165e, 0x7310, 0x7214, 0x0e7f, 0x0c7f,
+ 0x7820, 0xa318, 0x7824, 0xa211, 0x6810, 0xa300, 0x6812, 0x6814,
+ 0xa201, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x2009, 0x0048,
+ 0x1078, 0x5c29, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e, 0x0e7e,
+ 0x2071, 0x786a, 0x7000, 0xa086, 0x0000, 0x0040, 0x16b2, 0x7004,
+ 0xac06, 0x00c0, 0x16a3, 0x2079, 0x0030, 0x7804, 0xd0fc, 0x00c0,
+ 0x169f, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x1685, 0x7803,
+ 0x0004, 0x7804, 0xd0ac, 0x00c0, 0x1691, 0x7803, 0x0002, 0x7803,
+ 0x0009, 0x7003, 0x0003, 0x7007, 0x0000, 0x0078, 0x16a3, 0x1078,
+ 0x178d, 0x0078, 0x167a, 0x157e, 0x20a9, 0x0009, 0x2009, 0x7870,
+ 0x2104, 0xac06, 0x00c0, 0x16ad, 0x200a, 0xa188, 0x0003, 0x00f0,
+ 0x16a8, 0x157f, 0x0e7f, 0x0f7f, 0x007c, 0x700c, 0x7110, 0xa106,
+ 0x00c0, 0x16bd, 0x7003, 0x0000, 0x007c, 0x2104, 0x7006, 0x2060,
+ 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0x788b, 0x0048,
+ 0x16cb, 0x2009, 0x7870, 0x7112, 0x8cff, 0x00c0, 0x16d3, 0x1078,
+ 0x1958, 0x0078, 0x16fa, 0x6010, 0x2068, 0x2d58, 0x6828, 0xa406,
+ 0x00c0, 0x16de, 0x682c, 0xa306, 0x0040, 0x16e2, 0x1078, 0x1ca4,
+ 0x00c0, 0x16cf, 0x684c, 0xd0f4, 0x00c0, 0x16cf, 0x6824, 0x2050,
+ 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009,
+ 0x0011, 0x1078, 0x16fb, 0x0040, 0x16f9, 0x2009, 0x0001, 0x1078,
+ 0x16fb, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x1788, 0xa03e, 0x2730,
+ 0x6850, 0xd0fc, 0x00c0, 0x171a, 0x0d7e, 0x2804, 0xac68, 0x2900,
+ 0x0079, 0x170a, 0x176a, 0x172a, 0x172a, 0x176a, 0x176a, 0x1762,
+ 0x176a, 0x172a, 0x176a, 0x1730, 0x1730, 0x176a, 0x176a, 0x176a,
+ 0x1759, 0x1730, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20,
+ 0x0d7e, 0xd99c, 0x0040, 0x176d, 0x2804, 0xac68, 0x6f08, 0x6e0c,
+ 0x0078, 0x176d, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x176d,
+ 0x7b0c, 0xd3bc, 0x0040, 0x1751, 0x7004, 0x0e7e, 0x2070, 0x701c,
+ 0x0e7f, 0xa086, 0x0008, 0x00c0, 0x1751, 0x7b08, 0xa39c, 0x0fff,
+ 0x2d20, 0x0d7f, 0x0d7e, 0x6a14, 0x82ff, 0x00c0, 0x174c, 0x6810,
+ 0xa302, 0x0048, 0x174c, 0x6b10, 0x2011, 0x0000, 0x2468, 0x0078,
+ 0x1753, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078,
+ 0x176d, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
+ 0x00c0, 0x176a, 0x0d7f, 0x1078, 0x1c40, 0x00c0, 0x16fb, 0xa00e,
+ 0x0078, 0x1788, 0x0d7f, 0x1078, 0x12d5, 0x7b22, 0x7a26, 0x7d32,
+ 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x0d7f,
+ 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x2300, 0x6b10,
+ 0xa302, 0x6812, 0x2200, 0x6a14, 0xa203, 0x6816, 0x1078, 0x1c40,
+ 0x007c, 0x1078, 0x12d5, 0x1078, 0x12d5, 0x127e, 0x2091, 0x2100,
+ 0x007e, 0x017e, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002,
+ 0xa184, 0x0700, 0x00c0, 0x178b, 0xa184, 0x0003, 0xa086, 0x0003,
+ 0x0040, 0x178b, 0x7000, 0x0079, 0x17a5, 0x17ad, 0x17af, 0x1887,
+ 0x18ef, 0x1906, 0x17ad, 0x17ad, 0x17ad, 0x1078, 0x12d5, 0x8001,
+ 0x7002, 0xa184, 0x0880, 0x00c0, 0x17c4, 0x8aff, 0x0040, 0x1827,
+ 0x2009, 0x0001, 0x1078, 0x16fb, 0x0040, 0x1918, 0x2009, 0x0001,
+ 0x1078, 0x16fb, 0x0078, 0x1918, 0x7803, 0x0004, 0x7003, 0x0000,
+ 0xd1bc, 0x00c0, 0x180f, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x7820,
+ 0x686e, 0xa31a, 0x7824, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x7820,
+ 0x6910, 0xa100, 0x6812, 0x7824, 0x6914, 0xa101, 0x6816, 0x037f,
+ 0x027f, 0x7830, 0x681e, 0x7834, 0x6822, 0x1078, 0x1c59, 0x2a00,
+ 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x6850,
+ 0xc0fd, 0x6852, 0x6808, 0x8001, 0x680a, 0x00c0, 0x1801, 0x684c,
+ 0xd0e4, 0x0040, 0x1801, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078,
+ 0x5c29, 0x7808, 0xd0ec, 0x00c0, 0x180b, 0x7803, 0x0009, 0x7003,
+ 0x0004, 0x0078, 0x1918, 0x1078, 0x16b5, 0x0078, 0x1918, 0x057e,
+ 0x7d0c, 0xd5bc, 0x00c0, 0x1816, 0x1078, 0x7592, 0x057f, 0x1078,
+ 0x191c, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980,
+ 0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1918, 0x684c,
+ 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x183f, 0x7003, 0x0000,
+ 0x6808, 0x8001, 0x680a, 0x00c0, 0x183b, 0x7004, 0x2060, 0x2009,
+ 0x0048, 0x1078, 0x5c29, 0x1078, 0x16b5, 0x0078, 0x1918, 0x7814,
+ 0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, 0x6816, 0x7814,
+ 0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214,
+ 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b,
+ 0x1078, 0x1983, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001,
+ 0x7804, 0xd0fc, 0x0040, 0x1860, 0x7803, 0x0002, 0x7803, 0x0004,
+ 0x780f, 0x0070, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048,
+ 0x1078, 0x5c29, 0x1078, 0x19a6, 0x0040, 0x183b, 0x7908, 0xd1ec,
+ 0x00c0, 0x187e, 0x2009, 0x0009, 0x0078, 0x1880, 0x2009, 0x0019,
+ 0x7902, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1918, 0x8001,
+ 0x7002, 0xd194, 0x0040, 0x1899, 0x7804, 0xd0fc, 0x00c0, 0x1795,
+ 0x8aff, 0x0040, 0x1918, 0x2009, 0x0001, 0x1078, 0x16fb, 0x0078,
+ 0x1918, 0xa184, 0x0880, 0x00c0, 0x18a6, 0x8aff, 0x0040, 0x1918,
+ 0x2009, 0x0001, 0x1078, 0x16fb, 0x0078, 0x1918, 0x7803, 0x0004,
+ 0x7003, 0x0000, 0xd1bc, 0x00c0, 0x18da, 0x027e, 0x037e, 0x6b28,
+ 0x6a2c, 0x1078, 0x1c59, 0x0d7e, 0x0f7e, 0x2d78, 0x2804, 0xac68,
+ 0x6034, 0xd09c, 0x00c0, 0x18ca, 0x6808, 0x2008, 0xa31a, 0x680c,
+ 0xa213, 0x7810, 0xa100, 0x7812, 0x690c, 0x7814, 0xa101, 0x7816,
+ 0x0078, 0x18d6, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213, 0x7810,
+ 0xa100, 0x7812, 0x6914, 0x7814, 0xa101, 0x7816, 0x0f7f, 0x0d7f,
+ 0x0078, 0x17cf, 0x057e, 0x7d0c, 0x1078, 0x7592, 0x057f, 0x1078,
+ 0x191c, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980,
+ 0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1918, 0x7803,
+ 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0040, 0x1902, 0x6808,
+ 0x8001, 0x680a, 0x00c0, 0x1902, 0x7004, 0x2060, 0x2009, 0x0048,
+ 0x1078, 0x5c29, 0x1078, 0x16b5, 0x0078, 0x1918, 0x7803, 0x0004,
+ 0x7003, 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0040, 0x1902,
+ 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x1078, 0x16cc,
+ 0x017f, 0x007f, 0x127f, 0x007c, 0x1078, 0x192d, 0x20e1, 0x9028,
+ 0x700f, 0x7870, 0x7013, 0x7870, 0x2001, 0x015d, 0x200c, 0x810a,
+ 0x2102, 0x2001, 0x0138, 0x2202, 0x007c, 0x2001, 0x0138, 0x2014,
+ 0x2003, 0x0000, 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc,
+ 0x00c0, 0x194a, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0,
+ 0x194a, 0x2001, 0x0111, 0x201c, 0x83ff, 0x00c0, 0x194a, 0x8421,
+ 0x00c0, 0x1934, 0x007c, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204,
+ 0xa005, 0x00c0, 0x1957, 0x8109, 0x00c0, 0x194f, 0x007c, 0x007c,
+ 0x1078, 0x194b, 0x0040, 0x1980, 0x7908, 0xd1ec, 0x00c0, 0x1970,
+ 0x1078, 0x19a6, 0x0040, 0x1970, 0x7803, 0x0009, 0x7904, 0xd1fc,
+ 0x0040, 0x1966, 0x7803, 0x0006, 0x1078, 0x194b, 0x0040, 0x1980,
+ 0x780c, 0xd0a4, 0x00c0, 0x1980, 0x7007, 0x0000, 0x1078, 0x19a6,
+ 0x0040, 0x1982, 0x7803, 0x0019, 0x7003, 0x0003, 0x0078, 0x1982,
+ 0x1078, 0x191c, 0x007c, 0x3c00, 0x007e, 0x0e7e, 0x2071, 0x0200,
+ 0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x192d, 0x20e1, 0x7000,
+ 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f,
+ 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001,
+ 0x0138, 0x2202, 0x0e7f, 0x007f, 0x20e0, 0x007c, 0x3c00, 0x007e,
+ 0x7908, 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0048, 0x19b3, 0xa085,
+ 0x0001, 0x0078, 0x19c5, 0x2001, 0x020a, 0x81ff, 0x0040, 0x19be,
+ 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x20e1, 0x7000,
+ 0x200c, 0x200c, 0x7003, 0x0000, 0xa006, 0x007f, 0x20e0, 0x007c,
+ 0x0e7e, 0x2071, 0x788b, 0x7003, 0x0000, 0x0e7f, 0x007c, 0x0d7e,
+ 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1a4a, 0x6934,
+ 0xa184, 0x0007, 0x0079, 0x19dc, 0x19e4, 0x1a35, 0x19e4, 0x19e4,
+ 0x19e4, 0x1a1a, 0x19f7, 0x19e6, 0x1078, 0x12d5, 0x684c, 0xd0b4,
+ 0x0040, 0x1b4c, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812,
+ 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1a3d, 0x6834,
+ 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x19e4, 0x684c, 0xd0b4,
+ 0x0040, 0x1b4c, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812,
+ 0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d,
+ 0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004, 0x6832, 0x6958,
+ 0x0078, 0x1a46, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, 0x1a4a,
+ 0x684c, 0xd0b4, 0x0040, 0x1b4c, 0x6804, 0x681a, 0xa080, 0x000d,
+ 0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004, 0x6832, 0x6958,
+ 0xa006, 0x682e, 0x682a, 0x0078, 0x1a46, 0x684c, 0xd0b4, 0x0040,
+ 0x1789, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, 0x6834,
+ 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004, 0x6832, 0x6926, 0x684c,
+ 0xc0dd, 0x684e, 0x0d7f, 0x007c, 0x0f7e, 0x2079, 0x0020, 0x7804,
+ 0xd0fc, 0x10c0, 0x1b50, 0x0e7e, 0x0d7e, 0x2071, 0x788b, 0x7000,
+ 0xa005, 0x00c0, 0x1ac6, 0x0c7e, 0x7206, 0xa280, 0x0004, 0x205c,
+ 0x7004, 0x2068, 0x6818, 0x0d7e, 0x2068, 0x686c, 0x7812, 0x6890,
+ 0x0f7e, 0x20e1, 0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100,
+ 0x8004, 0x78d6, 0x0f7f, 0x0d7f, 0x2b68, 0x6824, 0x2050, 0x6818,
+ 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0xa184,
+ 0x0007, 0x0040, 0x1a88, 0x017e, 0x2009, 0x0008, 0xa102, 0x017f,
+ 0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081, 0x0000, 0x781e,
+ 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106,
+ 0x00c0, 0x1a9f, 0x6928, 0x6810, 0xa106, 0x0040, 0x1aac, 0x037e,
+ 0x047e, 0x6b14, 0x6c10, 0x1078, 0x1ca4, 0x047f, 0x037f, 0x0040,
+ 0x1aac, 0x0c7f, 0x0078, 0x1ac6, 0x8aff, 0x00c0, 0x1ab4, 0x0c7f,
+ 0xa085, 0x0001, 0x0078, 0x1ac6, 0x127e, 0x2091, 0x8000, 0x2079,
+ 0x0020, 0x2009, 0x0001, 0x1078, 0x1aca, 0x0040, 0x1ac3, 0x2009,
+ 0x0001, 0x1078, 0x1aca, 0x127f, 0x0c7f, 0xa006, 0x0d7f, 0x0e7f,
+ 0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e, 0x037e, 0x027e,
+ 0x8aff, 0x0040, 0x1b45, 0x700c, 0x7214, 0xa202, 0x7010, 0x7218,
+ 0xa203, 0x0048, 0x1b44, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0,
+ 0x1af7, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1ae7, 0x1b26,
+ 0x1b07, 0x1b07, 0x1b26, 0x1b26, 0x1b1e, 0x1b26, 0x1b07, 0x1b26,
+ 0x1b0d, 0x1b0d, 0x1b26, 0x1b26, 0x1b26, 0x1b15, 0x1b0d, 0xc0fc,
+ 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1b2a,
+ 0x0d7e, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x1b29, 0x6b08,
+ 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1b29, 0x6b10, 0x6a14, 0x6d00,
+ 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x1b29, 0x0d7f, 0x0d7e, 0x6834,
+ 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1b26, 0x0d7f, 0x1078,
+ 0x1c40, 0x00c0, 0x1ad0, 0xa00e, 0x0078, 0x1b45, 0x0d7f, 0x1078,
+ 0x12d5, 0x0d7f, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e,
+ 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c,
+ 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012,
+ 0x1078, 0x1c40, 0x0078, 0x1b45, 0xa006, 0x027f, 0x037f, 0x047f,
+ 0x057f, 0x067f, 0x077f, 0x007c, 0x1078, 0x12d5, 0x1078, 0x12d5,
+ 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e, 0x0e7e, 0x0d7e,
+ 0x0c7e, 0x2079, 0x0020, 0x2071, 0x788b, 0x2b68, 0x6818, 0x2060,
+ 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0, 0x1b4e, 0x7000,
+ 0x0079, 0x1b6a, 0x1c11, 0x1b6e, 0x1bde, 0x1c0f, 0x8001, 0x7002,
+ 0xd19c, 0x00c0, 0x1b82, 0x8aff, 0x0040, 0x1ba1, 0x2009, 0x0001,
+ 0x1078, 0x1aca, 0x0040, 0x1c11, 0x2009, 0x0001, 0x1078, 0x1aca,
+ 0x0078, 0x1c11, 0x7803, 0x0004, 0xd194, 0x0040, 0x1b92, 0x6850,
+ 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1b97, 0x684c, 0xc0f5, 0x684e,
+ 0x0078, 0x1b97, 0x1078, 0x1c59, 0x6850, 0xc0fd, 0x6852, 0x2a00,
+ 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0078,
+ 0x1c11, 0x711c, 0x81ff, 0x0040, 0x1bb7, 0x7918, 0x7922, 0x7827,
+ 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002, 0x700c, 0xa100,
+ 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078, 0x1c11, 0x0f7e,
+ 0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079, 0x0100, 0x7a14,
+ 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x7820, 0xd0bc, 0x00c0,
+ 0x1bc5, 0x79c8, 0x007f, 0xa102, 0x78ca, 0x79c4, 0x007f, 0xa102,
+ 0x78c6, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f,
+ 0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1c11, 0x8001, 0x7002,
+ 0xd194, 0x0040, 0x1bf3, 0x7804, 0xd0fc, 0x00c0, 0x1b60, 0xd19c,
+ 0x00c0, 0x1c0d, 0x8aff, 0x0040, 0x1c11, 0x2009, 0x0001, 0x1078,
+ 0x1aca, 0x0078, 0x1c11, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078,
+ 0x1c59, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1c06,
+ 0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1c0a, 0x6810, 0xa31a,
+ 0x6814, 0xa213, 0x0d7f, 0x0078, 0x1b92, 0x0078, 0x1b92, 0x1078,
+ 0x12d5, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f,
+ 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x788b, 0x7000, 0xa086, 0x0000,
+ 0x0040, 0x1c3d, 0x2079, 0x0020, 0x20e1, 0x9040, 0x7804, 0xd0fc,
+ 0x0040, 0x1c24, 0x1078, 0x1b50, 0x7000, 0xa086, 0x0000, 0x00c0,
+ 0x1c24, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, 0x1c33, 0x20e1,
+ 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f, 0x0f7f, 0x007c,
+ 0x8840, 0x2804, 0xa005, 0x00c0, 0x1c54, 0x6004, 0xa005, 0x0040,
+ 0x1c56, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x1c84,
+ 0x2044, 0x88ff, 0x1040, 0x12d5, 0x8a51, 0x007c, 0x2051, 0x0000,
+ 0x007c, 0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0, 0x1c73, 0x2c00,
+ 0xad06, 0x0040, 0x1c68, 0x6000, 0xa005, 0x00c0, 0x1c68, 0x2d00,
+ 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, 0x1c94, 0x2044,
+ 0x88ff, 0x1040, 0x12d5, 0x007c, 0x0000, 0x0011, 0x0015, 0x0019,
+ 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, 0x001b,
+ 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x1c79, 0x1c75, 0x0000,
+ 0x0000, 0x1c83, 0x0000, 0x1c79, 0x0000, 0x1c80, 0x1c7d, 0x0000,
+ 0x0000, 0x0000, 0x1c83, 0x1c80, 0x0000, 0x1c7b, 0x1c7b, 0x0000,
+ 0x0000, 0x1c83, 0x0000, 0x1c7b, 0x0000, 0x1c81, 0x1c81, 0x0000,
+ 0x0000, 0x0000, 0x1c83, 0x1c81, 0x0a7e, 0x097e, 0x087e, 0x6858,
+ 0xa055, 0x0040, 0x1d45, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0,
+ 0x1c84, 0xa986, 0x0007, 0x0040, 0x1cbd, 0xa986, 0x000e, 0x0040,
+ 0x1cbd, 0xa986, 0x000f, 0x00c0, 0x1cc1, 0x605c, 0xa422, 0x6060,
+ 0xa31a, 0x2804, 0xa045, 0x00c0, 0x1ccf, 0x0050, 0x1cc9, 0x0078,
+ 0x1d45, 0x6004, 0xa065, 0x0040, 0x1d45, 0x0078, 0x1cac, 0x2804,
+ 0xa005, 0x0040, 0x1ced, 0xac68, 0xd99c, 0x00c0, 0x1cdd, 0x6808,
+ 0xa422, 0x680c, 0xa31b, 0x0078, 0x1ce1, 0x6810, 0xa422, 0x6814,
+ 0xa31b, 0x0048, 0x1d0c, 0x2300, 0xa405, 0x0040, 0x1cf3, 0x8a51,
+ 0x0040, 0x1d45, 0x8840, 0x0078, 0x1ccf, 0x6004, 0xa065, 0x0040,
+ 0x1d45, 0x0078, 0x1cac, 0x8a51, 0x0040, 0x1d45, 0x8840, 0x2804,
+ 0xa005, 0x00c0, 0x1d06, 0x6004, 0xa065, 0x0040, 0x1d45, 0x6034,
+ 0xa0cc, 0x000f, 0xa9c0, 0x1c84, 0x2804, 0x2040, 0x2b68, 0x6850,
+ 0xc0fc, 0x6852, 0x0078, 0x1d39, 0x8422, 0x8420, 0x831a, 0xa399,
+ 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f, 0xd99c, 0x00c0,
+ 0x1d27, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x1048,
+ 0x12d5, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078, 0x1d33, 0x6910,
+ 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048, 0x12d5, 0x6800,
+ 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd,
+ 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, 0x007f,
+ 0x007f, 0x007f, 0xa006, 0x0078, 0x1d4a, 0x087f, 0x097f, 0x0a7f,
+ 0xa085, 0x0001, 0x007c, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007,
+ 0x0079, 0x1d52, 0x1d5a, 0x1d5b, 0x1d5e, 0x1d61, 0x1d66, 0x1d69,
+ 0x1d6e, 0x1d73, 0x007c, 0x1078, 0x1b50, 0x007c, 0x1078, 0x178d,
+ 0x007c, 0x1078, 0x178d, 0x1078, 0x1b50, 0x007c, 0x1078, 0x145e,
+ 0x007c, 0x1078, 0x1b50, 0x1078, 0x145e, 0x007c, 0x1078, 0x178d,
+ 0x1078, 0x145e, 0x007c, 0x1078, 0x178d, 0x1078, 0x1b50, 0x1078,
+ 0x145e, 0x007c, 0x127e, 0x2091, 0x2300, 0x2079, 0x0200, 0x2071,
+ 0x7b80, 0x2069, 0x7600, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004,
+ 0x1078, 0x2058, 0x781b, 0x0002, 0x20e1, 0x8700, 0x127f, 0x007c,
+ 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007, 0x0079, 0x1d98,
+ 0x1dbc, 0x1da0, 0x1da4, 0x1da8, 0x1dae, 0x1db2, 0x1db6, 0x1dba,
+ 0x1078, 0x417d, 0x0078, 0x1dbc, 0x1078, 0x41ac, 0x0078, 0x1dbc,
+ 0x1078, 0x417d, 0x1078, 0x41ac, 0x0078, 0x1dbc, 0x1078, 0x1dbe,
+ 0x0078, 0x1dbc, 0x1078, 0x1dbe, 0x0078, 0x1dbc, 0x1078, 0x1dbe,
+ 0x0078, 0x1dbc, 0x1078, 0x1dbe, 0x127f, 0x007c, 0x007e, 0x017e,
+ 0x027e, 0x7930, 0xa184, 0x0003, 0x0040, 0x1dc8, 0x1078, 0x12d5,
+ 0xa184, 0x0030, 0x0040, 0x1dd9, 0x6a00, 0xa286, 0x0003, 0x00c0,
+ 0x1dd3, 0x1078, 0x12d5, 0x1078, 0x357b, 0x20e1, 0x9010, 0x0078,
+ 0x1de5, 0xa184, 0x00c0, 0x0040, 0x1ddf, 0x1078, 0x12d5, 0xa184,
+ 0x0300, 0x0040, 0x1de5, 0x20e1, 0x9020, 0x7932, 0x027f, 0x017f,
+ 0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071, 0x7600, 0x7128,
+ 0x2001, 0x7823, 0x2102, 0x2001, 0x782b, 0x2102, 0xa182, 0x0211,
+ 0x00c8, 0x1dfe, 0x2009, 0x0008, 0x0078, 0x1e28, 0xa182, 0x0259,
+ 0x00c8, 0x1e06, 0x2009, 0x0007, 0x0078, 0x1e28, 0xa182, 0x02c1,
+ 0x00c8, 0x1e0e, 0x2009, 0x0006, 0x0078, 0x1e28, 0xa182, 0x0349,
+ 0x00c8, 0x1e16, 0x2009, 0x0005, 0x0078, 0x1e28, 0xa182, 0x0421,
+ 0x00c8, 0x1e1e, 0x2009, 0x0004, 0x0078, 0x1e28, 0xa182, 0x0581,
+ 0x00c8, 0x1e26, 0x2009, 0x0003, 0x0078, 0x1e28, 0x2009, 0x0002,
+ 0x2079, 0x0200, 0x7912, 0xa182, 0x0005, 0x00c8, 0x1e32, 0x7916,
+ 0x0078, 0x1e34, 0x7817, 0x0004, 0x1078, 0x2058, 0x0f7f, 0x0e7f,
+ 0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061, 0x0100, 0x2071,
+ 0x7600, 0x6024, 0x6026, 0x6033, 0x00ef, 0x60e7, 0x0000, 0x60eb,
+ 0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f,
+ 0x0080, 0x602f, 0x0000, 0x6007, 0x0caf, 0x600f, 0x00ff, 0x602b,
+ 0x002f, 0x127f, 0x007c, 0x2001, 0x762d, 0x2003, 0x0000, 0x2001,
+ 0x762c, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x007e,
+ 0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0, 0x1e73, 0xa184,
+ 0x0007, 0x0079, 0x1e79, 0xa195, 0x0004, 0xa284, 0x0007, 0x0079,
+ 0x1e79, 0x1ea5, 0x1e81, 0x1e85, 0x1e89, 0x1e8f, 0x1e93, 0x1e99,
+ 0x1e9f, 0x1078, 0x46e6, 0x0078, 0x1ea5, 0x1078, 0x47d5, 0x0078,
+ 0x1ea5, 0x1078, 0x47d5, 0x1078, 0x46e6, 0x0078, 0x1ea5, 0x1078,
+ 0x1eaa, 0x0078, 0x1ea5, 0x1078, 0x46e6, 0x1078, 0x1eaa, 0x0078,
+ 0x1ea5, 0x1078, 0x47d5, 0x1078, 0x1eaa, 0x0078, 0x1ea5, 0x1078,
+ 0x47d5, 0x1078, 0x46e6, 0x1078, 0x1eaa, 0x027f, 0x017f, 0x007f,
+ 0x127f, 0x007c, 0xd1ac, 0x0040, 0x1f5e, 0x017e, 0x047e, 0x0c7e,
+ 0x644c, 0x74ba, 0xa48c, 0xff00, 0xa196, 0xff00, 0x0040, 0x1ed9,
+ 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040, 0x1ed9, 0x7130,
+ 0xd18c, 0x00c0, 0x1ed9, 0x2011, 0x7652, 0x2214, 0xd2ec, 0x0040,
+ 0x1ecd, 0xc18d, 0x7132, 0x0078, 0x1ed9, 0x6240, 0xa294, 0x0010,
+ 0x0040, 0x1f1b, 0x6248, 0xa294, 0xff00, 0xa296, 0xff00, 0x00c0,
+ 0x1f1b, 0x037e, 0x73b8, 0x2011, 0x8013, 0x1078, 0x2d4a, 0x037f,
+ 0x7130, 0xc185, 0x7132, 0x2011, 0x7652, 0x220c, 0xd1a4, 0x0040,
+ 0x1f03, 0x017e, 0x2009, 0x0001, 0x2011, 0x0100, 0x1078, 0x46b4,
+ 0x2019, 0x000e, 0x1078, 0x74d9, 0xa484, 0x00ff, 0xa080, 0x232f,
+ 0x200c, 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e,
+ 0x1078, 0x7541, 0x017f, 0xd1ac, 0x00c0, 0x1f0c, 0x2019, 0x0004,
+ 0x1078, 0x2299, 0x0078, 0x1f1b, 0x157e, 0x20a9, 0x007f, 0x2009,
+ 0x0000, 0x1078, 0x3825, 0x00c0, 0x1f17, 0x1078, 0x3621, 0x8108,
+ 0x00f0, 0x1f11, 0x157f, 0x0c7f, 0x047f, 0x6043, 0x0000, 0x2009,
+ 0x00f7, 0x1078, 0x35e4, 0x0f7e, 0x2079, 0x7849, 0x783c, 0xa086,
+ 0x0000, 0x0040, 0x1f33, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079,
+ 0x0140, 0x7803, 0x0000, 0x0f7f, 0x2011, 0x0003, 0x1078, 0x57c0,
+ 0x2011, 0x0002, 0x1078, 0x57ca, 0x1078, 0x56d6, 0x1078, 0x45eb,
+ 0x037e, 0x2019, 0x0000, 0x1078, 0x5768, 0x037f, 0x60e3, 0x0000,
+ 0x017f, 0x2001, 0x7600, 0x2014, 0xa296, 0x0004, 0x00c0, 0x1f56,
+ 0xd19c, 0x00c0, 0x1f56, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001,
+ 0x2001, 0x7620, 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0040,
+ 0x1fff, 0x0f7e, 0x2079, 0x7849, 0x783c, 0xa086, 0x0001, 0x00c0,
+ 0x1f82, 0x017e, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, 0x0140,
+ 0x7803, 0x1000, 0x7803, 0x0000, 0x2079, 0x7836, 0x7807, 0x0000,
+ 0x7833, 0x0000, 0x1078, 0x4c7a, 0x1078, 0x4d3a, 0x017f, 0x0f7f,
+ 0x0078, 0x1fff, 0x0f7f, 0x017e, 0x6220, 0xd2b4, 0x0040, 0x1fb7,
+ 0x1078, 0x45eb, 0x1078, 0x5582, 0x6027, 0x0004, 0x0d7e, 0x2069,
+ 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x1f9a, 0x6803, 0x1000,
+ 0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0x7836, 0x6028, 0xa09a,
+ 0x0002, 0x00c8, 0x1faa, 0x8000, 0x602a, 0x0c7f, 0x1078, 0x5574,
+ 0x0078, 0x1ffe, 0x2019, 0x783f, 0x2304, 0xa065, 0x0040, 0x1fb4,
+ 0x2009, 0x0027, 0x1078, 0x5c29, 0x0c7f, 0x0078, 0x1ffe, 0xd2bc,
+ 0x0040, 0x1ffe, 0x1078, 0x45f9, 0x6017, 0x0010, 0x6027, 0x0004,
+ 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x1fcc,
+ 0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0x7836,
+ 0x6044, 0xa09a, 0x0002, 0x00c8, 0x1fed, 0x8000, 0x6046, 0x603c,
+ 0x0c7f, 0xa005, 0x0040, 0x1ffe, 0x1078, 0x45f0, 0xa080, 0x0007,
+ 0x2004, 0xa086, 0x0006, 0x00c0, 0x1fe9, 0x6017, 0x0012, 0x0078,
+ 0x1ffe, 0x6017, 0x0016, 0x0078, 0x1ffe, 0x037e, 0x2019, 0x0001,
+ 0x1078, 0x5768, 0x037f, 0x2019, 0x7845, 0x2304, 0xa065, 0x0040,
+ 0x1ffd, 0x2009, 0x004f, 0x1078, 0x5c29, 0x0c7f, 0x017f, 0xd19c,
+ 0x0040, 0x2027, 0x017e, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003,
+ 0x1078, 0x57c0, 0x2011, 0x0002, 0x1078, 0x57ca, 0x1078, 0x56d6,
+ 0x1078, 0x45eb, 0x037e, 0x2019, 0x0000, 0x1078, 0x5768, 0x037f,
+ 0x60e3, 0x0000, 0x1078, 0x75b0, 0x1078, 0x75ce, 0x2001, 0x7600,
+ 0x2003, 0x0004, 0x6027, 0x0008, 0x1078, 0x11c6, 0x017f, 0xa18c,
+ 0xffd0, 0x6126, 0x007c, 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e,
+ 0x127e, 0x2091, 0x8000, 0x2071, 0x7600, 0x71b0, 0x70b2, 0xa116,
+ 0x0040, 0x2051, 0x81ff, 0x0040, 0x2043, 0x2011, 0x8011, 0x1078,
+ 0x2d4a, 0x0078, 0x2051, 0x2011, 0x8012, 0x1078, 0x2d4a, 0x037e,
+ 0x0c7e, 0x2061, 0x0100, 0x2019, 0x0028, 0x1078, 0x2299, 0x0c7f,
+ 0x037f, 0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c,
+ 0x0c7e, 0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100, 0xa190, 0x2073,
+ 0x2204, 0x60f2, 0xa192, 0x0005, 0x00c8, 0x206a, 0xa190, 0x207c,
+ 0x0078, 0x206c, 0x2011, 0x2080, 0x2204, 0x60ee, 0x027f, 0x007f,
+ 0x0f7f, 0x0c7f, 0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420,
+ 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8,
+ 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0x2130, 0xa094,
+ 0xff00, 0x00c0, 0x208e, 0x81ff, 0x0040, 0x2092, 0x1078, 0x4330,
+ 0x0078, 0x2099, 0xa080, 0x232f, 0x200c, 0xa18c, 0xff00, 0x810f,
+ 0xa006, 0x007c, 0xa080, 0x232f, 0x200c, 0xa18c, 0x00ff, 0x007c,
+ 0x20c0, 0x20c4, 0x20c8, 0x20ce, 0x20d4, 0x20da, 0x20e0, 0x20e8,
+ 0x20f0, 0x20f6, 0x20fc, 0x2104, 0x210c, 0x2114, 0x211c, 0x2126,
+ 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130,
+ 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130,
+ 0x107e, 0x007e, 0x0078, 0x2149, 0x107e, 0x007e, 0x0078, 0x2149,
+ 0x107e, 0x007e, 0x1078, 0x1e64, 0x0078, 0x2149, 0x107e, 0x007e,
+ 0x1078, 0x1e64, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b,
+ 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b, 0x0078, 0x2149,
+ 0x107e, 0x007e, 0x1078, 0x1e64, 0x1078, 0x1d4b, 0x0078, 0x2149,
+ 0x107e, 0x007e, 0x1078, 0x1e64, 0x1078, 0x1d4b, 0x0078, 0x2149,
+ 0x107e, 0x007e, 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e,
+ 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1e64,
+ 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1e64,
+ 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b,
+ 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b,
+ 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1e64,
+ 0x1078, 0x1d4b, 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e,
+ 0x1078, 0x1e64, 0x1078, 0x1d4b, 0x1078, 0x1d90, 0x0078, 0x2149,
+ 0x0005, 0x0078, 0x2130, 0xb084, 0x003c, 0x8004, 0x8004, 0x0079,
+ 0x2139, 0x2149, 0x20c6, 0x20ca, 0x20d0, 0x20d6, 0x20dc, 0x20e2,
+ 0x20ea, 0x20f2, 0x20f8, 0x20fe, 0x2106, 0x210e, 0x2116, 0x211e,
+ 0x2128, 0x0008, 0x2133, 0x007f, 0x107f, 0x2091, 0x8001, 0x007c,
+ 0x0c7e, 0x027e, 0x2041, 0x007e, 0x70bc, 0xd09c, 0x0040, 0x215a,
+ 0x2041, 0x007f, 0x2001, 0x010c, 0x203c, 0x727c, 0x82ff, 0x0040,
+ 0x21a5, 0x037e, 0x738c, 0xa38e, 0xffff, 0x00c0, 0x2169, 0x2019,
+ 0x0001, 0x8314, 0xa2e0, 0x7cc0, 0x2c04, 0xa38c, 0x0001, 0x0040,
+ 0x2176, 0xa084, 0xff00, 0x8007, 0x0078, 0x2178, 0xa084, 0x00ff,
+ 0xa70e, 0x0040, 0x219a, 0xa08e, 0x00ff, 0x0040, 0x21a0, 0x2009,
+ 0x0000, 0x1078, 0x2085, 0x1078, 0x37ee, 0x00c0, 0x219d, 0x6004,
+ 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2194, 0x1078, 0x21f7,
+ 0x0040, 0x219d, 0x0078, 0x219a, 0x1078, 0x22fb, 0x1078, 0x221e,
+ 0x0040, 0x219d, 0x8318, 0x0078, 0x2169, 0x738e, 0x0078, 0x21a2,
+ 0x708f, 0xffff, 0x037f, 0x0078, 0x21f4, 0xa780, 0x232f, 0x203c,
+ 0xa7bc, 0xff00, 0x873f, 0x708c, 0xa096, 0xffff, 0x0040, 0x21b7,
+ 0xa812, 0x00c8, 0x21c7, 0x708f, 0xffff, 0x0078, 0x21f1, 0x2009,
+ 0x0000, 0x70bc, 0xd09c, 0x0040, 0x21c2, 0xd094, 0x0040, 0x21c2,
+ 0x2009, 0x007e, 0x2100, 0xa802, 0x20a8, 0x0078, 0x21cb, 0x2008,
+ 0x2810, 0xa202, 0x20a8, 0x2700, 0x157e, 0x017e, 0xa106, 0x0040,
+ 0x21e8, 0x1078, 0x37ee, 0x00c0, 0x21f1, 0x6004, 0xa084, 0x00ff,
+ 0xa086, 0x0006, 0x00c0, 0x21e2, 0x1078, 0x21f7, 0x0040, 0x21f1,
+ 0x0078, 0x21e8, 0x1078, 0x22fb, 0x1078, 0x221e, 0x0040, 0x21f1,
+ 0x017f, 0x8108, 0x157f, 0x00f0, 0x21cb, 0x708f, 0xffff, 0x0078,
+ 0x21f4, 0x017f, 0x157f, 0x718e, 0x027f, 0x0c7f, 0x007c, 0x017e,
+ 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b9c, 0x0040, 0x2219,
+ 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd,
+ 0x2001, 0x0000, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x7088,
+ 0x8000, 0x708a, 0x127f, 0x2009, 0x0004, 0x1078, 0x5c29, 0xa085,
+ 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x017e, 0x077e,
+ 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b9c, 0x0040, 0x2240, 0x2d00,
+ 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001,
+ 0x0002, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x7088, 0x8000,
+ 0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c29, 0xa085, 0x0001,
+ 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, 0x027e, 0x2009,
+ 0x0080, 0x1078, 0x37ee, 0x00c0, 0x2253, 0x1078, 0x2256, 0x0040,
+ 0x2253, 0x70c3, 0xffff, 0x027f, 0x0c7f, 0x007c, 0x017e, 0x077e,
+ 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b9c, 0x0040, 0x2278, 0x2d00,
+ 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001,
+ 0x0002, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x70c4, 0x8000,
+ 0x70c6, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c29, 0xa085, 0x0001,
+ 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, 0x0d7e, 0x2009,
+ 0x007f, 0x1078, 0x37ee, 0x00c0, 0x2296, 0x2c68, 0x1078, 0x5b9c,
+ 0x0040, 0x2296, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a,
+ 0x2009, 0x0022, 0x1078, 0x5c29, 0xa085, 0x0001, 0x0d7f, 0x0c7f,
+ 0x007c, 0x0e7e, 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078, 0x4969,
+ 0x1078, 0x4919, 0x1078, 0x6103, 0x20a9, 0x007f, 0x2009, 0x0000,
+ 0x017e, 0x1078, 0x3825, 0x00c0, 0x22b1, 0x1078, 0x39a6, 0x1078,
+ 0x3621, 0x017f, 0x8108, 0x00f0, 0x22a8, 0x027f, 0x037f, 0x067f,
+ 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e,
+ 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x4962,
+ 0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b, 0x017f, 0x2e60, 0x1078,
+ 0x39a6, 0x6210, 0x6314, 0x1078, 0x3621, 0x6212, 0x6316, 0x017f,
+ 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x6018,
+ 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x22f1, 0x2071, 0x7600,
+ 0x7088, 0xa005, 0x0040, 0x22ee, 0x8001, 0x708a, 0x007f, 0x0e7f,
+ 0x007c, 0x2071, 0x7600, 0x70c4, 0xa005, 0x0040, 0x22ee, 0x8001,
+ 0x70c6, 0x0078, 0x22ee, 0x6000, 0xc08c, 0x6002, 0x007c, 0x0e7e,
+ 0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x81ff, 0x00c0, 0x230c,
+ 0x20a9, 0x0001, 0x0078, 0x2310, 0x20a9, 0x007f, 0x2011, 0x0000,
+ 0x027e, 0xa2e0, 0x7720, 0x2c64, 0x8cff, 0x0040, 0x2322, 0x2019,
+ 0x0029, 0x1078, 0x4962, 0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b,
+ 0x1078, 0x39a6, 0x027f, 0x8210, 0x00f0, 0x2310, 0x027e, 0x027f,
+ 0x157f, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x7eef,
+ 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9,
+ 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd,
+ 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3,
+ 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2,
+ 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7,
+ 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098,
+ 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080,
+ 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072,
+ 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067,
+ 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055,
+ 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b,
+ 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a,
+ 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e,
+ 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025,
+ 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010,
+ 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800,
+ 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400,
+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200,
+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000,
+ 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000,
+ 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000,
+ 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000,
+ 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000,
+ 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000,
+ 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000,
+ 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000,
+ 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000,
+ 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500,
+ 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100,
+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000,
+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071,
+ 0x766d, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e,
+ 0x7033, 0x767d, 0x7037, 0x767d, 0x7007, 0x0001, 0x2061, 0x76bd,
+ 0x6003, 0x0002, 0x007c, 0x0090, 0x2456, 0x0068, 0x2456, 0x2071,
+ 0x766d, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2456, 0x2a60, 0x7820,
+ 0xa08e, 0x0069, 0x00c0, 0x253d, 0x0079, 0x24da, 0x007c, 0x2071,
+ 0x766d, 0x7004, 0x0079, 0x245c, 0x2460, 0x2461, 0x246b, 0x247d,
+ 0x007c, 0x0090, 0x246a, 0x0068, 0x246a, 0x2b78, 0x7818, 0xd084,
+ 0x0040, 0x2489, 0x007c, 0x2b78, 0x2061, 0x76bd, 0x6008, 0xa08e,
+ 0x0100, 0x0040, 0x2478, 0xa086, 0x0200, 0x0040, 0x2535, 0x007c,
+ 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068, 0x6834,
+ 0xa086, 0x0103, 0x0040, 0x2485, 0x007c, 0x2a60, 0x2b78, 0x7018,
+ 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2492, 0x61b0,
+ 0x0079, 0x249a, 0x2100, 0xa08a, 0x0036, 0x00c8, 0x2531, 0x61b0,
+ 0x0079, 0x24da, 0x2513, 0x2545, 0x254d, 0x2551, 0x2559, 0x255f,
+ 0x2563, 0x256c, 0x2570, 0x2578, 0x257c, 0x2531, 0x2531, 0x2531,
+ 0x2580, 0x2531, 0x2590, 0x25a7, 0x25be, 0x263a, 0x263f, 0x266c,
+ 0x26b9, 0x26c8, 0x26e9, 0x271f, 0x2729, 0x2736, 0x2749, 0x2761,
+ 0x276a, 0x27a7, 0x27ad, 0x2531, 0x27bd, 0x2531, 0x2531, 0x2531,
+ 0x2531, 0x2531, 0x27c1, 0x27c7, 0x2531, 0x2531, 0x2531, 0x2531,
+ 0x2531, 0x2531, 0x2531, 0x2531, 0x27cf, 0x2531, 0x2531, 0x2531,
+ 0x2531, 0x2531, 0x27dc, 0x27e2, 0x2531, 0x2531, 0x2531, 0x2531,
+ 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531,
+ 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531,
+ 0x2531, 0x2531, 0x2578, 0x257c, 0x2531, 0x2531, 0x27f4, 0x2531,
+ 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531,
+ 0x2531, 0x2531, 0x2841, 0x290e, 0x2922, 0x2929, 0x298c, 0x29e7,
+ 0x29f2, 0x2a34, 0x2a41, 0x2a4e, 0x2a51, 0x27f8, 0x2a7a, 0x2ac1,
+ 0x2ace, 0x2bc8, 0x2cb6, 0x2cdd, 0x2dd5, 0x2de3, 0x2df0, 0x2e2a,
+ 0x713c, 0x0078, 0x2513, 0x2021, 0x4000, 0x1078, 0x2d24, 0x127e,
+ 0x2091, 0x8000, 0x0068, 0x2520, 0x7818, 0xd084, 0x0040, 0x2523,
+ 0x127f, 0x0078, 0x2517, 0x781b, 0x0001, 0x7c22, 0x7926, 0x7a2a,
+ 0x7b2e, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x127f,
+ 0x007c, 0x2021, 0x4001, 0x0078, 0x2515, 0x2021, 0x4002, 0x0078,
+ 0x2515, 0x2021, 0x4003, 0x0078, 0x2515, 0x2021, 0x4005, 0x0078,
+ 0x2515, 0x2021, 0x4006, 0x0078, 0x2515, 0xa02e, 0x2520, 0x7b28,
+ 0x7a2c, 0x7824, 0x7930, 0x0078, 0x2d33, 0x7823, 0x0004, 0x7824,
+ 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078,
+ 0x2d37, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, 0x2513, 0x7924,
+ 0x2114, 0x0078, 0x2513, 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9,
+ 0x0007, 0x53a3, 0x0078, 0x2513, 0x7824, 0x2060, 0x0078, 0x2582,
+ 0x2009, 0x0001, 0x2011, 0x000f, 0x2019, 0x0013, 0x0078, 0x2513,
+ 0x7d38, 0x7c3c, 0x0078, 0x2547, 0x7d38, 0x7c3c, 0x0078, 0x2553,
+ 0x2061, 0x1000, 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109,
+ 0x00c0, 0x2584, 0x2010, 0xa005, 0x0040, 0x2513, 0x0078, 0x2539,
+ 0x2061, 0x7651, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2541, 0x8019,
+ 0x0040, 0x2541, 0x604a, 0x6142, 0x782c, 0x6052, 0x7828, 0x6056,
+ 0xa006, 0x605a, 0x605e, 0x1078, 0x3c71, 0x0078, 0x2513, 0x2061,
+ 0x7651, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2541, 0x8019, 0x0040,
+ 0x2541, 0x604e, 0x6146, 0x782c, 0x6062, 0x7828, 0x6066, 0xa006,
+ 0x606a, 0x606e, 0x1078, 0x3a47, 0x0078, 0x2513, 0xa02e, 0x2520,
+ 0x81ff, 0x00c0, 0x253d, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005,
+ 0x20a1, 0x7674, 0x41a1, 0x1078, 0x2cfb, 0x0040, 0x253d, 0x2009,
+ 0x0020, 0x1078, 0x2d33, 0x701b, 0x25d6, 0x007c, 0x6834, 0x2008,
+ 0xa084, 0x00ff, 0xa096, 0x0011, 0x0040, 0x25e2, 0xa096, 0x0019,
+ 0x00c0, 0x253d, 0x810f, 0xa18c, 0x00ff, 0x0040, 0x253d, 0x710e,
+ 0x700c, 0x8001, 0x0040, 0x2613, 0x700e, 0x1078, 0x2cfb, 0x0040,
+ 0x253d, 0x2009, 0x0020, 0x2061, 0x76bd, 0x6224, 0x6328, 0x642c,
+ 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
+ 0x0000, 0x1078, 0x2d33, 0x701b, 0x2606, 0x007c, 0x6834, 0xa084,
+ 0x00ff, 0xa096, 0x0002, 0x0040, 0x2611, 0xa096, 0x000a, 0x00c0,
+ 0x253d, 0x0078, 0x25e8, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a,
+ 0x1078, 0x3722, 0x00c0, 0x2621, 0x7007, 0x0003, 0x701b, 0x2623,
+ 0x007c, 0x1078, 0x3b0a, 0x127e, 0x2091, 0x8000, 0x20a9, 0x0005,
+ 0x2099, 0x7674, 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1,
+ 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x127f,
+ 0x0078, 0x2d37, 0x6198, 0x7824, 0x609a, 0x0078, 0x2513, 0x2091,
+ 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f,
+ 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061,
+ 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a,
+ 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000,
+ 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, 0x00f0, 0xa08a, 0x0003,
+ 0x00c8, 0x0427, 0x0078, 0x0423, 0x81ff, 0x00c0, 0x253d, 0x1078,
+ 0x2d13, 0x0040, 0x2541, 0x7c28, 0x7d2c, 0x1078, 0x3969, 0xd28c,
+ 0x00c0, 0x267e, 0x1078, 0x38f9, 0x0078, 0x2680, 0x1078, 0x3935,
+ 0x00c0, 0x26aa, 0x2061, 0x7d00, 0x127e, 0x2091, 0x8000, 0x6000,
+ 0xa086, 0x0000, 0x0040, 0x2698, 0x6010, 0xa06d, 0x0040, 0x2698,
+ 0x683c, 0xa406, 0x00c0, 0x2698, 0x6840, 0xa506, 0x0040, 0x26a3,
+ 0x127f, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8,
+ 0x253d, 0x0078, 0x2684, 0x1078, 0x6738, 0x127f, 0x0040, 0x253d,
+ 0x0078, 0x2513, 0xa00e, 0x2001, 0x0005, 0x1078, 0x3b0a, 0x127e,
+ 0x2091, 0x8000, 0x1078, 0x6b47, 0x1078, 0x3a7a, 0x127f, 0x0078,
+ 0x2513, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541,
+ 0x1078, 0x38ae, 0x1078, 0x397a, 0x0040, 0x253d, 0x0078, 0x2513,
+ 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x2031,
+ 0x000f, 0x1078, 0x38ae, 0x8631, 0x00c8, 0x26d1, 0x2019, 0x0005,
+ 0x1078, 0x399b, 0x0040, 0x253d, 0x7828, 0xa08a, 0x1000, 0x00c8,
+ 0x2541, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x457b, 0x0078,
+ 0x2513, 0x127e, 0x2091, 0x8000, 0x81ff, 0x00c0, 0x2719, 0x2029,
+ 0x00ff, 0x644c, 0x2400, 0xa506, 0x0040, 0x2713, 0x2508, 0x1078,
+ 0x3825, 0x00c0, 0x2713, 0x2031, 0x000f, 0x1078, 0x38ae, 0x8631,
+ 0x00c8, 0x26fd, 0x2019, 0x0004, 0x1078, 0x399b, 0x0040, 0x2719,
+ 0x7824, 0xa08a, 0x1000, 0x00c8, 0x271c, 0x8003, 0x800b, 0x810b,
+ 0xa108, 0x1078, 0x457b, 0x8529, 0x00c8, 0x26f2, 0x127f, 0x0078,
+ 0x2513, 0x127f, 0x0078, 0x253d, 0x127f, 0x0078, 0x2541, 0x1078,
+ 0x2d13, 0x0040, 0x2541, 0x1078, 0x38de, 0x1078, 0x3969, 0x0078,
+ 0x2513, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541,
+ 0x1078, 0x38c7, 0x1078, 0x3969, 0x0078, 0x2513, 0x81ff, 0x00c0,
+ 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x3938, 0x0040,
+ 0x253d, 0x1078, 0x376a, 0x1078, 0x38f2, 0x1078, 0x3969, 0x0078,
+ 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x38ae, 0x62a0,
+ 0x2019, 0x0005, 0x0c7e, 0x1078, 0x39a6, 0x0c7f, 0x1078, 0x4962,
+ 0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b, 0x1078, 0x3969, 0x0078,
+ 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x3969, 0x2208,
+ 0x0078, 0x2513, 0x157e, 0x0d7e, 0x0e7e, 0x2069, 0x76ff, 0x6810,
+ 0x6914, 0xa10a, 0x00c8, 0x2776, 0x2009, 0x0000, 0x6816, 0x2011,
+ 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069, 0x7720, 0x2d04,
+ 0xa075, 0x0040, 0x278b, 0x704c, 0x1078, 0x2795, 0xa210, 0x7080,
+ 0x1078, 0x2795, 0xa318, 0x8d68, 0x00f0, 0x277f, 0x2300, 0xa218,
+ 0x0e7f, 0x0d7f, 0x157f, 0x0078, 0x2513, 0x0f7e, 0x017e, 0xa07d,
+ 0x0040, 0x27a4, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0040,
+ 0x27a4, 0x2178, 0x0078, 0x279c, 0x017f, 0x0f7f, 0x007c, 0x2069,
+ 0x76ff, 0x6910, 0x629c, 0x0078, 0x2513, 0x81ff, 0x00c0, 0x253d,
+ 0x614c, 0xa190, 0x232f, 0x2214, 0xa294, 0x00ff, 0x6068, 0xa084,
+ 0xff00, 0xa215, 0x6364, 0x0078, 0x2513, 0x613c, 0x6240, 0x0078,
+ 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x0078, 0x2513, 0x1078,
+ 0x2d13, 0x0040, 0x2541, 0x6244, 0x6338, 0x0078, 0x2513, 0x613c,
+ 0x6240, 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0x7651, 0x831f,
+ 0xa305, 0x6816, 0x0078, 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541,
+ 0x0078, 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x7828, 0xa00d,
+ 0x0040, 0x2541, 0x782c, 0xa005, 0x0040, 0x2541, 0x6244, 0x6146,
+ 0x6338, 0x603a, 0x0078, 0x2513, 0x7d38, 0x7c3c, 0x0078, 0x25c0,
+ 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x253d, 0x624c,
+ 0xa084, 0xff00, 0x8007, 0xa206, 0x00c0, 0x2810, 0x2001, 0x7640,
+ 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2d37,
+ 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x6004,
+ 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x253d, 0x0c7e, 0x1078,
+ 0x2cfb, 0x0c7f, 0x0040, 0x253d, 0x6837, 0x0000, 0x6838, 0xc0fd,
+ 0x683a, 0x1078, 0x6a41, 0x0040, 0x253d, 0x7007, 0x0003, 0x701b,
+ 0x2832, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x253d, 0xad80,
+ 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078,
+ 0x2d37, 0x1078, 0x2cfb, 0x0040, 0x253d, 0x2009, 0x001c, 0x7a2c,
+ 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2d33, 0x701b, 0x2850, 0x007c,
+ 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, 0x2541, 0x6804, 0xd0ac,
+ 0x0040, 0x285d, 0xd0a4, 0x0040, 0x2541, 0xd094, 0x0040, 0x2868,
+ 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, 0xffdf, 0x6106, 0x0c7f,
+ 0xd08c, 0x0040, 0x2873, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18d,
+ 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002,
+ 0x0048, 0x2888, 0xd084, 0x0040, 0x2888, 0x6a28, 0xa28a, 0x007f,
+ 0x00c8, 0x2541, 0xa288, 0x232f, 0x210c, 0xa18c, 0x00ff, 0x6152,
+ 0xd0dc, 0x0040, 0x2891, 0x6828, 0xa08a, 0x007f, 0x00c8, 0x2541,
+ 0x604e, 0x6808, 0xa08a, 0x0100, 0x0048, 0x2541, 0xa08a, 0x0841,
+ 0x00c8, 0x2541, 0xa084, 0x0007, 0x00c0, 0x2541, 0x680c, 0xa005,
+ 0x0040, 0x2541, 0x6810, 0xa005, 0x0040, 0x2541, 0x6848, 0x6940,
+ 0xa10a, 0x00c8, 0x2541, 0x8001, 0x0040, 0x2541, 0x684c, 0x6944,
+ 0xa10a, 0x00c8, 0x2541, 0x8001, 0x0040, 0x2541, 0x20a9, 0x001c,
+ 0x2d98, 0x2069, 0x7651, 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff,
+ 0x613e, 0x8007, 0xa084, 0x00ff, 0x6042, 0x1078, 0x3c71, 0x1078,
+ 0x3a47, 0x6000, 0xa086, 0x0000, 0x00c0, 0x290c, 0x6808, 0x602a,
+ 0x1078, 0x1dea, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f,
+ 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4,
+ 0x0040, 0x28ec, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f,
+ 0x8217, 0x831f, 0x0078, 0x28ee, 0xa084, 0xf0ff, 0x6006, 0x610a,
+ 0x620e, 0x6312, 0x1078, 0x4607, 0x0c7e, 0x2061, 0x0100, 0x602f,
+ 0x0040, 0x602f, 0x0000, 0x0c7f, 0x60b4, 0xa005, 0x0040, 0x2908,
+ 0x6003, 0x0001, 0x2091, 0x301d, 0x1078, 0x357b, 0x0078, 0x290c,
+ 0x6003, 0x0004, 0x2091, 0x301d, 0x0078, 0x2513, 0x6000, 0xa086,
+ 0x0000, 0x0040, 0x253d, 0x2069, 0x7651, 0x7830, 0x6842, 0x7834,
+ 0x6846, 0x2d00, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
+ 0x0078, 0x2d37, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x357b, 0x0078,
+ 0x2513, 0x81ff, 0x00c0, 0x253d, 0x617c, 0x81ff, 0x0040, 0x2943,
+ 0x703f, 0x0000, 0x2001, 0x7cc0, 0x2009, 0x0040, 0x7a2c, 0x7b28,
+ 0x7c3c, 0x7d38, 0x127e, 0x2091, 0x8000, 0x1078, 0x2d37, 0x701b,
+ 0x2510, 0x127f, 0x007c, 0x703f, 0x0001, 0x0d7e, 0x2069, 0x7cc0,
+ 0x20a9, 0x0040, 0x20a1, 0x7cc0, 0x2019, 0xffff, 0x43a4, 0x654c,
+ 0xa588, 0x232f, 0x210c, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011,
+ 0x0002, 0x2100, 0xa506, 0x0040, 0x2975, 0x1078, 0x3825, 0x00c0,
+ 0x2975, 0x6014, 0x821c, 0x0048, 0x296d, 0xa398, 0x7cc0, 0xa085,
+ 0xff00, 0x8007, 0x201a, 0x0078, 0x2974, 0xa398, 0x7cc0, 0x2324,
+ 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080,
+ 0x00c8, 0x297c, 0x0078, 0x2959, 0x8201, 0x8007, 0x2d0c, 0xa105,
+ 0x206a, 0x0d7f, 0x20a9, 0x0040, 0x20a1, 0x7cc0, 0x2099, 0x7cc0,
+ 0x1078, 0x35c4, 0x0078, 0x2932, 0x1078, 0x2d13, 0x0040, 0x2541,
+ 0x0c7e, 0x1078, 0x2cfb, 0x0c7f, 0x0040, 0x253d, 0x2001, 0x7652,
+ 0x2004, 0xd0b4, 0x0040, 0x29b9, 0x6000, 0xd08c, 0x00c0, 0x29b9,
+ 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x29b9, 0x6837,
+ 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x6a79, 0x0040, 0x253d,
+ 0x7007, 0x0003, 0x701b, 0x29b5, 0x007c, 0x1078, 0x2d13, 0x0040,
+ 0x2541, 0x20a9, 0x0029, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3,
+ 0x20a9, 0x0002, 0xac80, 0x0004, 0x2098, 0xad80, 0x0004, 0x20a0,
+ 0x1078, 0x35c4, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80,
+ 0x0006, 0x20a0, 0x1078, 0x35c4, 0x20a9, 0x0004, 0xac80, 0x000a,
+ 0x2098, 0xad80, 0x000a, 0x20a0, 0x1078, 0x35c4, 0x2d00, 0x2009,
+ 0x0029, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2d37, 0x81ff,
+ 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x3985,
+ 0x0078, 0x2513, 0x81ff, 0x00c0, 0x253d, 0x7828, 0xa08a, 0x1000,
+ 0x00c8, 0x2541, 0x1078, 0x2d13, 0x0040, 0x2541, 0x2031, 0x000f,
+ 0x1078, 0x38ae, 0x8631, 0x00c8, 0x2a00, 0x2019, 0x0004, 0x1078,
+ 0x399b, 0x7924, 0x810f, 0x7a28, 0x1078, 0x2a10, 0x0078, 0x2513,
+ 0xa186, 0x00ff, 0x0040, 0x2a18, 0x1078, 0x2a28, 0x0078, 0x2a27,
+ 0x2029, 0x007e, 0x2061, 0x7600, 0x644c, 0x2400, 0xa506, 0x0040,
+ 0x2a24, 0x2508, 0x1078, 0x2a28, 0x8529, 0x00c8, 0x2a1d, 0x007c,
+ 0x1078, 0x3825, 0x00c0, 0x2a33, 0x2200, 0x8003, 0x800b, 0x810b,
+ 0xa108, 0x1078, 0x457b, 0x007c, 0x81ff, 0x00c0, 0x253d, 0x1078,
+ 0x2d13, 0x0040, 0x2541, 0x1078, 0x38ae, 0x1078, 0x3990, 0x0078,
+ 0x2513, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541,
+ 0x1078, 0x38ae, 0x1078, 0x397a, 0x0078, 0x2513, 0x6100, 0x0078,
+ 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x6004, 0xa086, 0x0707,
+ 0x0040, 0x2541, 0x2001, 0x7600, 0x2004, 0xa086, 0x0003, 0x00c0,
+ 0x253d, 0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x2a6a,
+ 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a,
+ 0x6b04, 0x831f, 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200,
+ 0x0078, 0x2513, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0040,
+ 0x2a84, 0x81ff, 0x00c0, 0x253d, 0x7828, 0xa08a, 0x1000, 0x00c8,
+ 0x2541, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0040,
+ 0x2a98, 0xa182, 0x007f, 0x00c8, 0x2541, 0x2100, 0x1078, 0x209a,
+ 0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x2061, 0x7849, 0x601b,
+ 0x0000, 0x601f, 0x0000, 0x2061, 0x0100, 0x6030, 0xa084, 0x00ff,
+ 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009,
+ 0x001e, 0x2011, 0x35a0, 0x1078, 0x45fe, 0x7924, 0xa18c, 0xff00,
+ 0x810f, 0x7a28, 0x1078, 0x2a10, 0x127f, 0x0c7f, 0x027f, 0x0078,
+ 0x2513, 0x7924, 0xa18c, 0xff00, 0x810f, 0x0c7e, 0x1078, 0x37ee,
+ 0x2c08, 0x0c7f, 0x00c0, 0x2541, 0x0078, 0x2513, 0x81ff, 0x00c0,
+ 0x253d, 0x60bc, 0xd09c, 0x0040, 0x253d, 0x1078, 0x2cfb, 0x0040,
+ 0x253d, 0x6823, 0x0000, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
+ 0x1078, 0x2d33, 0x701b, 0x2ae5, 0x007c, 0x2009, 0x0080, 0x1078,
+ 0x3825, 0x00c0, 0x2af2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
+ 0x0040, 0x2af6, 0x2021, 0x400a, 0x0078, 0x2515, 0x0d7e, 0xade8,
+ 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820,
+ 0xa0be, 0x0100, 0x0040, 0x2b68, 0xa0be, 0x0112, 0x0040, 0x2b68,
+ 0xa0be, 0x0113, 0x0040, 0x2b68, 0xa0be, 0x0114, 0x0040, 0x2b68,
+ 0xa0be, 0x0117, 0x0040, 0x2b68, 0xa0be, 0x011a, 0x0040, 0x2b68,
+ 0xa0be, 0x0121, 0x0040, 0x2b5e, 0xa0be, 0x0131, 0x0040, 0x2b5e,
+ 0xa0be, 0x0171, 0x0040, 0x2b68, 0xa0be, 0x0173, 0x0040, 0x2b68,
+ 0xa0be, 0x01a1, 0x00c0, 0x2b31, 0x6830, 0x8007, 0x6832, 0x0078,
+ 0x2b6e, 0xa0be, 0x0212, 0x0040, 0x2b64, 0xa0be, 0x0213, 0x0040,
+ 0x2b64, 0xa0be, 0x0214, 0x0040, 0x2b56, 0xa0be, 0x0217, 0x0040,
+ 0x2b50, 0xa0be, 0x021a, 0x00c0, 0x2b4a, 0x6838, 0x8007, 0x683a,
+ 0x0078, 0x2b68, 0xa0be, 0x0300, 0x0040, 0x2b68, 0x0078, 0x2541,
+ 0xad80, 0x0010, 0x20a9, 0x0007, 0x1078, 0x2ba4, 0xad80, 0x000e,
+ 0x20a9, 0x0001, 0x1078, 0x2ba4, 0x0078, 0x2b68, 0xad80, 0x000c,
+ 0x1078, 0x2bb2, 0x0078, 0x2b6e, 0xad80, 0x000e, 0x1078, 0x2bb2,
+ 0xad80, 0x000c, 0x20a9, 0x0001, 0x1078, 0x2ba4, 0x0c7e, 0x1078,
+ 0x2cfb, 0x0040, 0x2b99, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119,
+ 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, 0x0000,
+ 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, 0x0c7f,
+ 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000,
+ 0x1078, 0x6a5d, 0x0040, 0x253d, 0x7007, 0x0003, 0x701b, 0x2b9d,
+ 0x007c, 0x0c7f, 0x0d7f, 0x0078, 0x253d, 0x6820, 0xa086, 0x8001,
+ 0x0040, 0x253d, 0x0078, 0x2513, 0x017e, 0x2008, 0x2044, 0x8000,
+ 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x00f0, 0x2ba6,
+ 0x017f, 0x007c, 0x017e, 0x0a7e, 0x0b7e, 0x2008, 0x2044, 0x8000,
+ 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108, 0x2a0a,
+ 0x8108, 0x290a, 0x8108, 0x280a, 0x0b7f, 0x0a7f, 0x017f, 0x007c,
+ 0x81ff, 0x00c0, 0x253d, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f,
+ 0xa182, 0x0080, 0x0048, 0x2541, 0xa182, 0x00ff, 0x00c8, 0x2541,
+ 0x7a2c, 0x7b28, 0x6064, 0xa306, 0x00c0, 0x2be6, 0x6068, 0xa24e,
+ 0x0040, 0x2541, 0xa9cc, 0xff00, 0x0040, 0x2541, 0x0c7e, 0x1078,
+ 0x2c5a, 0x2c68, 0x0c7f, 0x0040, 0x2c0d, 0xa0c6, 0x4000, 0x00c0,
+ 0x2bf3, 0x0078, 0x2c0a, 0xa0c6, 0x4007, 0x00c0, 0x2bfa, 0x2408,
+ 0x0078, 0x2c0a, 0xa0c6, 0x4008, 0x00c0, 0x2c02, 0x2708, 0x2610,
+ 0x0078, 0x2c0a, 0xa0c6, 0x4009, 0x00c0, 0x2c08, 0x0078, 0x2c0a,
+ 0x2001, 0x4006, 0x2020, 0x0078, 0x2515, 0x017e, 0x0b7e, 0x0c7e,
+ 0x0e7e, 0x2c70, 0x1078, 0x5b9c, 0x0040, 0x2c48, 0x2d00, 0x601a,
+ 0x2e58, 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x2cfb, 0x0c7f, 0x2b70,
+ 0x0040, 0x253d, 0x6837, 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000,
+ 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x22bb,
+ 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001,
+ 0x0002, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x7088, 0x8000,
+ 0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c29, 0xa085, 0x0001,
+ 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x0040, 0x253d, 0x7007, 0x0003,
+ 0x701b, 0x2c53, 0x007c, 0x6830, 0xa086, 0x0100, 0x00c0, 0x2513,
+ 0x0078, 0x253d, 0x0e7e, 0x0d7e, 0x2029, 0x0000, 0x2021, 0x0080,
+ 0x20a9, 0x007f, 0x2071, 0x77a0, 0x2e04, 0xa005, 0x00c0, 0x2c6e,
+ 0x2100, 0xa406, 0x0040, 0x2cab, 0x0078, 0x2c9f, 0x2068, 0x6f10,
+ 0x2700, 0xa306, 0x00c0, 0x2c90, 0x6e14, 0x2600, 0xa206, 0x00c0,
+ 0x2c90, 0x2400, 0xa106, 0x00c0, 0x2c8c, 0x2d60, 0xd884, 0x0040,
+ 0x2cb1, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2cb1,
+ 0x2001, 0x4000, 0x0078, 0x2cb2, 0x2001, 0x4007, 0x0078, 0x2cb2,
+ 0x2400, 0xa106, 0x00c0, 0x2c9f, 0x6e14, 0x87ff, 0x00c0, 0x2c9b,
+ 0x86ff, 0x0040, 0x2cab, 0x2001, 0x4008, 0x0078, 0x2cb2, 0x8420,
+ 0x8e70, 0x00f0, 0x2c64, 0x2001, 0x4009, 0x0078, 0x2cb2, 0x2001,
+ 0x0001, 0x0078, 0x2cb2, 0x1078, 0x37ee, 0x00c0, 0x2ca7, 0x6312,
+ 0x6216, 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, 0x00c0,
+ 0x253d, 0x1078, 0x2cfb, 0x0040, 0x253d, 0x6837, 0x0000, 0x7824,
+ 0xa005, 0x0040, 0x2541, 0xa096, 0x00ff, 0x0040, 0x2ccb, 0xa092,
+ 0x0004, 0x00c8, 0x2541, 0x2010, 0x2d18, 0x1078, 0x227d, 0x0040,
+ 0x253d, 0x7007, 0x0003, 0x701b, 0x2cd6, 0x007c, 0x6830, 0xa086,
+ 0x0100, 0x0040, 0x253d, 0x0078, 0x2513, 0x81ff, 0x00c0, 0x253d,
+ 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, 0x2541,
+ 0xa182, 0x00ff, 0x00c8, 0x2541, 0x127e, 0x2091, 0x8000, 0x1078,
+ 0x697f, 0x00c0, 0x2cf8, 0x1078, 0x380d, 0x127f, 0x0078, 0x2513,
+ 0x127f, 0x0078, 0x253d, 0x1078, 0x132f, 0x0040, 0x2d12, 0xa006,
+ 0x6802, 0x7010, 0xa005, 0x00c0, 0x2d0a, 0x2d00, 0x7012, 0x7016,
+ 0x0078, 0x2d10, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016,
+ 0xad80, 0x000d, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x1078,
+ 0x3825, 0x00c0, 0x2d21, 0xa6b4, 0x00ff, 0xa682, 0x0010, 0x0048,
+ 0x2d22, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, 0x0040,
+ 0x2d2f, 0x2168, 0x6904, 0x1078, 0x1348, 0x0078, 0x2d26, 0x7112,
+ 0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x2d39, 0x2031,
+ 0x0000, 0x2061, 0x76bd, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a,
+ 0x642e, 0x6532, 0x2c10, 0x1078, 0x137f, 0x7007, 0x0002, 0x701b,
+ 0x2513, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, 0x0000,
+ 0x2001, 0x767b, 0x2004, 0xa005, 0x00c0, 0x2d65, 0x0068, 0x2d65,
+ 0x7818, 0xd084, 0x00c0, 0x2d65, 0x781b, 0x0001, 0x7a22, 0x7b26,
+ 0x7c2a, 0x2091, 0x4080, 0x0078, 0x2d8a, 0x017e, 0x0c7e, 0x0e7e,
+ 0x2071, 0x766d, 0x7138, 0xa182, 0x0008, 0x0048, 0x2d73, 0x7030,
+ 0x2060, 0x0078, 0x2d84, 0x7030, 0xa0e0, 0x0008, 0xac82, 0x76bd,
+ 0x0048, 0x2d7c, 0x2061, 0x767d, 0x2c00, 0x7032, 0x81ff, 0x00c0,
+ 0x2d82, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x0e7f,
+ 0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, 0x766d,
+ 0x7038, 0xa005, 0x0040, 0x2dc6, 0x127e, 0x2091, 0x8000, 0x0068,
+ 0x2dc5, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x2dc4,
+ 0x0c7e, 0x781b, 0x0001, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004,
+ 0x7826, 0x6008, 0x782a, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a,
+ 0xa005, 0x00c0, 0x2dba, 0x7033, 0x767d, 0x7037, 0x767d, 0x0c7f,
+ 0x0078, 0x2dc4, 0xac80, 0x0008, 0xa0fa, 0x76bd, 0x0048, 0x2dc2,
+ 0x2001, 0x767d, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, 0x007c,
+ 0x027e, 0x2001, 0x7652, 0x2004, 0xd0c4, 0x0040, 0x2dd3, 0x2011,
+ 0x8014, 0x1078, 0x2d4a, 0x027f, 0x007c, 0x81ff, 0x00c0, 0x253d,
+ 0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x1078, 0x357b,
+ 0x127f, 0x0078, 0x2513, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x00c0,
+ 0x2dee, 0x61c8, 0xa10d, 0x61ca, 0x0078, 0x2513, 0x0078, 0x2541,
+ 0x81ff, 0x00c0, 0x253d, 0x6000, 0xa086, 0x0003, 0x00c0, 0x253d,
+ 0x2001, 0x7652, 0x2004, 0xd0a4, 0x00c0, 0x253d, 0x1078, 0x2d13,
+ 0x0040, 0x2541, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0,
+ 0x2e0d, 0x7828, 0xa005, 0x0040, 0x2513, 0x0c7e, 0x1078, 0x2cfb,
+ 0x0c7f, 0x0040, 0x253d, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838,
+ 0xc0fd, 0x683a, 0x1078, 0x6ae6, 0x0040, 0x253d, 0x7007, 0x0003,
+ 0x701b, 0x2e23, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x253d,
+ 0x0078, 0x2513, 0x2001, 0x7600, 0x2004, 0xa086, 0x0003, 0x00c0,
+ 0x253d, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2cfb,
+ 0x0040, 0x253d, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000,
+ 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078, 0x3825,
+ 0x00c0, 0x2e70, 0x6004, 0xa0c6, 0x0707, 0x0040, 0x2e70, 0xa084,
+ 0x00ff, 0xa0c6, 0x0006, 0x00c0, 0x2e70, 0x87ff, 0x0040, 0x2e63,
+ 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078,
+ 0x2bb2, 0x0078, 0x2e6c, 0xac80, 0x000a, 0x2098, 0x3400, 0x20a9,
+ 0x0004, 0x53a3, 0x1078, 0x2bb2, 0x21a2, 0x94a0, 0xa6b0, 0x0005,
+ 0x8108, 0xa186, 0x007e, 0x0040, 0x2e7b, 0xa686, 0x0028, 0x0040,
+ 0x2e84, 0x0078, 0x2e46, 0x86ff, 0x00c0, 0x2e82, 0x7120, 0x810b,
+ 0x0078, 0x2513, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, 0x7022,
+ 0x772a, 0x2061, 0x76bd, 0x6007, 0x0000, 0x6612, 0x7024, 0x600e,
+ 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x137f, 0x7007,
+ 0x0002, 0x701b, 0x2e9c, 0x007c, 0x702c, 0xa005, 0x00c0, 0x2eae,
+ 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, 0x76bd,
+ 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x2e46, 0x7120, 0x810b,
+ 0x0078, 0x2513, 0x127e, 0x0c7e, 0x0e7e, 0x2061, 0x0100, 0x2071,
+ 0x7600, 0x6044, 0xd0a4, 0x00c0, 0x2edb, 0xd084, 0x0040, 0x2ec4,
+ 0x1078, 0x3004, 0x0078, 0x2ed7, 0xd08c, 0x0040, 0x2ecb, 0x1078,
+ 0x2f1b, 0x0078, 0x2ed7, 0xd094, 0x0040, 0x2ed2, 0x1078, 0x2efe,
+ 0x0078, 0x2ed7, 0xd09c, 0x0040, 0x2ed7, 0x1078, 0x2ee5, 0x0e7f,
+ 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, 0x00c0, 0x2ee2,
+ 0xc19d, 0x612a, 0x017f, 0x0078, 0x2ed7, 0x6043, 0x0040, 0x6043,
+ 0x0000, 0x706f, 0x0000, 0x7087, 0x0001, 0x70a7, 0x0000, 0x2009,
+ 0x7cc0, 0x200b, 0x0000, 0x707f, 0x0000, 0x7073, 0x000f, 0x2009,
+ 0x000f, 0x2011, 0x353b, 0x1078, 0x45fe, 0x007c, 0x7070, 0xa005,
+ 0x00c0, 0x2f1a, 0x2011, 0x353b, 0x1078, 0x456e, 0x6043, 0x0020,
+ 0x6043, 0x0000, 0x6044, 0xd08c, 0x00c0, 0x2f16, 0x7083, 0x0000,
+ 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x2f1a, 0x7077, 0x0000,
+ 0x0078, 0x2f1a, 0x007c, 0x7074, 0xa08a, 0x0003, 0x00c8, 0x2f24,
+ 0x1079, 0x2f27, 0x0078, 0x2f26, 0x1078, 0x12d5, 0x007c, 0x2f2a,
+ 0x2f79, 0x3003, 0x0f7e, 0x7077, 0x0001, 0x20e1, 0xa000, 0x20e1,
+ 0x8700, 0x1078, 0x1dea, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079,
+ 0x7b00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, 0x780f,
+ 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, 0x781f,
+ 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, 0x782f,
+ 0x0000, 0x2079, 0x7b0c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099,
+ 0x7605, 0x20a1, 0x7b0e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0x7b12,
+ 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0x7b00, 0x20a1, 0x020b,
+ 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x1078,
+ 0x3562, 0x0f7f, 0x707b, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000,
+ 0x007c, 0x0d7e, 0x7078, 0x707b, 0x0000, 0xa025, 0x0040, 0x2fed,
+ 0x6020, 0xd0b4, 0x00c0, 0x2feb, 0x7184, 0x81ff, 0x0040, 0x2fd4,
+ 0xa486, 0x000c, 0x00c0, 0x2fdf, 0xa480, 0x0018, 0x8004, 0x20a8,
+ 0x2011, 0x7b80, 0x2019, 0x7b00, 0x220c, 0x2304, 0xa106, 0x00c0,
+ 0x2fab, 0x8210, 0x8318, 0x00f0, 0x2f94, 0x6043, 0x0004, 0x608b,
+ 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x7077, 0x0002, 0x7083,
+ 0x0002, 0x0078, 0x2feb, 0x2069, 0x7b80, 0x6930, 0xa18e, 0x1101,
+ 0x00c0, 0x2fdf, 0x6834, 0xa005, 0x00c0, 0x2fdf, 0x6900, 0xa18c,
+ 0x00ff, 0x00c0, 0x2fbf, 0x6804, 0xa005, 0x0040, 0x2fd4, 0x2011,
+ 0x7b8e, 0x2019, 0x7605, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102,
+ 0x0048, 0x2fd2, 0x00c0, 0x2fdf, 0x8210, 0x8318, 0x00f0, 0x2fc5,
+ 0x0078, 0x2fdf, 0x7087, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000,
+ 0x2099, 0x7b80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043,
+ 0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x2feb, 0x60c3,
+ 0x000c, 0x1078, 0x3562, 0x0d7f, 0x007c, 0x6020, 0xd0b4, 0x00c0,
+ 0x2feb, 0x60c3, 0x000c, 0x2011, 0x7840, 0x2013, 0x0000, 0x707b,
+ 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078,
+ 0x5579, 0x0078, 0x2feb, 0x007c, 0x7080, 0xa08a, 0x001d, 0x00c8,
+ 0x300d, 0x1079, 0x3010, 0x0078, 0x300f, 0x1078, 0x12d5, 0x007c,
+ 0x3034, 0x3043, 0x3074, 0x3089, 0x30b9, 0x30e1, 0x3111, 0x313b,
+ 0x316b, 0x3191, 0x31da, 0x31fc, 0x3220, 0x3236, 0x325e, 0x3271,
+ 0x327a, 0x3293, 0x32c1, 0x32e9, 0x3317, 0x3341, 0x3384, 0x33b5,
+ 0x33d7, 0x3415, 0x343b, 0x3454, 0x3461, 0x7003, 0x0007, 0x6004,
+ 0xa084, 0xfff9, 0x6006, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0,
+ 0x6043, 0x0002, 0x7083, 0x0001, 0x2009, 0x07d0, 0x2011, 0x3542,
+ 0x1078, 0x4561, 0x007c, 0x0f7e, 0x7078, 0xa086, 0x0014, 0x00c0,
+ 0x3072, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3072, 0x2079,
+ 0x7b80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3070, 0x7834, 0xa005,
+ 0x00c0, 0x3070, 0x7a38, 0xd2fc, 0x0040, 0x3066, 0x70a4, 0xa005,
+ 0x00c0, 0x3066, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x2011, 0x3542,
+ 0x1078, 0x456e, 0x7083, 0x0010, 0x1078, 0x327a, 0x0078, 0x3072,
+ 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0003, 0x6043, 0x0004,
+ 0x1078, 0x35cc, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a,
+ 0x20a3, 0x0000, 0x00f0, 0x3080, 0x60c3, 0x0014, 0x1078, 0x3562,
+ 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x30b7, 0x2011, 0x3542,
+ 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x30b3, 0x2079, 0x7b80,
+ 0x7a30, 0xa296, 0x1102, 0x00c0, 0x30b3, 0x7834, 0xa005, 0x00c0,
+ 0x30b3, 0x7a38, 0xd2fc, 0x0040, 0x30ad, 0x70a4, 0xa005, 0x00c0,
+ 0x30ad, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, 0x0004, 0x1078,
+ 0x30b9, 0x0078, 0x30b7, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f,
+ 0x007c, 0x7083, 0x0005, 0x1078, 0x35cc, 0x20a3, 0x1103, 0x20a3,
+ 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, 0xa005, 0x00c0, 0x30d3,
+ 0x714c, 0xa186, 0xffff, 0x0040, 0x30d3, 0x1078, 0x3506, 0x0040,
+ 0x30d3, 0x1078, 0x35fb, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6,
+ 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562,
+ 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x310f, 0x2011, 0x3542,
+ 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x310b, 0x2079, 0x7b80,
+ 0x7a30, 0xa296, 0x1103, 0x00c0, 0x310b, 0x7834, 0xa005, 0x00c0,
+ 0x310b, 0x7a38, 0xd2fc, 0x0040, 0x3105, 0x70a4, 0xa005, 0x00c0,
+ 0x3105, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, 0x0006, 0x1078,
+ 0x3111, 0x0078, 0x310f, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f,
+ 0x007c, 0x7083, 0x0007, 0x1078, 0x35cc, 0x20a3, 0x1104, 0x20a3,
+ 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, 0xa005, 0x00c0, 0x312d,
+ 0x7150, 0xa186, 0xffff, 0x0040, 0x312d, 0xa180, 0x232f, 0x200c,
+ 0xa18c, 0xff00, 0x810f, 0x1078, 0x3506, 0x20a9, 0x0008, 0x2298,
+ 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
+ 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3169,
+ 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x3165,
+ 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3165, 0x7834,
+ 0xa005, 0x00c0, 0x3165, 0x7a38, 0xd2fc, 0x0040, 0x315f, 0x70a4,
+ 0xa005, 0x00c0, 0x315f, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083,
+ 0x0008, 0x1078, 0x316b, 0x0078, 0x3169, 0x7083, 0x0002, 0x707b,
+ 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0009, 0x1078, 0x35cc, 0x20a3,
+ 0x1105, 0x20a3, 0x0100, 0x3430, 0x706c, 0xa005, 0x00c0, 0x317e,
+ 0x1078, 0x3470, 0x0040, 0x318e, 0x0078, 0x3188, 0x20a9, 0x0008,
+ 0x2099, 0x7b8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
+ 0x60c3, 0x0014, 0x1078, 0x3562, 0x0078, 0x3190, 0x1078, 0x302d,
+ 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x31d8, 0x2011, 0x3542,
+ 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x31d4, 0x2079, 0x7b80,
+ 0x7a30, 0xa296, 0x1105, 0x00c0, 0x31d4, 0x7834, 0x2011, 0x0100,
+ 0xa21e, 0x00c0, 0x31bd, 0x7a38, 0xd2fc, 0x0040, 0x31b7, 0x70a4,
+ 0xa005, 0x00c0, 0x31b7, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083,
+ 0x000a, 0x1078, 0x31da, 0x0078, 0x31d8, 0xa005, 0x00c0, 0x31d4,
+ 0x7a38, 0xd2fc, 0x0040, 0x31cc, 0x70a4, 0xa005, 0x00c0, 0x31cc,
+ 0x1078, 0x35fb, 0x70a7, 0x0001, 0x707f, 0x0000, 0x7083, 0x000e,
+ 0x1078, 0x325e, 0x0078, 0x31d8, 0x7083, 0x0002, 0x707b, 0x0000,
+ 0x0f7f, 0x007c, 0x7083, 0x000b, 0x2011, 0x7b0e, 0x22a0, 0x20a9,
+ 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000,
+ 0x41a4, 0x1078, 0x35cc, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x6030,
+ 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3,
+ 0x0084, 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040,
+ 0x321e, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0084, 0x00c0,
+ 0x321a, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x321a,
+ 0x7834, 0xa005, 0x00c0, 0x321a, 0x7083, 0x000c, 0x1078, 0x3220,
+ 0x0078, 0x321e, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c,
+ 0x7083, 0x000d, 0x1078, 0x35cc, 0x20a3, 0x1107, 0x20a3, 0x0000,
+ 0x2099, 0x7b8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3,
+ 0x0000, 0x60c3, 0x0084, 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078,
+ 0xa005, 0x0040, 0x325c, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086,
+ 0x0084, 0x00c0, 0x3258, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1107,
+ 0x00c0, 0x3258, 0x7834, 0xa005, 0x00c0, 0x3258, 0x707f, 0x0001,
+ 0x1078, 0x35be, 0x7083, 0x000e, 0x1078, 0x325e, 0x0078, 0x325c,
+ 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x000f,
+ 0x707b, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005,
+ 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x3542, 0x1078, 0x4561,
+ 0x007c, 0x7078, 0xa005, 0x0040, 0x3279, 0x2011, 0x3542, 0x1078,
+ 0x456e, 0x007c, 0x7083, 0x0011, 0x20e1, 0x9080, 0x20e1, 0x4000,
+ 0x2099, 0x7b80, 0x20a1, 0x020b, 0x7478, 0xa480, 0x0018, 0xa080,
+ 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014,
+ 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x32bf,
+ 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x32bd,
+ 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x32bd, 0x7834,
+ 0xa005, 0x00c0, 0x32bd, 0x7a38, 0xd2fc, 0x0040, 0x32b7, 0x70a4,
+ 0xa005, 0x00c0, 0x32b7, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083,
+ 0x0012, 0x1078, 0x32c1, 0x0078, 0x32bf, 0x707b, 0x0000, 0x0f7f,
+ 0x007c, 0x7083, 0x0013, 0x1078, 0x35d8, 0x20a3, 0x1103, 0x20a3,
+ 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, 0xa005, 0x00c0, 0x32db,
+ 0x714c, 0xa186, 0xffff, 0x0040, 0x32db, 0x1078, 0x3506, 0x0040,
+ 0x32db, 0x1078, 0x35fb, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6,
+ 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562,
+ 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3315, 0x2011, 0x3542,
+ 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x3313, 0x2079, 0x7b80,
+ 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3313, 0x7834, 0xa005, 0x00c0,
+ 0x3313, 0x7a38, 0xd2fc, 0x0040, 0x330d, 0x70a4, 0xa005, 0x00c0,
+ 0x330d, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, 0x0014, 0x1078,
+ 0x3317, 0x0078, 0x3315, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083,
+ 0x0015, 0x1078, 0x35d8, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430,
+ 0x2011, 0x7b8e, 0x706c, 0xa006, 0x00c0, 0x3333, 0x7150, 0xa186,
+ 0xffff, 0x0040, 0x3333, 0xa180, 0x232f, 0x200c, 0xa18c, 0xff00,
+ 0x810f, 0x1078, 0x3506, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6,
+ 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562,
+ 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3382, 0x2011, 0x3542,
+ 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x3380, 0x2079, 0x7b80,
+ 0x7a30, 0xa296, 0x1105, 0x00c0, 0x3380, 0x7834, 0x2011, 0x0100,
+ 0xa21e, 0x00c0, 0x3369, 0x7a38, 0xd2fc, 0x0040, 0x3367, 0x70a4,
+ 0xa005, 0x00c0, 0x3367, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x0078,
+ 0x337a, 0xa005, 0x00c0, 0x3380, 0x7a38, 0xd2fc, 0x0040, 0x3378,
+ 0x70a4, 0xa005, 0x00c0, 0x3378, 0x1078, 0x35fb, 0x70a7, 0x0001,
+ 0x707f, 0x0000, 0x7083, 0x0016, 0x1078, 0x3384, 0x0078, 0x3382,
+ 0x707b, 0x0000, 0x0f7f, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000,
+ 0x2099, 0x7b80, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, 0x3430,
+ 0x2011, 0x7b8e, 0x7083, 0x0017, 0x0078, 0x3398, 0x7083, 0x001b,
+ 0x706c, 0xa005, 0x00c0, 0x33a2, 0x1078, 0x3470, 0x0040, 0x33b2,
+ 0x0078, 0x33ac, 0x20a9, 0x0008, 0x2099, 0x7b8e, 0x26a0, 0x53a6,
+ 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562,
+ 0x0078, 0x33b4, 0x1078, 0x302d, 0x007c, 0x0f7e, 0x7078, 0xa005,
+ 0x0040, 0x33d5, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0084,
+ 0x00c0, 0x33d3, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1106, 0x00c0,
+ 0x33d3, 0x7834, 0xa005, 0x00c0, 0x33d3, 0x7083, 0x0018, 0x1078,
+ 0x33d7, 0x0078, 0x33d5, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083,
+ 0x0019, 0x1078, 0x35d8, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430,
+ 0x2099, 0x7b8e, 0x2039, 0x7b0e, 0x27a0, 0x20a9, 0x0040, 0x53a3,
+ 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294,
+ 0x00ff, 0x8007, 0xa205, 0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0,
+ 0x7b0e, 0x2414, 0xa38c, 0x0001, 0x0040, 0x3402, 0xa294, 0xff00,
+ 0x0078, 0x3405, 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798,
+ 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
+ 0x60c3, 0x0084, 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005,
+ 0x0040, 0x3439, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0084,
+ 0x00c0, 0x3437, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1107, 0x00c0,
+ 0x3437, 0x7834, 0xa005, 0x00c0, 0x3437, 0x707f, 0x0001, 0x1078,
+ 0x35be, 0x7083, 0x001a, 0x1078, 0x343b, 0x0078, 0x3439, 0x707b,
+ 0x0000, 0x0f7f, 0x007c, 0x7083, 0x001b, 0x20e1, 0x9080, 0x20e1,
+ 0x4000, 0x2099, 0x7b80, 0x20a1, 0x020b, 0x7478, 0xa480, 0x0018,
+ 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3,
+ 0x0084, 0x1078, 0x3562, 0x007c, 0x7078, 0xa005, 0x0040, 0x3460,
+ 0x2011, 0x3542, 0x1078, 0x456e, 0x7083, 0x001c, 0x1078, 0x3461,
+ 0x007c, 0x707b, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043,
+ 0x0001, 0x2009, 0x07d0, 0x2011, 0x3542, 0x1078, 0x4561, 0x007c,
+ 0x087e, 0x097e, 0x2029, 0x7652, 0x252c, 0x20a9, 0x0008, 0x2041,
+ 0x7b0e, 0x28a0, 0x2099, 0x7b8e, 0x53a3, 0x20a9, 0x0008, 0x2011,
+ 0x0007, 0xd5d4, 0x0040, 0x3486, 0x2011, 0x0000, 0x2800, 0xa200,
+ 0x200c, 0xa1a6, 0xffff, 0x00c0, 0x3498, 0xd5d4, 0x0040, 0x3493,
+ 0x8210, 0x0078, 0x3494, 0x8211, 0x00f0, 0x3486, 0x0078, 0x34fd,
+ 0x82ff, 0x00c0, 0x34aa, 0xd5d4, 0x0040, 0x34a4, 0xa1a6, 0x3fff,
+ 0x0040, 0x3490, 0x0078, 0x34a8, 0xa1a6, 0x3fff, 0x0040, 0x34fd,
+ 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0040,
+ 0x34b3, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0040, 0x34ba, 0x8423,
+ 0x0078, 0x34bb, 0x8424, 0x00c8, 0x34c8, 0xd5d4, 0x0040, 0x34c3,
+ 0x8319, 0x0078, 0x34c4, 0x8318, 0x00f0, 0x34b4, 0x0078, 0x34fd,
+ 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x00f0, 0x34cc, 0x2328,
+ 0x8529, 0xa2be, 0x0007, 0x0040, 0x34e0, 0x007e, 0x2039, 0x0007,
+ 0x2200, 0xa73a, 0x007f, 0x27a8, 0xa5a8, 0x0010, 0x00f0, 0x34dc,
+ 0x754e, 0xa5c8, 0x232f, 0x292c, 0xa5ac, 0x00ff, 0x6532, 0x60e7,
+ 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, 0x201a, 0x706f, 0x0001,
+ 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3,
+ 0x0000, 0xa085, 0x0001, 0x0078, 0x3503, 0xa006, 0x0078, 0x3503,
+ 0xa006, 0x1078, 0x12d5, 0x097f, 0x087f, 0x007c, 0x2118, 0x2021,
+ 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0048, 0x3513, 0x8420,
+ 0x8001, 0x0078, 0x350b, 0x2118, 0x84ff, 0x0040, 0x351c, 0xa39a,
+ 0x0010, 0x8421, 0x00c0, 0x3517, 0x2021, 0x0001, 0x83ff, 0x0040,
+ 0x3525, 0x8423, 0x8319, 0x00c0, 0x3521, 0xa238, 0x2704, 0xa42c,
+ 0x00c0, 0x353a, 0xa405, 0x203a, 0x714e, 0xa1a0, 0x232f, 0x242c,
+ 0xa5ac, 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0001,
+ 0xa084, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x7073, 0x0000,
+ 0x0e7f, 0x007c, 0x0e7e, 0x0f7e, 0x2079, 0x0100, 0x2071, 0x0140,
+ 0x1078, 0x5582, 0x7004, 0xa084, 0x4000, 0x0040, 0x3553, 0x7003,
+ 0x1000, 0x7003, 0x0000, 0x127e, 0x2091, 0x8000, 0x2071, 0x7620,
+ 0x2073, 0x0000, 0x7843, 0x0090, 0x7843, 0x0010, 0x127f, 0x0f7f,
+ 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x2011, 0x7840, 0x2013,
+ 0x0000, 0x707b, 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, 0x0056,
+ 0x60a7, 0x9575, 0x1078, 0x5579, 0x2009, 0x07d0, 0x2011, 0x3542,
+ 0x1078, 0x45fe, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091,
+ 0x8000, 0x2009, 0x00f7, 0x1078, 0x35e4, 0x2061, 0x7849, 0x601b,
+ 0x0000, 0x601f, 0x0000, 0x2061, 0x7600, 0x6003, 0x0001, 0x2061,
+ 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011,
+ 0x35a0, 0x1078, 0x4561, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c,
+ 0x0e7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x0100, 0x1078,
+ 0x5582, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, 0x0040, 0x35b4,
+ 0x7003, 0x1000, 0x7003, 0x0000, 0x2001, 0x0001, 0x1078, 0x202b,
+ 0x1078, 0x357b, 0x127f, 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040,
+ 0x20a1, 0x7cc0, 0x2099, 0x7b8e, 0x3304, 0x8007, 0x20a2, 0x9398,
+ 0x94a0, 0x00f0, 0x35c4, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000,
+ 0x2099, 0x7b00, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c,
+ 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7b80, 0x20a1, 0x020b,
+ 0x20a9, 0x000c, 0x53a6, 0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100,
+ 0x810f, 0x2001, 0x762c, 0x2004, 0xa005, 0x00c0, 0x35f5, 0x6030,
+ 0xa084, 0x00ff, 0xa105, 0x0078, 0x35f7, 0xa185, 0x00f7, 0x604a,
+ 0x007f, 0x0c7f, 0x007c, 0x017e, 0x047e, 0x2001, 0x7652, 0x2004,
+ 0xd0a4, 0x0040, 0x360e, 0xa006, 0x2020, 0x2009, 0x002a, 0x1078,
+ 0x7541, 0x2001, 0x760c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a,
+ 0x1078, 0x2299, 0x047f, 0x017f, 0x007c, 0x157e, 0x20a9, 0x00ff,
+ 0x2009, 0x7720, 0xa006, 0x200a, 0x8108, 0x00f0, 0x361b, 0x157f,
+ 0x007c, 0x0d7e, 0x037e, 0x157e, 0x137e, 0x147e, 0x2069, 0x7651,
+ 0xa006, 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198,
+ 0x232f, 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, 0x6814, 0xa084,
+ 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, 0x037f, 0x0d7f, 0x007c,
+ 0x127e, 0x2091, 0x8000, 0x6944, 0xa1b4, 0x00ff, 0xa682, 0x0010,
+ 0x00c8, 0x3715, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8,
+ 0x371b, 0x2001, 0x760c, 0x2004, 0xa084, 0x0003, 0x00c0, 0x36fe,
+ 0xa188, 0x7720, 0x2104, 0xa065, 0x0040, 0x36ec, 0x6004, 0xa084,
+ 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x36f2, 0x6078, 0xa00d, 0x0040,
+ 0x3697, 0xa680, 0x75d5, 0x2004, 0xa10c, 0x00c0, 0x36e6, 0x607c,
+ 0xa00d, 0x0040, 0x36b3, 0xa680, 0x75d5, 0x2004, 0xa10c, 0x0040,
+ 0x36b3, 0x694c, 0xd1fc, 0x00c0, 0x36a9, 0x1078, 0x37ae, 0x0078,
+ 0x36e1, 0x1078, 0x377f, 0x694c, 0xd1ec, 0x00c0, 0x36e1, 0x1078,
+ 0x38c7, 0x0078, 0x36e1, 0x694c, 0xa184, 0xa000, 0x0040, 0x36d1,
+ 0xd1ec, 0x0040, 0x36ca, 0xd1fc, 0x0040, 0x36c2, 0x1078, 0x38de,
+ 0x0078, 0x36cd, 0xa680, 0x75d5, 0x200c, 0x607c, 0xa105, 0x607e,
+ 0x0078, 0x36d1, 0xd1fc, 0x0040, 0x36d1, 0x1078, 0x377f, 0x0078,
+ 0x36e1, 0x6050, 0xa00d, 0x0040, 0x36dc, 0x2d00, 0x200a, 0x6803,
+ 0x0000, 0x6052, 0x0078, 0x36e1, 0x2d00, 0x6052, 0x604e, 0x6803,
+ 0x0000, 0x1078, 0x4844, 0xa006, 0x127f, 0x007c, 0x2001, 0x0005,
+ 0x2009, 0x0000, 0x0078, 0x371f, 0x2001, 0x0028, 0x2009, 0x0000,
+ 0x0078, 0x371f, 0xa082, 0x0006, 0x00c8, 0x36fe, 0x60a0, 0xd0bc,
+ 0x0040, 0x368d, 0x2001, 0x0028, 0x0078, 0x3711, 0x2009, 0x760c,
+ 0x210c, 0xd18c, 0x0040, 0x3708, 0x2001, 0x0004, 0x0078, 0x3711,
+ 0xd184, 0x0040, 0x370f, 0x2001, 0x0004, 0x0078, 0x3711, 0x2001,
+ 0x0029, 0x2009, 0x0000, 0x0078, 0x371f, 0x2001, 0x0029, 0x2009,
+ 0x0000, 0x0078, 0x371f, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005,
+ 0x127f, 0x007c, 0x6944, 0xa1b4, 0x00ff, 0xa682, 0x0010, 0x00c8,
+ 0x3764, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, 0x3754,
+ 0xa188, 0x7720, 0x2104, 0xa065, 0x0040, 0x3754, 0x6004, 0xa084,
+ 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x375a, 0x684c, 0xd0ec, 0x0040,
+ 0x3747, 0x1078, 0x38de, 0x1078, 0x377f, 0x0078, 0x374f, 0x1078,
+ 0x377f, 0x684c, 0xd0fc, 0x0040, 0x374f, 0x1078, 0x38c7, 0x1078,
+ 0x38f2, 0xa006, 0x0078, 0x3768, 0x2001, 0x0028, 0x2009, 0x0000,
+ 0x0078, 0x3768, 0xa082, 0x0006, 0x0048, 0x373d, 0x2001, 0x0029,
+ 0x2009, 0x0000, 0x0078, 0x3768, 0x2001, 0x0029, 0x2009, 0x0000,
+ 0xa005, 0x007c, 0x127e, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0040,
+ 0x3778, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x127f, 0x007c,
+ 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x3776, 0x127e,
+ 0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x378b, 0x6802, 0x2d00,
+ 0x604e, 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000,
+ 0x0078, 0x3789, 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0040,
+ 0x37a0, 0x6800, 0xa005, 0x00c0, 0x379e, 0x6052, 0x604e, 0xad05,
+ 0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x37ad, 0x6800, 0xa005,
+ 0x00c0, 0x37ab, 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, 0x0000,
+ 0x6084, 0xa00d, 0x0040, 0x37b8, 0x2d00, 0x200a, 0x6086, 0x007c,
+ 0x2d00, 0x6086, 0x6082, 0x0078, 0x37b7, 0x127e, 0x0c7e, 0x027e,
+ 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, 0x37cb,
+ 0xc285, 0x0078, 0x37cc, 0xc284, 0x6202, 0x027f, 0x0c7f, 0x127f,
+ 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204,
+ 0xa294, 0xff00, 0xa215, 0x6206, 0x0c7f, 0x127f, 0x007c, 0x127e,
+ 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0xa294, 0x00ff,
+ 0x8007, 0xa215, 0x6206, 0x0c7f, 0x127f, 0x007c, 0x027e, 0xa182,
+ 0x00ff, 0x0048, 0x37f7, 0xa085, 0x0001, 0x0078, 0x380b, 0xa190,
+ 0x7720, 0x2204, 0xa065, 0x00c0, 0x380a, 0x017e, 0x0d7e, 0x1078,
+ 0x1314, 0x2d60, 0x0d7f, 0x017f, 0x0040, 0x37f3, 0x2c00, 0x2012,
+ 0x1078, 0x3621, 0xa006, 0x027f, 0x007c, 0x027e, 0xa182, 0x00ff,
+ 0x0048, 0x3816, 0xa085, 0x0001, 0x0078, 0x3823, 0x0d7e, 0xa190,
+ 0x7720, 0x2204, 0xa06d, 0x0040, 0x3821, 0x2013, 0x0000, 0x1078,
+ 0x1348, 0x0d7f, 0xa006, 0x027f, 0x007c, 0x017e, 0xa182, 0x00ff,
+ 0x0048, 0x382e, 0xa085, 0x0001, 0x0078, 0x3835, 0xa188, 0x7720,
+ 0x2104, 0xa065, 0x0040, 0x382a, 0xa006, 0x017f, 0x007c, 0x0d7e,
+ 0x157e, 0x137e, 0x147e, 0x600b, 0x0000, 0x600f, 0x0000, 0x6000,
+ 0xc08c, 0x6002, 0x2069, 0x7b8e, 0x6808, 0x605e, 0x6810, 0x6062,
+ 0x6138, 0xa10a, 0x0048, 0x384d, 0x603a, 0x6814, 0x6066, 0x2099,
+ 0x7b96, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099,
+ 0x7b9a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069,
+ 0x7bae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818,
+ 0x6076, 0xa182, 0x0211, 0x00c8, 0x3871, 0x2009, 0x0008, 0x0078,
+ 0x389b, 0xa182, 0x0259, 0x00c8, 0x3879, 0x2009, 0x0007, 0x0078,
+ 0x389b, 0xa182, 0x02c1, 0x00c8, 0x3881, 0x2009, 0x0006, 0x0078,
+ 0x389b, 0xa182, 0x0349, 0x00c8, 0x3889, 0x2009, 0x0005, 0x0078,
+ 0x389b, 0xa182, 0x0421, 0x00c8, 0x3891, 0x2009, 0x0004, 0x0078,
+ 0x389b, 0xa182, 0x0581, 0x00c8, 0x3899, 0x2009, 0x0003, 0x0078,
+ 0x389b, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, 0x0d7f,
+ 0x007c, 0x0e7e, 0x2071, 0x7b8d, 0x2e04, 0x6896, 0x2071, 0x7b8e,
+ 0x7004, 0x689a, 0x701c, 0x689e, 0x0e7f, 0x007c, 0x2001, 0x75d5,
+ 0xa600, 0x2004, 0x127e, 0x2091, 0x8000, 0x6178, 0xa10d, 0x617a,
+ 0x127f, 0x007c, 0x2001, 0x75d5, 0xa600, 0x2004, 0x8002, 0x127e,
+ 0x2091, 0x8000, 0x6178, 0xa10c, 0x617a, 0x127f, 0x007c, 0x2001,
+ 0x75d5, 0xa600, 0x2004, 0x8002, 0x127e, 0x2091, 0x8000, 0x617c,
+ 0xa10c, 0x617e, 0x127f, 0x0078, 0x38d7, 0x1078, 0x376a, 0x1078,
+ 0x3938, 0x00c0, 0x38d5, 0x1078, 0x38f2, 0x007c, 0x2001, 0x75d5,
+ 0xa600, 0x2004, 0x127e, 0x2091, 0x8000, 0x617c, 0xa10d, 0x617e,
+ 0x127f, 0x0078, 0x38ed, 0x1078, 0x37ae, 0x1078, 0x38fc, 0x00c0,
+ 0x38eb, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4844, 0x127f,
+ 0x007c, 0xa01e, 0x0078, 0x38fe, 0x2019, 0x0001, 0xa00e, 0x127e,
+ 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0, 0x391e,
+ 0x8dff, 0x0040, 0x3933, 0x83ff, 0x0040, 0x3916, 0x6844, 0xa084,
+ 0x00ff, 0xa606, 0x0040, 0x3923, 0x0078, 0x391e, 0x683c, 0xa406,
+ 0x00c0, 0x391e, 0x6840, 0xa506, 0x0040, 0x3923, 0x2d08, 0x6800,
+ 0x2068, 0x0078, 0x3908, 0x6a00, 0x604c, 0xad06, 0x00c0, 0x392b,
+ 0x624e, 0x0078, 0x392e, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0,
+ 0x3933, 0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, 0x393a,
+ 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, 0x3968,
+ 0x83ff, 0x0040, 0x394b, 0x6844, 0xa084, 0x00ff, 0xa606, 0x0040,
+ 0x3958, 0x0078, 0x3953, 0x683c, 0xa406, 0x00c0, 0x3953, 0x6840,
+ 0xa506, 0x0040, 0x3958, 0x2d08, 0x6800, 0x2068, 0x0078, 0x393d,
+ 0x6a00, 0x6080, 0xad06, 0x00c0, 0x3960, 0x6282, 0x0078, 0x3963,
+ 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x3968, 0x6186, 0x8dff,
+ 0x007c, 0x2001, 0x75d5, 0xa600, 0x2004, 0x6178, 0xa10c, 0x0040,
+ 0x3973, 0x2011, 0x0001, 0x617c, 0xa10c, 0x0040, 0x3979, 0xa295,
+ 0x0002, 0x007c, 0x1078, 0x39c5, 0x0040, 0x3982, 0x1078, 0x6a16,
+ 0x0078, 0x3984, 0xa085, 0x0001, 0x007c, 0x1078, 0x39c5, 0x0040,
+ 0x398d, 0x1078, 0x69a5, 0x0078, 0x398f, 0xa085, 0x0001, 0x007c,
+ 0x1078, 0x39c5, 0x0040, 0x3998, 0x1078, 0x69eb, 0x0078, 0x399a,
+ 0xa085, 0x0001, 0x007c, 0x1078, 0x39c5, 0x0040, 0x39a3, 0x1078,
+ 0x69c1, 0x0078, 0x39a5, 0xa085, 0x0001, 0x007c, 0x127e, 0x007e,
+ 0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, 0x0040, 0x39bd, 0x6800,
+ 0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b3f,
+ 0x1078, 0x3a7a, 0x007f, 0x0078, 0x39ac, 0x6083, 0x0000, 0x6087,
+ 0x0000, 0x0d7f, 0x007f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c,
+ 0x0f7e, 0x2079, 0x7651, 0x7804, 0xd0a4, 0x0040, 0x39f1, 0x157e,
+ 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3825,
+ 0x00c0, 0x39e5, 0x6004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006,
+ 0x00c0, 0x39e5, 0x6000, 0xc0ed, 0x6002, 0x017f, 0x8108, 0x00f0,
+ 0x39d5, 0x0c7f, 0x157f, 0x2009, 0x07d0, 0x2011, 0x39f3, 0x1078,
+ 0x45fe, 0x0f7f, 0x007c, 0x2011, 0x39f3, 0x1078, 0x456e, 0x157e,
+ 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3825,
+ 0x00c0, 0x3a1f, 0x6000, 0xd0ec, 0x0040, 0x3a1f, 0x047e, 0x62a0,
+ 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x7541,
+ 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x2019, 0x0029, 0x1078, 0x4962,
+ 0x1078, 0x48a5, 0x2009, 0x0000, 0x1078, 0x737b, 0x047f, 0x017f,
+ 0x8108, 0x00f0, 0x39fd, 0x0c7f, 0x157f, 0x007c, 0x0c7e, 0x6018,
+ 0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x2071, 0x76ff,
+ 0x7003, 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017, 0x0000,
+ 0x701b, 0x0000, 0x701f, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000,
+ 0x705b, 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x007c, 0x0e7e,
+ 0x2071, 0x76ff, 0x684c, 0xa005, 0x00c0, 0x3a55, 0x7028, 0xc085,
+ 0x702a, 0xa085, 0x0001, 0x0078, 0x3a78, 0x6a60, 0x7236, 0x6b64,
+ 0x733a, 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c,
+ 0x702e, 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x8007, 0x8006,
+ 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319,
+ 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006,
+ 0x0e7f, 0x007c, 0x0e7e, 0x6838, 0xd0fc, 0x00c0, 0x3acb, 0x6804,
+ 0xa00d, 0x0040, 0x3a99, 0x0d7e, 0x0e7e, 0x2071, 0x7600, 0x027e,
+ 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff,
+ 0x00c0, 0x3a8a, 0x702e, 0x70a0, 0xa200, 0x70a2, 0x027f, 0x0e7f,
+ 0x0d7f, 0x2071, 0x76ff, 0x701c, 0xa005, 0x00c0, 0x3adc, 0x0068,
+ 0x3ada, 0x2071, 0x7651, 0x7004, 0xd09c, 0x0040, 0x3ada, 0x6934,
+ 0xa186, 0x0103, 0x00c0, 0x3aed, 0x6948, 0x6844, 0xa105, 0x00c0,
+ 0x3acd, 0x2009, 0x8020, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0,
+ 0x3ada, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001,
+ 0x2091, 0x4080, 0x2071, 0x7600, 0x702c, 0x206a, 0x2d00, 0x702e,
+ 0x70a0, 0x8000, 0x70a2, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100,
+ 0x00c0, 0x3ada, 0x6868, 0xa005, 0x00c0, 0x3ada, 0x2009, 0x8020,
+ 0x0078, 0x3ab3, 0x2071, 0x76ff, 0x2d08, 0x206b, 0x0000, 0x7010,
+ 0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x3aea, 0x6902,
+ 0x0078, 0x3aeb, 0x711e, 0x0078, 0x3acb, 0xa18c, 0x00ff, 0xa186,
+ 0x0017, 0x0040, 0x3afb, 0xa186, 0x001e, 0x0040, 0x3afb, 0xa18e,
+ 0x001f, 0x00c0, 0x3ada, 0x684c, 0xd0cc, 0x0040, 0x3ada, 0x6850,
+ 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x3ada, 0x2009, 0x8021,
+ 0x0078, 0x3ab3, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80,
+ 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0x684a, 0x6952,
+ 0x007c, 0x2071, 0x76ff, 0x7004, 0x0079, 0x3b1e, 0x3b26, 0x3b35,
+ 0x3bc5, 0x3bc6, 0x3bd6, 0x3bdc, 0x3b27, 0x3bb3, 0x007c, 0x127e,
+ 0x2091, 0x8000, 0x0068, 0x3b34, 0x2009, 0x000d, 0x7030, 0x200a,
+ 0x2091, 0x4080, 0x7007, 0x0001, 0x127f, 0x701c, 0xa06d, 0x0040,
+ 0x3bb2, 0x0e7e, 0x2071, 0x7651, 0x7004, 0xd09c, 0x0040, 0x3b94,
+ 0x6934, 0xa186, 0x0103, 0x00c0, 0x3b6a, 0x6948, 0x6844, 0xa105,
+ 0x00c0, 0x3b87, 0x2009, 0x8020, 0x127e, 0x2091, 0x8000, 0x0068,
+ 0x3b66, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x3b66, 0x7122,
+ 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080,
+ 0x127f, 0x0e7f, 0x1078, 0x3c0f, 0x0078, 0x3bb2, 0x127f, 0x0e7f,
+ 0x0078, 0x3bb2, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0040, 0x3b78,
+ 0xa186, 0x001e, 0x0040, 0x3b78, 0xa18e, 0x001f, 0x00c0, 0x3b94,
+ 0x684c, 0xd0cc, 0x0040, 0x3b94, 0x6850, 0xa084, 0x00ff, 0xa086,
+ 0x0001, 0x00c0, 0x3b94, 0x2009, 0x8021, 0x0078, 0x3b4c, 0x6844,
+ 0xa086, 0x0100, 0x00c0, 0x3b94, 0x6868, 0xa005, 0x00c0, 0x3b94,
+ 0x2009, 0x8020, 0x0078, 0x3b4c, 0x0e7f, 0x1078, 0x3c23, 0x0040,
+ 0x3bb2, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003,
+ 0x00c0, 0x3ba9, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x3ba9,
+ 0x710e, 0x7007, 0x0003, 0x1078, 0x3c43, 0x7050, 0xa086, 0x0100,
+ 0x0040, 0x3bc6, 0x007c, 0x701c, 0xa06d, 0x0040, 0x3bc4, 0x1078,
+ 0x3c23, 0x0040, 0x3bc4, 0x7007, 0x0003, 0x1078, 0x3c43, 0x7050,
+ 0xa086, 0x0100, 0x0040, 0x3bc6, 0x007c, 0x007c, 0x7050, 0xa09e,
+ 0x0100, 0x00c0, 0x3bcf, 0x7007, 0x0004, 0x0078, 0x3bd6, 0xa086,
+ 0x0200, 0x00c0, 0x3bd5, 0x7007, 0x0005, 0x007c, 0x1078, 0x3bdd,
+ 0x7006, 0x1078, 0x3c0f, 0x007c, 0x007c, 0x702c, 0x7130, 0x8108,
+ 0xa102, 0x0048, 0x3bea, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072,
+ 0x0078, 0x3bf4, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x3bf4,
+ 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e,
+ 0x00c0, 0x3c08, 0x127e, 0x2091, 0x8000, 0x0068, 0x3c0b, 0x2001,
+ 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x127f, 0x007c,
+ 0x2001, 0x0007, 0x007c, 0x2001, 0x0006, 0x127f, 0x007c, 0x701c,
+ 0xa06d, 0x0040, 0x3c22, 0x127e, 0x2091, 0x8000, 0x7010, 0x8001,
+ 0x7012, 0x2d04, 0x701e, 0xa005, 0x00c0, 0x3c1f, 0x701a, 0x127f,
+ 0x1078, 0x1348, 0x007c, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e,
+ 0x0040, 0x3c32, 0x2304, 0x230c, 0xa10e, 0x0040, 0x3c32, 0xa006,
+ 0x0078, 0x3c42, 0x732c, 0x8319, 0x7130, 0xa102, 0x00c0, 0x3c3c,
+ 0x2300, 0xa005, 0x0078, 0x3c42, 0x0048, 0x3c41, 0xa302, 0x0078,
+ 0x3c42, 0x8002, 0x007c, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056,
+ 0x7053, 0x0000, 0x127e, 0x2091, 0x8000, 0x2009, 0x7859, 0x2104,
+ 0xc08d, 0x200a, 0x127f, 0x1078, 0x1399, 0x007c, 0x2071, 0x76cd,
+ 0x7003, 0x0000, 0x7007, 0x0000, 0x700f, 0x0000, 0x702b, 0x0001,
+ 0x704f, 0x0000, 0x7053, 0x0001, 0x705f, 0x0020, 0x7063, 0x0040,
+ 0x7083, 0x0000, 0x708b, 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000,
+ 0x007c, 0x0e7e, 0x2071, 0x76cd, 0x6848, 0xa005, 0x00c0, 0x3c7f,
+ 0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0078, 0x3ca4, 0x6a50,
+ 0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, 0x707a, 0x685c, 0x7042,
+ 0x707e, 0x6848, 0x702e, 0x6840, 0x7032, 0x2009, 0x000c, 0x200a,
+ 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210,
+ 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084, 0x702a, 0x7007,
+ 0x0001, 0x700f, 0x0000, 0xa006, 0x0e7f, 0x007c, 0x2b78, 0x2071,
+ 0x76cd, 0x7004, 0x1079, 0x3d04, 0x700c, 0x0079, 0x3caf, 0x3cb4,
+ 0x3ca9, 0x3ca9, 0x3ca9, 0x3ca9, 0x007c, 0x700c, 0x0079, 0x3cb8,
+ 0x3cbd, 0x3d02, 0x3d02, 0x3d03, 0x3d03, 0x7830, 0x7930, 0xa106,
+ 0x0040, 0x3cc7, 0x7830, 0x7930, 0xa106, 0x00c0, 0x3ced, 0x7030,
+ 0xa10a, 0x0040, 0x3ced, 0x00c8, 0x3ccf, 0x712c, 0xa10a, 0xa18a,
+ 0x0002, 0x00c8, 0x3cee, 0x1078, 0x1314, 0x0040, 0x3ced, 0x2d00,
+ 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057, 0x0000, 0x127e,
+ 0x007e, 0x2091, 0x8000, 0x2009, 0x7859, 0x2104, 0xc085, 0x200a,
+ 0x007f, 0x700e, 0x127f, 0x1078, 0x1399, 0x007c, 0x1078, 0x1314,
+ 0x0040, 0x3ced, 0x2d00, 0x705a, 0x1078, 0x1314, 0x00c0, 0x3cfa,
+ 0x0078, 0x3cd9, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004,
+ 0x0078, 0x3cdd, 0x007c, 0x007c, 0x3d15, 0x3d16, 0x3d4d, 0x3d4e,
+ 0x3d02, 0x3d84, 0x3d89, 0x3dc0, 0x3dc1, 0x3ddc, 0x3ddd, 0x3dde,
+ 0x3ddf, 0x3de0, 0x3de1, 0x3e4a, 0x3e74, 0x007c, 0x700c, 0x0079,
+ 0x3d19, 0x3d1e, 0x3d21, 0x3d31, 0x3d4c, 0x3d4c, 0x1078, 0x3cb5,
+ 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x4153,
+ 0x0040, 0x3d2e, 0x2091, 0x8000, 0x1078, 0x3cb5, 0x0d7f, 0x0078,
+ 0x3d3a, 0x127e, 0x8001, 0x700e, 0x1078, 0x4153, 0x7058, 0x2068,
+ 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084,
+ 0x00ff, 0xa08a, 0x0020, 0x00c8, 0x3d49, 0x1079, 0x3d64, 0x127f,
+ 0x007c, 0x127f, 0x1078, 0x3de2, 0x007c, 0x007c, 0x007c, 0x0e7e,
+ 0x2071, 0x76cd, 0x700c, 0x0079, 0x3d55, 0x3d5a, 0x3d5a, 0x3d5a,
+ 0x3d5c, 0x3d60, 0x0e7f, 0x007c, 0x700f, 0x0001, 0x0078, 0x3d62,
+ 0x700f, 0x0002, 0x0e7f, 0x007c, 0x3de2, 0x3de2, 0x3dfe, 0x3de2,
+ 0x3ee9, 0x3de2, 0x3de2, 0x3de2, 0x3de2, 0x3de2, 0x3dfe, 0x3f2e,
+ 0x3f77, 0x3fcf, 0x3fe2, 0x3de2, 0x3de2, 0x3e1a, 0x3dfe, 0x3de2,
+ 0x3de2, 0x3e30, 0x4069, 0x4086, 0x3de2, 0x3e1a, 0x3de2, 0x3de2,
+ 0x3de2, 0x3de2, 0x3e30, 0x4086, 0x7020, 0x2068, 0x1078, 0x1348,
+ 0x007c, 0x700c, 0x0079, 0x3d8c, 0x3d91, 0x3d94, 0x3da4, 0x3dbf,
+ 0x3dbf, 0x1078, 0x3cb5, 0x007c, 0x127e, 0x8001, 0x700e, 0x7058,
+ 0x007e, 0x1078, 0x4153, 0x0040, 0x3da1, 0x2091, 0x8000, 0x1078,
+ 0x3cb5, 0x0d7f, 0x0078, 0x3dad, 0x127e, 0x8001, 0x700e, 0x1078,
+ 0x4153, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807,
+ 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x3dbc,
+ 0x1079, 0x3dc2, 0x127f, 0x007c, 0x127f, 0x1078, 0x3de2, 0x007c,
+ 0x007c, 0x007c, 0x3de2, 0x3dfe, 0x3ed3, 0x3de2, 0x3dfe, 0x3de2,
+ 0x3dfe, 0x3dfe, 0x3de2, 0x3dfe, 0x3ed3, 0x3dfe, 0x3dfe, 0x3dfe,
+ 0x3dfe, 0x3dfe, 0x3de2, 0x3dfe, 0x3ed3, 0x3de2, 0x3de2, 0x3dfe,
+ 0x3de2, 0x3de2, 0x3de2, 0x3dfe, 0x007c, 0x007c, 0x007c, 0x007c,
+ 0x007c, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5,
+ 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3a7a, 0x127f, 0x007c,
+ 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x127e,
+ 0x2091, 0x8000, 0x1078, 0x3a7a, 0x127f, 0x007c, 0x7007, 0x0001,
+ 0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x127e, 0x2091, 0x8000,
+ 0x1078, 0x3a7a, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084,
+ 0x00ff, 0xc0dd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3a7a,
+ 0x127f, 0x007c, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0040, 0x3df0,
+ 0x8001, 0x00c0, 0x3e27, 0x7007, 0x0001, 0x0078, 0x3eb0, 0x7007,
+ 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x3eb0, 0x007c,
+ 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098,
+ 0x20a1, 0x76f8, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8,
+ 0x3e0c, 0x6884, 0xa08a, 0x0003, 0x00c8, 0x3e0c, 0xa080, 0x3ea1,
+ 0x2004, 0x70c6, 0x7010, 0xa015, 0x0040, 0x3e94, 0x1078, 0x1314,
+ 0x00c0, 0x3e55, 0x7007, 0x000f, 0x007c, 0x2d00, 0x7022, 0x70c4,
+ 0x2060, 0x6000, 0x6836, 0x6004, 0xad00, 0x7096, 0x6008, 0xa20a,
+ 0x00c8, 0x3e64, 0xa00e, 0x2200, 0x7112, 0x620c, 0x8003, 0x800b,
+ 0xa296, 0x0004, 0x0040, 0x3e6d, 0xa108, 0x719a, 0x810b, 0x719e,
+ 0xae90, 0x0022, 0x1078, 0x137f, 0x7090, 0xa08e, 0x0100, 0x0040,
+ 0x3e88, 0xa086, 0x0200, 0x0040, 0x3e80, 0x7007, 0x0010, 0x007c,
+ 0x7020, 0x2068, 0x1078, 0x1348, 0x7014, 0x2068, 0x0078, 0x3e0c,
+ 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068,
+ 0x6906, 0x711a, 0x0078, 0x3e4a, 0x7014, 0x2068, 0x7007, 0x0001,
+ 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0040, 0x40a3, 0x0078,
+ 0x3eb0, 0x3ea4, 0x3ea8, 0x3eac, 0x0002, 0x0011, 0x0007, 0x0004,
+ 0x000a, 0x000f, 0x0005, 0x0006, 0x0012, 0x000f, 0x0005, 0x0006,
+ 0x2009, 0x762c, 0x210c, 0x81ff, 0x00c0, 0x3ecd, 0x6838, 0xa084,
+ 0x00ff, 0x683a, 0x6853, 0x0000, 0x1078, 0x3668, 0x00c0, 0x3ec1,
+ 0x007c, 0x1078, 0x3b0a, 0x127e, 0x2091, 0x8000, 0x1078, 0x6b3f,
+ 0x1078, 0x3a7a, 0x127f, 0x0078, 0x3ec0, 0x2001, 0x0028, 0x2009,
+ 0x0000, 0x0078, 0x3ec1, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906,
+ 0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x3ee2, 0x7007, 0x0006,
+ 0x0078, 0x3ee8, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a,
+ 0x007c, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848,
+ 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x3f14,
+ 0x2009, 0x0000, 0x20a9, 0x007e, 0xa096, 0x0002, 0x0040, 0x3f14,
+ 0xa005, 0x00c0, 0x3f2b, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078,
+ 0x3825, 0x00c0, 0x3f2b, 0x067e, 0x6e44, 0xa6b4, 0x000f, 0x1078,
+ 0x38ba, 0x067f, 0x0078, 0x3f2b, 0x047e, 0x2011, 0x760c, 0x2224,
+ 0xc484, 0xc48c, 0x2412, 0x047f, 0x0c7e, 0x1078, 0x3825, 0x00c0,
+ 0x3f27, 0x2091, 0x8000, 0x607b, 0x0000, 0x2091, 0x8001, 0x8108,
+ 0x00f0, 0x3f1d, 0x0c7f, 0x1078, 0x1348, 0x007c, 0x127e, 0x2091,
+ 0x8000, 0x7007, 0x0001, 0x2001, 0x7652, 0x2004, 0xd0a4, 0x0040,
+ 0x3f6e, 0x6944, 0x1078, 0x416f, 0x6100, 0xd184, 0x0040, 0x3f53,
+ 0x6858, 0xa084, 0x00ff, 0x00c0, 0x3f71, 0x6000, 0xd084, 0x0040,
+ 0x3f6e, 0x6004, 0xa005, 0x00c0, 0x3f74, 0x6003, 0x0000, 0x600b,
+ 0x0000, 0x0078, 0x3f6b, 0x2011, 0x0001, 0x6860, 0xa005, 0x00c0,
+ 0x3f5b, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff,
+ 0x0040, 0x3f6e, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, 0x0040,
+ 0x3f6e, 0x600a, 0x6202, 0x127f, 0x0078, 0x4142, 0x127f, 0x0078,
+ 0x413a, 0x127f, 0x0078, 0x4132, 0x127f, 0x0078, 0x4136, 0x127e,
+ 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0x7652, 0x2004, 0xd0a4,
+ 0x0040, 0x3fcc, 0x6944, 0x1078, 0x416f, 0x6000, 0xa084, 0x0001,
+ 0x0040, 0x3fcc, 0x6204, 0x6308, 0x6c48, 0xa484, 0x0003, 0x0040,
+ 0x3fa4, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x3f9d, 0x2100,
+ 0xa210, 0x0048, 0x3fc9, 0x0078, 0x3fa4, 0x8001, 0x00c0, 0x3fc9,
+ 0x2100, 0xa212, 0x0048, 0x3fc9, 0xa484, 0x000c, 0x0040, 0x3fbe,
+ 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0, 0x3fb6,
+ 0x2100, 0xa318, 0x0048, 0x3fc9, 0x0078, 0x3fbe, 0xa082, 0x0004,
+ 0x00c0, 0x3fc9, 0x2100, 0xa31a, 0x0048, 0x3fc9, 0x6860, 0xa005,
+ 0x0040, 0x3fc4, 0x8000, 0x6016, 0x6206, 0x630a, 0x127f, 0x0078,
+ 0x4142, 0x127f, 0x0078, 0x413e, 0x127f, 0x0078, 0x413a, 0x127e,
+ 0x2091, 0x8000, 0x7007, 0x0001, 0x6944, 0x1078, 0x416f, 0x6308,
+ 0x8318, 0x0048, 0x3fdf, 0x630a, 0x127f, 0x0078, 0x4150, 0x127f,
+ 0x0078, 0x413e, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001,
+ 0x684c, 0xd0ac, 0x0040, 0x3ff6, 0x027e, 0x2009, 0x0000, 0x2011,
+ 0xfcff, 0x1078, 0x46b4, 0x027f, 0x0078, 0x402c, 0x6858, 0xa005,
+ 0x0040, 0x4040, 0x685c, 0xa065, 0x0040, 0x403c, 0x2001, 0x762c,
+ 0x2004, 0xa005, 0x0040, 0x4008, 0x1078, 0x6aa1, 0x0078, 0x400e,
+ 0x6013, 0x0400, 0x2009, 0x0041, 0x1078, 0x5c29, 0x6958, 0xa18c,
+ 0xe600, 0xa186, 0x2000, 0x0040, 0x4024, 0xa186, 0x0400, 0x0040,
+ 0x4024, 0x6944, 0x0c7e, 0x1078, 0x460c, 0x6000, 0xa084, 0xfdff,
+ 0x6002, 0x0c7f, 0x0078, 0x402c, 0x027e, 0x2009, 0x0000, 0x2011,
+ 0xfdff, 0x1078, 0x46b4, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x4038,
+ 0x6944, 0x1078, 0x460c, 0x6008, 0x8000, 0x0048, 0x4038, 0x600a,
+ 0x0c7f, 0x127f, 0x0078, 0x4142, 0x0c7f, 0x127f, 0x0078, 0x413a,
+ 0x6954, 0xa186, 0x002a, 0x00c0, 0x404c, 0x2001, 0x760c, 0x200c,
+ 0xc194, 0x2102, 0x0078, 0x402c, 0xa186, 0x0020, 0x0040, 0x4061,
+ 0xa186, 0x0029, 0x00c0, 0x403c, 0x6944, 0xa18c, 0xff00, 0x810f,
+ 0x1078, 0x3825, 0x00c0, 0x402c, 0x6000, 0xc0e4, 0x6002, 0x0078,
+ 0x402c, 0x685c, 0xa065, 0x0040, 0x403c, 0x6017, 0x0014, 0x0078,
+ 0x402c, 0x6944, 0x1078, 0x416f, 0x6000, 0xa084, 0x0001, 0x0040,
+ 0x4082, 0x2091, 0x8000, 0x6204, 0x8210, 0x0048, 0x407c, 0x6206,
+ 0x2091, 0x8001, 0x0078, 0x4150, 0x2091, 0x8001, 0x6853, 0x0016,
+ 0x0078, 0x4149, 0x6853, 0x0007, 0x0078, 0x4149, 0x6834, 0x8007,
+ 0xa084, 0x00ff, 0x00c0, 0x4090, 0x1078, 0x3df0, 0x0078, 0x40a2,
+ 0x2030, 0x8001, 0x00c0, 0x409a, 0x7007, 0x0001, 0x1078, 0x40a3,
+ 0x0078, 0x40a2, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a,
+ 0x704b, 0x40a3, 0x007c, 0x0e7e, 0x2009, 0x762c, 0x210c, 0x81ff,
+ 0x00c0, 0x4124, 0x2009, 0x760c, 0x210c, 0xd194, 0x00c0, 0x412e,
+ 0x6848, 0x2070, 0xae82, 0x7d00, 0x0048, 0x4113, 0x2001, 0x7615,
+ 0x2004, 0xae02, 0x00c8, 0x4113, 0x6944, 0x1078, 0x416f, 0x6100,
+ 0xa184, 0x0001, 0x0040, 0x40f9, 0xa184, 0x0100, 0x00c0, 0x4117,
+ 0xa184, 0x0200, 0x00c0, 0x411b, 0x601c, 0xa005, 0x00c0, 0x411f,
+ 0x711c, 0xa186, 0x0006, 0x00c0, 0x40fe, 0x6853, 0x0000, 0x6803,
+ 0x0000, 0x2d08, 0x127e, 0x2091, 0x8000, 0x7010, 0xa005, 0x00c0,
+ 0x40f0, 0x7112, 0x7018, 0xa065, 0x0040, 0x4123, 0x6000, 0xd0e4,
+ 0x00c0, 0x4128, 0x2e60, 0x1078, 0x4615, 0x127f, 0x0e7f, 0x007c,
+ 0x2068, 0x6800, 0xa005, 0x00c0, 0x40f0, 0x6902, 0x127f, 0x0e7f,
+ 0x007c, 0x0e7f, 0x6853, 0x0006, 0x0078, 0x4149, 0x6944, 0xa18c,
+ 0xff00, 0x810f, 0x1078, 0x3825, 0x00c0, 0x4129, 0x6000, 0xd0e4,
+ 0x00c0, 0x4129, 0x711c, 0xa186, 0x0007, 0x00c0, 0x4113, 0x6853,
+ 0x0002, 0x0078, 0x412b, 0x6853, 0x0008, 0x0078, 0x412b, 0x6853,
+ 0x000e, 0x0078, 0x412b, 0x6853, 0x0017, 0x0078, 0x412b, 0x6853,
+ 0x0035, 0x0078, 0x412b, 0x127f, 0x6853, 0x0028, 0x0078, 0x412b,
+ 0x127f, 0x6853, 0x0029, 0x0e7f, 0x0078, 0x4149, 0x6853, 0x002a,
+ 0x0078, 0x412b, 0x2009, 0x003e, 0x0078, 0x4144, 0x2009, 0x0004,
+ 0x0078, 0x4144, 0x2009, 0x0006, 0x0078, 0x4144, 0x2009, 0x0016,
+ 0x0078, 0x4144, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, 0xa105,
+ 0x6856, 0x2091, 0x8000, 0x1078, 0x3a7a, 0x2091, 0x8001, 0x007c,
+ 0x1078, 0x1348, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, 0x0048,
+ 0x4160, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078, 0x416c,
+ 0x7070, 0xa080, 0x0040, 0x7072, 0x00c8, 0x416c, 0x7074, 0xa081,
+ 0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x007c, 0x0d7e,
+ 0x1078, 0x460c, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004, 0x2204,
+ 0xa085, 0x8002, 0x2012, 0x0d7f, 0x007c, 0x20e1, 0x0002, 0x3d08,
+ 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x418b, 0xa086,
+ 0x1000, 0x00c0, 0x41a7, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x00c0,
+ 0x4192, 0x3e60, 0xac84, 0x0007, 0x00c0, 0x41a7, 0xac82, 0x7d00,
+ 0x0048, 0x41a7, 0x6854, 0xac02, 0x00c8, 0x41a7, 0x2009, 0x0047,
+ 0x1078, 0x5c29, 0x7a1c, 0xd284, 0x00c0, 0x417d, 0x007c, 0xa016,
+ 0x1078, 0x1572, 0x0078, 0x41a2, 0x157e, 0x137e, 0x147e, 0x20e1,
+ 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0070, 0x00c0, 0x41d5, 0xa484,
+ 0x7000, 0xa086, 0x1000, 0x00c0, 0x41d5, 0x1078, 0x41e2, 0x0040,
+ 0x41d5, 0x20e1, 0x3000, 0x7828, 0x7828, 0x1078, 0x4200, 0x147f,
+ 0x137f, 0x157f, 0x2009, 0x783e, 0x2104, 0xa005, 0x00c0, 0x41d1,
+ 0x007c, 0x1078, 0x4c7a, 0x0078, 0x41d0, 0x1078, 0x7574, 0x1078,
+ 0x41e2, 0x20e1, 0x3000, 0x7828, 0x7828, 0x147f, 0x137f, 0x157f,
+ 0x0078, 0x41d0, 0xa484, 0x01ff, 0x687a, 0xa005, 0x0040, 0x41f4,
+ 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0,
+ 0x2099, 0x020a, 0x53a5, 0x007c, 0x20a9, 0x000c, 0x20e1, 0x1000,
+ 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001, 0x0078, 0x41f3,
+ 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007, 0xa196, 0x0000,
+ 0x00c0, 0x420d, 0x0078, 0x4381, 0x007c, 0xa196, 0x2000, 0x00c0,
+ 0x421e, 0x6900, 0xa18e, 0x0001, 0x00c0, 0x421a, 0x1078, 0x2eb2,
+ 0x0078, 0x420c, 0x1078, 0x4226, 0x0078, 0x420c, 0xa196, 0x8000,
+ 0x00c0, 0x420c, 0x1078, 0x4407, 0x0078, 0x420c, 0x0c7e, 0x7110,
+ 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0040, 0x4233, 0xa196,
+ 0x0023, 0x00c0, 0x4328, 0xa08e, 0x0023, 0x00c0, 0x4264, 0x1078,
+ 0x447e, 0x0040, 0x4328, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200,
+ 0x00c0, 0x424c, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x0015,
+ 0x1078, 0x5c29, 0x0078, 0x4328, 0xa08e, 0x0210, 0x00c0, 0x4256,
+ 0x2009, 0x0015, 0x1078, 0x5c29, 0x0078, 0x4328, 0xa08e, 0x0100,
+ 0x00c0, 0x4328, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x0016,
+ 0x1078, 0x5c29, 0x0078, 0x4328, 0xa08e, 0x0022, 0x00c0, 0x4328,
+ 0x7030, 0xa08e, 0x0300, 0x00c0, 0x4275, 0x7034, 0xa005, 0x00c0,
+ 0x4328, 0x2009, 0x0017, 0x0078, 0x42f4, 0xa08e, 0x0500, 0x00c0,
+ 0x4281, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x0018, 0x0078,
+ 0x42f4, 0xa08e, 0x2010, 0x00c0, 0x4289, 0x2009, 0x0019, 0x0078,
+ 0x42f4, 0xa08e, 0x2110, 0x00c0, 0x4291, 0x2009, 0x001a, 0x0078,
+ 0x42f4, 0xa08e, 0x5200, 0x00c0, 0x429d, 0x7034, 0xa005, 0x00c0,
+ 0x4328, 0x2009, 0x001b, 0x0078, 0x42f4, 0xa08e, 0x5000, 0x00c0,
+ 0x42a9, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x001c, 0x0078,
+ 0x42f4, 0xa08e, 0x1200, 0x00c0, 0x42b5, 0x7034, 0xa005, 0x00c0,
+ 0x4328, 0x2009, 0x0024, 0x0078, 0x42f4, 0xa08c, 0xff00, 0xa18e,
+ 0x2400, 0x00c0, 0x42bf, 0x2009, 0x002d, 0x0078, 0x42f4, 0xa08c,
+ 0xff00, 0xa18e, 0x5300, 0x00c0, 0x42c9, 0x2009, 0x002a, 0x0078,
+ 0x42f4, 0xa08e, 0x0f00, 0x00c0, 0x42d1, 0x2009, 0x0020, 0x0078,
+ 0x42f4, 0xa08e, 0x5300, 0x00c0, 0x42d7, 0x0078, 0x42f2, 0xa08e,
+ 0x6104, 0x00c0, 0x42f2, 0x2011, 0x7b8d, 0x8208, 0x2204, 0xa082,
+ 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108,
+ 0x2124, 0x1078, 0x2d4a, 0x8108, 0x00f0, 0x42e4, 0x2009, 0x0023,
+ 0x0078, 0x42f4, 0x2009, 0x001d, 0x017e, 0x2011, 0x7b83, 0x2204,
+ 0x8211, 0x220c, 0x1078, 0x2085, 0x00c0, 0x432a, 0x1078, 0x37ee,
+ 0x00c0, 0x432a, 0x6612, 0x6516, 0x86ff, 0x0040, 0x431a, 0x017f,
+ 0x017e, 0xa186, 0x0017, 0x00c0, 0x431a, 0x6864, 0xa606, 0x00c0,
+ 0x431a, 0x6868, 0xa506, 0xa084, 0xff00, 0x00c0, 0x431a, 0x6000,
+ 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x5b9c, 0x0040, 0x432d, 0x017f,
+ 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x5c29,
+ 0x0c7f, 0x007c, 0x017f, 0x0078, 0x4328, 0x0c7f, 0x0078, 0x432a,
+ 0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, 0x00c0, 0x4350,
+ 0xa596, 0xfffd, 0x00c0, 0x4340, 0x2009, 0x007f, 0x0078, 0x437d,
+ 0xa596, 0xfffe, 0x00c0, 0x4348, 0x2009, 0x007e, 0x0078, 0x437d,
+ 0xa596, 0xfffc, 0x00c0, 0x4350, 0x2009, 0x0080, 0x0078, 0x437d,
+ 0x2011, 0x0000, 0x2021, 0x007e, 0x20a9, 0x0082, 0x2071, 0x779e,
+ 0x2e1c, 0x83ff, 0x00c0, 0x4362, 0x82ff, 0x00c0, 0x4371, 0x2410,
+ 0x0078, 0x4371, 0x2368, 0x6b10, 0x007e, 0x2100, 0xa31e, 0x007f,
+ 0x00c0, 0x4371, 0x6b14, 0xa31e, 0x00c0, 0x4371, 0x2408, 0x0078,
+ 0x437d, 0x8420, 0x8e70, 0x00f0, 0x4358, 0x82ff, 0x00c0, 0x437c,
+ 0xa085, 0x0001, 0x0078, 0x437e, 0x2208, 0xa006, 0x0d7f, 0x0e7f,
+ 0x007c, 0xa084, 0x0007, 0x0079, 0x4386, 0x007c, 0x438e, 0x438e,
+ 0x438e, 0x438e, 0x438e, 0x438f, 0x43a8, 0x43f0, 0x007c, 0x7110,
+ 0xd1bc, 0x0040, 0x43a7, 0x7120, 0x2160, 0xac8c, 0x0007, 0x00c0,
+ 0x43a7, 0xac8a, 0x7d00, 0x0048, 0x43a7, 0x6854, 0xac02, 0x00c8,
+ 0x43a7, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x5c29, 0x007c,
+ 0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x43ee, 0x2011, 0x7b83, 0x2204,
+ 0x8211, 0x220c, 0x1078, 0x2085, 0x00c0, 0x43ee, 0x1078, 0x3825,
+ 0x00c0, 0x43ee, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006,
+ 0x00c0, 0x43d3, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x43ee,
+ 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x2009, 0x0044, 0x1078,
+ 0x5c29, 0x0078, 0x43ee, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040,
+ 0x43ee, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004,
+ 0x00c0, 0x43e6, 0x6007, 0x0005, 0x0078, 0x43e8, 0x6007, 0x0001,
+ 0x6003, 0x0001, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0c7f, 0x007c,
+ 0x7110, 0xd1bc, 0x0040, 0x4406, 0x7020, 0x2060, 0xac84, 0x0007,
+ 0x00c0, 0x4406, 0xac82, 0x7d00, 0x0048, 0x4406, 0x6854, 0xac02,
+ 0x00c8, 0x4406, 0x2009, 0x0045, 0x1078, 0x5c29, 0x007c, 0x7110,
+ 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x4417, 0xa084,
+ 0x000f, 0xa08a, 0x0006, 0x10c8, 0x12d5, 0x1079, 0x4418, 0x007c,
+ 0x441e, 0x441f, 0x441e, 0x441e, 0x4460, 0x446f, 0x007c, 0x7110,
+ 0xd1bc, 0x00c0, 0x445f, 0x700c, 0x7108, 0x1078, 0x2085, 0x00c0,
+ 0x445f, 0x1078, 0x37ee, 0x00c0, 0x445f, 0x6612, 0x6516, 0x6204,
+ 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x00c0, 0x4448, 0x0c7e,
+ 0x1078, 0x5b9c, 0x017f, 0x0040, 0x445f, 0x611a, 0x601f, 0x0005,
+ 0x7120, 0x610a, 0x2009, 0x0088, 0x1078, 0x5c29, 0x0078, 0x445f,
+ 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x445f, 0x611a, 0x601f,
+ 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x445b, 0x2009,
+ 0x0005, 0x0078, 0x445d, 0x2009, 0x0001, 0x1078, 0x5c29, 0x007c,
+ 0x7110, 0xd1bc, 0x0040, 0x446e, 0x1078, 0x447e, 0x0040, 0x446e,
+ 0x7124, 0x610a, 0x2009, 0x0089, 0x1078, 0x5c29, 0x007c, 0x7110,
+ 0xd1bc, 0x0040, 0x447d, 0x1078, 0x447e, 0x0040, 0x447d, 0x7124,
+ 0x610a, 0x2009, 0x008a, 0x1078, 0x5c29, 0x007c, 0x7020, 0x2060,
+ 0xac84, 0x0007, 0x00c0, 0x4491, 0xac82, 0x7d00, 0x0048, 0x4491,
+ 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x4491, 0xa085, 0x0001,
+ 0x007c, 0xa006, 0x0078, 0x4490, 0x2071, 0x7849, 0x7003, 0x0003,
+ 0x700f, 0x0361, 0xa006, 0x701a, 0x7012, 0x7017, 0x7d00, 0x7007,
+ 0x0000, 0x7026, 0x702b, 0x558f, 0x7032, 0x7037, 0x55d0, 0x703b,
+ 0x0002, 0x703f, 0x0000, 0x007c, 0x2071, 0x7849, 0x00e0, 0x455b,
+ 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, 0x4524, 0x700f,
+ 0x0361, 0x7007, 0x0001, 0x127e, 0x2091, 0x8000, 0x7138, 0x8109,
+ 0x713a, 0x00c0, 0x4522, 0x703b, 0x0002, 0x2009, 0x0100, 0x2104,
+ 0xa082, 0x0003, 0x00c8, 0x4522, 0x703c, 0xa086, 0x0001, 0x00c0,
+ 0x44ff, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040,
+ 0x44dd, 0x6803, 0x1000, 0x0078, 0x44e4, 0x6804, 0xa084, 0x1000,
+ 0x0040, 0x44e4, 0x6803, 0x0100, 0x6803, 0x0000, 0x703f, 0x0000,
+ 0x2069, 0x7836, 0x6804, 0xa082, 0x0006, 0x00c0, 0x44f1, 0x6807,
+ 0x0000, 0x6830, 0xa082, 0x0003, 0x00c0, 0x44f8, 0x6833, 0x0000,
+ 0x1078, 0x4c7a, 0x1078, 0x4d3a, 0x0d7f, 0x0078, 0x4522, 0x0d7e,
+ 0x2069, 0x7600, 0x6944, 0x6860, 0xa102, 0x00c8, 0x4521, 0x2069,
+ 0x7836, 0x6804, 0xa086, 0x0000, 0x00c0, 0x4521, 0x6830, 0xa086,
+ 0x0000, 0x00c0, 0x4521, 0x703f, 0x0001, 0x6807, 0x0006, 0x6833,
+ 0x0003, 0x2069, 0x0100, 0x6830, 0x689e, 0x2069, 0x0140, 0x6803,
+ 0x0600, 0x0d7f, 0x0078, 0x4527, 0x127e, 0x2091, 0x8000, 0x7024,
+ 0xa00d, 0x0040, 0x4538, 0x7020, 0x8001, 0x7022, 0x00c0, 0x4538,
+ 0x7023, 0x0009, 0x8109, 0x7126, 0x00c0, 0x4538, 0x7028, 0x107a,
+ 0x7030, 0xa00d, 0x0040, 0x4549, 0x702c, 0x8001, 0x702e, 0x00c0,
+ 0x4549, 0x702f, 0x0009, 0x8109, 0x7132, 0x00c0, 0x4549, 0x7034,
+ 0x107a, 0x7018, 0xa00d, 0x0040, 0x455a, 0x7008, 0x8001, 0x700a,
+ 0x00c0, 0x455a, 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x455a,
+ 0x701c, 0x107a, 0x127f, 0x7004, 0x0079, 0x455e, 0x4585, 0x4586,
+ 0x45a2, 0x0e7e, 0x2071, 0x7849, 0x7018, 0xa005, 0x00c0, 0x456c,
+ 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e,
+ 0x2071, 0x7849, 0x701c, 0xa206, 0x00c0, 0x4578, 0x701a, 0x701e,
+ 0x007f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x7849, 0x6088, 0xa102,
+ 0x0048, 0x4583, 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078,
+ 0x3825, 0x00c0, 0x4598, 0x6088, 0x8001, 0x0048, 0x4598, 0x608a,
+ 0x00c0, 0x4598, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f,
+ 0x8108, 0xa182, 0x00ff, 0x0048, 0x45a0, 0xa00e, 0x7007, 0x0002,
+ 0x7112, 0x007c, 0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x6014,
+ 0xa005, 0x0040, 0x45d1, 0x8001, 0x6016, 0x00c0, 0x45d1, 0x611c,
+ 0xa186, 0x0003, 0x0040, 0x45b8, 0xa186, 0x0006, 0x00c0, 0x45cf,
+ 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x45cf, 0xa082,
+ 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x45c8, 0x2001, 0x1999,
+ 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x45d1, 0x1078,
+ 0x67c9, 0x127f, 0xac88, 0x0008, 0x7116, 0x2001, 0x7616, 0x2004,
+ 0xa102, 0x0048, 0x45df, 0x7017, 0x7d00, 0x7007, 0x0000, 0x007c,
+ 0x0e7e, 0x2071, 0x7849, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b,
+ 0x0002, 0x0e7f, 0x007c, 0x2001, 0x7852, 0x2003, 0x0000, 0x007c,
+ 0x0e7e, 0x2071, 0x7849, 0x7033, 0x07d0, 0x702f, 0x0009, 0x0e7f,
+ 0x007c, 0x2011, 0x7855, 0x2013, 0x0000, 0x007c, 0x0e7e, 0x2071,
+ 0x7849, 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0c7e,
+ 0x2061, 0x78da, 0x0c7f, 0x007c, 0xa184, 0x000f, 0x8003, 0x8003,
+ 0x8003, 0xa080, 0x78da, 0x2060, 0x007c, 0x6854, 0xa08a, 0x199a,
+ 0x0048, 0x461c, 0x2001, 0x1999, 0xa005, 0x00c0, 0x462c, 0x6944,
+ 0x0c7e, 0x1078, 0x460c, 0x6014, 0x0c7f, 0xa005, 0x00c0, 0x4631,
+ 0x2001, 0x001e, 0x0078, 0x4631, 0xa08e, 0xffff, 0x00c0, 0x4631,
+ 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c,
+ 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x466c, 0xd0b4, 0x00c0, 0x4648,
+ 0xd0bc, 0x00c0, 0x465a, 0x2009, 0x0006, 0x1078, 0x468f, 0x007c,
+ 0xd0fc, 0x0040, 0x4655, 0xa084, 0x0003, 0xa08e, 0x0003, 0x0040,
+ 0x4688, 0xa08e, 0x0000, 0x00c0, 0x4688, 0x2009, 0x0043, 0x1078,
+ 0x5c29, 0x007c, 0xd0fc, 0x0040, 0x4667, 0xa084, 0x0003, 0xa08e,
+ 0x0003, 0x0040, 0x4688, 0xa08e, 0x0000, 0x00c0, 0x4688, 0x2009,
+ 0x0042, 0x1078, 0x5c29, 0x007c, 0xd0fc, 0x0040, 0x467e, 0xa084,
+ 0x0003, 0xa08e, 0x0003, 0x0040, 0x4688, 0xa08e, 0x0002, 0x0040,
+ 0x4682, 0x2009, 0x0041, 0x1078, 0x5c29, 0x007c, 0x1078, 0x468d,
+ 0x0078, 0x467d, 0x2009, 0x0043, 0x1078, 0x5c29, 0x0078, 0x467d,
+ 0x2009, 0x0004, 0x1078, 0x468f, 0x007c, 0x2009, 0x0001, 0x6010,
+ 0xa0ec, 0xf000, 0x0040, 0x46b3, 0x2068, 0x6952, 0x6800, 0x6012,
+ 0xa186, 0x0001, 0x00c0, 0x46ad, 0x694c, 0xa18c, 0x8100, 0xa18e,
+ 0x8100, 0x00c0, 0x46ad, 0x0c7e, 0x6944, 0x1078, 0x460c, 0x6204,
+ 0x8210, 0x0048, 0x46ac, 0x6206, 0x0c7f, 0x1078, 0x3a7a, 0x6010,
+ 0xa06d, 0x10c0, 0x4615, 0x007c, 0x157e, 0x0c7e, 0x20a9, 0x0010,
+ 0x2061, 0x78da, 0x6000, 0x81ff, 0x0040, 0x46c1, 0xa205, 0x0078,
+ 0x46c2, 0xa204, 0x6002, 0xace0, 0x0008, 0x00f0, 0x46ba, 0x0c7f,
+ 0x157f, 0x007c, 0x6808, 0xa005, 0x0040, 0x46d2, 0x8001, 0x680a,
+ 0xa085, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x2079, 0x7836,
+ 0x127f, 0x0d7e, 0x2069, 0x7836, 0x6803, 0x0005, 0x2069, 0x0004,
+ 0x2d04, 0xa085, 0x8001, 0x206a, 0x0d7f, 0x007c, 0x0c7e, 0x6027,
+ 0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x46ee, 0x46f8, 0x471d,
+ 0x4778, 0x46fe, 0x471d, 0x46f6, 0x46f6, 0x46f6, 0x1078, 0x12d5,
+ 0x1078, 0x45eb, 0x1078, 0x4c7a, 0x0c7f, 0x007c, 0x62c0, 0x82ff,
+ 0x00c0, 0x4704, 0x0c7f, 0x007c, 0x2011, 0x3542, 0x1078, 0x456e,
+ 0x7828, 0xa092, 0x0002, 0x00c8, 0x4713, 0x8000, 0x782a, 0x1078,
+ 0x3572, 0x0078, 0x4702, 0x1078, 0x3542, 0x7807, 0x0003, 0x7827,
+ 0x0000, 0x782b, 0x0000, 0x0078, 0x4702, 0x1078, 0x45eb, 0x3c00,
+ 0x007e, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x007f, 0x20e0,
+ 0x82ff, 0x0040, 0x473b, 0x62c0, 0x82ff, 0x00c0, 0x473b, 0x782b,
+ 0x0000, 0x7824, 0xa065, 0x1040, 0x12d5, 0x2009, 0x0013, 0x1078,
+ 0x5c29, 0x0c7f, 0x007c, 0x3900, 0xa082, 0x797a, 0x00c8, 0x4742,
+ 0x1078, 0x5b2c, 0x0c7e, 0x7824, 0xa065, 0x1040, 0x12d5, 0x7804,
+ 0xa086, 0x0004, 0x0040, 0x47bd, 0x7828, 0xa092, 0x2710, 0x00c8,
+ 0x4758, 0x8000, 0x782a, 0x0c7f, 0x1078, 0x5574, 0x0078, 0x4739,
+ 0x6104, 0xa186, 0x0003, 0x00c0, 0x476f, 0x0e7e, 0x2071, 0x7600,
+ 0x70c8, 0x0e7f, 0xd08c, 0x0040, 0x476f, 0x0c7e, 0x0e7e, 0x2061,
+ 0x0100, 0x2071, 0x7600, 0x1078, 0x357b, 0x0e7f, 0x0c7f, 0x1078,
+ 0x75c7, 0x2009, 0x0014, 0x1078, 0x5c29, 0x0c7f, 0x0078, 0x4739,
+ 0x2001, 0x7852, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x478c,
+ 0x782b, 0x0000, 0x7824, 0xa065, 0x1040, 0x12d5, 0x2009, 0x0013,
+ 0x1078, 0x5c77, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x3900, 0xa082,
+ 0x797a, 0x00c8, 0x4795, 0x1078, 0x5b2c, 0x7824, 0xa005, 0x1040,
+ 0x12d5, 0x781c, 0xa06d, 0x1040, 0x12d5, 0x6800, 0xc0dc, 0x6802,
+ 0x7924, 0x2160, 0x1078, 0x5c02, 0x693c, 0x81ff, 0x1040, 0x12d5,
+ 0x8109, 0x693e, 0x6854, 0xa015, 0x0040, 0x47b1, 0x7a1e, 0x0078,
+ 0x47b3, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f,
+ 0x0c7f, 0x1078, 0x4c7a, 0x0078, 0x478a, 0x6104, 0xa186, 0x0002,
+ 0x0040, 0x47c8, 0xa186, 0x0004, 0x0040, 0x47c8, 0x0078, 0x474c,
+ 0x7808, 0xac06, 0x0040, 0x474c, 0x1078, 0x4b81, 0x1078, 0x4872,
+ 0x0c7f, 0x1078, 0x4c7a, 0x0078, 0x4739, 0x0c7e, 0x6027, 0x0002,
+ 0x2011, 0x7855, 0x2013, 0x0000, 0x62c8, 0x82ff, 0x00c0, 0x47ef,
+ 0x62c4, 0x82ff, 0x00c0, 0x47ef, 0x793c, 0xa1e5, 0x0000, 0x0040,
+ 0x47ed, 0x2009, 0x0049, 0x1078, 0x5c29, 0x0c7f, 0x007c, 0x3908,
+ 0xa192, 0x797a, 0x00c8, 0x47f6, 0x1078, 0x5b2c, 0x6017, 0x0010,
+ 0x793c, 0x81ff, 0x0040, 0x47ed, 0x7944, 0xa192, 0x7530, 0x00c8,
+ 0x4815, 0x8108, 0x7946, 0x1078, 0x45f0, 0x793c, 0xa188, 0x0007,
+ 0x210c, 0xa18e, 0x0006, 0x00c0, 0x4811, 0x6017, 0x0012, 0x0078,
+ 0x47ed, 0x6017, 0x0016, 0x0078, 0x47ed, 0x037e, 0x2019, 0x0001,
+ 0x1078, 0x5768, 0x037f, 0x1078, 0x75c7, 0x793c, 0x2160, 0x2009,
+ 0x004a, 0x1078, 0x5c29, 0x0078, 0x47ed, 0x007e, 0x017e, 0x0c7e,
+ 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0x7836,
+ 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0040, 0x4840, 0xa080,
+ 0x0003, 0x2102, 0x6112, 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c,
+ 0x6116, 0x6112, 0x0078, 0x483b, 0x0d7e, 0x2069, 0x7836, 0x6000,
+ 0xd0d4, 0x0040, 0x4859, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001,
+ 0x00c0, 0x4854, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0079,
+ 0x4c82, 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0040, 0x486b, 0x6056,
+ 0x605b, 0x0000, 0x007e, 0x2c00, 0x681a, 0x0d7f, 0x685a, 0x2069,
+ 0x7836, 0x0078, 0x484b, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e,
+ 0x0078, 0x484b, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000,
+ 0x600f, 0x0000, 0x2c08, 0x2061, 0x7836, 0x6020, 0x8000, 0x6022,
+ 0x6008, 0xa005, 0x0040, 0x488d, 0xa080, 0x0003, 0x2102, 0x610a,
+ 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c, 0x610e, 0x610a, 0x0078,
+ 0x4888, 0x0c7e, 0x600f, 0x0000, 0x2c08, 0x2061, 0x7836, 0x6034,
+ 0xa005, 0x0040, 0x48a1, 0xa080, 0x0003, 0x2102, 0x6136, 0x0c7f,
+ 0x007c, 0x613a, 0x6136, 0x0078, 0x489f, 0x0f7e, 0x0e7e, 0x0d7e,
+ 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2071, 0x7836, 0x7638,
+ 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x4907, 0x6018,
+ 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x4902, 0x703c, 0xac06,
+ 0x00c0, 0x48c7, 0x6003, 0x000a, 0x630a, 0x0078, 0x4902, 0x7038,
+ 0xac36, 0x00c0, 0x48cd, 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0,
+ 0x48db, 0x2c00, 0xaf36, 0x0040, 0x48d9, 0x2f00, 0x7036, 0x0078,
+ 0x48db, 0x7037, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040,
+ 0x48e4, 0x7e0e, 0x0078, 0x48e5, 0x2678, 0x600f, 0x0000, 0x1078,
+ 0x693e, 0x0040, 0x48fd, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003,
+ 0x00c0, 0x4910, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
+ 0x6b3f, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x1078, 0x6aa1, 0x0c7f,
+ 0x0078, 0x48b4, 0x2c78, 0x600c, 0x2060, 0x0078, 0x48b4, 0x127f,
+ 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c,
+ 0x601c, 0xa086, 0x0006, 0x00c0, 0x48f2, 0x1078, 0x74fd, 0x0078,
+ 0x48fd, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000,
+ 0x127e, 0x2091, 0x8000, 0x2079, 0x7836, 0x7838, 0xa065, 0x0040,
+ 0x4950, 0x600c, 0x007e, 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0,
+ 0x4937, 0x6003, 0x000a, 0x630a, 0x2c30, 0x0078, 0x494d, 0x1078,
+ 0x693e, 0x0040, 0x494b, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003,
+ 0x00c0, 0x4959, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
+ 0x3a7a, 0x1078, 0x6a94, 0x1078, 0x6aa1, 0x007f, 0x0078, 0x4926,
+ 0x7e3a, 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f, 0x007f,
+ 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x4942, 0x1078, 0x74fd,
+ 0x0078, 0x494b, 0x027e, 0x1078, 0x4976, 0x1078, 0x4a0f, 0x027f,
+ 0x007c, 0x0f7e, 0x127e, 0x2079, 0x7836, 0x2091, 0x8000, 0x1078,
+ 0x4aa6, 0x1078, 0x4b0e, 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e,
+ 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
+ 0x7836, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0040, 0x49fe, 0x6018,
+ 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x49f9, 0x7024, 0xac06,
+ 0x00c0, 0x49bc, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x49b7,
+ 0x1078, 0x5582, 0x68c3, 0x0000, 0x1078, 0x5a32, 0x7027, 0x0000,
+ 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x49ac,
+ 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
+ 0x0040, 0x49b4, 0x6827, 0x0001, 0x037f, 0x0078, 0x49bc, 0x6003,
+ 0x0009, 0x630a, 0x0078, 0x49f9, 0x7014, 0xac36, 0x00c0, 0x49c2,
+ 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x49d0, 0x2c00, 0xaf36,
+ 0x0040, 0x49ce, 0x2f00, 0x7012, 0x0078, 0x49d0, 0x7013, 0x0000,
+ 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x49d9, 0x7e0e, 0x0078,
+ 0x49da, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x693e,
+ 0x0040, 0x49f2, 0x601c, 0xa086, 0x0003, 0x00c0, 0x4a06, 0x6837,
+ 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b3f, 0x1078, 0x3a7a,
+ 0x1078, 0x6a94, 0x1078, 0x6aa1, 0x1078, 0x5902, 0x0c7f, 0x0078,
+ 0x4984, 0x2c78, 0x600c, 0x2060, 0x0078, 0x4984, 0x127f, 0x007f,
+ 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086,
+ 0x0006, 0x00c0, 0x49e7, 0x1078, 0x74fd, 0x0078, 0x49f2, 0x0c7e,
+ 0x007e, 0x127e, 0x2091, 0x8000, 0xa280, 0x7720, 0x2004, 0xa065,
+ 0x0040, 0x4aa2, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e, 0x2071, 0x7836,
+ 0x6654, 0x7018, 0xac06, 0x00c0, 0x4a26, 0x761a, 0x701c, 0xac06,
+ 0x00c0, 0x4a32, 0x86ff, 0x00c0, 0x4a31, 0x7018, 0x701e, 0x0078,
+ 0x4a32, 0x761e, 0x6058, 0xa07d, 0x0040, 0x4a37, 0x7e56, 0xa6ed,
+ 0x0000, 0x0040, 0x4a3d, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b,
+ 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x37a2, 0x0040,
+ 0x4a9e, 0x7624, 0x86ff, 0x0040, 0x4a8e, 0xa680, 0x0004, 0x2004,
+ 0xad06, 0x00c0, 0x4a8e, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005,
+ 0x0040, 0x4a85, 0x1078, 0x5582, 0x68c3, 0x0000, 0x1078, 0x5a32,
+ 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
+ 0x0040, 0x4a6e, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
+ 0x6824, 0xd084, 0x0040, 0x4a76, 0x6827, 0x0001, 0x037f, 0x0d7f,
+ 0x0c7e, 0x603c, 0xa005, 0x0040, 0x4a7f, 0x8001, 0x603e, 0x2660,
+ 0x1078, 0x6aa1, 0x0c7f, 0x0078, 0x4a8e, 0x0d7f, 0x0c7e, 0x2660,
+ 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x4a45, 0x8dff, 0x0040,
+ 0x4a9a, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b3f,
+ 0x1078, 0x3a7a, 0x1078, 0x5902, 0x0078, 0x4a45, 0x067f, 0x0d7f,
+ 0x0e7f, 0x0f7f, 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e,
+ 0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x4afe,
+ 0x600c, 0x007e, 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x4ae3,
+ 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x4add, 0x1078, 0x5582,
+ 0x68c3, 0x0000, 0x1078, 0x5a32, 0x7827, 0x0000, 0x037e, 0x2069,
+ 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x4ad2, 0x6803, 0x0100,
+ 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4ada,
+ 0x6827, 0x0001, 0x037f, 0x0078, 0x4ae3, 0x6003, 0x0009, 0x630a,
+ 0x2c30, 0x0078, 0x4afb, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040,
+ 0x4af7, 0x601c, 0xa086, 0x0003, 0x00c0, 0x4b05, 0x6837, 0x0103,
+ 0x6b4a, 0x6847, 0x0000, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x1078,
+ 0x6aa1, 0x1078, 0x5902, 0x007f, 0x0078, 0x4aad, 0x7e16, 0x7e12,
+ 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, 0xa086, 0x0006,
+ 0x00c0, 0x4aee, 0x1078, 0x74fd, 0x0078, 0x4af7, 0x007e, 0x067e,
+ 0x0c7e, 0x0d7e, 0x7818, 0xa065, 0x0040, 0x4b7a, 0x6054, 0x007e,
+ 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002,
+ 0x1078, 0x37a2, 0x0040, 0x4b77, 0x7e24, 0x86ff, 0x0040, 0x4b69,
+ 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, 0x4b69, 0x0d7e, 0x2069,
+ 0x0100, 0x68c0, 0xa005, 0x0040, 0x4b60, 0x1078, 0x5582, 0x68c3,
+ 0x0000, 0x1078, 0x5a32, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140,
+ 0x6b04, 0xa384, 0x1000, 0x0040, 0x4b49, 0x6803, 0x0100, 0x6803,
+ 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4b51, 0x6827,
+ 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x4b5a,
+ 0x8001, 0x603e, 0x2660, 0x1078, 0x6aa1, 0x0c7f, 0x0078, 0x4b69,
+ 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078,
+ 0x4b20, 0x8dff, 0x0040, 0x4b73, 0x6837, 0x0103, 0x6b4a, 0x6847,
+ 0x0000, 0x1078, 0x3a7a, 0x1078, 0x5902, 0x0078, 0x4b20, 0x007f,
+ 0x0078, 0x4b13, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f,
+ 0x007c, 0x0e7e, 0x0c7e, 0x2071, 0x7836, 0x7004, 0xa084, 0x0007,
+ 0x0079, 0x4b8a, 0x4b94, 0x4b97, 0x4bb0, 0x4bcc, 0x4c11, 0x4b94,
+ 0x4b94, 0x4b92, 0x1078, 0x12d5, 0x0c7f, 0x0e7f, 0x007c, 0x7024,
+ 0xa065, 0x0040, 0x4ba5, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015,
+ 0x0040, 0x4bac, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027,
+ 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x4ba5,
+ 0x6018, 0x2060, 0x1078, 0x37a2, 0x6000, 0xc0dc, 0x6002, 0x7020,
+ 0x8001, 0x7022, 0x0040, 0x4bc1, 0x6054, 0xa015, 0x0040, 0x4bc8,
+ 0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c,
+ 0x7218, 0x721e, 0x0078, 0x4bc1, 0x7024, 0xa065, 0x0040, 0x4c0e,
+ 0x700c, 0xac06, 0x00c0, 0x4be3, 0x1078, 0x5902, 0x600c, 0xa015,
+ 0x0040, 0x4bdf, 0x720e, 0x600f, 0x0000, 0x0078, 0x4c0c, 0x720e,
+ 0x720a, 0x0078, 0x4c0c, 0x7014, 0xac06, 0x00c0, 0x4bf6, 0x1078,
+ 0x5902, 0x600c, 0xa015, 0x0040, 0x4bf2, 0x7216, 0x600f, 0x0000,
+ 0x0078, 0x4c0c, 0x7216, 0x7212, 0x0078, 0x4c0c, 0x6018, 0x2060,
+ 0x1078, 0x37a2, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x5902, 0x701c,
+ 0xa065, 0x0040, 0x4c0c, 0x6054, 0xa015, 0x0040, 0x4c0a, 0x721e,
+ 0x0078, 0x4c0c, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f,
+ 0x007c, 0x7024, 0xa065, 0x0040, 0x4c1e, 0x1078, 0x5902, 0x600c,
+ 0xa015, 0x0040, 0x4c25, 0x720e, 0x600f, 0x0000, 0x1078, 0x5a32,
+ 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, 0x0078,
+ 0x4c1e, 0x0d7e, 0x2069, 0x7836, 0x6830, 0xa084, 0x0003, 0x0079,
+ 0x4c31, 0x4c37, 0x4c39, 0x4c5f, 0x4c37, 0x1078, 0x12d5, 0x0d7f,
+ 0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x4c55, 0x683c,
+ 0xa065, 0x0040, 0x4c4a, 0x600c, 0xa015, 0x0040, 0x4c51, 0x6a3a,
+ 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c7f, 0x0d7f,
+ 0x007c, 0x683a, 0x6836, 0x0078, 0x4c4a, 0x6843, 0x0000, 0x6838,
+ 0xa065, 0x0040, 0x4c4a, 0x6003, 0x0003, 0x0078, 0x4c4a, 0x0c7e,
+ 0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x4c77,
+ 0x600c, 0xa015, 0x0040, 0x4c73, 0x6a3a, 0x600f, 0x0000, 0x683f,
+ 0x0000, 0x0078, 0x4c77, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f,
+ 0x0d7f, 0x007c, 0x0d7e, 0x2069, 0x7836, 0x6804, 0xa084, 0x0007,
+ 0x0079, 0x4c82, 0x4c8c, 0x4d29, 0x4d29, 0x4d29, 0x4d29, 0x4d2b,
+ 0x4d29, 0x4c8a, 0x1078, 0x12d5, 0x6820, 0xa005, 0x00c0, 0x4c92,
+ 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4ca1, 0x6807,
+ 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4d71, 0x0c7f, 0x0d7f,
+ 0x007c, 0x6814, 0xa065, 0x0040, 0x4caf, 0x6807, 0x0001, 0x6826,
+ 0x682b, 0x0000, 0x1078, 0x4d71, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e,
+ 0x037e, 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x4d24, 0x704c, 0xa00d,
+ 0x0040, 0x4cbe, 0x7088, 0xa005, 0x0040, 0x4cd6, 0x7054, 0xa075,
+ 0x0040, 0x4cc7, 0xa20e, 0x0040, 0x4d24, 0x0078, 0x4ccc, 0x6818,
+ 0xa20e, 0x0040, 0x4d24, 0x2070, 0x704c, 0xa00d, 0x0040, 0x4cbe,
+ 0x7088, 0xa005, 0x00c0, 0x4cbe, 0x2e00, 0x681e, 0x733c, 0x7038,
+ 0xa302, 0x00c8, 0x4cbe, 0x1078, 0x5bd1, 0x0040, 0x4d24, 0x8318,
+ 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180, 0x0015, 0x2004, 0xa08a,
+ 0x199a, 0x0048, 0x4ced, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b,
+ 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc, 0x0040,
+ 0x4d06, 0x7100, 0xd1f4, 0x0040, 0x4d02, 0x7114, 0xa18c, 0x00ff,
+ 0x0078, 0x4d0b, 0x2009, 0x0000, 0x0078, 0x4d0b, 0xa1e0, 0x232f,
+ 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, 0x51c2,
+ 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b,
+ 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x0f7f,
+ 0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f, 0x0078,
+ 0x4d22, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4d37,
+ 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4d71, 0x0c7f,
+ 0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0x7836, 0x6830, 0xa086,
+ 0x0000, 0x00c0, 0x4d58, 0x6838, 0xa07d, 0x0040, 0x4d58, 0x6833,
+ 0x0001, 0x683e, 0x6847, 0x0000, 0x127e, 0x0f7e, 0x2091, 0x2200,
+ 0x027f, 0x1078, 0x1a4c, 0x00c0, 0x4d5b, 0x127f, 0x1078, 0x5457,
+ 0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843, 0x0000, 0x7803, 0x0002,
+ 0x780c, 0xa015, 0x0040, 0x4d6d, 0x6a3a, 0x780f, 0x0000, 0x6833,
+ 0x0000, 0x683f, 0x0000, 0x0078, 0x4d58, 0x683a, 0x6836, 0x0078,
+ 0x4d67, 0x601c, 0xa084, 0x000f, 0x1079, 0x4d77, 0x007c, 0x4d80,
+ 0x4d85, 0x508c, 0x5182, 0x4d85, 0x508c, 0x5182, 0x4d80, 0x4d85,
+ 0x1078, 0x4b81, 0x1078, 0x4c7a, 0x007c, 0x157e, 0x137e, 0x147e,
+ 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12d5, 0x6118,
+ 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x4da2, 0x7900, 0xd1f4, 0x0040,
+ 0x4d9e, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x4da7, 0x2009, 0x0000,
+ 0x0078, 0x4da7, 0xa1f8, 0x232f, 0x2f0c, 0xa18c, 0x00ff, 0x2c78,
+ 0x2061, 0x0100, 0x619a, 0x1079, 0x4db3, 0x0f7f, 0x0c7f, 0x147f,
+ 0x137f, 0x157f, 0x007c, 0x4de5, 0x4e1d, 0x4e35, 0x4eb4, 0x4ee1,
+ 0x4ee9, 0x4f0a, 0x4f1b, 0x4f2c, 0x4f34, 0x4f45, 0x4f34, 0x4f8d,
+ 0x4f1b, 0x4fae, 0x4fb6, 0x4f2c, 0x4fb6, 0x4fc7, 0x4de3, 0x4de3,
+ 0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3,
+ 0x4de3, 0x4de3, 0x5640, 0x5655, 0x5678, 0x569c, 0x4f0a, 0x4de3,
+ 0x4f0a, 0x4f34, 0x4de3, 0x4e35, 0x4eb4, 0x4de3, 0x5b4c, 0x4f34,
+ 0x4de3, 0x5b6f, 0x4f34, 0x1078, 0x12d5, 0x20a1, 0x020b, 0x1078,
+ 0x4fdc, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x0d7e, 0x2069, 0x7651,
+ 0x6804, 0xd084, 0x0040, 0x4dff, 0x6828, 0x20a3, 0x0000, 0x017e,
+ 0x1078, 0x209a, 0x21a2, 0x017f, 0x0d7f, 0x0078, 0x4e04, 0x0d7f,
+ 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x7605,
+ 0x53a6, 0x20a9, 0x0004, 0x2099, 0x7601, 0x53a6, 0x20a3, 0x0000,
+ 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
+ 0x60c3, 0x001c, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078,
+ 0x4fdc, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6030,
+ 0xa084, 0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0x7605, 0x53a6,
+ 0x60c3, 0x0010, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078,
+ 0x4fdc, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0,
+ 0x4e48, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0078, 0x4e4a,
+ 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004,
+ 0xa086, 0x007e, 0x00c0, 0x4e83, 0x2099, 0x7820, 0x33a6, 0x9398,
+ 0x33a6, 0x9398, 0x3304, 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6,
+ 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
+ 0x20a9, 0x0004, 0x2099, 0x7605, 0x53a6, 0x20a9, 0x0004, 0x2099,
+ 0x7601, 0x53a6, 0x20a9, 0x0010, 0x20a3, 0x0000, 0x00f0, 0x4e74,
+ 0x2099, 0x7828, 0x33a6, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x00f0,
+ 0x4e7d, 0x0078, 0x4ea3, 0x2099, 0x7820, 0x20a9, 0x0008, 0x53a6,
+ 0x20a9, 0x0004, 0x2099, 0x7605, 0x53a6, 0x20a9, 0x0004, 0x2099,
+ 0x7601, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4e94,
+ 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4e9a, 0x2099, 0x7828,
+ 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0,
+ 0x4ea5, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x4eab, 0x60c3,
+ 0x0074, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4fdc,
+ 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000,
+ 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079,
+ 0x7651, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x4ed0, 0xa085, 0x0020,
+ 0xd1a4, 0x0040, 0x4ed5, 0xa085, 0x0010, 0xa085, 0x0002, 0x20a2,
+ 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x556e,
+ 0x007c, 0x20a1, 0x020b, 0x1078, 0x4fdc, 0x20a3, 0x5000, 0x0078,
+ 0x4e4a, 0x20a1, 0x020b, 0x1078, 0x4fdc, 0x20a3, 0x2110, 0x20a3,
+ 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
+ 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
+ 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078,
+ 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5053, 0x20a3, 0x0200,
+ 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004,
+ 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5053, 0x20a3,
+ 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3,
+ 0x0008, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5053,
+ 0x20a3, 0x0200, 0x0078, 0x4e4a, 0x20a1, 0x020b, 0x1078, 0x5053,
+ 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x7810, 0x20a2,
+ 0x60c3, 0x0008, 0x1078, 0x556e, 0x007c, 0x0d7e, 0x20a1, 0x020b,
+ 0x1078, 0x5053, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800,
+ 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x4f6b, 0x6998,
+ 0xa184, 0xc000, 0x00c0, 0x4f67, 0xd1ec, 0x0040, 0x4f63, 0x20a3,
+ 0x2100, 0x0078, 0x4f6d, 0x20a3, 0x0100, 0x0078, 0x4f6d, 0x20a3,
+ 0x0400, 0x0078, 0x4f6d, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2,
+ 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0x7651, 0x7904, 0x0f7f,
+ 0xd1ac, 0x00c0, 0x4f7d, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x4f82,
+ 0xa085, 0x0010, 0xa085, 0x0002, 0x20a2, 0x20a2, 0x20a2, 0x60c3,
+ 0x0014, 0x1078, 0x556e, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078,
+ 0x5053, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3,
+ 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
+ 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
+ 0x0000, 0x60c3, 0x0014, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b,
+ 0x1078, 0x5053, 0x20a3, 0x0200, 0x0078, 0x4deb, 0x20a1, 0x020b,
+ 0x1078, 0x5053, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003,
+ 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x1078, 0x556e, 0x007c, 0x20e1,
+ 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x1078, 0x5053, 0x20a3,
+ 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3,
+ 0x0008, 0x1078, 0x556e, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1,
+ 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0,
+ 0x4fef, 0x20a3, 0x22ff, 0x20a3, 0xfffe, 0x0078, 0x501d, 0xa286,
+ 0x007f, 0x00c0, 0x4ffa, 0x0d7e, 0x20a3, 0x22ff, 0x20a3, 0xfffd,
+ 0x0078, 0x5011, 0xd2bc, 0x0040, 0x5019, 0xa286, 0x0080, 0x0d7e,
+ 0x00c0, 0x5008, 0x20a3, 0x22ff, 0x20a3, 0xfffc, 0x0078, 0x5011,
+ 0xa2e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x2200, 0x20a2, 0x6814,
+ 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078,
+ 0x5021, 0x20a3, 0x2200, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230,
+ 0x22a2, 0x20a3, 0x0129, 0x20a3, 0x0000, 0x1078, 0x555d, 0x22a2,
+ 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3,
+ 0x0000, 0x027f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
+ 0x20a3, 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x0d7e, 0x2069, 0x7619,
+ 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x20a3, 0x2029, 0x20a3, 0x0000,
+ 0x0078, 0x5025, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02,
+ 0x20a3, 0x0000, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
+ 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x5072,
+ 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x2300, 0x20a2,
+ 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
+ 0x0078, 0x507a, 0x20a3, 0x2300, 0x6298, 0x22a2, 0x20a3, 0x0000,
+ 0x6230, 0x22a2, 0x20a3, 0x0198, 0x20a3, 0x0000, 0x1078, 0x555d,
+ 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000,
+ 0x20a3, 0x0000, 0x027f, 0x007c, 0x0c7e, 0x0f7e, 0x6004, 0xa08a,
+ 0x0085, 0x1048, 0x12d5, 0xa08a, 0x008c, 0x10c8, 0x12d5, 0x6118,
+ 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x50aa, 0x7900, 0xd1f4, 0x0040,
+ 0x50a6, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x50af, 0x2009, 0x0000,
+ 0x0078, 0x50af, 0xa1f8, 0x232f, 0x2f0c, 0xa18c, 0x00ff, 0x2c78,
+ 0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x1079, 0x50ba, 0x0f7f,
+ 0x0c7f, 0x007c, 0x50c3, 0x50ce, 0x50e8, 0x50c1, 0x50c1, 0x50c1,
+ 0x50c3, 0x1078, 0x12d5, 0x147e, 0x20a1, 0x020b, 0x1078, 0x50fb,
+ 0x60c3, 0x0000, 0x1078, 0x556e, 0x147f, 0x007c, 0x147e, 0x20a1,
+ 0x020b, 0x1078, 0x5128, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808,
+ 0x20a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000,
+ 0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x556e, 0x147f, 0x007c,
+ 0x147e, 0x20a1, 0x020b, 0x1078, 0x5155, 0x20a3, 0x0003, 0x20a3,
+ 0x0300, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x1078,
+ 0x556e, 0x147f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
+ 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x511a,
+ 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2,
+ 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
+ 0x0078, 0x5122, 0x20a3, 0x8100, 0x6298, 0x22a2, 0x20a3, 0x0000,
+ 0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0078, 0x5025,
+ 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
+ 0x2004, 0xa092, 0x007e, 0x0048, 0x5147, 0x0d7e, 0xa0e8, 0x7720,
+ 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069,
+ 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x514f, 0x20a3,
+ 0x8400, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3,
+ 0x00d1, 0x20a3, 0x0000, 0x0078, 0x507e, 0x027e, 0x20e1, 0x9080,
+ 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e,
+ 0x0048, 0x5174, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085,
+ 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68,
+ 0x2da6, 0x0d7f, 0x0078, 0x517c, 0x20a3, 0x8500, 0x6298, 0x22a2,
+ 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x00d1, 0x20a3, 0x0000,
+ 0x0078, 0x507e, 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040,
+ 0x1048, 0x12d5, 0xa08a, 0x0050, 0x10c8, 0x12d5, 0x7918, 0x2160,
+ 0x61a0, 0xd1bc, 0x0040, 0x51a1, 0x6100, 0xd1f4, 0x0040, 0x519d,
+ 0x6114, 0xa18c, 0x00ff, 0x0078, 0x51a6, 0x2009, 0x0000, 0x0078,
+ 0x51a6, 0xa1e0, 0x232f, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100,
+ 0x619a, 0xa082, 0x0040, 0x1079, 0x51b0, 0x0f7f, 0x0c7f, 0x007c,
+ 0x51c2, 0x52aa, 0x5252, 0x53d2, 0x51c0, 0x51c0, 0x51c0, 0x51c0,
+ 0x51c0, 0x51c0, 0x51c0, 0x581b, 0x582c, 0x583d, 0x584e, 0x51c0,
+ 0x1078, 0x12d5, 0x0d7e, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078,
+ 0x5215, 0x7910, 0x2168, 0x6944, 0xa18c, 0x00ff, 0x21a2, 0xa016,
+ 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x0006, 0x8004, 0x20a2,
+ 0xd1ac, 0x0040, 0x51df, 0x20a3, 0x0002, 0x0078, 0x51eb, 0xd1b4,
+ 0x0040, 0x51e6, 0x20a3, 0x0001, 0x0078, 0x51eb, 0x20a3, 0x0000,
+ 0x2230, 0x0078, 0x51ed, 0x6a80, 0x6e7c, 0x20a9, 0x0008, 0xad80,
+ 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0, 0x51f1, 0x22a2,
+ 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004,
+ 0xa085, 0x0009, 0x6016, 0x2001, 0x7852, 0x2003, 0x07d0, 0x2001,
+ 0x7851, 0x2003, 0x0009, 0x2001, 0x7857, 0x2003, 0x0002, 0x1078,
+ 0x1504, 0x147f, 0x157f, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x20e1,
+ 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff,
+ 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040,
+ 0x523b, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x0600,
+ 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6,
+ 0x0d7f, 0x0078, 0x5243, 0x20a3, 0x0600, 0x6198, 0x21a2, 0x20a3,
+ 0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2,
+ 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3,
+ 0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b,
+ 0x1078, 0x5272, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2,
+ 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2,
+ 0x20a2, 0x60c3, 0x000c, 0x1078, 0x556e, 0x147f, 0x137f, 0x157f,
+ 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
+ 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x5290, 0x0d7e, 0xa0e8,
+ 0x7720, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2,
+ 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5298,
+ 0x20a3, 0x0500, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2,
+ 0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x555d, 0x22a2, 0x20a3,
+ 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
+ 0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b,
+ 0x1078, 0x539a, 0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2, 0x22a2,
+ 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x00c0, 0x52c7, 0x7810,
+ 0xa084, 0x0700, 0x8007, 0x1079, 0x52cf, 0x0078, 0x52ca, 0xa006,
+ 0x1079, 0x52cf, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x52d9,
+ 0x533b, 0x533f, 0x5362, 0x536f, 0x5381, 0x5385, 0x52d7, 0x1078,
+ 0x12d5, 0x017e, 0x037e, 0x694c, 0xa18c, 0x0003, 0xa186, 0x0000,
+ 0x00c0, 0x52ec, 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2,
+ 0x037f, 0x017f, 0x0078, 0x5366, 0xa186, 0x0001, 0x00c0, 0x5336,
+ 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874,
+ 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300,
+ 0x0040, 0x5335, 0xd3c4, 0x0040, 0x5307, 0x687c, 0xa108, 0xd3cc,
+ 0x0040, 0x530c, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80,
+ 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x5311, 0x157f,
+ 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x5335, 0x20a1,
+ 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x0700, 0x6298,
+ 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0898, 0x20a2,
+ 0x1078, 0x555d, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f, 0x017f,
+ 0x1078, 0x556e, 0x007c, 0x20a3, 0x0008, 0x0078, 0x5364, 0x20a3,
+ 0x0302, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3,
+ 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3,
+ 0x0500, 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500,
+ 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x1078,
+ 0x556e, 0x007c, 0x20a3, 0x0028, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
+ 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x1078, 0x556e, 0x007c, 0x20a3,
+ 0x0100, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008,
+ 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x556e,
+ 0x007c, 0x20a3, 0x0008, 0x0078, 0x5364, 0x037e, 0x7b10, 0xa384,
+ 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x5393, 0x22a2,
+ 0x037f, 0x0078, 0x5364, 0x20a3, 0x0800, 0x22a2, 0x20a2, 0x037f,
+ 0x0078, 0x5366, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
+ 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x53b8, 0x0d7e, 0xa0e8,
+ 0x7720, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2,
+ 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x53c0,
+ 0x20a3, 0x0700, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2,
+ 0x20a3, 0x0898, 0x20a3, 0x0000, 0x1078, 0x555d, 0x22a2, 0x20a3,
+ 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
+ 0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x017e, 0x037e,
+ 0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x53e5, 0x037f, 0x017f,
+ 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x53ed, 0x53ed, 0x53ef,
+ 0x53ed, 0x53ed, 0x53ed, 0x5414, 0x53ed, 0x1078, 0x12d5, 0x7910,
+ 0xa18c, 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009,
+ 0x0003, 0x1078, 0x541e, 0x0d7e, 0x2069, 0x7651, 0x6804, 0xd0bc,
+ 0x0040, 0x5409, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078,
+ 0x540b, 0x20a3, 0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3,
+ 0x0001, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003,
+ 0x1078, 0x541e, 0x20a3, 0x7f00, 0x0078, 0x540c, 0x027e, 0x20e1,
+ 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc,
+ 0x0040, 0x543c, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085,
+ 0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68,
+ 0x2da6, 0x0d7f, 0x0078, 0x5444, 0x20a3, 0x0100, 0x6298, 0x22a2,
+ 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008,
+ 0x21a2, 0x1078, 0x555d, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
+ 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0e7e,
+ 0x0d7e, 0x0c7e, 0x057e, 0x047e, 0x037e, 0x2061, 0x0100, 0x2071,
+ 0x7600, 0x6130, 0x7818, 0x2068, 0x68a0, 0x2028, 0xd0bc, 0x00c0,
+ 0x5470, 0xa080, 0x232f, 0x2014, 0xa294, 0x00ff, 0x0078, 0x5474,
+ 0x6910, 0x6a14, 0x7364, 0x7468, 0x781c, 0xa086, 0x0006, 0x0040,
+ 0x54c8, 0xd5bc, 0x0040, 0x5484, 0xa185, 0x0100, 0x6062, 0x6266,
+ 0x636a, 0x646e, 0x0078, 0x548a, 0x6063, 0x0100, 0x6266, 0x606b,
+ 0x0000, 0x616e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000,
+ 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00,
+ 0x6082, 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010,
+ 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab,
+ 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048,
+ 0x54bc, 0x6a00, 0xd2f4, 0x0040, 0x54ba, 0x6a14, 0xa294, 0x00ff,
+ 0x0078, 0x54bc, 0x2011, 0x0000, 0x629e, 0x6017, 0x0016, 0x1078,
+ 0x45f0, 0x037f, 0x047f, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c,
+ 0x7810, 0x2070, 0x704c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040,
+ 0x5517, 0xd5bc, 0x0040, 0x54dc, 0xa185, 0x0100, 0x6062, 0x6266,
+ 0x636a, 0x646e, 0x0078, 0x54e2, 0x6063, 0x0100, 0x6266, 0x606b,
+ 0x0000, 0x616e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000,
+ 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00,
+ 0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080,
+ 0x60c6, 0x707c, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af,
+ 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x5512, 0x6a00,
+ 0xd2f4, 0x0040, 0x5510, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x5512,
+ 0x2011, 0x0000, 0x629e, 0x6017, 0x0012, 0x0078, 0x54bf, 0xd5bc,
+ 0x0040, 0x5522, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e,
+ 0x0078, 0x5528, 0x6063, 0x0700, 0x6266, 0x606b, 0x0000, 0x616e,
+ 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff,
+ 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808,
+ 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008,
+ 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7,
+ 0x0000, 0xa582, 0x0080, 0x0048, 0x5558, 0x6a00, 0xd2f4, 0x0040,
+ 0x5556, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x5558, 0x2011, 0x0000,
+ 0x629e, 0x6017, 0x0016, 0x0078, 0x54bf, 0x7a18, 0xa280, 0x0023,
+ 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e,
+ 0x2069, 0x7836, 0x6843, 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080,
+ 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078, 0x5579, 0x1078, 0x45e0,
+ 0x007c, 0x007e, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016,
+ 0x007f, 0x007c, 0x007e, 0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084,
+ 0x0004, 0xa085, 0x0008, 0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e,
+ 0x0d7e, 0x017e, 0x027e, 0x1078, 0x45eb, 0x2061, 0x0100, 0x2069,
+ 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x55cc, 0x1078, 0x5582,
+ 0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e, 0x2061, 0x7836, 0x6128,
+ 0xa192, 0x0002, 0x00c8, 0x55b9, 0x8108, 0x612a, 0x6124, 0x0c7f,
+ 0x81ff, 0x0040, 0x55c7, 0x1078, 0x45e0, 0x1078, 0x5579, 0x0078,
+ 0x55c7, 0x6124, 0xa1e5, 0x0000, 0x0040, 0x55c4, 0x1078, 0x75c7,
+ 0x2009, 0x0014, 0x1078, 0x5c29, 0x0c7f, 0x0078, 0x55c7, 0x027f,
+ 0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x1078, 0x357b, 0x0078, 0x55c7,
+ 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x45f9, 0x2071,
+ 0x7836, 0x713c, 0x81ff, 0x0040, 0x55fa, 0x2061, 0x0100, 0x2069,
+ 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x5600, 0x6803, 0x1000,
+ 0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x5768, 0x037f,
+ 0x713c, 0x2160, 0x1078, 0x75c7, 0x2009, 0x004a, 0x1078, 0x5c29,
+ 0x0078, 0x55fa, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c,
+ 0x7144, 0xa192, 0x0002, 0x00c8, 0x55ea, 0x8108, 0x7146, 0x1078,
+ 0x45f0, 0x0078, 0x55fa, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e,
+ 0x047e, 0x007e, 0x127e, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0,
+ 0x2071, 0x7836, 0x7018, 0x2068, 0x8dff, 0x0040, 0x5637, 0x68a0,
+ 0xa406, 0x0040, 0x5627, 0x6854, 0x2068, 0x0078, 0x561c, 0x6010,
+ 0x2060, 0x643c, 0x6540, 0x6644, 0xa6b4, 0x000f, 0x2d60, 0x1078,
+ 0x38f9, 0x0040, 0x5637, 0x1078, 0x5902, 0xa085, 0x0001, 0x127f,
+ 0x007f, 0x047f, 0x057f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c,
+ 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4fdc, 0x20a3, 0x0f00,
+ 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008,
+ 0x1078, 0x556e, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1,
+ 0x020b, 0x1078, 0x5053, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9,
+ 0x0006, 0x2011, 0x7640, 0x2019, 0x7641, 0x23a6, 0x22a6, 0xa398,
+ 0x0002, 0xa290, 0x0002, 0x00f0, 0x5665, 0x20a3, 0x0000, 0x20a3,
+ 0x0000, 0x60c3, 0x001c, 0x1078, 0x556e, 0x147f, 0x157f, 0x007c,
+ 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x5033,
+ 0x1078, 0x504a, 0x7810, 0x007e, 0xa080, 0x0015, 0x2098, 0x7808,
+ 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2,
+ 0x007f, 0xa080, 0x0001, 0x2004, 0x7812, 0x1078, 0x556e, 0x027f,
+ 0x017f, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b,
+ 0x1078, 0x4fdc, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000,
+ 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x556e, 0x147f, 0x157f,
+ 0x007c, 0x0e7e, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
+ 0x7836, 0x700c, 0x2060, 0x8cff, 0x0040, 0x56cd, 0x1078, 0x6ace,
+ 0x00c0, 0x56c4, 0x1078, 0x5e57, 0x600c, 0x007e, 0x1078, 0x5c02,
+ 0x1078, 0x5902, 0x0c7f, 0x0078, 0x56bb, 0x700f, 0x0000, 0x700b,
+ 0x0000, 0x127f, 0x007f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x157e,
+ 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091,
+ 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x7836, 0x7024,
+ 0x2060, 0x8cff, 0x0040, 0x5726, 0x1078, 0x5582, 0x68c3, 0x0000,
+ 0x1078, 0x45eb, 0x2009, 0x0013, 0x1078, 0x5c29, 0x20a9, 0x01f4,
+ 0x6824, 0xd094, 0x0040, 0x5709, 0x6827, 0x0004, 0x7804, 0xa084,
+ 0x4000, 0x0040, 0x571b, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078,
+ 0x571b, 0xd084, 0x0040, 0x5710, 0x6827, 0x0001, 0x0078, 0x5712,
+ 0x00f0, 0x56f8, 0x7804, 0xa084, 0x1000, 0x0040, 0x571b, 0x7803,
+ 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f, 0x027f, 0x0c7f,
+ 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, 0x2001, 0x7600,
+ 0x2004, 0xa096, 0x0001, 0x0040, 0x575e, 0xa096, 0x0004, 0x0040,
+ 0x575e, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x3542, 0x1078,
+ 0x456e, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x574c, 0x6827,
+ 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x575e, 0x7803, 0x1000,
+ 0x7803, 0x0000, 0x0078, 0x575e, 0xd084, 0x0040, 0x5753, 0x6827,
+ 0x0001, 0x0078, 0x5755, 0x00f0, 0x573b, 0x7804, 0xa084, 0x1000,
+ 0x0040, 0x575e, 0x7803, 0x0100, 0x7803, 0x0000, 0x007f, 0x017f,
+ 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c,
+ 0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e,
+ 0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071,
+ 0x7836, 0x703c, 0x2060, 0x8cff, 0x0040, 0x57b6, 0x6817, 0x0010,
+ 0x68cb, 0x0000, 0x68c7, 0x0000, 0x1078, 0x45f9, 0x1078, 0x1c19,
+ 0xa39d, 0x0000, 0x00c0, 0x5790, 0x2009, 0x0049, 0x1078, 0x5c29,
+ 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x57a3, 0x6827, 0x0004,
+ 0x7804, 0xa084, 0x4000, 0x0040, 0x57b5, 0x7803, 0x1000, 0x7803,
+ 0x0000, 0x0078, 0x57b5, 0xd094, 0x0040, 0x57aa, 0x6827, 0x0002,
+ 0x0078, 0x57ac, 0x00f0, 0x5792, 0x7804, 0xa084, 0x1000, 0x0040,
+ 0x57b5, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f,
+ 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c,
+ 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0x7836, 0x6a06, 0x127f,
+ 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0x7836,
+ 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e,
+ 0x007e, 0x127e, 0x2071, 0x7836, 0x7614, 0x2660, 0x2678, 0x2091,
+ 0x8000, 0x8cff, 0x0040, 0x5814, 0x601c, 0xa206, 0x00c0, 0x580f,
+ 0x7014, 0xac36, 0x00c0, 0x57ee, 0x660c, 0x7616, 0x7010, 0xac36,
+ 0x00c0, 0x57fc, 0x2c00, 0xaf36, 0x0040, 0x57fa, 0x2f00, 0x7012,
+ 0x0078, 0x57fc, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06,
+ 0x0040, 0x5805, 0x7e0e, 0x0078, 0x5806, 0x2678, 0x600f, 0x0000,
+ 0x1078, 0x6aa1, 0x1078, 0x5902, 0x0c7f, 0x0078, 0x57e1, 0x2c78,
+ 0x600c, 0x2060, 0x0078, 0x57e1, 0x127f, 0x007f, 0x067f, 0x0c7f,
+ 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078,
+ 0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2,
+ 0x20a3, 0x4000, 0x0078, 0x585d, 0x157e, 0x147e, 0x20a1, 0x020b,
+ 0x1078, 0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2,
+ 0x20a2, 0x20a3, 0x2000, 0x0078, 0x585d, 0x157e, 0x147e, 0x20a1,
+ 0x020b, 0x1078, 0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
+ 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x585d, 0x157e, 0x147e,
+ 0x20a1, 0x020b, 0x1078, 0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2,
+ 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x590d, 0x60c3,
+ 0x0020, 0x1078, 0x556e, 0x147f, 0x157f, 0x007c, 0x127e, 0x0c7e,
+ 0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0, 0x5875,
+ 0xd1bc, 0x00c0, 0x58bf, 0x0078, 0x58ff, 0x2009, 0x017f, 0x200b,
+ 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9, 0x001e,
+ 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x58b6, 0x6020,
+ 0xd0b4, 0x0040, 0x58b6, 0x6024, 0xd094, 0x00c0, 0x58b6, 0x2104,
+ 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x58b6, 0x00f0, 0x5882,
+ 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff,
+ 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, 0xbc91, 0x6043, 0x0001,
+ 0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0, 0x58b5,
+ 0x6a04, 0xa294, 0x4000, 0x00c0, 0x58ac, 0x027f, 0x0d7f, 0x007f,
+ 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x58ff, 0x2009,
+ 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140,
+ 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040,
+ 0x58f8, 0x6020, 0xd0bc, 0x0040, 0x58f8, 0x2104, 0xa084, 0x000f,
+ 0xa086, 0x0004, 0x00c0, 0x58f8, 0x00f0, 0x58cc, 0x027e, 0x6164,
+ 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d, 0x6088,
+ 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, 0x0001, 0x6043, 0x0000,
+ 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x58f2, 0x027f,
+ 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0c7f,
+ 0x127f, 0x007c, 0x0e7e, 0x2071, 0x7836, 0x7020, 0xa005, 0x0040,
+ 0x590b, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008, 0x20a2,
+ 0x00f0, 0x590f, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e,
+ 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
+ 0x7836, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0040,
+ 0x59a5, 0x8cff, 0x0040, 0x59a5, 0x601c, 0xa086, 0x0006, 0x00c0,
+ 0x59a0, 0x88ff, 0x0040, 0x593c, 0x2800, 0xac06, 0x00c0, 0x59a0,
+ 0x2039, 0x0000, 0x0078, 0x5940, 0x6018, 0xa206, 0x00c0, 0x59a0,
+ 0x7024, 0xac06, 0x00c0, 0x596e, 0x2069, 0x0100, 0x68c0, 0xa005,
+ 0x0040, 0x5969, 0x6817, 0x0008, 0x68c3, 0x0000, 0x1078, 0x5a32,
+ 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
+ 0x0040, 0x595e, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
+ 0x6824, 0xd084, 0x0040, 0x5966, 0x6827, 0x0001, 0x037f, 0x0078,
+ 0x596e, 0x6003, 0x0009, 0x630a, 0x0078, 0x59a0, 0x7014, 0xac36,
+ 0x00c0, 0x5974, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x5982,
+ 0x2c00, 0xaf36, 0x0040, 0x5980, 0x2f00, 0x7012, 0x0078, 0x5982,
+ 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x598b,
+ 0x7e0e, 0x0078, 0x598c, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068,
+ 0x1078, 0x693e, 0x0040, 0x5996, 0x1078, 0x74fd, 0x1078, 0x6aa1,
+ 0x1078, 0x5902, 0x88ff, 0x00c0, 0x59af, 0x0c7f, 0x0078, 0x5926,
+ 0x2c78, 0x600c, 0x2060, 0x0078, 0x5926, 0xa006, 0x127f, 0x007f,
+ 0x067f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017,
+ 0x0000, 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x59a6, 0x0f7e, 0x0e7e,
+ 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000,
+ 0x2071, 0x7836, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5a21,
+ 0x601c, 0xa086, 0x0006, 0x00c0, 0x5a1c, 0x88ff, 0x0040, 0x59d6,
+ 0x2800, 0xac06, 0x00c0, 0x5a1c, 0x0078, 0x59da, 0x6018, 0xa206,
+ 0x00c0, 0x5a1c, 0x703c, 0xac06, 0x00c0, 0x59ec, 0x037e, 0x2019,
+ 0x0001, 0x1078, 0x5768, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043,
+ 0x0000, 0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x59f2,
+ 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5a00, 0x2c00, 0xaf36,
+ 0x0040, 0x59fe, 0x2f00, 0x7036, 0x0078, 0x5a00, 0x7037, 0x0000,
+ 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5a09, 0x7e0e, 0x0078,
+ 0x5a0a, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x693e,
+ 0x0040, 0x5a14, 0x1078, 0x74fd, 0x1078, 0x6aa1, 0x88ff, 0x00c0,
+ 0x5a2b, 0x0c7f, 0x0078, 0x59c5, 0x2c78, 0x600c, 0x2060, 0x0078,
+ 0x59c5, 0xa006, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f,
+ 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5, 0x0001,
+ 0x0078, 0x5a22, 0x0e7e, 0x2071, 0x7836, 0x2001, 0x7600, 0x2004,
+ 0xa086, 0x0002, 0x00c0, 0x5a40, 0x7007, 0x0005, 0x0078, 0x5a42,
+ 0x7007, 0x0000, 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e,
+ 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7836, 0x2c10,
+ 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5a82, 0x2200, 0xac06,
+ 0x00c0, 0x5a7d, 0x7038, 0xac36, 0x00c0, 0x5a60, 0x660c, 0x763a,
+ 0x7034, 0xac36, 0x00c0, 0x5a6e, 0x2c00, 0xaf36, 0x0040, 0x5a6c,
+ 0x2f00, 0x7036, 0x0078, 0x5a6e, 0x7037, 0x0000, 0x660c, 0x2c00,
+ 0xaf06, 0x0040, 0x5a76, 0x7e0e, 0x0078, 0x5a77, 0x2678, 0x600f,
+ 0x0000, 0xa085, 0x0001, 0x0078, 0x5a82, 0x2c78, 0x600c, 0x2060,
+ 0x0078, 0x5a53, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f,
+ 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e,
+ 0x127e, 0x2091, 0x8000, 0x2071, 0x7836, 0x760c, 0x2660, 0x2678,
+ 0x8cff, 0x0040, 0x5b1b, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
+ 0x00c0, 0x5b16, 0x7024, 0xac06, 0x00c0, 0x5ac9, 0x2069, 0x0100,
+ 0x68c0, 0xa005, 0x0040, 0x5ac9, 0x1078, 0x5582, 0x68c3, 0x0000,
+ 0x1078, 0x5a32, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04,
+ 0xa384, 0x1000, 0x0040, 0x5ac0, 0x6803, 0x0100, 0x6803, 0x0000,
+ 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5ac8, 0x6827, 0x0001,
+ 0x037f, 0x700c, 0xac36, 0x00c0, 0x5acf, 0x660c, 0x760e, 0x7008,
+ 0xac36, 0x00c0, 0x5add, 0x2c00, 0xaf36, 0x0040, 0x5adb, 0x2f00,
+ 0x700a, 0x0078, 0x5add, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00,
+ 0xaf06, 0x0040, 0x5ae6, 0x7e0e, 0x0078, 0x5ae7, 0x2678, 0x600f,
+ 0x0000, 0x1078, 0x6aba, 0x00c0, 0x5af1, 0x1078, 0x22dd, 0x0078,
+ 0x5b0d, 0x1078, 0x6ace, 0x00c0, 0x5af9, 0x1078, 0x5e57, 0x0078,
+ 0x5b0d, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x5b0d, 0x601c,
+ 0xa086, 0x0003, 0x00c0, 0x5b23, 0x6837, 0x0103, 0x6b4a, 0x6847,
+ 0x0000, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x6003, 0x0000, 0x1078,
+ 0x6aa1, 0x1078, 0x5902, 0x0c7f, 0x0078, 0x5a98, 0x2c78, 0x600c,
+ 0x2060, 0x0078, 0x5a98, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f,
+ 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5b04,
+ 0x1078, 0x74fd, 0x0078, 0x5b0d, 0x037e, 0x157e, 0x137e, 0x147e,
+ 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x214f, 0x00c0,
+ 0x5b3d, 0x8210, 0x8000, 0x0078, 0x5b34, 0xa005, 0x0040, 0x5b47,
+ 0x20a9, 0x0020, 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x147f,
+ 0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078,
+ 0x5053, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3,
+ 0x0000, 0x20a3, 0x0000, 0x20a3, 0x514c, 0x20a3, 0x4f47, 0x20a3,
+ 0x4943, 0x20a3, 0x2020, 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3,
+ 0x0000, 0x20a3, 0x0000, 0x1078, 0x556e, 0x0d7f, 0x007c, 0x20a1,
+ 0x020b, 0x1078, 0x5053, 0x20a3, 0x0210, 0x20a3, 0x0018, 0x20a3,
+ 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3,
+ 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810,
+ 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
+ 0x0018, 0x1078, 0x556e, 0x007c, 0x2061, 0x7d00, 0x2a70, 0x7060,
+ 0x7046, 0x704b, 0x7d00, 0x007c, 0x0e7e, 0x127e, 0x2071, 0x7600,
+ 0x2091, 0x8000, 0x7544, 0xa582, 0x0001, 0x0048, 0x5bce, 0x7048,
+ 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5bba, 0xace0, 0x0008,
+ 0x7054, 0xac02, 0x00c8, 0x5bb6, 0x0078, 0x5ba9, 0x2061, 0x7d00,
+ 0x0078, 0x5ba9, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0008,
+ 0x7054, 0xa502, 0x00c8, 0x5bca, 0x754a, 0xa085, 0x0001, 0x127f,
+ 0x0e7f, 0x007c, 0x704b, 0x7d00, 0x0078, 0x5bc5, 0xa006, 0x0078,
+ 0x5bc7, 0x0e7e, 0x2071, 0x7600, 0x7544, 0xa582, 0x0001, 0x0048,
+ 0x5bff, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5bec,
+ 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x5be8, 0x0078, 0x5bdb,
+ 0x2061, 0x7d00, 0x0078, 0x5bdb, 0x6003, 0x0008, 0x8529, 0x7546,
+ 0xaca8, 0x0008, 0x7054, 0xa502, 0x00c8, 0x5bfb, 0x754a, 0xa085,
+ 0x0001, 0x0e7f, 0x007c, 0x704b, 0x7d00, 0x0078, 0x5bf7, 0xa006,
+ 0x0078, 0x5bf9, 0xac82, 0x7d00, 0x1048, 0x12d5, 0x2001, 0x7615,
+ 0x2004, 0xac02, 0x10c8, 0x12d5, 0xa006, 0x6006, 0x600a, 0x600e,
+ 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x2061,
+ 0x7600, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0040, 0x5c21,
+ 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x0078,
+ 0x5c20, 0x601c, 0xa084, 0x000f, 0x0079, 0x5c2e, 0x5c37, 0x5c3f,
+ 0x5c5b, 0x5c77, 0x6b4b, 0x6b67, 0x6b83, 0x5c37, 0x5c3f, 0xa18e,
+ 0x0047, 0x00c0, 0x5c3e, 0xa016, 0x1078, 0x1572, 0x007c, 0x067e,
+ 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d5, 0x1079, 0x5c49, 0x067f,
+ 0x007c, 0x5c59, 0x5d40, 0x5e72, 0x5c59, 0x5ec9, 0x5c59, 0x5c59,
+ 0x5c59, 0x5cef, 0x6182, 0x5c59, 0x5c59, 0x5c59, 0x5c59, 0x5c59,
+ 0x5c59, 0x1078, 0x12d5, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
+ 0x12d5, 0x1079, 0x5c65, 0x067f, 0x007c, 0x5c75, 0x5c75, 0x5c75,
+ 0x5c75, 0x5c75, 0x5c75, 0x5c75, 0x5c75, 0x65f2, 0x66b8, 0x5c75,
+ 0x660b, 0x6664, 0x660b, 0x6664, 0x5c75, 0x1078, 0x12d5, 0x067e,
+ 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d5, 0x1079, 0x5c81, 0x067f,
+ 0x007c, 0x5c91, 0x61c0, 0x6266, 0x6328, 0x647c, 0x5c91, 0x5c91,
+ 0x5c91, 0x619e, 0x65a7, 0x65ab, 0x5c91, 0x5c91, 0x5c91, 0x5c91,
+ 0x65d1, 0x1078, 0x12d5, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0,
+ 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0, 0x3318,
+ 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002, 0xa398,
+ 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x5ca1, 0x0e7e, 0x1078, 0x693e,
+ 0x0040, 0x5cb8, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103,
+ 0x0e7f, 0x1078, 0x5c02, 0x007c, 0x0d7e, 0x037e, 0x7330, 0xa386,
+ 0x0200, 0x00c0, 0x5cc9, 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817,
+ 0xfffd, 0x6010, 0xa005, 0x0040, 0x5cd3, 0x2068, 0x6807, 0x0000,
+ 0x6837, 0x0103, 0x6b32, 0x1078, 0x5c02, 0x037f, 0x0d7f, 0x007c,
+ 0x0d7e, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6,
+ 0x0015, 0x00c0, 0x5cec, 0x6018, 0x2068, 0x7038, 0x680a, 0x703c,
+ 0x680e, 0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x5cad, 0x2100,
+ 0xa1b2, 0x0030, 0x10c8, 0x12d5, 0x0079, 0x5cf6, 0x5d28, 0x5d34,
+ 0x5d28, 0x5d28, 0x5d28, 0x5d28, 0x5d26, 0x5d26, 0x5d26, 0x5d26,
+ 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26,
+ 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26,
+ 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d28, 0x5d26, 0x5d28,
+ 0x5d28, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d28, 0x5d26,
+ 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x1078, 0x12d5,
+ 0x6003, 0x0001, 0x6106, 0x1078, 0x4872, 0x127e, 0x2091, 0x8000,
+ 0x1078, 0x4c7a, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078,
+ 0x4872, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x007c,
+ 0x6004, 0xa0b2, 0x0030, 0x10c8, 0x12d5, 0xa1b6, 0x0013, 0x00c0,
+ 0x5d4c, 0x2008, 0x0079, 0x5dd5, 0xa1b6, 0x0027, 0x00c0, 0x5da2,
+ 0x1078, 0x4b81, 0x6004, 0x1078, 0x6aba, 0x0040, 0x5d65, 0x1078,
+ 0x6ace, 0x0040, 0x5d9a, 0xa08e, 0x0021, 0x0040, 0x5d9e, 0xa08e,
+ 0x0022, 0x0040, 0x5d9a, 0x0078, 0x5d95, 0x1078, 0x22dd, 0x2001,
+ 0x0007, 0x1078, 0x37d1, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078,
+ 0x5e57, 0xa186, 0x007e, 0x00c0, 0x5d7b, 0x2001, 0x762f, 0x2014,
+ 0xa295, 0x0001, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019,
+ 0x0028, 0x1078, 0x4962, 0x1078, 0x48a5, 0x0c7e, 0x6018, 0xa065,
+ 0x0040, 0x5d8c, 0x1078, 0x39a6, 0x0c7f, 0x2c08, 0x1078, 0x737b,
+ 0x037f, 0x027f, 0x017f, 0x1078, 0x380d, 0x1078, 0x5c02, 0x1078,
+ 0x4c7a, 0x007c, 0x1078, 0x5e57, 0x0078, 0x5d95, 0x1078, 0x5e66,
+ 0x0078, 0x5d95, 0xa186, 0x0014, 0x00c0, 0x5d99, 0x1078, 0x4b81,
+ 0x1078, 0x22bb, 0x1078, 0x6aba, 0x00c0, 0x5dc2, 0x1078, 0x22dd,
+ 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, 0x5e57, 0xa186, 0x007e,
+ 0x00c0, 0x5dc0, 0x2001, 0x762f, 0x200c, 0xa18d, 0x0001, 0x2102,
+ 0x0078, 0x5d95, 0x1078, 0x6ace, 0x00c0, 0x5dca, 0x1078, 0x5e57,
+ 0x0078, 0x5d95, 0x6004, 0xa08e, 0x0021, 0x0040, 0x5dc6, 0xa08e,
+ 0x0022, 0x1040, 0x5e66, 0x0078, 0x5d95, 0x5e07, 0x5e09, 0x5e0d,
+ 0x5e11, 0x5e15, 0x5e19, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05,
+ 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05,
+ 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05,
+ 0x5e05, 0x5e05, 0x5e05, 0x5e1d, 0x5e23, 0x5e05, 0x5e2d, 0x5e23,
+ 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e23, 0x5e23, 0x5e05,
+ 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x1078, 0x12d5, 0x0078,
+ 0x5e23, 0x2001, 0x000b, 0x0078, 0x5e36, 0x2001, 0x0003, 0x0078,
+ 0x5e36, 0x2001, 0x0005, 0x0078, 0x5e36, 0x2001, 0x0001, 0x0078,
+ 0x5e36, 0x2001, 0x0009, 0x0078, 0x5e36, 0x1078, 0x12d5, 0x0078,
+ 0x5e35, 0x1078, 0x37d1, 0x1078, 0x4b81, 0x6003, 0x0002, 0x6017,
+ 0x0028, 0x1078, 0x4c7a, 0x0078, 0x5e35, 0x1078, 0x4b81, 0x6003,
+ 0x0004, 0x6017, 0x0028, 0x1078, 0x4c7a, 0x007c, 0x1078, 0x37d1,
+ 0x1078, 0x4b81, 0x6003, 0x0002, 0x037e, 0x2019, 0x765c, 0x2304,
+ 0xa084, 0xff00, 0x00c0, 0x5e48, 0x2019, 0x0028, 0x0078, 0x5e51,
+ 0x8007, 0xa09a, 0x0004, 0x0048, 0x5e44, 0x8003, 0x801b, 0x831b,
+ 0xa318, 0x6316, 0x037f, 0x1078, 0x4c7a, 0x0078, 0x5e35, 0x0e7e,
+ 0x1078, 0x693e, 0x0040, 0x5e64, 0x6010, 0x2070, 0x7007, 0x0000,
+ 0x7037, 0x0103, 0x7033, 0x0100, 0x0e7f, 0x007c, 0x0e7e, 0xacf0,
+ 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x7023, 0x8001,
+ 0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff,
+ 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x12d5, 0x6604, 0xa6b6, 0x0028,
+ 0x00c0, 0x5e86, 0x1078, 0x6b03, 0x0078, 0x5eb8, 0x6604, 0xa6b6,
+ 0x0029, 0x00c0, 0x5e8f, 0x1078, 0x6b1d, 0x0078, 0x5eb8, 0x6604,
+ 0xa6b6, 0x001f, 0x00c0, 0x5e98, 0x1078, 0x5c93, 0x0078, 0x5eb8,
+ 0x6604, 0xa6b6, 0x0000, 0x00c0, 0x5ea1, 0x1078, 0x5cd8, 0x0078,
+ 0x5eb8, 0x6604, 0xa6b6, 0x0022, 0x00c0, 0x5eaa, 0x1078, 0x5cbc,
+ 0x0078, 0x5eb8, 0xa1b6, 0x0015, 0x00c0, 0x5eb2, 0x1079, 0x5ebd,
+ 0x0078, 0x5eb8, 0xa1b6, 0x0016, 0x00c0, 0x5eb9, 0x1079, 0x5ffa,
+ 0x007c, 0x1078, 0x5c37, 0x0078, 0x5eb8, 0x5ee1, 0x5ee4, 0x5ee1,
+ 0x5f25, 0x5ee1, 0x5f96, 0x5ee1, 0x5ee1, 0x5ee1, 0x5fd2, 0x5ee1,
+ 0x5fe8, 0xa1b6, 0x0048, 0x0040, 0x5ed5, 0x20e1, 0x0005, 0x3d18,
+ 0x3e20, 0x2c10, 0x1078, 0x1572, 0x007c, 0x0e7e, 0xacf0, 0x0004,
+ 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x5c02,
+ 0x007c, 0x0005, 0x0005, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x7078,
+ 0xa086, 0x0074, 0x00c0, 0x5f0e, 0x1078, 0x734f, 0x00c0, 0x5f00,
+ 0x0d7e, 0x6018, 0x2068, 0x1078, 0x5f12, 0x0d7f, 0x2001, 0x0006,
+ 0x1078, 0x37d1, 0x1078, 0x22dd, 0x1078, 0x5c02, 0x0078, 0x5f10,
+ 0x2001, 0x000a, 0x1078, 0x37d1, 0x1078, 0x22dd, 0x6003, 0x0001,
+ 0x6007, 0x0001, 0x1078, 0x4872, 0x0078, 0x5f10, 0x1078, 0x5f86,
+ 0x0e7f, 0x007c, 0x6800, 0xd084, 0x0040, 0x5f24, 0x2001, 0x0000,
+ 0x1078, 0x37bd, 0x2069, 0x7651, 0x6804, 0xd0a4, 0x0040, 0x5f24,
+ 0x2001, 0x0006, 0x1078, 0x37df, 0x007c, 0x0d7e, 0x2011, 0x761e,
+ 0x2204, 0xa086, 0x0074, 0x00c0, 0x5f82, 0x1078, 0x60d4, 0x6018,
+ 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x0040, 0x5f4d,
+ 0xa286, 0x0080, 0x00c0, 0x5f76, 0x6813, 0x00ff, 0x6817, 0xfffc,
+ 0x6010, 0xa005, 0x0040, 0x5f6c, 0x2068, 0x6807, 0x0000, 0x6837,
+ 0x0103, 0x6833, 0x0200, 0x0078, 0x5f6c, 0x0e7e, 0x0f7e, 0x6813,
+ 0x00ff, 0x6817, 0xfffe, 0x2071, 0x762f, 0x2e04, 0xa085, 0x0003,
+ 0x2072, 0x2071, 0x7b80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff,
+ 0x2069, 0x7619, 0x206a, 0x78e6, 0x8e70, 0x2e04, 0x2069, 0x761a,
+ 0x206a, 0x78ea, 0x0f7f, 0x0e7f, 0x2001, 0x0006, 0x1078, 0x37d1,
+ 0x1078, 0x22dd, 0x1078, 0x5c02, 0x0078, 0x5f84, 0x2001, 0x0004,
+ 0x1078, 0x37d1, 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x4872,
+ 0x0078, 0x5f84, 0x1078, 0x5f86, 0x0d7f, 0x007c, 0x2001, 0x7600,
+ 0x2004, 0xa086, 0x0003, 0x0040, 0x5f91, 0x2001, 0x0007, 0x1078,
+ 0x37d1, 0x1078, 0x22dd, 0x1078, 0x5c02, 0x007c, 0x0e7e, 0x2071,
+ 0x7600, 0x7078, 0xa086, 0x0014, 0x00c0, 0x5fcc, 0x7000, 0xa086,
+ 0x0003, 0x00c0, 0x5fa9, 0x6010, 0xa005, 0x00c0, 0x5fa9, 0x1078,
+ 0x2dc8, 0x0d7e, 0x6018, 0x2068, 0x1078, 0x38a1, 0x1078, 0x5f12,
+ 0x0d7f, 0x1078, 0x60de, 0x00c0, 0x5fcc, 0x2001, 0x0006, 0x1078,
+ 0x37d1, 0x0e7e, 0x6010, 0xa005, 0x0040, 0x5fc5, 0x2070, 0x7007,
+ 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x0e7f, 0x1078, 0x22dd,
+ 0x1078, 0x5c02, 0x0078, 0x5fd0, 0x1078, 0x5e57, 0x1078, 0x5f86,
+ 0x0e7f, 0x007c, 0x2011, 0x761e, 0x2204, 0xa086, 0x0014, 0x00c0,
+ 0x5fe5, 0x2001, 0x0002, 0x1078, 0x37d1, 0x6003, 0x0001, 0x6007,
+ 0x0001, 0x1078, 0x4872, 0x0078, 0x5fe7, 0x1078, 0x5f86, 0x007c,
+ 0x2011, 0x761e, 0x2204, 0xa086, 0x0004, 0x00c0, 0x5ff7, 0x2001,
+ 0x0007, 0x1078, 0x37d1, 0x1078, 0x5c02, 0x0078, 0x5ff9, 0x1078,
+ 0x5f86, 0x007c, 0x5ee1, 0x6006, 0x5ee1, 0x602c, 0x5ee1, 0x6087,
+ 0x5ee1, 0x5ee1, 0x5ee1, 0x609c, 0x5ee1, 0x60af, 0x0c7e, 0x1078,
+ 0x60c2, 0x00c0, 0x601b, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001,
+ 0x0002, 0x1078, 0x37d1, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078,
+ 0x4872, 0x0078, 0x602a, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00,
+ 0xa086, 0x1900, 0x00c0, 0x6028, 0x1078, 0x5c02, 0x0078, 0x602a,
+ 0x1078, 0x5f86, 0x0c7f, 0x007c, 0x1078, 0x60d1, 0x00c0, 0x6040,
+ 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001, 0x0002, 0x1078, 0x37d1,
+ 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x4872, 0x0078, 0x6062,
+ 0x1078, 0x5e57, 0x2009, 0x7b8e, 0x2134, 0xa6b4, 0x00ff, 0xa686,
+ 0x0005, 0x0040, 0x6063, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00,
+ 0xa086, 0x1900, 0x00c0, 0x6060, 0xa686, 0x0009, 0x0040, 0x6063,
+ 0x2001, 0x0004, 0x1078, 0x37d1, 0x1078, 0x5c02, 0x0078, 0x6062,
+ 0x1078, 0x5f86, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x693e,
+ 0x0040, 0x6071, 0x6838, 0xd0fc, 0x0040, 0x6071, 0x0d7f, 0x0078,
+ 0x6060, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040,
+ 0x6082, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f,
+ 0x0078, 0x6062, 0x1078, 0x22bb, 0x0d7f, 0x0078, 0x6060, 0x1078,
+ 0x60d1, 0x00c0, 0x6097, 0x2001, 0x0004, 0x1078, 0x37d1, 0x6003,
+ 0x0001, 0x6007, 0x0003, 0x1078, 0x4872, 0x0078, 0x609b, 0x1078,
+ 0x5e57, 0x1078, 0x5f86, 0x007c, 0x1078, 0x60d1, 0x00c0, 0x60ac,
+ 0x2001, 0x0008, 0x1078, 0x37d1, 0x6003, 0x0001, 0x6007, 0x0005,
+ 0x1078, 0x4872, 0x0078, 0x60ae, 0x1078, 0x5f86, 0x007c, 0x1078,
+ 0x60d1, 0x00c0, 0x60bf, 0x2001, 0x000a, 0x1078, 0x37d1, 0x6003,
+ 0x0001, 0x6007, 0x0001, 0x1078, 0x4872, 0x0078, 0x60c1, 0x1078,
+ 0x5f86, 0x007c, 0x2009, 0x7b8e, 0x2104, 0xa086, 0x0003, 0x00c0,
+ 0x60d0, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00,
+ 0x007c, 0xa085, 0x0001, 0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006,
+ 0x2164, 0x1078, 0x3837, 0x017f, 0x0c7f, 0x007c, 0x0e7e, 0x2071,
+ 0x7b8c, 0x7004, 0xa086, 0x0014, 0x00c0, 0x6101, 0x7008, 0xa086,
+ 0x0800, 0x00c0, 0x6101, 0x700c, 0xd0ec, 0x0040, 0x60ff, 0xa084,
+ 0x0f00, 0xa086, 0x0100, 0x00c0, 0x60ff, 0x7024, 0xd0a4, 0x0040,
+ 0x60ff, 0xd08c, 0x0040, 0x60ff, 0xa006, 0x0078, 0x6101, 0xa085,
+ 0x0001, 0x0e7f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x057e,
+ 0x047e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2029, 0x783f,
+ 0x252c, 0x2021, 0x7845, 0x2424, 0x2061, 0x7d00, 0x2071, 0x7600,
+ 0x7244, 0x7060, 0xa202, 0x00c8, 0x6158, 0x1078, 0x7559, 0x0040,
+ 0x6150, 0x671c, 0xa786, 0x0001, 0x0040, 0x6150, 0xa786, 0x0007,
+ 0x0040, 0x6150, 0x2500, 0xac06, 0x0040, 0x6150, 0x2400, 0xac06,
+ 0x0040, 0x6150, 0x0c7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x613a,
+ 0x1078, 0x1676, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x614d,
+ 0xa786, 0x0003, 0x00c0, 0x6162, 0x6837, 0x0103, 0x6b4a, 0x6847,
+ 0x0000, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x1078, 0x6aa1, 0x0c7f,
+ 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x6158, 0x0078, 0x6118,
+ 0x127f, 0x007f, 0x027f, 0x047f, 0x057f, 0x077f, 0x0c7f, 0x0d7f,
+ 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0, 0x6144, 0x1078, 0x74fd,
+ 0x0078, 0x614d, 0x220c, 0x2304, 0xa106, 0x00c0, 0x6175, 0x8210,
+ 0x8318, 0x00f0, 0x616a, 0xa006, 0x007c, 0x2304, 0xa102, 0x0048,
+ 0x617d, 0x2001, 0x0001, 0x0078, 0x617f, 0x2001, 0x0000, 0xa18d,
+ 0x0001, 0x007c, 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12d5, 0x1078,
+ 0x6aba, 0x0040, 0x6191, 0x1078, 0x6ace, 0x0040, 0x619a, 0x0078,
+ 0x6193, 0x1078, 0x22dd, 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078,
+ 0x4c7a, 0x007c, 0x1078, 0x5e57, 0x0078, 0x6193, 0xa182, 0x0040,
+ 0x0079, 0x61a2, 0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b2,
+ 0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b4, 0x61b4, 0x61b4,
+ 0x61b4, 0x61b2, 0x1078, 0x12d5, 0x6003, 0x0001, 0x6106, 0x1078,
+ 0x4825, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x007c,
+ 0xa186, 0x0013, 0x00c0, 0x61c9, 0x6004, 0xa082, 0x0040, 0x0079,
+ 0x623f, 0xa186, 0x0027, 0x00c0, 0x61e6, 0x1078, 0x4b81, 0x1078,
+ 0x22bb, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x693e, 0x0040, 0x61e0,
+ 0x6837, 0x0103, 0x684b, 0x0029, 0x1078, 0x3a7a, 0x1078, 0x6a94,
+ 0x0d7f, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0xa186, 0x0014,
+ 0x00c0, 0x61ef, 0x6004, 0xa082, 0x0040, 0x0079, 0x620f, 0xa186,
+ 0x0047, 0x10c0, 0x12d5, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040,
+ 0x620c, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078,
+ 0x46e6, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002,
+ 0x00c0, 0x620c, 0x0078, 0x6266, 0x1078, 0x5c37, 0x007c, 0x6221,
+ 0x621f, 0x621f, 0x621f, 0x621f, 0x621f, 0x621f, 0x621f, 0x621f,
+ 0x621f, 0x621f, 0x6238, 0x6238, 0x6238, 0x6238, 0x621f, 0x1078,
+ 0x12d5, 0x1078, 0x4b81, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x693e,
+ 0x0040, 0x6232, 0x6837, 0x0103, 0x684b, 0x0006, 0x1078, 0x3a7a,
+ 0x1078, 0x6a94, 0x0d7f, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c,
+ 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0x6251,
+ 0x624f, 0x624f, 0x624f, 0x624f, 0x624f, 0x624f, 0x624f, 0x624f,
+ 0x624f, 0x624f, 0x625f, 0x625f, 0x625f, 0x625f, 0x624f, 0x1078,
+ 0x12d5, 0x1078, 0x4b81, 0x6003, 0x0002, 0x1078, 0x4c7a, 0x6010,
+ 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078,
+ 0x4b81, 0x6003, 0x000f, 0x1078, 0x4c7a, 0x007c, 0xa182, 0x0040,
+ 0x0079, 0x626a, 0x627a, 0x627a, 0x627a, 0x627a, 0x627a, 0x627c,
+ 0x6305, 0x631d, 0x627a, 0x627a, 0x627a, 0x627a, 0x627a, 0x627a,
+ 0x627a, 0x627a, 0x1078, 0x12d5, 0x0e7e, 0x0d7e, 0x2071, 0x7b8c,
+ 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, 0x62e9,
+ 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x62ae, 0xa186, 0x0028,
+ 0x00c0, 0x6298, 0x1078, 0x6aa8, 0x684b, 0x001c, 0x0078, 0x62b0,
+ 0xd6dc, 0x0040, 0x62a3, 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c,
+ 0x6b5e, 0x0078, 0x62b0, 0xd6d4, 0x0040, 0x62ae, 0x684b, 0x0007,
+ 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x62b0, 0x684b, 0x0000,
+ 0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x62c3, 0x7328,
+ 0x732c, 0x6b56, 0x037e, 0x2308, 0x2019, 0x7b98, 0xad90, 0x0019,
+ 0x1078, 0x6727, 0x037f, 0xd6cc, 0x0040, 0x62f9, 0x7124, 0x695a,
+ 0xa192, 0x0021, 0x00c8, 0x62d7, 0x2071, 0x7b98, 0x831c, 0x2300,
+ 0xae18, 0xad90, 0x001d, 0x1078, 0x6727, 0x0078, 0x62f9, 0x6838,
+ 0xd0fc, 0x0040, 0x62e0, 0x2009, 0x0020, 0x695a, 0x0078, 0x62cc,
+ 0x0f7e, 0x2d78, 0x1078, 0x66bf, 0x0f7f, 0x1078, 0x6714, 0x0078,
+ 0x62fb, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac,
+ 0x0040, 0x62f9, 0x6810, 0x6914, 0xa115, 0x0040, 0x62f9, 0x1078,
+ 0x646d, 0x1078, 0x3a7a, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
+ 0x0d7f, 0x0e7f, 0x1078, 0x5c02, 0x007c, 0x0f7e, 0x6003, 0x0003,
+ 0x2079, 0x7b8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078,
+ 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19cf,
+ 0x1078, 0x4891, 0x1078, 0x4d3a, 0x007c, 0x6003, 0x0004, 0x6110,
+ 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x1572, 0x007c,
+ 0xa182, 0x0040, 0x0079, 0x632c, 0x633c, 0x633c, 0x633c, 0x633c,
+ 0x633c, 0x633e, 0x63d5, 0x633c, 0x633c, 0x63eb, 0x644d, 0x633c,
+ 0x633c, 0x633c, 0x633c, 0x6454, 0x1078, 0x12d5, 0x077e, 0x0f7e,
+ 0x0e7e, 0x0d7e, 0x2071, 0x7b8c, 0x6110, 0x2178, 0x7614, 0xa6b4,
+ 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c,
+ 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x63d0, 0xa694, 0xff00, 0xa284,
+ 0x0c00, 0x0040, 0x635f, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284,
+ 0x0300, 0x0040, 0x63d0, 0x1078, 0x132f, 0x1040, 0x12d5, 0x2d00,
+ 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a,
+ 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186,
+ 0x0002, 0x0040, 0x6399, 0xa186, 0x0028, 0x00c0, 0x6383, 0x684b,
+ 0x001c, 0x0078, 0x639b, 0xd6dc, 0x0040, 0x638e, 0x684b, 0x0015,
+ 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x639b, 0xd6d4, 0x0040,
+ 0x6399, 0x684b, 0x0007, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078,
+ 0x639b, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856,
+ 0xa01e, 0xd6c4, 0x0040, 0x63b0, 0x7328, 0x732c, 0x6b56, 0x037e,
+ 0x2308, 0x2019, 0x7b98, 0xad90, 0x0019, 0x1078, 0x6727, 0x037f,
+ 0xd6cc, 0x0040, 0x63d0, 0x7124, 0x695a, 0xa192, 0x0021, 0x00c8,
+ 0x63c4, 0x2071, 0x7b98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d,
+ 0x1078, 0x6727, 0x0078, 0x63d0, 0x7838, 0xd0fc, 0x0040, 0x63cd,
+ 0x2009, 0x0020, 0x695a, 0x0078, 0x63b9, 0x2d78, 0x1078, 0x66bf,
+ 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003,
+ 0x2079, 0x7b8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078,
+ 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19cf,
+ 0x1078, 0x5567, 0x007c, 0x0d7e, 0x6003, 0x0002, 0x1078, 0x4c29,
+ 0x1078, 0x4d3a, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x644b,
+ 0xd1cc, 0x0040, 0x6426, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x641e,
+ 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198,
+ 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318,
+ 0x8210, 0x00f0, 0x640d, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e,
+ 0x017f, 0x2168, 0x1078, 0x1358, 0x0078, 0x6449, 0x017e, 0x1078,
+ 0x1358, 0x0d7f, 0x1078, 0x6714, 0x0078, 0x6449, 0x6837, 0x0103,
+ 0x6944, 0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x6445, 0xa086,
+ 0x0028, 0x00c0, 0x6437, 0x684b, 0x001c, 0x0078, 0x6447, 0xd1dc,
+ 0x0040, 0x643e, 0x684b, 0x0015, 0x0078, 0x6447, 0xd1d4, 0x0040,
+ 0x6445, 0x684b, 0x0007, 0x0078, 0x6447, 0x684b, 0x0000, 0x1078,
+ 0x3a7a, 0x1078, 0x5c02, 0x0d7f, 0x007c, 0x6003, 0x0002, 0x1078,
+ 0x4c29, 0x1078, 0x4d3a, 0x007c, 0x1078, 0x4c29, 0x1078, 0x22bb,
+ 0x0d7e, 0x6110, 0x2168, 0x1078, 0x693e, 0x0040, 0x6467, 0x6837,
+ 0x0103, 0x684b, 0x0029, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x0d7f,
+ 0x1078, 0x5c02, 0x1078, 0x4d3a, 0x007c, 0x684b, 0x0015, 0xd1fc,
+ 0x0040, 0x6479, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189,
+ 0x0000, 0x6962, 0x685e, 0x007c, 0xa182, 0x0040, 0x0079, 0x6480,
+ 0x6490, 0x6490, 0x6490, 0x6490, 0x6490, 0x6492, 0x6490, 0x6536,
+ 0x653e, 0x6490, 0x6490, 0x6490, 0x6490, 0x6490, 0x6490, 0x6490,
+ 0x1078, 0x12d5, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0x7b8c,
+ 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5,
+ 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040,
+ 0x6528, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, 0x64b3, 0x7018,
+ 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, 0x6525, 0x1078,
+ 0x132f, 0x1040, 0x12d5, 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200,
+ 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840,
+ 0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x64ee,
+ 0xa186, 0x0028, 0x00c0, 0x64d8, 0x684b, 0x001c, 0x0078, 0x64f0,
+ 0xd6dc, 0x0040, 0x64e3, 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c,
+ 0x6b5e, 0x0078, 0x64f0, 0xd6d4, 0x0040, 0x64ee, 0x684b, 0x0007,
+ 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x64f0, 0x684b, 0x0000,
+ 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040,
+ 0x6505, 0x7328, 0x732c, 0x6b56, 0x037e, 0x2308, 0x2019, 0x7b98,
+ 0xad90, 0x0019, 0x1078, 0x6727, 0x037f, 0xd6cc, 0x0040, 0x6525,
+ 0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, 0x6519, 0x2071, 0x7b98,
+ 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x6727, 0x0078,
+ 0x6525, 0x7838, 0xd0fc, 0x0040, 0x6522, 0x2009, 0x0020, 0x695a,
+ 0x0078, 0x650e, 0x2d78, 0x1078, 0x66bf, 0xd6dc, 0x00c0, 0x652b,
+ 0xa006, 0x0078, 0x652f, 0x2001, 0x0001, 0x7218, 0x731c, 0x1078,
+ 0x15b6, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, 0x20e1, 0x0005,
+ 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x1572, 0x007c, 0x0d7e, 0x6003,
+ 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x65a5, 0xd1cc,
+ 0x0040, 0x6575, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x656d, 0x017e,
+ 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198, 0x000d,
+ 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210,
+ 0x00f0, 0x655c, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e, 0x017f,
+ 0x2168, 0x1078, 0x1358, 0x0078, 0x65a3, 0x017e, 0x1078, 0x1358,
+ 0x0d7f, 0x1078, 0x6714, 0x0078, 0x65a3, 0x6837, 0x0103, 0x6944,
+ 0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x6594, 0xa086, 0x0028,
+ 0x00c0, 0x6586, 0x684b, 0x001c, 0x0078, 0x65a1, 0xd1dc, 0x0040,
+ 0x658d, 0x684b, 0x0015, 0x0078, 0x65a1, 0xd1d4, 0x0040, 0x6594,
+ 0x684b, 0x0007, 0x0078, 0x65a1, 0x684b, 0x0000, 0x684c, 0xd0ac,
+ 0x0040, 0x65a1, 0x6810, 0x6914, 0xa115, 0x0040, 0x65a1, 0x1078,
+ 0x646d, 0x1078, 0x3a7a, 0x1078, 0x5c02, 0x0d7f, 0x007c, 0x1078,
+ 0x4b81, 0x0078, 0x65ad, 0x1078, 0x4c29, 0x1078, 0x693e, 0x0040,
+ 0x65c4, 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0x760c,
+ 0x210c, 0xd18c, 0x00c0, 0x65cd, 0xd184, 0x00c0, 0x65c9, 0x6108,
+ 0x694a, 0x1078, 0x3a7a, 0x0d7f, 0x1078, 0x5c02, 0x1078, 0x4c7a,
+ 0x007c, 0x684b, 0x0004, 0x0078, 0x65c1, 0x684b, 0x0004, 0x0078,
+ 0x65c1, 0xa182, 0x0040, 0x0079, 0x65d5, 0x65e5, 0x65e5, 0x65e5,
+ 0x65e5, 0x65e5, 0x65e7, 0x65e5, 0x65ea, 0x65e5, 0x65e5, 0x65e5,
+ 0x65e5, 0x65e5, 0x65e5, 0x65e5, 0x65e5, 0x1078, 0x12d5, 0x1078,
+ 0x5c02, 0x007c, 0x007e, 0x027e, 0xa016, 0x1078, 0x1572, 0x027f,
+ 0x007f, 0x007c, 0xa182, 0x0085, 0x0079, 0x65f6, 0x65ff, 0x65fd,
+ 0x65fd, 0x65fd, 0x65fd, 0x65fd, 0x65fd, 0x1078, 0x12d5, 0x6003,
+ 0x0001, 0x6106, 0x1078, 0x4825, 0x127e, 0x2091, 0x8000, 0x1078,
+ 0x4c7a, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x6615, 0x6004,
+ 0xa082, 0x0085, 0x2008, 0x0079, 0x6649, 0xa186, 0x0027, 0x00c0,
+ 0x6636, 0x1078, 0x4b81, 0x1078, 0x22bb, 0x0d7e, 0x6010, 0x2068,
+ 0x1078, 0x693e, 0x0040, 0x662c, 0x6837, 0x0103, 0x684b, 0x0029,
+ 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x0d7f, 0x1078, 0x5c02, 0x1078,
+ 0x4c7a, 0x007c, 0x1078, 0x5c37, 0x0078, 0x6631, 0xa186, 0x0014,
+ 0x00c0, 0x6632, 0x1078, 0x4b81, 0x0d7e, 0x6010, 0x2068, 0x1078,
+ 0x693e, 0x0040, 0x662c, 0x6837, 0x0103, 0x684b, 0x0006, 0x0078,
+ 0x6628, 0x6652, 0x6650, 0x6650, 0x6650, 0x6650, 0x6650, 0x665b,
+ 0x1078, 0x12d5, 0x1078, 0x4b81, 0x6017, 0x0014, 0x6003, 0x000c,
+ 0x1078, 0x4c7a, 0x007c, 0x1078, 0x4b81, 0x6017, 0x0014, 0x6003,
+ 0x000e, 0x1078, 0x4c7a, 0x007c, 0xa182, 0x008c, 0x00c8, 0x666e,
+ 0xa182, 0x0085, 0x0048, 0x666e, 0x0079, 0x6671, 0x1078, 0x5c37,
+ 0x007c, 0x6678, 0x6678, 0x6678, 0x6678, 0x667a, 0x6699, 0x6678,
+ 0x1078, 0x12d5, 0x0d7e, 0x1078, 0x6a94, 0x1078, 0x693e, 0x0040,
+ 0x6695, 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040,
+ 0x668d, 0x684b, 0x0006, 0x0078, 0x6691, 0x684b, 0x0005, 0x1078,
+ 0x6b47, 0x6847, 0x0000, 0x1078, 0x3a7a, 0x1078, 0x5c02, 0x0d7f,
+ 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x66b4,
+ 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x66aa, 0x684b, 0x0006,
+ 0x0078, 0x66ae, 0x684b, 0x0005, 0x1078, 0x6b47, 0x6847, 0x0000,
+ 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x0d7f, 0x1078, 0x5c02, 0x007c,
+ 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0x057e,
+ 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, 0xa182, 0x0101, 0x00c8,
+ 0x66cb, 0x0078, 0x66cd, 0x2009, 0x0100, 0x2130, 0x2069, 0x7b98,
+ 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, 0x001d, 0x1078,
+ 0x6727, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0040, 0x66e1, 0x1078,
+ 0x1358, 0x1078, 0x132f, 0x0040, 0x670b, 0x8528, 0x6837, 0x0110,
+ 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x00c8, 0x66f7,
+ 0x2608, 0xad90, 0x000f, 0x1078, 0x6727, 0x0078, 0x670b, 0xa6b2,
+ 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f, 0x1078, 0x6727,
+ 0x0078, 0x66e1, 0x0f7f, 0x852f, 0xa5ad, 0x0003, 0x7d36, 0xa5ac,
+ 0x0000, 0x0078, 0x6710, 0x0f7f, 0x852f, 0xa5ad, 0x0003, 0x7d36,
+ 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, 0x8dff, 0x0040, 0x6725,
+ 0x6804, 0xa07d, 0x0040, 0x6723, 0x6807, 0x0000, 0x1078, 0x3a7a,
+ 0x2f68, 0x0078, 0x6718, 0x1078, 0x3a7a, 0x0f7f, 0x007c, 0x157e,
+ 0xa184, 0x0001, 0x0040, 0x672d, 0x8108, 0x810c, 0x21a8, 0x2304,
+ 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, 0x672f, 0x157f, 0x007c,
+ 0x127e, 0x2091, 0x8000, 0x601c, 0xa084, 0x000f, 0x1079, 0x6742,
+ 0x127f, 0x007c, 0x6751, 0x674a, 0x674c, 0x676a, 0x674a, 0x674c,
+ 0x674c, 0x674c, 0x1078, 0x12d5, 0xa006, 0x007c, 0xa085, 0x0001,
+ 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x6767,
+ 0xa00e, 0x2001, 0x0005, 0x1078, 0x3b0a, 0x1078, 0x6b47, 0x1078,
+ 0x3a7a, 0x1078, 0x5c02, 0xa085, 0x0001, 0x0d7f, 0x007c, 0xa006,
+ 0x0078, 0x6765, 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12d5, 0x1079,
+ 0x6772, 0x007c, 0x6782, 0x679f, 0x6784, 0x67b0, 0x679b, 0x6782,
+ 0x674c, 0x6751, 0x6751, 0x674c, 0x674c, 0x674c, 0x674c, 0x674c,
+ 0x674c, 0x674c, 0x1078, 0x12d5, 0x0d7e, 0x6010, 0x2068, 0x1078,
+ 0x693e, 0x0040, 0x678d, 0x1078, 0x6b47, 0x0d7f, 0x6007, 0x0085,
+ 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, 0x4825, 0x1078, 0x4c7a,
+ 0xa085, 0x0001, 0x007c, 0x1078, 0x1676, 0x0078, 0x6784, 0x0e7e,
+ 0x2071, 0x7836, 0x7024, 0xac06, 0x00c0, 0x67a8, 0x1078, 0x56d6,
+ 0x1078, 0x560b, 0x0e7f, 0x00c0, 0x6784, 0x1078, 0x674c, 0x007c,
+ 0x037e, 0x0e7e, 0x2071, 0x7836, 0x703c, 0xac06, 0x00c0, 0x67c0,
+ 0x2019, 0x0000, 0x1078, 0x5768, 0x0e7f, 0x037f, 0x0078, 0x6784,
+ 0x1078, 0x5a44, 0x0e7f, 0x037f, 0x00c0, 0x6784, 0x1078, 0x674c,
+ 0x007c, 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079, 0x67d1, 0x0c7f,
+ 0x007c, 0x67e0, 0x683d, 0x68e2, 0x67e4, 0x67e0, 0x67e0, 0x71dd,
+ 0x5c02, 0x683d, 0x1078, 0x6ace, 0x00c0, 0x67e0, 0x1078, 0x5e57,
+ 0x007c, 0x6017, 0x0001, 0x007c, 0x6000, 0xa08a, 0x0010, 0x10c8,
+ 0x12d5, 0x1079, 0x67ec, 0x007c, 0x67fc, 0x67fe, 0x681e, 0x6830,
+ 0x6830, 0x67fc, 0x67e0, 0x67e0, 0x67e0, 0x6830, 0x6830, 0x67fc,
+ 0x67fc, 0x67fc, 0x67fc, 0x683a, 0x1078, 0x12d5, 0x0e7e, 0x6010,
+ 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0x7836, 0x7024, 0xac06,
+ 0x0040, 0x681a, 0x1078, 0x560b, 0x6007, 0x0085, 0x6003, 0x000b,
+ 0x601f, 0x0002, 0x6017, 0x0014, 0x1078, 0x4825, 0x1078, 0x4c7a,
+ 0x0e7f, 0x007c, 0x6017, 0x0001, 0x0078, 0x6818, 0x0d7e, 0x6010,
+ 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x6007, 0x0085, 0x6003,
+ 0x000b, 0x601f, 0x0002, 0x1078, 0x4825, 0x1078, 0x4c7a, 0x007c,
+ 0x0d7e, 0x6017, 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852,
+ 0x0d7f, 0x007c, 0x1078, 0x5c02, 0x007c, 0x6000, 0xa08a, 0x0010,
+ 0x10c8, 0x12d5, 0x1079, 0x6845, 0x007c, 0x6855, 0x67e1, 0x6857,
+ 0x6855, 0x6857, 0x6855, 0x6855, 0x6855, 0x67da, 0x67da, 0x6855,
+ 0x6855, 0x6855, 0x6855, 0x6855, 0x6855, 0x1078, 0x12d5, 0x0d7e,
+ 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa08a, 0x000c,
+ 0x10c8, 0x12d5, 0x1079, 0x6865, 0x007c, 0x6871, 0x6890, 0x6871,
+ 0x6890, 0x6871, 0x6890, 0x6873, 0x687c, 0x6871, 0x6890, 0x6871,
+ 0x6889, 0x1078, 0x12d5, 0x6004, 0xa08e, 0x0004, 0x0040, 0x688b,
+ 0xa08e, 0x0002, 0x0040, 0x688b, 0x6004, 0x1078, 0x6ace, 0x0040,
+ 0x68da, 0xa08e, 0x0021, 0x0040, 0x68de, 0xa08e, 0x0022, 0x0040,
+ 0x68da, 0x1078, 0x22bb, 0x1078, 0x5e57, 0x1078, 0x5c02, 0x007c,
+ 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, 0x0040, 0x68ca, 0xa186,
+ 0x0002, 0x00c0, 0x68b9, 0x6018, 0x2068, 0x68a0, 0xd0bc, 0x00c0,
+ 0x68b9, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x68b9, 0x8001,
+ 0x6842, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, 0x1078,
+ 0x5b9c, 0x0040, 0x68b9, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0078,
+ 0x68ca, 0x0d7f, 0x0c7f, 0x1078, 0x5e57, 0x1078, 0x22bb, 0x0e7e,
+ 0x127e, 0x2091, 0x8000, 0x1078, 0x22dd, 0x127f, 0x0e7f, 0x1078,
+ 0x5c02, 0x007c, 0x2001, 0x0002, 0x1078, 0x37d1, 0x6003, 0x0001,
+ 0x6007, 0x0002, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0d7f, 0x0c7f,
+ 0x0078, 0x68c9, 0x1078, 0x5e57, 0x0078, 0x688d, 0x1078, 0x5e66,
+ 0x0078, 0x688d, 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12d5, 0x1079,
+ 0x68ea, 0x007c, 0x68fa, 0x68fa, 0x68fa, 0x68fa, 0x68fa, 0x68fa,
+ 0x68fa, 0x68fa, 0x68fa, 0x67e0, 0x68fa, 0x67e1, 0x68fc, 0x67e1,
+ 0x6905, 0x68fa, 0x1078, 0x12d5, 0x6007, 0x008b, 0x6003, 0x000d,
+ 0x1078, 0x4825, 0x1078, 0x4c7a, 0x007c, 0x1078, 0x6a94, 0x1078,
+ 0x693e, 0x0040, 0x6927, 0x1078, 0x22bb, 0x0d7e, 0x1078, 0x693e,
+ 0x0040, 0x691a, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006,
+ 0x1078, 0x3a7a, 0x0d7f, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003,
+ 0x0001, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0078, 0x6929, 0x1078,
+ 0x5c02, 0x007c, 0xa284, 0x0007, 0x00c0, 0x693b, 0xa282, 0x7d00,
+ 0x0048, 0x693b, 0x2001, 0x7615, 0x2004, 0xa202, 0x00c8, 0x693b,
+ 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x693a, 0x027e, 0x0e7e,
+ 0x2071, 0x7600, 0x6210, 0x7058, 0xa202, 0x0048, 0x6950, 0x705c,
+ 0xa202, 0x00c8, 0x6950, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c,
+ 0xa006, 0x0078, 0x694d, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e,
+ 0x2091, 0x8000, 0x2061, 0x7d00, 0x2071, 0x7600, 0x7344, 0x7060,
+ 0xa302, 0x00c8, 0x6979, 0x601c, 0xa206, 0x00c0, 0x6971, 0x1078,
+ 0x6ace, 0x00c0, 0x696d, 0x1078, 0x5e57, 0x0c7e, 0x1078, 0x5c02,
+ 0x0c7f, 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x6979, 0x0078,
+ 0x695e, 0x127f, 0x007f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e,
+ 0x0c7e, 0x017e, 0xa188, 0x7720, 0x210c, 0x81ff, 0x0040, 0x699c,
+ 0x2061, 0x7d00, 0x2071, 0x7600, 0x7344, 0x7060, 0xa302, 0x00c8,
+ 0x699c, 0x017e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x699f, 0x611a,
+ 0x1078, 0x22bb, 0x1078, 0x5c02, 0xa006, 0x0078, 0x69a1, 0xa085,
+ 0x0001, 0x017f, 0x0c7f, 0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e,
+ 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c, 0x057f, 0x0040, 0x69be,
+ 0x6612, 0x651a, 0x601f, 0x0003, 0x2009, 0x004b, 0x1078, 0x5c29,
+ 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078,
+ 0x69ba, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e,
+ 0x1078, 0x5b9c, 0x057f, 0x0040, 0x69e8, 0x6013, 0x0000, 0x651a,
+ 0x601f, 0x0003, 0x0c7e, 0x2560, 0x1078, 0x39a6, 0x0c7f, 0x1078,
+ 0x4962, 0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b, 0x2009, 0x004c,
+ 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c,
+ 0xa006, 0x0078, 0x69e4, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000,
+ 0x62a0, 0x0c7e, 0x1078, 0x5b9c, 0x057f, 0x0040, 0x6a13, 0x6612,
+ 0x651a, 0x601f, 0x0003, 0x2019, 0x0005, 0x0c7e, 0x2560, 0x1078,
+ 0x39a6, 0x0c7f, 0x1078, 0x4962, 0x1078, 0x48a5, 0x2c08, 0x1078,
+ 0x737b, 0x2009, 0x004d, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f,
+ 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6a0f, 0x0c7e, 0x057e,
+ 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x5b9c, 0x057f,
+ 0x0040, 0x6a3e, 0x6612, 0x651a, 0x601f, 0x0003, 0x2019, 0x0005,
+ 0x0c7e, 0x2560, 0x1078, 0x39a6, 0x0c7f, 0x1078, 0x4962, 0x1078,
+ 0x48a5, 0x2c08, 0x1078, 0x737b, 0x2009, 0x004e, 0x1078, 0x5c29,
+ 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078,
+ 0x6a3a, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c,
+ 0x017f, 0x0040, 0x6a5a, 0x660a, 0x611a, 0x601f, 0x0001, 0x2d00,
+ 0x6012, 0x2009, 0x001f, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f,
+ 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6a57, 0x0c7e, 0x127e, 0x2091,
+ 0x8000, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x6a76, 0x660a,
+ 0x611a, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x1078,
+ 0x5c29, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
+ 0x6a73, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c,
+ 0x017f, 0x0040, 0x6a91, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012,
+ 0x2009, 0x0000, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f, 0x0c7f,
+ 0x007c, 0xa006, 0x0078, 0x6a8e, 0x027e, 0x0d7e, 0x6218, 0x2268,
+ 0x6a3c, 0x82ff, 0x0040, 0x6a9e, 0x8211, 0x6a3e, 0x0d7f, 0x027f,
+ 0x007c, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0014, 0x007c,
+ 0x067e, 0x0c7e, 0x0d7e, 0x2031, 0x7652, 0x2634, 0xd6e4, 0x0040,
+ 0x6ab6, 0x6618, 0x2660, 0x6e44, 0x1078, 0x38de, 0x0d7f, 0x0c7f,
+ 0x067f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0002, 0x0040,
+ 0x6acb, 0xa08e, 0x0003, 0x0040, 0x6acb, 0xa08e, 0x0004, 0x0040,
+ 0x6acb, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x007e, 0x017e,
+ 0x6004, 0xa08e, 0x0000, 0x0040, 0x6ae3, 0xa08e, 0x001f, 0x0040,
+ 0x6ae3, 0xa08e, 0x0028, 0x0040, 0x6ae3, 0xa08e, 0x0029, 0x0040,
+ 0x6ae3, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x0c7e, 0x127e,
+ 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x6b00,
+ 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x1078, 0x22bb, 0x2009,
+ 0x0028, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c,
+ 0xa006, 0x0078, 0x6afd, 0xa186, 0x0015, 0x00c0, 0x6b18, 0x2011,
+ 0x761e, 0x2204, 0xa086, 0x0074, 0x00c0, 0x6b18, 0x1078, 0x60d4,
+ 0x6003, 0x0001, 0x6007, 0x0029, 0x1078, 0x4872, 0x0078, 0x6b1c,
+ 0x1078, 0x5e57, 0x1078, 0x5c02, 0x007c, 0xa186, 0x0015, 0x00c0,
+ 0x6b3a, 0x2011, 0x761e, 0x2204, 0xa086, 0x0014, 0x00c0, 0x6b3a,
+ 0x0d7e, 0x6018, 0x2068, 0x1078, 0x38a1, 0x0d7f, 0x1078, 0x60de,
+ 0x00c0, 0x6b3a, 0x2001, 0x0006, 0x1078, 0x37d1, 0x1078, 0x5cad,
+ 0x0078, 0x6b3e, 0x1078, 0x5e57, 0x1078, 0x5c02, 0x007c, 0x6848,
+ 0xa086, 0x0005, 0x00c0, 0x6b46, 0x1078, 0x6b47, 0x007c, 0x6850,
+ 0xc0ad, 0x6852, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
+ 0x12d5, 0x1079, 0x6b55, 0x067f, 0x007c, 0x6b65, 0x6d3c, 0x6e1d,
+ 0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x6b9f, 0x6e8b, 0x6b65,
+ 0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x1078, 0x12d5, 0x067e,
+ 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d5, 0x1079, 0x6b71, 0x067f,
+ 0x007c, 0x6b81, 0x718c, 0x6b81, 0x6b81, 0x6b81, 0x6b81, 0x6b81,
+ 0x6b81, 0x7167, 0x71d6, 0x6b81, 0x6b81, 0x6b81, 0x6b81, 0x6b81,
+ 0x6b81, 0x1078, 0x12d5, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
+ 0x12d5, 0x1079, 0x6b8d, 0x067f, 0x007c, 0x6b9d, 0x6fd8, 0x704a,
+ 0x706c, 0x70b8, 0x6b9d, 0x6b9d, 0x7112, 0x6e97, 0x714f, 0x7153,
+ 0x6b9d, 0x6b9d, 0x6b9d, 0x6b9d, 0x6b9d, 0x1078, 0x12d5, 0xa1b2,
+ 0x0030, 0x10c8, 0x12d5, 0x2100, 0x0079, 0x6ba6, 0x6bd6, 0x6cb3,
+ 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6,
+ 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6,
+ 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd8, 0x6c07, 0x6c12,
+ 0x6c3a, 0x6c40, 0x6c74, 0x6cac, 0x6bd6, 0x6bd6, 0x6cbb, 0x6bd6,
+ 0x6bd6, 0x6cc2, 0x6cc9, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6,
+ 0x6ce6, 0x6bd6, 0x6bd6, 0x6cf1, 0x6bd6, 0x6bd6, 0x1078, 0x12d5,
+ 0x1078, 0x3a26, 0x6618, 0x0c7e, 0x2660, 0x1078, 0x3837, 0x0c7f,
+ 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048,
+ 0x6bf9, 0x1078, 0x72b7, 0x00c0, 0x6c34, 0x1078, 0x7255, 0x00c0,
+ 0x6bf5, 0x6007, 0x0008, 0x0078, 0x6cae, 0x6007, 0x0009, 0x0078,
+ 0x6cae, 0x1078, 0x744c, 0x0040, 0x6c03, 0x1078, 0x72b7, 0x0040,
+ 0x6bed, 0x0078, 0x6c34, 0x6013, 0x1900, 0x0078, 0x6bf5, 0x6106,
+ 0x1078, 0x7217, 0x6007, 0x0006, 0x0078, 0x6cae, 0x6007, 0x0007,
+ 0x0078, 0x6cae, 0x0d7e, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00,
+ 0x8637, 0xa686, 0x0006, 0x0040, 0x6c24, 0xa686, 0x0004, 0x0040,
+ 0x6c24, 0x0d7f, 0x0078, 0x6c34, 0x1078, 0x7315, 0x00c0, 0x6c2f,
+ 0x1078, 0x38a1, 0x6007, 0x000a, 0x0d7f, 0x0078, 0x6cae, 0x6007,
+ 0x000b, 0x0d7f, 0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x0001,
+ 0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x000c, 0x0078, 0x6cae,
+ 0x1078, 0x3a26, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff,
+ 0xa082, 0x0006, 0x0048, 0x6c61, 0xa6b4, 0xff00, 0x8637, 0xa686,
+ 0x0006, 0x00c0, 0x6c34, 0x1078, 0x7324, 0x00c0, 0x6c5b, 0x6007,
+ 0x000e, 0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x000f, 0x0078,
+ 0x6cae, 0x1078, 0x744c, 0x0040, 0x6c6e, 0xa6b4, 0xff00, 0x8637,
+ 0xa686, 0x0006, 0x0040, 0x6c53, 0x0078, 0x6c34, 0x6013, 0x1900,
+ 0x6007, 0x0009, 0x0078, 0x6cae, 0x1078, 0x3a26, 0x6618, 0xa6b0,
+ 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x6c99,
+ 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x00c0, 0x6c34, 0x1078,
+ 0x734f, 0x00c0, 0x6c93, 0x1078, 0x7255, 0x00c0, 0x6c93, 0x6007,
+ 0x0010, 0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x0011, 0x0078,
+ 0x6cae, 0x1078, 0x744c, 0x0040, 0x6ca6, 0xa6b4, 0xff00, 0x8637,
+ 0xa686, 0x0006, 0x0040, 0x6c87, 0x0078, 0x6c34, 0x6013, 0x1900,
+ 0x6007, 0x0009, 0x0078, 0x6cae, 0x6007, 0x0012, 0x6003, 0x0001,
+ 0x1078, 0x4872, 0x007c, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078,
+ 0x4872, 0x0078, 0x6cb2, 0x6007, 0x0020, 0x6003, 0x0001, 0x1078,
+ 0x4872, 0x007c, 0x6007, 0x0023, 0x6003, 0x0001, 0x1078, 0x4872,
+ 0x007c, 0x017e, 0x027e, 0x2011, 0x7b88, 0x2214, 0x2c08, 0x1078,
+ 0x7514, 0x00c0, 0x6cda, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700,
+ 0x0078, 0x6cdf, 0x1078, 0x5c02, 0x2160, 0x6007, 0x0025, 0x6003,
+ 0x0001, 0x1078, 0x4872, 0x027f, 0x017f, 0x007c, 0x6106, 0x1078,
+ 0x6cf8, 0x6007, 0x002b, 0x0078, 0x6cae, 0x6007, 0x002c, 0x0078,
+ 0x6cae, 0x6106, 0x1078, 0x6cfd, 0x6007, 0x002e, 0x0078, 0x6cae,
+ 0x0d7e, 0x1078, 0x6d23, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x6d32,
+ 0x00c0, 0x6d1c, 0x680c, 0xa08c, 0xff00, 0x6824, 0xa084, 0x00ff,
+ 0xa115, 0x6212, 0xd1e4, 0x0040, 0x6d11, 0x2009, 0x0001, 0x0078,
+ 0x6d18, 0xd1ec, 0x0040, 0x6d1c, 0x2009, 0x0000, 0xa294, 0x00ff,
+ 0x1078, 0x22ff, 0x0078, 0x6d20, 0xa085, 0x0001, 0x0078, 0x6d21,
+ 0xa006, 0x0d7f, 0x007c, 0x2069, 0x7b8d, 0x6800, 0xa082, 0x0010,
+ 0x00c8, 0x6d30, 0x6013, 0x0000, 0xa085, 0x0001, 0x0078, 0x6d31,
+ 0xa006, 0x007c, 0x6013, 0x0000, 0x2069, 0x7b8c, 0x6808, 0xa084,
+ 0xff00, 0xa086, 0x0800, 0x007c, 0x6004, 0xa0b2, 0x0030, 0x10c8,
+ 0x12d5, 0xa1b6, 0x0013, 0x00c0, 0x6d48, 0x2008, 0x0079, 0x6d5b,
+ 0xa1b6, 0x0027, 0x0040, 0x6d50, 0xa1b6, 0x0014, 0x10c0, 0x12d5,
+ 0x2001, 0x0007, 0x1078, 0x37df, 0x1078, 0x4b81, 0x1078, 0x6aa1,
+ 0x1078, 0x4c7a, 0x007c, 0x6d8b, 0x6d8d, 0x6d8b, 0x6d8b, 0x6d8b,
+ 0x6d8d, 0x6d95, 0x6df8, 0x6dbb, 0x6df8, 0x6dcf, 0x6df8, 0x6d95,
+ 0x6df8, 0x6df0, 0x6df8, 0x6df0, 0x6df8, 0x6df8, 0x6d8b, 0x6d8b,
+ 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b,
+ 0x6d8b, 0x6d8b, 0x6d8b, 0x6df8, 0x6d8b, 0x6d8b, 0x6df8, 0x6d8b,
+ 0x6df8, 0x6df8, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6df8, 0x6df8,
+ 0x6d8b, 0x6df8, 0x6df8, 0x1078, 0x12d5, 0x1078, 0x4b81, 0x6003,
+ 0x0002, 0x1078, 0x4c7a, 0x0078, 0x6dfe, 0x0f7e, 0x2079, 0x7651,
+ 0x7804, 0x0f7f, 0xd0ac, 0x00c0, 0x6df8, 0x2001, 0x0000, 0x1078,
+ 0x37bd, 0x2001, 0x0002, 0x1078, 0x37d1, 0x1078, 0x4b81, 0x601f,
+ 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x4872, 0x1078,
+ 0x4c7a, 0x0c7e, 0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x457b,
+ 0x0c7f, 0x0078, 0x6dfe, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f,
+ 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x6df8, 0xa686,
+ 0x0004, 0x0040, 0x6df8, 0x2001, 0x0004, 0x0078, 0x6df6, 0x2001,
+ 0x7600, 0x2004, 0xa086, 0x0003, 0x00c0, 0x6dd8, 0x1078, 0x2dc8,
+ 0x2001, 0x0006, 0x1078, 0x6dff, 0x6618, 0x0d7e, 0x2668, 0x6e04,
+ 0x0d7f, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x6df8,
+ 0x2001, 0x0006, 0x0078, 0x6df6, 0x2001, 0x0004, 0x0078, 0x6df6,
+ 0x2001, 0x0006, 0x1078, 0x6dff, 0x0078, 0x6df8, 0x1078, 0x37df,
+ 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0x017e,
+ 0x0d7e, 0x6118, 0x2168, 0x6900, 0xd184, 0x0040, 0x6e1a, 0x6104,
+ 0xa18e, 0x000a, 0x00c0, 0x6e12, 0x699c, 0xd1a4, 0x00c0, 0x6e12,
+ 0x2001, 0x0007, 0x1078, 0x37d1, 0x2001, 0x0000, 0x1078, 0x37bd,
+ 0x1078, 0x22dd, 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668,
+ 0x6804, 0xa084, 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8,
+ 0x12d5, 0xa1b6, 0x0015, 0x00c0, 0x6e31, 0x1079, 0x6e38, 0x0078,
+ 0x6e37, 0xa1b6, 0x0016, 0x10c0, 0x12d5, 0x1079, 0x6e70, 0x007c,
+ 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x6e44,
+ 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x0f7e, 0x2079, 0x7651, 0x7804,
+ 0x0f7f, 0xd0ac, 0x00c0, 0x6e60, 0x2001, 0x0000, 0x1078, 0x37bd,
+ 0x2001, 0x0002, 0x1078, 0x37d1, 0x601f, 0x0001, 0x6003, 0x0001,
+ 0x6007, 0x0002, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0078, 0x6e6f,
+ 0x2011, 0x7b83, 0x220c, 0x017e, 0x0c7e, 0x1078, 0x3825, 0x00c0,
+ 0x6e6f, 0x1078, 0x3621, 0x0c7f, 0x017f, 0x1078, 0x5c02, 0x007c,
+ 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x6e7c,
+ 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x1078, 0x60d1, 0x00c0, 0x6e88,
+ 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x4872, 0x0078, 0x6e8a,
+ 0x1078, 0x5c02, 0x007c, 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12d5,
+ 0x1078, 0x4b81, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0xa182,
+ 0x0040, 0x0079, 0x6e9b, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6ead,
+ 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab,
+ 0x6eab, 0x6eab, 0x6eab, 0x1078, 0x12d5, 0x0d7e, 0x0e7e, 0x0f7e,
+ 0x157e, 0x047e, 0x027e, 0x6106, 0x2071, 0x7b80, 0x7444, 0xa4a4,
+ 0xe600, 0x0040, 0x6f1e, 0xa486, 0x2000, 0x0040, 0x6edd, 0xa486,
+ 0x0400, 0x0040, 0x6edd, 0x7130, 0xa18c, 0x00ff, 0xa182, 0x0010,
+ 0x00c8, 0x6fb0, 0x0c7e, 0x1078, 0x460c, 0x2c68, 0x0c7f, 0x6a00,
+ 0xa284, 0x0001, 0x0040, 0x6f91, 0x1078, 0x46ca, 0x0040, 0x6fbc,
+ 0xa295, 0x0200, 0x6a02, 0x0078, 0x6ee3, 0x2009, 0x0001, 0x2011,
+ 0x0200, 0x1078, 0x46b4, 0x1078, 0x132f, 0x1040, 0x12d5, 0x6003,
+ 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000,
+ 0x6c5a, 0x2c00, 0x685e, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130,
+ 0xa18c, 0x00ff, 0xa10d, 0x6946, 0x684f, 0x0000, 0x6857, 0x0036,
+ 0x1078, 0x3a7a, 0xa486, 0x2000, 0x00c0, 0x6f0c, 0x2019, 0x0017,
+ 0x1078, 0x74d9, 0x0078, 0x6f7e, 0xa486, 0x0400, 0x00c0, 0x6f16,
+ 0x2019, 0x0002, 0x1078, 0x74d9, 0x0078, 0x6f7e, 0xa486, 0x0200,
+ 0x00c0, 0x6f1c, 0x1078, 0x74ca, 0x0078, 0x6f7e, 0x7130, 0xa184,
+ 0xff00, 0x00c0, 0x6fd0, 0xa18c, 0x00ff, 0xa182, 0x0010, 0x00c8,
+ 0x6fd0, 0x0c7e, 0x1078, 0x460c, 0x2c68, 0x0c7f, 0x6a00, 0xa284,
+ 0x0001, 0x0040, 0x6fd4, 0xa284, 0x0300, 0x00c0, 0x6fcc, 0x6804,
+ 0xa005, 0x0040, 0x6fbc, 0x8001, 0x6806, 0x6003, 0x0007, 0x1078,
+ 0x1314, 0x0040, 0x6f85, 0x6013, 0x0000, 0x6803, 0x0000, 0x6837,
+ 0x0116, 0x683b, 0x0000, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0,
+ 0x8007, 0xa10d, 0x6946, 0x6853, 0x003d, 0x7044, 0xa084, 0x0003,
+ 0xa086, 0x0002, 0x00c0, 0x6f60, 0x684f, 0x0040, 0x0078, 0x6f6a,
+ 0xa086, 0x0001, 0x00c0, 0x6f68, 0x684f, 0x0080, 0x0078, 0x6f6a,
+ 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0x7b90, 0xad90, 0x0015,
+ 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x6f70, 0x200c,
+ 0x6982, 0x8000, 0x200c, 0x697e, 0x1078, 0x3a7a, 0x027f, 0x047f,
+ 0x157f, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x6013, 0x0100, 0x6003,
+ 0x0001, 0x6007, 0x0041, 0x1078, 0x4825, 0x1078, 0x4c7a, 0x0078,
+ 0x6f7e, 0x2069, 0x7b92, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200,
+ 0x00c0, 0x6fb0, 0x2069, 0x7b80, 0x686c, 0xa084, 0x00ff, 0x017e,
+ 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, 0x0001,
+ 0x6007, 0x0043, 0x1078, 0x4825, 0x1078, 0x4c7a, 0x0078, 0x6f7e,
+ 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4825,
+ 0x1078, 0x4c7a, 0x0078, 0x6f7e, 0x6013, 0x0300, 0x0078, 0x6fc2,
+ 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4825,
+ 0x1078, 0x4c7a, 0x0078, 0x6f7e, 0x6013, 0x0500, 0x0078, 0x6fc2,
+ 0x6013, 0x0600, 0x0078, 0x6f91, 0x6013, 0x0200, 0x0078, 0x6f91,
+ 0xa186, 0x0013, 0x00c0, 0x6fea, 0x6004, 0xa08a, 0x0040, 0x1048,
+ 0x12d5, 0xa08a, 0x0050, 0x10c8, 0x12d5, 0xa082, 0x0040, 0x2008,
+ 0x0079, 0x701b, 0xa186, 0x0047, 0x00c0, 0x6ff0, 0x0078, 0x704a,
+ 0xa186, 0x0027, 0x0040, 0x6ff8, 0xa186, 0x0014, 0x10c0, 0x12d5,
+ 0x6004, 0xa082, 0x0040, 0x2008, 0x0079, 0x6ffe, 0x700e, 0x7010,
+ 0x7010, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e,
+ 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x1078, 0x12d5,
+ 0x2001, 0x0007, 0x1078, 0x37df, 0x1078, 0x4b81, 0x1078, 0x6aa1,
+ 0x1078, 0x4c7a, 0x007c, 0x702b, 0x703b, 0x7034, 0x7044, 0x702b,
+ 0x702b, 0x702b, 0x702b, 0x702b, 0x702b, 0x702b, 0x702b, 0x702b,
+ 0x702b, 0x702b, 0x702b, 0x1078, 0x12d5, 0x6010, 0xa088, 0x0013,
+ 0x2104, 0xa085, 0x0400, 0x200a, 0x1078, 0x4b81, 0x6003, 0x0002,
+ 0x1078, 0x4c7a, 0x007c, 0x1078, 0x4b81, 0x1078, 0x468d, 0x1078,
+ 0x5c02, 0x1078, 0x4c7a, 0x007c, 0x1078, 0x4b81, 0x2009, 0x0041,
+ 0x0078, 0x7112, 0xa182, 0x0040, 0x0079, 0x704e, 0x705e, 0x7060,
+ 0x705e, 0x705e, 0x705e, 0x705e, 0x705e, 0x7061, 0x705e, 0x705e,
+ 0x705e, 0x705e, 0x705e, 0x705e, 0x705e, 0x705e, 0x1078, 0x12d5,
+ 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20,
+ 0x2c10, 0x1078, 0x1572, 0x007c, 0xa182, 0x0040, 0x0079, 0x7070,
+ 0x7080, 0x7080, 0x7080, 0x7080, 0x7080, 0x7080, 0x7080, 0x7080,
+ 0x7080, 0x7082, 0x70a5, 0x7080, 0x7080, 0x7080, 0x7080, 0x70a5,
+ 0x1078, 0x12d5, 0x1078, 0x4c29, 0x1078, 0x4d3a, 0x6010, 0x0d7e,
+ 0x2068, 0x684c, 0xd0fc, 0x0040, 0x7098, 0xa08c, 0x0003, 0xa18e,
+ 0x0002, 0x0040, 0x709e, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x7112,
+ 0x6003, 0x0007, 0x1078, 0x468d, 0x0d7f, 0x007c, 0x1078, 0x468d,
+ 0x1078, 0x5c02, 0x0d7f, 0x0078, 0x709d, 0x037e, 0x1078, 0x4c29,
+ 0x1078, 0x4d3a, 0x6010, 0x0d7e, 0x2068, 0x2019, 0x0004, 0x1078,
+ 0x74fd, 0x1078, 0x6aa1, 0x6017, 0x0028, 0x0d7f, 0x037f, 0x007c,
+ 0xa186, 0x0013, 0x00c0, 0x70c6, 0x6004, 0xa086, 0x0042, 0x10c0,
+ 0x12d5, 0x1078, 0x4b81, 0x1078, 0x4c7a, 0x007c, 0xa186, 0x0027,
+ 0x0040, 0x70ce, 0xa186, 0x0014, 0x00c0, 0x70de, 0x6004, 0xa086,
+ 0x0042, 0x10c0, 0x12d5, 0x2001, 0x0007, 0x1078, 0x37df, 0x1078,
+ 0x4b81, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0xa182, 0x0040,
+ 0x0079, 0x70e2, 0x70f2, 0x70f2, 0x70f2, 0x70f2, 0x70f2, 0x70f2,
+ 0x70f2, 0x70f4, 0x7100, 0x70f2, 0x70f2, 0x70f2, 0x70f2, 0x70f2,
+ 0x70f2, 0x70f2, 0x1078, 0x12d5, 0x037e, 0x047e, 0x20e1, 0x0005,
+ 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x1572, 0x047f, 0x037f, 0x007c,
+ 0x6010, 0x0d7e, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x710c, 0x2009,
+ 0x0041, 0x0d7f, 0x0078, 0x7112, 0x6003, 0x0007, 0x1078, 0x468d,
+ 0x0d7f, 0x007c, 0xa182, 0x0040, 0x0079, 0x7116, 0x7126, 0x7128,
+ 0x7134, 0x7140, 0x7126, 0x7126, 0x7126, 0x7126, 0x7126, 0x7126,
+ 0x7126, 0x7126, 0x7126, 0x7126, 0x7126, 0x7126, 0x1078, 0x12d5,
+ 0x6003, 0x0001, 0x6106, 0x1078, 0x4825, 0x127e, 0x2091, 0x8000,
+ 0x1078, 0x4c7a, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078,
+ 0x4825, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x007c,
+ 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, 0x19cf, 0x127e, 0x2091,
+ 0x8000, 0x1078, 0x4891, 0x1078, 0x4d3a, 0x127f, 0x007c, 0x1078,
+ 0x4b81, 0x0078, 0x7155, 0x1078, 0x4c29, 0x6110, 0x81ff, 0x0040,
+ 0x7162, 0x0d7e, 0x2168, 0x037e, 0x2019, 0x0029, 0x1078, 0x74fd,
+ 0x037f, 0x0d7f, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0xa182,
+ 0x0085, 0x0079, 0x716b, 0x7172, 0x7172, 0x7172, 0x7174, 0x7172,
+ 0x7172, 0x7172, 0x1078, 0x12d5, 0x027e, 0x0e7e, 0x2071, 0x7b80,
+ 0x7220, 0x1078, 0x7417, 0x0040, 0x7181, 0x6007, 0x0086, 0x0078,
+ 0x7183, 0x6007, 0x0087, 0x6003, 0x0001, 0x1078, 0x4825, 0x1078,
+ 0x4c7a, 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x719d,
+ 0x6004, 0xa08a, 0x0085, 0x1048, 0x12d5, 0xa08a, 0x008c, 0x10c8,
+ 0x12d5, 0xa082, 0x0085, 0x0079, 0x71b0, 0xa186, 0x0027, 0x0040,
+ 0x71a5, 0xa186, 0x0014, 0x10c0, 0x12d5, 0x2001, 0x0007, 0x1078,
+ 0x37df, 0x1078, 0x4b81, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c,
+ 0x71b7, 0x71b9, 0x71b9, 0x71b7, 0x71b7, 0x71b7, 0x71b7, 0x1078,
+ 0x12d5, 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c,
+ 0xa182, 0x0085, 0x1048, 0x12d5, 0xa182, 0x008c, 0x10c8, 0x12d5,
+ 0xa182, 0x0085, 0x0079, 0x71cc, 0x71d3, 0x71d3, 0x71d3, 0x71d5,
+ 0x71d3, 0x71d3, 0x71d3, 0x1078, 0x12d5, 0x007c, 0x1078, 0x4b81,
+ 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0x037e, 0x2019, 0x000b,
+ 0x1078, 0x71e6, 0x601f, 0x0006, 0x037f, 0x007c, 0x127e, 0x037e,
+ 0x087e, 0x2091, 0x8000, 0x2c40, 0x1078, 0x5915, 0x00c0, 0x7213,
+ 0x1078, 0x59b6, 0x00c0, 0x7213, 0x6000, 0xa086, 0x0000, 0x0040,
+ 0x7213, 0x601c, 0xa086, 0x0007, 0x0040, 0x7213, 0x0d7e, 0x6000,
+ 0xa086, 0x0004, 0x00c0, 0x7206, 0x1078, 0x1676, 0x6010, 0x2068,
+ 0x1078, 0x693e, 0x0040, 0x720e, 0x1078, 0x74fd, 0x0d7f, 0x6013,
+ 0x0000, 0x601f, 0x0007, 0x087f, 0x037f, 0x127f, 0x007c, 0x0f7e,
+ 0x0c7e, 0x037e, 0x157e, 0x2079, 0x7b80, 0x7838, 0xa08c, 0x00ff,
+ 0x783c, 0x1078, 0x2085, 0x00c0, 0x724e, 0x017e, 0x0c7e, 0x1078,
+ 0x3825, 0x00c0, 0x724e, 0x2011, 0x7b90, 0xac98, 0x000a, 0x20a9,
+ 0x0004, 0x1078, 0x616a, 0x00c0, 0x724e, 0x017f, 0x027f, 0x027e,
+ 0x017e, 0x2019, 0x0029, 0x1078, 0x5a8a, 0x1078, 0x4962, 0x1078,
+ 0x48a5, 0x017f, 0x1078, 0x737b, 0x1078, 0x39a6, 0x017f, 0x1078,
+ 0x3621, 0x6612, 0x6516, 0xa006, 0x0078, 0x7250, 0x0c7f, 0x017f,
+ 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, 0x0c7e, 0x0d7e, 0x017e,
+ 0x2009, 0x761e, 0x2104, 0xa086, 0x0074, 0x00c0, 0x72ac, 0x2069,
+ 0x7b8e, 0x690c, 0xa182, 0x0100, 0x0048, 0x729c, 0x6908, 0xa184,
+ 0x8000, 0x0040, 0x72a8, 0xa184, 0x0800, 0x0040, 0x72a8, 0x6910,
+ 0xa18a, 0x0001, 0x0048, 0x72a0, 0x6914, 0x2069, 0x7bae, 0x6904,
+ 0x81ff, 0x00c0, 0x7294, 0x690c, 0xa182, 0x0100, 0x0048, 0x729c,
+ 0x6908, 0x81ff, 0x00c0, 0x7298, 0x6910, 0xa18a, 0x0001, 0x0048,
+ 0x72a0, 0x6918, 0xa18a, 0x0001, 0x0048, 0x72a8, 0x0078, 0x72b2,
+ 0x6013, 0x0100, 0x0078, 0x72ae, 0x6013, 0x0300, 0x0078, 0x72ae,
+ 0x6013, 0x0500, 0x0078, 0x72ae, 0x6013, 0x0700, 0x0078, 0x72ae,
+ 0x6013, 0x0900, 0x0078, 0x72ae, 0x6013, 0x0b00, 0x0078, 0x72ae,
+ 0x6013, 0x0f00, 0x0078, 0x72ae, 0x6013, 0x2d00, 0xa085, 0x0001,
+ 0x0078, 0x72b3, 0xa006, 0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e,
+ 0x0d7e, 0x027e, 0x037e, 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394,
+ 0x00ff, 0xa286, 0x0006, 0x0040, 0x72db, 0xa286, 0x0004, 0x0040,
+ 0x72db, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x72db,
+ 0xa286, 0x0004, 0x0040, 0x72db, 0x0c7e, 0x2d60, 0x1078, 0x3837,
+ 0x0c7f, 0x0078, 0x730e, 0x2011, 0x7b96, 0xad98, 0x000a, 0x20a9,
+ 0x0004, 0x1078, 0x616a, 0x00c0, 0x730f, 0x2011, 0x7b9a, 0xad98,
+ 0x0006, 0x20a9, 0x0004, 0x1078, 0x616a, 0x00c0, 0x730f, 0x047e,
+ 0x017e, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x7652,
+ 0x210c, 0xd1a4, 0x0040, 0x7303, 0x2009, 0x0029, 0x1078, 0x7541,
+ 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x1078, 0x4962, 0x1078,
+ 0x48a5, 0x2c08, 0x1078, 0x737b, 0x017f, 0x047f, 0xa006, 0x157f,
+ 0x037f, 0x027f, 0x0d7f, 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0x7b8e,
+ 0x6800, 0xa086, 0x0800, 0x0040, 0x7321, 0x6013, 0x0000, 0x0078,
+ 0x7322, 0xa006, 0x0d7f, 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e,
+ 0x037e, 0x157e, 0x2079, 0x7b8c, 0x7930, 0x7834, 0x1078, 0x2085,
+ 0x00c0, 0x7348, 0x1078, 0x3825, 0x00c0, 0x7348, 0x2011, 0x7b90,
+ 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x616a, 0x00c0, 0x7348,
+ 0x2011, 0x7b94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x616a,
+ 0x157f, 0x037f, 0x027f, 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e,
+ 0x007e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2011, 0x7b83, 0x2204,
+ 0x8211, 0x220c, 0x1078, 0x2085, 0x00c0, 0x7374, 0x1078, 0x3825,
+ 0x00c0, 0x7374, 0x2011, 0x7b96, 0xac98, 0x000a, 0x20a9, 0x0004,
+ 0x1078, 0x616a, 0x00c0, 0x7374, 0x2011, 0x7b9a, 0xac98, 0x0006,
+ 0x20a9, 0x0004, 0x1078, 0x616a, 0x157f, 0x037f, 0x027f, 0x017f,
+ 0x007f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e,
+ 0x047e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2029, 0x783f, 0x252c,
+ 0x2021, 0x7845, 0x2424, 0x2061, 0x7d00, 0x2071, 0x7600, 0x7644,
+ 0x7060, 0x8001, 0xa602, 0x00c8, 0x73e0, 0x2100, 0xac06, 0x0040,
+ 0x73d6, 0x1078, 0x7559, 0x0040, 0x73d6, 0x671c, 0xa786, 0x0001,
+ 0x0040, 0x73f5, 0xa786, 0x0007, 0x0040, 0x73d6, 0x2500, 0xac06,
+ 0x0040, 0x73d6, 0x2400, 0xac06, 0x0040, 0x73d6, 0x1078, 0x756d,
+ 0x00c0, 0x73d6, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x73bc,
+ 0x017e, 0x1078, 0x1676, 0x017f, 0x6010, 0x2068, 0x1078, 0x693e,
+ 0x0040, 0x73d3, 0xa786, 0x0003, 0x00c0, 0x73e9, 0x6837, 0x0103,
+ 0x6b4a, 0x6847, 0x0000, 0x017e, 0x1078, 0x6b3f, 0x1078, 0x3a7a,
+ 0x017f, 0x1078, 0x6a94, 0x0d7f, 0x1078, 0x6aa1, 0xace0, 0x0008,
+ 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x73e0, 0x0078, 0x738d,
+ 0x127f, 0x027f, 0x047f, 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f,
+ 0x007c, 0xa786, 0x0006, 0x00c0, 0x73c6, 0xa386, 0x0005, 0x0040,
+ 0x73d6, 0x1078, 0x74fd, 0x0078, 0x73d3, 0x1078, 0x756d, 0x00c0,
+ 0x73d6, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x00c0, 0x73d6,
+ 0x6000, 0xa086, 0x0002, 0x00c0, 0x73d6, 0x1078, 0x6aba, 0x0040,
+ 0x7411, 0x1078, 0x6ace, 0x00c0, 0x73d6, 0x1078, 0x5e57, 0x0078,
+ 0x7413, 0x1078, 0x22dd, 0x1078, 0x6aa1, 0x0078, 0x73d6, 0x0c7e,
+ 0x0e7e, 0x017e, 0x2c08, 0x2170, 0x1078, 0x7514, 0x017f, 0x0040,
+ 0x7426, 0x601c, 0xa084, 0x000f, 0x1079, 0x7429, 0x0e7f, 0x0c7f,
+ 0x007c, 0x7431, 0x7431, 0x7431, 0x7431, 0x7431, 0x7431, 0x7433,
+ 0x7431, 0xa006, 0x007c, 0x047e, 0x017e, 0x7018, 0xa080, 0x0028,
+ 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, 0x1078,
+ 0x7541, 0x017f, 0x047f, 0x037e, 0x2019, 0x0002, 0x1078, 0x71e6,
+ 0x037f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0001, 0x1078, 0x37bd,
+ 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019, 0x7605,
+ 0x2011, 0x7b96, 0x1078, 0x616a, 0x037f, 0x027f, 0x017f, 0x157f,
+ 0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x027e,
+ 0x127e, 0x2091, 0x8000, 0x2061, 0x7d00, 0x2079, 0x0001, 0x8fff,
+ 0x0040, 0x74bd, 0x2071, 0x7600, 0x7644, 0x7060, 0x8001, 0xa602,
+ 0x00c8, 0x74bd, 0x88ff, 0x0040, 0x7483, 0x2800, 0xac06, 0x00c0,
+ 0x74b3, 0x2079, 0x0000, 0x1078, 0x7559, 0x0040, 0x74b3, 0x2400,
+ 0xac06, 0x0040, 0x74b3, 0x671c, 0xa786, 0x0006, 0x00c0, 0x74b3,
+ 0xa786, 0x0007, 0x0040, 0x74b3, 0x88ff, 0x00c0, 0x749b, 0x6018,
+ 0xa206, 0x00c0, 0x74b3, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0,
+ 0x74a3, 0x1078, 0x1676, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040,
+ 0x74ad, 0x047e, 0x1078, 0x74fd, 0x047f, 0x0d7f, 0x1078, 0x6aa1,
+ 0x88ff, 0x00c0, 0x74c6, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004,
+ 0xac02, 0x00c8, 0x74bd, 0x0078, 0x746f, 0xa006, 0x127f, 0x027f,
+ 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001,
+ 0x0078, 0x74be, 0x087e, 0x2041, 0x0000, 0x2c20, 0x2019, 0x0002,
+ 0x6218, 0x1078, 0x5915, 0x1078, 0x59b6, 0x1078, 0x7462, 0x087f,
+ 0x007c, 0x027e, 0x047e, 0x087e, 0x0c7e, 0x157e, 0x2c20, 0x20a9,
+ 0x007f, 0x2009, 0x0000, 0x017e, 0x037e, 0x1078, 0x3825, 0x00c0,
+ 0x74f2, 0x2c10, 0x2041, 0x0000, 0x1078, 0x5915, 0x1078, 0x59b6,
+ 0x1078, 0x7462, 0x037f, 0x017f, 0x8108, 0x00f0, 0x74e3, 0x157f,
+ 0x0c7f, 0x087f, 0x047f, 0x027f, 0x007c, 0x017e, 0x0f7e, 0x8dff,
+ 0x0040, 0x7511, 0x6800, 0xa07d, 0x0040, 0x750e, 0x6803, 0x0000,
+ 0x6b52, 0x1078, 0x3a7a, 0x2f68, 0x0078, 0x7502, 0x6b52, 0x1078,
+ 0x3a7a, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061,
+ 0x7d00, 0x2071, 0x7600, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8,
+ 0x753c, 0x2100, 0xac06, 0x0040, 0x752e, 0x6000, 0xa086, 0x0000,
+ 0x0040, 0x752e, 0x6008, 0xa206, 0x0040, 0x7538, 0xace0, 0x0008,
+ 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x753c, 0x0078, 0x7519,
+ 0xa085, 0x0001, 0x0078, 0x753d, 0xa006, 0x037f, 0x047f, 0x0e7f,
+ 0x007c, 0x0d7e, 0x007e, 0x1078, 0x132f, 0x007f, 0x1040, 0x12d5,
+ 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b, 0x0000,
+ 0x685e, 0x6956, 0x6c46, 0x684f, 0x0000, 0x1078, 0x3a7a, 0x0d7f,
+ 0x007c, 0x6700, 0xa786, 0x0000, 0x0040, 0x756c, 0xa786, 0x0001,
+ 0x0040, 0x756c, 0xa786, 0x000a, 0x0040, 0x756c, 0xa786, 0x0009,
+ 0x0040, 0x756c, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x6018, 0x2070,
+ 0x70a0, 0xa206, 0x0e7f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091,
+ 0x8000, 0x2071, 0x7640, 0xd5a4, 0x0040, 0x7581, 0x7034, 0x8000,
+ 0x7036, 0xd5b4, 0x0040, 0x7587, 0x7030, 0x8000, 0x7032, 0xd5ac,
+ 0x0040, 0x758e, 0x2071, 0x764a, 0x1078, 0x75bd, 0x0e7f, 0x007f,
+ 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071,
+ 0x7640, 0xd5a4, 0x0040, 0x759f, 0x7034, 0x8000, 0x7036, 0xd5b4,
+ 0x0040, 0x75a5, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0x75ac,
+ 0x2071, 0x764a, 0x1078, 0x75bd, 0x0e7f, 0x007f, 0x127f, 0x007c,
+ 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x7642, 0x1078,
+ 0x75bd, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x2e04, 0x8000, 0x2072,
+ 0x00c8, 0x75c6, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e,
+ 0x2071, 0x7640, 0x1078, 0x75bd, 0x0e7f, 0x007c, 0x0e7e, 0x2071,
+ 0x7644, 0x1078, 0x75bd, 0x0e7f, 0x007c, 0x0001, 0x0002, 0x0004,
+ 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400,
+ 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0xaaff
+};
+unsigned short risc_code_length01 = 0x65e6;
+
diff --git a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c
index d33da018a..436a95d01 100644
--- a/drivers/scsi/qlogicisp.c
+++ b/drivers/scsi/qlogicisp.c
@@ -27,6 +27,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/spinlock.h>
+#include <asm/byteorder.h>
#include "sd.h"
#include "hosts.h"
@@ -49,7 +50,7 @@
/* Macros used for debugging */
#define DEBUG_ISP1020 0
-#define DEBUG_ISP1020_INT 0
+#define DEBUG_ISP1020_INTR 0
#define DEBUG_ISP1020_SETUP 0
#define TRACE_ISP 0
@@ -730,17 +731,17 @@ int isp1020_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *))
cmd->hdr.entry_type = ENTRY_COMMAND;
cmd->hdr.entry_cnt = 1;
- cmd->handle = (u_int) virt_to_bus(Cmnd);
+ cmd->handle = cpu_to_le32((u_int) virt_to_bus(Cmnd));
cmd->target_lun = Cmnd->lun;
cmd->target_id = Cmnd->target;
- cmd->cdb_length = Cmnd->cmd_len;
- cmd->control_flags = CFLAG_READ | CFLAG_WRITE;
- cmd->time_out = 30;
+ cmd->cdb_length = cpu_to_le16(Cmnd->cmd_len);
+ cmd->control_flags = cpu_to_le16(CFLAG_READ | CFLAG_WRITE);
+ cmd->time_out = cpu_to_le16(30);
memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);
if (Cmnd->use_sg) {
- cmd->segment_cnt = sg_count = Cmnd->use_sg;
+ cmd->segment_cnt = cpu_to_le16(sg_count = Cmnd->use_sg);
sg = (struct scatterlist *) Cmnd->request_buffer;
ds = cmd->dataseg;
@@ -749,8 +750,8 @@ int isp1020_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *))
if (n > 4)
n = 4;
for (i = 0; i < n; i++) {
- ds[i].d_base = (u_int) virt_to_bus(sg->address);
- ds[i].d_count = sg->length;
+ ds[i].d_base = cpu_to_le32((u_int) virt_to_bus(sg->address));
+ ds[i].d_count = cpu_to_le32(sg->length);
++sg;
}
sg_count -= 4;
@@ -776,18 +777,18 @@ int isp1020_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *))
if (n > 7)
n = 7;
for (i = 0; i < n; ++i) {
- ds[i].d_base = (u_int)virt_to_bus(sg->address);
- ds[i].d_count = sg->length;
+ ds[i].d_base = cpu_to_le32((u_int)virt_to_bus(sg->address));
+ ds[i].d_count = cpu_to_le32(sg->length);
++sg;
}
sg_count -= n;
}
} else {
cmd->dataseg[0].d_base =
- (u_int) virt_to_bus(Cmnd->request_buffer);
+ cpu_to_le32((u_int) virt_to_bus(Cmnd->request_buffer));
cmd->dataseg[0].d_count =
- (u_int) Cmnd->request_bufflen;
- cmd->segment_cnt = 1;
+ cpu_to_le32((u_int) Cmnd->request_bufflen);
+ cmd->segment_cnt = cpu_to_le16(1);
}
outw(in_ptr, host->io_port + MBOX4);
@@ -861,22 +862,22 @@ void isp1020_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
DEBUG_INTR(printk("qlogicisp : response queue update\n"));
DEBUG_INTR(printk("qlogicisp : response queue depth %d\n",
- QUEUE_DEPTH(in_ptr, out_ptr)));
+ QUEUE_DEPTH(in_ptr, out_ptr, RES_QUEUE_LEN)));
while (out_ptr != in_ptr) {
sts = (struct Status_Entry *) &hostdata->res[out_ptr][0];
out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;
- Cmnd = (Scsi_Cmnd *) bus_to_virt(sts->handle);
+ Cmnd = (Scsi_Cmnd *) bus_to_virt(le32_to_cpu(sts->handle));
TRACE("done", out_ptr, Cmnd);
- if (sts->completion_status == CS_RESET_OCCURRED
- || sts->completion_status == CS_ABORTED
- || (sts->status_flags & STF_BUS_RESET))
+ if (le16_to_cpu(sts->completion_status) == CS_RESET_OCCURRED
+ || le16_to_cpu(sts->completion_status) == CS_ABORTED
+ || (le16_to_cpu(sts->status_flags) & STF_BUS_RESET))
hostdata->send_marker = 1;
- if (sts->state_flags & SF_GOT_SENSE)
+ if (le16_to_cpu(sts->state_flags) & SF_GOT_SENSE)
memcpy(Cmnd->sense_buffer, sts->req_sense_data,
sizeof(Cmnd->sense_buffer));
@@ -917,24 +918,24 @@ static int isp1020_return_status(struct Status_Entry *sts)
ENTER("isp1020_return_status");
DEBUG(printk("qlogicisp : completion status = 0x%04x\n",
- sts->completion_status));
+ le16_to_cpu(sts->completion_status)));
- switch(sts->completion_status) {
+ switch(le16_to_cpu(sts->completion_status)) {
case CS_COMPLETE:
host_status = DID_OK;
break;
case CS_INCOMPLETE:
- if (!(sts->state_flags & SF_GOT_BUS))
+ if (!(le16_to_cpu(sts->state_flags) & SF_GOT_BUS))
host_status = DID_NO_CONNECT;
- else if (!(sts->state_flags & SF_GOT_TARGET))
+ else if (!(le16_to_cpu(sts->state_flags) & SF_GOT_TARGET))
host_status = DID_BAD_TARGET;
- else if (!(sts->state_flags & SF_SENT_CDB))
+ else if (!(le16_to_cpu(sts->state_flags) & SF_SENT_CDB))
host_status = DID_ERROR;
- else if (!(sts->state_flags & SF_TRANSFERRED_DATA))
+ else if (!(le16_to_cpu(sts->state_flags) & SF_TRANSFERRED_DATA))
host_status = DID_ERROR;
- else if (!(sts->state_flags & SF_GOT_STATUS))
+ else if (!(le16_to_cpu(sts->state_flags) & SF_GOT_STATUS))
host_status = DID_ERROR;
- else if (!(sts->state_flags & SF_GOT_SENSE))
+ else if (!(le16_to_cpu(sts->state_flags) & SF_GOT_SENSE))
host_status = DID_ERROR;
break;
case CS_DMA_ERROR:
@@ -970,17 +971,17 @@ static int isp1020_return_status(struct Status_Entry *sts)
break;
default:
printk("qlogicisp : unknown completion status 0x%04x\n",
- sts->completion_status);
+ le16_to_cpu(sts->completion_status));
host_status = DID_ERROR;
break;
}
DEBUG_INTR(printk("qlogicisp : host status (%s) scsi status %x\n",
- reason[host_status], sts->scsi_status));
+ reason[host_status], le16_to_cpu(sts->scsi_status)));
LEAVE("isp1020_return_status");
- return (sts->scsi_status & STATUS_MASK) | (host_status << 16);
+ return (le16_to_cpu(sts->scsi_status) & STATUS_MASK) | (host_status << 16);
}
@@ -1082,7 +1083,9 @@ static int isp1020_reset_hardware(struct Scsi_Host *host)
ENTER("isp1020_reset_hardware");
outw(ISP_RESET, host->io_port + PCI_INTF_CTL);
+ udelay(100);
outw(HCCR_RESET, host->io_port + HOST_HCCR);
+ udelay(100);
outw(HCCR_RELEASE, host->io_port + HOST_HCCR);
outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR);
@@ -1103,27 +1106,25 @@ static int isp1020_reset_hardware(struct Scsi_Host *host)
printk("qlogicisp : mbox 5 0x%04x \n", inw(host->io_port + MBOX5));
#endif /* DEBUG_ISP1020 */
+ param[0] = MBOX_NO_OP;
+ isp1020_mbox_command(host, param);
+ if (param[0] != MBOX_COMMAND_COMPLETE) {
+ printk("qlogicisp : NOP test failed\n");
+ return 1;
+ }
+
DEBUG(printk("qlogicisp : loading risc ram\n"));
#if RELOAD_FIRMWARE
- /* Do not reload firmware if 1040B, i.e. revision 5 chip. */
- if (((struct isp1020_hostdata *) host->hostdata)->revision >= 5)
- printk("qlogicisp : 1040B or later chip,"
- " firmware not (re)loaded\n");
- else
- {
- 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];
-
- isp1020_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicisp : firmware load failure\n");
- return 1;
- }
+ for (loop_count = 0; loop_count < risc_code_length01; loop_count++) {
+ param[0] = MBOX_WRITE_RAM_WORD;
+ param[1] = risc_code_addr01 + loop_count;
+ param[2] = risc_code01[loop_count];
+ isp1020_mbox_command(host, param);
+ if (param[0] != MBOX_COMMAND_COMPLETE) {
+ printk("qlogicisp : firmware load failure at %d\n",
+ loop_count);
+ return 1;
}
}
#endif /* RELOAD_FIRMWARE */
@@ -1200,6 +1201,15 @@ static int isp1020_init(struct Scsi_Host *sh)
return 1;
}
+#ifdef __sparc__
+ command |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY|
+ PCI_COMMAND_INVALIDATE|PCI_COMMAND_SERR);
+ pci_write_config_word(pdev, PCI_COMMAND, command);
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 16);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+#endif
+
if (command & PCI_COMMAND_IO && (io_base & 3) == 1)
io_base &= PCI_BASE_ADDRESS_IO_MASK;
else {
@@ -1227,6 +1237,8 @@ static int isp1020_init(struct Scsi_Host *sh)
sh->irq = irq;
sh->io_port = io_base;
+ sh->max_id = MAX_TARGETS;
+ sh->max_lun = MAX_LUNS;
LEAVE("isp1020_init");
@@ -1691,14 +1703,15 @@ void isp1020_print_status_entry(struct Status_Entry *status)
printk("qlogicisp : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n",
status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags);
printk("qlogicisp : scsi status = 0x%04x, completion status = 0x%04x\n",
- status->scsi_status, status->completion_status);
+ le16_to_cpu(status->scsi_status), le16_to_cpu(status->completion_status));
printk("qlogicisp : state flags = 0x%04x, status flags = 0x%04x\n",
- status->state_flags, status->status_flags);
+ le16_to_cpu(status->state_flags), le16_to_cpu(status->status_flags));
printk("qlogicisp : time = 0x%04x, request sense length = 0x%04x\n",
- status->time, status->req_sense_len);
- printk("qlogicisp : residual transfer length = 0x%08x\n", status->residual);
+ le16_to_cpu(status->time), le16_to_cpu(status->req_sense_len));
+ printk("qlogicisp : residual transfer length = 0x%08x\n",
+ le32_to_cpu(status->residual));
- for (i = 0; i < status->req_sense_len; i++)
+ for (i = 0; i < le16_to_cpu(status->req_sense_len); i++)
printk("qlogicisp : sense data = 0x%02x\n", status->req_sense_data[i]);
}
diff --git a/drivers/scsi/qlogicisp_asm.c b/drivers/scsi/qlogicisp_asm.c
index 0b1828ca0..9ea4beca4 100644
--- a/drivers/scsi/qlogicisp_asm.c
+++ b/drivers/scsi/qlogicisp_asm.c
@@ -1,1304 +1,2034 @@
/*
- * Version 2.10 Initiator Firmware (16:13 Oct 18, 1995)
+ * Firmware Version 7.63.00 (12:07 Jan 27, 1999)
*/
-
-static const unsigned short risc_code_version = 2*1024+10;
+static const unsigned short risc_code_version = 7*1024+63;
static const unsigned short risc_code_addr01 = 0x1000 ;
#if RELOAD_FIRMWARE
-static const unsigned short risc_code01[] = {
- 0x0078, 0x1041, 0x0000, 0x283a, 0x0000, 0x2043, 0x4f50, 0x5952,
- 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31,
- 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320,
- 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350,
- 0x3130, 0x3230, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056,
- 0x6572, 0x7369, 0x6f6e, 0x2030, 0x322e, 0x3130, 0x2020, 0x2043,
- 0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050,
- 0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020,
- 0x2400, 0x20b9, 0x1212, 0x2071, 0x0010, 0x70c3, 0x0004, 0x20c9,
- 0x43ff, 0x2089, 0x115b, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf,
- 0x2020, 0x70d3, 0x0002, 0x3f00, 0x70d6, 0x20c1, 0x0008, 0x2019,
- 0x0000, 0x2009, 0xfeff, 0x2100, 0x200b, 0xa5a5, 0xa1ec, 0x7fff,
- 0x2d64, 0x206b, 0x0a0a, 0xaddc, 0x3fff, 0x2b54, 0x205b, 0x5050,
- 0x2114, 0xa286, 0xa5a5, 0x0040, 0x10b3, 0xa386, 0x000f, 0x0040,
- 0x1079, 0x2c6a, 0x2a5a, 0x20c1, 0x0000, 0x2019, 0x000f, 0x0078,
- 0x1059, 0x2c6a, 0x2a5a, 0x20c1, 0x0008, 0x2009, 0x7fff, 0x2148,
- 0x2944, 0x204b, 0x0a0a, 0xa9bc, 0x3fff, 0x2734, 0x203b, 0x5050,
- 0x2114, 0xa286, 0x0a0a, 0x0040, 0x109d, 0x284a, 0x263a, 0x20c1,
- 0x0004, 0x2009, 0x3fff, 0x2134, 0x200b, 0x5050, 0x2114, 0xa286,
- 0x5050, 0x0040, 0x109e, 0x0078, 0x1163, 0x284a, 0x263a, 0x98c0,
- 0xa188, 0x1000, 0x212c, 0x200b, 0xa5a5, 0x2114, 0xa286, 0xa5a5,
- 0x0040, 0x10b0, 0x250a, 0xa18a, 0x1000, 0x98c1, 0x0078, 0x10b5,
- 0x250a, 0x0078, 0x10b5, 0x2c6a, 0x2a5a, 0x2130, 0xa18a, 0x0040,
- 0x2128, 0xa1a2, 0x3900, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
- 0x8424, 0xa192, 0x4400, 0x2009, 0x0000, 0x2001, 0x002f, 0x1078,
- 0x1a70, 0x2218, 0x2079, 0x3900, 0x2fa0, 0x2408, 0x2011, 0x0000,
- 0x20a9, 0x0040, 0x42a4, 0x8109, 0x00c0, 0x10d0, 0x7eea, 0x7dde,
- 0x8528, 0x7dda, 0x7ce2, 0x7be6, 0x787b, 0x0000, 0x2031, 0x0030,
- 0x78c3, 0x0101, 0x780b, 0x0002, 0x780f, 0x0002, 0x784f, 0x0003,
- 0x2069, 0x3940, 0x681b, 0x0028, 0x6807, 0x0007, 0x680b, 0x00fa,
- 0x680f, 0x0008, 0x6813, 0x0005, 0x681f, 0x0000, 0x6823, 0x0006,
- 0x6817, 0x0008, 0x6827, 0x0000, 0x2069, 0x3a00, 0x2011, 0x0020,
- 0x2009, 0x0010, 0x680b, 0x0c19, 0x680f, 0x0019, 0x6803, 0xfd00,
+static const unsigned short risc_code01[] = {
+ 0x0078, 0x103a, 0x0000, 0x3f14, 0x0000, 0x2043, 0x4f50, 0x5952,
+ 0x4947, 0x4854, 0x2031, 0x3939, 0x3520, 0x514c, 0x4f47, 0x4943,
+ 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350,
+ 0x3130, 0x3230, 0x2049, 0x2f54, 0x2046, 0x6972, 0x6d77, 0x6172,
+ 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x372e, 0x3633,
+ 0x2020, 0x2043, 0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20,
+ 0x3030, 0x2050, 0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020,
+ 0x3031, 0x2024, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x0048,
+ 0x1045, 0x0038, 0x104b, 0x0078, 0x1047, 0x0028, 0x104b, 0x20b9,
+ 0x1212, 0x0078, 0x104d, 0x20b9, 0x2222, 0x20c1, 0x0008, 0x2071,
+ 0x0010, 0x70c3, 0x0004, 0x20c9, 0x76ff, 0x2089, 0x1186, 0x70c7,
+ 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0007, 0x3f00,
+ 0x70d6, 0x20c1, 0x0008, 0x2019, 0x0000, 0x2009, 0xfeff, 0x2100,
+ 0x200b, 0xa5a5, 0xa1ec, 0x7fff, 0x2d64, 0x206b, 0x0a0a, 0xaddc,
+ 0x3fff, 0x2b54, 0x205b, 0x5050, 0x2114, 0xa286, 0xa5a5, 0x0040,
+ 0x10bf, 0xa386, 0x000f, 0x0040, 0x1085, 0x2c6a, 0x2a5a, 0x20c1,
+ 0x0000, 0x2019, 0x000f, 0x0078, 0x1065, 0x2c6a, 0x2a5a, 0x20c1,
+ 0x0008, 0x2009, 0x7fff, 0x2148, 0x2944, 0x204b, 0x0a0a, 0xa9bc,
+ 0x3fff, 0x2734, 0x203b, 0x5050, 0x2114, 0xa286, 0x0a0a, 0x0040,
+ 0x10a9, 0x284a, 0x263a, 0x20c1, 0x0004, 0x2009, 0x3fff, 0x2134,
+ 0x200b, 0x5050, 0x2114, 0xa286, 0x5050, 0x0040, 0x10aa, 0x0078,
+ 0x118e, 0x284a, 0x263a, 0x98c0, 0xa188, 0x1000, 0x212c, 0x200b,
+ 0xa5a5, 0x2114, 0xa286, 0xa5a5, 0x0040, 0x10bc, 0x250a, 0xa18a,
+ 0x1000, 0x98c1, 0x0078, 0x10c1, 0x250a, 0x0078, 0x10c1, 0x2c6a,
+ 0x2a5a, 0x2130, 0xa18a, 0x0040, 0x2128, 0xa1a2, 0x5000, 0x8424,
+ 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0xa192, 0x7700, 0x2009,
+ 0x0000, 0x2001, 0x0031, 0x1078, 0x1c9d, 0x2218, 0x2079, 0x5000,
+ 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9, 0x0040, 0x42a4, 0x8109,
+ 0x00c0, 0x10dc, 0x7ef2, 0x8528, 0x7de6, 0x7cea, 0x7bee, 0x7883,
+ 0x0000, 0x2031, 0x0030, 0x78cf, 0x0101, 0x780b, 0x0002, 0x780f,
+ 0x0002, 0x784f, 0x0003, 0x2069, 0x5040, 0x2001, 0x04fd, 0x2004,
+ 0xa082, 0x0005, 0x0048, 0x1104, 0x0038, 0x1100, 0x0078, 0x1108,
+ 0x681b, 0x003c, 0x0078, 0x110a, 0x00a8, 0x1108, 0x681b, 0x003c,
+ 0x681b, 0x0028, 0x6807, 0x0007, 0x680b, 0x00fa, 0x680f, 0x0008,
+ 0x6813, 0x0005, 0x6823, 0x0000, 0x6827, 0x0006, 0x6817, 0x0008,
+ 0x682b, 0x0000, 0x681f, 0x0019, 0x2069, 0x5280, 0x2011, 0x0020,
+ 0x2009, 0x0010, 0x680b, 0x080c, 0x680f, 0x0019, 0x6803, 0xfd00,
0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004,
- 0x8109, 0x00c0, 0x1102, 0x2069, 0x3a80, 0x20a9, 0x0080, 0x680b,
- 0x0040, 0x7be8, 0xa386, 0xfeff, 0x00c0, 0x1124, 0x6817, 0x0100,
- 0x681f, 0x0064, 0x0078, 0x1128, 0x6817, 0x0064, 0x681f, 0x0002,
- 0xade8, 0x0010, 0x0070, 0x112e, 0x0078, 0x1117, 0x1078, 0x1d15,
- 0x1078, 0x3366, 0x1078, 0x18a4, 0x1078, 0x37fc, 0x3200, 0xa085,
- 0x000d, 0x2090, 0x70c3, 0x0000, 0x0090, 0x1145, 0x70c0, 0xa086,
- 0x0002, 0x00c0, 0x1145, 0x1078, 0x1274, 0x1078, 0x1186, 0x78c0,
- 0xa005, 0x00c0, 0x1151, 0x1078, 0x1a99, 0x0068, 0x1155, 0x1078,
- 0x1c6f, 0x0068, 0x1155, 0x1078, 0x1997, 0x00e0, 0x1145, 0x1078,
- 0x369a, 0x0078, 0x1145, 0x1163, 0x1165, 0x1ebb, 0x1ebb, 0x33d7,
- 0x33d7, 0x1ebb, 0x1ebb, 0x0078, 0x1163, 0x0078, 0x1165, 0x0078,
- 0x1167, 0x0078, 0x1169, 0x2009, 0x0022, 0x2104, 0xa086, 0x4000,
- 0x0040, 0x1181, 0x7008, 0x800b, 0x00c8, 0x1181, 0x7007, 0x0002,
- 0xa08c, 0x0060, 0x00c0, 0x1182, 0xa084, 0x0008, 0x0040, 0x1181,
- 0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x1277, 0x0068, 0x11f1,
- 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x11f1, 0x7814,
- 0xa005, 0x00c0, 0x1197, 0x0010, 0x11f2, 0x0078, 0x11f1, 0x2009,
- 0x3968, 0x2104, 0xa005, 0x00c0, 0x11f1, 0x2009, 0x3971, 0x200b,
- 0x0000, 0x7914, 0xa186, 0x0042, 0x00c0, 0x11bc, 0x7816, 0x2009,
- 0x396f, 0x2164, 0x200b, 0x0000, 0x6018, 0x70c6, 0x6014, 0x70ca,
+ 0x8109, 0x00c0, 0x1122, 0x2069, 0x5300, 0x2009, 0x0002, 0x20a9,
+ 0x0100, 0x6837, 0x0000, 0x680b, 0x0040, 0x7bf0, 0xa386, 0xfeff,
+ 0x00c0, 0x1148, 0x6817, 0x0100, 0x681f, 0x0064, 0x0078, 0x114c,
+ 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010, 0x0070, 0x1152,
+ 0x0078, 0x1139, 0x8109, 0x00c0, 0x1137, 0x1078, 0x21e9, 0x1078,
+ 0x46e9, 0x1078, 0x1946, 0x1078, 0x4bdf, 0x3200, 0xa085, 0x000d,
+ 0x2090, 0x70c3, 0x0000, 0x0090, 0x116c, 0x70c0, 0xa086, 0x0002,
+ 0x00c0, 0x116c, 0x1078, 0x1284, 0x1078, 0x1196, 0x78cc, 0xa005,
+ 0x00c0, 0x117a, 0x1078, 0x1cc6, 0x0010, 0x1180, 0x0068, 0x1180,
+ 0x1078, 0x20c8, 0x0010, 0x1180, 0x0068, 0x1180, 0x1078, 0x1a2b,
+ 0x00e0, 0x116c, 0x1078, 0x4a66, 0x0078, 0x116c, 0x118e, 0x1190,
+ 0x23ea, 0x23ea, 0x476a, 0x476a, 0x23ea, 0x23ea, 0x0078, 0x118e,
+ 0x0078, 0x1190, 0x0078, 0x1192, 0x0078, 0x1194, 0x0068, 0x1201,
+ 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1201, 0x7814,
+ 0xa005, 0x00c0, 0x11a7, 0x0010, 0x1202, 0x0078, 0x1201, 0x2009,
+ 0x505b, 0x2104, 0xa005, 0x00c0, 0x1201, 0x2009, 0x5064, 0x200b,
+ 0x0000, 0x7914, 0xa186, 0x0042, 0x00c0, 0x11cc, 0x7816, 0x2009,
+ 0x5062, 0x2164, 0x200b, 0x0000, 0x6018, 0x70c6, 0x6014, 0x70ca,
0x611c, 0xa18c, 0xff00, 0x6020, 0xa084, 0x00ff, 0xa105, 0x70ce,
- 0x1078, 0x1896, 0x0078, 0x11ef, 0x7814, 0xa086, 0x0018, 0x00c0,
- 0x11c3, 0x1078, 0x1622, 0x7817, 0x0000, 0x2009, 0x396f, 0x2104,
- 0xa065, 0x0040, 0x11df, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x18f6,
- 0x0c7f, 0x609f, 0x0000, 0x1078, 0x16e9, 0x2009, 0x001c, 0x6087,
- 0x0103, 0x1078, 0x181d, 0x00c0, 0x11eb, 0x1078, 0x1896, 0x2009,
- 0x396f, 0x200b, 0x0000, 0x2009, 0x3969, 0x2104, 0x200b, 0x0000,
- 0xa005, 0x0040, 0x11ef, 0x2001, 0x4005, 0x0078, 0x1276, 0x0078,
- 0x1274, 0x007c, 0x70c3, 0x0000, 0x70c7, 0x0000, 0x70cb, 0x0000,
- 0x70cf, 0x0000, 0x70c0, 0xa0bc, 0xffc0, 0x00c0, 0x1242, 0x2038,
- 0x0079, 0x1202, 0x1274, 0x12cf, 0x1293, 0x12cf, 0x1338, 0x1338,
- 0x128a, 0x16fd, 0x1343, 0x1282, 0x1297, 0x1299, 0x129b, 0x129d,
- 0x1702, 0x1282, 0x1355, 0x1380, 0x163a, 0x16f7, 0x129f, 0x1569,
- 0x158b, 0x15a1, 0x15be, 0x1526, 0x1534, 0x1548, 0x155c, 0x13f3,
- 0x1282, 0x13a1, 0x13a7, 0x13ac, 0x13b1, 0x13b7, 0x13bc, 0x13c1,
- 0x13c6, 0x13cb, 0x13cf, 0x13e4, 0x13f0, 0x1282, 0x1282, 0x1282,
- 0x1282, 0x13ff, 0x1408, 0x1417, 0x143d, 0x1447, 0x144e, 0x1474,
- 0x1483, 0x1492, 0x14a4, 0x1506, 0x1516, 0x1282, 0x1282, 0x1282,
- 0x1282, 0x151b, 0xa0bc, 0xffa0, 0x00c0, 0x1282, 0x2038, 0xa084,
- 0x001f, 0x0079, 0x124b, 0x1719, 0x171c, 0x172c, 0x17a8, 0x17e1,
- 0x1282, 0x1282, 0x1282, 0x1282, 0x1282, 0x1282, 0x1282, 0x1282,
- 0x1282, 0x1282, 0x1282, 0x12c5, 0x132e, 0x134b, 0x1376, 0x1630,
- 0x1282, 0x1282, 0x1282, 0x1282, 0x1282, 0x17f9, 0x1803, 0x1807,
- 0x1815, 0x1282, 0x1282, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078,
- 0x1276, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068,
- 0x1277, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091,
- 0x4080, 0x007c, 0x70c3, 0x4001, 0x0078, 0x1277, 0x70c3, 0x4006,
- 0x0078, 0x1277, 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005,
- 0x53a3, 0x0078, 0x1274, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078,
- 0x1274, 0x0078, 0x1274, 0x0078, 0x1274, 0x0078, 0x1274, 0x2091,
- 0x8000, 0x70c3, 0x0000, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf,
- 0x2020, 0x70d3, 0x0002, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b,
- 0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051,
- 0x0470, 0x2061, 0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091,
- 0x5000, 0x2091, 0x4080, 0x0078, 0x0455, 0x1078, 0x1a04, 0x00c0,
- 0x1286, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x12d2, 0x2029,
- 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0, 0x2098,
- 0x2031, 0x0030, 0x81ff, 0x0040, 0x1274, 0x7007, 0x0004, 0x731a,
- 0x721e, 0x7422, 0x7526, 0x2051, 0x0012, 0x2049, 0x130d, 0x2041,
- 0x1274, 0x7003, 0x0002, 0xa786, 0x0001, 0x0040, 0x12f5, 0xa786,
- 0x0050, 0x0040, 0x12f5, 0x0078, 0x12fb, 0x2049, 0x131a, 0x2041,
- 0x1326, 0x7003, 0x0003, 0x7017, 0x0000, 0x810b, 0x7112, 0x00c8,
- 0x1303, 0x7017, 0x0001, 0x7007, 0x0001, 0xa786, 0x0001, 0x0040,
- 0x131a, 0xa786, 0x0050, 0x0040, 0x131a, 0x700c, 0xa084, 0x007f,
- 0x2009, 0x0040, 0xa102, 0x8004, 0x094a, 0x20a8, 0x26a0, 0x53a6,
- 0x0078, 0x116b, 0x700c, 0xa084, 0x007f, 0x0040, 0x131a, 0x80ac,
- 0x0048, 0x131a, 0x2698, 0x53a5, 0x0078, 0x116b, 0x700c, 0xa084,
- 0x007f, 0x80ac, 0x2698, 0x53a5, 0x0078, 0x1274, 0x1078, 0x1a04,
- 0x00c0, 0x1286, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x12d2,
- 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0, 0x1340, 0x200a,
- 0x72ca, 0x0078, 0x1273, 0x70c7, 0x0002, 0x70cb, 0x000a, 0x70cf,
- 0x0000, 0x0078, 0x1274, 0x1078, 0x1a04, 0x00c0, 0x1286, 0x75d8,
- 0x76dc, 0x75da, 0x76de, 0x0078, 0x1358, 0x2029, 0x0000, 0x2530,
- 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca, 0x73ce, 0x74d2,
- 0xa005, 0x0040, 0x1370, 0x8001, 0x788a, 0x7a92, 0x7b96, 0x7d9a,
- 0x7e9e, 0x7c8e, 0x78c0, 0xa084, 0xfffc, 0x78c2, 0x0078, 0x1374,
- 0x78c0, 0xa085, 0x0001, 0x78c2, 0x0078, 0x1274, 0x1078, 0x1a04,
- 0x00c0, 0x1286, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x1383,
+ 0x1078, 0x192b, 0x0078, 0x11ff, 0x7814, 0xa086, 0x0018, 0x00c0,
+ 0x11d3, 0x1078, 0x165a, 0x7817, 0x0000, 0x2009, 0x5062, 0x2104,
+ 0xa065, 0x0040, 0x11ef, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x1996,
+ 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009, 0x000c, 0x6007,
+ 0x0103, 0x1078, 0x1907, 0x00c0, 0x11fb, 0x1078, 0x192b, 0x2009,
+ 0x5062, 0x200b, 0x0000, 0x2009, 0x505c, 0x2104, 0x200b, 0x0000,
+ 0xa005, 0x0040, 0x11ff, 0x2001, 0x4005, 0x0078, 0x1286, 0x0078,
+ 0x1284, 0x007c, 0x70c3, 0x0000, 0x70c7, 0x0000, 0x70cb, 0x0000,
+ 0x70cf, 0x0000, 0x70c0, 0xa0bc, 0xffc0, 0x00c0, 0x1252, 0x2038,
+ 0x0079, 0x1212, 0x1284, 0x12e5, 0x12a9, 0x12fe, 0x130d, 0x1313,
+ 0x12a0, 0x1748, 0x1317, 0x1298, 0x12ad, 0x12af, 0x12b1, 0x12b3,
+ 0x174d, 0x1298, 0x1329, 0x1360, 0x1672, 0x1742, 0x12b5, 0x1591,
+ 0x15ad, 0x15c9, 0x15f4, 0x154a, 0x1558, 0x156c, 0x1580, 0x13df,
+ 0x1298, 0x138d, 0x1393, 0x1398, 0x139d, 0x13a3, 0x13a8, 0x13ad,
+ 0x13b2, 0x13b7, 0x13bb, 0x13d0, 0x13dc, 0x1298, 0x1298, 0x1298,
+ 0x1298, 0x13eb, 0x13f4, 0x1403, 0x1429, 0x1433, 0x143a, 0x1480,
+ 0x148f, 0x149e, 0x14b0, 0x152a, 0x153a, 0x1298, 0x1298, 0x1298,
+ 0x1298, 0x153f, 0xa0bc, 0xffa0, 0x00c0, 0x1298, 0x2038, 0xa084,
+ 0x001f, 0x0079, 0x125b, 0x1786, 0x1789, 0x1799, 0x1298, 0x1298,
+ 0x18d8, 0x18f5, 0x1298, 0x1298, 0x1298, 0x18f9, 0x1901, 0x1298,
+ 0x1298, 0x1298, 0x1298, 0x12db, 0x12f4, 0x131f, 0x1356, 0x1668,
+ 0x1764, 0x1778, 0x1298, 0x1829, 0x1298, 0x18b4, 0x18be, 0x18c2,
+ 0x18d0, 0x1298, 0x1298, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078,
+ 0x1286, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068,
+ 0x1287, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x00e0,
+ 0x128f, 0x00e0, 0x1291, 0x0068, 0x1291, 0x2091, 0x4080, 0x007c,
+ 0x70c3, 0x4001, 0x0078, 0x1287, 0x70c3, 0x4006, 0x0078, 0x1287,
+ 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078,
+ 0x1284, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x1284, 0x0078,
+ 0x1284, 0x0078, 0x1284, 0x0078, 0x1284, 0x2091, 0x8000, 0x70c3,
+ 0x0000, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3,
+ 0x0007, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031,
+ 0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051, 0x0470, 0x2061,
+ 0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091, 0x5000, 0x2091,
+ 0x4080, 0x0078, 0x0455, 0x1078, 0x1b36, 0x00c0, 0x129c, 0x75d8,
+ 0x74dc, 0x75da, 0x74de, 0x0078, 0x12e8, 0x2029, 0x0000, 0x2520,
+ 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1a70, 0x0040, 0x1284,
+ 0x70c3, 0x4002, 0x0078, 0x1284, 0x1078, 0x1b36, 0x00c0, 0x129c,
+ 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1301, 0x2029, 0x0000,
+ 0x2520, 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1ad0, 0x0040,
+ 0x1284, 0x70c3, 0x4002, 0x0078, 0x1284, 0x71c4, 0x70c8, 0x2114,
+ 0x200a, 0x0078, 0x1282, 0x71c4, 0x2114, 0x0078, 0x1282, 0x70c7,
+ 0x0007, 0x70cb, 0x003f, 0x70cf, 0x0000, 0x0078, 0x1284, 0x1078,
+ 0x1b36, 0x00c0, 0x129c, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078,
+ 0x132c, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0,
+ 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x1350, 0x8001,
+ 0x7892, 0xa084, 0xfc00, 0x0040, 0x1345, 0x78cc, 0xa085, 0x0001,
+ 0x78ce, 0x2001, 0x4005, 0x0078, 0x1286, 0x7a9a, 0x7b9e, 0x7da2,
+ 0x7ea6, 0x7c96, 0x78cc, 0xa084, 0xfffc, 0x78ce, 0x0078, 0x1354,
+ 0x78cc, 0xa085, 0x0001, 0x78ce, 0x0078, 0x1284, 0x1078, 0x1b36,
+ 0x00c0, 0x129c, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x1363,
0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6,
- 0x72ca, 0x73ce, 0x74d6, 0xa005, 0x0040, 0x139b, 0x8001, 0x78a6,
- 0x7aae, 0x7bb2, 0x7db6, 0x7eba, 0x7caa, 0x78c0, 0xa084, 0xfcff,
- 0x78c2, 0x0078, 0x139f, 0x78c0, 0xa085, 0x0100, 0x78c2, 0x0078,
- 0x1274, 0x2009, 0x395f, 0x210c, 0x7ae4, 0x0078, 0x1272, 0x2009,
- 0x3941, 0x210c, 0x0078, 0x1273, 0x2009, 0x3942, 0x210c, 0x0078,
- 0x1273, 0x2061, 0x3940, 0x610c, 0x6210, 0x0078, 0x1272, 0x2009,
- 0x3945, 0x210c, 0x0078, 0x1273, 0x2009, 0x3946, 0x210c, 0x0078,
- 0x1273, 0x2009, 0x3947, 0x210c, 0x0078, 0x1273, 0x2009, 0x3948,
- 0x210c, 0x0078, 0x1273, 0x7908, 0x7a0c, 0x0078, 0x1272, 0x71c4,
- 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x3a00,
- 0x6a00, 0x6804, 0xa084, 0x0008, 0x0040, 0x13e1, 0x6b08, 0x0078,
- 0x13e2, 0x6b0c, 0x0078, 0x1271, 0x77c4, 0x1078, 0x18b4, 0x2091,
- 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x1271,
- 0x794c, 0x0078, 0x1273, 0x77c4, 0x1078, 0x18b4, 0x2091, 0x8000,
- 0x6908, 0x6a18, 0x6b10, 0x2091, 0x8001, 0x0078, 0x1271, 0x71c4,
- 0xa182, 0x0010, 0x00c8, 0x126c, 0x1078, 0x1d9b, 0x0078, 0x1271,
- 0x71c4, 0xa182, 0x0010, 0x00c8, 0x126c, 0x2011, 0x3941, 0x2204,
- 0x007e, 0x2112, 0x1078, 0x1d54, 0x017f, 0x0078, 0x1273, 0x71c4,
- 0x2011, 0x1435, 0x20a9, 0x0008, 0x2204, 0xa106, 0x0040, 0x1427,
- 0x8210, 0x0070, 0x1425, 0x0078, 0x141c, 0x0078, 0x126c, 0xa292,
- 0x1435, 0x027e, 0x2011, 0x3942, 0x2204, 0x2112, 0x017f, 0x007e,
- 0x1078, 0x1d60, 0x017f, 0x0078, 0x1273, 0x03e8, 0x00fa, 0x01f4,
- 0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x3940, 0x610c,
- 0x6210, 0x70c4, 0x600e, 0x70c8, 0x6012, 0x0078, 0x1272, 0x2061,
- 0x3940, 0x6114, 0x70c4, 0x6016, 0x0078, 0x1273, 0x71c4, 0x2011,
- 0x0004, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x1467, 0x2011,
- 0x0005, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040, 0x1467, 0x2011,
- 0x0006, 0x2019, 0x2323, 0xa186, 0x003c, 0x00c0, 0x126c, 0x2061,
- 0x3940, 0x6018, 0x007e, 0x611a, 0x23b8, 0x1078, 0x1d71, 0x1078,
- 0x37fc, 0x017f, 0x0078, 0x1273, 0x71c4, 0xa184, 0xffcf, 0x00c0,
- 0x126c, 0x2011, 0x3947, 0x2204, 0x2112, 0x007e, 0x1078, 0x1d93,
- 0x017f, 0x0078, 0x1273, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x126c,
- 0x2011, 0x3948, 0x2204, 0x007e, 0x2112, 0x1078, 0x1d82, 0x017f,
- 0x0078, 0x1273, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x126b,
- 0xa284, 0xfffd, 0x00c0, 0x126b, 0x2100, 0x7908, 0x780a, 0x2200,
- 0x7a0c, 0x780e, 0x0078, 0x1272, 0x71c4, 0x8107, 0xa084, 0x000f,
- 0x8003, 0x8003, 0x8003, 0xa0e8, 0x3a00, 0x2019, 0x0000, 0x72c8,
- 0x6800, 0x007e, 0xa226, 0x0040, 0x14d3, 0x6a02, 0xa484, 0x2000,
- 0x0040, 0x14bc, 0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x14c2,
- 0xa39d, 0x0008, 0xa484, 0x4000, 0x0040, 0x14d3, 0x810f, 0xa284,
- 0x4000, 0x0040, 0x14cf, 0x1078, 0x1db5, 0x0078, 0x14d3, 0x1078,
- 0x1da7, 0x0078, 0x14d3, 0x72cc, 0x82ff, 0x0040, 0x14ff, 0x6808,
- 0xa206, 0x0040, 0x14ff, 0xa2a4, 0x00ff, 0x2061, 0x3940, 0x6118,
- 0xa186, 0x0028, 0x0040, 0x14ec, 0xa186, 0x0032, 0x0040, 0x14f2,
- 0xa186, 0x003c, 0x0040, 0x14f8, 0xa482, 0x0064, 0x00c8, 0x126d,
- 0x0078, 0x14fc, 0xa482, 0x0050, 0x00c8, 0x126d, 0x0078, 0x14fc,
- 0xa482, 0x0043, 0x00c8, 0x126d, 0x6a0a, 0xa39d, 0x000a, 0x6804,
- 0xa305, 0x6806, 0x027f, 0x6b0c, 0x0078, 0x1271, 0x77c4, 0x1078,
- 0x18b4, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8,
- 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078, 0x1271, 0x70c4, 0x794c,
- 0x784e, 0x0078, 0x1273, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010,
- 0x00c8, 0x126c, 0x1078, 0x1dc3, 0x0078, 0x1271, 0x77c4, 0x1078,
- 0x18b4, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0002, 0x6a0a, 0x2091,
- 0x8001, 0x2708, 0x0078, 0x1272, 0x77c4, 0x1078, 0x18b4, 0x2091,
- 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040,
- 0x1543, 0x1078, 0x1cf6, 0x2091, 0x8001, 0x2708, 0x0078, 0x1272,
- 0x77c4, 0x1078, 0x18b4, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0004,
- 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1557, 0x1078, 0x1cf6, 0x2091,
- 0x8001, 0x2708, 0x0078, 0x1272, 0x77c4, 0x2041, 0x0001, 0x2049,
- 0x0005, 0x2051, 0x0020, 0x1078, 0x18c1, 0x2708, 0x6a08, 0x0078,
- 0x1272, 0x77c4, 0x73c8, 0x72cc, 0x77c6, 0x73ca, 0x72ce, 0x1078,
- 0x193c, 0x00c0, 0x1587, 0x6818, 0xa005, 0x0040, 0x1581, 0x2708,
- 0x1078, 0x1dd3, 0x00c0, 0x1581, 0x7817, 0x0015, 0x2091, 0x8001,
- 0x007c, 0x2091, 0x8001, 0x2001, 0x4005, 0x0078, 0x1276, 0x2091,
- 0x8001, 0x0078, 0x1274, 0x77c4, 0x77c6, 0x2061, 0x3940, 0x60a3,
- 0x0003, 0x67b6, 0x60c7, 0x000f, 0x2041, 0x0021, 0x2049, 0x0005,
- 0x2051, 0x0020, 0x1078, 0x18c1, 0x7817, 0x0016, 0x1078, 0x1cf6,
- 0x007c, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2061, 0x3940, 0x60a3,
- 0x0002, 0x67b6, 0x60c7, 0x000f, 0x7817, 0x0017, 0x1078, 0x1cf6,
- 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x1078, 0x18c1,
- 0x8738, 0xa784, 0x0007, 0x00c0, 0x15b6, 0x007c, 0x78c0, 0xa084,
- 0x0003, 0x00c0, 0x15e2, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049,
- 0x0004, 0x2051, 0x0008, 0x1078, 0x18b4, 0x2091, 0x8000, 0x6808,
- 0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x0007, 0x00c0,
- 0x15cb, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00,
- 0x00c0, 0x15cb, 0x2091, 0x8000, 0x2069, 0x0100, 0x6830, 0xa084,
- 0x0040, 0x0040, 0x160b, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848,
- 0xa084, 0x0004, 0x0040, 0x15f8, 0x0070, 0x15f8, 0x0078, 0x15ef,
- 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040,
- 0x1605, 0x0070, 0x1605, 0x0078, 0x15fc, 0x20a9, 0x00fa, 0x0070,
- 0x160b, 0x0078, 0x1607, 0x2079, 0x3900, 0x7817, 0x0018, 0x2061,
- 0x3940, 0x60a3, 0x0001, 0x60c7, 0x000f, 0x78c0, 0xa085, 0x0002,
- 0x78c2, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0047, 0x2091,
- 0x8001, 0x007c, 0x78c0, 0xa084, 0xfffd, 0x78c2, 0xa084, 0x0001,
- 0x00c0, 0x162c, 0x1078, 0x197e, 0x71c4, 0x71c6, 0x794a, 0x007c,
- 0x1078, 0x1a04, 0x00c0, 0x1286, 0x75d8, 0x74dc, 0x75da, 0x74de,
- 0x0078, 0x163d, 0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8, 0x72cc,
- 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x3900, 0x1078, 0x188d, 0x0040,
- 0x16e5, 0x20a9, 0x0005, 0x20a1, 0x3916, 0x41a1, 0x2009, 0x0040,
- 0x1078, 0x1857, 0x0040, 0x1658, 0x1078, 0x1896, 0x0078, 0x16e5,
- 0x6004, 0xa084, 0xff00, 0x8007, 0x8009, 0x0040, 0x16b9, 0x0c7e,
- 0x2c68, 0x1078, 0x188d, 0x0040, 0x1688, 0x2c00, 0x689e, 0x8109,
- 0x00c0, 0x1660, 0x609f, 0x0000, 0x0c7f, 0x0c7e, 0x7218, 0x731c,
- 0x7420, 0x7524, 0x2c68, 0x689c, 0xa065, 0x0040, 0x16b8, 0x2009,
- 0x0040, 0x1078, 0x1857, 0x00c0, 0x16a1, 0x6004, 0xa084, 0x00ff,
- 0xa086, 0x0002, 0x00c0, 0x1688, 0x2d00, 0x6002, 0x0078, 0x166e,
- 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x18f6, 0x0c7f, 0x609f,
- 0x0000, 0x1078, 0x16e9, 0x2009, 0x001c, 0x6008, 0xa085, 0x0200,
- 0x600a, 0x6004, 0x6086, 0x1078, 0x181d, 0x1078, 0x1896, 0x0078,
- 0x16e5, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x18f6, 0x0c7f,
- 0x609f, 0x0000, 0x1078, 0x16e9, 0x2009, 0x001c, 0x6087, 0x0103,
- 0x601b, 0x0003, 0x1078, 0x181d, 0x1078, 0x1896, 0x0078, 0x16e5,
- 0x0c7f, 0x74c4, 0x73c8, 0x72cc, 0x6014, 0x7817, 0x0012, 0x0e7e,
- 0x2071, 0x3940, 0x70a3, 0x0005, 0x70a7, 0x0000, 0x73aa, 0x72ae,
- 0x74b2, 0x70b6, 0x70bb, 0x0000, 0x2c00, 0x70be, 0x70c3, 0x0000,
- 0xa02e, 0x2530, 0x611c, 0xa184, 0x0060, 0x0040, 0x16d9, 0x1078,
- 0x330a, 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x669a, 0x60af, 0x0000,
- 0x60b3, 0x0000, 0x1078, 0x1cf6, 0x007c, 0x70c3, 0x4005, 0x0078,
- 0x1277, 0x20a9, 0x0005, 0x2099, 0x3916, 0x530a, 0x2100, 0xa210,
- 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c, 0x71c4,
- 0x70c7, 0x0000, 0x7906, 0x0078, 0x1274, 0x71c4, 0x71c6, 0x2168,
- 0x0078, 0x1704, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210,
- 0x8d68, 0x8109, 0x00c0, 0x1706, 0xa285, 0x0000, 0x00c0, 0x1714,
- 0x70c3, 0x4000, 0x0078, 0x1716, 0x70c3, 0x4003, 0x70ca, 0x0078,
- 0x1277, 0x79d8, 0x0078, 0x1273, 0x71c4, 0x71c6, 0x2198, 0x20a1,
- 0x0042, 0x20a9, 0x0004, 0x53a3, 0x21a0, 0x2099, 0x0042, 0x20a9,
- 0x0004, 0x53a3, 0x0078, 0x1274, 0x70c4, 0x2068, 0x2079, 0x3900,
- 0x1078, 0x188d, 0x0040, 0x17a4, 0x6007, 0x0001, 0x600b, 0x0000,
- 0x602b, 0x0000, 0x601b, 0x0006, 0x6a10, 0xa28c, 0x0007, 0xa284,
- 0x00f0, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x6016, 0xa284,
- 0x0800, 0x0040, 0x174f, 0x601b, 0x000a, 0x0078, 0x1755, 0xa284,
- 0x1000, 0x0040, 0x1755, 0x601b, 0x000c, 0xa284, 0x0300, 0x0040,
- 0x175e, 0x602b, 0x0001, 0x8004, 0x8004, 0x8004, 0xa085, 0x0001,
- 0x601e, 0x6023, 0x0000, 0x6027, 0x000a, 0xa284, 0x0400, 0x0040,
- 0x176b, 0x602b, 0x0000, 0x20a9, 0x0006, 0xac80, 0x000b, 0x20a0,
- 0xad80, 0x0005, 0x2098, 0x53a3, 0xa284, 0x0300, 0x00c0, 0x1780,
- 0x6046, 0x604a, 0x604e, 0x6052, 0x6096, 0x609a, 0x0078, 0x178a,
- 0x6800, 0x6046, 0x6804, 0x604a, 0x6e08, 0x664e, 0x6d0c, 0x6552,
- 0x6596, 0x669a, 0x6014, 0x7817, 0x0042, 0x2c08, 0x2061, 0x3940,
- 0x60a3, 0x0005, 0x60a7, 0x0000, 0x60ab, 0x0000, 0x60af, 0x0000,
- 0x60b3, 0x0000, 0x60b6, 0x61be, 0xa284, 0x0400, 0x60c2, 0x1078,
- 0x32f5, 0x1078, 0x1cf6, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1277,
- 0x78f0, 0xa005, 0x0040, 0x1282, 0x2091, 0x8000, 0x70c4, 0x800a,
- 0x2011, 0x0010, 0x810c, 0x0048, 0x17ba, 0x3a00, 0xa084, 0xfff7,
- 0x0078, 0x17bd, 0x3a00, 0xa085, 0x0008, 0x20d0, 0x0005, 0x0005,
- 0xa084, 0xfffb, 0x20d0, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005,
- 0x0005, 0x0005, 0x0005, 0xa085, 0x0004, 0x20d0, 0x0005, 0x0005,
- 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x8211, 0x00c0,
- 0x17b2, 0x3a00, 0xa085, 0x0008, 0x20d0, 0x2091, 0x8001, 0x0078,
- 0x1274, 0x2011, 0x04fd, 0x2204, 0xa082, 0x0004, 0x0048, 0x17f5,
- 0x78f3, 0x0001, 0x2009, 0xff01, 0x200a, 0x2001, 0x000c, 0x20d8,
- 0x2001, 0x000c, 0x20d0, 0x0078, 0x1274, 0x2001, 0x4005, 0x0078,
- 0x1276, 0x7978, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x126c,
- 0x797a, 0x0078, 0x1274, 0x7978, 0x71c6, 0x0078, 0x1274, 0x796c,
- 0x71c6, 0x71c4, 0x796e, 0x7970, 0x71ca, 0x71c8, 0x7972, 0x7974,
- 0x71ce, 0x71cc, 0x7976, 0x0078, 0x1274, 0x796c, 0x71c6, 0x7970,
- 0x71ca, 0x7974, 0x71ce, 0x0078, 0x1274, 0x700c, 0xa084, 0x00ff,
- 0x0040, 0x1829, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
- 0x1824, 0x7017, 0x0000, 0x7112, 0x721a, 0x731e, 0x7422, 0x7526,
- 0xac80, 0x0001, 0x8108, 0x810c, 0x81a9, 0x8098, 0x20a1, 0x0030,
- 0x6084, 0x20a2, 0x53a6, 0x780c, 0xa085, 0x0000, 0x7002, 0x7007,
- 0x0001, 0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1841,
- 0x7108, 0x8103, 0x00c8, 0x1841, 0x7014, 0xa005, 0x0040, 0x1841,
- 0x7007, 0x0002, 0xa184, 0x0060, 0x7003, 0x0000, 0x007c, 0x700c,
- 0xa084, 0x00ff, 0x0040, 0x1863, 0x7007, 0x0004, 0x7004, 0xa084,
- 0x0004, 0x00c0, 0x185e, 0x7017, 0x0000, 0x7112, 0x721a, 0x7422,
- 0x7526, 0x731e, 0x2099, 0x0030, 0x8108, 0x81ac, 0x780c, 0xa085,
- 0x0001, 0x7002, 0x7007, 0x0001, 0x2009, 0x0022, 0x2104, 0xa084,
- 0x4000, 0x00c0, 0x1874, 0x7008, 0x800b, 0x00c8, 0x1874, 0x7007,
- 0x0002, 0xa08c, 0x0060, 0x00c0, 0x188a, 0xac80, 0x0001, 0x20a0,
- 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x7850, 0xa065, 0x0040,
- 0x1895, 0x2c04, 0x7852, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079,
- 0x3900, 0x7850, 0x2062, 0x2c00, 0xa005, 0x00c0, 0x18a1, 0x1078,
- 0x1eac, 0x7852, 0x0f7f, 0x007c, 0x2011, 0x4400, 0x7a52, 0x7be4,
- 0x8319, 0x0040, 0x18b1, 0xa280, 0x002f, 0x2012, 0x2010, 0x0078,
- 0x18a8, 0x2013, 0x0000, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784,
- 0x0007, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8, 0x3a80,
- 0x007c, 0x1078, 0x18b4, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808,
- 0xa084, 0xffef, 0xa80d, 0x690a, 0x2091, 0x8000, 0x2009, 0x394f,
- 0x210c, 0x6804, 0xa005, 0x0040, 0x18de, 0xa116, 0x00c0, 0x18de,
- 0x2060, 0x6000, 0x6806, 0x017e, 0x0078, 0x18e1, 0x2009, 0x0000,
- 0x017e, 0x6804, 0xa065, 0x0040, 0x18f0, 0x6000, 0x6806, 0x1078,
- 0x1903, 0x1078, 0x1a14, 0x6810, 0x8001, 0x6812, 0x00c0, 0x18e1,
- 0x017f, 0x6902, 0x6906, 0x2091, 0x8001, 0x007c, 0xa065, 0x0040,
- 0x1902, 0x609c, 0x609f, 0x0000, 0x2008, 0x1078, 0x1896, 0x2100,
- 0x0078, 0x18f6, 0x007c, 0x6007, 0x0103, 0x20a9, 0x001c, 0xac80,
- 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, 0x682c,
- 0x6022, 0x007c, 0x0e7e, 0x2071, 0x3940, 0x7040, 0xa08c, 0x0080,
- 0x00c0, 0x1920, 0xa088, 0x3980, 0x2d0a, 0x8000, 0x7042, 0xa006,
- 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x3940, 0x2009, 0x3980, 0x7240,
- 0x8221, 0x8211, 0x0048, 0x193a, 0x2104, 0x8108, 0xad06, 0x00c0,
- 0x1929, 0x8119, 0x211e, 0x8108, 0x8318, 0x8211, 0x00c8, 0x1932,
- 0x7442, 0xa006, 0x0e7f, 0x007c, 0x1078, 0x18b4, 0x2091, 0x8000,
- 0x6804, 0x781e, 0xa065, 0x0040, 0x197d, 0x0078, 0x194d, 0x2c00,
- 0x781e, 0x6000, 0xa065, 0x0040, 0x197d, 0x6010, 0xa306, 0x00c0,
- 0x1947, 0x600c, 0xa206, 0x00c0, 0x1947, 0x2c28, 0x6804, 0xac06,
- 0x00c0, 0x1964, 0x6000, 0x2060, 0x6806, 0xa005, 0x00c0, 0x1964,
- 0x6803, 0x0000, 0x0078, 0x196e, 0x6400, 0x781c, 0x2060, 0x6402,
- 0xa486, 0x0000, 0x00c0, 0x196e, 0x2c00, 0x6802, 0x2560, 0x1078,
- 0x1903, 0x601b, 0x0005, 0x6023, 0x0020, 0x1078, 0x1a14, 0x6810,
- 0x8001, 0x6812, 0x2001, 0xffff, 0xa005, 0x007c, 0x2039, 0x0000,
- 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078, 0x18c1,
- 0x8738, 0xa784, 0x0007, 0x00c0, 0x1986, 0xa7bc, 0xff00, 0x873f,
- 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1986, 0x007c, 0x2061,
- 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x19a8, 0x2091, 0x8000,
- 0x78d4, 0x78d7, 0x0000, 0x2091, 0x8001, 0xa005, 0x00c0, 0x19a9,
- 0x007c, 0xa08c, 0xfff0, 0x0040, 0x19af, 0x1078, 0x1eac, 0x0079,
- 0x19b1, 0x19c1, 0x19c3, 0x19c9, 0x19cd, 0x19c1, 0x19d1, 0x19c1,
- 0x19d8, 0x19dc, 0x19e0, 0x1a0a, 0x1a0e, 0x19c1, 0x19c1, 0x19c1,
- 0x19c1, 0x1078, 0x1eac, 0x1078, 0x197e, 0x2001, 0x8001, 0x0078,
- 0x1276, 0x2001, 0x8003, 0x0078, 0x1276, 0x2001, 0x8004, 0x0078,
- 0x1276, 0x1078, 0x197e, 0x2001, 0x8006, 0x007c, 0x0078, 0x1276,
- 0x2001, 0x8008, 0x0078, 0x1276, 0x2001, 0x8009, 0x0078, 0x1276,
- 0x2091, 0x8000, 0x2069, 0x3940, 0x6800, 0xa086, 0x0000, 0x0040,
- 0x19ee, 0x2091, 0x8001, 0x78d7, 0x0009, 0x007c, 0x68b4, 0xa0bc,
- 0xff00, 0x2091, 0x8000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051,
- 0x0010, 0x1078, 0x18c1, 0x8738, 0xa784, 0x0007, 0x00c0, 0x19f9,
- 0x2001, 0x800a, 0x0078, 0x1276, 0x2001, 0x04fd, 0x2004, 0xa086,
- 0x0004, 0x007c, 0x2001, 0x800c, 0x0078, 0x1276, 0x1078, 0x197e,
- 0x2001, 0x800d, 0x0078, 0x1276, 0x6004, 0x6086, 0x2c08, 0x2063,
- 0x0000, 0x787c, 0x8000, 0x787e, 0x7880, 0xa005, 0x7982, 0x0040,
- 0x1a24, 0x2c02, 0x0078, 0x1a25, 0x7986, 0x007c, 0x0c7e, 0x2061,
- 0x3900, 0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x607c, 0x8000,
- 0x607e, 0x6080, 0xa005, 0x6182, 0x0040, 0x1a39, 0x2d02, 0x0078,
- 0x1a3a, 0x6186, 0x0c7f, 0x007c, 0x1078, 0x1a4d, 0x0040, 0x1a4c,
- 0x0c7e, 0x609c, 0xa065, 0x0040, 0x1a47, 0x1078, 0x18f6, 0x0c7f,
- 0x609f, 0x0000, 0x1078, 0x1896, 0x007c, 0x7884, 0xa065, 0x0040,
- 0x1a5f, 0x2091, 0x8000, 0x787c, 0x8001, 0x787e, 0x2c04, 0x7886,
- 0xa005, 0x00c0, 0x1a5d, 0x7882, 0x8000, 0x2091, 0x8001, 0x007c,
- 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x1a69,
- 0xa200, 0x0070, 0x1a6d, 0x0078, 0x1a64, 0x8086, 0x818e, 0x007c,
- 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x1a93, 0xa11a, 0x00c8,
- 0x1a93, 0x8213, 0x818d, 0x0048, 0x1a84, 0xa11a, 0x00c8, 0x1a85,
- 0x0070, 0x1a8b, 0x0078, 0x1a79, 0xa11a, 0x2308, 0x8210, 0x0070,
- 0x1a8b, 0x0078, 0x1a79, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080,
- 0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078,
- 0x1a8f, 0x798c, 0x70d0, 0x007e, 0x007f, 0xa106, 0x0040, 0x1ae9,
- 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x1ae9,
- 0x7008, 0x7208, 0xa206, 0x00c0, 0x1ae9, 0xa286, 0x0008, 0x00c0,
- 0x1ae9, 0x2071, 0x0010, 0x1078, 0x188d, 0x0040, 0x1ae9, 0x7a94,
- 0x7b90, 0x7c9c, 0x7d98, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399,
- 0x0000, 0x2009, 0x0040, 0x1078, 0x1857, 0x2091, 0x8001, 0x0040,
- 0x1ae0, 0x1078, 0x1896, 0x78a0, 0x8000, 0x78a2, 0xa086, 0x0002,
- 0x00c0, 0x1ae9, 0x2091, 0x8000, 0x78d7, 0x0002, 0x78a3, 0x0000,
- 0x78c0, 0xa085, 0x0003, 0x78c2, 0x2091, 0x8001, 0x0078, 0x1ae9,
- 0x78a3, 0x0000, 0x1078, 0x1c38, 0x6004, 0xa084, 0x000f, 0x0079,
- 0x1aee, 0x2071, 0x0010, 0x2091, 0x8001, 0x007c, 0x1afe, 0x1b20,
- 0x1b46, 0x1afe, 0x1b58, 0x1b0d, 0x1afe, 0x1afe, 0x1afe, 0x1b1a,
- 0x1b40, 0x1afe, 0x1afe, 0x1afe, 0x1afe, 0x1afe, 0x2039, 0x0400,
- 0x78d0, 0xa705, 0x78d2, 0x6008, 0xa705, 0x600a, 0x1078, 0x1b96,
- 0x609c, 0x78ce, 0x1078, 0x1c20, 0x007c, 0x78d0, 0xa084, 0x0100,
- 0x0040, 0x1b14, 0x0078, 0x1afe, 0x601c, 0xa085, 0x0080, 0x601e,
- 0x0078, 0x1b27, 0x1078, 0x1a04, 0x00c0, 0x1afe, 0x1078, 0x1c52,
- 0x78d0, 0xa084, 0x0100, 0x0040, 0x1b27, 0x0078, 0x1afe, 0x78d3,
- 0x0000, 0x6004, 0x8007, 0xa084, 0x00ff, 0x78c6, 0x8001, 0x609f,
- 0x0000, 0x0040, 0x1b3d, 0x1078, 0x1b96, 0x0040, 0x1b3d, 0x78d0,
- 0xa085, 0x0100, 0x78d2, 0x0078, 0x1b3f, 0x1078, 0x1bba, 0x007c,
- 0x1078, 0x1a04, 0x00c0, 0x1afe, 0x1078, 0x1c4e, 0x78d0, 0xa08c,
- 0x0e00, 0x00c0, 0x1b4f, 0xa084, 0x0100, 0x00c0, 0x1b51, 0x0078,
- 0x1afe, 0x1078, 0x1b96, 0x00c0, 0x1b57, 0x1078, 0x1bba, 0x007c,
- 0x78d0, 0xa084, 0x0100, 0x0040, 0x1b5f, 0x0078, 0x1afe, 0x78d3,
- 0x0000, 0x6714, 0x20a9, 0x0001, 0x6018, 0xa005, 0x0040, 0x1b7a,
- 0xa7bc, 0xff00, 0x20a9, 0x0008, 0xa08e, 0x0001, 0x0040, 0x1b7a,
- 0x2039, 0x0000, 0x20a9, 0x0080, 0xa08e, 0x0002, 0x0040, 0x1b7a,
- 0x0078, 0x1b93, 0x1078, 0x18b4, 0x2d00, 0xa088, 0x0002, 0x2091,
- 0x8000, 0x2168, 0x682b, 0x0000, 0x682f, 0x0000, 0x2104, 0xa084,
- 0xffde, 0x200a, 0x2100, 0xa088, 0x0010, 0x2091, 0x8001, 0x0070,
- 0x1b93, 0x0078, 0x1b7f, 0x1078, 0x1896, 0x007c, 0x78c8, 0xa06d,
- 0x00c0, 0x1ba1, 0x2c00, 0x78ca, 0x78ce, 0x609f, 0x0000, 0x0078,
- 0x1bad, 0x2c00, 0x689e, 0x609f, 0x0000, 0x78ca, 0x2d00, 0x6002,
- 0x78cc, 0xad06, 0x00c0, 0x1bad, 0x6002, 0x78c4, 0x8001, 0x78c6,
- 0x00c0, 0x1bb9, 0x78d0, 0xa084, 0x0000, 0x78d2, 0x78cc, 0x2060,
- 0xa006, 0x007c, 0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184, 0xc1ff,
- 0x601e, 0xa184, 0x0060, 0x0040, 0x1bc9, 0x0e7e, 0x1078, 0x330a,
- 0x0e7f, 0x6596, 0x669a, 0x6714, 0x1078, 0x18b4, 0x2091, 0x8000,
- 0x6808, 0xa084, 0x0001, 0x0040, 0x1be5, 0x2091, 0x8001, 0x1078,
- 0x1903, 0x2091, 0x8000, 0x1078, 0x1a14, 0x2091, 0x8001, 0x78cb,
- 0x0000, 0x78cf, 0x0000, 0x0078, 0x1c1f, 0x6024, 0xa096, 0x0001,
- 0x00c0, 0x1bec, 0x8000, 0x6026, 0x6a10, 0x6814, 0x2091, 0x8001,
- 0xa202, 0x0048, 0x1bfb, 0x0040, 0x1bfb, 0x2039, 0x0200, 0x1078,
- 0x1c20, 0x0078, 0x1c1f, 0x2c08, 0x2091, 0x8000, 0x6800, 0xa065,
- 0x0040, 0x1c03, 0x6102, 0x6902, 0x00c0, 0x1c07, 0x6906, 0x2160,
- 0x6003, 0x0000, 0x6810, 0x8000, 0x6812, 0x2091, 0x8001, 0x6808,
- 0xa08c, 0x0040, 0x0040, 0x1c19, 0xa086, 0x0040, 0x680a, 0x1078,
- 0x1912, 0x1078, 0x1cf6, 0x78cf, 0x0000, 0x78cb, 0x0000, 0x007c,
- 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x1a14, 0x2091,
- 0x8001, 0x78cc, 0xa065, 0x0040, 0x1c33, 0x609c, 0x78ce, 0x609f,
- 0x0000, 0x0078, 0x1c23, 0x78cb, 0x0000, 0x78cf, 0x0000, 0x007c,
- 0x7988, 0x788c, 0x8000, 0xa10a, 0x00c8, 0x1c3f, 0xa006, 0x788e,
- 0x70d2, 0x7804, 0xa005, 0x0040, 0x1c4d, 0x8001, 0x7806, 0x00c0,
- 0x1c4d, 0x0068, 0x1c4d, 0x2091, 0x4080, 0x007c, 0x2039, 0x1c66,
- 0x0078, 0x1c54, 0x2039, 0x1c6c, 0x2704, 0xa005, 0x0040, 0x1c65,
- 0xac00, 0x2068, 0x6b08, 0x6c0c, 0x6910, 0x6a14, 0x690a, 0x6a0e,
- 0x6b12, 0x6c16, 0x8738, 0x0078, 0x1c54, 0x007c, 0x0003, 0x0009,
- 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000, 0x0068,
- 0x1c87, 0x2029, 0x0000, 0x7884, 0xa065, 0x0040, 0x1c82, 0x1078,
- 0x1c88, 0x0040, 0x1c82, 0x1078, 0x1c99, 0x00c0, 0x1c82, 0x8528,
- 0x0078, 0x1c73, 0x85ff, 0x0040, 0x1c87, 0x2091, 0x4080, 0x007c,
- 0x7ba4, 0x79a8, 0x70d4, 0x007e, 0x007f, 0xa102, 0x00c0, 0x1c93,
- 0x2300, 0xa005, 0x007c, 0x0048, 0x1c97, 0xa302, 0x007c, 0x8002,
- 0x007c, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0,
- 0x1cdd, 0x7008, 0x7208, 0xa206, 0x00c0, 0x1cdd, 0xa286, 0x0008,
- 0x00c0, 0x1cdd, 0x2071, 0x0010, 0x1078, 0x1ce2, 0x2009, 0x001c,
- 0x6028, 0xa005, 0x0040, 0x1cb6, 0x2009, 0x0040, 0x1078, 0x181d,
- 0x0040, 0x1ccf, 0x78bc, 0x8000, 0x78be, 0xa086, 0x0002, 0x00c0,
- 0x1cdd, 0x2091, 0x8000, 0x78d7, 0x0003, 0x78bf, 0x0000, 0x78c0,
- 0xa085, 0x0300, 0x78c2, 0x2091, 0x8001, 0x0078, 0x1cdd, 0x78bf,
- 0x0000, 0x1078, 0x1a3c, 0x79a4, 0x78a8, 0x8000, 0xa10a, 0x00c8,
- 0x1cda, 0xa006, 0x78aa, 0x70d6, 0xa006, 0x2071, 0x0010, 0x2091,
- 0x8001, 0x007c, 0x8107, 0x8004, 0x8004, 0x7ab0, 0x7bac, 0x7cb8,
- 0x7db4, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
- 0x007c, 0x2009, 0x3968, 0x2091, 0x8000, 0x200a, 0x0f7e, 0x2079,
- 0x0100, 0x2009, 0x3940, 0x2091, 0x8000, 0x2104, 0xa086, 0x0000,
- 0x00c0, 0x1d11, 0x2009, 0x3912, 0x2104, 0xa005, 0x00c0, 0x1d11,
- 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1d11, 0x0018, 0x1d11, 0x781b,
- 0x0045, 0x2091, 0x8001, 0x0f7f, 0x007c, 0x127e, 0x2091, 0x2300,
- 0x2071, 0x3940, 0x2079, 0x0100, 0x784b, 0x000f, 0x2019, 0x3205,
- 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040, 0x1d2f, 0x789a, 0x8318,
- 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, 0x0078, 0x1d22, 0x789b,
- 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, 0x0020, 0x0070,
- 0x1d3b, 0x0078, 0x1d33, 0x7003, 0x0000, 0x1078, 0x1e40, 0x7004,
- 0xa084, 0x000f, 0xa085, 0x6280, 0x7806, 0x780f, 0x9200, 0x7843,
- 0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7047, 0x397f, 0x7043,
- 0x0000, 0x127f, 0x2000, 0x007c, 0xa18c, 0x000f, 0x2011, 0x0101,
- 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x1078, 0x1e40, 0x007c,
- 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x0070, 0x1d69, 0x0078,
- 0x1d64, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012,
- 0x007c, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x0070, 0x1d7a,
- 0x0078, 0x1d75, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205,
- 0x200a, 0x007c, 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b, 0x0070,
- 0x1d8b, 0x0078, 0x1d86, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff,
- 0xa105, 0x2012, 0x007c, 0x2011, 0x0102, 0x2204, 0xa084, 0xffcf,
- 0xa105, 0x2012, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e,
- 0x2061, 0x0100, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x8103,
- 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4,
- 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080,
- 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa085, 0x0020,
- 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e,
- 0x2061, 0x0100, 0x609a, 0x60a4, 0x62ae, 0x2010, 0x60a4, 0x63ae,
- 0x2018, 0x0c7f, 0x007c, 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040,
- 0x1e1c, 0x2061, 0x4380, 0x1078, 0x1e22, 0x0040, 0x1e06, 0x20a9,
- 0x0000, 0x2061, 0x4280, 0x0c7e, 0x1078, 0x1e22, 0x0040, 0x1df0,
- 0x0c7f, 0x8c60, 0x0070, 0x1dee, 0x0078, 0x1de3, 0x0078, 0x1e1c,
- 0x007f, 0xa082, 0x4280, 0x2071, 0x3940, 0x70ba, 0x6020, 0xa085,
- 0x0800, 0x6022, 0x2091, 0x8001, 0x71b6, 0x2001, 0x0004, 0x70a2,
- 0x70c7, 0x000f, 0x1078, 0x1cf1, 0x0078, 0x1e18, 0x2071, 0x3940,
- 0x6020, 0xa085, 0x0800, 0x6022, 0x2091, 0x8001, 0x71b6, 0x2c00,
- 0x70be, 0x2001, 0x0006, 0x70a2, 0x70c7, 0x000f, 0x1078, 0x1cf1,
- 0x2001, 0x0000, 0x0078, 0x1e1e, 0x2001, 0x0001, 0xa005, 0x0e7f,
- 0x0c7f, 0x007c, 0x2091, 0x8000, 0x2c04, 0xa005, 0x0040, 0x1e3b,
- 0x2060, 0x6010, 0xa306, 0x00c0, 0x1e38, 0x600c, 0xa206, 0x00c0,
- 0x1e38, 0x6014, 0xa106, 0x00c0, 0x1e38, 0xa006, 0x0078, 0x1e3f,
- 0x6000, 0x0078, 0x1e25, 0xa085, 0x0001, 0x2091, 0x8001, 0x007c,
- 0x2011, 0x3941, 0x220c, 0xa18c, 0x000f, 0x2011, 0x013b, 0x2204,
- 0xa084, 0x0100, 0x0040, 0x1e56, 0x2021, 0xff04, 0x2122, 0x810b,
- 0x810b, 0x810b, 0x810b, 0xa18d, 0x0f00, 0x2104, 0x007c, 0x0e7e,
- 0x68e4, 0xa08c, 0x0020, 0x0040, 0x1eaa, 0xa084, 0x0006, 0x00c0,
- 0x1eaa, 0x6014, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
- 0xa0f0, 0x3a00, 0x7004, 0xa084, 0x000a, 0x00c0, 0x1eaa, 0x7108,
- 0xa194, 0xff00, 0x0040, 0x1eaa, 0xa18c, 0x00ff, 0x2001, 0x000c,
- 0xa106, 0x0040, 0x1e91, 0x2001, 0x0012, 0xa106, 0x0040, 0x1e95,
- 0x2001, 0x0014, 0xa106, 0x0040, 0x1e99, 0x2001, 0x0019, 0xa106,
- 0x0040, 0x1e9d, 0x2001, 0x0032, 0xa106, 0x0040, 0x1ea1, 0x0078,
- 0x1ea5, 0x2009, 0x0012, 0x0078, 0x1ea7, 0x2009, 0x0014, 0x0078,
- 0x1ea7, 0x2009, 0x0019, 0x0078, 0x1ea7, 0x2009, 0x0020, 0x0078,
- 0x1ea7, 0x2009, 0x003f, 0x0078, 0x1ea7, 0x2011, 0x0000, 0x2100,
- 0xa205, 0x700a, 0x0e7f, 0x007c, 0x2071, 0x0010, 0x70ca, 0x007f,
- 0x70c6, 0x70c3, 0x8002, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091,
- 0x4080, 0x0078, 0x1eb9, 0x107e, 0x007e, 0x127e, 0x2091, 0x2300,
- 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x2009, 0x3974, 0x78a0, 0x200a,
- 0x8108, 0x250a, 0x8108, 0x240a, 0x8108, 0x260a, 0x8108, 0x270a,
- 0xa594, 0x003f, 0xa484, 0x4000, 0x0040, 0x1edc, 0xa784, 0x007c,
- 0x00c0, 0x318f, 0x1078, 0x1eac, 0xa49c, 0x000f, 0xa382, 0x0004,
- 0x0050, 0x1ee4, 0x1078, 0x1eac, 0x8507, 0xa084, 0x000f, 0x0079,
- 0x1ee9, 0x236e, 0x240d, 0x242e, 0x2699, 0x28dd, 0x293b, 0x2984,
- 0x29f0, 0x2a8d, 0x2b1a, 0x1f11, 0x1ef9, 0x21c3, 0x2288, 0x28bc,
- 0x1ef9, 0x1078, 0x1eac, 0x0018, 0x1ec0, 0x127f, 0x2091, 0x8001,
- 0x007f, 0x107f, 0x007c, 0x7003, 0x0000, 0x703f, 0x0000, 0x7030,
- 0xa005, 0x0040, 0x1f0d, 0x7033, 0x0000, 0x1078, 0x316a, 0x0018,
- 0x1ec0, 0x2009, 0x390f, 0x200b, 0x0000, 0x705c, 0xa005, 0x00c0,
- 0x1fe2, 0x70a0, 0xa084, 0x0007, 0x0079, 0x1f1e, 0x2005, 0x1f26,
- 0x1f34, 0x1f51, 0x1f73, 0x1fc0, 0x1f99, 0x1f26, 0x7808, 0xa084,
- 0xfffd, 0x780a, 0x2009, 0x0047, 0x1078, 0x27c1, 0x00c0, 0x1f32,
- 0x7003, 0x0004, 0x0078, 0x1efb, 0x1078, 0x3151, 0x00c0, 0x1f4f,
- 0x70b4, 0x8007, 0x7882, 0x789b, 0x0010, 0x78ab, 0x000c, 0x789b,
- 0x0060, 0x78ab, 0x0001, 0x785b, 0x0004, 0x2009, 0x00fb, 0x1078,
- 0x27bf, 0x00c0, 0x1f4f, 0x7003, 0x0004, 0x70c7, 0x000f, 0x0078,
- 0x1efb, 0x1078, 0x3151, 0x00c0, 0x1f71, 0x71b4, 0x8107, 0x7882,
- 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab,
- 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002, 0x785b, 0x0004, 0x2009,
- 0x00fb, 0x1078, 0x27bf, 0x00c0, 0x1f71, 0x7003, 0x0004, 0x70c7,
- 0x000f, 0x0078, 0x1efb, 0x1078, 0x3151, 0x00c0, 0x1f97, 0x71b4,
- 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0,
- 0x79aa, 0x78ab, 0x0020, 0x71b8, 0x79aa, 0x78ab, 0x000d, 0x789b,
- 0x0060, 0x78ab, 0x0004, 0x785b, 0x0004, 0x2009, 0x00fb, 0x1078,
- 0x27bf, 0x00c0, 0x1f97, 0x7003, 0x0004, 0x70c7, 0x000f, 0x0078,
- 0x1efb, 0x1078, 0x3151, 0x00c0, 0x1fbe, 0x71b4, 0x8107, 0x7882,
- 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab,
- 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002, 0x785b, 0x0004, 0x2009,
- 0x00fb, 0x1078, 0x27bf, 0x00c0, 0x1fbe, 0x70bc, 0x70bf, 0x0000,
- 0x2068, 0x703e, 0x7003, 0x0002, 0x70c7, 0x000f, 0x0078, 0x1efb,
- 0x1078, 0x3151, 0x00c0, 0x1efb, 0x70bc, 0x2068, 0x1078, 0x31f3,
- 0x789b, 0x0010, 0x6814, 0xa084, 0x0007, 0xa085, 0x0080, 0x007e,
- 0x007f, 0x78aa, 0x6e1c, 0x067e, 0x067f, 0x2041, 0x0001, 0x70c0,
- 0xa084, 0x0400, 0x2001, 0x0004, 0x0040, 0x1fe0, 0x2001, 0x0006,
- 0x0078, 0x20e1, 0x1078, 0x3151, 0x00c0, 0x1efb, 0x789b, 0x0010,
- 0x705c, 0x2068, 0x1078, 0x31f3, 0x6f14, 0x1078, 0x3099, 0x6008,
- 0xa085, 0x0010, 0x600a, 0xad80, 0x0009, 0x2003, 0x0005, 0x6814,
- 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, 0x2031, 0x0020, 0x2041,
- 0x0001, 0x2001, 0x0003, 0x0078, 0x20e1, 0x0018, 0x1ec0, 0x7440,
- 0xa485, 0x0000, 0x0040, 0x201f, 0xa080, 0x3980, 0x2030, 0x7144,
- 0x8108, 0xa12a, 0x0048, 0x2016, 0x2009, 0x3980, 0x2164, 0x6504,
- 0x85ff, 0x00c0, 0x202c, 0x8421, 0x00c0, 0x2010, 0x7146, 0x7003,
- 0x0000, 0x703f, 0x0000, 0x0078, 0x1efb, 0x7640, 0xa6b0, 0x3980,
- 0x7144, 0x2600, 0x0078, 0x201b, 0x7146, 0x2568, 0x2558, 0x753e,
- 0x2c50, 0x6708, 0x7736, 0xa784, 0x013f, 0x0040, 0x2059, 0xa784,
- 0x0021, 0x00c0, 0x2029, 0xa784, 0x0002, 0x0040, 0x2046, 0xa784,
- 0x0004, 0x0040, 0x2029, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0008,
- 0x00c0, 0x2029, 0xa784, 0x0010, 0x00c0, 0x2029, 0xa784, 0x0100,
- 0x0040, 0x2059, 0x6018, 0xa005, 0x00c0, 0x2029, 0xa7bc, 0xfeff,
- 0x670a, 0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e, 0x6118, 0x0040,
- 0x2069, 0x601c, 0xa102, 0x0048, 0x206c, 0x0040, 0x206c, 0x0078,
- 0x2025, 0x81ff, 0x00c0, 0x2025, 0xa784, 0x0080, 0x00c0, 0x2072,
- 0x700c, 0x6022, 0x1078, 0x31f3, 0x0018, 0x1ec0, 0x789b, 0x0010,
- 0xa046, 0x1078, 0x3151, 0x00c0, 0x1efb, 0x6b14, 0xa39c, 0x0007,
- 0xa39d, 0x00c0, 0x704c, 0xa084, 0x8000, 0x0040, 0x208b, 0xa684,
- 0x0001, 0x0040, 0x208d, 0xa39c, 0xffbf, 0xa684, 0x0010, 0x0040,
- 0x2093, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684, 0x000e, 0x00c0,
- 0x209e, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x20df, 0x714c, 0xa18c,
- 0x0800, 0x0040, 0x2cfc, 0x2011, 0x0021, 0x8004, 0x8004, 0x0048,
- 0x20b5, 0x2011, 0x0022, 0x8004, 0x0048, 0x20b5, 0x2011, 0x0020,
- 0x8004, 0x0048, 0x20b5, 0x0040, 0x20df, 0x7aaa, 0x8840, 0x1078,
- 0x316a, 0x6a14, 0x610c, 0x8108, 0xa18c, 0x00ff, 0xa1e0, 0x4280,
- 0x2c64, 0x8cff, 0x0040, 0x20d6, 0x6014, 0xa206, 0x00c0, 0x20c0,
- 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x20bb, 0x0c7e, 0x2a60, 0x6008,
- 0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078, 0x2005, 0x1078, 0x3151,
- 0x00c0, 0x1efb, 0x2a60, 0x610e, 0x79aa, 0x8840, 0x712e, 0x2001,
- 0x0001, 0x007e, 0x7150, 0xa184, 0x0018, 0x0040, 0x20fc, 0xa184,
- 0x0010, 0x0040, 0x20ef, 0x1078, 0x2ee3, 0x00c0, 0x211f, 0xa184,
- 0x0008, 0x0040, 0x20fc, 0x69a0, 0xa184, 0x0600, 0x00c0, 0x20fc,
- 0x1078, 0x2ddf, 0x0078, 0x211f, 0x69a0, 0xa184, 0x0800, 0x0040,
- 0x2113, 0x0c7e, 0x027e, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002,
- 0x6104, 0xa18d, 0x0010, 0x6106, 0x027f, 0x0c7f, 0x1078, 0x2ee3,
- 0x00c0, 0x211f, 0x69a0, 0xa184, 0x0200, 0x0040, 0x211b, 0x1078,
- 0x2e2e, 0x0078, 0x211f, 0xa184, 0x0400, 0x00c0, 0x20f8, 0x69a0,
- 0xa184, 0x1000, 0x0040, 0x212a, 0x6914, 0xa18c, 0xff00, 0x810f,
- 0x1078, 0x1da7, 0x007f, 0x7002, 0xa68c, 0x00e0, 0xa684, 0x0060,
- 0x0040, 0x2138, 0xa086, 0x0060, 0x00c0, 0x2138, 0xa18d, 0x4000,
- 0x88ff, 0x0040, 0x213d, 0xa18d, 0x0004, 0x795a, 0x69b6, 0x789b,
- 0x0060, 0x2800, 0x78aa, 0x789b, 0x0061, 0x6818, 0xa08d, 0x8000,
- 0xa084, 0x7fff, 0x691a, 0xa68c, 0x0080, 0x0040, 0x215c, 0x70cb,
- 0x0000, 0xa08a, 0x000d, 0x0050, 0x215a, 0xa08a, 0x000c, 0x71ca,
- 0x2001, 0x000c, 0x800c, 0x71ce, 0x78aa, 0x8008, 0x810c, 0x0040,
- 0x2d07, 0xa18c, 0x00f8, 0x00c0, 0x2d07, 0x157e, 0x137e, 0x147e,
- 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b,
- 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6814, 0x8007, 0x7882,
- 0x6d94, 0x7dd6, 0x7dde, 0x6e98, 0x7ed2, 0x7eda, 0x7830, 0xa084,
- 0x00c0, 0x00c0, 0x2185, 0x0098, 0x218d, 0x6008, 0xa084, 0xffef,
- 0x600a, 0x1078, 0x316a, 0x0078, 0x1f03, 0x7200, 0xa284, 0x0007,
- 0xa086, 0x0001, 0x00c0, 0x219a, 0x781b, 0x004a, 0x1078, 0x316a,
- 0x0078, 0x21ab, 0x6ab4, 0xa295, 0x2000, 0x7a5a, 0x781b, 0x004a,
- 0x1078, 0x316a, 0x7200, 0x2500, 0xa605, 0x0040, 0x21ab, 0xa284,
- 0x0007, 0x1079, 0x21b9, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0,
- 0x1efb, 0x6018, 0x8000, 0x601a, 0xad80, 0x0009, 0x7032, 0x0078,
- 0x1efb, 0x21c1, 0x3571, 0x3571, 0x3560, 0x3571, 0x21c1, 0x3560,
- 0x21c1, 0x1078, 0x1eac, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0f7e,
- 0x2079, 0x3900, 0x78c0, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x21e9,
- 0x70a0, 0xa086, 0x0001, 0x00c0, 0x21d8, 0x70a2, 0x0078, 0x226c,
- 0x70a0, 0xa086, 0x0005, 0x00c0, 0x21e7, 0x70bc, 0x2068, 0x681b,
- 0x0004, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x70a3,
- 0x0000, 0x157e, 0x2011, 0x0004, 0x71a0, 0xa186, 0x0001, 0x0040,
- 0x2207, 0xa186, 0x0007, 0x00c0, 0x21fb, 0x2009, 0x3935, 0x200b,
- 0x0005, 0x0078, 0x2207, 0x2009, 0x3913, 0x2104, 0x2009, 0x3912,
- 0x200a, 0x2009, 0x3935, 0x200b, 0x0001, 0x0078, 0x2209, 0x70a3,
- 0x0000, 0x1078, 0x32f5, 0x20a9, 0x0010, 0x2039, 0x0000, 0x1078,
- 0x2f9a, 0xa7b8, 0x0100, 0x0070, 0x2217, 0x0078, 0x220f, 0x7000,
- 0x0079, 0x221a, 0x2248, 0x2231, 0x2231, 0x2224, 0x2248, 0x2248,
- 0x2248, 0x2222, 0x1078, 0x1eac, 0x2021, 0x3957, 0x2404, 0xa005,
- 0x0040, 0x2248, 0xad06, 0x00c0, 0x2231, 0x6800, 0x2022, 0x0078,
- 0x2241, 0x6820, 0xa084, 0x0001, 0x00c0, 0x223d, 0x6f14, 0x1078,
- 0x3099, 0x1078, 0x2cc9, 0x0078, 0x2241, 0x7054, 0x2060, 0x6800,
- 0x6002, 0x6a1a, 0x6820, 0xa085, 0x0008, 0x6822, 0x1078, 0x1a26,
- 0x2021, 0x4380, 0x1078, 0x2272, 0x2021, 0x3957, 0x1078, 0x2272,
- 0x20a9, 0x0000, 0x2021, 0x4280, 0x1078, 0x2272, 0x8420, 0x0070,
- 0x225b, 0x0078, 0x2254, 0x20a9, 0x0080, 0x2061, 0x3a80, 0x6018,
- 0x6110, 0xa102, 0x6012, 0x601b, 0x0000, 0xace0, 0x0010, 0x0070,
- 0x226b, 0x0078, 0x225f, 0x157f, 0x7003, 0x0000, 0x703f, 0x0000,
- 0x0078, 0x1efb, 0x047e, 0x2404, 0xa005, 0x0040, 0x2284, 0x2068,
- 0x6800, 0x007e, 0x6a1a, 0x6820, 0xa085, 0x0008, 0x6822, 0x1078,
- 0x1a26, 0x007f, 0x0078, 0x2274, 0x047f, 0x2023, 0x0000, 0x007c,
- 0xa282, 0x0003, 0x0050, 0x228e, 0x1078, 0x1eac, 0x2300, 0x0079,
- 0x2291, 0x2294, 0x2311, 0x232e, 0xa282, 0x0002, 0x0040, 0x229a,
- 0x1078, 0x1eac, 0x70a0, 0x70a3, 0x0000, 0x70c7, 0x0000, 0x0079,
- 0x22a1, 0x22a9, 0x22a9, 0x22ab, 0x22e9, 0x2d0d, 0x22a9, 0x22e9,
- 0x22a9, 0x1078, 0x1eac, 0x77b4, 0x1078, 0x2f9a, 0x77b4, 0xa7bc,
- 0x0f00, 0x1078, 0x3099, 0x6018, 0xa005, 0x0040, 0x22e0, 0x2021,
- 0x4380, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x2349, 0x0040,
- 0x22e0, 0x157e, 0x20a9, 0x0000, 0x2021, 0x4280, 0x047e, 0x2009,
- 0x0004, 0x2011, 0x0010, 0x1078, 0x2349, 0x047f, 0x0040, 0x22d5,
- 0x8420, 0x0070, 0x22d5, 0x0078, 0x22c6, 0x157f, 0x2021, 0x3957,
- 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x2349, 0x0040, 0x22e0,
- 0x8738, 0xa784, 0x0007, 0x00c0, 0x22b1, 0x0078, 0x1f03, 0x0078,
- 0x1f03, 0x77b4, 0x1078, 0x3099, 0x6018, 0xa005, 0x0040, 0x230f,
- 0x2021, 0x4380, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x2349,
- 0x0040, 0x230f, 0x157e, 0x20a9, 0x0000, 0x2021, 0x4280, 0x047e,
- 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x2349, 0x047f, 0x0040,
- 0x230e, 0x8420, 0x0070, 0x230e, 0x0078, 0x22ff, 0x157f, 0x0078,
- 0x1f03, 0x2200, 0x0079, 0x2314, 0x2317, 0x2319, 0x2319, 0x1078,
- 0x1eac, 0x2009, 0x0012, 0x70a0, 0xa086, 0x0002, 0x0040, 0x2322,
- 0x2009, 0x000e, 0x6818, 0xa084, 0x8000, 0x0040, 0x2328, 0x691a,
- 0x70a3, 0x0000, 0x70a7, 0x0001, 0x0078, 0x311c, 0x2200, 0x0079,
- 0x2331, 0x2336, 0x2319, 0x2334, 0x1078, 0x1eac, 0x1078, 0x27ce,
- 0x7000, 0xa086, 0x0001, 0x00c0, 0x2c9f, 0x1078, 0x2cdf, 0x6008,
- 0xa084, 0xffef, 0x600a, 0x1078, 0x2c92, 0x0040, 0x2c9f, 0x0078,
- 0x2005, 0x2404, 0xa005, 0x0040, 0x236a, 0x2068, 0x2d04, 0x007e,
- 0x6814, 0xa706, 0x0040, 0x2358, 0x2d20, 0x007f, 0x0078, 0x234a,
- 0x007f, 0x2022, 0x691a, 0x6820, 0xa205, 0x6822, 0x1078, 0x1a26,
- 0x6010, 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078,
- 0x2cdf, 0x007c, 0xa085, 0x0001, 0x0078, 0x2369, 0x2300, 0x0079,
- 0x2371, 0x2376, 0x2374, 0x23c2, 0x1078, 0x1eac, 0x78e4, 0xa005,
- 0x00d0, 0x238a, 0x0018, 0x238a, 0xa084, 0x0007, 0x0079, 0x2380,
- 0x239b, 0x23a8, 0x238e, 0x2388, 0x3144, 0x3144, 0x2388, 0x23b5,
- 0x1078, 0x1eac, 0x2001, 0x0003, 0x0078, 0x26ad, 0x6818, 0xa084,
- 0x8000, 0x0040, 0x2395, 0x681b, 0x001d, 0x1078, 0x2f7d, 0x781b,
- 0x0053, 0x0078, 0x1efb, 0x6818, 0xa084, 0x8000, 0x0040, 0x23a2,
- 0x681b, 0x001d, 0x1078, 0x2f7d, 0x781b, 0x00de, 0x0078, 0x1efb,
- 0x6818, 0xa084, 0x8000, 0x0040, 0x23af, 0x681b, 0x001d, 0x1078,
- 0x2f7d, 0x781b, 0x00e5, 0x0078, 0x1efb, 0x6818, 0xa084, 0x8000,
- 0x0040, 0x23bc, 0x681b, 0x001d, 0x1078, 0x2f7d, 0x781b, 0x009c,
- 0x0078, 0x1efb, 0xa584, 0x000f, 0x00c0, 0x23e1, 0x1078, 0x27ce,
- 0x7000, 0x0079, 0x23cb, 0x23d3, 0x23d5, 0x23d3, 0x2c9f, 0x2c9f,
- 0x2c9f, 0x2c9f, 0x23d3, 0x1078, 0x1eac, 0x1078, 0x2cdf, 0x6008,
- 0xa084, 0xffef, 0x600a, 0x1078, 0x2c92, 0x0040, 0x2c9f, 0x0078,
- 0x2005, 0x79e4, 0xa005, 0x00d0, 0x238a, 0x0018, 0x238a, 0xa184,
- 0x0007, 0x0079, 0x23eb, 0x23fb, 0x2401, 0x23f5, 0x23f3, 0x3144,
- 0x3144, 0x23f3, 0x313c, 0x1078, 0x1eac, 0x1078, 0x2f85, 0x781b,
- 0x0053, 0x0078, 0x1efb, 0x1078, 0x2f85, 0x781b, 0x00de, 0x0078,
- 0x1efb, 0x1078, 0x2f85, 0x781b, 0x00e5, 0x0078, 0x1efb, 0x1078,
- 0x2f85, 0x781b, 0x009c, 0x0078, 0x1efb, 0x2300, 0x0079, 0x2410,
- 0x2415, 0x2413, 0x2417, 0x1078, 0x1eac, 0x0078, 0x29f0, 0x681b,
- 0x0008, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x29f0,
- 0xa184, 0x0007, 0x0079, 0x2424, 0x242c, 0x2401, 0x238e, 0x311c,
- 0x3144, 0x3144, 0x242c, 0x313c, 0x1078, 0x1eac, 0xa282, 0x0005,
- 0x0050, 0x2434, 0x1078, 0x1eac, 0x2300, 0x0079, 0x2437, 0x243a,
- 0x265e, 0x266a, 0x2200, 0x0079, 0x243d, 0x2457, 0x2444, 0x2457,
- 0x2442, 0x2643, 0x1078, 0x1eac, 0x789b, 0x0018, 0x78a8, 0xa084,
- 0x00ff, 0xa082, 0x0020, 0x0048, 0x2f69, 0xa08a, 0x0004, 0x00c8,
- 0x2f69, 0x0079, 0x2453, 0x2f69, 0x2f69, 0x2f69, 0x2f23, 0x789b,
- 0x0018, 0x79a8, 0xa184, 0x0080, 0x0040, 0x246c, 0xa184, 0x0018,
- 0x0040, 0x2468, 0x0078, 0x2f69, 0x7000, 0xa005, 0x00c0, 0x2462,
- 0x2011, 0x0004, 0x0078, 0x2b28, 0xa184, 0x00ff, 0xa08a, 0x0010,
- 0x00c8, 0x2f69, 0x0079, 0x2474, 0x2486, 0x2484, 0x249e, 0x24a2,
- 0x255a, 0x2f69, 0x2f69, 0x255c, 0x2f69, 0x2f69, 0x263f, 0x263f,
- 0x2f69, 0x2f69, 0x2f69, 0x2641, 0x1078, 0x1eac, 0xa684, 0x1000,
- 0x0040, 0x2493, 0x2001, 0x0300, 0x8000, 0x8000, 0x783a, 0x781b,
- 0x0099, 0x0078, 0x1efb, 0x6818, 0xa084, 0x8000, 0x0040, 0x249c,
- 0x681b, 0x001d, 0x0078, 0x248a, 0x0078, 0x311c, 0x681b, 0x001d,
- 0x0078, 0x2f75, 0x6920, 0xa184, 0x8000, 0x00c0, 0x24ae, 0x68af,
- 0x0000, 0x68b3, 0x0000, 0xa18d, 0x8000, 0x6922, 0xa684, 0x1800,
- 0x00c0, 0x24ed, 0x6820, 0xa084, 0x0001, 0x00c0, 0x24f3, 0x6818,
- 0xa086, 0x0008, 0x00c0, 0x24be, 0x681b, 0x0000, 0xa684, 0x0400,
- 0x0040, 0x2556, 0xa684, 0x0080, 0x0040, 0x24e9, 0x70cb, 0x0000,
- 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, 0x0050, 0x24e9, 0xa08a,
- 0x000c, 0x71ca, 0x2001, 0x000c, 0x800c, 0x71ce, 0x789b, 0x0061,
- 0x78aa, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000,
- 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f,
- 0x157f, 0x781b, 0x0056, 0x0078, 0x1efb, 0xa684, 0x1000, 0x0040,
- 0x24f3, 0x0078, 0x1efb, 0xa684, 0x0060, 0x0040, 0x2552, 0xa684,
- 0x0800, 0x0040, 0x2552, 0xa684, 0x8000, 0x00c0, 0x2503, 0x69b0,
- 0x6aac, 0x0078, 0x251d, 0xa6b4, 0x7fff, 0x7e5a, 0x6eb6, 0x789b,
- 0x0074, 0x7aac, 0x79ac, 0x78ac, 0x801b, 0x00c8, 0x2510, 0x8000,
- 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302,
- 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0xa684, 0x4000, 0x0040,
- 0x2525, 0xa6b4, 0xbfff, 0x7e5a, 0x6eb6, 0xa006, 0x1078, 0x362f,
- 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040, 0x2534,
- 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x6ba6, 0x7bd6,
- 0x2300, 0xa405, 0x00c0, 0x2544, 0xa6b5, 0x4000, 0x7e5a, 0x6eb6,
- 0x781b, 0x0065, 0x0078, 0x1efb, 0x781b, 0x0065, 0x2200, 0xa115,
- 0x00c0, 0x254e, 0x1078, 0x3571, 0x0078, 0x1efb, 0x1078, 0x35a6,
- 0x0078, 0x1efb, 0x781b, 0x0068, 0x0078, 0x1efb, 0x781b, 0x0056,
- 0x0078, 0x1efb, 0x1078, 0x1eac, 0x0078, 0x25b1, 0x6920, 0xa184,
- 0x0100, 0x0040, 0x2570, 0xa18c, 0xfeff, 0x6922, 0x0c7e, 0x7048,
- 0x2060, 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078, 0x25a0,
- 0xa184, 0x0200, 0x0040, 0x25a0, 0xa18c, 0xfdff, 0x6922, 0x0c7e,
- 0x7048, 0x2060, 0x6004, 0xa084, 0xffef, 0x6006, 0x2008, 0x2c48,
- 0x0c7f, 0xa184, 0x0008, 0x0040, 0x25a0, 0x1078, 0x3095, 0x1078,
- 0x2ddf, 0x88ff, 0x0040, 0x25a0, 0x789b, 0x0060, 0x2800, 0x78aa,
- 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x259c,
- 0x781b, 0x0053, 0x0078, 0x1efb, 0x781b, 0x0067, 0x0078, 0x1efb,
- 0x7e58, 0xa684, 0x0400, 0x00c0, 0x25a9, 0x781b, 0x0056, 0x0078,
- 0x1efb, 0x781b, 0x0068, 0x0078, 0x1efb, 0x0078, 0x2f6f, 0x0078,
- 0x2f6f, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x0040, 0x25af,
- 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0,
- 0x25d4, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x25cc,
- 0x0048, 0x25cc, 0x0078, 0x25ce, 0x0078, 0x255e, 0x24a8, 0x7aa8,
- 0x00f0, 0x25ce, 0x0078, 0x25ba, 0xa284, 0x00f0, 0xa086, 0x0020,
- 0x00c0, 0x2630, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040, 0x25e4,
- 0x0048, 0x25e4, 0x0078, 0x262d, 0xa286, 0x0023, 0x0040, 0x25af,
- 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1, 0xa085,
- 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085, 0x0010, 0x600a, 0x0c7e,
- 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0010,
- 0x0040, 0x2608, 0x1078, 0x3095, 0x1078, 0x2ee3, 0x0078, 0x2617,
- 0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xa184,
- 0x0008, 0x0040, 0x25a0, 0x1078, 0x3095, 0x1078, 0x2ddf, 0x88ff,
- 0x0040, 0x25a0, 0x789b, 0x0060, 0x2800, 0x78aa, 0xa6b5, 0x0004,
- 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2629, 0x781b, 0x0053, 0x0078,
- 0x1efb, 0x781b, 0x0067, 0x0078, 0x1efb, 0x7aa8, 0x0078, 0x25ba,
- 0x8318, 0x2300, 0xa102, 0x0040, 0x2639, 0x0048, 0x2639, 0x0078,
- 0x25ba, 0xa284, 0x0080, 0x00c0, 0x2f75, 0x0078, 0x2f6f, 0x0078,
- 0x2f75, 0x0078, 0x2f69, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff,
- 0xa08e, 0x0001, 0x0040, 0x264e, 0x1078, 0x1eac, 0x7aa8, 0xa294,
- 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x2f69,
- 0x0079, 0x265a, 0x2f69, 0x2d32, 0x2f69, 0x2e7e, 0xa282, 0x0000,
- 0x00c0, 0x2664, 0x1078, 0x1eac, 0x1078, 0x2f7d, 0x781b, 0x0067,
- 0x0078, 0x1efb, 0xa282, 0x0003, 0x00c0, 0x2670, 0x1078, 0x1eac,
- 0xa484, 0x8000, 0x00c0, 0x2693, 0x70a0, 0xa005, 0x0040, 0x267a,
- 0x1078, 0x1eac, 0x6f14, 0x77b6, 0xa7bc, 0x0f00, 0x1078, 0x3099,
- 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x0007, 0x00c0,
- 0x267e, 0x1078, 0x2f81, 0x70a3, 0x0002, 0x2009, 0x3935, 0x200b,
- 0x0009, 0x0078, 0x2695, 0x1078, 0x2f8d, 0x781b, 0x0067, 0x0078,
- 0x1efb, 0xa282, 0x0004, 0x0050, 0x269f, 0x1078, 0x1eac, 0x2300,
- 0x0079, 0x26a2, 0x26a5, 0x2781, 0x27a9, 0xa286, 0x0003, 0x0040,
- 0x26ab, 0x1078, 0x1eac, 0x2001, 0x0000, 0x703a, 0x7000, 0xa084,
- 0x0007, 0x0079, 0x26b3, 0x26bb, 0x26bd, 0x26bd, 0x2871, 0x28a2,
- 0x1f03, 0x28a2, 0x26bb, 0x1078, 0x1eac, 0xa684, 0x1000, 0x00c0,
- 0x26c5, 0x1078, 0x32f5, 0x0040, 0x275b, 0x7868, 0xa08c, 0x00ff,
- 0x0040, 0x270d, 0xa186, 0x0008, 0x00c0, 0x26dc, 0x1078, 0x2cdf,
- 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x2c92, 0x0040, 0x270d,
- 0x1078, 0x32f5, 0x0078, 0x26f4, 0xa186, 0x0028, 0x00c0, 0x270d,
- 0x1078, 0x32f5, 0x6008, 0xa084, 0xffef, 0x600a, 0x6018, 0xa005,
- 0x0040, 0x26f4, 0x8001, 0x601a, 0xa005, 0x0040, 0x26f4, 0x8001,
- 0xa005, 0x0040, 0x26f4, 0x601e, 0x6820, 0xa084, 0x0001, 0x0040,
- 0x1f03, 0x6820, 0xa084, 0xfffe, 0x6822, 0x7054, 0x0c7e, 0x2060,
- 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0,
- 0x270a, 0x6002, 0x6006, 0x0078, 0x1f03, 0x017e, 0x1078, 0x27ce,
- 0x017f, 0xa684, 0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14, 0x81ff,
- 0x0040, 0x275b, 0xa186, 0x0002, 0x00c0, 0x2753, 0xa684, 0x0800,
- 0x00c0, 0x272a, 0xa684, 0x0060, 0x0040, 0x272a, 0x78d8, 0x7adc,
- 0x682e, 0x6a32, 0x6820, 0xa084, 0x0800, 0x00c0, 0x275b, 0x8717,
- 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xa290, 0x3a00, 0xa290,
- 0x0000, 0x221c, 0x8210, 0x2204, 0xa085, 0x0018, 0x2012, 0x8211,
- 0xa384, 0x0400, 0x0040, 0x274d, 0x68a0, 0xa084, 0x0100, 0x00c0,
- 0x274d, 0x1078, 0x2830, 0x0078, 0x1f03, 0x6008, 0xa085, 0x0002,
- 0x600a, 0x0078, 0x275b, 0xa186, 0x0018, 0x0040, 0x275b, 0xa186,
- 0x0014, 0x0040, 0x1f03, 0x6916, 0x6818, 0xa084, 0x8000, 0x0040,
- 0x2763, 0x7038, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x1078, 0x2cd0,
- 0x1078, 0x2cdf, 0x00c0, 0x2770, 0x6008, 0xa084, 0xffef, 0x600a,
- 0x6820, 0xa084, 0x0001, 0x00c0, 0x2779, 0x1078, 0x2cc9, 0x0078,
- 0x277d, 0x7054, 0x2060, 0x6800, 0x6002, 0x1078, 0x1a26, 0x0078,
- 0x1f03, 0xa282, 0x0004, 0x0048, 0x2787, 0x1078, 0x1eac, 0x2200,
- 0x0079, 0x278a, 0x2785, 0x278e, 0x2794, 0x278e, 0x1078, 0x2f7d,
- 0x781b, 0x0067, 0x0078, 0x1efb, 0x7890, 0x8007, 0x8001, 0xa084,
- 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186,
- 0x0003, 0x0040, 0x27a5, 0x0078, 0x2f69, 0x781b, 0x0068, 0x0078,
- 0x1efb, 0x6820, 0xa085, 0x0004, 0x6822, 0x82ff, 0x00c0, 0x27b4,
- 0x1078, 0x2f7d, 0x0078, 0x27bb, 0x8211, 0x0040, 0x27b9, 0x1078,
- 0x1eac, 0x1078, 0x2f8d, 0x781b, 0x0067, 0x0078, 0x1efb, 0x1078,
- 0x316a, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x27cb, 0x0018, 0x27cb,
- 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684, 0x0060,
- 0x00c0, 0x27d8, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x282f,
- 0xa684, 0x0800, 0x00c0, 0x27e8, 0x6998, 0x6a94, 0x692e, 0x6a32,
- 0x7000, 0xa086, 0x0006, 0x0040, 0x27e7, 0x1078, 0x32f5, 0x007c,
- 0xa684, 0x0020, 0x0040, 0x2802, 0xa684, 0x4000, 0x0040, 0x27f6,
- 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x27e0, 0x7038, 0xa005,
- 0x00c0, 0x27fc, 0x703b, 0x0015, 0x79d8, 0x7adc, 0x692e, 0x6a32,
- 0x0078, 0x27e0, 0xa684, 0x4000, 0x0040, 0x280c, 0x682f, 0x0000,
- 0x6833, 0x0000, 0x0078, 0x27e0, 0x7038, 0xa005, 0x00c0, 0x2812,
- 0x703b, 0x0015, 0x79d8, 0x7adc, 0x78d0, 0x80fb, 0x00c8, 0x2819,
+ 0x72ca, 0x73ce, 0x74d6, 0xa005, 0x0040, 0x1387, 0x8001, 0x78ae,
+ 0xa084, 0xfc00, 0x0040, 0x137c, 0x78cc, 0xa085, 0x0100, 0x78ce,
+ 0x2001, 0x4005, 0x0078, 0x1286, 0x7ab6, 0x7bba, 0x7dbe, 0x7ec2,
+ 0x7cb2, 0x78cc, 0xa084, 0xfcff, 0x78ce, 0x0078, 0x138b, 0x78cc,
+ 0xa085, 0x0100, 0x78ce, 0x0078, 0x1284, 0x2009, 0x5061, 0x210c,
+ 0x7aec, 0x0078, 0x1282, 0x2009, 0x5041, 0x210c, 0x0078, 0x1283,
+ 0x2009, 0x5042, 0x210c, 0x0078, 0x1283, 0x2061, 0x5040, 0x610c,
+ 0x6210, 0x0078, 0x1282, 0x2009, 0x5045, 0x210c, 0x0078, 0x1283,
+ 0x2009, 0x5046, 0x210c, 0x0078, 0x1283, 0x2009, 0x5048, 0x210c,
+ 0x0078, 0x1283, 0x2009, 0x5049, 0x210c, 0x0078, 0x1283, 0x7908,
+ 0x7a0c, 0x0078, 0x1282, 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003,
+ 0x8003, 0x8003, 0xa0e8, 0x5280, 0x6a00, 0x6804, 0xa084, 0x0008,
+ 0x0040, 0x13cd, 0x6b08, 0x0078, 0x13ce, 0x6b0c, 0x0078, 0x1281,
+ 0x77c4, 0x1078, 0x1956, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091,
+ 0x8001, 0x2708, 0x0078, 0x1281, 0x794c, 0x0078, 0x1283, 0x77c4,
+ 0x1078, 0x1956, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x2091,
+ 0x8001, 0x0078, 0x1281, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x127c,
+ 0x1078, 0x22c1, 0x0078, 0x1281, 0x71c4, 0xa182, 0x0010, 0x00c8,
+ 0x127c, 0x2011, 0x5041, 0x2204, 0x007e, 0x2112, 0x1078, 0x227a,
+ 0x017f, 0x0078, 0x1283, 0x71c4, 0x2011, 0x1421, 0x20a9, 0x0008,
+ 0x2204, 0xa106, 0x0040, 0x1413, 0x8210, 0x0070, 0x1411, 0x0078,
+ 0x1408, 0x0078, 0x127c, 0xa292, 0x1421, 0x027e, 0x2011, 0x5042,
+ 0x2204, 0x2112, 0x017f, 0x007e, 0x1078, 0x2286, 0x017f, 0x0078,
+ 0x1283, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032,
+ 0x004b, 0x2061, 0x5040, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8,
+ 0x6012, 0x0078, 0x1282, 0x2061, 0x5040, 0x6114, 0x70c4, 0x6016,
+ 0x0078, 0x1283, 0x2061, 0x5040, 0x71c4, 0x2011, 0x0004, 0x601f,
+ 0x0019, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x145b, 0x2011,
+ 0x0005, 0x601f, 0x0019, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040,
+ 0x145b, 0x2011, 0x0006, 0x601f, 0x000c, 0x2019, 0x2222, 0xa186,
+ 0x003c, 0x00c0, 0x127c, 0x6018, 0x007e, 0x611a, 0x7800, 0xa084,
+ 0x0001, 0x00c0, 0x1476, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
+ 0x0048, 0x146e, 0x0038, 0x1472, 0x0078, 0x1476, 0x0028, 0x1472,
+ 0x0078, 0x1476, 0x2019, 0x2222, 0x0078, 0x1478, 0x2019, 0x1212,
+ 0x23b8, 0x1078, 0x2297, 0x1078, 0x4bdf, 0x017f, 0x0078, 0x1283,
+ 0x71c4, 0xa184, 0xffcf, 0x00c0, 0x127c, 0x2011, 0x5048, 0x2204,
+ 0x2112, 0x007e, 0x1078, 0x22b9, 0x017f, 0x0078, 0x1283, 0x71c4,
+ 0xa182, 0x0010, 0x00c8, 0x127c, 0x2011, 0x5049, 0x2204, 0x007e,
+ 0x2112, 0x1078, 0x22a8, 0x017f, 0x0078, 0x1283, 0x71c4, 0x72c8,
+ 0xa184, 0xfffd, 0x00c0, 0x127b, 0xa284, 0xfffd, 0x00c0, 0x127b,
+ 0x2100, 0x7908, 0x780a, 0x2200, 0x7a0c, 0x780e, 0x0078, 0x1282,
+ 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8,
+ 0x5280, 0x2019, 0x0000, 0x72c8, 0xa284, 0x0080, 0x0040, 0x14c6,
+ 0x6c14, 0x84ff, 0x00c0, 0x14c6, 0x6817, 0x0040, 0xa284, 0x0040,
+ 0x0040, 0x14d0, 0x6c10, 0x84ff, 0x00c0, 0x14d0, 0x6813, 0x0001,
+ 0x6800, 0x007e, 0xa226, 0x0040, 0x14f3, 0x6a02, 0xa484, 0x2000,
+ 0x0040, 0x14dc, 0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x14e2,
+ 0xa39d, 0x0008, 0xa484, 0x4000, 0x0040, 0x14f3, 0x810f, 0xa284,
+ 0x4000, 0x0040, 0x14ef, 0x1078, 0x22db, 0x0078, 0x14f3, 0x1078,
+ 0x22cd, 0x0078, 0x14f3, 0x72cc, 0x6808, 0xa206, 0x0040, 0x1522,
+ 0xa2a4, 0x00ff, 0x2061, 0x5040, 0x6118, 0xa186, 0x0028, 0x0040,
+ 0x1509, 0xa186, 0x0032, 0x0040, 0x150f, 0xa186, 0x003c, 0x0040,
+ 0x1515, 0xa482, 0x0064, 0x0048, 0x151f, 0x0078, 0x1519, 0xa482,
+ 0x0050, 0x0048, 0x151f, 0x0078, 0x1519, 0xa482, 0x0043, 0x0048,
+ 0x151f, 0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x127d, 0x6a0a,
+ 0xa39d, 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4,
+ 0x0078, 0x1281, 0x77c4, 0x1078, 0x1956, 0x2091, 0x8000, 0x6a14,
+ 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708,
+ 0x0078, 0x1281, 0x70c4, 0x794c, 0x784e, 0x0078, 0x1283, 0x71c4,
+ 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8, 0x127c, 0x1078, 0x22e9,
+ 0x0078, 0x1281, 0x77c4, 0x1078, 0x1956, 0x2091, 0x8000, 0x6a08,
+ 0xa295, 0x0002, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282,
+ 0x77c4, 0x1078, 0x1956, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9,
+ 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1567, 0x1078, 0x21b1, 0x2091,
+ 0x8001, 0x2708, 0x0078, 0x1282, 0x77c4, 0x1078, 0x1956, 0x2091,
+ 0x8000, 0x6a08, 0xa295, 0x0004, 0x6a0a, 0x6804, 0xa005, 0x0040,
+ 0x157b, 0x1078, 0x21b1, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282,
+ 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091,
+ 0x8000, 0x1078, 0x1963, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078,
+ 0x1282, 0x77c4, 0x72c8, 0x73cc, 0x77c6, 0x72ca, 0x73ce, 0x1078,
+ 0x19c4, 0x00c0, 0x15a9, 0x6818, 0xa005, 0x0040, 0x15a9, 0x2708,
+ 0x1078, 0x22f9, 0x00c0, 0x15a9, 0x7817, 0x0015, 0x2091, 0x8001,
+ 0x007c, 0x2091, 0x8001, 0x0078, 0x1284, 0x77c4, 0x77c6, 0x2041,
+ 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
+ 0x1963, 0x2061, 0x5040, 0x606f, 0x0003, 0x6782, 0x6093, 0x000f,
+ 0x6073, 0x0000, 0x7817, 0x0016, 0x1078, 0x21b1, 0x2091, 0x8001,
+ 0x007c, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091,
+ 0x8000, 0x2061, 0x5040, 0x606f, 0x0002, 0x6073, 0x0000, 0x6782,
+ 0x6093, 0x000f, 0x7817, 0x0017, 0x1078, 0x21b1, 0x2091, 0x8001,
+ 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x2091, 0x8000,
+ 0x1078, 0x1963, 0x70c8, 0x6836, 0x8738, 0xa784, 0x001f, 0x00c0,
+ 0x15e8, 0x2091, 0x8001, 0x007c, 0x78cc, 0xa084, 0x0003, 0x00c0,
+ 0x1618, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051,
+ 0x0008, 0x1078, 0x1956, 0x2091, 0x8000, 0x6808, 0xa80d, 0x690a,
+ 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1601, 0xa7bc,
+ 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1601,
+ 0x2091, 0x8000, 0x2069, 0x0100, 0x6830, 0xa084, 0x0040, 0x0040,
+ 0x1641, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004,
+ 0x0040, 0x162e, 0x0070, 0x162e, 0x0078, 0x1625, 0x684b, 0x0009,
+ 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, 0x163b, 0x0070,
+ 0x163b, 0x0078, 0x1632, 0x20a9, 0x00fa, 0x0070, 0x1641, 0x0078,
+ 0x163d, 0x2079, 0x5000, 0x7817, 0x0018, 0x2061, 0x5040, 0x606f,
+ 0x0001, 0x6073, 0x0000, 0x6093, 0x000f, 0x78cc, 0xa085, 0x0002,
+ 0x78ce, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0048, 0x2091,
+ 0x8001, 0x007c, 0x78cc, 0xa084, 0xfffd, 0x78ce, 0xa084, 0x0001,
+ 0x00c0, 0x1664, 0x1078, 0x1a0e, 0x71c4, 0x71c6, 0x794a, 0x007c,
+ 0x1078, 0x1b36, 0x00c0, 0x129c, 0x75d8, 0x74dc, 0x75da, 0x74de,
+ 0x0078, 0x1675, 0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8, 0x72cc,
+ 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x5000, 0x2091, 0x8000, 0x1078,
+ 0x1911, 0x2091, 0x8001, 0x0040, 0x172c, 0x20a9, 0x0005, 0x20a1,
+ 0x5018, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0020,
+ 0x1078, 0x190c, 0x0040, 0x1698, 0x1078, 0x192b, 0x0078, 0x172c,
+ 0x6004, 0xa084, 0xff00, 0x8007, 0x8009, 0x0040, 0x16fb, 0x0c7e,
+ 0x2c68, 0x2091, 0x8000, 0x1078, 0x1911, 0x2091, 0x8001, 0x0040,
+ 0x16cc, 0x2c00, 0x689e, 0x8109, 0x00c0, 0x16a0, 0x609f, 0x0000,
+ 0x0c7f, 0x0c7e, 0x7218, 0x731c, 0x7420, 0x7524, 0x2c68, 0x689c,
+ 0xa065, 0x0040, 0x16fa, 0x2009, 0x0020, 0x1078, 0x190c, 0x00c0,
+ 0x16e3, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0002, 0x00c0, 0x16cc,
+ 0x2d00, 0x6002, 0x0078, 0x16b2, 0x0c7f, 0x0c7e, 0x609c, 0x2060,
+ 0x1078, 0x1996, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009,
+ 0x000c, 0x6008, 0xa085, 0x0200, 0x600a, 0x1078, 0x1907, 0x1078,
+ 0x192b, 0x0078, 0x172c, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078,
+ 0x1996, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009, 0x000c,
+ 0x6007, 0x0103, 0x601b, 0x0003, 0x1078, 0x1907, 0x1078, 0x192b,
+ 0x0078, 0x172c, 0x0c7f, 0x74c4, 0x73c8, 0x72cc, 0x6014, 0x2091,
+ 0x8000, 0x7817, 0x0012, 0x0e7e, 0x2071, 0x5040, 0x706f, 0x0005,
+ 0x7073, 0x0000, 0x7376, 0x727a, 0x747e, 0x7082, 0x7087, 0x0000,
+ 0x2c00, 0x708a, 0x708f, 0x0000, 0xa02e, 0x2530, 0x611c, 0x61a2,
+ 0xa184, 0x0060, 0x0040, 0x171e, 0x1078, 0x467f, 0x0e7f, 0x6596,
+ 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x1078,
+ 0x21b1, 0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1287,
+ 0x20a9, 0x0005, 0x2099, 0x5018, 0x2091, 0x8000, 0x530a, 0x2091,
+ 0x8001, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
+ 0x0000, 0x007c, 0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x1284,
+ 0x71c4, 0x71c6, 0x2168, 0x0078, 0x174f, 0x2069, 0x1000, 0x690c,
+ 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1751, 0xa285,
+ 0x0000, 0x00c0, 0x175f, 0x70c3, 0x4000, 0x0078, 0x1761, 0x70c3,
+ 0x4003, 0x70ca, 0x0078, 0x1287, 0x2011, 0x5067, 0x220c, 0x70c4,
+ 0x8003, 0x0048, 0x1771, 0x1078, 0x3b49, 0xa184, 0x7fff, 0x0078,
+ 0x1775, 0x1078, 0x3b3c, 0xa185, 0x8000, 0x2012, 0x0078, 0x1283,
+ 0x71c4, 0x1078, 0x3b33, 0x6100, 0x2001, 0x5067, 0x2004, 0xa084,
+ 0x8000, 0xa10d, 0x6204, 0x6308, 0x0078, 0x1281, 0x79e4, 0x0078,
+ 0x1283, 0x71c4, 0x71c6, 0x2198, 0x20a1, 0x0042, 0x20a9, 0x0004,
+ 0x53a3, 0x21a0, 0x2099, 0x0042, 0x20a9, 0x0004, 0x53a3, 0x0078,
+ 0x1284, 0x70c4, 0x2068, 0x2079, 0x5000, 0x2091, 0x8000, 0x1078,
+ 0x1911, 0x2091, 0x8001, 0x0040, 0x1825, 0x6007, 0x0001, 0x600b,
+ 0x0000, 0x602b, 0x0000, 0x601b, 0x0006, 0x6a10, 0xa28c, 0x000f,
+ 0xa284, 0x00f0, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x6016,
+ 0xa284, 0x0800, 0x0040, 0x17c0, 0x601b, 0x000a, 0x0078, 0x17c6,
+ 0xa284, 0x1000, 0x0040, 0x17c6, 0x601b, 0x000c, 0xa284, 0x0300,
+ 0x0040, 0x17cf, 0x602b, 0x0001, 0x8004, 0x8004, 0x8004, 0xa085,
+ 0x0001, 0x601e, 0x6023, 0x0000, 0x6027, 0x0000, 0xa284, 0x0400,
+ 0x0040, 0x17dc, 0x602b, 0x0000, 0x20a9, 0x0006, 0xac80, 0x000b,
+ 0x20a0, 0xad80, 0x0005, 0x2098, 0x53a3, 0xa284, 0x0300, 0x00c0,
+ 0x17f1, 0x6046, 0x604a, 0x604e, 0x6052, 0x6096, 0x609a, 0x0078,
+ 0x17fb, 0x6800, 0x6046, 0x6804, 0x604a, 0x6e08, 0x664e, 0x6d0c,
+ 0x6552, 0x6596, 0x669a, 0x6014, 0x2091, 0x8000, 0x7817, 0x0042,
+ 0x2c08, 0x2061, 0x5040, 0x606f, 0x0005, 0x6073, 0x0000, 0x6077,
+ 0x0000, 0x607b, 0x0000, 0x607f, 0x0000, 0x6082, 0x618a, 0xa284,
+ 0x0400, 0x608e, 0x2091, 0x8001, 0x0e7e, 0x2071, 0x0020, 0x7007,
+ 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x0e7f, 0x2091, 0x8000,
+ 0x1078, 0x21b1, 0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078,
+ 0x1287, 0x0c7e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2091, 0x8000, 0x2071,
+ 0x5040, 0x2079, 0x0100, 0x2061, 0x0010, 0x70a0, 0xa06d, 0x0040,
+ 0x18aa, 0x6a04, 0xa294, 0x00ff, 0xa286, 0x0007, 0x0040, 0x1844,
+ 0xa286, 0x000f, 0x00c0, 0x18aa, 0x691c, 0xa184, 0x0080, 0x00c0,
+ 0x18aa, 0x6824, 0xa18c, 0xff00, 0xa085, 0x0019, 0x6826, 0x71b0,
+ 0x81ff, 0x0040, 0x1865, 0x0d7e, 0x2069, 0x0020, 0x6908, 0x6808,
+ 0xa106, 0x00c0, 0x1856, 0x690c, 0x680c, 0xa106, 0x00c0, 0x185b,
+ 0xa184, 0x00ff, 0x00c0, 0x185b, 0x0d7f, 0x78b8, 0xa084, 0x801f,
+ 0x00c0, 0x1865, 0x7848, 0xa085, 0x000c, 0x784a, 0x71b0, 0x81ff,
+ 0x0040, 0x1888, 0x70b3, 0x0000, 0x0d7e, 0x2069, 0x0020, 0x6807,
+ 0x0008, 0x6804, 0xa084, 0x0008, 0x00c0, 0x1879, 0x6807, 0x0008,
+ 0x6804, 0xa084, 0x0008, 0x00c0, 0x1880, 0x6807, 0x0002, 0x0d7f,
+ 0x61c4, 0x62c8, 0x63cc, 0x61c6, 0x62ca, 0x63ce, 0x0e7e, 0x2071,
+ 0x5000, 0x7266, 0x736a, 0xae80, 0x0019, 0x0e7f, 0x1078, 0x4598,
+ 0x78a3, 0x0000, 0x7858, 0xa084, 0xedff, 0x785a, 0x70b4, 0xa080,
+ 0x00da, 0x781a, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091, 0x8001,
+ 0x0078, 0x1284, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091, 0x8001,
+ 0x2001, 0x4005, 0x0078, 0x1286, 0x7980, 0x71c6, 0x71c4, 0xa182,
+ 0x0003, 0x00c8, 0x127c, 0x7982, 0x0078, 0x1284, 0x7980, 0x71c6,
+ 0x0078, 0x1284, 0x7974, 0x71c6, 0x71c4, 0x7976, 0x7978, 0x71ca,
+ 0x71c8, 0x797a, 0x797c, 0x71ce, 0x71cc, 0x797e, 0x0078, 0x1284,
+ 0x7974, 0x71c6, 0x7978, 0x71ca, 0x797c, 0x71ce, 0x0078, 0x1284,
+ 0x7900, 0x71c6, 0x71c4, 0x7902, 0x2001, 0x04fd, 0x2004, 0xa082,
+ 0x0005, 0x0048, 0x18e7, 0x0038, 0x18e9, 0x0078, 0x18f3, 0x00a8,
+ 0x18f3, 0xa18c, 0x0001, 0x00c0, 0x18f1, 0x20b9, 0x2222, 0x0078,
+ 0x18f3, 0x20b9, 0x1212, 0x0078, 0x1284, 0x7900, 0x71c6, 0x0078,
+ 0x1284, 0x2009, 0x5074, 0x2104, 0x70c6, 0x70c4, 0x200a, 0x0078,
+ 0x1284, 0x2009, 0x5074, 0x2104, 0x70c6, 0x0078, 0x1284, 0xac80,
+ 0x0001, 0x1078, 0x1af2, 0x007c, 0xac80, 0x0001, 0x1078, 0x1a92,
+ 0x007c, 0x7850, 0xa065, 0x0040, 0x1919, 0x2c04, 0x7852, 0x2063,
+ 0x0000, 0x007c, 0x0f7e, 0x2079, 0x5000, 0x7850, 0xa06d, 0x0040,
+ 0x1929, 0x2d04, 0x7852, 0x6803, 0x0000, 0x6807, 0x0000, 0x680b,
+ 0x0000, 0x0f7f, 0x007c, 0x2091, 0x8000, 0x0f7e, 0x2079, 0x5000,
+ 0x7850, 0x2062, 0x2c00, 0xa005, 0x00c0, 0x1938, 0x1078, 0x23ca,
+ 0x7852, 0x0f7f, 0x2091, 0x8001, 0x007c, 0x0f7e, 0x2079, 0x5000,
+ 0x7850, 0x206a, 0x2d00, 0x7852, 0x0f7f, 0x007c, 0x2011, 0x7700,
+ 0x7a52, 0x7bec, 0x8319, 0x0040, 0x1953, 0xa280, 0x0031, 0x2012,
+ 0x2010, 0x0078, 0x194a, 0x2013, 0x0000, 0x007c, 0xa784, 0x0f00,
+ 0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105,
+ 0xa0e8, 0x5300, 0x007c, 0x1078, 0x1956, 0x2900, 0x682a, 0x2a00,
+ 0x682e, 0x6808, 0xa084, 0xffef, 0xa80d, 0x690a, 0x2009, 0x5052,
+ 0x210c, 0x6804, 0xa005, 0x0040, 0x1995, 0xa116, 0x00c0, 0x1980,
+ 0x2060, 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x1983,
+ 0x2009, 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1992, 0x6000,
+ 0x6806, 0x1078, 0x19a3, 0x1078, 0x1c42, 0x6810, 0x8001, 0x6812,
+ 0x00c0, 0x1983, 0x017f, 0x6902, 0x6906, 0x007c, 0xa065, 0x0040,
+ 0x19a2, 0x609c, 0x609f, 0x0000, 0x2008, 0x1078, 0x192b, 0x2100,
+ 0x0078, 0x1996, 0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9,
+ 0x001c, 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828,
+ 0x601a, 0x682c, 0x6022, 0x007c, 0x0e7e, 0x2071, 0x5040, 0x704c,
+ 0xa08c, 0x0200, 0x00c0, 0x19c2, 0xa088, 0x5080, 0x2d0a, 0x8000,
+ 0x704e, 0xa006, 0x0e7f, 0x007c, 0x1078, 0x1956, 0x2091, 0x8000,
+ 0x6804, 0x781e, 0xa065, 0x0040, 0x1a0d, 0x0078, 0x19d5, 0x2c00,
+ 0x781e, 0x6000, 0xa065, 0x0040, 0x1a0d, 0x600c, 0xa306, 0x00c0,
+ 0x19cf, 0x6010, 0xa206, 0x00c0, 0x19cf, 0x2c28, 0x2001, 0x5052,
+ 0x2004, 0xac06, 0x00c0, 0x19e6, 0x0078, 0x1a0b, 0x6804, 0xac06,
+ 0x00c0, 0x19f3, 0x6000, 0xa065, 0x6806, 0x00c0, 0x19fd, 0x6803,
+ 0x0000, 0x0078, 0x19fd, 0x6400, 0x781c, 0x2060, 0x6402, 0xa486,
+ 0x0000, 0x00c0, 0x19fd, 0x2c00, 0x6802, 0x2560, 0x1078, 0x19a3,
+ 0x601b, 0x0005, 0x6023, 0x0020, 0x1078, 0x1c42, 0x6810, 0x8001,
+ 0x1050, 0x23ca, 0x6812, 0xa085, 0xffff, 0x007c, 0x2039, 0x0000,
+ 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x2091, 0x8000,
+ 0x1078, 0x1963, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1a18, 0xa7bc,
+ 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1a18,
+ 0x2091, 0x8001, 0x007c, 0x2061, 0x0000, 0x6018, 0xa084, 0x0001,
+ 0x00c0, 0x1a3c, 0x2091, 0x8000, 0x78e0, 0x78e3, 0x0000, 0x2091,
+ 0x8001, 0xa005, 0x00c0, 0x1a3d, 0x007c, 0xa08c, 0xfff0, 0x0040,
+ 0x1a43, 0x1078, 0x23ca, 0x0079, 0x1a45, 0x1a55, 0x1a58, 0x1a5e,
+ 0x1a62, 0x1a56, 0x1a66, 0x1a6c, 0x1a56, 0x1a56, 0x1c0c, 0x1c30,
+ 0x1c34, 0x1a56, 0x1a56, 0x1a56, 0x1a56, 0x007c, 0x1078, 0x23ca,
+ 0x1078, 0x1a0e, 0x2001, 0x8001, 0x0078, 0x1c3a, 0x2001, 0x8003,
+ 0x0078, 0x1c3a, 0x2001, 0x8004, 0x0078, 0x1c3a, 0x1078, 0x1a0e,
+ 0x2001, 0x8006, 0x0078, 0x1c3a, 0x2001, 0x8007, 0x0078, 0x1c3a,
+ 0x2030, 0x2138, 0xa782, 0x0021, 0x0048, 0x1a78, 0x2009, 0x0020,
+ 0x2600, 0x1078, 0x1a92, 0x00c0, 0x1a91, 0xa7ba, 0x0020, 0x0048,
+ 0x1a90, 0x0040, 0x1a90, 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040,
+ 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1a72,
+ 0xa006, 0x007c, 0x81ff, 0x0040, 0x1acd, 0x2099, 0x0030, 0x20a0,
+ 0x700c, 0xa084, 0x00ff, 0x0040, 0x1aa4, 0x7007, 0x0004, 0x7004,
+ 0xa084, 0x0004, 0x00c0, 0x1a9f, 0x21a8, 0x7017, 0x0000, 0x810b,
+ 0x7112, 0x721a, 0x731e, 0x7422, 0x7526, 0x780c, 0xa085, 0x0001,
+ 0x7002, 0x7007, 0x0001, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
+ 0x00c8, 0x1ac1, 0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0,
+ 0x1ab3, 0x7008, 0x800b, 0x00c8, 0x1ab3, 0x7007, 0x0002, 0xa08c,
+ 0x01e0, 0x00c0, 0x1acd, 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c,
+ 0x2030, 0x2138, 0xa782, 0x0021, 0x0048, 0x1ad8, 0x2009, 0x0020,
+ 0x2600, 0x1078, 0x1af2, 0x00c0, 0x1af1, 0xa7ba, 0x0020, 0x0048,
+ 0x1af0, 0x0040, 0x1af0, 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040,
+ 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1ad2,
+ 0xa006, 0x007c, 0x81ff, 0x0040, 0x1b33, 0x2098, 0x20a1, 0x0030,
+ 0x700c, 0xa084, 0x00ff, 0x0040, 0x1b04, 0x7007, 0x0004, 0x7004,
+ 0xa084, 0x0004, 0x00c0, 0x1aff, 0x21a8, 0x7017, 0x0000, 0x810b,
+ 0x7112, 0x721a, 0x731e, 0x7422, 0x7526, 0x780c, 0xa085, 0x0000,
+ 0x7002, 0x53a6, 0x7007, 0x0001, 0x2001, 0x04fd, 0x2004, 0xa082,
+ 0x0005, 0x00c8, 0x1b22, 0x2009, 0x0022, 0x2104, 0xa084, 0x4000,
+ 0x00c0, 0x1b14, 0x7010, 0xa084, 0xf000, 0x0040, 0x1b2b, 0x7007,
+ 0x0008, 0x0078, 0x1b2f, 0x7108, 0x8103, 0x00c8, 0x1b14, 0x7007,
+ 0x0002, 0xa184, 0x01e0, 0x7003, 0x0000, 0x007c, 0x2001, 0x04fd,
+ 0x2004, 0xa082, 0x0004, 0x00c8, 0x1b3f, 0x0078, 0x1b42, 0xa006,
+ 0x0078, 0x1b44, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x2071, 0x5000,
+ 0x2d08, 0x7058, 0x6802, 0xa005, 0x00c0, 0x1b4f, 0x715e, 0x715a,
+ 0x0e7f, 0x007c, 0x2c08, 0x7858, 0x6002, 0xa005, 0x00c0, 0x1b59,
+ 0x795e, 0x795a, 0x007c, 0x2091, 0x8000, 0x6003, 0x0000, 0x2c08,
+ 0x785c, 0xa065, 0x00c0, 0x1b67, 0x795a, 0x0078, 0x1b68, 0x6102,
+ 0x795e, 0x2091, 0x8001, 0x1078, 0x21ce, 0x007c, 0x0e7e, 0x2071,
+ 0x5000, 0x7058, 0xa06d, 0x0040, 0x1b7c, 0x6800, 0x705a, 0xa005,
+ 0x00c0, 0x1b7b, 0x705e, 0x8dff, 0x0e7f, 0x007c, 0x0d7e, 0x0c7e,
+ 0x0f7e, 0x2079, 0x5000, 0xaf80, 0x0016, 0x2060, 0x6000, 0xa005,
+ 0x0040, 0x1bac, 0x2068, 0x6814, 0xa306, 0x00c0, 0x1b95, 0x6828,
+ 0xa084, 0x00ff, 0xa406, 0x0040, 0x1b98, 0x2d60, 0x0078, 0x1b86,
+ 0x6800, 0xa005, 0x6002, 0x00c0, 0x1ba4, 0xaf80, 0x0016, 0xac06,
+ 0x0040, 0x1ba3, 0x2c00, 0x785e, 0x0d7e, 0x689c, 0xa005, 0x0040,
+ 0x1bab, 0x1078, 0x1996, 0x007f, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005,
+ 0x007c, 0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5000, 0xaf80, 0x0016,
+ 0x2060, 0x6000, 0xa005, 0x0040, 0x1bdb, 0x2068, 0x6814, 0xa084,
+ 0x00ff, 0xa306, 0x0040, 0x1bc7, 0x2d60, 0x0078, 0x1bb9, 0x6800,
+ 0xa005, 0x6002, 0x00c0, 0x1bd3, 0xaf80, 0x0016, 0xac06, 0x0040,
+ 0x1bd2, 0x2c00, 0x785e, 0x0d7e, 0x689c, 0xa005, 0x0040, 0x1bda,
+ 0x1078, 0x1996, 0x007f, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c,
+ 0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5000, 0xaf80, 0x0016, 0x2060,
+ 0x6000, 0xa06d, 0x0040, 0x1c07, 0x6814, 0xa306, 0x0040, 0x1bf3,
+ 0x2d60, 0x0078, 0x1be8, 0x6800, 0xa005, 0x6002, 0x00c0, 0x1bff,
+ 0xaf80, 0x0016, 0xac06, 0x0040, 0x1bfe, 0x2c00, 0x785e, 0x0d7e,
+ 0x689c, 0xa005, 0x0040, 0x1c06, 0x1078, 0x1996, 0x007f, 0x0f7f,
+ 0x0c7f, 0x0d7f, 0xa005, 0x007c, 0x2091, 0x8000, 0x2069, 0x5040,
+ 0x6800, 0xa086, 0x0000, 0x0040, 0x1c1a, 0x2091, 0x8001, 0x78e3,
+ 0x0009, 0x007c, 0x6880, 0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049,
+ 0x0004, 0x2051, 0x0010, 0x1078, 0x1963, 0x8738, 0xa784, 0x001f,
+ 0x00c0, 0x1c23, 0x2091, 0x8001, 0x2001, 0x800a, 0x0078, 0x1c3a,
+ 0x2001, 0x800c, 0x0078, 0x1c3a, 0x1078, 0x1a0e, 0x2001, 0x800d,
+ 0x0078, 0x1c3a, 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091,
+ 0x4080, 0x007c, 0x6004, 0x2c08, 0x2063, 0x0000, 0x7884, 0x8000,
+ 0x7886, 0x7888, 0xa005, 0x798a, 0x0040, 0x1c51, 0x2c02, 0x0078,
+ 0x1c52, 0x798e, 0x007c, 0x6807, 0x0103, 0x0c7e, 0x2061, 0x5000,
+ 0x2d08, 0x206b, 0x0000, 0x6084, 0x8000, 0x6086, 0x6088, 0xa005,
+ 0x618a, 0x0040, 0x1c66, 0x2d02, 0x0078, 0x1c67, 0x618e, 0x0c7f,
+ 0x007c, 0x1078, 0x1c7a, 0x0040, 0x1c79, 0x0c7e, 0x609c, 0xa065,
+ 0x0040, 0x1c74, 0x1078, 0x1996, 0x0c7f, 0x609f, 0x0000, 0x1078,
+ 0x192b, 0x007c, 0x788c, 0xa065, 0x0040, 0x1c8c, 0x2091, 0x8000,
+ 0x7884, 0x8001, 0x7886, 0x2c04, 0x788e, 0xa005, 0x00c0, 0x1c8a,
+ 0x788a, 0x8000, 0x2091, 0x8001, 0x007c, 0x20a9, 0x0010, 0xa006,
+ 0x8004, 0x8086, 0x818e, 0x00c8, 0x1c96, 0xa200, 0x0070, 0x1c9a,
+ 0x0078, 0x1c91, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9, 0x0010,
+ 0xa005, 0x0040, 0x1cc0, 0xa11a, 0x00c8, 0x1cc0, 0x8213, 0x818d,
+ 0x0048, 0x1cb1, 0xa11a, 0x00c8, 0x1cb2, 0x0070, 0x1cb8, 0x0078,
+ 0x1ca6, 0xa11a, 0x2308, 0x8210, 0x0070, 0x1cb8, 0x0078, 0x1ca6,
+ 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c,
+ 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x1cbc, 0x7994, 0x70d0,
+ 0xa106, 0x0040, 0x1d34, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004,
+ 0xa005, 0x00c0, 0x1d34, 0x7008, 0x7208, 0xa206, 0x00c0, 0x1d34,
+ 0xa286, 0x0008, 0x00c0, 0x1d34, 0x2071, 0x0010, 0x1078, 0x1911,
+ 0x0040, 0x1d34, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, 0xa184, 0xff00,
+ 0x0040, 0x1d02, 0x2031, 0x0000, 0x810b, 0x86b5, 0x810b, 0x86b5,
+ 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5,
+ 0x2100, 0xa210, 0x2600, 0xa319, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
+ 0x0078, 0x1d0c, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399, 0x0000,
+ 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x2009, 0x0020, 0x1078, 0x190c,
+ 0x2091, 0x8001, 0x0040, 0x1d2b, 0x1078, 0x192b, 0x78a8, 0x8000,
+ 0x78aa, 0xa086, 0x0002, 0x00c0, 0x1d34, 0x2091, 0x8000, 0x78e3,
+ 0x0002, 0x78ab, 0x0000, 0x78cc, 0xa085, 0x0003, 0x78ce, 0x2091,
+ 0x8001, 0x0078, 0x1d34, 0x78ab, 0x0000, 0x1078, 0x208b, 0x6004,
+ 0xa084, 0x000f, 0x0079, 0x1d39, 0x2071, 0x0010, 0x2091, 0x8001,
+ 0x007c, 0x1d49, 0x1d6b, 0x1d91, 0x1d49, 0x1dae, 0x1d58, 0x1f0d,
+ 0x1f28, 0x1d49, 0x1d65, 0x1d8b, 0x1df6, 0x1e63, 0x1eb3, 0x1ec5,
+ 0x1f24, 0x2039, 0x0400, 0x78dc, 0xa705, 0x78de, 0x6008, 0xa705,
+ 0x600a, 0x1078, 0x1fa6, 0x609c, 0x78da, 0x1078, 0x2073, 0x007c,
+ 0x78dc, 0xa084, 0x0100, 0x0040, 0x1d5f, 0x0078, 0x1d49, 0x601c,
+ 0xa085, 0x0080, 0x601e, 0x0078, 0x1d72, 0x1078, 0x1b36, 0x00c0,
+ 0x1d49, 0x1078, 0x20a5, 0x78dc, 0xa084, 0x0100, 0x0040, 0x1d72,
+ 0x0078, 0x1d49, 0x78df, 0x0000, 0x6004, 0x8007, 0xa084, 0x00ff,
+ 0x78d2, 0x8001, 0x609f, 0x0000, 0x0040, 0x1d88, 0x1078, 0x1fa6,
+ 0x0040, 0x1d88, 0x78dc, 0xa085, 0x0100, 0x78de, 0x0078, 0x1d8a,
+ 0x1078, 0x1fca, 0x007c, 0x1078, 0x1b36, 0x00c0, 0x1d49, 0x1078,
+ 0x20a1, 0x78dc, 0xa08c, 0x0e00, 0x00c0, 0x1d9a, 0xa084, 0x0100,
+ 0x00c0, 0x1d9c, 0x0078, 0x1d49, 0x1078, 0x1fa6, 0x00c0, 0x1dad,
+ 0x6104, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x1f63, 0xa186,
+ 0x000f, 0x0040, 0x1f63, 0x1078, 0x1fca, 0x007c, 0x78dc, 0xa084,
+ 0x0100, 0x0040, 0x1db5, 0x0078, 0x1d49, 0x78df, 0x0000, 0x6714,
+ 0x2011, 0x0001, 0x20a9, 0x0001, 0x6018, 0xa084, 0x00ff, 0xa005,
+ 0x0040, 0x1dd8, 0x2011, 0x0001, 0xa7bc, 0xff00, 0x20a9, 0x0020,
+ 0xa08e, 0x0001, 0x0040, 0x1dd8, 0x2039, 0x0000, 0x2011, 0x0002,
+ 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0040, 0x1dd8, 0x0078, 0x1df3,
+ 0x1078, 0x1956, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000,
+ 0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091, 0x8001,
+ 0x0070, 0x1dec, 0x0078, 0x1dda, 0x8211, 0x0040, 0x1df3, 0x20a9,
+ 0x0100, 0x0078, 0x1dda, 0x1078, 0x192b, 0x007c, 0x2001, 0x5067,
+ 0x2004, 0xa084, 0x8000, 0x0040, 0x1f8b, 0x6114, 0x1078, 0x20c2,
+ 0x6900, 0xa184, 0x0001, 0x0040, 0x1e17, 0x6028, 0xa084, 0x00ff,
+ 0x00c0, 0x1f83, 0x6800, 0xa084, 0x0001, 0x0040, 0x1f8b, 0x6803,
+ 0x0000, 0x680b, 0x0000, 0x6807, 0x0000, 0x0078, 0x1f93, 0x2011,
+ 0x0001, 0x6020, 0xa084, 0x4000, 0x0040, 0x1e20, 0xa295, 0x0002,
+ 0x6020, 0xa084, 0x0100, 0x0040, 0x1e27, 0xa295, 0x0008, 0x601c,
+ 0xa084, 0x0002, 0x0040, 0x1e2e, 0xa295, 0x0004, 0x602c, 0xa08c,
+ 0x00ff, 0xa182, 0x0002, 0x0048, 0x1f8f, 0xa182, 0x001b, 0x00c8,
+ 0x1f8f, 0x0040, 0x1f8f, 0x690e, 0x602c, 0x8007, 0xa08c, 0x00ff,
+ 0xa182, 0x0002, 0x0048, 0x1f8f, 0xa182, 0x001b, 0x00c8, 0x1f8f,
+ 0x0040, 0x1f8f, 0x6912, 0x6030, 0xa005, 0x00c0, 0x1e51, 0x2001,
+ 0x001e, 0x8000, 0x6816, 0x6028, 0xa084, 0x00ff, 0x0040, 0x1f8b,
+ 0x6806, 0x6028, 0x8007, 0xa084, 0x00ff, 0x0040, 0x1f8b, 0x680a,
+ 0x6a02, 0x0078, 0x1f93, 0x2001, 0x5067, 0x2004, 0xa084, 0x8000,
+ 0x0040, 0x1f8b, 0x6114, 0x1078, 0x20c2, 0x2091, 0x8000, 0x6a04,
+ 0x6b08, 0x6418, 0xa484, 0x0003, 0x0040, 0x1e89, 0x6128, 0xa18c,
+ 0x00ff, 0x8001, 0x00c0, 0x1e82, 0x2100, 0xa210, 0x0048, 0x1eaf,
+ 0x0078, 0x1e89, 0x8001, 0x00c0, 0x1eaf, 0x2100, 0xa212, 0x0048,
+ 0x1eaf, 0xa484, 0x000c, 0x0040, 0x1ea3, 0x6128, 0x810f, 0xa18c,
+ 0x00ff, 0xa082, 0x0004, 0x00c0, 0x1e9b, 0x2100, 0xa318, 0x0048,
+ 0x1eaf, 0x0078, 0x1ea3, 0xa082, 0x0004, 0x00c0, 0x1eaf, 0x2100,
+ 0xa31a, 0x0048, 0x1eaf, 0x6030, 0xa005, 0x0040, 0x1ea9, 0x8000,
+ 0x6816, 0x6a06, 0x6b0a, 0x2091, 0x8001, 0x0078, 0x1f93, 0x2091,
+ 0x8001, 0x0078, 0x1f8f, 0x6114, 0x1078, 0x20c2, 0x2091, 0x8000,
+ 0x6b08, 0x8318, 0x0048, 0x1ec1, 0x6b0a, 0x2091, 0x8001, 0x0078,
+ 0x1fa2, 0x2091, 0x8001, 0x0078, 0x1f8f, 0x6024, 0x8007, 0xa084,
+ 0x00ff, 0x0040, 0x1ee3, 0xa086, 0x0080, 0x00c0, 0x1f0b, 0x20a9,
+ 0x0008, 0x2069, 0x7410, 0x2091, 0x8000, 0x6800, 0xa084, 0xfcff,
+ 0x6802, 0xade8, 0x0008, 0x0070, 0x1edf, 0x0078, 0x1ed5, 0x2091,
+ 0x8001, 0x0078, 0x1f93, 0x6028, 0xa015, 0x0040, 0x1f0b, 0x6114,
+ 0x1078, 0x20c2, 0x0d7e, 0xade8, 0x0007, 0x2091, 0x8000, 0x6800,
+ 0xa00d, 0x0040, 0x1f08, 0xa206, 0x0040, 0x1ef9, 0x2168, 0x0078,
+ 0x1eef, 0x0c7e, 0x2160, 0x6000, 0x6802, 0x1078, 0x192b, 0x0c7f,
+ 0x0d7f, 0x6808, 0x8000, 0x680a, 0x2091, 0x8001, 0x0078, 0x1fa2,
+ 0x2091, 0x8001, 0x0d7f, 0x0078, 0x1f8b, 0x6114, 0x1078, 0x20c2,
+ 0x6800, 0xa084, 0x0001, 0x0040, 0x1f7b, 0x2091, 0x8000, 0x6a04,
+ 0x8210, 0x0048, 0x1f20, 0x6a06, 0x2091, 0x8001, 0x0078, 0x1fa2,
+ 0x2091, 0x8001, 0x0078, 0x1f8f, 0x1078, 0x1b36, 0x00c0, 0x1d49,
+ 0x6114, 0x1078, 0x20c2, 0x60be, 0x6900, 0xa184, 0x0008, 0x0040,
+ 0x1f35, 0x6020, 0xa085, 0x0100, 0x6022, 0xa184, 0x0001, 0x0040,
+ 0x1f8b, 0xa184, 0x0100, 0x00c0, 0x1f77, 0xa184, 0x0200, 0x00c0,
+ 0x1f73, 0x681c, 0xa005, 0x00c0, 0x1f7f, 0x6004, 0xa084, 0x00ff,
+ 0xa086, 0x000f, 0x00c0, 0x1f4e, 0x1078, 0x20a5, 0x78df, 0x0000,
+ 0x6004, 0x8007, 0xa084, 0x00ff, 0x78d2, 0x8001, 0x609f, 0x0000,
+ 0x0040, 0x1f63, 0x1078, 0x1fa6, 0x0040, 0x1f63, 0x78dc, 0xa085,
+ 0x0100, 0x78de, 0x007c, 0x78d7, 0x0000, 0x78db, 0x0000, 0x6024,
+ 0xa084, 0xff00, 0x6026, 0x1078, 0x39aa, 0x0040, 0x1cc6, 0x1078,
+ 0x1b5b, 0x0078, 0x1cc6, 0x2009, 0x0017, 0x0078, 0x1f95, 0x2009,
+ 0x000e, 0x0078, 0x1f95, 0x2009, 0x0007, 0x0078, 0x1f95, 0x2009,
+ 0x0035, 0x0078, 0x1f95, 0x2009, 0x003e, 0x0078, 0x1f95, 0x2009,
+ 0x0004, 0x0078, 0x1f95, 0x2009, 0x0006, 0x0078, 0x1f95, 0x2009,
+ 0x0016, 0x0078, 0x1f95, 0x2009, 0x0001, 0x6024, 0xa084, 0xff00,
+ 0xa105, 0x6026, 0x2091, 0x8000, 0x1078, 0x1c42, 0x2091, 0x8001,
+ 0x0078, 0x1cc6, 0x1078, 0x192b, 0x0078, 0x1cc6, 0x78d4, 0xa06d,
+ 0x00c0, 0x1fb1, 0x2c00, 0x78d6, 0x78da, 0x609f, 0x0000, 0x0078,
+ 0x1fbd, 0x2c00, 0x689e, 0x609f, 0x0000, 0x78d6, 0x2d00, 0x6002,
+ 0x78d8, 0xad06, 0x00c0, 0x1fbd, 0x6002, 0x78d0, 0x8001, 0x78d2,
+ 0x00c0, 0x1fc9, 0x78dc, 0xa084, 0xfeff, 0x78de, 0x78d8, 0x2060,
+ 0xa006, 0x007c, 0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184, 0xe1ff,
+ 0x601e, 0xa184, 0x0060, 0x0040, 0x1fd9, 0x0e7e, 0x1078, 0x467f,
+ 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3,
+ 0x0000, 0x6714, 0x1078, 0x1956, 0x2091, 0x8000, 0x60a0, 0xa084,
+ 0x8000, 0x00c0, 0x2000, 0x6808, 0xa084, 0x0001, 0x0040, 0x2000,
+ 0x2091, 0x8001, 0x1078, 0x19a3, 0x2091, 0x8000, 0x1078, 0x1c42,
+ 0x2091, 0x8001, 0x78d7, 0x0000, 0x78db, 0x0000, 0x0078, 0x2072,
+ 0x6024, 0xa096, 0x0001, 0x00c0, 0x2007, 0x8000, 0x6026, 0x6a10,
+ 0x6814, 0x2091, 0x8001, 0xa202, 0x0048, 0x2016, 0x0040, 0x2016,
+ 0x2039, 0x0200, 0x1078, 0x2073, 0x0078, 0x2072, 0x2c08, 0x2091,
+ 0x8000, 0x60a0, 0xa084, 0x8000, 0x0040, 0x2043, 0x6800, 0xa065,
+ 0x0040, 0x2048, 0x6a04, 0x0e7e, 0x2071, 0x5040, 0x7000, 0xa084,
+ 0x0001, 0x0040, 0x203d, 0x7048, 0xa206, 0x00c0, 0x203d, 0x6b04,
+ 0x231c, 0x2160, 0x6302, 0x2300, 0xa005, 0x00c0, 0x2038, 0x6902,
+ 0x2260, 0x6102, 0x0e7f, 0x0078, 0x204f, 0x2160, 0x6202, 0x6906,
+ 0x0e7f, 0x0078, 0x204f, 0x6800, 0xa065, 0x0040, 0x2048, 0x6102,
+ 0x6902, 0x00c0, 0x204c, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160,
+ 0x60a0, 0xa084, 0x8000, 0x0040, 0x2059, 0x6808, 0xa084, 0xfffc,
+ 0x680a, 0x6810, 0x8000, 0x6812, 0x2091, 0x8001, 0x6808, 0xa08c,
+ 0x0040, 0x0040, 0x2068, 0xa086, 0x0040, 0x680a, 0x1078, 0x19b4,
+ 0x2091, 0x8000, 0x1078, 0x21b1, 0x2091, 0x8001, 0x78db, 0x0000,
+ 0x78d7, 0x0000, 0x007c, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000,
+ 0x1078, 0x1c42, 0x2091, 0x8001, 0x78d8, 0xa065, 0x0040, 0x2086,
+ 0x609c, 0x78da, 0x609f, 0x0000, 0x0078, 0x2076, 0x78d7, 0x0000,
+ 0x78db, 0x0000, 0x007c, 0x7990, 0x7894, 0x8000, 0xa10a, 0x00c8,
+ 0x2092, 0xa006, 0x7896, 0x70d2, 0x7804, 0xa005, 0x0040, 0x20a0,
+ 0x8001, 0x7806, 0x00c0, 0x20a0, 0x0068, 0x20a0, 0x2091, 0x4080,
+ 0x007c, 0x2039, 0x20b9, 0x0078, 0x20a7, 0x2039, 0x20bf, 0x2704,
+ 0xa005, 0x0040, 0x20b8, 0xac00, 0x2068, 0x6b08, 0x6c0c, 0x6910,
+ 0x6a14, 0x690a, 0x6a0e, 0x6b12, 0x6c16, 0x8738, 0x0078, 0x20a7,
+ 0x007c, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015,
+ 0x001b, 0x0000, 0x0c7e, 0x1078, 0x3b33, 0x2c68, 0x0c7f, 0x007c,
+ 0x0010, 0x2139, 0x0068, 0x2139, 0x2029, 0x0000, 0x78cb, 0x0000,
+ 0x788c, 0xa065, 0x0040, 0x2132, 0x2009, 0x5074, 0x2104, 0xa084,
+ 0x0001, 0x0040, 0x2100, 0x6004, 0xa086, 0x0103, 0x00c0, 0x2100,
+ 0x6018, 0xa005, 0x00c0, 0x2100, 0x6014, 0xa005, 0x00c0, 0x2100,
+ 0x0d7e, 0x2069, 0x0000, 0x6818, 0xa084, 0x0001, 0x00c0, 0x20ff,
+ 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001,
+ 0x2091, 0x4080, 0x0d7f, 0x1078, 0x1c69, 0x0078, 0x2137, 0x0d7f,
+ 0x1078, 0x213a, 0x0040, 0x2132, 0x6204, 0xa294, 0x00ff, 0xa296,
+ 0x0003, 0x0040, 0x2112, 0x6204, 0xa296, 0x0110, 0x00c0, 0x2120,
+ 0x78cb, 0x0001, 0x6204, 0xa294, 0xff00, 0x8217, 0x8211, 0x0040,
+ 0x2120, 0x85ff, 0x00c0, 0x2132, 0x8210, 0xa202, 0x00c8, 0x2132,
+ 0x057e, 0x1078, 0x2149, 0x057f, 0x0040, 0x212d, 0x78e0, 0xa086,
+ 0x0003, 0x0040, 0x2132, 0x0078, 0x2120, 0x8528, 0x78c8, 0xa005,
+ 0x0040, 0x20d0, 0x85ff, 0x0040, 0x2139, 0x2091, 0x4080, 0x78b0,
+ 0x70d6, 0x007c, 0x7bac, 0x79b0, 0x70d4, 0xa102, 0x00c0, 0x2143,
+ 0x2300, 0xa005, 0x007c, 0x0048, 0x2147, 0xa302, 0x007c, 0x8002,
+ 0x007c, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x2163,
+ 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x2198,
+ 0x7008, 0x7208, 0xa206, 0x00c0, 0x2198, 0xa286, 0x0008, 0x00c0,
+ 0x2198, 0x2071, 0x0010, 0x1078, 0x219d, 0x2009, 0x0020, 0x6004,
+ 0xa086, 0x0103, 0x00c0, 0x2172, 0x6028, 0xa005, 0x00c0, 0x2172,
+ 0x2009, 0x000c, 0x1078, 0x1907, 0x0040, 0x218b, 0x78c4, 0x8000,
+ 0x78c6, 0xa086, 0x0002, 0x00c0, 0x2198, 0x2091, 0x8000, 0x78e3,
+ 0x0003, 0x78c7, 0x0000, 0x78cc, 0xa085, 0x0300, 0x78ce, 0x2091,
+ 0x8001, 0x0078, 0x2198, 0x78c7, 0x0000, 0x1078, 0x1c69, 0x79ac,
+ 0x78b0, 0x8000, 0xa10a, 0x00c8, 0x2196, 0xa006, 0x78b2, 0xa006,
+ 0x2071, 0x0010, 0x2091, 0x8001, 0x007c, 0x8107, 0x8004, 0x8004,
+ 0x7ab8, 0x7bb4, 0x7cc0, 0x7dbc, 0xa210, 0xa399, 0x0000, 0xa4a1,
+ 0x0000, 0xa5a9, 0x0000, 0x007c, 0x2009, 0x505b, 0x2091, 0x8000,
+ 0x200a, 0x0f7e, 0x0e7e, 0x2071, 0x5040, 0x7000, 0xa086, 0x0000,
+ 0x00c0, 0x21cb, 0x2009, 0x5012, 0x2104, 0xa005, 0x00c0, 0x21cb,
+ 0x2079, 0x0100, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x21cb, 0x0018,
+ 0x21cb, 0x781b, 0x004b, 0x0e7f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e,
+ 0x2071, 0x5040, 0x2091, 0x8000, 0x7000, 0xa086, 0x0000, 0x00c0,
+ 0x21e4, 0x2079, 0x0100, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x21e4,
+ 0x0018, 0x21e4, 0x781b, 0x004d, 0x2091, 0x8001, 0x0e7f, 0x0f7f,
+ 0x007c, 0x127e, 0x2091, 0x2300, 0x2071, 0x5040, 0x2079, 0x0100,
+ 0x784b, 0x000f, 0x0098, 0x21f7, 0x7838, 0x0078, 0x21f0, 0x20a9,
+ 0x0040, 0x7800, 0xa082, 0x0004, 0x0048, 0x2200, 0x20a9, 0x0060,
+ 0x789b, 0x0000, 0x78af, 0x0000, 0x78af, 0x0000, 0x0070, 0x220a,
+ 0x0078, 0x2202, 0x7800, 0xa082, 0x0004, 0x0048, 0x2219, 0x70b7,
+ 0x009b, 0x2019, 0x4da4, 0x1078, 0x2255, 0x702f, 0x8001, 0x0078,
+ 0x2225, 0x70b7, 0x0000, 0x2019, 0x4c1c, 0x1078, 0x2255, 0x2019,
+ 0x4c5b, 0x1078, 0x2255, 0x702f, 0x8000, 0x7003, 0x0000, 0x1078,
+ 0x235e, 0x7004, 0xa084, 0x000f, 0x017e, 0x2009, 0x04fd, 0x210c,
+ 0xa18a, 0x0005, 0x0048, 0x223a, 0x0038, 0x2240, 0xa085, 0x6280,
+ 0x0078, 0x2242, 0x0028, 0x2240, 0xa085, 0x6280, 0x0078, 0x2242,
+ 0xa085, 0x62c0, 0x017f, 0x7806, 0x780f, 0xb204, 0x7843, 0x00d8,
+ 0x7853, 0x0080, 0x780b, 0x0008, 0x7047, 0x0008, 0x7053, 0x507f,
+ 0x704f, 0x0000, 0x127f, 0x2000, 0x007c, 0x137e, 0x147e, 0x157e,
+ 0x047e, 0x20a1, 0x012b, 0x2304, 0xa005, 0x789a, 0x0040, 0x2275,
+ 0x8318, 0x2324, 0x8318, 0x2398, 0x24a8, 0xa484, 0xff00, 0x0040,
+ 0x226d, 0xa482, 0x0100, 0x20a9, 0x0100, 0x2020, 0x53a6, 0xa005,
+ 0x00c0, 0x2264, 0x3318, 0x0078, 0x225b, 0x047f, 0x157f, 0x147f,
+ 0x137f, 0x007c, 0xa18c, 0x000f, 0x2011, 0x0101, 0x2204, 0xa084,
+ 0xfff0, 0xa105, 0x2012, 0x1078, 0x235e, 0x007c, 0x2011, 0x0101,
+ 0x20a9, 0x0009, 0x810b, 0x0070, 0x228f, 0x0078, 0x228a, 0xa18c,
+ 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2009,
+ 0x0101, 0x20a9, 0x0005, 0x8213, 0x0070, 0x22a0, 0x0078, 0x229b,
+ 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x007c,
+ 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b, 0x0070, 0x22b1, 0x0078,
+ 0x22ac, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012,
+ 0x007c, 0x2011, 0x0102, 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012,
+ 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100,
+ 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080,
+ 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa084, 0xffdf,
+ 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e,
+ 0x2061, 0x0100, 0x609a, 0x60a4, 0xa085, 0x0020, 0x60ae, 0x0c7f,
+ 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100,
+ 0x609a, 0x60a4, 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x0c7f,
+ 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040,
+ 0x233c, 0x2061, 0x7400, 0x1078, 0x2344, 0x0040, 0x2328, 0x20a9,
+ 0x0000, 0x2061, 0x7300, 0x0c7e, 0x1078, 0x2344, 0x0040, 0x2318,
+ 0x0c7f, 0x8c60, 0x0070, 0x2316, 0x0078, 0x230b, 0x0078, 0x233c,
+ 0x007f, 0xa082, 0x7300, 0x2071, 0x5040, 0x7086, 0x7182, 0x2001,
+ 0x0004, 0x706e, 0x7093, 0x000f, 0x1078, 0x21ac, 0x0078, 0x2338,
+ 0x60c0, 0xa005, 0x00c0, 0x233c, 0x2071, 0x5040, 0x7182, 0x2c00,
+ 0x708a, 0x2001, 0x0006, 0x706e, 0x7093, 0x000f, 0x1078, 0x21ac,
+ 0x2001, 0x0000, 0x0078, 0x233e, 0x2001, 0x0001, 0x2091, 0x8001,
+ 0xa005, 0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005, 0x0040, 0x235b,
+ 0x2060, 0x600c, 0xa306, 0x00c0, 0x2358, 0x6010, 0xa206, 0x00c0,
+ 0x2358, 0x6014, 0xa106, 0x00c0, 0x2358, 0xa006, 0x0078, 0x235d,
+ 0x6000, 0x0078, 0x2345, 0xa085, 0x0001, 0x007c, 0x2011, 0x5041,
+ 0x220c, 0xa18c, 0x000f, 0x2011, 0x013b, 0x2204, 0xa084, 0x0100,
+ 0x0040, 0x2374, 0x2021, 0xff04, 0x2122, 0x810b, 0x810b, 0x810b,
+ 0x810b, 0xa18d, 0x0f00, 0x2104, 0x007c, 0x0e7e, 0x68e4, 0xa08c,
+ 0x0020, 0x0040, 0x23c8, 0xa084, 0x0006, 0x00c0, 0x23c8, 0x6014,
+ 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0f0, 0x5280,
+ 0x7004, 0xa084, 0x000a, 0x00c0, 0x23c8, 0x7108, 0xa194, 0xff00,
+ 0x0040, 0x23c8, 0xa18c, 0x00ff, 0x2001, 0x000c, 0xa106, 0x0040,
+ 0x23af, 0x2001, 0x0012, 0xa106, 0x0040, 0x23b3, 0x2001, 0x0014,
+ 0xa106, 0x0040, 0x23b7, 0x2001, 0x0019, 0xa106, 0x0040, 0x23bb,
+ 0x2001, 0x0032, 0xa106, 0x0040, 0x23bf, 0x0078, 0x23c3, 0x2009,
+ 0x0012, 0x0078, 0x23c5, 0x2009, 0x0014, 0x0078, 0x23c5, 0x2009,
+ 0x0019, 0x0078, 0x23c5, 0x2009, 0x0020, 0x0078, 0x23c5, 0x2009,
+ 0x003f, 0x0078, 0x23c5, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a,
+ 0x0e7f, 0x007c, 0x0068, 0x23ca, 0x2091, 0x8000, 0x2071, 0x0000,
+ 0x007e, 0x7018, 0xa084, 0x0001, 0x00c0, 0x23d1, 0x007f, 0x2071,
+ 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x073f,
+ 0x70df, 0x0000, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
+ 0x0078, 0x23e8, 0x107e, 0x007e, 0x127e, 0x2091, 0x2300, 0x7f3c,
+ 0x7e58, 0x7c30, 0x7d38, 0x77c2, 0x74c6, 0x76ca, 0x75ce, 0xa594,
+ 0x003f, 0xa49c, 0x0003, 0xa484, 0x000f, 0x0079, 0x23ff, 0x2411,
+ 0x2411, 0x2411, 0x274b, 0x3907, 0x240f, 0x2440, 0x244a, 0x240f,
+ 0x240f, 0x240f, 0x240f, 0x240f, 0x240f, 0x240f, 0x240f, 0x1078,
+ 0x23ca, 0x8507, 0xa084, 0x001f, 0x0079, 0x2416, 0x2454, 0x274b,
+ 0x2905, 0x2a02, 0x2a2a, 0x2cc3, 0x2f6e, 0x2fb1, 0x2ffc, 0x3081,
+ 0x3139, 0x31e2, 0x2440, 0x2827, 0x2f43, 0x2436, 0x3c78, 0x3c98,
+ 0x3e5e, 0x3e6a, 0x3f3f, 0x2436, 0x2436, 0x4012, 0x4016, 0x3c76,
+ 0x2436, 0x3dc9, 0x2436, 0x3b56, 0x244a, 0x2436, 0x1078, 0x23ca,
+ 0x0018, 0x23ef, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c,
+ 0x2019, 0x4cfd, 0x1078, 0x2255, 0x702f, 0x0001, 0x781b, 0x004f,
+ 0x0078, 0x2438, 0x2019, 0x4c5b, 0x1078, 0x2255, 0x702f, 0x8000,
+ 0x781b, 0x00d5, 0x0078, 0x2438, 0x7242, 0x2009, 0x500f, 0x200b,
+ 0x0000, 0xa584, 0x0001, 0x00c0, 0x3b6a, 0x0040, 0x2471, 0x1078,
+ 0x23ca, 0x7003, 0x0000, 0x704b, 0x0000, 0x7043, 0x0000, 0x7037,
+ 0x0000, 0x1078, 0x38de, 0x0018, 0x23ef, 0x2009, 0x500f, 0x200b,
+ 0x0000, 0x7068, 0xa005, 0x00c0, 0x253c, 0x706c, 0xa084, 0x0007,
+ 0x0079, 0x247a, 0x2573, 0x2482, 0x248e, 0x24ab, 0x24cd, 0x251a,
+ 0x24f3, 0x2482, 0x1078, 0x38c6, 0x2009, 0x0048, 0x1078, 0x2e0f,
+ 0x00c0, 0x248c, 0x7003, 0x0004, 0x0078, 0x2438, 0x1078, 0x38c6,
+ 0x00c0, 0x24a9, 0x7080, 0x8007, 0x7882, 0x789b, 0x0010, 0x78ab,
+ 0x000c, 0x789b, 0x0060, 0x78ab, 0x0001, 0x785b, 0x0004, 0x2009,
+ 0x00e5, 0x1078, 0x2e03, 0x00c0, 0x24a9, 0x7003, 0x0004, 0x7093,
+ 0x000f, 0x0078, 0x2438, 0x1078, 0x38c6, 0x00c0, 0x24cb, 0x7180,
+ 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f, 0xa18d, 0x00c0,
+ 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002, 0x785b,
+ 0x0004, 0x2009, 0x00e5, 0x1078, 0x2e03, 0x00c0, 0x24cb, 0x7003,
+ 0x0004, 0x7093, 0x000f, 0x0078, 0x2438, 0x1078, 0x38c6, 0x00c0,
+ 0x24f1, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f,
+ 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0020, 0x7184, 0x79aa, 0x78ab,
+ 0x000d, 0x789b, 0x0060, 0x78ab, 0x0004, 0x785b, 0x0004, 0x2009,
+ 0x00e5, 0x1078, 0x2e03, 0x00c0, 0x24f1, 0x7003, 0x0004, 0x7093,
+ 0x000f, 0x0078, 0x2438, 0x1078, 0x38c6, 0x00c0, 0x2518, 0x7180,
+ 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f, 0xa18d, 0x00c0,
+ 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002, 0x785b,
+ 0x0004, 0x2009, 0x00e5, 0x1078, 0x2e03, 0x00c0, 0x2518, 0x7088,
+ 0x708b, 0x0000, 0x2068, 0x704a, 0x7003, 0x0002, 0x7093, 0x000f,
+ 0x0078, 0x2438, 0x1078, 0x38c6, 0x00c0, 0x2438, 0x7088, 0x2068,
+ 0x6f14, 0x1078, 0x37bd, 0x2c50, 0x1078, 0x3978, 0x789b, 0x0010,
+ 0x6814, 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa, 0x6e1c, 0x2041,
+ 0x0001, 0x708c, 0xa084, 0x0400, 0x2001, 0x0004, 0x0040, 0x253a,
+ 0x2001, 0x0006, 0x0078, 0x265b, 0x1078, 0x38c6, 0x00c0, 0x2438,
+ 0x789b, 0x0010, 0x7068, 0x2068, 0x6f14, 0x1078, 0x37bd, 0x2c50,
+ 0x1078, 0x3978, 0x6008, 0xa085, 0x0010, 0x600a, 0x6824, 0xa005,
+ 0x0040, 0x255a, 0xa082, 0x0006, 0x0048, 0x2558, 0x0078, 0x255a,
+ 0x6827, 0x0005, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0x7058,
+ 0xa084, 0x8000, 0x0040, 0x2568, 0xa684, 0x0001, 0x0040, 0x256a,
+ 0xa39c, 0xffbf, 0x7baa, 0x2031, 0x0020, 0x2041, 0x0001, 0x2001,
+ 0x0003, 0x0078, 0x265b, 0x0018, 0x23ef, 0x744c, 0xa485, 0x0000,
+ 0x0040, 0x258d, 0xa080, 0x5080, 0x2030, 0x7150, 0x8108, 0xa12a,
+ 0x0048, 0x2584, 0x2009, 0x5080, 0x2164, 0x6504, 0x85ff, 0x00c0,
+ 0x259e, 0x8421, 0x00c0, 0x257e, 0x7152, 0x7003, 0x0000, 0x704b,
+ 0x0000, 0x7040, 0xa005, 0x0040, 0x3b6a, 0x0078, 0x2438, 0x764c,
+ 0xa6b0, 0x5080, 0x7150, 0x2600, 0x0078, 0x2589, 0x7152, 0x2568,
+ 0x2558, 0x754a, 0x2c50, 0x6034, 0xa085, 0x0000, 0x00c0, 0x259b,
+ 0x6708, 0x773a, 0xa784, 0x033f, 0x0040, 0x25d4, 0xa784, 0x0021,
+ 0x00c0, 0x259b, 0xa784, 0x0002, 0x0040, 0x25bd, 0xa784, 0x0004,
+ 0x0040, 0x259b, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0008, 0x00c0,
+ 0x259b, 0xa784, 0x0010, 0x00c0, 0x259b, 0xa784, 0x0200, 0x00c0,
+ 0x259b, 0xa784, 0x0100, 0x0040, 0x25d4, 0x6018, 0xa005, 0x00c0,
+ 0x259b, 0xa7bc, 0xfeff, 0x670a, 0x6823, 0x0000, 0x6e1c, 0xa684,
+ 0x000e, 0x6118, 0x0040, 0x25e4, 0x601c, 0xa102, 0x0048, 0x25e7,
+ 0x0040, 0x25e7, 0x0078, 0x2597, 0x81ff, 0x00c0, 0x2597, 0x68c3,
+ 0x0000, 0xa784, 0x0080, 0x00c0, 0x25ef, 0x700c, 0x6022, 0xa7bc,
+ 0xff7f, 0x670a, 0x1078, 0x3978, 0x0018, 0x23ef, 0x789b, 0x0010,
+ 0xa046, 0x1078, 0x38c6, 0x00c0, 0x2438, 0x6b14, 0xa39c, 0x001f,
+ 0xa39d, 0x00c0, 0x7058, 0xa084, 0x8000, 0x0040, 0x260b, 0xa684,
+ 0x0001, 0x0040, 0x260d, 0xa39c, 0xffbf, 0xa684, 0x0010, 0x0040,
+ 0x2613, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684, 0x000e, 0x00c0,
+ 0x261e, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x2659, 0x7158, 0xa18c,
+ 0x0800, 0x0040, 0x33d7, 0x2011, 0x0020, 0xa684, 0x0008, 0x00c0,
+ 0x262f, 0x8210, 0xa684, 0x0002, 0x00c0, 0x262f, 0x8210, 0x7aaa,
+ 0x8840, 0x1078, 0x38de, 0x6a14, 0x610c, 0x8108, 0xa18c, 0x00ff,
+ 0xa1e0, 0x7300, 0x2c64, 0x8cff, 0x0040, 0x2650, 0x6014, 0xa206,
+ 0x00c0, 0x263a, 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x2635, 0x0c7e,
+ 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078, 0x2573,
+ 0x1078, 0x38c6, 0x00c0, 0x2438, 0x2a60, 0x610e, 0x79aa, 0x8840,
+ 0x7132, 0x2001, 0x0001, 0x007e, 0x715c, 0xa184, 0x0018, 0x0040,
+ 0x2676, 0xa184, 0x0010, 0x0040, 0x2669, 0x1078, 0x35d6, 0x00c0,
+ 0x2699, 0xa184, 0x0008, 0x0040, 0x2676, 0x69a0, 0xa184, 0x0600,
+ 0x00c0, 0x2676, 0x1078, 0x34c7, 0x0078, 0x2699, 0x69a0, 0xa184,
+ 0x0800, 0x0040, 0x268d, 0x0c7e, 0x027e, 0x2960, 0x6000, 0xa085,
+ 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010, 0x6106, 0x027f, 0x0c7f,
+ 0x1078, 0x35d6, 0x00c0, 0x2699, 0x69a0, 0xa184, 0x0200, 0x0040,
+ 0x2695, 0x1078, 0x3516, 0x0078, 0x2699, 0xa184, 0x0400, 0x00c0,
+ 0x2672, 0x69a0, 0xa184, 0x1000, 0x0040, 0x26a4, 0x6914, 0xa18c,
+ 0xff00, 0x810f, 0x1078, 0x22cd, 0x007f, 0x7002, 0xa68c, 0x00e0,
+ 0xa684, 0x0060, 0x0040, 0x26b2, 0xa086, 0x0060, 0x00c0, 0x26b2,
+ 0xa18d, 0x4000, 0x88ff, 0x0040, 0x26b7, 0xa18d, 0x0004, 0x795a,
+ 0x69b6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b, 0x0061, 0x6818,
+ 0xa08d, 0x8000, 0xa084, 0x7fff, 0x691a, 0xa68c, 0x0080, 0x0040,
+ 0x26d6, 0x7097, 0x0000, 0xa08a, 0x000d, 0x0050, 0x26d4, 0xa08a,
+ 0x000c, 0x7196, 0x2001, 0x000c, 0x800c, 0x719a, 0x78aa, 0x8008,
+ 0x810c, 0x0040, 0x33dd, 0xa18c, 0x00f8, 0x00c0, 0x33dd, 0x157e,
+ 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000, 0x80ac,
+ 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6814,
+ 0x8007, 0x7882, 0x6d94, 0x7dd6, 0x7dde, 0x6e98, 0x7ed2, 0x7eda,
+ 0x1078, 0x38c6, 0x00c0, 0x270d, 0x702c, 0x8003, 0x0048, 0x2706,
+ 0x2019, 0x4c5b, 0x1078, 0x2255, 0x702f, 0x8000, 0x7830, 0xa084,
+ 0x00c0, 0x00c0, 0x270d, 0x0098, 0x2715, 0x6008, 0xa084, 0xffef,
+ 0x600a, 0x1078, 0x38de, 0x0078, 0x2461, 0x7200, 0xa284, 0x0007,
+ 0xa086, 0x0001, 0x00c0, 0x2722, 0x781b, 0x004f, 0x1078, 0x38de,
+ 0x0078, 0x2733, 0x6ab4, 0xa295, 0x2000, 0x7a5a, 0x781b, 0x004f,
+ 0x1078, 0x38de, 0x7200, 0x2500, 0xa605, 0x0040, 0x2733, 0xa284,
+ 0x0007, 0x1079, 0x2741, 0xad80, 0x0009, 0x7036, 0xa284, 0x0007,
+ 0xa086, 0x0001, 0x00c0, 0x2438, 0x6018, 0x8000, 0x601a, 0x0078,
+ 0x2438, 0x2749, 0x48f7, 0x48f7, 0x48e6, 0x48f7, 0x2749, 0x48e6,
+ 0x2749, 0x1078, 0x23ca, 0x1078, 0x38c6, 0x0f7e, 0x2079, 0x5000,
+ 0x78cc, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x276f, 0x706c, 0xa086,
+ 0x0001, 0x00c0, 0x275e, 0x706e, 0x0078, 0x2802, 0x706c, 0xa086,
+ 0x0005, 0x00c0, 0x276d, 0x7088, 0x2068, 0x681b, 0x0004, 0x6817,
+ 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x706f, 0x0000, 0x2011,
+ 0x0004, 0x716c, 0xa186, 0x0001, 0x0040, 0x2790, 0xa186, 0x0007,
+ 0x00c0, 0x2780, 0x2009, 0x5038, 0x200b, 0x0005, 0x0078, 0x2790,
+ 0x2009, 0x5013, 0x2104, 0x2009, 0x5012, 0x200a, 0x2009, 0x5038,
+ 0x200b, 0x0001, 0x706f, 0x0000, 0x7073, 0x0001, 0x0078, 0x2792,
+ 0x706f, 0x0000, 0x1078, 0x4633, 0x157e, 0x20a9, 0x0010, 0x2039,
+ 0x0000, 0x1078, 0x36b0, 0xa7b8, 0x0100, 0x0070, 0x27a1, 0x0078,
+ 0x2799, 0x157f, 0x7000, 0x0079, 0x27a5, 0x27d3, 0x27ba, 0x27ba,
+ 0x27ad, 0x27d3, 0x27d3, 0x27d3, 0x27d3, 0x2021, 0x505a, 0x2404,
+ 0xa005, 0x0040, 0x27d3, 0xad06, 0x00c0, 0x27ba, 0x6800, 0x2022,
+ 0x0078, 0x27ca, 0x6820, 0xa084, 0x0001, 0x00c0, 0x27c6, 0x6f14,
+ 0x1078, 0x37bd, 0x1078, 0x33ae, 0x0078, 0x27ca, 0x7060, 0x2060,
+ 0x6800, 0x6002, 0x6a1a, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008,
+ 0x6822, 0x1078, 0x1c53, 0x2021, 0x7400, 0x1078, 0x280f, 0x2021,
+ 0x505a, 0x1078, 0x280f, 0x157e, 0x20a9, 0x0000, 0x2021, 0x7300,
+ 0x1078, 0x280f, 0x8420, 0x0070, 0x27e7, 0x0078, 0x27e0, 0x2061,
+ 0x5300, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6018, 0x6110, 0x81ff,
+ 0x0040, 0x27f6, 0xa102, 0x0050, 0x27f6, 0x6012, 0x601b, 0x0000,
+ 0xace0, 0x0010, 0x0070, 0x27fe, 0x0078, 0x27ed, 0x8421, 0x00c0,
+ 0x27eb, 0x157f, 0x709c, 0xa084, 0x8000, 0x0040, 0x2809, 0x1078,
+ 0x39cc, 0x7003, 0x0000, 0x704b, 0x0000, 0x0078, 0x2438, 0x047e,
+ 0x2404, 0xa005, 0x0040, 0x2823, 0x2068, 0x6800, 0x007e, 0x6a1a,
+ 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x1078, 0x1c53,
+ 0x007f, 0x0078, 0x2811, 0x047f, 0x2023, 0x0000, 0x007c, 0xa282,
+ 0x0003, 0x0050, 0x282d, 0x1078, 0x23ca, 0x2300, 0x0079, 0x2830,
+ 0x2833, 0x28a6, 0x28c3, 0xa282, 0x0002, 0x0040, 0x2839, 0x1078,
+ 0x23ca, 0x706c, 0x706f, 0x0000, 0x7093, 0x0000, 0x0079, 0x2840,
+ 0x2848, 0x2848, 0x284a, 0x287e, 0x33e3, 0x2848, 0x287e, 0x2848,
+ 0x1078, 0x23ca, 0x7780, 0x1078, 0x36b0, 0x7780, 0xa7bc, 0x0f00,
+ 0x1078, 0x37bd, 0x6018, 0xa005, 0x0040, 0x2875, 0x2021, 0x7400,
+ 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x28de, 0x0040, 0x2875,
+ 0x157e, 0x20a9, 0x0000, 0x2021, 0x7300, 0x047e, 0x2009, 0x0004,
+ 0x2011, 0x0010, 0x1078, 0x28de, 0x047f, 0x0040, 0x2874, 0x8420,
+ 0x0070, 0x2874, 0x0078, 0x2865, 0x157f, 0x8738, 0xa784, 0x001f,
+ 0x00c0, 0x2850, 0x0078, 0x2461, 0x0078, 0x2461, 0x7780, 0x1078,
+ 0x37bd, 0x6018, 0xa005, 0x0040, 0x28a4, 0x2021, 0x7400, 0x2009,
+ 0x0005, 0x2011, 0x0020, 0x1078, 0x28de, 0x0040, 0x28a4, 0x157e,
+ 0x20a9, 0x0000, 0x2021, 0x7300, 0x047e, 0x2009, 0x0005, 0x2011,
+ 0x0020, 0x1078, 0x28de, 0x047f, 0x0040, 0x28a3, 0x8420, 0x0070,
+ 0x28a3, 0x0078, 0x2894, 0x157f, 0x0078, 0x2461, 0x2200, 0x0079,
+ 0x28a9, 0x28ac, 0x28ae, 0x28ae, 0x1078, 0x23ca, 0x2009, 0x0012,
+ 0x706c, 0xa086, 0x0002, 0x0040, 0x28b7, 0x2009, 0x000e, 0x6818,
+ 0xa084, 0x8000, 0x0040, 0x28bd, 0x691a, 0x706f, 0x0000, 0x7073,
+ 0x0001, 0x0078, 0x3854, 0x2200, 0x0079, 0x28c6, 0x28cb, 0x28ae,
+ 0x28c9, 0x1078, 0x23ca, 0x1078, 0x4633, 0x7000, 0xa086, 0x0001,
+ 0x00c0, 0x3373, 0x1078, 0x33c4, 0x6008, 0xa084, 0xffef, 0x600a,
+ 0x1078, 0x3366, 0x0040, 0x3373, 0x0078, 0x2573, 0x2404, 0xa005,
+ 0x0040, 0x2901, 0x2068, 0x2d04, 0x007e, 0x6814, 0xa706, 0x0040,
+ 0x28ed, 0x2d20, 0x007f, 0x0078, 0x28df, 0x007f, 0x2022, 0x691a,
+ 0x6817, 0x0000, 0x6820, 0xa205, 0x6822, 0x1078, 0x1c53, 0x6010,
+ 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x33c4,
+ 0x007c, 0xa085, 0x0001, 0x0078, 0x2900, 0x2300, 0x0079, 0x2908,
+ 0x290d, 0x290b, 0x29a6, 0x1078, 0x23ca, 0x78ec, 0xa084, 0x0001,
+ 0x00c0, 0x2921, 0x7000, 0xa086, 0x0004, 0x00c0, 0x2919, 0x0078,
+ 0x2944, 0x1078, 0x33c4, 0x6008, 0xa084, 0xffef, 0x600a, 0x0078,
+ 0x3373, 0x78e4, 0xa005, 0x00d0, 0x2944, 0x0018, 0x2438, 0x2008,
+ 0xa084, 0x0030, 0x00c0, 0x2930, 0x781b, 0x004f, 0x0078, 0x2438,
+ 0x78ec, 0xa084, 0x0003, 0x0040, 0x292c, 0x2100, 0xa084, 0x0007,
+ 0x0079, 0x293a, 0x297d, 0x2988, 0x296e, 0x2942, 0x38b9, 0x38b9,
+ 0x2942, 0x2997, 0x1078, 0x23ca, 0x7000, 0xa086, 0x0004, 0x00c0,
+ 0x295e, 0x706c, 0xa086, 0x0002, 0x00c0, 0x2954, 0x2011, 0x0002,
+ 0x2019, 0x0000, 0x0078, 0x2827, 0x706c, 0xa086, 0x0006, 0x0040,
+ 0x294e, 0x706c, 0xa086, 0x0004, 0x0040, 0x294e, 0x79e4, 0xa184,
+ 0x0030, 0x0040, 0x2968, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x296a,
+ 0x0078, 0x2f43, 0x2001, 0x0003, 0x0078, 0x2cd7, 0x6818, 0xa084,
+ 0x8000, 0x0040, 0x2975, 0x681b, 0x001d, 0x1078, 0x368f, 0x782b,
+ 0x3008, 0x781b, 0x0056, 0x0078, 0x2438, 0x6818, 0xa084, 0x8000,
+ 0x0040, 0x2984, 0x681b, 0x001d, 0x1078, 0x368f, 0x0078, 0x3884,
+ 0x6818, 0xa084, 0x8000, 0x0040, 0x298f, 0x681b, 0x001d, 0x1078,
+ 0x368f, 0x782b, 0x3008, 0x781b, 0x00d2, 0x0078, 0x2438, 0x6818,
+ 0xa084, 0x8000, 0x0040, 0x299e, 0x681b, 0x001d, 0x1078, 0x368f,
+ 0x782b, 0x3008, 0x781b, 0x0093, 0x0078, 0x2438, 0xa584, 0x000f,
+ 0x00c0, 0x29c3, 0x7000, 0x0079, 0x29ad, 0x2461, 0x29b7, 0x29b5,
+ 0x3373, 0x3373, 0x3373, 0x3373, 0x29b5, 0x1078, 0x23ca, 0x1078,
+ 0x33c4, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x3366, 0x0040,
+ 0x3373, 0x0078, 0x2573, 0x78e4, 0xa005, 0x00d0, 0x2944, 0x0018,
+ 0x2944, 0x2008, 0xa084, 0x0030, 0x00c0, 0x29d2, 0x781b, 0x004f,
+ 0x0078, 0x2438, 0x78ec, 0xa084, 0x0003, 0x0040, 0x29ce, 0x2100,
+ 0xa184, 0x0007, 0x0079, 0x29dc, 0x29ee, 0x29f2, 0x29e6, 0x29e4,
+ 0x38b9, 0x38b9, 0x29e4, 0x38af, 0x1078, 0x23ca, 0x1078, 0x3697,
+ 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2438, 0x1078, 0x3697,
+ 0x0078, 0x3884, 0x1078, 0x3697, 0x782b, 0x3008, 0x781b, 0x00d2,
+ 0x0078, 0x2438, 0x1078, 0x3697, 0x782b, 0x3008, 0x781b, 0x0093,
+ 0x0078, 0x2438, 0x2300, 0x0079, 0x2a05, 0x2a0a, 0x2a08, 0x2a0c,
+ 0x1078, 0x23ca, 0x0078, 0x3081, 0x681b, 0x0008, 0x78a3, 0x0000,
+ 0x79e4, 0xa184, 0x0030, 0x0040, 0x3081, 0x78ec, 0xa084, 0x0003,
+ 0x0040, 0x3081, 0xa184, 0x0007, 0x0079, 0x2a1e, 0x2a26, 0x29f2,
+ 0x296e, 0x3854, 0x38b9, 0x38b9, 0x2a26, 0x38af, 0x1078, 0x3868,
+ 0x0078, 0x2438, 0xa282, 0x0005, 0x0050, 0x2a30, 0x1078, 0x23ca,
+ 0x2300, 0x0079, 0x2a33, 0x2a36, 0x2c84, 0x2c92, 0x2200, 0x0079,
+ 0x2a39, 0x2a53, 0x2a40, 0x2a53, 0x2a3e, 0x2c69, 0x1078, 0x23ca,
+ 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0048,
+ 0x366b, 0xa08a, 0x0004, 0x00c8, 0x366b, 0x0079, 0x2a4f, 0x366b,
+ 0x366b, 0x366b, 0x3619, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080,
+ 0x0040, 0x2a64, 0x0078, 0x366b, 0x7000, 0xa005, 0x00c0, 0x2a5a,
+ 0x2011, 0x0004, 0x0078, 0x31f5, 0xa184, 0x00ff, 0xa08a, 0x0010,
+ 0x00c8, 0x366b, 0x0079, 0x2a6c, 0x2a7e, 0x2a7c, 0x2a96, 0x2a9a,
+ 0x2b55, 0x366b, 0x366b, 0x2b57, 0x366b, 0x366b, 0x2c65, 0x2c65,
+ 0x366b, 0x366b, 0x366b, 0x2c67, 0x1078, 0x23ca, 0xa684, 0x1000,
+ 0x0040, 0x2a8b, 0x2001, 0x0500, 0x8000, 0x8000, 0x783a, 0x781b,
+ 0x0091, 0x0078, 0x2438, 0x6818, 0xa084, 0x8000, 0x0040, 0x2a94,
+ 0x681b, 0x001d, 0x0078, 0x2a82, 0x0078, 0x3854, 0x681b, 0x001d,
+ 0x0078, 0x367b, 0x6920, 0x6922, 0xa684, 0x1800, 0x00c0, 0x2adb,
+ 0x6820, 0xa084, 0x0001, 0x00c0, 0x2ae1, 0x6818, 0xa086, 0x0008,
+ 0x00c0, 0x2aac, 0x681b, 0x0000, 0xa684, 0x0400, 0x0040, 0x2b51,
+ 0xa684, 0x0080, 0x0040, 0x2ad7, 0x7097, 0x0000, 0x6818, 0xa084,
+ 0x003f, 0xa08a, 0x000d, 0x0050, 0x2ad7, 0xa08a, 0x000c, 0x7196,
+ 0x2001, 0x000c, 0x800c, 0x719a, 0x789b, 0x0061, 0x78aa, 0x157e,
+ 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000, 0x80ac,
+ 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x781b,
+ 0x0058, 0x0078, 0x2438, 0xa684, 0x1000, 0x0040, 0x2ae1, 0x0078,
+ 0x2438, 0xa684, 0x0060, 0x0040, 0x2b4d, 0xa684, 0x0800, 0x0040,
+ 0x2b4d, 0xa684, 0x8000, 0x00c0, 0x2aef, 0x0078, 0x2b09, 0xa6b4,
+ 0x7fff, 0x7e5a, 0x6eb6, 0x789b, 0x0076, 0x7aac, 0x79ac, 0x78ac,
+ 0x801b, 0x00c8, 0x2afc, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291,
+ 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303,
+ 0x68ae, 0xa684, 0x4000, 0x0040, 0x2b11, 0xa6b4, 0xbfff, 0x7e5a,
+ 0x6eb6, 0x7000, 0xa086, 0x0003, 0x00c0, 0x2b1e, 0x1078, 0x46e9,
+ 0x1078, 0x48e6, 0x781b, 0x0064, 0x0078, 0x2438, 0xa006, 0x1078,
+ 0x49ed, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040,
+ 0x2b2d, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda,
+ 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x00c0, 0x2b3f, 0xa6b5,
+ 0x4000, 0x7e5a, 0x6eb6, 0x781b, 0x0064, 0x0078, 0x2438, 0x781b,
+ 0x0064, 0x2200, 0xa115, 0x00c0, 0x2b49, 0x1078, 0x48f7, 0x0078,
+ 0x2438, 0x1078, 0x4942, 0x0078, 0x2438, 0x781b, 0x0065, 0x0078,
+ 0x2438, 0x781b, 0x0058, 0x0078, 0x2438, 0x1078, 0x23ca, 0x0078,
+ 0x2bb8, 0x6920, 0xa184, 0x0100, 0x0040, 0x2b6f, 0xa18c, 0xfeff,
+ 0x6922, 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084, 0xefff, 0x6002,
+ 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078, 0x2ba7, 0xa184,
+ 0x0200, 0x0040, 0x2ba7, 0xa18c, 0xfdff, 0x6922, 0x0c7e, 0x7054,
+ 0x2060, 0x6000, 0xa084, 0xdfff, 0x6002, 0x6004, 0xa084, 0xffef,
+ 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2ba7,
+ 0x1078, 0x37b9, 0x1078, 0x34c7, 0x88ff, 0x0040, 0x2ba7, 0x789b,
+ 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684,
+ 0x0400, 0x00c0, 0x2ba1, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078,
+ 0x2438, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x7e58,
+ 0xa684, 0x0400, 0x00c0, 0x2bb0, 0x781b, 0x0058, 0x0078, 0x2438,
+ 0x781b, 0x0065, 0x0078, 0x2438, 0x0078, 0x3673, 0x0078, 0x3673,
+ 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x0040, 0x2bb6, 0x789b,
+ 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0, 0x2bf6,
+ 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x2bee, 0x0048,
+ 0x2bd3, 0x0078, 0x2bf0, 0xa380, 0x0002, 0xa102, 0x00c8, 0x2bee,
+ 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0c7e, 0x7054, 0x2060, 0x6000,
+ 0xa084, 0xefef, 0x6002, 0x6004, 0xa084, 0xffe5, 0x6006, 0x0c7f,
+ 0x7e58, 0xa6b4, 0xfffb, 0x7e5a, 0x0078, 0x2ba8, 0x0078, 0x2b59,
+ 0x24a8, 0x7aa8, 0x00f0, 0x2bf0, 0x0078, 0x2bc1, 0xa284, 0x00f0,
+ 0xa086, 0x0020, 0x00c0, 0x2c56, 0x8318, 0x8318, 0x2300, 0xa102,
+ 0x0040, 0x2c06, 0x0048, 0x2c06, 0x0078, 0x2c53, 0xa286, 0x0023,
+ 0x0040, 0x2bb6, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684,
+ 0xfff1, 0xa085, 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085, 0x0010,
+ 0x600a, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f,
+ 0xa184, 0x0010, 0x0040, 0x2c2a, 0x1078, 0x37b9, 0x1078, 0x35d6,
+ 0x0078, 0x2c39, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008, 0x2c48,
+ 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2ba7, 0x1078, 0x37b9, 0x1078,
+ 0x34c7, 0x88ff, 0x0040, 0x2ba7, 0x789b, 0x0060, 0x2800, 0x78aa,
+ 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2c4d, 0x782b,
+ 0x3008, 0x781b, 0x0056, 0x0078, 0x2438, 0x782b, 0x3008, 0x781b,
+ 0x0065, 0x0078, 0x2438, 0x7aa8, 0x0078, 0x2bc1, 0x8318, 0x2300,
+ 0xa102, 0x0040, 0x2c5f, 0x0048, 0x2c5f, 0x0078, 0x2bc1, 0xa284,
+ 0x0080, 0x00c0, 0x367b, 0x0078, 0x3673, 0x0078, 0x367b, 0x0078,
+ 0x366b, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001,
+ 0x0040, 0x2c74, 0x1078, 0x23ca, 0x7aa8, 0xa294, 0x00ff, 0x78a8,
+ 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x366b, 0x0079, 0x2c80,
+ 0x366b, 0x3414, 0x366b, 0x356b, 0xa282, 0x0000, 0x00c0, 0x2c8a,
+ 0x1078, 0x23ca, 0x1078, 0x368f, 0x782b, 0x3008, 0x781b, 0x0065,
+ 0x0078, 0x2438, 0xa282, 0x0003, 0x00c0, 0x2c98, 0x1078, 0x23ca,
+ 0xa484, 0x8000, 0x00c0, 0x2cbb, 0x706c, 0xa005, 0x0040, 0x2ca2,
+ 0x1078, 0x23ca, 0x6f14, 0x7782, 0xa7bc, 0x0f00, 0x1078, 0x37bd,
+ 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f, 0x00c0,
+ 0x2ca6, 0x1078, 0x3693, 0x706f, 0x0002, 0x2009, 0x5038, 0x200b,
+ 0x0009, 0x0078, 0x2cbd, 0x1078, 0x369f, 0x782b, 0x3008, 0x781b,
+ 0x0065, 0x0078, 0x2438, 0xa282, 0x0004, 0x0050, 0x2cc9, 0x1078,
+ 0x23ca, 0x2300, 0x0079, 0x2ccc, 0x2ccf, 0x2db8, 0x2deb, 0xa286,
+ 0x0003, 0x0040, 0x2cd5, 0x1078, 0x23ca, 0x2001, 0x0000, 0x007e,
+ 0x68c0, 0xa005, 0x0040, 0x2cde, 0x7003, 0x0003, 0x68a0, 0xa084,
+ 0x2000, 0x0040, 0x2ce7, 0x6008, 0xa085, 0x0002, 0x600a, 0x007f,
+ 0x703e, 0x7000, 0xa084, 0x0007, 0x0079, 0x2cee, 0x2461, 0x2cf8,
+ 0x2cf8, 0x2eed, 0x2f29, 0x2461, 0x2f29, 0x2cf6, 0x1078, 0x23ca,
+ 0xa684, 0x1000, 0x00c0, 0x2d00, 0x1078, 0x4633, 0x0040, 0x2d92,
+ 0x7868, 0xa08c, 0x00ff, 0x0040, 0x2d48, 0xa186, 0x0008, 0x00c0,
+ 0x2d17, 0x1078, 0x33c4, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078,
+ 0x3366, 0x0040, 0x2d48, 0x1078, 0x4633, 0x0078, 0x2d2f, 0xa186,
+ 0x0028, 0x00c0, 0x2d48, 0x1078, 0x4633, 0x6008, 0xa084, 0xffef,
+ 0x600a, 0x6018, 0xa005, 0x0040, 0x2d2f, 0x8001, 0x601a, 0xa005,
+ 0x0040, 0x2d2f, 0x8001, 0xa005, 0x0040, 0x2d2f, 0x601e, 0x6820,
+ 0xa084, 0x0001, 0x0040, 0x2461, 0x6820, 0xa084, 0xfffe, 0x6822,
+ 0x7060, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802,
+ 0xa005, 0x2d00, 0x00c0, 0x2d45, 0x6002, 0x6006, 0x0078, 0x2461,
+ 0x017e, 0x1078, 0x2e1c, 0x017f, 0xa684, 0xdf00, 0x681e, 0x682b,
+ 0x0000, 0x6f14, 0x81ff, 0x0040, 0x2d92, 0xa186, 0x0002, 0x00c0,
+ 0x2d92, 0xa684, 0x0800, 0x00c0, 0x2d65, 0xa684, 0x0060, 0x0040,
+ 0x2d65, 0x78d8, 0x7adc, 0x682e, 0x6a32, 0x6820, 0xa084, 0x0800,
+ 0x00c0, 0x2d92, 0x8717, 0xa294, 0x000f, 0x8213, 0x8213, 0x8213,
+ 0xa290, 0x5280, 0xa290, 0x0000, 0x221c, 0xa384, 0x0100, 0x00c0,
+ 0x2d7b, 0x0078, 0x2d81, 0x8210, 0x2204, 0xa085, 0x0018, 0x2012,
+ 0x8211, 0xa384, 0x0400, 0x0040, 0x2d8e, 0x68a0, 0xa084, 0x0100,
+ 0x00c0, 0x2d8e, 0x1078, 0x2ea0, 0x0078, 0x2461, 0x6008, 0xa085,
+ 0x0002, 0x600a, 0x6916, 0x6818, 0xa084, 0x8000, 0x0040, 0x2d9a,
+ 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x1078, 0x33b5, 0x1078,
+ 0x33c4, 0x00c0, 0x2da7, 0x6008, 0xa084, 0xffef, 0x600a, 0x6820,
+ 0xa084, 0x0001, 0x00c0, 0x2db0, 0x1078, 0x33ae, 0x0078, 0x2db4,
+ 0x7060, 0x2060, 0x6800, 0x6002, 0x1078, 0x1c53, 0x0078, 0x2461,
+ 0xa282, 0x0004, 0x0048, 0x2dbe, 0x1078, 0x23ca, 0x2200, 0x0079,
+ 0x2dc1, 0x2dbc, 0x2dc5, 0x2dd2, 0x2dc5, 0x7000, 0xa086, 0x0005,
+ 0x0040, 0x2dce, 0x1078, 0x368f, 0x782b, 0x3008, 0x781b, 0x0065,
+ 0x0078, 0x2438, 0x7890, 0x8007, 0x8001, 0xa084, 0x0007, 0xa080,
+ 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186, 0x0003, 0x0040,
+ 0x2de7, 0xa186, 0x0000, 0x0040, 0x2de7, 0x0078, 0x366b, 0x781b,
+ 0x0065, 0x0078, 0x2438, 0x6820, 0xa085, 0x0004, 0x6822, 0x82ff,
+ 0x00c0, 0x2df6, 0x1078, 0x368f, 0x0078, 0x2dfd, 0x8211, 0x0040,
+ 0x2dfb, 0x1078, 0x23ca, 0x1078, 0x369f, 0x782b, 0x3008, 0x781b,
+ 0x0065, 0x0078, 0x2438, 0x702c, 0x8003, 0x0048, 0x2e0d, 0x2019,
+ 0x4c5b, 0x1078, 0x2255, 0x702f, 0x8000, 0x1078, 0x38de, 0x7830,
+ 0xa084, 0x00c0, 0x00c0, 0x2e19, 0x0018, 0x2e19, 0x791a, 0xa006,
+ 0x007c, 0xa085, 0x0001, 0x007c, 0xa684, 0x0060, 0x00c0, 0x2e26,
+ 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2e9f, 0xa684, 0x0800,
+ 0x00c0, 0x2e48, 0x68b4, 0xa084, 0x4800, 0xa635, 0xa684, 0x0800,
+ 0x00c0, 0x2e48, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x703c, 0xa005,
+ 0x00c0, 0x2e40, 0x2200, 0xa105, 0x0040, 0x2e47, 0x703f, 0x0015,
+ 0x7000, 0xa086, 0x0006, 0x0040, 0x2e47, 0x1078, 0x4633, 0x007c,
+ 0xa684, 0x0020, 0x0040, 0x2e6a, 0xa684, 0x4000, 0x0040, 0x2e56,
+ 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2e40, 0x68b4, 0xa084,
+ 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2e50, 0x703c, 0xa005,
+ 0x00c0, 0x2e64, 0x703f, 0x0015, 0x79d8, 0x7adc, 0x692e, 0x6a32,
+ 0x0078, 0x2e40, 0xa684, 0x4000, 0x0040, 0x2e74, 0x682f, 0x0000,
+ 0x6833, 0x0000, 0x0078, 0x2e40, 0x68b4, 0xa084, 0x4800, 0xa635,
+ 0xa684, 0x4000, 0x00c0, 0x2e6e, 0x703c, 0xa005, 0x00c0, 0x2e82,
+ 0x703f, 0x0015, 0x79d8, 0x7adc, 0x78d0, 0x80fb, 0x00c8, 0x2e89,
0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a32,
- 0x2100, 0xa205, 0x00c0, 0x2826, 0x0078, 0x27e0, 0x7000, 0xa086,
- 0x0006, 0x0040, 0x282f, 0x1078, 0x362f, 0x0078, 0x27e0, 0x007c,
- 0xa384, 0x0200, 0x0040, 0x2838, 0x6008, 0xa085, 0x0002, 0x600a,
- 0x681b, 0x0006, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003,
+ 0x2100, 0xa205, 0x00c0, 0x2e96, 0x0078, 0x2e40, 0x7000, 0xa086,
+ 0x0006, 0x0040, 0x2e9f, 0x1078, 0x49ed, 0x0078, 0x2e40, 0x007c,
+ 0x6008, 0xa085, 0x0200, 0x600a, 0xa384, 0x0200, 0x0040, 0x2eac,
+ 0x6008, 0xa085, 0x0002, 0x600a, 0x681b, 0x0006, 0x688f, 0x0000,
+ 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003,
0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b, 0x0020,
- 0x7000, 0x0079, 0x284b, 0x2853, 0x2855, 0x285e, 0x2853, 0x2853,
- 0x2853, 0x2853, 0x2853, 0x1078, 0x1eac, 0x6820, 0xa084, 0x0001,
- 0x00c0, 0x285e, 0x1078, 0x2cc9, 0x0078, 0x2864, 0x7054, 0x2c50,
- 0x2060, 0x6800, 0x6002, 0x2a60, 0x2021, 0x3957, 0x2404, 0xa005,
- 0x0040, 0x286d, 0x2020, 0x0078, 0x2866, 0x2d22, 0x206b, 0x0000,
- 0x007c, 0x1078, 0x2cd0, 0x1078, 0x2cdf, 0x682b, 0x0000, 0x789b,
- 0x000e, 0x6f14, 0x6817, 0x0002, 0x1078, 0x366b, 0xa684, 0x0800,
- 0x0040, 0x2886, 0x691c, 0xa18d, 0x2000, 0x691e, 0x6818, 0xa084,
- 0x8000, 0x0040, 0x2896, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x2894,
- 0x681b, 0x001e, 0x0078, 0x2896, 0x681b, 0x0000, 0x2021, 0x3957,
- 0x6800, 0x2022, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078, 0x1a26,
- 0x0078, 0x1f03, 0x1078, 0x27ce, 0x682b, 0x0000, 0x789b, 0x000e,
- 0x6f14, 0x1078, 0x316f, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xa084,
- 0x8000, 0x0040, 0x28b5, 0x7038, 0x681a, 0xa68c, 0xdf00, 0x691e,
- 0x70a3, 0x0000, 0x0078, 0x1f03, 0xa006, 0x1078, 0x32f5, 0x6817,
- 0x0000, 0x681b, 0x0001, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000,
- 0x7000, 0x0079, 0x28cb, 0x28d3, 0x28d5, 0x28d5, 0x28d7, 0x28d7,
- 0x28d7, 0x28d7, 0x28d3, 0x1078, 0x1eac, 0x1078, 0x2cdf, 0x6008,
- 0xa084, 0xffef, 0x600a, 0x0078, 0x2caa, 0x2300, 0x0079, 0x28e0,
- 0x28e3, 0x28e5, 0x2939, 0x1078, 0x1eac, 0x7000, 0x0079, 0x28e8,
- 0x28f0, 0x28f2, 0x28f2, 0x290d, 0x28f2, 0x291a, 0x290d, 0x28f0,
- 0x1078, 0x1eac, 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0, 0x2909,
- 0xa6b4, 0xffdf, 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a, 0x681c,
- 0xa084, 0xffdf, 0x681e, 0x1078, 0x32f5, 0x1078, 0x3571, 0x0078,
- 0x311c, 0xa684, 0x2000, 0x0040, 0x28fc, 0x6818, 0xa084, 0x8000,
- 0x0040, 0x291a, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040, 0x291a,
- 0x681b, 0x0007, 0x2009, 0x391e, 0x210c, 0xa186, 0x0000, 0x0040,
- 0x292f, 0xa186, 0x0001, 0x0040, 0x2933, 0x2009, 0x3935, 0x200b,
- 0x000b, 0x70a3, 0x0001, 0x781b, 0x0047, 0x0078, 0x1efb, 0x781b,
- 0x00df, 0x0078, 0x1efb, 0x2009, 0x3935, 0x200b, 0x000a, 0x0078,
- 0x1efb, 0x1078, 0x1eac, 0x2300, 0x0079, 0x293e, 0x2941, 0x2943,
- 0x2976, 0x1078, 0x1eac, 0x7000, 0x0079, 0x2946, 0x294e, 0x2950,
- 0x2950, 0x296b, 0x2950, 0x2972, 0x296b, 0x294e, 0x1078, 0x1eac,
- 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0, 0x2967, 0xa6b4, 0xffbf,
- 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a, 0x681c, 0xa084, 0xffbf,
- 0x681e, 0x1078, 0x32f5, 0x1078, 0x3571, 0x0078, 0x311c, 0xa684,
- 0x2000, 0x0040, 0x295a, 0x6818, 0xa084, 0x8000, 0x0040, 0x2972,
- 0x681b, 0x0007, 0x781b, 0x00e6, 0x0078, 0x1efb, 0x6820, 0xa085,
- 0x0004, 0x6822, 0x1078, 0x30e7, 0xa6b5, 0x0800, 0x1078, 0x2f7d,
- 0x781b, 0x0067, 0x0078, 0x1efb, 0x2300, 0x0079, 0x2987, 0x298a,
- 0x298c, 0x298e, 0x1078, 0x1eac, 0x1078, 0x1eac, 0xa684, 0x0400,
- 0x00c0, 0x29ae, 0x782b, 0x3009, 0x6920, 0xa18c, 0xfdff, 0xa18c,
- 0xfeff, 0x6922, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb,
- 0x785a, 0x79e4, 0xa184, 0x0020, 0x00c0, 0x29aa, 0x2001, 0x0014,
- 0x0078, 0x26ad, 0xa184, 0x0007, 0x0079, 0x29e6, 0x7a90, 0xa294,
- 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x29e4, 0x789b,
- 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x29d5, 0x7ba8, 0x7ba8,
- 0xa386, 0x0001, 0x00c0, 0x29c8, 0x2009, 0xfff7, 0x0078, 0x29ce,
- 0xa386, 0x0003, 0x00c0, 0x29d5, 0x2009, 0xffef, 0x0c7e, 0x7048,
- 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab,
- 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c,
- 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x311c, 0x239b, 0x23a8,
- 0x3124, 0x3124, 0x29ee, 0x29ee, 0x29ee, 0x3124, 0x1078, 0x1eac,
- 0x79e4, 0xa184, 0x0030, 0x00c0, 0x2a06, 0x70a0, 0xa086, 0x0002,
- 0x00c0, 0x29fe, 0x2011, 0x0002, 0x0078, 0x2288, 0x6818, 0xa085,
- 0x8000, 0x681a, 0x2001, 0x0014, 0x0078, 0x26ad, 0xa184, 0x0007,
- 0x0079, 0x2a0a, 0x311c, 0x311c, 0x2a12, 0x311c, 0x3144, 0x3144,
- 0x311c, 0x311c, 0xa684, 0x0080, 0x0040, 0x2a41, 0x71c8, 0x81ff,
- 0x0040, 0x2a41, 0xa182, 0x000d, 0x00d0, 0x2a22, 0x70cb, 0x0000,
- 0x0078, 0x2a27, 0xa182, 0x000c, 0x70ca, 0x2009, 0x000c, 0x789b,
- 0x0061, 0x79aa, 0x157e, 0x137e, 0x147e, 0x70cc, 0x8114, 0xa210,
- 0x72ce, 0xa080, 0x000b, 0xad00, 0x2098, 0x20a1, 0x012b, 0x789b,
- 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f, 0x137f, 0x157f, 0x0078,
- 0x3124, 0xa684, 0x0400, 0x00c0, 0x2a82, 0x6820, 0xa084, 0x0001,
- 0x0040, 0x3124, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0040, 0x2a56,
- 0xa086, 0x0060, 0x00c0, 0x2a56, 0xa18d, 0x4000, 0xa18c, 0xfffb,
- 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061,
- 0x6818, 0xa085, 0x8000, 0x681a, 0x78aa, 0x8008, 0x810c, 0x0040,
- 0x2d07, 0xa18c, 0x00f8, 0x00c0, 0x2d07, 0x157e, 0x137e, 0x147e,
- 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b,
- 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6814, 0x8007, 0x7882,
- 0x0078, 0x3124, 0x6818, 0xa084, 0x8000, 0x0040, 0x2a89, 0x681b,
- 0x0008, 0x781b, 0x00da, 0x0078, 0x1efb, 0x2300, 0x0079, 0x2a90,
- 0x2a95, 0x2b18, 0x2a93, 0x1078, 0x1eac, 0x7000, 0xa084, 0x0007,
- 0x0079, 0x2a9a, 0x2aa2, 0x2aa4, 0x2ac0, 0x2aa2, 0x2aa2, 0x1f03,
- 0x2aa2, 0x2aa2, 0x1078, 0x1eac, 0x6920, 0xa18d, 0x0001, 0x6922,
- 0x6800, 0x6006, 0xa005, 0x00c0, 0x2aae, 0x6002, 0x681c, 0xa084,
- 0x000e, 0x0040, 0x2aba, 0x7014, 0x68ba, 0x712c, 0xa188, 0x4280,
- 0x0078, 0x2abc, 0x2009, 0x4380, 0x2104, 0x6802, 0x2d0a, 0x7156,
- 0x6920, 0xa184, 0x8000, 0x00c0, 0x2acc, 0x68af, 0x0000, 0x68b3,
- 0x0000, 0xa18d, 0x8000, 0x6922, 0x6eb6, 0xa684, 0x0060, 0x0040,
- 0x2b16, 0xa684, 0x0800, 0x00c0, 0x2add, 0x6894, 0x68a6, 0x6898,
- 0x68aa, 0x1078, 0x32f5, 0x0078, 0x2b16, 0xa684, 0x0020, 0x0040,
- 0x2aea, 0xa006, 0x1078, 0x362f, 0x79d8, 0x7adc, 0x69aa, 0x6aa6,
- 0x0078, 0x2af0, 0x1078, 0x30a6, 0x69aa, 0x6aa6, 0x1078, 0x362f,
- 0xa684, 0x8000, 0x0040, 0x2b16, 0xa684, 0x7fff, 0x68b6, 0x789b,
- 0x0074, 0x1078, 0x316f, 0x2010, 0x1078, 0x316f, 0x2008, 0xa684,
- 0x0020, 0x00c0, 0x2b0e, 0x1078, 0x316f, 0x801b, 0x00c8, 0x2b09,
+ 0x68b3, 0x0000, 0x68af, 0x0000, 0x7000, 0x0079, 0x2ec7, 0x2461,
+ 0x2ed1, 0x2eda, 0x2ecf, 0x2ecf, 0x2ecf, 0x2ecf, 0x2ecf, 0x1078,
+ 0x23ca, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2eda, 0x1078, 0x33ae,
+ 0x0078, 0x2ee0, 0x7060, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60,
+ 0x2021, 0x505a, 0x2404, 0xa005, 0x0040, 0x2ee9, 0x2020, 0x0078,
+ 0x2ee2, 0x2d22, 0x206b, 0x0000, 0x007c, 0x1078, 0x33b5, 0x1078,
+ 0x33c4, 0x6008, 0xa084, 0xfdff, 0x600a, 0x682b, 0x0000, 0x789b,
+ 0x000e, 0x6f14, 0x6817, 0x0002, 0x1078, 0x4a35, 0xa684, 0x0800,
+ 0x0040, 0x2f06, 0x691c, 0xa18d, 0x2000, 0x691e, 0x6818, 0xa084,
+ 0x8000, 0x0040, 0x2f16, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x2f14,
+ 0x681b, 0x001e, 0x0078, 0x2f16, 0x681b, 0x0000, 0x2021, 0x505a,
+ 0x2404, 0xad06, 0x0040, 0x2f1d, 0x7460, 0x6800, 0x2022, 0x68c3,
+ 0x0000, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078, 0x1c53, 0x0078,
+ 0x2461, 0x1078, 0x2e1c, 0x682b, 0x0000, 0x2001, 0x000e, 0x6f14,
+ 0x1078, 0x38e4, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xa084, 0x8000,
+ 0x0040, 0x2f3c, 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x706f,
+ 0x0000, 0x0078, 0x2461, 0x7000, 0xa005, 0x00c0, 0x2f49, 0x0078,
+ 0x2461, 0xa006, 0x1078, 0x4633, 0x6817, 0x0000, 0x681b, 0x0014,
+ 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa085, 0x00ff,
+ 0x6822, 0x7000, 0x0079, 0x2f5c, 0x2461, 0x2f66, 0x2f66, 0x2f68,
+ 0x2f68, 0x2f68, 0x2f68, 0x2f64, 0x1078, 0x23ca, 0x1078, 0x33c4,
+ 0x6008, 0xa084, 0xffef, 0x600a, 0x0078, 0x337e, 0x2300, 0x0079,
+ 0x2f71, 0x2f74, 0x2f76, 0x2faf, 0x1078, 0x23ca, 0x7000, 0x0079,
+ 0x2f79, 0x2461, 0x2f83, 0x2f83, 0x2f9e, 0x2f83, 0x2fab, 0x2f9e,
+ 0x2f81, 0x1078, 0x23ca, 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0,
+ 0x2f9a, 0xa6b4, 0xffdf, 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a,
+ 0x681c, 0xa084, 0xffdf, 0x681e, 0x1078, 0x4633, 0x1078, 0x48f7,
+ 0x0078, 0x3854, 0xa684, 0x2000, 0x0040, 0x2f8d, 0x6818, 0xa084,
+ 0x8000, 0x0040, 0x2fab, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040,
+ 0x2fab, 0x681b, 0x0007, 0x1078, 0x3868, 0x0078, 0x2438, 0x1078,
+ 0x23ca, 0x2300, 0x0079, 0x2fb4, 0x2fb7, 0x2fb9, 0x2fec, 0x1078,
+ 0x23ca, 0x7000, 0x0079, 0x2fbc, 0x2461, 0x2fc6, 0x2fc6, 0x2fe1,
+ 0x2fc6, 0x2fe8, 0x2fe1, 0x2fc4, 0x1078, 0x23ca, 0xa684, 0x0060,
+ 0xa086, 0x0060, 0x00c0, 0x2fdd, 0xa6b4, 0xffbf, 0xa6b4, 0xbfff,
+ 0xa6b5, 0x2000, 0x7e5a, 0x681c, 0xa084, 0xffbf, 0x681e, 0x1078,
+ 0x4633, 0x1078, 0x48f7, 0x0078, 0x3854, 0xa684, 0x2000, 0x0040,
+ 0x2fd0, 0x6818, 0xa084, 0x8000, 0x0040, 0x2fe8, 0x681b, 0x0007,
+ 0x781b, 0x00d2, 0x0078, 0x2438, 0x6820, 0xa085, 0x0004, 0x6822,
+ 0x1078, 0x381f, 0xa6b5, 0x0800, 0x1078, 0x368f, 0x782b, 0x3008,
+ 0x781b, 0x0065, 0x0078, 0x2438, 0x2300, 0x0079, 0x2fff, 0x3002,
+ 0x3004, 0x3006, 0x1078, 0x23ca, 0x0078, 0x367b, 0xa684, 0x0400,
+ 0x00c0, 0x302f, 0x79e4, 0xa184, 0x0020, 0x0040, 0x3016, 0x78ec,
+ 0xa084, 0x0003, 0x0040, 0x3016, 0x782b, 0x3009, 0x789b, 0x0060,
+ 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xa184, 0x0020,
+ 0x0040, 0x3027, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x302b, 0x2001,
+ 0x0014, 0x0078, 0x2cd7, 0xa184, 0x0007, 0x0079, 0x3067, 0x7a90,
+ 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x3065,
+ 0x789b, 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x3056, 0x7ba8,
+ 0x7ba8, 0xa386, 0x0001, 0x00c0, 0x3049, 0x2009, 0xfff7, 0x0078,
+ 0x304f, 0xa386, 0x0003, 0x00c0, 0x3056, 0x2009, 0xffef, 0x0c7e,
+ 0x7054, 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060,
+ 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920,
+ 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x3854, 0x297d,
+ 0x2988, 0x3071, 0x3079, 0x306f, 0x306f, 0x3854, 0x3854, 0x1078,
+ 0x23ca, 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078,
+ 0x385e, 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078,
+ 0x3854, 0x79e4, 0xa184, 0x0030, 0x0040, 0x308b, 0x78ec, 0xa084,
+ 0x0003, 0x00c0, 0x30b2, 0x7000, 0xa086, 0x0004, 0x00c0, 0x30a5,
+ 0x706c, 0xa086, 0x0002, 0x00c0, 0x309b, 0x2011, 0x0002, 0x2019,
+ 0x0000, 0x0078, 0x2827, 0x706c, 0xa086, 0x0006, 0x0040, 0x3095,
+ 0x706c, 0xa086, 0x0004, 0x0040, 0x3095, 0x7000, 0xa086, 0x0000,
+ 0x0040, 0x2438, 0x6818, 0xa085, 0x8000, 0x681a, 0x2001, 0x0014,
+ 0x0078, 0x2cd7, 0xa184, 0x0007, 0x0079, 0x30b6, 0x3854, 0x3854,
+ 0x30be, 0x3854, 0x38b9, 0x38b9, 0x3854, 0x3854, 0xa684, 0x0080,
+ 0x0040, 0x30ed, 0x7194, 0x81ff, 0x0040, 0x30ed, 0xa182, 0x000d,
+ 0x00d0, 0x30ce, 0x7097, 0x0000, 0x0078, 0x30d3, 0xa182, 0x000c,
+ 0x7096, 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa, 0x157e, 0x137e,
+ 0x147e, 0x7098, 0x8114, 0xa210, 0x729a, 0xa080, 0x000b, 0xad00,
+ 0x2098, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6,
+ 0x147f, 0x137f, 0x157f, 0x0078, 0x385e, 0xa684, 0x0400, 0x00c0,
+ 0x312e, 0x6820, 0xa084, 0x0001, 0x0040, 0x385e, 0xa68c, 0x0060,
+ 0xa684, 0x0060, 0x0040, 0x3102, 0xa086, 0x0060, 0x00c0, 0x3102,
+ 0xa18d, 0x4000, 0xa18c, 0xfffb, 0x795a, 0x69b6, 0x789b, 0x0060,
+ 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, 0xa085, 0x8000, 0x681a,
+ 0x78aa, 0x8008, 0x810c, 0x0040, 0x33dd, 0xa18c, 0x00f8, 0x00c0,
+ 0x33dd, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000,
+ 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f,
+ 0x157f, 0x6814, 0x8007, 0x7882, 0x0078, 0x385e, 0x6818, 0xa084,
+ 0x8000, 0x0040, 0x3135, 0x681b, 0x0008, 0x781b, 0x00c8, 0x0078,
+ 0x2438, 0x2300, 0x0079, 0x313c, 0x3141, 0x31e0, 0x313f, 0x1078,
+ 0x23ca, 0x7000, 0xa084, 0x0007, 0x0079, 0x3146, 0x2461, 0x3150,
+ 0x3185, 0x315b, 0x314e, 0x2461, 0x314e, 0x314e, 0x1078, 0x23ca,
+ 0x681c, 0xa084, 0x2000, 0x0040, 0x3169, 0x6008, 0xa085, 0x0002,
+ 0x600a, 0x0078, 0x3169, 0x68c0, 0xa005, 0x00c0, 0x3185, 0x6920,
+ 0xa18d, 0x0001, 0x6922, 0x68c3, 0x0001, 0x6800, 0x706a, 0x0078,
+ 0x317f, 0x6920, 0xa18d, 0x0001, 0x6922, 0x6800, 0x6006, 0xa005,
+ 0x00c0, 0x3173, 0x6002, 0x681c, 0xa084, 0x000e, 0x0040, 0x317f,
+ 0x7014, 0x68ba, 0x7130, 0xa188, 0x7300, 0x0078, 0x3181, 0x2009,
+ 0x7400, 0x2104, 0x6802, 0x2d0a, 0x7162, 0x6eb6, 0xa684, 0x0060,
+ 0x0040, 0x31de, 0xa684, 0x0800, 0x00c0, 0x3199, 0xa684, 0x7fff,
+ 0x68b6, 0x6894, 0x68a6, 0x6898, 0x68aa, 0x1078, 0x4633, 0x0078,
+ 0x31de, 0xa684, 0x0020, 0x0040, 0x31ae, 0x68c0, 0xa005, 0x0040,
+ 0x31a5, 0x1078, 0x4a35, 0x0078, 0x31a8, 0xa006, 0x1078, 0x49ed,
+ 0x79d8, 0x7adc, 0x69aa, 0x6aa6, 0x0078, 0x31b4, 0x1078, 0x37ca,
+ 0x69aa, 0x6aa6, 0x1078, 0x49ed, 0xa684, 0x8000, 0x0040, 0x31de,
+ 0xa684, 0x7fff, 0x68b6, 0x2001, 0x0076, 0x1078, 0x38e4, 0x2010,
+ 0x2001, 0x0078, 0x1078, 0x38e4, 0x2008, 0xa684, 0x0020, 0x00c0,
+ 0x31d6, 0x2001, 0x007a, 0x1078, 0x38e4, 0x801b, 0x00c8, 0x31d1,
0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100,
- 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x0078, 0x1f03,
- 0x0078, 0x2f75, 0x7033, 0x0000, 0xa282, 0x0006, 0x0050, 0x2b22,
- 0x1078, 0x1eac, 0x2300, 0x0079, 0x2b25, 0x2b28, 0x2b4e, 0x2b72,
- 0x2200, 0x0079, 0x2b2b, 0x2b31, 0x2f75, 0x2b33, 0x2b31, 0x2b9c,
- 0x2bed, 0x1078, 0x1eac, 0x7003, 0x0005, 0x2001, 0x4390, 0x2068,
- 0x703e, 0x157e, 0x20a9, 0x002f, 0x2003, 0x0000, 0x8000, 0x0070,
- 0x2b43, 0x0078, 0x2b3c, 0x157f, 0x6817, 0x0000, 0x68b7, 0x0700,
- 0x6823, 0x0800, 0x6827, 0x0003, 0x0078, 0x2f69, 0x7000, 0xa086,
- 0x0001, 0x00c0, 0x2b5b, 0x1078, 0x2cdf, 0x1078, 0x32f5, 0x7034,
- 0x600a, 0x0078, 0x2b60, 0x7000, 0xa086, 0x0003, 0x0040, 0x2b55,
- 0x7003, 0x0005, 0x2001, 0x4390, 0x2068, 0x703e, 0x7032, 0x2200,
- 0x0079, 0x2b6a, 0x2f75, 0x2b70, 0x2b70, 0x2b9c, 0x2b70, 0x2f75,
- 0x1078, 0x1eac, 0x7000, 0xa086, 0x0001, 0x00c0, 0x2b7f, 0x1078,
- 0x2cdf, 0x1078, 0x32f5, 0x7034, 0x600a, 0x0078, 0x2b84, 0x7000,
- 0xa086, 0x0003, 0x0040, 0x2b79, 0x7003, 0x0005, 0x2001, 0x4390,
- 0x2068, 0x703e, 0x7032, 0x2200, 0x0079, 0x2b8e, 0x2b96, 0x2b94,
- 0x2b94, 0x2b96, 0x2b94, 0x2b96, 0x1078, 0x1eac, 0x1078, 0x2f8d,
- 0x781b, 0x0067, 0x0078, 0x1efb, 0x7000, 0xa086, 0x0001, 0x00c0,
- 0x2ba9, 0x1078, 0x2cdf, 0x1078, 0x32f5, 0x7034, 0x600a, 0x0078,
- 0x2bae, 0x7000, 0xa086, 0x0003, 0x0040, 0x2ba3, 0x7003, 0x0002,
- 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007,
- 0xa215, 0x2069, 0x4380, 0x2d04, 0x2d08, 0x7156, 0x2068, 0xa005,
- 0x0040, 0x2bc9, 0x6814, 0xa206, 0x0040, 0x2be2, 0x6800, 0x0078,
- 0x2bbc, 0x7003, 0x0005, 0x2001, 0x4390, 0x2068, 0x703e, 0x7032,
- 0x157e, 0x20a9, 0x002f, 0x2003, 0x0000, 0x8000, 0x0070, 0x2bda,
- 0x0078, 0x2bd3, 0x157f, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800,
+ 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x0078, 0x2461,
+ 0x0078, 0x367b, 0x7037, 0x0000, 0xa282, 0x0006, 0x0050, 0x31ea,
+ 0x1078, 0x23ca, 0x7000, 0xa084, 0x0007, 0x10c0, 0x398a, 0x2300,
+ 0x0079, 0x31f2, 0x31f5, 0x321e, 0x3232, 0x2200, 0x0079, 0x31f8,
+ 0x321c, 0x367b, 0x31fe, 0x321c, 0x324e, 0x3290, 0x7003, 0x0005,
+ 0x2001, 0x7510, 0x2068, 0x704a, 0x157e, 0x20a9, 0x0031, 0x2003,
+ 0x0000, 0x8000, 0x0070, 0x320e, 0x0078, 0x3207, 0x157f, 0xad80,
+ 0x0009, 0x7036, 0x6817, 0x0000, 0x68b7, 0x0700, 0x6823, 0x0800,
+ 0x6827, 0x0003, 0x0078, 0x366b, 0x1078, 0x23ca, 0x7003, 0x0005,
+ 0x2001, 0x7510, 0x2068, 0x704a, 0xad80, 0x0009, 0x7036, 0x2200,
+ 0x0079, 0x322a, 0x367b, 0x3230, 0x3230, 0x324e, 0x3230, 0x367b,
+ 0x1078, 0x23ca, 0x7003, 0x0005, 0x2001, 0x7510, 0x2068, 0x704a,
+ 0xad80, 0x0009, 0x7036, 0x2200, 0x0079, 0x323e, 0x3246, 0x3244,
+ 0x3244, 0x3246, 0x3244, 0x3246, 0x1078, 0x23ca, 0x1078, 0x369f,
+ 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x7003, 0x0002,
+ 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f,
+ 0xa215, 0x2069, 0x7400, 0x2d04, 0x2d08, 0x7162, 0x2068, 0xa005,
+ 0x0040, 0x3269, 0x6814, 0xa206, 0x0040, 0x3285, 0x6800, 0x0078,
+ 0x325c, 0x7003, 0x0005, 0x2001, 0x7510, 0x2068, 0x704a, 0x7036,
+ 0x157e, 0x20a9, 0x0031, 0x2003, 0x0000, 0x8000, 0x0070, 0x327a,
+ 0x0078, 0x3273, 0x157f, 0xad80, 0x0009, 0x7036, 0x6a16, 0x68b7,
+ 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a, 0x6820,
+ 0xa084, 0x0c00, 0x0040, 0x32df, 0x1078, 0x3697, 0x0078, 0x32df,
+ 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8,
+ 0xa484, 0x001f, 0xa215, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0xa1e8,
+ 0x7300, 0x2d04, 0x2d08, 0x7162, 0x2068, 0xa005, 0x0040, 0x32af,
+ 0x6814, 0xa206, 0x0040, 0x32ca, 0x6800, 0x0078, 0x32a2, 0x7003,
+ 0x0005, 0x2001, 0x7510, 0x2068, 0x704a, 0x157e, 0x20a9, 0x0031,
+ 0x2003, 0x0000, 0x8000, 0x0070, 0x32bf, 0x0078, 0x32b8, 0x157f,
+ 0xad80, 0x0009, 0x7036, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800,
0x6827, 0x0003, 0x6eb4, 0x7e5a, 0x6820, 0xa084, 0x0c00, 0x0040,
- 0x2c4b, 0x1078, 0x2f85, 0x0078, 0x2c4b, 0x7000, 0xa086, 0x0001,
- 0x00c0, 0x2bfa, 0x1078, 0x2cdf, 0x1078, 0x32f5, 0x7034, 0x600a,
- 0x0078, 0x2bff, 0x7000, 0xa086, 0x0003, 0x0040, 0x2bf4, 0x7003,
- 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484,
- 0x0007, 0xa215, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0xa1e8, 0x4280,
- 0x2d04, 0x2d08, 0x7156, 0x2068, 0xa005, 0x0040, 0x2c1e, 0x6814,
- 0xa206, 0x0040, 0x2c36, 0x6800, 0x0078, 0x2c11, 0x7003, 0x0005,
- 0x2001, 0x4390, 0x2068, 0x703e, 0x157e, 0x20a9, 0x002f, 0x2003,
- 0x0000, 0x8000, 0x0070, 0x2c2e, 0x0078, 0x2c27, 0x157f, 0x6a16,
- 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a,
- 0x6820, 0xa084, 0x0c00, 0x0040, 0x2c4b, 0xa084, 0x0800, 0x0040,
- 0x2c45, 0x1078, 0x2f89, 0x0078, 0x2c4b, 0x1078, 0x2f85, 0x70bf,
- 0x0000, 0x0078, 0x2c4b, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003,
- 0x8003, 0x8003, 0xa080, 0x3a00, 0x2060, 0x704a, 0x6000, 0x704e,
- 0x6004, 0x7052, 0xa684, 0x0060, 0x0040, 0x2c64, 0x68a8, 0x78d2,
- 0x78da, 0x68a4, 0x78d6, 0x78de, 0x077f, 0x1078, 0x3099, 0x2009,
- 0x0068, 0xa684, 0x0008, 0x0040, 0x2c6f, 0x2009, 0x0067, 0xa6b5,
- 0x2000, 0x7e5a, 0x791a, 0xa684, 0x0060, 0x0040, 0x2c85, 0xa684,
- 0x0800, 0x00c0, 0x2c7f, 0x1078, 0x3571, 0x0078, 0x2c85, 0xa684,
- 0x4000, 0x00c0, 0x2c85, 0x1078, 0x3502, 0x2d00, 0x703e, 0x8207,
- 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3a00, 0x2048,
- 0x0078, 0x1efb, 0x6020, 0xa005, 0x0040, 0x2c9e, 0x8001, 0x6022,
- 0x6008, 0xa085, 0x0008, 0x600a, 0x7010, 0x6026, 0x007c, 0xa006,
- 0x1078, 0x32f5, 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040,
- 0x681f, 0x0100, 0x7000, 0xa084, 0x0007, 0x0079, 0x2caf, 0x2cb7,
- 0x2cb9, 0x2cb9, 0x2cc5, 0x2cc1, 0x2cb7, 0x2cc1, 0x2cb7, 0x1078,
- 0x1eac, 0x1078, 0x2cd0, 0x1078, 0x2cc9, 0x1078, 0x1a26, 0x0078,
- 0x1f03, 0x70a3, 0x0000, 0x0078, 0x1f03, 0x681b, 0x0000, 0x0078,
- 0x2871, 0x6800, 0xa005, 0x00c0, 0x2cce, 0x6002, 0x6006, 0x007c,
- 0x6010, 0xa005, 0x0040, 0x2cd9, 0x8001, 0x00d0, 0x2cd9, 0x1078,
- 0x1eac, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x007c, 0x6018,
- 0xa005, 0x0040, 0x2ce5, 0x8001, 0x601a, 0x007c, 0x1078, 0x316a,
- 0x6818, 0xa084, 0x8000, 0x0040, 0x2cef, 0x681b, 0x0018, 0x0078,
- 0x2d26, 0x1078, 0x316a, 0x6818, 0xa084, 0x8000, 0x0040, 0x2cfa,
- 0x681b, 0x0019, 0x0078, 0x2d26, 0x1078, 0x316a, 0x6818, 0xa084,
- 0x8000, 0x0040, 0x2d05, 0x681b, 0x001a, 0x0078, 0x2d26, 0x1078,
- 0x316a, 0x681b, 0x0003, 0x0078, 0x2d26, 0x71b8, 0xa18c, 0x00ff,
- 0xa1e8, 0x4280, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, 0x2d1a,
- 0x0078, 0x1f03, 0x6814, 0x72b4, 0xa206, 0x0040, 0x2d22, 0x6800,
- 0x0078, 0x2d13, 0x6800, 0x200a, 0x681b, 0x0005, 0x681f, 0x0000,
- 0x6823, 0x0020, 0x1078, 0x2cd0, 0x1078, 0x2cc9, 0x1078, 0x1a26,
- 0x0078, 0x1f03, 0xa282, 0x0003, 0x00c0, 0x2f69, 0x7da8, 0xa5ac,
- 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920, 0xa18d, 0x0080, 0x6922,
- 0xa184, 0x0100, 0x0040, 0x2d92, 0xa18c, 0xfeff, 0x6922, 0xa6b4,
- 0x00ff, 0x0040, 0x2d7c, 0xa682, 0x000c, 0x0048, 0x2d53, 0x0040,
- 0x2d53, 0x2031, 0x000c, 0x852b, 0x852b, 0x1078, 0x3018, 0x0040,
- 0x2d5d, 0x1078, 0x2e4a, 0x0078, 0x2d85, 0x1078, 0x2fd3, 0x0c7e,
- 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x2e6e, 0x0c7f,
- 0x6920, 0xa18d, 0x0100, 0x6922, 0x7e58, 0xa6b5, 0x0004, 0x7e5a,
- 0xa684, 0x0400, 0x00c0, 0x2d78, 0x781b, 0x0053, 0x0078, 0x1efb,
- 0x781b, 0x0067, 0x0078, 0x1efb, 0x0c7e, 0x2960, 0x6004, 0xa084,
- 0xfff5, 0x6006, 0x1078, 0x2e6e, 0x0c7f, 0x7e58, 0xa684, 0x0400,
- 0x00c0, 0x2d8e, 0x781b, 0x0056, 0x0078, 0x1efb, 0x781b, 0x0068,
- 0x0078, 0x1efb, 0x0c7e, 0x7048, 0x2060, 0x6100, 0xa18c, 0x1000,
- 0x0040, 0x2dd2, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c,
- 0x0048, 0x2da6, 0x0040, 0x2da6, 0x2011, 0x000c, 0x2600, 0xa202,
- 0x00c8, 0x2dab, 0x2230, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086,
- 0x0028, 0x00c0, 0x2dbb, 0xa282, 0x0019, 0x00c8, 0x2dc1, 0x2011,
- 0x0019, 0x0078, 0x2dc1, 0xa282, 0x000c, 0x00c8, 0x2dc1, 0x2011,
- 0x000c, 0x2200, 0xa502, 0x00c8, 0x2dc6, 0x2228, 0x1078, 0x2fd7,
- 0x852b, 0x852b, 0x1078, 0x3018, 0x0040, 0x2dd2, 0x1078, 0x2e4a,
- 0x0078, 0x2dd6, 0x1078, 0x2fd3, 0x1078, 0x2e6e, 0x7858, 0xa085,
- 0x0004, 0x785a, 0x0c7f, 0x781b, 0x0067, 0x0078, 0x1efb, 0x0c7e,
- 0x2960, 0x6000, 0xa084, 0x1000, 0x00c0, 0x2df7, 0x6010, 0xa084,
- 0x000f, 0x00c0, 0x2df1, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x0c7f,
- 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x2e1e, 0x68a0,
- 0xa084, 0x0200, 0x00c0, 0x2df1, 0x6208, 0xa294, 0x00ff, 0x7018,
- 0xa086, 0x0028, 0x00c0, 0x2e0c, 0xa282, 0x0019, 0x00c8, 0x2e12,
- 0x2011, 0x0019, 0x0078, 0x2e12, 0xa282, 0x000c, 0x00c8, 0x2e12,
+ 0x32df, 0xa084, 0x0800, 0x0040, 0x32d9, 0x1078, 0x369b, 0x0078,
+ 0x32df, 0x1078, 0x3697, 0x708b, 0x0000, 0x0078, 0x32df, 0x027e,
+ 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x5280,
+ 0x2060, 0x7056, 0x6000, 0x705a, 0x6004, 0x705e, 0xa684, 0x0060,
+ 0x0040, 0x3337, 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x00c0,
+ 0x3319, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4, 0xb7ff, 0x7e5a,
+ 0xa684, 0x0060, 0xa086, 0x0060, 0x0040, 0x3337, 0x68c0, 0xa005,
+ 0x0040, 0x3312, 0x7003, 0x0003, 0x682b, 0x0000, 0x1078, 0x48e6,
+ 0x0078, 0x3314, 0x1078, 0x48f7, 0xa6b5, 0x2000, 0x7e5a, 0x0078,
+ 0x3337, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040,
+ 0x3337, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xa6b4, 0xbfff,
+ 0x7e5a, 0x007e, 0x68c0, 0xa005, 0x007f, 0x0040, 0x3335, 0x7003,
+ 0x0003, 0x1078, 0x48e6, 0x0078, 0x3337, 0x1078, 0x4942, 0x077f,
+ 0x1078, 0x37bd, 0x2009, 0x0065, 0xa684, 0x0004, 0x0040, 0x3358,
+ 0x78e4, 0xa084, 0x0030, 0x0040, 0x3350, 0x78ec, 0xa084, 0x0003,
+ 0x0040, 0x3350, 0x782b, 0x3008, 0x2009, 0x0065, 0x0078, 0x3358,
+ 0x0f7e, 0x2079, 0x5000, 0x1078, 0x4633, 0x0f7f, 0x0040, 0x2461,
+ 0x791a, 0x2d00, 0x704a, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003,
+ 0x8003, 0xa080, 0x5280, 0x2048, 0x0078, 0x2438, 0x6020, 0xa005,
+ 0x0040, 0x3372, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a,
+ 0x7010, 0x6026, 0x007c, 0xa006, 0x1078, 0x4633, 0x6817, 0x0000,
+ 0x681b, 0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084,
+ 0x0007, 0x0079, 0x3383, 0x2461, 0x338d, 0x338d, 0x33aa, 0x3395,
+ 0x3393, 0x3395, 0x338b, 0x1078, 0x23ca, 0x1078, 0x33b5, 0x1078,
+ 0x33ae, 0x1078, 0x1c53, 0x0078, 0x2461, 0x706c, 0x706f, 0x0000,
+ 0x7093, 0x0000, 0x0079, 0x339c, 0x33a6, 0x33a6, 0x33a4, 0x33a4,
+ 0x33a4, 0x33a6, 0x33a4, 0x33a6, 0x0079, 0x2840, 0x706f, 0x0000,
+ 0x0078, 0x2461, 0x681b, 0x0000, 0x0078, 0x2eed, 0x6800, 0xa005,
+ 0x00c0, 0x33b3, 0x6002, 0x6006, 0x007c, 0x6010, 0xa005, 0x0040,
+ 0x33be, 0x8001, 0x00d0, 0x33be, 0x1078, 0x23ca, 0x6012, 0x6008,
+ 0xa084, 0xffef, 0x600a, 0x007c, 0x6018, 0xa005, 0x0040, 0x33ca,
+ 0x8001, 0x601a, 0x007c, 0x1078, 0x38de, 0x681b, 0x0018, 0x0078,
+ 0x3401, 0x1078, 0x38de, 0x681b, 0x0019, 0x0078, 0x3401, 0x1078,
+ 0x38de, 0x681b, 0x001a, 0x0078, 0x3401, 0x1078, 0x38de, 0x681b,
+ 0x0003, 0x0078, 0x3401, 0x7780, 0x1078, 0x37bd, 0x7184, 0xa18c,
+ 0x00ff, 0xa1e8, 0x7300, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0,
+ 0x33f3, 0x0078, 0x2461, 0x6814, 0x7280, 0xa206, 0x0040, 0x33fb,
+ 0x6800, 0x0078, 0x33ec, 0x6800, 0x200a, 0x681b, 0x0005, 0x708b,
+ 0x0000, 0x1078, 0x33b5, 0x6820, 0xa084, 0x0001, 0x00c0, 0x340a,
+ 0x1078, 0x33ae, 0x1078, 0x33c4, 0x681f, 0x0000, 0x6823, 0x0020,
+ 0x1078, 0x1c53, 0x0078, 0x2461, 0xa282, 0x0003, 0x00c0, 0x366b,
+ 0x7da8, 0xa5ac, 0x00ff, 0x7ca8, 0xa4a4, 0x00ff, 0x6920, 0xa18d,
+ 0x0080, 0x6922, 0xa184, 0x0100, 0x0040, 0x3478, 0xa18c, 0xfeff,
+ 0x6922, 0xa4a4, 0x00ff, 0x0040, 0x3462, 0xa482, 0x000c, 0x0048,
+ 0x3435, 0x0040, 0x3435, 0x2021, 0x000c, 0x852b, 0x852b, 0x1078,
+ 0x372e, 0x0040, 0x343f, 0x1078, 0x3531, 0x0078, 0x346b, 0x1078,
+ 0x36e9, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078,
+ 0x3558, 0x0c7f, 0x6920, 0xa18d, 0x0100, 0x6922, 0x7e58, 0xa6b5,
+ 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x345c, 0x782b, 0x3008,
+ 0x781b, 0x0056, 0x0078, 0x2438, 0x782b, 0x3008, 0x781b, 0x0065,
+ 0x0078, 0x2438, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006,
+ 0x1078, 0x3558, 0x0c7f, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x3474,
+ 0x781b, 0x0058, 0x0078, 0x2438, 0x781b, 0x0065, 0x0078, 0x2438,
+ 0x0c7e, 0x7054, 0x2060, 0x6100, 0xa18c, 0x1000, 0x0040, 0x34b8,
+ 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048, 0x348c,
+ 0x0040, 0x348c, 0x2011, 0x000c, 0x2400, 0xa202, 0x00c8, 0x3491,
+ 0x2220, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0,
+ 0x34a1, 0xa282, 0x0019, 0x00c8, 0x34a7, 0x2011, 0x0019, 0x0078,
+ 0x34a7, 0xa282, 0x000c, 0x00c8, 0x34a7, 0x2011, 0x000c, 0x2200,
+ 0xa502, 0x00c8, 0x34ac, 0x2228, 0x1078, 0x36ed, 0x852b, 0x852b,
+ 0x1078, 0x372e, 0x0040, 0x34b8, 0x1078, 0x3531, 0x0078, 0x34bc,
+ 0x1078, 0x36e9, 0x1078, 0x3558, 0x7858, 0xa085, 0x0004, 0x785a,
+ 0x0c7f, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x0c7e,
+ 0x2960, 0x6000, 0xa084, 0x1000, 0x00c0, 0x34df, 0x6010, 0xa084,
+ 0x000f, 0x00c0, 0x34d9, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x0c7f,
+ 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3506, 0x68a0,
+ 0xa084, 0x0200, 0x00c0, 0x34d9, 0x6208, 0xa294, 0x00ff, 0x7018,
+ 0xa086, 0x0028, 0x00c0, 0x34f4, 0xa282, 0x0019, 0x00c8, 0x34fa,
+ 0x2011, 0x0019, 0x0078, 0x34fa, 0xa282, 0x000c, 0x00c8, 0x34fa,
0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c,
- 0x0048, 0x2e1e, 0x0040, 0x2e1e, 0x2019, 0x000c, 0x78ab, 0x0001,
+ 0x0048, 0x3506, 0x0040, 0x3506, 0x2019, 0x000c, 0x78ab, 0x0001,
0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005,
0x6820, 0xa085, 0x0100, 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x2960,
- 0x6104, 0xa18c, 0xfff5, 0x6106, 0x2011, 0x0032, 0x2019, 0x0000,
- 0x0078, 0x2e3a, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001,
- 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xa085, 0x0100, 0x6822,
- 0x0c7f, 0x007c, 0x0c7e, 0x7148, 0x2160, 0x2008, 0xa084, 0xfff0,
- 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084,
- 0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6, 0x6016, 0x788a, 0xa6b4,
- 0x000f, 0x8637, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa605, 0x600e,
- 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x007c, 0x0c7e, 0x7048,
- 0x2060, 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012,
- 0x7884, 0xa084, 0xfff0, 0x7886, 0x0c7f, 0x007c, 0xa282, 0x0002,
- 0x00c0, 0x2f69, 0x7aa8, 0x6920, 0xa18d, 0x0080, 0x6922, 0xa184,
- 0x0200, 0x0040, 0x2ec3, 0xa18c, 0xfdff, 0x6922, 0xa294, 0x00ff,
- 0xa282, 0x0002, 0x00c8, 0x2f69, 0x1078, 0x2f0a, 0x1078, 0x2e6e,
- 0xa980, 0x0001, 0x200c, 0x1078, 0x3095, 0x1078, 0x2ddf, 0x88ff,
- 0x0040, 0x2eb6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5,
- 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2eb2, 0x781b, 0x0053,
- 0x0078, 0x1efb, 0x781b, 0x0067, 0x0078, 0x1efb, 0x7e58, 0xa684,
- 0x0400, 0x00c0, 0x2ebf, 0x781b, 0x0056, 0x0078, 0x1efb, 0x781b,
- 0x0068, 0x0078, 0x1efb, 0xa282, 0x0002, 0x00c8, 0x2ecb, 0xa284,
- 0x0001, 0x0040, 0x2ed5, 0x7148, 0xa188, 0x0000, 0x210c, 0xa18c,
- 0x2000, 0x00c0, 0x2ed5, 0x2011, 0x0000, 0x1078, 0x2fc5, 0x1078,
- 0x2f0a, 0x1078, 0x2e6e, 0x7858, 0xa085, 0x0004, 0x785a, 0x781b,
- 0x0067, 0x0078, 0x1efb, 0x0c7e, 0x027e, 0x2960, 0x6000, 0x2011,
- 0x0001, 0xa084, 0x2000, 0x00c0, 0x2efa, 0x6014, 0xa084, 0x0040,
- 0x00c0, 0x2ef8, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078, 0x2f07,
- 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003,
- 0x7aaa, 0xa8c0, 0x0004, 0x6820, 0xa085, 0x0200, 0x6822, 0x027f,
- 0x0c7f, 0x007c, 0x0c7e, 0x7048, 0x2060, 0x82ff, 0x0040, 0x2f12,
- 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084,
- 0xffbf, 0xa205, 0x78a6, 0x6016, 0x788a, 0x6004, 0xa084, 0xffef,
- 0x6006, 0x0c7f, 0x007c, 0xa684, 0x0020, 0x0040, 0x2f65, 0x7888,
- 0xa084, 0x0040, 0x0040, 0x2f65, 0x7bb8, 0xa384, 0x003f, 0x831b,
- 0x00c8, 0x2f33, 0x8000, 0xa005, 0x0040, 0x2f4c, 0x831b, 0x00c8,
- 0x2f3c, 0x8001, 0x0040, 0x2f61, 0xa684, 0x4000, 0x0040, 0x2f4c,
- 0x78b8, 0x801b, 0x00c8, 0x2f45, 0x8000, 0xa084, 0x003f, 0x00c0,
- 0x2f61, 0xa6b4, 0xbfff, 0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001,
- 0xa108, 0x00c8, 0x2f55, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6,
- 0x7ade, 0x1078, 0x362f, 0x781b, 0x0065, 0x1078, 0x3502, 0x0078,
- 0x1efb, 0x781b, 0x0065, 0x0078, 0x1efb, 0x781b, 0x0068, 0x0078,
- 0x1efb, 0x1078, 0x2f91, 0x781b, 0x0067, 0x0078, 0x1efb, 0x1078,
- 0x2f7d, 0x781b, 0x0067, 0x0078, 0x1efb, 0x6827, 0x0002, 0x1078,
- 0x2f85, 0x781b, 0x0067, 0x0078, 0x1efb, 0x2001, 0x0005, 0x0078,
- 0x2f93, 0x2001, 0x000c, 0x0078, 0x2f93, 0x2001, 0x0006, 0x0078,
- 0x2f93, 0x2001, 0x000d, 0x0078, 0x2f93, 0x2001, 0x0009, 0x0078,
- 0x2f93, 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa, 0xa6b5, 0x0008,
- 0x7e5a, 0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b,
- 0x8703, 0xa0e0, 0x3a00, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184,
- 0x000f, 0x0040, 0x2fb3, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004,
- 0xa085, 0x0008, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184,
- 0x0040, 0x0040, 0x2fc3, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004,
- 0xa085, 0x0010, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab,
- 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060,
- 0x78ab, 0x0004, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b,
- 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa,
- 0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007,
- 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4,
- 0xa18c, 0xfff0, 0x2001, 0x3946, 0x2004, 0xa082, 0x0028, 0x0040,
- 0x3001, 0x2021, 0x307c, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078,
- 0x3007, 0x2021, 0x3088, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011,
- 0x0064, 0x2404, 0xa084, 0xfff0, 0xa106, 0x0040, 0x3016, 0x8420,
- 0x2300, 0xa210, 0x0070, 0x3016, 0x0078, 0x3009, 0x157f, 0x007c,
- 0x157e, 0x2011, 0x3946, 0x2214, 0xa282, 0x0032, 0x0048, 0x302c,
- 0x0040, 0x3030, 0x2021, 0x306e, 0x2019, 0x0011, 0x20a9, 0x000e,
- 0x2011, 0x0032, 0x0078, 0x3042, 0xa282, 0x0028, 0x0040, 0x303a,
- 0x2021, 0x307c, 0x2019, 0x0014, 0x20a9, 0x000c, 0x2011, 0x0064,
- 0x0078, 0x3042, 0x2021, 0x3088, 0x2019, 0x0019, 0x20a9, 0x000d,
- 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x3052, 0x0048, 0x3052,
- 0x8420, 0x2300, 0xa210, 0x0070, 0x304f, 0x0078, 0x3042, 0x157f,
- 0xa006, 0x007c, 0x157f, 0x7a08, 0xa582, 0x0064, 0x00c8, 0x305d,
- 0xa285, 0x0040, 0x780a, 0x0078, 0x305d, 0x78ec, 0xa084, 0x0300,
- 0x0040, 0x306b, 0x2404, 0xa09e, 0x2002, 0x00c0, 0x306b, 0x2001,
- 0x2101, 0x0078, 0x306c, 0x2404, 0xa015, 0x007c, 0x2002, 0x3002,
- 0x3202, 0x4203, 0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806,
- 0x7a06, 0x0a07, 0x0c07, 0x0e07, 0x3202, 0x4202, 0x5202, 0x6202,
- 0x7202, 0x6605, 0x7605, 0x7805, 0x7a05, 0x7c05, 0x7e05, 0x7f05,
- 0x2202, 0x3202, 0x4202, 0x5202, 0x5404, 0x6404, 0x7404, 0x7604,
- 0x7804, 0x7a04, 0x7c04, 0x7e04, 0x7f04, 0x789b, 0x0010, 0xa046,
- 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, 0x0007, 0x8003, 0x8003,
- 0x8003, 0x8003, 0xa105, 0xa0e0, 0x3a80, 0x007c, 0x79d8, 0x7adc,
- 0x78d0, 0x801b, 0x00c8, 0x30ad, 0x8000, 0xa084, 0x003f, 0xa108,
- 0xa291, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3940,
- 0x2091, 0x8000, 0x2104, 0x0079, 0x30bd, 0x30e3, 0x30c7, 0x30c7,
- 0x30c7, 0x30c7, 0x30c7, 0x30c7, 0x30c5, 0x1078, 0x1eac, 0x784b,
- 0x0004, 0x68b4, 0xa085, 0x4000, 0x68b6, 0x7858, 0xa085, 0x4000,
- 0x785a, 0x7830, 0xa084, 0x0080, 0x00c0, 0x30e3, 0x0018, 0x30e3,
- 0x681c, 0xa084, 0x0020, 0x00c0, 0x30e1, 0x781b, 0x00df, 0x0078,
- 0x30e3, 0x781b, 0x00e6, 0x2091, 0x8001, 0x0f7f, 0x007c, 0x0c7e,
+ 0xa18c, 0xfff5, 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078,
+ 0x3521, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa,
+ 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xa085, 0x0100, 0x6822, 0x0c7f,
+ 0x007c, 0x0c7e, 0x7154, 0x2160, 0x1078, 0x3538, 0x0c7f, 0x007c,
+ 0x2008, 0xa084, 0xfff0, 0xa425, 0x7c86, 0x6018, 0x789a, 0x7cae,
+ 0x6412, 0x78a4, 0xa084, 0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6,
+ 0x6016, 0x788a, 0xa4a4, 0x000f, 0x8427, 0x8204, 0x8004, 0xa084,
+ 0x00ff, 0xa405, 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006, 0x007c,
+ 0x0c7e, 0x7054, 0x2060, 0x1078, 0x355f, 0x0c7f, 0x007c, 0x6018,
+ 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084,
+ 0xfff0, 0x7886, 0x007c, 0xa282, 0x0002, 0x00c0, 0x366b, 0x7aa8,
+ 0x6920, 0xa18d, 0x0080, 0x6922, 0xa184, 0x0200, 0x0040, 0x35b4,
+ 0xa18c, 0xfdff, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8,
+ 0x366b, 0x1078, 0x35fd, 0x1078, 0x3558, 0xa980, 0x0001, 0x200c,
+ 0x1078, 0x37b9, 0x1078, 0x34c7, 0x88ff, 0x0040, 0x35a7, 0x789b,
+ 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684,
+ 0x0400, 0x00c0, 0x35a1, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078,
+ 0x2438, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x7e58,
+ 0xa684, 0x0400, 0x00c0, 0x35b0, 0x781b, 0x0058, 0x0078, 0x2438,
+ 0x781b, 0x0065, 0x0078, 0x2438, 0xa282, 0x0002, 0x00c8, 0x35bc,
+ 0xa284, 0x0001, 0x0040, 0x35c6, 0x7154, 0xa188, 0x0000, 0x210c,
+ 0xa18c, 0x2000, 0x00c0, 0x35c6, 0x2011, 0x0000, 0x1078, 0x36db,
+ 0x1078, 0x35fd, 0x1078, 0x3558, 0x7858, 0xa085, 0x0004, 0x785a,
+ 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x0c7e, 0x027e,
+ 0x2960, 0x6000, 0x2011, 0x0001, 0xa084, 0x2000, 0x00c0, 0x35ed,
+ 0x6014, 0xa084, 0x0040, 0x00c0, 0x35eb, 0xa18c, 0xffef, 0x6106,
+ 0xa006, 0x0078, 0x35fa, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
+ 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x6820, 0xa085,
+ 0x0200, 0x6822, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7054, 0x2060,
+ 0x1078, 0x3604, 0x0c7f, 0x007c, 0x82ff, 0x0040, 0x3609, 0x2011,
+ 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084, 0xffbf,
+ 0xa205, 0x78a6, 0x788a, 0x6016, 0x6004, 0xa084, 0xffef, 0x6006,
+ 0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x3622, 0x007f,
+ 0x0078, 0x3625, 0x007f, 0x0078, 0x3667, 0xa684, 0x0020, 0x0040,
+ 0x3667, 0x7888, 0xa084, 0x0040, 0x0040, 0x3667, 0x7bb8, 0xa384,
+ 0x003f, 0x831b, 0x00c8, 0x3635, 0x8000, 0xa005, 0x0040, 0x364b,
+ 0x831b, 0x00c8, 0x363e, 0x8001, 0x0040, 0x3663, 0xa684, 0x4000,
+ 0x0040, 0x364b, 0x78b8, 0x801b, 0x00c8, 0x3647, 0x8000, 0xa084,
+ 0x003f, 0x00c0, 0x3663, 0xa6b4, 0xbfff, 0x7e5a, 0x79d8, 0x7adc,
+ 0x2001, 0x0001, 0xa108, 0x00c8, 0x3657, 0xa291, 0x0000, 0x79d2,
+ 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x49ed, 0x781b, 0x0064, 0x1078,
+ 0x4872, 0x0078, 0x2438, 0x781b, 0x0064, 0x0078, 0x2438, 0x781b,
+ 0x0065, 0x0078, 0x2438, 0x1078, 0x36a3, 0x782b, 0x3008, 0x781b,
+ 0x0065, 0x0078, 0x2438, 0x1078, 0x368f, 0x782b, 0x3008, 0x781b,
+ 0x0065, 0x0078, 0x2438, 0x6827, 0x0002, 0x1078, 0x3697, 0x78e4,
+ 0xa084, 0x0030, 0x0040, 0x2461, 0x78ec, 0xa084, 0x0003, 0x0040,
+ 0x2461, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x2001,
+ 0x0005, 0x0078, 0x36a5, 0x2001, 0x000c, 0x0078, 0x36a5, 0x2001,
+ 0x0006, 0x0078, 0x36a5, 0x2001, 0x000d, 0x0078, 0x36a5, 0x2001,
+ 0x0009, 0x0078, 0x36a5, 0x2001, 0x0007, 0x789b, 0x0010, 0x78aa,
+ 0x789b, 0x0060, 0x78ab, 0x0001, 0xa6b5, 0x0004, 0x7e5a, 0x007c,
+ 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0xa0e0,
+ 0x5280, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f, 0x0040,
+ 0x36c9, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085, 0x0008,
+ 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040, 0x0040,
+ 0x36d9, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085, 0x0010,
+ 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab,
+ 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, 0x0004,
+ 0x007c, 0x2021, 0x0000, 0x2029, 0x0032, 0x789b, 0x0010, 0x78ab,
+ 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7caa, 0x789b,
+ 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007, 0xa084, 0x00ff,
+ 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, 0xfff0,
+ 0x2001, 0x5046, 0x2004, 0xa082, 0x0028, 0x0040, 0x3717, 0x2021,
+ 0x37a0, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x371d, 0x2021,
+ 0x37ac, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2404,
+ 0xa084, 0xfff0, 0xa106, 0x0040, 0x372c, 0x8420, 0x2300, 0xa210,
+ 0x0070, 0x372c, 0x0078, 0x371f, 0x157f, 0x007c, 0x157e, 0x2009,
+ 0x5046, 0x210c, 0xa182, 0x0032, 0x0048, 0x3742, 0x0040, 0x3746,
+ 0x2009, 0x3792, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032,
+ 0x0078, 0x3758, 0xa182, 0x0028, 0x0040, 0x3750, 0x2009, 0x37a0,
+ 0x2019, 0x0014, 0x20a9, 0x000c, 0x2011, 0x0064, 0x0078, 0x3758,
+ 0x2009, 0x37ac, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064,
+ 0x2200, 0xa502, 0x0040, 0x3768, 0x0048, 0x3768, 0x8108, 0x2300,
+ 0xa210, 0x0070, 0x3765, 0x0078, 0x3758, 0x157f, 0xa006, 0x007c,
+ 0x157f, 0xa582, 0x0064, 0x00c8, 0x3777, 0x7808, 0xa085, 0x0070,
+ 0x780a, 0x7044, 0xa085, 0x0070, 0x7046, 0x0078, 0x3777, 0x78ec,
+ 0xa084, 0x0300, 0x0040, 0x377f, 0x2104, 0x0078, 0x3790, 0x2104,
+ 0xa09e, 0x1102, 0x00c0, 0x3790, 0x2001, 0x04fd, 0x2004, 0xa082,
+ 0x0005, 0x0048, 0x378f, 0x2001, 0x1201, 0x0078, 0x3790, 0x2104,
+ 0xa005, 0x007c, 0x1102, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404,
+ 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07, 0x0e07,
+ 0x3202, 0x4202, 0x5202, 0x6202, 0x7202, 0x6605, 0x7605, 0x7805,
+ 0x7a05, 0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202, 0x4202, 0x5202,
+ 0x5404, 0x6404, 0x7404, 0x7604, 0x7804, 0x7a04, 0x7c04, 0x7e04,
+ 0x7f04, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00, 0x800b,
+ 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e0,
+ 0x5300, 0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b, 0x00c8, 0x37d1,
+ 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x007c, 0x0f7e,
+ 0x2079, 0x0100, 0x2009, 0x5040, 0x2091, 0x8000, 0x2104, 0x0079,
+ 0x37e1, 0x3817, 0x37eb, 0x37eb, 0x37eb, 0x37eb, 0x37eb, 0x37eb,
+ 0x381b, 0x1078, 0x23ca, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
+ 0x00c0, 0x37ed, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0,
+ 0x37f4, 0x68b4, 0xa085, 0x4000, 0x68b6, 0x7858, 0xa085, 0x4000,
+ 0x785a, 0x7830, 0xa084, 0x0080, 0x00c0, 0x3817, 0x0018, 0x3817,
+ 0x681c, 0xa084, 0x0020, 0x00c0, 0x3815, 0x0e7e, 0x2071, 0x5040,
+ 0x1078, 0x3868, 0x0e7f, 0x0078, 0x3817, 0x781b, 0x00d2, 0x2091,
+ 0x8001, 0x0f7f, 0x007c, 0x1078, 0x3a42, 0x0078, 0x3817, 0x0c7e,
0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e0,
- 0x3a00, 0x6004, 0xa084, 0x000a, 0x00c0, 0x311a, 0x6108, 0xa194,
- 0xff00, 0x0040, 0x311a, 0xa18c, 0x00ff, 0x2001, 0x0019, 0xa106,
- 0x0040, 0x3109, 0x2001, 0x0032, 0xa106, 0x0040, 0x310d, 0x0078,
- 0x3111, 0x2009, 0x0020, 0x0078, 0x3113, 0x2009, 0x003f, 0x0078,
- 0x3113, 0x2011, 0x0000, 0x2100, 0xa205, 0x600a, 0x6004, 0xa085,
- 0x0002, 0x6006, 0x0c7f, 0x007c, 0x781b, 0x0068, 0x0078, 0x1efb,
- 0x781b, 0x0067, 0x0078, 0x1efb, 0x781b, 0x0056, 0x0078, 0x1efb,
- 0x781b, 0x0053, 0x0078, 0x1efb, 0x781b, 0x00df, 0x0078, 0x1efb,
- 0x781b, 0x00de, 0x0078, 0x1efb, 0x781b, 0x00e6, 0x0078, 0x1efb,
- 0x781b, 0x00e5, 0x0078, 0x1efb, 0x781b, 0x009d, 0x0078, 0x1efb,
- 0x781b, 0x009c, 0x0078, 0x1efb, 0x6818, 0xa084, 0x8000, 0x0040,
- 0x314b, 0x681b, 0x001d, 0x70a3, 0x0001, 0x781b, 0x0047, 0x0078,
- 0x1efb, 0x007e, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3168, 0x7808,
- 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec,
- 0xa084, 0x0021, 0x0040, 0x3168, 0x7808, 0xa085, 0x0002, 0x780a,
- 0x007f, 0x007c, 0x7808, 0xa085, 0x0002, 0x780a, 0x007c, 0x7830,
- 0xa084, 0x0040, 0x00c0, 0x316f, 0x0098, 0x3178, 0x78ac, 0x007c,
+ 0x5280, 0x6004, 0xa084, 0x000a, 0x00c0, 0x3852, 0x6108, 0xa194,
+ 0xff00, 0x0040, 0x3852, 0xa18c, 0x00ff, 0x2001, 0x0019, 0xa106,
+ 0x0040, 0x3841, 0x2001, 0x0032, 0xa106, 0x0040, 0x3845, 0x0078,
+ 0x3849, 0x2009, 0x0020, 0x0078, 0x384b, 0x2009, 0x003f, 0x0078,
+ 0x384b, 0x2011, 0x0000, 0x2100, 0xa205, 0x600a, 0x6004, 0xa085,
+ 0x0002, 0x6006, 0x0c7f, 0x007c, 0x781b, 0x0065, 0x0078, 0x2438,
+ 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2438, 0x781b, 0x0058,
+ 0x0078, 0x2438, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2438,
+ 0x2009, 0x5020, 0x210c, 0xa186, 0x0000, 0x0040, 0x387c, 0xa186,
+ 0x0001, 0x0040, 0x387f, 0x2009, 0x5038, 0x200b, 0x000b, 0x706f,
+ 0x0001, 0x781b, 0x0048, 0x007c, 0x781b, 0x00cc, 0x007c, 0x2009,
+ 0x5038, 0x200b, 0x000a, 0x007c, 0x2009, 0x5020, 0x210c, 0xa186,
+ 0x0000, 0x0040, 0x389f, 0xa186, 0x0001, 0x0040, 0x3899, 0x2009,
+ 0x5038, 0x200b, 0x000b, 0x706f, 0x0001, 0x781b, 0x0048, 0x0078,
+ 0x2438, 0x2009, 0x5038, 0x200b, 0x000a, 0x0078, 0x2438, 0x782b,
+ 0x3008, 0x781b, 0x00cc, 0x0078, 0x2438, 0x781b, 0x00d2, 0x0078,
+ 0x2438, 0x782b, 0x3008, 0x781b, 0x00d2, 0x0078, 0x2438, 0x781b,
+ 0x0093, 0x0078, 0x2438, 0x782b, 0x3008, 0x781b, 0x0093, 0x0078,
+ 0x2438, 0x6818, 0xa084, 0x8000, 0x0040, 0x38c0, 0x681b, 0x001d,
+ 0x706f, 0x0001, 0x781b, 0x0048, 0x0078, 0x2438, 0x007e, 0x7830,
+ 0xa084, 0x00c0, 0x00c0, 0x38dc, 0x7808, 0xa084, 0xfffc, 0x780a,
+ 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040,
+ 0x38dc, 0x7044, 0x780a, 0xa005, 0x007f, 0x007c, 0x7044, 0xa085,
+ 0x0002, 0x7046, 0x780a, 0x007c, 0x007e, 0x7830, 0xa084, 0x0040,
+ 0x00c0, 0x38e5, 0x0098, 0x38f0, 0x007f, 0x789a, 0x78ac, 0x007c,
0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005,
- 0x78ec, 0xa084, 0x0021, 0x0040, 0x3187, 0x0098, 0x3185, 0x78ac,
- 0x007e, 0x7808, 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0xa784,
- 0x0070, 0x0040, 0x319b, 0x0c7e, 0x2d60, 0x2f68, 0x1078, 0x1e57,
- 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040, 0x31a8, 0x784b,
- 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x1f03, 0x0078, 0x311c,
- 0xa784, 0x0004, 0x0040, 0x31db, 0x78b8, 0xa084, 0x4001, 0x0040,
- 0x31db, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x1f03,
- 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0, 0x31db, 0x78c0,
- 0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00e6, 0x0078, 0x1efb,
- 0x784b, 0x0008, 0x6818, 0xa084, 0x8000, 0x0040, 0x31d7, 0x681b,
- 0x0015, 0xa684, 0x4000, 0x0040, 0x31d7, 0x681b, 0x0007, 0x781b,
- 0x00df, 0x0078, 0x1efb, 0x681b, 0x0003, 0x7858, 0xa084, 0x3f00,
- 0x681e, 0x682f, 0x0000, 0x6833, 0x0000, 0x784b, 0x0008, 0x78e4,
- 0xa005, 0x00d0, 0x238a, 0xa084, 0x0020, 0x0040, 0x238a, 0x0018,
- 0x238a, 0x0078, 0x2f6f, 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003,
- 0x8003, 0x8003, 0xa080, 0x3a00, 0x2060, 0x2048, 0x704a, 0x6000,
- 0x704e, 0x6004, 0x7052, 0x2a60, 0x007c, 0x0020, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0062,
- 0x0009, 0x0014, 0x0014, 0x9848, 0x0014, 0x0014, 0x98f9, 0x98e9,
- 0x0014, 0x0014, 0x0080, 0x00c0, 0x0100, 0x0402, 0x2008, 0xf880,
- 0x0018, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014, 0xa200, 0x8838,
- 0x3806, 0x8839, 0x28c2, 0x9cc2, 0xa805, 0x0864, 0xa83d, 0x3008,
- 0x28c1, 0x9cc2, 0xa201, 0x300c, 0x2847, 0x8161, 0x846a, 0x8000,
- 0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2, 0x9c9f, 0xa8f3, 0x0864,
- 0xa82b, 0x300c, 0xa801, 0x3008, 0x28e1, 0x9c9f, 0x280d, 0xa204,
- 0x64c0, 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677,
- 0xa80f, 0x786e, 0x883e, 0xa80c, 0x282b, 0xa205, 0x64a0, 0x67a0,
- 0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, 0xa801, 0x883e,
- 0x206b, 0x28c1, 0x9cc2, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8dc,
- 0xa207, 0x2901, 0xa80a, 0x0014, 0xa203, 0x8000, 0x85a4, 0x1872,
- 0x879a, 0x883c, 0x1fe2, 0xf601, 0xa208, 0x856e, 0x866f, 0x0704,
- 0x3008, 0x9c9f, 0x0014, 0xa202, 0x8000, 0x85a4, 0x3009, 0x84a8,
- 0x19e2, 0xf848, 0x8174, 0x86eb, 0x85eb, 0x872e, 0x87a9, 0x883f,
- 0x08e6, 0xa8f1, 0xf861, 0xa8e8, 0xf801, 0x0014, 0xf881, 0x0016,
- 0x85b2, 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532, 0xf221,
- 0x0014, 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0xa206, 0x6865,
- 0x817e, 0x842a, 0x1dc1, 0x8823, 0x0016, 0x6042, 0x8008, 0xa8fa,
- 0x8000, 0x84a4, 0x8160, 0x842a, 0xf021, 0x3008, 0x84a8, 0x11d6,
- 0x7042, 0x20dd, 0x0011, 0x20d4, 0x8822, 0x0016, 0x8000, 0x2848,
- 0x1011, 0xa8fc, 0x3008, 0x8000, 0xa000, 0x2802, 0x1011, 0xa8fd,
- 0xa883, 0x3008, 0x283d, 0x1011, 0xa8fd, 0xa209, 0x0017, 0x300c,
- 0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014, 0xd301, 0x0014, 0x26e0,
- 0x873a, 0xfaa2, 0x19f2, 0x1fe2, 0x0014, 0xa20b, 0x0014, 0xa20d,
- 0x3806, 0x0210, 0x9ccc, 0x0704, 0x0000, 0x127e, 0x2091, 0x2200,
- 0x2049, 0x32f5, 0x7000, 0x7204, 0xa205, 0x720c, 0xa215, 0x7008,
- 0xa084, 0xfff7, 0xa205, 0x0040, 0x3307, 0x1078, 0x3380, 0x127f,
- 0x2000, 0x007c, 0x6428, 0x84ff, 0x0040, 0x3336, 0x2c70, 0x7004,
- 0xa0bc, 0x000f, 0xa7b8, 0x3346, 0x273c, 0x87fb, 0x00c0, 0x3324,
- 0x0048, 0x331c, 0x1078, 0x1eac, 0x609c, 0xa075, 0x0040, 0x3336,
- 0x0078, 0x330f, 0x2039, 0x333b, 0x2704, 0xae68, 0x6808, 0xa630,
- 0x680c, 0xa529, 0x8421, 0x0040, 0x3336, 0x8738, 0x2704, 0xa005,
- 0x00c0, 0x3325, 0x709c, 0xa075, 0x00c0, 0x330f, 0x007c, 0x0000,
- 0x0005, 0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000,
- 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x333b,
- 0x3338, 0x0000, 0x0000, 0x8000, 0x0000, 0x333b, 0x0000, 0x3343,
- 0x3340, 0x0000, 0x0000, 0x0000, 0x0000, 0x3343, 0x0000, 0x333e,
- 0x333e, 0x0000, 0x0000, 0x8000, 0x0000, 0x333e, 0x0000, 0x3344,
- 0x3344, 0x0000, 0x0000, 0x0000, 0x0000, 0x3344, 0x127e, 0x2091,
- 0x2200, 0x2079, 0x3900, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007,
- 0x0002, 0x7003, 0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007,
- 0x0002, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c,
- 0x2049, 0x3380, 0x2019, 0x0000, 0x7004, 0x8004, 0x00c8, 0x33b2,
- 0x7007, 0x0012, 0x7108, 0x7008, 0xa106, 0x00c0, 0x338a, 0xa184,
- 0x01e0, 0x0040, 0x3395, 0x1078, 0x1eac, 0xa184, 0x4000, 0x00c0,
- 0x338a, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0040, 0x33a7, 0xa386,
- 0x0008, 0x0040, 0x33b2, 0xa386, 0x200c, 0x00c0, 0x338a, 0x7200,
- 0x8204, 0x0048, 0x33b2, 0x730c, 0xa384, 0x00ff, 0x0040, 0x33b2,
- 0x1078, 0x1eac, 0x7007, 0x0012, 0x7000, 0xa084, 0x0001, 0x00c0,
- 0x33c3, 0x7310, 0x7014, 0xa305, 0x0040, 0x33c3, 0x700c, 0xa084,
- 0x00ff, 0x00c0, 0x3380, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004,
- 0xa084, 0x0008, 0x00c0, 0x33c7, 0x7007, 0x0012, 0x7108, 0x8103,
- 0x0048, 0x33cc, 0x7003, 0x0000, 0x2049, 0x0000, 0x007c, 0x107e,
- 0x007e, 0x127e, 0x157e, 0x2091, 0x2200, 0x7108, 0x1078, 0x33e7,
- 0x157f, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7204,
- 0x7500, 0x730c, 0xa384, 0x0300, 0x00c0, 0x3426, 0xa184, 0x0060,
- 0x00c0, 0x3442, 0x7008, 0x7108, 0xa106, 0x00c0, 0x33f2, 0xa184,
- 0x01e0, 0x00c0, 0x3442, 0xa184, 0x4000, 0x00c0, 0x33f2, 0xa986,
- 0x362f, 0x00c0, 0x341a, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0040,
- 0x3411, 0xa386, 0x0008, 0x0040, 0x341a, 0xa386, 0x200c, 0x00c0,
- 0x33f2, 0x7200, 0x8204, 0x0048, 0x341a, 0x730c, 0xa384, 0x00ff,
- 0x00c0, 0x3426, 0xa184, 0x0007, 0x0079, 0x341e, 0x3428, 0x3436,
- 0x3426, 0x3436, 0x3426, 0x348f, 0x3426, 0x348d, 0x1078, 0x1eac,
- 0x7007, 0x0002, 0x8aff, 0x00c0, 0x3431, 0x2049, 0x0000, 0x0078,
- 0x3435, 0x1078, 0x3606, 0x00c0, 0x3431, 0x007c, 0x7007, 0x0002,
- 0x8aff, 0x00c0, 0x343d, 0x0078, 0x3441, 0x1078, 0x3606, 0x00c0,
- 0x343d, 0x007c, 0x7108, 0x7008, 0xa106, 0x00c0, 0x3442, 0xa184,
- 0x4000, 0x00c0, 0x3442, 0x7007, 0x0012, 0x7108, 0x7008, 0xa106,
- 0x00c0, 0x344d, 0xa184, 0x4000, 0x00c0, 0x344d, 0x00e0, 0x3456,
- 0x2091, 0x6000, 0x00e0, 0x345a, 0x2091, 0x6000, 0x7007, 0x0012,
- 0x7007, 0x0008, 0x7004, 0xa084, 0x0008, 0x00c0, 0x3462, 0x7007,
- 0x0012, 0x7108, 0x8103, 0x0048, 0x3467, 0x7003, 0x0000, 0x7000,
- 0xa005, 0x00c0, 0x347b, 0x7004, 0xa005, 0x00c0, 0x347b, 0x700c,
- 0xa005, 0x0040, 0x347d, 0x0078, 0x345e, 0x2049, 0x0000, 0x1078,
- 0x30b3, 0x6818, 0xa084, 0x8000, 0x0040, 0x3488, 0x681b, 0x0002,
- 0x007c, 0x1078, 0x1eac, 0x1078, 0x1eac, 0x1078, 0x34ed, 0x7210,
- 0x7114, 0x700c, 0xa09c, 0x00ff, 0x2800, 0xa300, 0xa211, 0xa189,
- 0x0000, 0x1078, 0x34ed, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200,
- 0xa322, 0x630c, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x34b2,
- 0x00c8, 0x34b2, 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60,
- 0x0078, 0x3499, 0x2b60, 0x8a07, 0x007e, 0x6004, 0xa084, 0x0008,
- 0x0040, 0x34be, 0xa7ba, 0x3340, 0x0078, 0x34c0, 0xa7ba, 0x3338,
- 0x007f, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x1078,
- 0x3380, 0x007c, 0x8738, 0x2704, 0xa005, 0x00c0, 0x34dd, 0x609c,
- 0xa005, 0x0040, 0x34ea, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080,
- 0x3346, 0x203c, 0x87fb, 0x1040, 0x1eac, 0x8a51, 0x0040, 0x34e9,
- 0x7008, 0x7508, 0xa52e, 0x00c0, 0x34e0, 0xa084, 0x0003, 0xa086,
+ 0x78ec, 0xa084, 0x0021, 0x0040, 0x38ff, 0x0098, 0x38fd, 0x007f,
+ 0x789a, 0x78ac, 0x007e, 0x7044, 0x780a, 0x007f, 0x007c, 0x78ec,
+ 0xa084, 0x0002, 0x00c0, 0x461d, 0xa784, 0x007d, 0x00c0, 0x3913,
+ 0x2700, 0x1078, 0x23ca, 0xa784, 0x0001, 0x00c0, 0x2f43, 0xa784,
+ 0x0070, 0x0040, 0x3923, 0x0c7e, 0x2d60, 0x2f68, 0x1078, 0x2375,
+ 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040, 0x3930, 0x784b,
+ 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2461, 0x0078, 0x3854,
+ 0xa784, 0x0004, 0x0040, 0x3963, 0x78b8, 0xa084, 0x4001, 0x0040,
+ 0x3963, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2461,
+ 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0, 0x3963, 0x78c0,
+ 0xa085, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00d2, 0x0078, 0x2438,
+ 0x784b, 0x0008, 0x6818, 0xa084, 0x8000, 0x0040, 0x395f, 0x681b,
+ 0x0015, 0xa684, 0x4000, 0x0040, 0x395f, 0x681b, 0x0007, 0x1078,
+ 0x3868, 0x0078, 0x2438, 0x681b, 0x0003, 0x7858, 0xa084, 0x3f00,
+ 0x681e, 0x682f, 0x0000, 0x6833, 0x0000, 0x784b, 0x0008, 0x78ec,
+ 0xa084, 0x0003, 0x0040, 0x2944, 0x0018, 0x2438, 0x0078, 0x3673,
+ 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080,
+ 0x5280, 0x2060, 0x2048, 0x7056, 0x6000, 0x705a, 0x6004, 0x705e,
+ 0x2a60, 0x007c, 0x0079, 0x398c, 0x3994, 0x3995, 0x3994, 0x3997,
+ 0x3994, 0x3994, 0x3994, 0x399c, 0x007c, 0x1078, 0x33c4, 0x1078,
+ 0x4633, 0x7038, 0x600a, 0x007c, 0x70a0, 0xa005, 0x0040, 0x39a9,
+ 0x2068, 0x1078, 0x1b45, 0x1078, 0x45b5, 0x1078, 0x45bc, 0x70a3,
+ 0x0000, 0x007c, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x5040, 0x7000,
+ 0xa086, 0x0007, 0x00c0, 0x39c0, 0x6110, 0x70bc, 0xa106, 0x00c0,
+ 0x39c0, 0x0e7f, 0x1078, 0x1b52, 0x1078, 0x39c6, 0xa006, 0x007c,
+ 0x2091, 0x8001, 0x0e7f, 0xa085, 0x0001, 0x007c, 0x0f7e, 0x0e7e,
+ 0x2071, 0x5040, 0x0078, 0x21d9, 0x785b, 0x0000, 0x70af, 0x000e,
+ 0x2009, 0x0100, 0x017e, 0x70a0, 0xa06d, 0x0040, 0x39db, 0x70a3,
+ 0x0000, 0x0078, 0x39e1, 0x70b3, 0x0000, 0x1078, 0x1b6e, 0x0040,
+ 0x39e7, 0x70ac, 0x6826, 0x1078, 0x3ac2, 0x0078, 0x39db, 0x017f,
+ 0x157e, 0x0c7e, 0x0d7e, 0x20a9, 0x0008, 0x2061, 0x7410, 0x6000,
+ 0xa105, 0x6002, 0x601c, 0xa06d, 0x0040, 0x39ff, 0x6800, 0x601e,
+ 0x1078, 0x193d, 0x6008, 0x8000, 0x600a, 0x0078, 0x39f2, 0x6018,
+ 0xa06d, 0x0040, 0x3a09, 0x6800, 0x601a, 0x1078, 0x193d, 0x0078,
+ 0x39ff, 0xace0, 0x0008, 0x0070, 0x3a0f, 0x0078, 0x39ef, 0x709c,
+ 0xa084, 0x8000, 0x0040, 0x3a16, 0x1078, 0x3b3c, 0x0d7f, 0x0c7f,
+ 0x157f, 0x007c, 0x127e, 0x2091, 0x2300, 0x6804, 0xa084, 0x000f,
+ 0x0079, 0x3a22, 0x3a32, 0x3a32, 0x3a32, 0x3a32, 0x3a32, 0x3a32,
+ 0x3a34, 0x3a3a, 0x3a32, 0x3a32, 0x3a32, 0x3a32, 0x3a32, 0x3a3c,
+ 0x3a32, 0x3a34, 0x1078, 0x23ca, 0x1078, 0x4466, 0x1078, 0x193d,
+ 0x0078, 0x3a40, 0x6827, 0x000b, 0x1078, 0x4466, 0x1078, 0x3ac2,
+ 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x0098, 0x3a5e, 0x7830,
+ 0xa084, 0x00c0, 0x00c0, 0x3a5e, 0x0d7e, 0x1078, 0x45c5, 0x2d00,
+ 0x682e, 0x2009, 0x0004, 0x2001, 0x0000, 0x6827, 0x0084, 0x1078,
+ 0x457e, 0x1078, 0x3ac2, 0x0d7f, 0x0078, 0x3a90, 0x7948, 0xa185,
+ 0x4000, 0x784a, 0x0098, 0x3a67, 0x794a, 0x0078, 0x3a4c, 0x7828,
+ 0xa086, 0x1834, 0x00c0, 0x3a70, 0xa185, 0x0004, 0x0078, 0x3a77,
+ 0x7828, 0xa186, 0x1814, 0x00c0, 0x3a64, 0xa185, 0x000c, 0x784a,
+ 0x789b, 0x000e, 0x78ab, 0x0002, 0x7858, 0xa084, 0x00ff, 0xa085,
+ 0x0400, 0x785a, 0x70b4, 0xa080, 0x0091, 0x781a, 0x6827, 0x0002,
+ 0x6827, 0x0084, 0x2009, 0x0004, 0x2001, 0x0000, 0x1078, 0x457e,
+ 0x127f, 0x007c, 0x0d7e, 0x6b14, 0x1078, 0x1be0, 0x0040, 0x3a9f,
+ 0x2068, 0x6827, 0x0002, 0x1078, 0x3ac2, 0x0078, 0x3a94, 0x0d7f,
+ 0x007c, 0x0d7e, 0x6b14, 0x6c28, 0xa4a4, 0x00ff, 0x1078, 0x1b7e,
+ 0x0040, 0x3aaf, 0x2068, 0x6827, 0x0002, 0x1078, 0x3ac2, 0x0d7f,
+ 0x007c, 0x0d7e, 0x6b14, 0xa39c, 0x00ff, 0x1078, 0x1bb1, 0x0040,
+ 0x3ac0, 0x2068, 0x6827, 0x0002, 0x1078, 0x3ac2, 0x0078, 0x3ab5,
+ 0x0d7f, 0x007c, 0x0c7e, 0x6914, 0x1078, 0x3b33, 0x6904, 0xa18c,
+ 0x00ff, 0xa186, 0x0006, 0x0040, 0x3add, 0xa186, 0x000d, 0x0040,
+ 0x3afc, 0xa186, 0x0017, 0x00c0, 0x3ad9, 0x1078, 0x193d, 0x0078,
+ 0x3adb, 0x1078, 0x1c55, 0x0c7f, 0x007c, 0x6004, 0x8001, 0x0048,
+ 0x3afa, 0x6006, 0x2009, 0x0000, 0xa684, 0x0001, 0x00c0, 0x3aea,
+ 0xa18d, 0x8000, 0xa684, 0x0004, 0x0040, 0x3af0, 0xa18d, 0x0002,
+ 0x691e, 0x6823, 0x0000, 0x7104, 0x810f, 0x6818, 0xa105, 0x681a,
+ 0x0078, 0x3ad9, 0x1078, 0x23ca, 0x6018, 0xa005, 0x00c0, 0x3b0b,
+ 0x6008, 0x8001, 0x0048, 0x3b0b, 0x600a, 0x601c, 0x6802, 0x2d00,
+ 0x601e, 0x0078, 0x3b21, 0xac88, 0x0006, 0x2104, 0xa005, 0x0040,
+ 0x3b14, 0x2008, 0x0078, 0x3b0d, 0x6802, 0x2d0a, 0x6008, 0x8001,
+ 0x0048, 0x3adb, 0x600a, 0x6018, 0x2068, 0x6800, 0x601a, 0x0078,
+ 0x3b05, 0x157e, 0x137e, 0x147e, 0x0c7e, 0x0d7e, 0x1078, 0x191a,
+ 0x2da0, 0x137f, 0x20a9, 0x0031, 0x53a3, 0x0c7f, 0x147f, 0x137f,
+ 0x157f, 0x0078, 0x3ad9, 0xa184, 0x001f, 0x8003, 0x8003, 0x8003,
+ 0xa080, 0x7410, 0x2060, 0x007c, 0x2019, 0x5051, 0x2304, 0xa085,
+ 0x0001, 0x201a, 0x2019, 0x0102, 0x2304, 0xa085, 0x0001, 0x201a,
+ 0x007c, 0x2019, 0x5051, 0x2304, 0xa084, 0xfffe, 0x201a, 0x2019,
+ 0x0102, 0x2304, 0xa084, 0xfffe, 0x201a, 0x007c, 0x7990, 0xa18c,
+ 0xfff8, 0x7992, 0x70b4, 0xa080, 0x00d8, 0x781a, 0x0078, 0x2438,
+ 0x70a3, 0x0000, 0x7003, 0x0000, 0x7043, 0x0001, 0x7037, 0x0000,
+ 0x0018, 0x23ef, 0x1078, 0x1b6e, 0x0040, 0x3b91, 0x2009, 0x500f,
+ 0x200b, 0x0000, 0x68bc, 0x2060, 0x6100, 0xa184, 0x0300, 0x0040,
+ 0x3b85, 0x6827, 0x000e, 0xa084, 0x0200, 0x0040, 0x3b81, 0x6827,
+ 0x0017, 0x1078, 0x3ac2, 0x0078, 0x3b60, 0x7000, 0xa086, 0x0007,
+ 0x00c0, 0x3be3, 0x2d00, 0x70a2, 0xad80, 0x000f, 0x7036, 0x0078,
+ 0x3b98, 0x7040, 0xa086, 0x0001, 0x0040, 0x2471, 0x0078, 0x2438,
+ 0x2031, 0x0000, 0x691c, 0xa184, 0x0002, 0x0040, 0x3ba1, 0xa6b5,
+ 0x0004, 0xa184, 0x00c0, 0x8003, 0x8003, 0x8007, 0xa080, 0x3c72,
+ 0x2004, 0xa635, 0x6820, 0xa084, 0x0400, 0x0040, 0x3bb9, 0x789b,
+ 0x0018, 0x78ab, 0x0003, 0x789b, 0x0081, 0x78ab, 0x0001, 0xa6b5,
+ 0x1000, 0x6820, 0xa084, 0x8000, 0x0040, 0x3bc5, 0xa6b5, 0x0400,
+ 0x789b, 0x000e, 0x6824, 0x8007, 0x78aa, 0xa684, 0x0200, 0x0040,
+ 0x3bdf, 0x682c, 0x78d2, 0x6830, 0x78d6, 0xa684, 0x0100, 0x0040,
+ 0x3bdd, 0x682c, 0xa084, 0x0001, 0x0040, 0x3bdd, 0x7888, 0xa084,
+ 0x0040, 0x0040, 0x3bdd, 0xa6b5, 0x8000, 0x1078, 0x45ad, 0x7e5a,
+ 0x6eb6, 0x0078, 0x45e4, 0x1078, 0x38c6, 0x00c0, 0x3c6c, 0x702c,
+ 0x8004, 0x0048, 0x3bf1, 0x2019, 0x4cfd, 0x1078, 0x2255, 0x702f,
+ 0x0001, 0x2011, 0x0001, 0x2031, 0x1000, 0x789b, 0x0018, 0x6814,
+ 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa, 0x691c, 0xa184, 0x0002,
+ 0x0040, 0x3c0a, 0xa6b5, 0x0004, 0x78ab, 0x0020, 0x6828, 0x78aa,
+ 0xa290, 0x0002, 0x6820, 0xa084, 0x8000, 0x0040, 0x3c18, 0xa6b5,
+ 0x0400, 0x789b, 0x000e, 0x6824, 0x8007, 0x78aa, 0x0078, 0x3c26,
+ 0x681c, 0xa084, 0x8000, 0x00c0, 0x3c26, 0xa6b5, 0x0800, 0x6820,
+ 0xa084, 0x0100, 0x0040, 0x3c26, 0xa6b5, 0x4000, 0x681c, 0xa084,
+ 0x00c0, 0x8003, 0x8003, 0x8007, 0xa080, 0x3c72, 0x2004, 0xa635,
+ 0xa684, 0x0100, 0x0040, 0x3c40, 0x682c, 0xa084, 0x0001, 0x0040,
+ 0x3c40, 0x7888, 0xa084, 0x0040, 0x0040, 0x3c40, 0xa6b5, 0x8000,
+ 0x789b, 0x007e, 0x7eae, 0x6eb6, 0x6814, 0x8007, 0x78aa, 0x7882,
+ 0x7aaa, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3c6c, 0x0018, 0x3c6c,
+ 0x70b4, 0xa080, 0x00dd, 0x781a, 0x1078, 0x38de, 0xa684, 0x0200,
+ 0x0040, 0x3c60, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x1078, 0x45ad,
+ 0x2d00, 0x70a2, 0x704a, 0x6810, 0x70be, 0x7003, 0x0007, 0xad80,
+ 0x000f, 0x7036, 0x0078, 0x2438, 0x1078, 0x1b45, 0x1078, 0x38de,
+ 0x0078, 0x2438, 0x0000, 0x0300, 0x0200, 0x0000, 0x1078, 0x23ca,
+ 0x2300, 0x0079, 0x3c7b, 0x3c7e, 0x3c7e, 0x3c80, 0x1078, 0x23ca,
+ 0x1078, 0x45bc, 0x6924, 0xa184, 0x00ff, 0xa086, 0x000a, 0x0040,
+ 0x3c92, 0xa184, 0xff00, 0xa085, 0x000a, 0x6826, 0x1078, 0x1b45,
+ 0x0078, 0x3b60, 0x2001, 0x000a, 0x1078, 0x454c, 0x0078, 0x3b60,
+ 0xa282, 0x0005, 0x0050, 0x3c9e, 0x1078, 0x23ca, 0x7000, 0xa084,
+ 0x0007, 0x10c0, 0x398a, 0x1078, 0x191a, 0x00c0, 0x3cbd, 0xa684,
+ 0x0004, 0x0040, 0x3caf, 0x2001, 0x2800, 0x0078, 0x3cb1, 0x2001,
+ 0x0800, 0x71b4, 0xa188, 0x0091, 0x789b, 0x000e, 0x78aa, 0x2031,
+ 0x0400, 0x7e5a, 0x791a, 0x0078, 0x2438, 0x6807, 0x0106, 0x680b,
+ 0x0000, 0x689f, 0x0000, 0x6827, 0x0000, 0xa386, 0x0002, 0x00c0,
+ 0x3cde, 0xa286, 0x0002, 0x00c0, 0x3cde, 0x78a0, 0xa005, 0x00c0,
+ 0x3cde, 0xa484, 0x8000, 0x00c0, 0x3cde, 0x78e4, 0xa084, 0x0008,
+ 0x0040, 0x3cde, 0xa6b5, 0x0008, 0x2019, 0x0000, 0x1078, 0x40d3,
+ 0x2d00, 0x70a2, 0x704a, 0x7003, 0x0007, 0x7037, 0x0000, 0x6824,
+ 0xa084, 0x0080, 0x0040, 0x3cf0, 0x1078, 0x4180, 0x0078, 0x2438,
+ 0x2300, 0x0079, 0x3cf3, 0x3cf6, 0x3d77, 0x3d96, 0x2200, 0x0079,
+ 0x3cf9, 0x3cfe, 0x3d0e, 0x3d34, 0x3d40, 0x3d63, 0x2029, 0x0001,
+ 0xa026, 0x2011, 0x0000, 0x1078, 0x428d, 0x0079, 0x3d07, 0x3d0c,
+ 0x2438, 0x3b60, 0x3d0c, 0x3d0c, 0x1078, 0x23ca, 0x7990, 0xa18c,
+ 0x0007, 0x00c0, 0x3d15, 0x2009, 0x0008, 0x2011, 0x0001, 0xa684,
+ 0x0004, 0x0040, 0x3d1d, 0x2011, 0x0003, 0x2220, 0xa12a, 0x2011,
+ 0x0001, 0x1078, 0x428d, 0x0079, 0x3d25, 0x3d2a, 0x2438, 0x3b60,
+ 0x3d32, 0x3d2c, 0x0078, 0x45ea, 0x70ab, 0x3d30, 0x0078, 0x2438,
+ 0x0078, 0x3d2a, 0x1078, 0x23ca, 0xa684, 0x0010, 0x0040, 0x3d3e,
+ 0x1078, 0x414f, 0x0040, 0x3d3e, 0x0078, 0x2438, 0x0078, 0x41bc,
+ 0x6000, 0xa084, 0x0002, 0x0040, 0x3d5d, 0x70b4, 0xa080, 0x00cd,
+ 0x781a, 0x0d7e, 0x1078, 0x45c5, 0x2d00, 0x682e, 0x6827, 0x0000,
+ 0x1078, 0x3ac2, 0x0d7f, 0x1078, 0x193d, 0x7003, 0x0000, 0x7037,
+ 0x0000, 0x704b, 0x0000, 0x0078, 0x3b60, 0xa684, 0x0004, 0x00c0,
+ 0x3d63, 0x0078, 0x45ea, 0x6000, 0xa084, 0x0004, 0x00c0, 0x3d75,
+ 0x6000, 0xa084, 0x0001, 0x0040, 0x3d75, 0x70ab, 0x3d75, 0x2001,
+ 0x0007, 0x1078, 0x4544, 0x0078, 0x45f0, 0x0078, 0x45ea, 0x2200,
+ 0x0079, 0x3d7a, 0x3d7f, 0x3d7f, 0x3d7f, 0x3d81, 0x3d7f, 0x1078,
+ 0x23ca, 0x70a7, 0x3d85, 0x0078, 0x45f6, 0x2011, 0x0018, 0x1078,
+ 0x4287, 0x0079, 0x3d8b, 0x3d90, 0x2438, 0x3b60, 0x3d92, 0x3d94,
+ 0x1078, 0x23ca, 0x1078, 0x23ca, 0x1078, 0x23ca, 0x2200, 0x0079,
+ 0x3d99, 0x3d9e, 0x3da0, 0x3da0, 0x3d9e, 0x3d9e, 0x1078, 0x23ca,
+ 0x78e4, 0xa084, 0x0008, 0x0040, 0x3db5, 0x70a7, 0x3da9, 0x0078,
+ 0x45f6, 0x2011, 0x0004, 0x1078, 0x4287, 0x0079, 0x3daf, 0x3db5,
+ 0x2438, 0x3b60, 0x3db5, 0x3dbf, 0x3dc3, 0x70ab, 0x3dbd, 0x2001,
+ 0x0003, 0x1078, 0x4544, 0x0078, 0x45f0, 0x0078, 0x45ea, 0x70ab,
+ 0x3db5, 0x0078, 0x2438, 0x70ab, 0x3dc7, 0x0078, 0x2438, 0x0078,
+ 0x3dbd, 0xa282, 0x0003, 0x0050, 0x3dcf, 0x1078, 0x23ca, 0xa386,
+ 0x0002, 0x00c0, 0x3de8, 0xa286, 0x0002, 0x00c0, 0x3dee, 0x78a0,
+ 0xa005, 0x00c0, 0x3dee, 0xa484, 0x8000, 0x00c0, 0x3dee, 0x78e4,
+ 0xa084, 0x0008, 0x0040, 0x3de8, 0xa6b5, 0x0008, 0x2019, 0x0000,
+ 0xa684, 0x0008, 0x0040, 0x3dee, 0x1078, 0x412c, 0x6810, 0x70be,
+ 0x7003, 0x0007, 0x2300, 0x0079, 0x3df5, 0x3df8, 0x3e25, 0x3e2d,
+ 0x2200, 0x0079, 0x3dfb, 0x3e00, 0x3dfe, 0x3e19, 0x1078, 0x23ca,
+ 0x7990, 0xa1ac, 0x0007, 0xa026, 0x2011, 0x0001, 0x1078, 0x428d,
+ 0x0079, 0x3e0a, 0x3e0f, 0x2438, 0x3b60, 0x3e17, 0x3e11, 0x0078,
+ 0x45ea, 0x70ab, 0x3e15, 0x0078, 0x2438, 0x0078, 0x3e0f, 0x1078,
+ 0x23ca, 0xa684, 0x0010, 0x0040, 0x3e23, 0x1078, 0x414f, 0x0040,
+ 0x3e23, 0x0078, 0x2438, 0x0078, 0x41bc, 0x2200, 0x0079, 0x3e28,
+ 0x3e2b, 0x3e2b, 0x3e2b, 0x1078, 0x23ca, 0x2200, 0x0079, 0x3e30,
+ 0x3e33, 0x3e35, 0x3e35, 0x1078, 0x23ca, 0x78e4, 0xa084, 0x0008,
+ 0x0040, 0x3e4a, 0x70a7, 0x3e3e, 0x0078, 0x45f6, 0x2011, 0x0004,
+ 0x1078, 0x4287, 0x0079, 0x3e44, 0x3e4a, 0x2438, 0x3b60, 0x3e4a,
+ 0x3e54, 0x3e58, 0x70ab, 0x3e52, 0x2001, 0x0003, 0x1078, 0x4544,
+ 0x0078, 0x45f0, 0x0078, 0x45ea, 0x70ab, 0x3e4a, 0x0078, 0x2438,
+ 0x70ab, 0x3e5c, 0x0078, 0x2438, 0x0078, 0x3e52, 0x2300, 0x0079,
+ 0x3e61, 0x3e66, 0x3e68, 0x3e64, 0x1078, 0x23ca, 0x70a4, 0x007a,
+ 0x70a4, 0x007a, 0xa282, 0x0002, 0x0050, 0x3e70, 0x1078, 0x23ca,
+ 0xa684, 0x0200, 0x0040, 0x3e7a, 0x1078, 0x45b5, 0x1078, 0x426f,
+ 0x1078, 0x45bc, 0x2300, 0x0079, 0x3e7d, 0x3e80, 0x3ea4, 0x3f0a,
+ 0xa286, 0x0001, 0x0040, 0x3e86, 0x1078, 0x23ca, 0xa684, 0x0200,
+ 0x0040, 0x3e8e, 0x1078, 0x45b5, 0x1078, 0x45bc, 0x2001, 0x0001,
+ 0x1078, 0x454c, 0x78b8, 0xa084, 0xc001, 0x0040, 0x3ea0, 0x7848,
+ 0xa085, 0x0008, 0x784a, 0x7848, 0xa084, 0x0008, 0x00c0, 0x3e9b,
+ 0x7003, 0x0000, 0x0078, 0x3b60, 0x2200, 0x0079, 0x3ea7, 0x3ea9,
+ 0x3eda, 0x70a7, 0x3ead, 0x0078, 0x45f6, 0x2011, 0x000d, 0x1078,
+ 0x4287, 0x0079, 0x3eb3, 0x3eba, 0x2438, 0x3b60, 0x3ec2, 0x3eca,
+ 0x3ed0, 0x3ed2, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
+ 0x0078, 0x45e4, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
+ 0x0078, 0x45e4, 0x70ab, 0x3ece, 0x0078, 0x2438, 0x0078, 0x3eba,
+ 0x1078, 0x23ca, 0x70ab, 0x3ed6, 0x0078, 0x2438, 0x1078, 0x45fc,
+ 0x0078, 0x2438, 0x70a7, 0x3ede, 0x0078, 0x45f6, 0x2011, 0x0012,
+ 0x1078, 0x4287, 0x0079, 0x3ee4, 0x3eea, 0x2438, 0x3b60, 0x3ef6,
+ 0x3efe, 0x3f04, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
+ 0x70b4, 0xa080, 0x00a5, 0x781a, 0x0078, 0x2438, 0xa6b4, 0x00ff,
+ 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x0078, 0x45e4, 0x70ab, 0x3f02,
+ 0x0078, 0x2438, 0x0078, 0x3eea, 0x70ab, 0x3f08, 0x0078, 0x2438,
+ 0x0078, 0x3ef6, 0xa286, 0x0001, 0x0040, 0x3f10, 0x1078, 0x23ca,
+ 0x70a7, 0x3f14, 0x0078, 0x45f6, 0x2011, 0x0015, 0x1078, 0x4287,
+ 0x0079, 0x3f1a, 0x3f1f, 0x2438, 0x3b60, 0x3f2d, 0x3f39, 0xa6b4,
+ 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x783b, 0x1301, 0x70b4,
+ 0xa080, 0x00b5, 0x781a, 0x0078, 0x2438, 0xa6b4, 0x00ff, 0xa6b5,
+ 0x0400, 0x6eb6, 0x7e5a, 0x70b4, 0xa080, 0x00a5, 0x781a, 0x0078,
+ 0x2438, 0x70ab, 0x3f3d, 0x0078, 0x2438, 0x0078, 0x3f1f, 0xa282,
+ 0x0003, 0x0050, 0x3f45, 0x1078, 0x23ca, 0x2300, 0x0079, 0x3f48,
+ 0x3f4b, 0x3f82, 0x3fdd, 0xa286, 0x0001, 0x0040, 0x3f51, 0x1078,
+ 0x23ca, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x3f5e,
+ 0x1078, 0x3ac2, 0x7003, 0x0000, 0x0078, 0x3b60, 0x683b, 0x0000,
+ 0x6837, 0x0000, 0xa684, 0x0200, 0x0040, 0x3f6c, 0x1078, 0x45b5,
+ 0x1078, 0x426f, 0x1078, 0x45bc, 0x2001, 0x0001, 0x1078, 0x454c,
+ 0x78b8, 0xa084, 0xc001, 0x0040, 0x3f7e, 0x7848, 0xa085, 0x0008,
+ 0x784a, 0x7848, 0xa084, 0x0008, 0x00c0, 0x3f79, 0x7003, 0x0000,
+ 0x0078, 0x3b60, 0x2200, 0x0079, 0x3f85, 0x3f87, 0x3fb8, 0x70a7,
+ 0x3f8b, 0x0078, 0x45f6, 0x2011, 0x000d, 0x1078, 0x4287, 0x0079,
+ 0x3f91, 0x3f98, 0x2438, 0x3b60, 0x3fa0, 0x3fa8, 0x3fae, 0x3fb0,
+ 0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x45e4,
+ 0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x45e4,
+ 0x70ab, 0x3fac, 0x0078, 0x2438, 0x0078, 0x3f98, 0x1078, 0x23ca,
+ 0x70ab, 0x3fb4, 0x0078, 0x2438, 0x1078, 0x45fc, 0x0078, 0x2438,
+ 0x70a7, 0x3fbc, 0x0078, 0x45f6, 0x2011, 0x0005, 0x1078, 0x4287,
+ 0x0079, 0x3fc2, 0x3fc7, 0x2438, 0x3b60, 0x3fcf, 0x3fd7, 0xa6b4,
+ 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x45e4, 0xa6b4,
+ 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x45e4, 0x70ab,
+ 0x3fdb, 0x0078, 0x2438, 0x0078, 0x3fc7, 0xa286, 0x0001, 0x0040,
+ 0x3fe3, 0x1078, 0x23ca, 0x70a7, 0x3fe7, 0x0078, 0x45f6, 0x2011,
+ 0x0006, 0x1078, 0x4287, 0x0079, 0x3fed, 0x3ff2, 0x2438, 0x3b60,
+ 0x3ff8, 0x4002, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x45e4,
+ 0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0xa6b5, 0x4000, 0x7e5a,
+ 0x0078, 0x45e4, 0x70ab, 0x4006, 0x0078, 0x2438, 0x0078, 0x3ff2,
+ 0x2300, 0x0079, 0x400b, 0x4010, 0x400e, 0x400e, 0x1078, 0x23ca,
+ 0x1078, 0x23ca, 0x2300, 0x71a8, 0xa005, 0x017a, 0x6810, 0x70be,
+ 0xa282, 0x0003, 0x0050, 0x401e, 0x1078, 0x23ca, 0x2300, 0x0079,
+ 0x4021, 0x4024, 0x4037, 0x4059, 0x82ff, 0x00c0, 0x4029, 0x1078,
+ 0x23ca, 0xa684, 0x0200, 0x0040, 0x4031, 0x1078, 0x45b5, 0x1078,
+ 0x45bc, 0x2001, 0x0001, 0x1078, 0x454c, 0x0078, 0x2438, 0xa296,
+ 0x0002, 0x0040, 0x4040, 0x82ff, 0x0040, 0x4040, 0x1078, 0x23ca,
+ 0x70a7, 0x4044, 0x0078, 0x45f6, 0x2011, 0x0018, 0x1078, 0x4287,
+ 0x0079, 0x404a, 0x404f, 0x2438, 0x3b60, 0x4051, 0x4053, 0x0078,
+ 0x45e4, 0x0078, 0x45e4, 0x70ab, 0x4057, 0x0078, 0x2438, 0x0078,
+ 0x404f, 0x2200, 0x0079, 0x405c, 0x405e, 0x4077, 0x70a7, 0x4062,
+ 0x0078, 0x45f6, 0x2011, 0x0017, 0x1078, 0x4287, 0x0079, 0x4068,
+ 0x406d, 0x2438, 0x3b60, 0x406f, 0x4071, 0x0078, 0x45e4, 0x0078,
+ 0x45e4, 0x70ab, 0x4075, 0x0078, 0x2438, 0x0078, 0x406d, 0xa484,
+ 0x8000, 0x00c0, 0x40c1, 0xa684, 0x0100, 0x0040, 0x408b, 0x1078,
+ 0x45b5, 0x1078, 0x426f, 0x1078, 0x45bc, 0x7848, 0xa085, 0x000c,
+ 0x784a, 0x0078, 0x408f, 0x78d8, 0x78d2, 0x78dc, 0x78d6, 0xa6b4,
+ 0xefff, 0x7e5a, 0x70a7, 0x4096, 0x0078, 0x45f6, 0x2011, 0x000d,
+ 0x1078, 0x4287, 0x0079, 0x409c, 0x40a3, 0x2438, 0x3b60, 0x40a3,
+ 0x40b1, 0x40b7, 0x40b9, 0xa684, 0x0100, 0x0040, 0x40af, 0x1078,
+ 0x4573, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x1078, 0x45ad, 0x0078,
+ 0x45e4, 0x70ab, 0x40b5, 0x0078, 0x2438, 0x0078, 0x40a3, 0x1078,
+ 0x23ca, 0x70ab, 0x40bd, 0x0078, 0x2438, 0x1078, 0x45fc, 0x0078,
+ 0x2438, 0x1078, 0x45bc, 0x70ab, 0x40cb, 0x2001, 0x0003, 0x1078,
+ 0x4544, 0x0078, 0x45f0, 0x1078, 0x45ad, 0x682c, 0x78d2, 0x6830,
+ 0x78d6, 0x0078, 0x45e4, 0x70b8, 0x6812, 0x70be, 0x8000, 0x70ba,
+ 0x681b, 0x0000, 0xa684, 0x0008, 0x0040, 0x40f6, 0x157e, 0x137e,
+ 0x147e, 0x7890, 0x8004, 0x8004, 0x8004, 0x8004, 0xa084, 0x000f,
+ 0x681a, 0x80ac, 0x789b, 0x0000, 0xaf80, 0x002b, 0x2098, 0xad80,
+ 0x000b, 0x20a0, 0x53a5, 0x147f, 0x137f, 0x157f, 0xa6c4, 0x0f00,
+ 0xa684, 0x0002, 0x00c0, 0x4102, 0x692c, 0x810d, 0x810d, 0x810d,
+ 0x0078, 0x410f, 0x789b, 0x0010, 0x79ac, 0x0078, 0x410f, 0x017e,
+ 0x2009, 0x0005, 0x2001, 0x3d00, 0x1078, 0x457e, 0x017f, 0xa184,
+ 0x001f, 0xa805, 0x6816, 0x1078, 0x3b33, 0x68be, 0xa684, 0x0004,
+ 0x0040, 0x4120, 0xa18c, 0xff00, 0x78a8, 0xa084, 0x00ff, 0xa105,
+ 0x682a, 0xa6b4, 0x00ff, 0x6000, 0xa084, 0x0008, 0x0040, 0x412a,
+ 0xa6b5, 0x4000, 0x6eb6, 0x007c, 0x157e, 0x137e, 0x147e, 0x6918,
+ 0x7890, 0x8004, 0x8004, 0x8004, 0x8004, 0xa084, 0x000f, 0x007e,
+ 0xa100, 0x681a, 0x007f, 0x8000, 0x8004, 0x0040, 0x414b, 0x20a8,
+ 0x8104, 0xa080, 0x000b, 0xad00, 0x20a0, 0x789b, 0x0000, 0xaf80,
+ 0x002b, 0x2098, 0x53a5, 0x147f, 0x137f, 0x157f, 0x007c, 0x682c,
+ 0xa084, 0x0020, 0x00c0, 0x4157, 0x620c, 0x0078, 0x4158, 0x6210,
+ 0x6b18, 0x2300, 0xa202, 0x0040, 0x4178, 0x2018, 0xa382, 0x000e,
+ 0x0048, 0x4168, 0x0040, 0x4168, 0x2019, 0x000e, 0x0078, 0x416c,
+ 0x7858, 0xa084, 0xffef, 0x785a, 0x783b, 0x1b01, 0x7893, 0x0000,
+ 0x7ba2, 0x70b4, 0xa080, 0x008e, 0x781a, 0xa085, 0x0001, 0x007c,
+ 0x7858, 0xa084, 0xffef, 0x785a, 0x7893, 0x0000, 0xa006, 0x007c,
+ 0x6904, 0xa18c, 0x00ff, 0xa196, 0x0007, 0x0040, 0x418d, 0xa196,
+ 0x000f, 0x0040, 0x418d, 0x6807, 0x0117, 0x6914, 0x1078, 0x3b33,
+ 0x6100, 0x8104, 0x00c8, 0x41a8, 0x601c, 0xa005, 0x0040, 0x419c,
+ 0x2001, 0x0800, 0x0078, 0x41aa, 0x0d7e, 0x6824, 0x007e, 0x1078,
+ 0x45c5, 0x007f, 0x6826, 0x2d00, 0x682e, 0x1078, 0x3ac2, 0x0d7f,
+ 0x2001, 0x0200, 0x6826, 0x8007, 0x789b, 0x000e, 0x78aa, 0x6820,
+ 0xa085, 0x8000, 0x6822, 0x2031, 0x0400, 0x6eb6, 0x7e5a, 0x71b4,
+ 0xa188, 0x0091, 0x791a, 0x007c, 0xa6c4, 0x0f00, 0xa684, 0x0002,
+ 0x00c0, 0x41cf, 0x692c, 0x810d, 0x810d, 0x810d, 0xa184, 0x001f,
+ 0xa805, 0x6816, 0x1078, 0x3b33, 0x68be, 0x0078, 0x41d2, 0x6914,
+ 0x1078, 0x3b33, 0x6100, 0x8104, 0x00c8, 0x421c, 0xa184, 0x0300,
+ 0x0040, 0x41de, 0x6807, 0x0117, 0x0078, 0x41fc, 0x6004, 0xa005,
+ 0x00c0, 0x4205, 0x6807, 0x0117, 0x601c, 0xa005, 0x00c0, 0x41f2,
+ 0x0d7e, 0x1078, 0x45c5, 0x6827, 0x0034, 0x2d00, 0x682e, 0x1078,
+ 0x3ac2, 0x0d7f, 0xa684, 0x0004, 0x0040, 0x41fc, 0x2031, 0x0400,
+ 0x2001, 0x2800, 0x0078, 0x4200, 0x2031, 0x0400, 0x2001, 0x0800,
+ 0x71b4, 0xa188, 0x0091, 0x0078, 0x424a, 0x6018, 0xa005, 0x00c0,
+ 0x41f2, 0x601c, 0xa005, 0x00c0, 0x41f2, 0x689f, 0x0000, 0x6827,
+ 0x003d, 0xa684, 0x0001, 0x0040, 0x4258, 0xa6b5, 0x0800, 0x71b4,
+ 0xa188, 0x00ae, 0x0078, 0x4253, 0x6807, 0x0117, 0x2031, 0x0400,
+ 0x692c, 0xa18c, 0x00ff, 0xa186, 0x0012, 0x00c0, 0x422d, 0x2001,
+ 0x4265, 0x2009, 0x0001, 0x0078, 0x423e, 0xa186, 0x0003, 0x00c0,
+ 0x4237, 0x2001, 0x4266, 0x2009, 0x0012, 0x0078, 0x423e, 0x2001,
+ 0x0200, 0x71b4, 0xa188, 0x0091, 0x0078, 0x424a, 0x1078, 0x4598,
+ 0x78a3, 0x0000, 0x681c, 0xa085, 0x0040, 0x681e, 0x71b4, 0xa188,
+ 0x00da, 0xa006, 0x6826, 0x8007, 0x789b, 0x000e, 0x78aa, 0x6820,
+ 0xa085, 0x8000, 0x6822, 0x6eb6, 0x7e5a, 0x791a, 0x0078, 0x2438,
+ 0x6eb6, 0x1078, 0x3ac2, 0x6810, 0x70be, 0x7003, 0x0007, 0x70a3,
+ 0x0000, 0x704b, 0x0000, 0x0078, 0x2438, 0x0023, 0x0070, 0x0005,
+ 0x0000, 0x0a00, 0x0000, 0x0000, 0x0025, 0x0000, 0x0000, 0x683b,
+ 0x0000, 0x6837, 0x0000, 0xa684, 0x0200, 0x0040, 0x4286, 0x78b8,
+ 0xa08c, 0x001f, 0xa084, 0x8000, 0x0040, 0x427f, 0x8108, 0x78d8,
+ 0xa100, 0x6836, 0x78dc, 0xa081, 0x0000, 0x683a, 0x007c, 0x7990,
+ 0x810f, 0xa5ac, 0x0007, 0x2021, 0x0000, 0xa480, 0x0010, 0x789a,
+ 0x79a8, 0xa18c, 0x00ff, 0xa184, 0x0080, 0x00c0, 0x42b5, 0xa182,
+ 0x0020, 0x00c8, 0x42cf, 0xa182, 0x0012, 0x00c8, 0x4536, 0x2100,
+ 0x1079, 0x42a3, 0x007c, 0x4536, 0x447e, 0x4536, 0x4536, 0x42dc,
+ 0x42df, 0x4319, 0x434f, 0x4381, 0x4384, 0x4536, 0x4536, 0x433a,
+ 0x43a8, 0x43e2, 0x4536, 0x4536, 0x4409, 0xa18c, 0x001f, 0x6814,
+ 0xa084, 0x001f, 0xa106, 0x0040, 0x42cc, 0x70b4, 0xa080, 0x00cd,
+ 0x781a, 0x2001, 0x0014, 0x1078, 0x454c, 0x1078, 0x45bc, 0x7003,
+ 0x0000, 0x2001, 0x0002, 0x007c, 0x2001, 0x0000, 0x007c, 0xa182,
+ 0x0024, 0x00c8, 0x4536, 0xa184, 0x0003, 0x1079, 0x42a3, 0x007c,
+ 0x4536, 0x4536, 0x4536, 0x4536, 0x1078, 0x4536, 0x007c, 0x2200,
+ 0x0079, 0x42e2, 0x440c, 0x440c, 0x4306, 0x4306, 0x4306, 0x4306,
+ 0x4306, 0x4306, 0x4306, 0x4306, 0x4304, 0x4306, 0x42fb, 0x4306,
+ 0x4306, 0x4306, 0x4306, 0x4306, 0x430e, 0x4311, 0x440c, 0x4311,
+ 0x4306, 0x4306, 0x4306, 0x0c7e, 0x077e, 0x6f14, 0x1078, 0x36b0,
+ 0x077f, 0x0c7f, 0x0078, 0x4306, 0x1078, 0x44d1, 0x6827, 0x02b3,
+ 0x2009, 0x000b, 0x2001, 0x4800, 0x0078, 0x4440, 0x1078, 0x452b,
+ 0x007c, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001, 0x4800, 0x0078,
+ 0x4428, 0x2d58, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0,
+ 0x4323, 0x6807, 0x0117, 0x6827, 0x0002, 0x1078, 0x45c5, 0x6827,
+ 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078, 0x3a92, 0x1078,
+ 0x4466, 0x2b68, 0x1078, 0x3ac2, 0x0d7f, 0x1078, 0x3ac2, 0x2001,
+ 0x0002, 0x007c, 0x1078, 0x4466, 0x2001, 0x0017, 0x1078, 0x454c,
+ 0x70a3, 0x0000, 0x2009, 0x5038, 0x200b, 0x0006, 0x70af, 0x0017,
+ 0x2009, 0x0200, 0x1078, 0x39d2, 0x2001, 0x0001, 0x007c, 0x2200,
+ 0x0079, 0x4352, 0x440c, 0x443d, 0x443d, 0x443d, 0x4373, 0x444d,
+ 0x4379, 0x444d, 0x444d, 0x4450, 0x4450, 0x4455, 0x4455, 0x436b,
+ 0x436b, 0x443d, 0x443d, 0x444d, 0x443d, 0x4379, 0x440c, 0x4379,
+ 0x4379, 0x4379, 0x4379, 0x6827, 0x0084, 0x2009, 0x000b, 0x2001,
+ 0x4300, 0x0078, 0x445f, 0x2009, 0x000b, 0x2001, 0x4300, 0x0078,
+ 0x4440, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001, 0x4300, 0x0078,
+ 0x4428, 0x2001, 0x0000, 0x007c, 0x2200, 0x0079, 0x4387, 0x440c,
+ 0x43a0, 0x43a0, 0x43a0, 0x43a0, 0x444d, 0x444d, 0x444d, 0x444d,
+ 0x444d, 0x444d, 0x444d, 0x444d, 0x43a0, 0x43a0, 0x43a0, 0x43a0,
+ 0x444d, 0x43a0, 0x43a0, 0x444d, 0x444d, 0x444d, 0x444d, 0x440c,
+ 0x6827, 0x0093, 0x2009, 0x000b, 0x2001, 0x4300, 0x0078, 0x4428,
+ 0xa684, 0x0004, 0x00c0, 0x43bc, 0x6804, 0xa084, 0x00ff, 0xa086,
+ 0x0006, 0x00c0, 0x4536, 0x1078, 0x4466, 0x6807, 0x0117, 0x1078,
+ 0x3ac2, 0x2001, 0x0002, 0x007c, 0x6000, 0xa084, 0x0004, 0x0040,
+ 0x4536, 0x2d58, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0,
+ 0x43cb, 0x6807, 0x0117, 0x6827, 0x0002, 0x1078, 0x45c5, 0x6827,
+ 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078, 0x3aa1, 0x1078,
+ 0x4466, 0x2b68, 0x1078, 0x3ac2, 0x0d7f, 0x1078, 0x3ac2, 0x2001,
+ 0x0002, 0x007c, 0x6000, 0xa084, 0x0004, 0x0040, 0x4536, 0x2d58,
+ 0x6a04, 0xa294, 0x00ff, 0xa286, 0x0006, 0x00c0, 0x43f1, 0x6807,
+ 0x0117, 0x6827, 0x0002, 0x2d58, 0x1078, 0x45c5, 0x6827, 0x0036,
+ 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078, 0x3ab1, 0x1078, 0x4466,
+ 0x2b68, 0x1078, 0x3ac2, 0x0d7f, 0x1078, 0x3ac2, 0x2001, 0x0002,
+ 0x007c, 0x1078, 0x4536, 0x007c, 0x70b4, 0xa080, 0x00cd, 0x781a,
+ 0x2001, 0x0001, 0x1078, 0x454c, 0x1078, 0x45bc, 0x7003, 0x0000,
+ 0x2001, 0x0002, 0x007c, 0x1078, 0x457e, 0x1078, 0x45b5, 0x1078,
+ 0x426f, 0x1078, 0x4180, 0x1078, 0x45bc, 0x2001, 0x0001, 0x007c,
+ 0x1078, 0x457e, 0x1078, 0x45b5, 0x1078, 0x426f, 0x70b4, 0xa080,
+ 0x00cd, 0x781a, 0x2001, 0x0013, 0x1078, 0x454c, 0x1078, 0x45bc,
+ 0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x1078, 0x4536, 0x007c,
+ 0x1078, 0x457e, 0x1078, 0x45b5, 0x1078, 0x426f, 0x1078, 0x4180,
+ 0x1078, 0x45bc, 0x2001, 0x0001, 0x007c, 0x2001, 0x0003, 0x007c,
+ 0x1078, 0x44d1, 0x2001, 0x0000, 0x007c, 0x0c7e, 0x077e, 0x6f14,
+ 0x1078, 0x36b0, 0x077f, 0x0c7f, 0x2001, 0x0000, 0x007c, 0x1078,
+ 0x457e, 0x1078, 0x4536, 0x2001, 0x0006, 0x007c, 0x6904, 0xa18c,
+ 0x00ff, 0xa186, 0x0007, 0x0040, 0x4471, 0xa186, 0x000f, 0x00c0,
+ 0x4475, 0x1078, 0x45b5, 0x1078, 0x426f, 0x70b4, 0xa080, 0x00cd,
+ 0x781a, 0x1078, 0x45bc, 0x7003, 0x0000, 0x007c, 0x7aa8, 0xa294,
+ 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x4536,
+ 0x1079, 0x448b, 0x007c, 0x4536, 0x448f, 0x4536, 0x44df, 0xa282,
+ 0x0003, 0x0040, 0x4496, 0x1078, 0x4536, 0x007c, 0x7da8, 0xa5ac,
+ 0x00ff, 0x7ca8, 0xa4a4, 0x00ff, 0xa482, 0x000c, 0x0048, 0x44a4,
+ 0x0040, 0x44a4, 0x2021, 0x000c, 0x701c, 0xa502, 0x00c8, 0x44a9,
+ 0x751c, 0x1078, 0x451c, 0x852b, 0x852b, 0x1078, 0x372e, 0x0040,
+ 0x44b5, 0x1078, 0x44c3, 0x0078, 0x44b9, 0x1078, 0x4518, 0x1078,
+ 0x44d1, 0xa6b5, 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, 0x781a,
+ 0x2001, 0x0004, 0x007c, 0x0c7e, 0x6914, 0x810f, 0xa18c, 0x000f,
+ 0x810b, 0x810b, 0x810b, 0xa1e0, 0x5280, 0x1078, 0x3538, 0x0c7f,
+ 0x007c, 0x0c7e, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003,
+ 0x8003, 0xa0e0, 0x5280, 0x1078, 0x355f, 0x0c7f, 0x007c, 0xa282,
+ 0x0002, 0x00c0, 0x4536, 0x7aa8, 0xa294, 0x00ff, 0xa284, 0xfffe,
+ 0x0040, 0x44ec, 0x2011, 0x0001, 0x1078, 0x450a, 0x1078, 0x44fc,
+ 0x1078, 0x44d1, 0xa6b5, 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9,
+ 0x781a, 0x2001, 0x0004, 0x007c, 0x0c7e, 0x6814, 0x8007, 0xa084,
+ 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e0, 0x5280, 0x1078, 0x3604,
+ 0x0c7f, 0x007c, 0x789b, 0x0018, 0x78ab, 0x0001, 0x78ab, 0x0002,
+ 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0081, 0x78ab, 0x0004, 0x007c,
+ 0x2021, 0x0000, 0x2029, 0x0032, 0x789b, 0x0018, 0x78ab, 0x0001,
+ 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7caa, 0x789b, 0x0081,
+ 0x78ab, 0x0005, 0x007c, 0x2001, 0x0003, 0x1078, 0x4544, 0x70b4,
+ 0xa080, 0x00b9, 0x781a, 0x2001, 0x0005, 0x007c, 0x2001, 0x0007,
+ 0x1078, 0x4544, 0xa6b5, 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9,
+ 0x781a, 0x2001, 0x0004, 0x007c, 0x789b, 0x0018, 0x78aa, 0x789b,
+ 0x0081, 0x78ab, 0x0001, 0x007c, 0x6904, 0xa18c, 0x00ff, 0xa196,
+ 0x0007, 0x0040, 0x455a, 0xa196, 0x000f, 0x0040, 0x455a, 0x1078,
+ 0x193d, 0x007c, 0x6924, 0xa194, 0x003f, 0x00c0, 0x4563, 0xa18c,
+ 0xffc0, 0xa105, 0x6826, 0x1078, 0x3ac2, 0x691c, 0xa184, 0x0100,
+ 0x0040, 0x4572, 0x1078, 0x1b7e, 0x6914, 0x1078, 0x3b33, 0x6204,
+ 0x8210, 0x6206, 0x007c, 0x692c, 0x6834, 0x682e, 0xa112, 0x6930,
+ 0x6838, 0x6832, 0xa11b, 0xa200, 0xa301, 0x007c, 0x0c7e, 0xade0,
+ 0x0018, 0x6003, 0x0070, 0x6106, 0x600b, 0x0000, 0x600f, 0x0a00,
+ 0x6013, 0x0000, 0x6017, 0x0000, 0x8007, 0x601a, 0x601f, 0x0000,
+ 0x6023, 0x0000, 0x0c7f, 0x6824, 0xa085, 0x0080, 0x6826, 0x007c,
+ 0x157e, 0x137e, 0x147e, 0x2098, 0xaf80, 0x002d, 0x20a0, 0x81ac,
+ 0x0040, 0x45a3, 0x53a6, 0xa184, 0x0001, 0x0040, 0x45a9, 0x3304,
+ 0x78be, 0x147f, 0x137f, 0x157f, 0x007c, 0x70b0, 0xa005, 0x10c0,
+ 0x23ca, 0x70b3, 0x8000, 0x0078, 0x48f7, 0x71b0, 0x81ff, 0x0040,
+ 0x45bb, 0x1078, 0x49ed, 0x007c, 0x71b0, 0x81ff, 0x0040, 0x45c4,
+ 0x70b3, 0x0000, 0x1078, 0x4633, 0x007c, 0x0c7e, 0x0d7e, 0x1078,
+ 0x191a, 0x0c7f, 0x157e, 0x137e, 0x147e, 0x2da0, 0x2c98, 0x20a9,
+ 0x0031, 0x53a3, 0x147f, 0x137f, 0x157f, 0x6807, 0x010d, 0x680b,
+ 0x0000, 0x7004, 0x8007, 0x681a, 0x6823, 0x0000, 0x681f, 0x0000,
+ 0x689f, 0x0000, 0x0c7f, 0x007c, 0x70b4, 0xa080, 0x0091, 0x781a,
+ 0x0078, 0x2438, 0x70b4, 0xa080, 0x0081, 0x781a, 0x0078, 0x2438,
+ 0x70b4, 0xa080, 0x00b9, 0x781a, 0x0078, 0x2438, 0x70b4, 0xa080,
+ 0x00c3, 0x781a, 0x0078, 0x2438, 0x6904, 0xa18c, 0x00ff, 0xa196,
+ 0x0007, 0x0040, 0x4609, 0xa196, 0x000f, 0x0040, 0x4609, 0x6807,
+ 0x0117, 0x2001, 0x0200, 0x6826, 0x8007, 0x789b, 0x000e, 0x78aa,
+ 0x6820, 0xa085, 0x8000, 0x6822, 0x2031, 0x0400, 0x6eb6, 0x7e5a,
+ 0x71b4, 0xa188, 0x0091, 0x791a, 0x007c, 0x1078, 0x45bc, 0x7848,
+ 0xa085, 0x000c, 0x784a, 0x70b4, 0xa080, 0x00cd, 0x781a, 0x2009,
+ 0x000b, 0x2001, 0x4400, 0x1078, 0x457e, 0x2001, 0x0013, 0x1078,
+ 0x454c, 0x0078, 0x3b60, 0x127e, 0x2091, 0x2200, 0x2049, 0x4633,
+ 0x7000, 0x7204, 0xa205, 0x720c, 0xa215, 0x7008, 0xa084, 0xfff7,
+ 0xa205, 0x0040, 0x4645, 0x0078, 0x464a, 0x7003, 0x0000, 0x127f,
+ 0x2000, 0x007c, 0x7000, 0xa084, 0x0001, 0x00c0, 0x4678, 0x7108,
+ 0x8103, 0x00c8, 0x4657, 0x1078, 0x477a, 0x0078, 0x464f, 0x700c,
+ 0xa08c, 0x00ff, 0x0040, 0x4678, 0x7004, 0x8004, 0x00c8, 0x466f,
+ 0x7014, 0xa005, 0x00c0, 0x466b, 0x7010, 0xa005, 0x0040, 0x466f,
+ 0xa102, 0x00c8, 0x464f, 0x7007, 0x0010, 0x0078, 0x4678, 0x8aff,
+ 0x0040, 0x4678, 0x1078, 0x49c4, 0x00c0, 0x4672, 0x0040, 0x464f,
+ 0x1078, 0x4703, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x017e,
+ 0x6104, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x468b, 0xa18e,
+ 0x000f, 0x00c0, 0x468e, 0x6040, 0x0078, 0x468f, 0x6428, 0x017f,
+ 0x84ff, 0x0040, 0x46b9, 0x2c70, 0x7004, 0xa0bc, 0x000f, 0xa7b8,
+ 0x46c9, 0x273c, 0x87fb, 0x00c0, 0x46a7, 0x0048, 0x46a1, 0x1078,
+ 0x23ca, 0x609c, 0xa075, 0x0040, 0x46b9, 0x0078, 0x4694, 0x2704,
+ 0xae68, 0x6808, 0xa630, 0x680c, 0xa529, 0x8421, 0x0040, 0x46b9,
+ 0x8738, 0x2704, 0xa005, 0x00c0, 0x46a8, 0x709c, 0xa075, 0x00c0,
+ 0x4694, 0x007c, 0x0000, 0x0005, 0x0009, 0x000d, 0x0011, 0x0015,
+ 0x0019, 0x001d, 0x0000, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b,
+ 0x0000, 0x0000, 0x46be, 0x46bb, 0x0000, 0x0000, 0x8000, 0x0000,
+ 0x46be, 0x0000, 0x46c6, 0x46c3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x46c6, 0x0000, 0x46c1, 0x46c1, 0x0000, 0x0000, 0x8000, 0x0000,
+ 0x46c1, 0x0000, 0x46c7, 0x46c7, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x46c7, 0x127e, 0x2091, 0x2200, 0x2079, 0x5000, 0x2071, 0x0010,
+ 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2071, 0x0020,
+ 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2049, 0x0000,
+ 0x127f, 0x2000, 0x007c, 0x2049, 0x4703, 0x2019, 0x0000, 0x7004,
+ 0x8004, 0x00c8, 0x4756, 0x7007, 0x0012, 0x7108, 0x7008, 0xa106,
+ 0x00c0, 0x470d, 0xa184, 0x01e0, 0x0040, 0x4718, 0x1078, 0x23ca,
+ 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x4723, 0xa184,
+ 0x4000, 0x00c0, 0x470d, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0040,
+ 0x4731, 0xa386, 0x0008, 0x0040, 0x473c, 0xa386, 0x200c, 0x00c0,
+ 0x470d, 0x7200, 0x8204, 0x0048, 0x473c, 0x730c, 0xa384, 0x00ff,
+ 0x0040, 0x473c, 0x1078, 0x23ca, 0x7007, 0x0012, 0x7000, 0xa084,
+ 0x0001, 0x00c0, 0x4756, 0x7008, 0xa084, 0x01e0, 0x00c0, 0x4756,
+ 0x7310, 0x7014, 0xa305, 0x0040, 0x4756, 0x710c, 0xa184, 0x0300,
+ 0x00c0, 0x4756, 0xa184, 0x00ff, 0x00c0, 0x4703, 0x7007, 0x0012,
+ 0x7007, 0x0008, 0x7004, 0xa084, 0x0008, 0x00c0, 0x475a, 0x7007,
+ 0x0012, 0x7108, 0x8103, 0x0048, 0x475f, 0x7003, 0x0000, 0x2049,
+ 0x0000, 0x007c, 0x107e, 0x007e, 0x127e, 0x157e, 0x2091, 0x2200,
+ 0x7108, 0x1078, 0x477a, 0x157f, 0x127f, 0x2091, 0x8001, 0x007f,
+ 0x107f, 0x007c, 0x7204, 0x7500, 0x730c, 0xa384, 0x0300, 0x00c0,
+ 0x47a1, 0xa184, 0x01e0, 0x00c0, 0x47c5, 0x7108, 0xa184, 0x01e0,
+ 0x00c0, 0x47c5, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8,
+ 0x4795, 0xa184, 0x4000, 0x00c0, 0x4785, 0xa184, 0x0007, 0x0079,
+ 0x4799, 0x47a3, 0x47b5, 0x47a1, 0x47b5, 0x47a1, 0x4801, 0x47a1,
+ 0x47ff, 0x1078, 0x23ca, 0x7004, 0xa084, 0x0010, 0xa085, 0x0002,
+ 0x7006, 0x8aff, 0x00c0, 0x47b0, 0x2049, 0x0000, 0x0078, 0x47b4,
+ 0x1078, 0x49c4, 0x00c0, 0x47b0, 0x007c, 0x7004, 0xa084, 0x0010,
+ 0xa085, 0x0002, 0x7006, 0x8aff, 0x00c0, 0x47c0, 0x0078, 0x47c4,
+ 0x1078, 0x49c4, 0x00c0, 0x47c0, 0x007c, 0x7007, 0x0012, 0x7108,
+ 0x00e0, 0x47c8, 0x2091, 0x6000, 0x00e0, 0x47cc, 0x2091, 0x6000,
+ 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084, 0x0008, 0x00c0,
+ 0x47d4, 0x7007, 0x0012, 0x7108, 0x8103, 0x0048, 0x47d9, 0x7003,
+ 0x0000, 0x7000, 0xa005, 0x00c0, 0x47ed, 0x7004, 0xa005, 0x00c0,
+ 0x47ed, 0x700c, 0xa005, 0x0040, 0x47ef, 0x0078, 0x47d0, 0x2049,
+ 0x0000, 0x1078, 0x37d7, 0x6818, 0xa084, 0x8000, 0x0040, 0x47fa,
+ 0x681b, 0x0002, 0x007c, 0x1078, 0x23ca, 0x1078, 0x23ca, 0x1078,
+ 0x485d, 0x7210, 0x7114, 0x700c, 0xa09c, 0x00ff, 0x2800, 0xa300,
+ 0xa211, 0xa189, 0x0000, 0x1078, 0x485d, 0x2704, 0x2c58, 0xac60,
+ 0x6308, 0x2200, 0xa322, 0x630c, 0x2100, 0xa31b, 0x2400, 0xa305,
+ 0x0040, 0x4824, 0x00c8, 0x4824, 0x8412, 0x8210, 0x830a, 0xa189,
+ 0x0000, 0x2b60, 0x0078, 0x480b, 0x2b60, 0x8a07, 0x007e, 0x6004,
+ 0xa084, 0x0008, 0x0040, 0x4830, 0xa7ba, 0x46c3, 0x0078, 0x4832,
+ 0xa7ba, 0x46bb, 0x007f, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92,
+ 0x6b8e, 0x7007, 0x0012, 0x1078, 0x4703, 0x007c, 0x8738, 0x2704,
+ 0xa005, 0x00c0, 0x4851, 0x609c, 0xa005, 0x0040, 0x485a, 0x2060,
+ 0x6004, 0xa084, 0x000f, 0xa080, 0x46c9, 0x203c, 0x87fb, 0x1040,
+ 0x23ca, 0x8a51, 0x0040, 0x4859, 0x7008, 0xa084, 0x0003, 0xa086,
0x0003, 0x007c, 0x2051, 0x0000, 0x007c, 0x8a50, 0x8739, 0x2704,
- 0xa004, 0x00c0, 0x3501, 0x6000, 0xa064, 0x00c0, 0x34f8, 0x2d60,
- 0x6004, 0xa084, 0x000f, 0xa080, 0x3356, 0x203c, 0x87fb, 0x1040,
- 0x1eac, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x6884,
+ 0xa004, 0x00c0, 0x4871, 0x6000, 0xa064, 0x00c0, 0x4868, 0x2d60,
+ 0x6004, 0xa084, 0x000f, 0xa080, 0x46d9, 0x203c, 0x87fb, 0x1040,
+ 0x23ca, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x6884,
0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057, 0xaad4, 0x00ff, 0xa084,
- 0x00ff, 0x007e, 0x6804, 0xa084, 0x0008, 0x007f, 0x0040, 0x351c,
- 0xa0b8, 0x3340, 0x0078, 0x351e, 0xa0b8, 0x3338, 0x7e08, 0xa6b5,
- 0x000c, 0x681c, 0xa084, 0x0040, 0x0040, 0x3528, 0xa6b5, 0x0001,
- 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x352a, 0x2400,
- 0xa305, 0x00c0, 0x3535, 0x0078, 0x3559, 0x2c58, 0x2704, 0x6104,
- 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184,
- 0x0008, 0x0040, 0x3549, 0x6010, 0xa001, 0x7022, 0x6014, 0xa001,
- 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300, 0xa203,
- 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078, 0x34ca, 0x0078,
- 0x355b, 0x1078, 0x3606, 0x00c0, 0x3559, 0x127f, 0x2000, 0x007c,
- 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007, 0x0004, 0x7004,
- 0xa084, 0x0004, 0x00c0, 0x3567, 0x7003, 0x0008, 0x127f, 0x2000,
- 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x3571,
- 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x357a, 0x7e08,
- 0xa6b5, 0x000c, 0x681c, 0xa084, 0x0020, 0x00c0, 0x3589, 0xa6b5,
- 0x0001, 0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8,
- 0x3346, 0x273c, 0x87fb, 0x00c0, 0x359f, 0x0048, 0x3599, 0x1078,
- 0x1eac, 0x689c, 0xa065, 0x0040, 0x35a3, 0x0078, 0x358c, 0x1078,
- 0x3606, 0x00c0, 0x359f, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e,
- 0x017e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f, 0x047f, 0x7e08,
- 0xa6b5, 0x000c, 0x681c, 0xa084, 0x0040, 0x0040, 0x35b9, 0xa6b5,
- 0x0001, 0x2049, 0x35a6, 0x6828, 0xa055, 0x0040, 0x3603, 0x2d70,
- 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x3346, 0x273c, 0x87fb,
- 0x00c0, 0x35d5, 0x0048, 0x35ce, 0x1078, 0x1eac, 0x709c, 0xa075,
- 0x2060, 0x0040, 0x3603, 0x0078, 0x35c1, 0x2704, 0xae68, 0x6808,
- 0xa422, 0x680c, 0xa31b, 0x0048, 0x35f0, 0x8a51, 0x00c0, 0x35e2,
- 0x1078, 0x1eac, 0x8738, 0x2704, 0xa005, 0x00c0, 0x35d6, 0x709c,
- 0xa075, 0x2060, 0x0040, 0x3603, 0x2039, 0x3338, 0x0078, 0x35c1,
- 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x6908, 0x2400, 0xa122,
- 0x690c, 0x2300, 0xa11b, 0x00c8, 0x35ff, 0x1078, 0x1eac, 0x2071,
- 0x0020, 0x0078, 0x3528, 0x127f, 0x2000, 0x007c, 0x7008, 0x7508,
- 0xa52e, 0x00c0, 0x3606, 0xa084, 0x0003, 0xa086, 0x0003, 0x0040,
- 0x362e, 0x2704, 0xac08, 0x2104, 0x701a, 0x8108, 0x2104, 0x701e,
- 0x8108, 0x2104, 0x7012, 0x8108, 0x2104, 0x7016, 0x6004, 0xa084,
- 0x0008, 0x0040, 0x3629, 0x8108, 0x2104, 0x7022, 0x8108, 0x2104,
- 0x7026, 0x7602, 0x7007, 0x0001, 0x1078, 0x34ca, 0x007c, 0x127e,
- 0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x362f, 0x0d7f, 0x087f,
- 0x7108, 0x7008, 0xa106, 0x00c0, 0x3638, 0xa184, 0x4000, 0x00c0,
- 0x3638, 0xa184, 0x0003, 0x00c0, 0x364f, 0x6828, 0xa005, 0x0040,
- 0x365d, 0x0020, 0x364f, 0x1078, 0x348f, 0x0078, 0x365d, 0x00a0,
- 0x3656, 0x7108, 0x1078, 0x33e7, 0x0078, 0x3638, 0x7007, 0x0010,
- 0x00a0, 0x3658, 0x7108, 0x1078, 0x33e7, 0x7008, 0xa086, 0x0008,
- 0x00c0, 0x3638, 0x7000, 0xa005, 0x00c0, 0x3638, 0x2049, 0x0000,
- 0x127f, 0x2000, 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0d7e,
- 0x2091, 0x2200, 0x0d7f, 0x2049, 0x366b, 0xad80, 0x0011, 0x20a0,
- 0x2099, 0x0031, 0x700c, 0xa084, 0x00ff, 0x682a, 0x7007, 0x0008,
- 0x7007, 0x0002, 0x7003, 0x0001, 0x0040, 0x3689, 0x8000, 0x80ac,
- 0x53a5, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x368b,
- 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, 0x127f,
- 0x2000, 0x007c, 0x2091, 0x6000, 0x78c0, 0xa005, 0x0040, 0x36af,
- 0x798c, 0x70d0, 0xa106, 0x00c0, 0x36af, 0x7804, 0xa005, 0x0040,
- 0x36af, 0x7807, 0x0000, 0x0068, 0x36af, 0x2091, 0x4080, 0x7820,
- 0x8001, 0x7822, 0x00c0, 0x370f, 0x7824, 0x7822, 0x2091, 0x8000,
- 0x78f0, 0xa005, 0x0040, 0x36dc, 0x78d4, 0xa005, 0x00c0, 0x36dc,
- 0x3a10, 0xa284, 0x0002, 0x00c0, 0x36cc, 0x78d7, 0x0007, 0x2009,
- 0xff01, 0x200a, 0x0078, 0x36dc, 0xa284, 0x0001, 0x00c0, 0x36d4,
- 0x78ef, 0x0000, 0x0078, 0x36dc, 0x78ec, 0xa005, 0x00c0, 0x36dc,
- 0x78d7, 0x0008, 0x78ef, 0x0001, 0x2069, 0x3940, 0x6800, 0xa084,
- 0x0007, 0x0040, 0x36f3, 0xa086, 0x0002, 0x0040, 0x36f3, 0x6830,
- 0xa00d, 0x0040, 0x36f3, 0x2104, 0xa005, 0x0040, 0x36f3, 0x8001,
- 0x200a, 0x0040, 0x37b1, 0x7848, 0xa005, 0x0040, 0x3703, 0x8001,
- 0x784a, 0x00c0, 0x3703, 0x0f7e, 0x2079, 0x0100, 0x1078, 0x316a,
- 0x0f7f, 0x1078, 0x1cf6, 0x68c4, 0xa005, 0x0040, 0x370f, 0x8001,
- 0x68c6, 0x00c0, 0x370f, 0x68a3, 0x0000, 0x68a7, 0x0001, 0x1078,
- 0x3716, 0x1078, 0x373b, 0x2091, 0x8001, 0x007c, 0x7834, 0x8001,
- 0x7836, 0x00c0, 0x373a, 0x7838, 0x7836, 0x2091, 0x8000, 0x7844,
- 0xa005, 0x00c0, 0x3725, 0x2001, 0x0101, 0x8001, 0x7846, 0xa080,
- 0x4280, 0x2040, 0x2004, 0xa065, 0x0040, 0x373a, 0x6024, 0xa005,
- 0x0040, 0x3736, 0x8001, 0x6026, 0x0040, 0x376a, 0x6000, 0x2c40,
- 0x0078, 0x372b, 0x007c, 0x7828, 0x8001, 0x782a, 0x00c0, 0x3769,
- 0x782c, 0x782a, 0x7830, 0xa005, 0x00c0, 0x3748, 0x2001, 0x0080,
- 0x8001, 0x7832, 0x8003, 0x8003, 0x8003, 0x8003, 0xa090, 0x3a80,
- 0xa298, 0x0002, 0x2304, 0xa084, 0x0008, 0x0040, 0x3769, 0xa290,
- 0x0009, 0x2204, 0xa005, 0x0040, 0x3761, 0x8001, 0x2012, 0x00c0,
- 0x3769, 0x2304, 0xa084, 0xfff7, 0xa085, 0x0080, 0x201a, 0x1078,
- 0x1cf6, 0x007c, 0x2069, 0x3940, 0x6800, 0xa005, 0x0040, 0x3774,
- 0x683c, 0xac06, 0x0040, 0x37b1, 0x601b, 0x0006, 0x60b4, 0xa084,
- 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0060, 0x6022,
- 0x6000, 0x2042, 0x6714, 0x6fb6, 0x1078, 0x18b4, 0x6818, 0xa005,
- 0x0040, 0x378c, 0x8001, 0x681a, 0x6808, 0xa084, 0xffef, 0x680a,
- 0x6810, 0x8001, 0x00d0, 0x3796, 0x1078, 0x1eac, 0x6812, 0x602f,
- 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078, 0x1a26, 0x2069, 0x3940,
- 0x2001, 0x0006, 0x68a2, 0x7944, 0xa184, 0x0100, 0x00c0, 0x37ac,
- 0x69ba, 0x2001, 0x0004, 0x68a2, 0x1078, 0x1cf1, 0x2091, 0x8001,
- 0x007c, 0x2009, 0x394f, 0x2164, 0x2069, 0x0100, 0x1078, 0x1e57,
- 0x601b, 0x0006, 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084,
- 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000,
- 0x6830, 0xa084, 0x0040, 0x0040, 0x37ed, 0x684b, 0x0004, 0x20a9,
- 0x0014, 0x6848, 0xa084, 0x0004, 0x0040, 0x37da, 0x0070, 0x37da,
- 0x0078, 0x37d1, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084,
- 0x0001, 0x0040, 0x37e7, 0x0070, 0x37e7, 0x0078, 0x37de, 0x20a9,
- 0x00fa, 0x0070, 0x37ed, 0x0078, 0x37e9, 0x6808, 0xa084, 0xfffd,
- 0x680a, 0x681b, 0x0047, 0x2009, 0x3968, 0x200b, 0x0007, 0x784c,
- 0x784a, 0x2091, 0x8001, 0x007c, 0x2079, 0x3900, 0x1078, 0x3827,
- 0x1078, 0x380b, 0x1078, 0x3819, 0x7833, 0x0000, 0x7847, 0x0000,
- 0x784b, 0x0000, 0x007c, 0x2019, 0x000c, 0x2011, 0x3946, 0x2204,
- 0xa086, 0x003c, 0x0040, 0x3816, 0x2019, 0x0008, 0x7b2a, 0x7b2e,
- 0x007c, 0x2019, 0x0039, 0x2011, 0x3946, 0x2204, 0xa086, 0x003c,
- 0x0040, 0x3824, 0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019,
- 0x3971, 0x2011, 0x3946, 0x2204, 0xa086, 0x003c, 0x0040, 0x3832,
- 0x2019, 0x2626, 0x7b22, 0x7b26, 0x783f, 0x0000, 0x7843, 0x000a,
- 0x007c, 0x8e59
+ 0x00ff, 0x007e, 0x6804, 0xa084, 0x0008, 0x007f, 0x0040, 0x488c,
+ 0xa0b8, 0x46c3, 0x0078, 0x488e, 0xa0b8, 0x46bb, 0x7e08, 0xa6b5,
+ 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x489c,
+ 0xa18e, 0x000f, 0x00c0, 0x48a5, 0x681c, 0xa084, 0x0040, 0x0040,
+ 0x48ac, 0xa6b5, 0x0001, 0x0078, 0x48ac, 0x681c, 0xa084, 0x0040,
+ 0x0040, 0x48ac, 0xa6b5, 0x0001, 0x7007, 0x0004, 0x7004, 0xa084,
+ 0x0004, 0x00c0, 0x48ae, 0x2400, 0xa305, 0x00c0, 0x48b9, 0x0078,
+ 0x48df, 0x2c58, 0x2704, 0x6104, 0xac60, 0x6000, 0xa400, 0x701a,
+ 0x6004, 0xa301, 0x701e, 0xa184, 0x0008, 0x0040, 0x48cf, 0x6010,
+ 0xa081, 0x0000, 0x7022, 0x6014, 0xa081, 0x0000, 0x7026, 0x6208,
+ 0x2400, 0xa202, 0x7012, 0x620c, 0x2300, 0xa203, 0x7016, 0x7602,
+ 0x7007, 0x0001, 0x2b60, 0x1078, 0x483e, 0x0078, 0x48e1, 0x1078,
+ 0x49c4, 0x00c0, 0x48df, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e,
+ 0x2091, 0x2200, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
+ 0x00c0, 0x48ed, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x127e,
+ 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x48f7, 0x7007, 0x0004,
+ 0x7004, 0xa084, 0x0004, 0x00c0, 0x4900, 0x7e08, 0xa6b5, 0x000c,
+ 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4913, 0xa18e,
+ 0x000f, 0x00c0, 0x491e, 0x681c, 0xa084, 0x0040, 0x0040, 0x491a,
+ 0xa6b5, 0x0001, 0x6840, 0x2050, 0x0078, 0x4927, 0x681c, 0xa084,
+ 0x0020, 0x00c0, 0x4925, 0xa6b5, 0x0001, 0x6828, 0x2050, 0x2d60,
+ 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x46c9, 0x273c, 0x87fb, 0x00c0,
+ 0x493b, 0x0048, 0x4935, 0x1078, 0x23ca, 0x689c, 0xa065, 0x0040,
+ 0x493f, 0x0078, 0x4928, 0x1078, 0x49c4, 0x00c0, 0x493b, 0x127f,
+ 0x2000, 0x007c, 0x127e, 0x007e, 0x017e, 0x0d7e, 0x2091, 0x2200,
+ 0x0d7f, 0x037f, 0x047f, 0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c,
+ 0x00ff, 0xa186, 0x0007, 0x0040, 0x4959, 0xa18e, 0x000f, 0x00c0,
+ 0x4962, 0x681c, 0xa084, 0x0040, 0x0040, 0x4969, 0xa6b5, 0x0001,
+ 0x0078, 0x4969, 0x681c, 0xa084, 0x0040, 0x0040, 0x4969, 0xa6b5,
+ 0x0001, 0x2049, 0x4942, 0x017e, 0x6904, 0xa18c, 0x00ff, 0xa186,
+ 0x0007, 0x0040, 0x4977, 0xa18e, 0x000f, 0x00c0, 0x497a, 0x6840,
+ 0x0078, 0x497b, 0x6828, 0x017f, 0xa055, 0x0040, 0x49c1, 0x2d70,
+ 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x46c9, 0x273c, 0x87fb,
+ 0x00c0, 0x4995, 0x0048, 0x498e, 0x1078, 0x23ca, 0x709c, 0xa075,
+ 0x2060, 0x0040, 0x49c1, 0x0078, 0x4981, 0x2704, 0xae68, 0x6808,
+ 0xa422, 0x680c, 0xa31b, 0x0048, 0x49ae, 0x8a51, 0x00c0, 0x49a2,
+ 0x1078, 0x23ca, 0x8738, 0x2704, 0xa005, 0x00c0, 0x4996, 0x709c,
+ 0xa075, 0x2060, 0x0040, 0x49c1, 0x0078, 0x4981, 0x8422, 0x8420,
+ 0x831a, 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300,
+ 0xa11b, 0x00c8, 0x49bd, 0x1078, 0x23ca, 0x2071, 0x0020, 0x0078,
+ 0x48ac, 0x127f, 0x2000, 0x007c, 0x7008, 0xa084, 0x0003, 0xa086,
+ 0x0003, 0x0040, 0x49ec, 0x2704, 0xac08, 0x2104, 0x701a, 0x8108,
+ 0x2104, 0x701e, 0x8108, 0x2104, 0x7012, 0x8108, 0x2104, 0x7016,
+ 0x6004, 0xa084, 0x0008, 0x0040, 0x49e3, 0x8108, 0x2104, 0x7022,
+ 0x8108, 0x2104, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010, 0xa085,
+ 0x0001, 0x7006, 0x1078, 0x483e, 0x007c, 0x127e, 0x007e, 0x0d7e,
+ 0x2091, 0x2200, 0x2049, 0x49ed, 0x0d7f, 0x087f, 0x7108, 0xa184,
+ 0x0003, 0x00c0, 0x4a17, 0x017e, 0x6904, 0xa18c, 0x00ff, 0xa186,
+ 0x0007, 0x0040, 0x4a07, 0xa18e, 0x000f, 0x00c0, 0x4a0a, 0x6840,
+ 0x0078, 0x4a0b, 0x6828, 0x017f, 0xa005, 0x0040, 0x4a25, 0x0078,
+ 0x464a, 0x0020, 0x4a17, 0x1078, 0x4801, 0x0078, 0x4a25, 0x00a0,
+ 0x4a1e, 0x7108, 0x1078, 0x477a, 0x0078, 0x49f6, 0x7007, 0x0010,
+ 0x00a0, 0x4a20, 0x7108, 0x1078, 0x477a, 0x7008, 0xa086, 0x0008,
+ 0x00c0, 0x49f6, 0x7000, 0xa005, 0x00c0, 0x49f6, 0x7003, 0x0000,
+ 0x2049, 0x0000, 0x127f, 0x2000, 0x007c, 0x127e, 0x147e, 0x137e,
+ 0x157e, 0x0c7e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x4a35,
+ 0xad80, 0x0011, 0x20a0, 0x2099, 0x0031, 0x700c, 0xa084, 0x00ff,
+ 0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0040,
+ 0x4a54, 0x8000, 0x80ac, 0x53a5, 0x7007, 0x0004, 0x7004, 0xa084,
+ 0x0004, 0x00c0, 0x4a56, 0x0c7f, 0x2049, 0x0000, 0x7003, 0x0000,
+ 0x157f, 0x137f, 0x147f, 0x127f, 0x2000, 0x007c, 0x2091, 0x6000,
+ 0x2091, 0x8000, 0x78cc, 0xa005, 0x0040, 0x4a7d, 0x7994, 0x70d0,
+ 0xa106, 0x00c0, 0x4a7d, 0x7804, 0xa005, 0x0040, 0x4a7d, 0x7807,
+ 0x0000, 0x0068, 0x4a7d, 0x2091, 0x4080, 0x7820, 0x8001, 0x7822,
+ 0x00c0, 0x4ad8, 0x7824, 0x7822, 0x2069, 0x5040, 0x6800, 0xa084,
+ 0x0007, 0x0040, 0x4a9b, 0xa086, 0x0002, 0x0040, 0x4a9b, 0x6834,
+ 0xa00d, 0x0040, 0x4a9b, 0x2104, 0xa005, 0x0040, 0x4a9b, 0x8001,
+ 0x200a, 0x0040, 0x4b80, 0x7848, 0xa005, 0x0040, 0x4aa9, 0x8001,
+ 0x784a, 0x00c0, 0x4aa9, 0x2009, 0x0102, 0x6844, 0x200a, 0x1078,
+ 0x21b1, 0x6890, 0xa005, 0x0040, 0x4ab5, 0x8001, 0x6892, 0x00c0,
+ 0x4ab5, 0x686f, 0x0000, 0x6873, 0x0001, 0x2061, 0x5300, 0x20a9,
+ 0x0100, 0x2009, 0x0002, 0x6034, 0xa005, 0x0040, 0x4acb, 0x8001,
+ 0x6036, 0x00c0, 0x4acb, 0x6010, 0xa005, 0x0040, 0x4acb, 0x017e,
+ 0x1078, 0x21b1, 0x017f, 0xace0, 0x0010, 0x0070, 0x4ad1, 0x0078,
+ 0x4abb, 0x8109, 0x0040, 0x4ad8, 0x20a9, 0x0100, 0x0078, 0x4abb,
+ 0x1078, 0x4ae5, 0x1078, 0x4b0a, 0x2009, 0x5051, 0x2104, 0x2009,
+ 0x0102, 0x200a, 0x2091, 0x8001, 0x007c, 0x7834, 0x8001, 0x7836,
+ 0x00c0, 0x4b09, 0x7838, 0x7836, 0x2091, 0x8000, 0x7844, 0xa005,
+ 0x00c0, 0x4af4, 0x2001, 0x0101, 0x8001, 0x7846, 0xa080, 0x7300,
+ 0x2040, 0x2004, 0xa065, 0x0040, 0x4b09, 0x6024, 0xa005, 0x0040,
+ 0x4b05, 0x8001, 0x6026, 0x0040, 0x4b39, 0x6000, 0x2c40, 0x0078,
+ 0x4afa, 0x007c, 0x7828, 0x8001, 0x782a, 0x00c0, 0x4b38, 0x782c,
+ 0x782a, 0x7830, 0xa005, 0x00c0, 0x4b17, 0x2001, 0x0200, 0x8001,
+ 0x7832, 0x8003, 0x8003, 0x8003, 0x8003, 0xa090, 0x5300, 0xa298,
+ 0x0002, 0x2304, 0xa084, 0x0008, 0x0040, 0x4b38, 0xa290, 0x0009,
+ 0x2204, 0xa005, 0x0040, 0x4b30, 0x8001, 0x2012, 0x00c0, 0x4b38,
+ 0x2304, 0xa084, 0xfff7, 0xa085, 0x0080, 0x201a, 0x1078, 0x21b1,
+ 0x007c, 0x2069, 0x5040, 0x6800, 0xa005, 0x0040, 0x4b43, 0x6848,
+ 0xac06, 0x0040, 0x4b80, 0x601b, 0x0006, 0x60b4, 0xa084, 0x3f00,
+ 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0060, 0x6022, 0x6000,
+ 0x2042, 0x6714, 0x6f82, 0x1078, 0x1956, 0x6818, 0xa005, 0x0040,
+ 0x4b5b, 0x8001, 0x681a, 0x6808, 0xa084, 0xffef, 0x680a, 0x6810,
+ 0x8001, 0x00d0, 0x4b65, 0x1078, 0x23ca, 0x6812, 0x602f, 0x0000,
+ 0x6033, 0x0000, 0x2c68, 0x1078, 0x1c53, 0x2069, 0x5040, 0x7944,
+ 0xa184, 0x0100, 0x2001, 0x0006, 0x686e, 0x00c0, 0x4b7b, 0x6986,
+ 0x2001, 0x0004, 0x686e, 0x1078, 0x21ac, 0x2091, 0x8001, 0x007c,
+ 0x2069, 0x0100, 0x2009, 0x5040, 0x2104, 0xa084, 0x0007, 0x0040,
+ 0x4bdc, 0xa086, 0x0007, 0x00c0, 0x4b96, 0x0d7e, 0x2009, 0x5052,
+ 0x216c, 0x1078, 0x3a1a, 0x0d7f, 0x0078, 0x4bdc, 0x2009, 0x5052,
+ 0x2164, 0x1078, 0x2375, 0x601b, 0x0006, 0x6858, 0xa084, 0x3f00,
+ 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f,
+ 0x0000, 0x6033, 0x0000, 0x6830, 0xa084, 0x0040, 0x0040, 0x4bd0,
+ 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004, 0x0040,
+ 0x4bbd, 0x0070, 0x4bbd, 0x0078, 0x4bb4, 0x684b, 0x0009, 0x20a9,
+ 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, 0x4bca, 0x0070, 0x4bca,
+ 0x0078, 0x4bc1, 0x20a9, 0x00fa, 0x0070, 0x4bd0, 0x0078, 0x4bcc,
+ 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0048, 0x2009, 0x505b,
+ 0x200b, 0x0007, 0x784c, 0x784a, 0x2091, 0x8001, 0x007c, 0x2079,
+ 0x5000, 0x1078, 0x4c0a, 0x1078, 0x4bee, 0x1078, 0x4bfc, 0x7833,
+ 0x0000, 0x7847, 0x0000, 0x784b, 0x0000, 0x007c, 0x2019, 0x0003,
+ 0x2011, 0x5046, 0x2204, 0xa086, 0x003c, 0x0040, 0x4bf9, 0x2019,
+ 0x0002, 0x7b2a, 0x7b2e, 0x007c, 0x2019, 0x0039, 0x2011, 0x5046,
+ 0x2204, 0xa086, 0x003c, 0x0040, 0x4c07, 0x2019, 0x0027, 0x7b36,
+ 0x7b3a, 0x007c, 0x2019, 0x3971, 0x2011, 0x5046, 0x2204, 0xa086,
+ 0x003c, 0x0040, 0x4c15, 0x2019, 0x2626, 0x7b22, 0x7b26, 0x783f,
+ 0x0000, 0x7843, 0x000a, 0x007c, 0x0020, 0x002b, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0014,
+ 0x0014, 0x9849, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014,
+ 0x0014, 0x0080, 0x000f, 0x0000, 0x0201, 0x0604, 0x0c08, 0x2120,
+ 0x4022, 0xf880, 0x0018, 0x300b, 0xa201, 0x0014, 0xa200, 0x0014,
+ 0xa200, 0x0214, 0x0000, 0x006c, 0x0002, 0x0014, 0x98d5, 0x009e,
+ 0x009b, 0xa202, 0x8838, 0x3806, 0x8839, 0x20c3, 0x0864, 0x9889,
+ 0x28c1, 0x9cb6, 0xa203, 0x300c, 0x2846, 0x8161, 0x846a, 0x8300,
+ 0x1856, 0x883a, 0x9865, 0x28f2, 0x9c95, 0x9858, 0x300c, 0x28e1,
+ 0x9c95, 0x2809, 0xa206, 0x64c0, 0x67a0, 0x6fc0, 0x1814, 0x883b,
+ 0x782c, 0x786d, 0x9879, 0x282b, 0xa207, 0x64a0, 0x67a0, 0x6fc0,
+ 0x1814, 0x883b, 0x7822, 0x883e, 0x987d, 0x8576, 0x8677, 0x206b,
+ 0x28c1, 0x9cb6, 0x2044, 0x2103, 0x20a2, 0x2081, 0x9865, 0xa209,
+ 0x2901, 0x9891, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a, 0x883c,
+ 0x1fe2, 0xc601, 0xa20a, 0x856e, 0x0704, 0x9c95, 0x0014, 0xa204,
+ 0xa300, 0x3009, 0x19e2, 0xf868, 0x8176, 0x86eb, 0x85eb, 0x872e,
+ 0x87a9, 0x883f, 0x08e6, 0x9895, 0xf881, 0x9890, 0xc801, 0x0014,
+ 0xf8c1, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfb02, 0x1de2, 0x0014,
+ 0x8532, 0xf241, 0x0014, 0x1de2, 0x84a8, 0xd7a0, 0x1fe6, 0x0014,
+ 0xa208, 0x6043, 0x8008, 0x1dc1, 0x0016, 0x8300, 0x8160, 0x842a,
+ 0xf041, 0x3008, 0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d5,
+ 0x8822, 0x0016, 0x8000, 0x2847, 0x1011, 0x98c8, 0x8000, 0xa000,
+ 0x2802, 0x1011, 0x98ce, 0x9865, 0x283e, 0x1011, 0x98d2, 0xa20b,
+ 0x0017, 0x300c, 0xa300, 0x1de2, 0xdb81, 0x0014, 0x0210, 0x98df,
+ 0x0014, 0x26e0, 0x873a, 0xfb02, 0x19f2, 0x1fe2, 0x0014, 0xa20d,
+ 0x3806, 0x0210, 0x9cbb, 0x0704, 0x0000, 0x006c, 0x0002, 0x984f,
+ 0x0014, 0x009e, 0x00a0, 0x0017, 0x60ff, 0x300c, 0x8720, 0xa211,
+ 0x9cd0, 0x8772, 0x8837, 0x2101, 0x987a, 0x10d2, 0x78e2, 0x9cd3,
+ 0x9859, 0xd984, 0xf0e2, 0xf0a1, 0x98cd, 0x0014, 0x8831, 0xd166,
+ 0x8830, 0x800f, 0x9401, 0xb520, 0xc802, 0x8820, 0x987a, 0x2301,
+ 0x987a, 0x10d2, 0x78e4, 0x9cd3, 0x8821, 0x8820, 0x9859, 0xf123,
+ 0xf142, 0xf101, 0x98c6, 0x10d2, 0x70f6, 0x8832, 0x8203, 0x870c,
+ 0xd99e, 0x6001, 0x0014, 0x6845, 0x0214, 0xa21b, 0x9cd0, 0x2001,
+ 0x98c5, 0x8201, 0x1852, 0xd184, 0xd163, 0x8834, 0x8001, 0x988d,
+ 0x3027, 0x84a8, 0x1a56, 0x8833, 0x0014, 0xa218, 0x6981, 0x9cbc,
+ 0x6b2a, 0x6902, 0x1834, 0x989d, 0x1814, 0x8010, 0x8592, 0x8026,
+ 0x84b9, 0x7021, 0x0014, 0xa300, 0x69e1, 0x9ca9, 0x694b, 0xa213,
+ 0x1462, 0xa213, 0x8000, 0x16e1, 0x98b5, 0x8023, 0x16e1, 0x8001,
+ 0x10f1, 0x0016, 0x6969, 0xa214, 0x61c2, 0x8002, 0x14e1, 0x8004,
+ 0x16e1, 0x0101, 0x300a, 0x8827, 0x0014, 0xa217, 0x9cbc, 0x0014,
+ 0xa300, 0x8181, 0x842a, 0x84a8, 0x1ce6, 0x882c, 0x0016, 0xa212,
+ 0x9cd0, 0x10d2, 0x70e4, 0x0004, 0x8007, 0x9424, 0xcc1a, 0x9cd3,
+ 0x98c5, 0x8827, 0x300a, 0x0013, 0x8000, 0x84a4, 0x0016, 0x11c2,
+ 0x211e, 0x870e, 0xa21d, 0x0014, 0x878e, 0x0016, 0xa21c, 0x1035,
+ 0x9891, 0xa210, 0xa000, 0x8010, 0x8592, 0x853b, 0xd044, 0x8022,
+ 0x3807, 0x84bb, 0x98ea, 0x8021, 0x3807, 0x84b9, 0x300c, 0x817e,
+ 0x872b, 0x8772, 0x9891, 0x0000, 0x0020, 0x002b, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0014,
+ 0x0014, 0x9849, 0x0014, 0x0014, 0x98ea, 0x98d5, 0x0014, 0x0014,
+ 0x0014, 0x0080, 0x013f, 0x0000, 0x0201, 0x0604, 0x0c08, 0x2120,
+ 0x4022, 0xf880, 0x0018, 0x300b, 0xa201, 0x0014, 0xa200, 0x0014,
+ 0xa200, 0x0214, 0xa202, 0x8838, 0x3806, 0x8839, 0x20c3, 0x0864,
+ 0xa833, 0x28c1, 0x9cb6, 0xa203, 0x300c, 0x2846, 0x8161, 0x846a,
+ 0x8300, 0x1856, 0x883a, 0xa804, 0x28f2, 0x9c95, 0xa8f4, 0x300c,
+ 0x28e1, 0x9c95, 0x2809, 0xa206, 0x64c0, 0x67a0, 0x6fc0, 0x1814,
+ 0x883b, 0x782c, 0x786d, 0xa808, 0x282b, 0xa207, 0x64a0, 0x67a0,
+ 0x6fc0, 0x1814, 0x883b, 0x7822, 0x883e, 0xa802, 0x8576, 0x8677,
+ 0x206b, 0x28c1, 0x9cb6, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8e0,
+ 0xa209, 0x2901, 0xa809, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a,
+ 0x883c, 0x1fe2, 0xc601, 0xa20a, 0x856e, 0x0704, 0x9c95, 0x0014,
+ 0xa204, 0xa300, 0x3009, 0x19e2, 0xf868, 0x8176, 0x86eb, 0x85eb,
+ 0x872e, 0x87a9, 0x883f, 0x08e6, 0xa8f3, 0xf881, 0xa8ec, 0xc801,
+ 0x0014, 0xf8c1, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfb02, 0x1de2,
+ 0x0014, 0x8532, 0xf241, 0x0014, 0x1de2, 0x84a8, 0xd7a0, 0x1fe6,
+ 0x0014, 0xa208, 0x6043, 0x8008, 0x1dc1, 0x0016, 0x8300, 0x8160,
+ 0x842a, 0xf041, 0x3008, 0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011,
+ 0x20d5, 0x8822, 0x0016, 0x8000, 0x2847, 0x1011, 0xa8fc, 0x8000,
+ 0xa000, 0x2802, 0x1011, 0xa8fd, 0xa893, 0x283e, 0x1011, 0xa8fd,
+ 0xa20b, 0x0017, 0x300c, 0xa300, 0x1de2, 0xdb81, 0x0014, 0x0210,
+ 0xa801, 0x0014, 0x26e0, 0x873a, 0xfb02, 0x19f2, 0x1fe2, 0x0014,
+ 0xa20d, 0x3806, 0x0210, 0x9cbb, 0x0704, 0x0017, 0x60ff, 0x300c,
+ 0x8720, 0xa211, 0x9d6b, 0x8772, 0x8837, 0x2101, 0xa821, 0x10d2,
+ 0x78e2, 0x9d6e, 0xa8fc, 0xd984, 0xf0e2, 0xf0a1, 0xa86c, 0x0014,
+ 0x8831, 0xd166, 0x8830, 0x800f, 0x9401, 0xb520, 0xc802, 0x8820,
+ 0xa80f, 0x2301, 0xa80d, 0x10d2, 0x78e4, 0x9d6e, 0x8821, 0x8820,
+ 0xa8e6, 0xf123, 0xf142, 0xf101, 0xa84f, 0x10d2, 0x70f6, 0x8832,
+ 0x8203, 0x870c, 0xd99e, 0x6001, 0x0014, 0x6845, 0x0214, 0xa21b,
+ 0x9d6b, 0x2001, 0xa840, 0x8201, 0x1852, 0xd184, 0xd163, 0x8834,
+ 0x8001, 0xa801, 0x3027, 0x84a8, 0x1a56, 0x8833, 0x0014, 0xa218,
+ 0x6981, 0x9d57, 0x6b2a, 0x6902, 0x1834, 0xa805, 0x1814, 0x8010,
+ 0x8592, 0x8026, 0x84b9, 0x7021, 0x0014, 0xa300, 0x69e1, 0x9d44,
+ 0x694b, 0xa213, 0x1462, 0xa213, 0x8000, 0x16e1, 0xa80c, 0x8023,
+ 0x16e1, 0x8001, 0x10f1, 0x0016, 0x6969, 0xa214, 0x61c2, 0x8002,
+ 0x14e1, 0x8004, 0x16e1, 0x0101, 0x300a, 0x8827, 0x0014, 0xa217,
+ 0x9d57, 0x0014, 0xa300, 0x8181, 0x842a, 0x84a8, 0x1ce6, 0x882c,
+ 0x0016, 0xa212, 0x9d6b, 0x10d2, 0x70e4, 0x0004, 0x8007, 0x9424,
+ 0xcc1a, 0x9d6e, 0xa8f8, 0x8827, 0x300a, 0x0013, 0x8000, 0x84a4,
+ 0x0016, 0x11c2, 0x211e, 0x870e, 0xa21d, 0x0014, 0x878e, 0x0016,
+ 0xa21c, 0x1035, 0xa8b4, 0xa210, 0x3807, 0x300c, 0x817e, 0x872b,
+ 0x8772, 0xa8ad, 0x0000, 0x8ec6
};
#endif /* RELOAD_FIRMWARE */
-static const unsigned short risc_code_length01 = 0x283a;
+static const unsigned short risc_code_length01 = 0x3f14;
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index c3d4102bf..6def71bcb 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -223,9 +223,15 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
struct qlogicpti_regs *qregs = qpti->qregs;
u_short param[6];
+ unsigned short risc_code_addr;
int loop_count, i;
unsigned long flags;
+ if(qpti->is_pti != 0)
+ risc_code_addr = pti_risc_code_addr01;
+ else
+ risc_code_addr = sbus_risc_code_addr01;
+
save_flags(flags); cli();
qregs->hcctrl = HCCTRL_PAUSE;
@@ -264,7 +270,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
/* Get RISC to start executing the firmware code. */
param[0] = MBOX_EXEC_FIRMWARE;
- param[1] = risc_code_addr01;
+ param[1] = risc_code_addr;
if(qlogicpti_mbox_command(qpti, param, 1)) {
printk(KERN_EMERG "qlogicpti%d: Cannot execute ISP firmware.\n",
qpti->qpti_id);
@@ -352,21 +358,32 @@ __initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
struct qlogicpti_regs *qregs = qpti->qregs;
unsigned short csum = 0;
unsigned short param[6];
+ unsigned short *risc_code, risc_code_addr, risc_code_length;
unsigned long flags;
#if !defined(MODULE) && !defined(__sparc_v9__)
unsigned long dvma_addr;
#endif
int i, timeout;
+ if(qpti->is_pti != 0) {
+ risc_code = &pti_risc_code01[0];
+ risc_code_addr = pti_risc_code_addr01;
+ risc_code_length = pti_risc_code_length01;
+ } else {
+ risc_code = &sbus_risc_code01[0];
+ risc_code_addr = sbus_risc_code_addr01;
+ risc_code_length = sbus_risc_code_length01;
+ }
+
save_flags(flags); cli();
/* Verify the checksum twice, one before loading it, and once
* afterwards via the mailbox commands.
*/
- for(i = 0; i < risc_code_length01; i++)
- csum += risc_code01[i];
+ for(i = 0; i < risc_code_length; i++)
+ csum += risc_code[i];
if(csum) {
- printk(KERN_EMERG "qlogicpti%d: AIeee, firmware checksum failed!",
+ printk(KERN_EMERG "qlogicpti%d: Aieee, firmware checksum failed!",
qpti->qpti_id);
return 1;
}
@@ -406,11 +423,6 @@ __initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
qpti->differential = 0;
qregs->hcctrl = HCCTRL_REL;
- /* XXX Talk to PTI engineer about the following, ISP always
- * XXX returns 0x4001 return status for stop firmware command,
- * XXX documentation claims this means the cmd is unsupported
- * XXX on this ISP. I think something fishy is going on.
- */
param[0] = MBOX_STOP_FIRMWARE;
param[1] = param[2] = param[3] = param[4] = param[5] = 0;
if(qlogicpti_mbox_command(qpti, param, 1)) {
@@ -423,13 +435,13 @@ __initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
/* Load the firmware. */
#if !defined(MODULE) && !defined(__sparc_v9__)
if (sparc_cpu_model != sun4d) {
- dvma_addr = (unsigned long) mmu_lockarea((char *)&risc_code01[0],
- (sizeof(u_short) * risc_code_length01));
+ dvma_addr = (unsigned long) mmu_lockarea((char *)&risc_code[0],
+ (sizeof(u_short) * risc_code_length));
param[0] = MBOX_LOAD_RAM;
- param[1] = risc_code_addr01;
+ param[1] = risc_code_addr;
param[2] = (dvma_addr >> 16);
param[3] = (dvma_addr & 0xffff);
- param[4] = (sizeof(u_short) * risc_code_length01);
+ param[4] = (sizeof(u_short) * risc_code_length);
if(qlogicpti_mbox_command(qpti, param, 1) ||
(param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: Firmware dload failed, I'm bolixed!\n",
@@ -437,14 +449,14 @@ __initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
restore_flags(flags);
return 1;
}
- mmu_unlockarea((char *)dvma_addr, (sizeof(u_short) * risc_code_length01));
+ mmu_unlockarea((char *)dvma_addr, (sizeof(u_short) * risc_code_length));
} else
#endif
/* We need to do it this slow way always on Ultra, SS[12]000. */
- for(i = 0; i < risc_code_length01; i++) {
+ for(i = 0; i < risc_code_length; i++) {
param[0] = MBOX_WRITE_RAM_WORD;
- param[1] = risc_code_addr01 + i;
- param[2] = risc_code01[i];
+ param[1] = risc_code_addr + i;
+ param[2] = risc_code[i];
if(qlogicpti_mbox_command(qpti, param, 1) ||
param[0] != MBOX_COMMAND_COMPLETE) {
printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n",
@@ -464,7 +476,7 @@ __initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
/* Ask ISP to verify the checksum of the new code. */
param[0] = MBOX_VERIFY_CHECKSUM;
- param[1] = risc_code_addr01;
+ param[1] = risc_code_addr;
if(qlogicpti_mbox_command(qpti, param, 1) ||
(param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: New firmware csum failure!\n",
@@ -475,7 +487,7 @@ __initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
/* Start using newly downloaded firmware. */
param[0] = MBOX_EXEC_FIRMWARE;
- param[1] = risc_code_addr01;
+ param[1] = risc_code_addr;
qlogicpti_mbox_command(qpti, param, 1);
param[0] = MBOX_ABOUT_FIRMWARE;
@@ -491,16 +503,18 @@ __initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
qpti->fware_majrev = param[1];
qpti->fware_minrev = param[2];
- /* Load scsi initiator ID and interrupt level into sbus static ram. */
- param[0] = MBOX_WRITE_RAM_WORD;
- param[1] = 0xff80;
- param[2] = (unsigned short) qpti->scsi_id;
- qlogicpti_mbox_command(qpti, param, 1);
-
- param[0] = MBOX_WRITE_RAM_WORD;
- param[1] = 0xff00;
- param[2] = (unsigned short) 3;
- qlogicpti_mbox_command(qpti, param, 1);
+ if(qpti->is_pti != 0) {
+ /* Load scsi initiator ID and interrupt level into sbus static ram. */
+ param[0] = MBOX_WRITE_RAM_WORD;
+ param[1] = 0xff80;
+ param[2] = (unsigned short) qpti->scsi_id;
+ qlogicpti_mbox_command(qpti, param, 1);
+
+ param[0] = MBOX_WRITE_RAM_WORD;
+ param[1] = 0xff00;
+ param[2] = (unsigned short) 3;
+ qlogicpti_mbox_command(qpti, param, 1);
+ }
restore_flags(flags);
return 0;
@@ -617,6 +631,10 @@ __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
/* We are wide capable, 16 targets. */
qpti_host->max_id = MAX_TARGETS;
+#ifdef __sparc_v9__
+ qpti_host->unchecked_isa_dma = 1;
+#endif
+
/* Setup back pointers and misc. state. */
qpti->qhost = qpti_host;
qpti->qdev = qpti_dev;
@@ -638,7 +656,8 @@ __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
sizeof(qpti->prom_name));
qpti->prom_node = qpti_node;
- is_pti = strcmp (qpti->prom_name, "QLGC,isp");
+ qpti->is_pti = is_pti =
+ (strcmp (qpti->prom_name, "QLGC,isp") != 0);
/* Setup the reg property for this device. */
prom_apply_sbus_ranges(qpti->qdev->my_bus,
@@ -728,6 +747,9 @@ qpti_irq_acquired:
bsizes = (DMA_BURST32 - 1);
qpti->bursts = bsizes;
+ /* Clear out Scsi_Cmnd array. */
+ memset(qpti->cmd_slots, 0, sizeof(qpti->cmd_slots));
+
/* The request and response queues must each be aligned
* on a page boundry.
*/
@@ -747,11 +769,13 @@ qpti_irq_acquired:
/* Set adapter and per-device default values. */
qlogicpti_set_hostdev_defaults(qpti);
- if (is_pti) {
- /* Load the firmware. */
- if(qlogicpti_load_firmware(qpti))
- panic("PTI Qlogic/ISP firmware load failed");
+ /* Load the firmware. */
+ /* XXX Find out where is it possible to download
+ our sbus_risc_code on non-PTI ISP1000. */
+ if(is_pti && qlogicpti_load_firmware(qpti))
+ panic("SBUS Qlogic/ISP firmware load failed");
+ if (is_pti) {
/* Check the PTI status reg. */
if(qlogicpti_verify_tmon(qpti))
panic("PTI Qlogic/ISP tmon verification failed");
@@ -768,7 +792,10 @@ qpti_irq_acquired:
char buffer[60];
prom_getstring (qpti_node, "isp-fcode", buffer, 60);
- printk("(Firmware %s)", buffer);
+ if (buffer[0])
+ printk("(Firmware %s)", buffer);
+ if (prom_getbool(qpti_node, "differential"))
+ qpti->differential = 1;
}
printk (" [%s Wide, using %s interface]\n",
@@ -831,11 +858,6 @@ static inline void cmd_frob(struct Command_Entry *cmd, Scsi_Cmnd *Cmnd,
memset(cmd, 0, sizeof(struct Command_Entry));
cmd->hdr.entry_cnt = 1;
cmd->hdr.entry_type = ENTRY_COMMAND;
-#ifdef __sparc_v9__
- cmd->handle = (u_int) (((unsigned long)Cmnd) - PAGE_OFFSET); /* magic mushroom */
-#else
- cmd->handle = (u_int) ((unsigned long)Cmnd); /* magic mushroom */
-#endif
cmd->target_id = Cmnd->target;
cmd->target_lun = Cmnd->lun;
cmd->cdb_length = Cmnd->cmd_len;
@@ -924,9 +946,15 @@ static inline u_int load_cmd(Scsi_Cmnd *Cmnd, struct Command_Entry *cmd,
cmd->dataseg[0].d_count = Cmnd->request_bufflen;
cmd->segment_cnt = 1;
}
+
+ /* Committed, record Scsi_Cmd so we can find it later. */
+ cmd->handle = in_ptr;
+ qpti->cmd_slots[in_ptr] = Cmnd;
+
qpti->cmd_count[Cmnd->target]++;
qregs->mbox4 = in_ptr;
qpti->req_in_ptr = in_ptr;
+
return in_ptr;
}
@@ -1099,9 +1127,18 @@ static __inline__ int qlogicpti_intr_handler(struct qlogicpti *qpti)
/* This looks like a network driver! */
out_ptr = qpti->res_out_ptr;
while(out_ptr != in_ptr) {
+ u_int cmd_slot;
+
sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr];
out_ptr = NEXT_RES_PTR(out_ptr);
- Cmnd = (Scsi_Cmnd *) (((unsigned long)sts->handle)+PAGE_OFFSET);
+
+ /* We store an index in the handle, not the pointer in
+ * some form. This avoids problems due to the fact
+ * that the handle provided is only 32-bits. -DaveM
+ */
+ cmd_slot = sts->handle;
+ Cmnd = qpti->cmd_slots[cmd_slot];
+ qpti->cmd_slots[cmd_slot] = NULL;
if(sts->completion_status == CS_RESET_OCCURRED ||
sts->completion_status == CS_ABORTED ||
@@ -1144,8 +1181,8 @@ static void do_qlogicpti_intr_handler_sun4m(int irq, void *dev_id, struct pt_reg
int again;
spin_lock_irqsave(&io_request_lock, flags);
- again = 0;
do {
+ again = 0;
for_each_qlogicpti(qpti)
again |= qlogicpti_intr_handler(qpti);
} while (again);
diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h
index 67a79ab41..b58f4e28b 100644
--- a/drivers/scsi/qlogicpti.h
+++ b/drivers/scsi/qlogicpti.h
@@ -455,16 +455,24 @@ struct qlogicpti {
/* These are the hot elements in the cache, so they come first. */
struct qlogicpti *next; /* Next active adapter */
struct qlogicpti_regs *qregs; /* Adapter registers */
- u_int req_in_ptr; /* index of next request slot */
- u_int res_out_ptr; /* index of next result slot */
struct pti_queue_entry *res_cpu; /* Ptr to RESPONSE bufs (CPU) */
- __u32 res_dvma; /* Ptr to RESPONSE bufs (DVMA)*/
struct pti_queue_entry *req_cpu; /* Ptr to REQUEST bufs (CPU) */
+
+ __u32 res_dvma; /* Ptr to RESPONSE bufs (DVMA)*/
__u32 req_dvma; /* Ptr to REQUEST bufs (DVMA) */
+ u_int req_in_ptr; /* index of next request slot */
+ u_int res_out_ptr; /* index of next result slot */
+
int cmd_count[MAX_TARGETS];
unsigned long tag_ages[MAX_TARGETS];
long send_marker; /* must we send a marker? */
+ /* The cmd->handler is only 32-bits, so that things work even on monster
+ * Ex000 sparc64 machines with >4GB of ram we just keep track of the
+ * scsi command pointers here. This is essentially what Matt Jacob does. -DaveM
+ */
+ Scsi_Cmnd *cmd_slots[QLOGICISP_REQ_QUEUE_LEN + 1];
+
/* The rest of the elements are unimportant for performance. */
u_char fware_majrev, fware_minrev;
struct Scsi_Host *qhost;
@@ -487,11 +495,7 @@ struct qlogicpti {
#define SREG_IMASK 0x0c /* Interrupt level */
#define SREG_SPMASK 0x03 /* Mask for switch pack */
unsigned char swsreg;
-
-#if 0
- char res[RES_QUEUE_LEN+1][QUEUE_ENTRY_LEN];
- char req[QLOGICISP_REQ_QUEUE_LEN+1][QUEUE_ENTRY_LEN];
-#endif
+ unsigned char is_pti; /* Non-zero if this is a PTI board. */
};
/* How to twiddle them bits... */
diff --git a/drivers/scsi/qlogicpti_asm.c b/drivers/scsi/qlogicpti_asm.c
index b6e48a06a..0e82ea024 100644
--- a/drivers/scsi/qlogicpti_asm.c
+++ b/drivers/scsi/qlogicpti_asm.c
@@ -1,8 +1,8 @@
/* Version 1.24 Initiator Firmware (Aug 8, 1996) */
-unsigned short risc_code_addr01 = 0x1000;
+unsigned short pti_risc_code_addr01 = 0x1000;
-unsigned short risc_code01[] __initdata = {
+unsigned short pti_risc_code01[] __initdata = {
0x0078, 0x1030, 0x0000, 0x231f, 0x0000, 0x12ff, 0x2043, 0x4f50,
0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932,
0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749,
@@ -1129,4 +1129,1170 @@ unsigned short risc_code01[] __initdata = {
0x331b, 0x2019, 0x2626, 0x7b22, 0x7b26, 0x007c, 0xae5b
};
-unsigned short risc_code_length01 = 0x231f;
+unsigned short pti_risc_code_length01 = 0x231f;
+
+/* Version 1.31.00 ISP1000 Initiator RISC firmware
+ * We use this for all non-PTI SBUS boards.
+ */
+unsigned short sbus_risc_code_addr01 = 0x1000;
+
+unsigned short sbus_risc_code01[] __initdata = {
+ 0x0078, 0x1030, 0xa5e3, 0x241a, 0x0001, 0x12ff, 0x2043, 0x4f50,
+ 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932,
+ 0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749,
+ 0x4320, 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049,
+ 0x5350, 0x3130, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520,
+ 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3331, 0x2020,
+ 0x2071, 0x0010, 0x70c3, 0x0004, 0x20c9, 0x3fff, 0x2089, 0x10ca,
+ 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0001,
+ 0x3f00, 0x70d6, 0x2031, 0x0030, 0x2079, 0x3500, 0x7863, 0x0000,
+ 0x2fa0, 0x2009, 0x012b, 0x2011, 0x0000, 0x20a9, 0x0040, 0x42a4,
+ 0x8109, 0x00c0, 0x104d, 0x789b, 0x0101, 0x780b, 0x0002, 0x780f,
+ 0x0002, 0x784f, 0x0bb8, 0x2069, 0x3540, 0x00a8, 0x106c, 0x681b,
+ 0x003c, 0x2009, 0x1313, 0xa18c, 0xff00, 0x3700, 0xa084, 0x00ff,
+ 0xa105, 0x20b8, 0x0078, 0x106e, 0x681b, 0x0028, 0x6807, 0x0007,
+ 0x680b, 0x00fa, 0x680f, 0x0008, 0x6813, 0x0005, 0x681f, 0x0000,
+ 0x6823, 0x0006, 0x6817, 0x0008, 0x6827, 0x0000, 0x2069, 0x3600,
+ 0x2011, 0x0020, 0x2009, 0x0010, 0x680b, 0x0c19, 0x680f, 0x0019,
+ 0x6803, 0xdd00, 0x6807, 0x001a, 0x6a1a, 0x2d00, 0xa0e8, 0x0008,
+ 0xa290, 0x0004, 0x8109, 0x00c0, 0x1084, 0x2069, 0x3680, 0x20a9,
+ 0x0080, 0x6837, 0x0000, 0x680b, 0x0040, 0x6817, 0x0064, 0x681f,
+ 0x0002, 0xade8, 0x0010, 0x0070, 0x10a7, 0x0078, 0x1099, 0x1078,
+ 0x1a42, 0x1078, 0x2f3d, 0x1078, 0x168b, 0x1078, 0x33bb, 0x3200,
+ 0xa085, 0x000d, 0x2090, 0x70c3, 0x0000, 0x0090, 0x10be, 0x70c0,
+ 0xa086, 0x0002, 0x00c0, 0x10be, 0x1078, 0x11be, 0x1078, 0x10ee,
+ 0x1078, 0x1821, 0x1078, 0x19b2, 0x1078, 0x3280, 0x1078, 0x1787,
+ 0x0078, 0x10be, 0x10d2, 0x10d4, 0x1b9f, 0x1b9f, 0x2f9b, 0x2f9b,
+ 0x1b9f, 0x1b9f, 0x0078, 0x10d2, 0x0078, 0x10d4, 0x0078, 0x10d6,
+ 0x0078, 0x10d8, 0x7008, 0x800c, 0x00c8, 0x10e9, 0x7007, 0x0002,
+ 0xa08c, 0x000c, 0x00c0, 0x10ea, 0x8004, 0x8004, 0x00c8, 0x10e9,
+ 0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x11c1, 0x0068, 0x1133,
+ 0x7814, 0xa005, 0x00c0, 0x10f8, 0x0010, 0x1134, 0x0078, 0x1133,
+ 0x2009, 0x3568, 0x2104, 0xa005, 0x00c0, 0x1133, 0x7814, 0xa086,
+ 0x0001, 0x00c0, 0x1105, 0x1078, 0x1540, 0x7817, 0x0000, 0x2009,
+ 0x356f, 0x2104, 0xa065, 0x0040, 0x1121, 0x2009, 0x356a, 0x211c,
+ 0x8108, 0x2114, 0x8108, 0x2104, 0xa210, 0xa399, 0x0000, 0x2009,
+ 0x001c, 0x6083, 0x0103, 0x1078, 0x161b, 0x00c0, 0x112d, 0x1078,
+ 0x1682, 0x2009, 0x356f, 0x200b, 0x0000, 0x2009, 0x3569, 0x2104,
+ 0x200b, 0x0000, 0xa005, 0x0040, 0x1131, 0x2001, 0x4005, 0x0078,
+ 0x11c0, 0x0078, 0x11be, 0x007c, 0x2061, 0x0000, 0x6018, 0xa084,
+ 0x0001, 0x0040, 0x113c, 0x007c, 0x70c3, 0x0000, 0x70c7, 0x0000,
+ 0x70cb, 0x0000, 0x70cf, 0x0000, 0x70c0, 0xa0bc, 0xffc0, 0x00c0,
+ 0x118c, 0x2038, 0x0079, 0x114c, 0x11be, 0x1209, 0x11d7, 0x1209,
+ 0x125a, 0x125a, 0x11ce, 0x159a, 0x1265, 0x11ca, 0x11db, 0x11dd,
+ 0x11df, 0x11e1, 0x159f, 0x11ca, 0x126b, 0x1287, 0x154e, 0x1594,
+ 0x11e3, 0x1475, 0x1497, 0x14b1, 0x14da, 0x142e, 0x143c, 0x1450,
+ 0x1464, 0x12f3, 0x11ca, 0x12a3, 0x12aa, 0x12af, 0x12b4, 0x12ba,
+ 0x12bf, 0x12c4, 0x12c9, 0x12ce, 0x12d2, 0x12e7, 0x11ca, 0x11ca,
+ 0x11ca, 0x11ca, 0x11ca, 0x12ff, 0x1308, 0x1317, 0x133d, 0x1347,
+ 0x134e, 0x137a, 0x1389, 0x1398, 0x13aa, 0x1413, 0x11ca, 0x11ca,
+ 0x11ca, 0x11ca, 0x11ca, 0x1423, 0xa0bc, 0xffa0, 0x00c0, 0x11ca,
+ 0x2038, 0xa084, 0x001f, 0x0079, 0x1195, 0x11ca, 0x11ca, 0x11ca,
+ 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca,
+ 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca,
+ 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x15f7,
+ 0x1601, 0x1605, 0x1613, 0x11ca, 0x11ca, 0x72ca, 0x71c6, 0x2001,
+ 0x4006, 0x0078, 0x11c0, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000,
+ 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091,
+ 0x4080, 0x007c, 0x70c3, 0x4001, 0x0078, 0x11c1, 0x2099, 0x0041,
+ 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078, 0x11be, 0x70c4,
+ 0x70c3, 0x0004, 0x007a, 0x0078, 0x11be, 0x0078, 0x11be, 0x0078,
+ 0x11be, 0x0078, 0x11be, 0x2091, 0x8000, 0x70c3, 0x0000, 0x70c7,
+ 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0001, 0x3f00,
+ 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031, 0x0030, 0x2059,
+ 0x1000, 0x2029, 0x0457, 0x2051, 0x0470, 0x2061, 0x0472, 0x20b9,
+ 0xffff, 0x20c1, 0x0000, 0x2091, 0x5000, 0x2091, 0x4080, 0x0078,
+ 0x0455, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0, 0x2098, 0x2031,
+ 0x0030, 0x81ff, 0x0040, 0x11be, 0x7007, 0x0004, 0x731a, 0x721e,
+ 0x2051, 0x0012, 0x2049, 0x1238, 0x2041, 0x11be, 0x7003, 0x0002,
+ 0xa786, 0x0001, 0x00c0, 0x122a, 0x2049, 0x1246, 0x2041, 0x1252,
+ 0x7003, 0x0003, 0x7017, 0x0000, 0x810b, 0x7112, 0x00c8, 0x1232,
+ 0x7017, 0x0001, 0x7007, 0x0001, 0xa786, 0x0001, 0x0040, 0x1246,
+ 0x700c, 0xa084, 0x007f, 0x8004, 0x2009, 0x0020, 0xa102, 0x0942,
+ 0x094a, 0x20a8, 0x26a0, 0x53a6, 0x0078, 0x10da, 0x700c, 0xa084,
+ 0x007f, 0x0040, 0x1246, 0x80ac, 0x0048, 0x1246, 0x2698, 0x53a5,
+ 0x0078, 0x10da, 0x700c, 0xa084, 0x007f, 0x80ac, 0x2698, 0x53a5,
+ 0x0078, 0x11be, 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0,
+ 0x1262, 0x200a, 0x72ca, 0x0078, 0x11bd, 0x70c7, 0x0001, 0x70cb,
+ 0x001f, 0x0078, 0x11be, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6,
+ 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x1281, 0x8001, 0x7872,
+ 0x7a7a, 0x7b7e, 0x7c76, 0x7898, 0xa084, 0xfffc, 0x789a, 0x0078,
+ 0x1285, 0x7898, 0xa085, 0x0001, 0x789a, 0x0078, 0x11be, 0x70c4,
+ 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6, 0xa005,
+ 0x0040, 0x129d, 0x8001, 0x7886, 0x7a8e, 0x7b92, 0x7c8a, 0x7898,
+ 0xa084, 0xfcff, 0x789a, 0x0078, 0x12a1, 0x7898, 0xa085, 0x0100,
+ 0x789a, 0x0078, 0x11be, 0x2009, 0x3559, 0x210c, 0x2011, 0x015c,
+ 0x0078, 0x11bc, 0x2009, 0x3541, 0x210c, 0x0078, 0x11bd, 0x2009,
+ 0x3542, 0x210c, 0x0078, 0x11bd, 0x2061, 0x3540, 0x610c, 0x6210,
+ 0x0078, 0x11bc, 0x2009, 0x3545, 0x210c, 0x0078, 0x11bd, 0x2009,
+ 0x3546, 0x210c, 0x0078, 0x11bd, 0x2009, 0x3547, 0x210c, 0x0078,
+ 0x11bd, 0x2009, 0x3548, 0x210c, 0x0078, 0x11bd, 0x7908, 0x7a0c,
+ 0x0078, 0x11bc, 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
+ 0x8003, 0xa0e8, 0x3600, 0x6a00, 0x6804, 0xa084, 0x0008, 0x0040,
+ 0x12e4, 0x6b08, 0x0078, 0x12e5, 0x6b0c, 0x0078, 0x11bb, 0x77c4,
+ 0x1078, 0x169c, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001,
+ 0x2708, 0x0078, 0x11bb, 0x77c4, 0x1078, 0x169c, 0x2091, 0x8000,
+ 0x6908, 0x6a18, 0x6b10, 0x2091, 0x8001, 0x0078, 0x11bb, 0x71c4,
+ 0xa182, 0x0010, 0x00c8, 0x11b6, 0x1078, 0x1ac6, 0x0078, 0x11bb,
+ 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b6, 0x2011, 0x3541, 0x2204,
+ 0x007e, 0x2112, 0x1078, 0x1a7f, 0x017f, 0x0078, 0x11bd, 0x71c4,
+ 0x2011, 0x1335, 0x20a9, 0x0008, 0x2204, 0xa106, 0x0040, 0x1327,
+ 0x8210, 0x0070, 0x1325, 0x0078, 0x131c, 0x0078, 0x11b6, 0xa292,
+ 0x1335, 0x027e, 0x2011, 0x3542, 0x2204, 0x2112, 0x017f, 0x007e,
+ 0x1078, 0x1a8b, 0x017f, 0x0078, 0x11bd, 0x03e8, 0x00fa, 0x01f4,
+ 0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x3540, 0x610c,
+ 0x6210, 0x70c4, 0x600e, 0x70c8, 0x6012, 0x0078, 0x11bc, 0x2061,
+ 0x3540, 0x6114, 0x70c4, 0x6016, 0x0078, 0x11bd, 0x71c4, 0x2011,
+ 0x0004, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x1367, 0x2011,
+ 0x0005, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040, 0x1367, 0x2011,
+ 0x0006, 0x2019, 0x1313, 0xa186, 0x003c, 0x00c0, 0x11b6, 0x2061,
+ 0x3540, 0x6018, 0x007e, 0x611a, 0xa39c, 0xff00, 0x3700, 0xa084,
+ 0x00ff, 0xa305, 0x20b8, 0x1078, 0x1a9c, 0x1078, 0x33bb, 0x017f,
+ 0x0078, 0x11bd, 0x71c4, 0xa184, 0xffcf, 0x00c0, 0x11b6, 0x2011,
+ 0x3547, 0x2204, 0x2112, 0x007e, 0x1078, 0x1abe, 0x017f, 0x0078,
+ 0x11bd, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b6, 0x2011, 0x3548,
+ 0x2204, 0x007e, 0x2112, 0x1078, 0x1aad, 0x017f, 0x0078, 0x11bd,
+ 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x11b5, 0xa284, 0xfffd,
+ 0x00c0, 0x11b5, 0x2100, 0x7908, 0x780a, 0x2200, 0x7a0c, 0x780e,
+ 0x0078, 0x11bc, 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
+ 0x8003, 0xa0e8, 0x3600, 0x2019, 0x0000, 0x72c8, 0x6800, 0x007e,
+ 0xa226, 0x0040, 0x13d9, 0x6a02, 0xa484, 0x2000, 0x0040, 0x13c2,
+ 0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x13c8, 0xa39d, 0x0008,
+ 0xa484, 0x4000, 0x0040, 0x13d9, 0x810f, 0xa284, 0x4000, 0x0040,
+ 0x13d5, 0x1078, 0x1ae0, 0x0078, 0x13d9, 0x1078, 0x1ad2, 0x0078,
+ 0x13d9, 0x72cc, 0x82ff, 0x0040, 0x140b, 0x6808, 0xa206, 0x0040,
+ 0x140b, 0xa2a4, 0x00ff, 0x2061, 0x3540, 0x6118, 0xa186, 0x0028,
+ 0x0040, 0x13f2, 0xa186, 0x0032, 0x0040, 0x13f8, 0xa186, 0x003c,
+ 0x0040, 0x13fe, 0xa482, 0x0064, 0x0048, 0x1408, 0x0078, 0x1402,
+ 0xa482, 0x0050, 0x0048, 0x1408, 0x0078, 0x1402, 0xa482, 0x0043,
+ 0x0048, 0x1408, 0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x11b7,
+ 0x6a0a, 0xa39d, 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c,
+ 0x71c4, 0x0078, 0x11bb, 0x77c4, 0x1078, 0x169c, 0x2091, 0x8000,
+ 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e,
+ 0x2708, 0x0078, 0x11bb, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010,
+ 0x00c8, 0x11b6, 0x1078, 0x1aee, 0x0078, 0x11bb, 0x77c4, 0x1078,
+ 0x169c, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0002, 0x6a0a, 0x2091,
+ 0x8001, 0x2708, 0x0078, 0x11bc, 0x77c4, 0x1078, 0x169c, 0x2091,
+ 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040,
+ 0x144b, 0x1078, 0x1a23, 0x2091, 0x8001, 0x2708, 0x0078, 0x11bc,
+ 0x77c4, 0x1078, 0x169c, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0004,
+ 0x6a0a, 0x6804, 0xa005, 0x0040, 0x145f, 0x1078, 0x1a23, 0x2091,
+ 0x8001, 0x2708, 0x0078, 0x11bc, 0x77c4, 0x2041, 0x0001, 0x2049,
+ 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, 0x16a9, 0x2091,
+ 0x8001, 0x2708, 0x6a08, 0x0078, 0x11bc, 0x77c4, 0x72c8, 0x73cc,
+ 0x77c6, 0x72ca, 0x73ce, 0x1078, 0x1722, 0x00c0, 0x1493, 0x6818,
+ 0xa005, 0x0040, 0x148d, 0x2708, 0x1078, 0x1afe, 0x00c0, 0x148d,
+ 0x7817, 0xffff, 0x2091, 0x8001, 0x007c, 0x2091, 0x8001, 0x2001,
+ 0x4005, 0x0078, 0x11c0, 0x2091, 0x8001, 0x0078, 0x11be, 0x77c4,
+ 0x77c6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091,
+ 0x8000, 0x1078, 0x16a9, 0x2061, 0x3540, 0x60a3, 0x0003, 0x67b6,
+ 0x60a7, 0x0000, 0x7817, 0xffff, 0x2091, 0x8001, 0x1078, 0x1a23,
+ 0x007c, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091,
+ 0x8000, 0x2061, 0x3540, 0x60a3, 0x0002, 0x60a7, 0x0000, 0x67b6,
+ 0x7817, 0xffff, 0x1078, 0x1a23, 0x2091, 0x8001, 0x2041, 0x0021,
+ 0x2049, 0x0004, 0x2051, 0x0010, 0x2091, 0x8000, 0x1078, 0x16a9,
+ 0x70c8, 0x6836, 0x8738, 0xa784, 0x0007, 0x00c0, 0x14ce, 0x2091,
+ 0x8001, 0x007c, 0x7898, 0xa084, 0x0003, 0x00c0, 0x14fe, 0x2039,
+ 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078,
+ 0x169c, 0x2091, 0x8000, 0x6808, 0xa80d, 0x690a, 0x2091, 0x8001,
+ 0x8738, 0xa784, 0x0007, 0x00c0, 0x14e7, 0xa7bc, 0xff00, 0x873f,
+ 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x14e7, 0x2091, 0x8000,
+ 0x2069, 0x0100, 0x6830, 0xa084, 0x0040, 0x0040, 0x1527, 0x684b,
+ 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004, 0x0040, 0x1514,
+ 0x0070, 0x1514, 0x0078, 0x150b, 0x684b, 0x0009, 0x20a9, 0x0014,
+ 0x6848, 0xa084, 0x0001, 0x0040, 0x1521, 0x0070, 0x1521, 0x0078,
+ 0x1518, 0x20a9, 0x00fa, 0x0070, 0x1527, 0x0078, 0x1523, 0x2079,
+ 0x3500, 0x7817, 0x0001, 0x2061, 0x3540, 0x60a3, 0x0001, 0x60a7,
+ 0x0000, 0x60c3, 0x000f, 0x7898, 0xa085, 0x0002, 0x789a, 0x6808,
+ 0xa084, 0xfffd, 0x680a, 0x681b, 0x0046, 0x2091, 0x8001, 0x007c,
+ 0x7898, 0xa084, 0xfffd, 0x789a, 0xa084, 0x0001, 0x00c0, 0x154a,
+ 0x1078, 0x176a, 0x71c4, 0x71c6, 0x794a, 0x007c, 0x74c4, 0x73c8,
+ 0x72cc, 0x74c6, 0x73ca, 0x72ce, 0x2079, 0x3500, 0x2009, 0x0040,
+ 0x1078, 0x1679, 0x0040, 0x1590, 0x1078, 0x1649, 0x0040, 0x1564,
+ 0x1078, 0x1682, 0x0078, 0x1590, 0x6010, 0x2091, 0x8001, 0x7817,
+ 0xffff, 0x2009, 0x3568, 0x200b, 0x0005, 0x8108, 0x200b, 0x0000,
+ 0x8108, 0x230a, 0x8108, 0x220a, 0x8108, 0x240a, 0x8108, 0x200a,
+ 0x8108, 0x200b, 0x0000, 0x8108, 0x2c0a, 0xa02e, 0x2530, 0x0e7e,
+ 0x1078, 0x2f16, 0x0e7f, 0x6592, 0x65a2, 0x6696, 0x66a6, 0x60ab,
+ 0x0000, 0x60af, 0x0000, 0x2091, 0x8001, 0x1078, 0x1a23, 0x007c,
+ 0x70c3, 0x4005, 0x0078, 0x11c1, 0x71c4, 0x70c7, 0x0000, 0x7906,
+ 0x0078, 0x11be, 0x71c4, 0x71c6, 0x2168, 0x0078, 0x15a1, 0x2069,
+ 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0,
+ 0x15a3, 0xa285, 0x0000, 0x00c0, 0x15b1, 0x70c3, 0x4000, 0x0078,
+ 0x15b3, 0x70c3, 0x4003, 0x70ca, 0x0078, 0x11c1, 0x71c4, 0x72c8,
+ 0x73cc, 0x2100, 0xa184, 0xfffc, 0x00c0, 0x11ca, 0x2100, 0x0079,
+ 0x15c1, 0x15d8, 0x15ed, 0x15ef, 0x15f1, 0x70c3, 0x4003, 0x71ce,
+ 0x72d2, 0x73d6, 0x0078, 0x15d4, 0x70c3, 0x4000, 0x70cf, 0x0000,
+ 0x70d3, 0x0000, 0x70d7, 0x0000, 0x77c6, 0x71ca, 0x0078, 0x11be,
+ 0x2031, 0x15f3, 0x2624, 0x8630, 0x2412, 0x2204, 0xa446, 0x00c0,
+ 0x15c5, 0xa484, 0xffff, 0x00c0, 0x15da, 0x2031, 0x15f3, 0x8210,
+ 0x8319, 0xa384, 0xffff, 0x00c0, 0x15da, 0x0078, 0x15cc, 0x0078,
+ 0x15cc, 0x0078, 0x15cc, 0x5555, 0xaaaa, 0xffff, 0x0000, 0x7960,
+ 0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x11b6, 0x7962, 0x0078,
+ 0x11be, 0x7960, 0x71c6, 0x0078, 0x11be, 0x7954, 0x71c6, 0x71c4,
+ 0x7956, 0x7958, 0x71ca, 0x71c8, 0x795a, 0x795c, 0x71ce, 0x71cc,
+ 0x795e, 0x0078, 0x11be, 0x7954, 0x71c6, 0x7958, 0x71ca, 0x795c,
+ 0x71ce, 0x0078, 0x11be, 0x700c, 0xa084, 0x007f, 0x0040, 0x1627,
+ 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x1622, 0x7017,
+ 0x0000, 0x7112, 0x721a, 0x731e, 0x8108, 0x810c, 0x81a9, 0x8c98,
+ 0x20a1, 0x0030, 0x6080, 0x20a2, 0x53a6, 0x780c, 0xa085, 0x0000,
+ 0x7002, 0x7007, 0x0001, 0x7108, 0x8104, 0x00c8, 0x163b, 0x7007,
+ 0x0002, 0xa184, 0x000c, 0x710c, 0xa184, 0x0300, 0x7003, 0x0000,
+ 0x007c, 0x700c, 0xa084, 0x007f, 0x0040, 0x1655, 0x7007, 0x0004,
+ 0x7004, 0xa084, 0x0004, 0x00c0, 0x1650, 0x7017, 0x0000, 0x7112,
+ 0x721a, 0x731e, 0x2099, 0x0030, 0x8108, 0x81ac, 0x780c, 0xa085,
+ 0x0001, 0x7002, 0x7007, 0x0001, 0x7008, 0x800c, 0x00c8, 0x1664,
+ 0x7007, 0x0002, 0xa08c, 0x000c, 0x00c0, 0x1676, 0x710c, 0xa184,
+ 0x0300, 0x00c0, 0x1676, 0x2ca0, 0x53a5, 0xa006, 0x7003, 0x0000,
+ 0x007c, 0x7850, 0xa065, 0x0040, 0x1681, 0x2c04, 0x7852, 0x2063,
+ 0x0000, 0x007c, 0x0f7e, 0x2079, 0x3500, 0x7850, 0x2062, 0x2c00,
+ 0x7852, 0x0f7f, 0x007c, 0x2011, 0x4000, 0x7a52, 0x2019, 0x015c,
+ 0x8319, 0x0040, 0x1699, 0xa280, 0x002f, 0x2012, 0x2010, 0x0078,
+ 0x1690, 0x2013, 0x0000, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784,
+ 0x0007, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8, 0x3680,
+ 0x007c, 0x1078, 0x169c, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808,
+ 0xa084, 0xffef, 0xa80d, 0x690a, 0x2009, 0x354f, 0x210c, 0x6804,
+ 0xa005, 0x0040, 0x16c6, 0xa116, 0x00c0, 0x16c6, 0x2060, 0x6000,
+ 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x16c9, 0x2009, 0x0000,
+ 0x017e, 0x6804, 0xa065, 0x0040, 0x16d8, 0x6000, 0x6806, 0x1078,
+ 0x16e9, 0x1078, 0x17d5, 0x6810, 0x8001, 0x6812, 0x00c0, 0x16c9,
+ 0x017f, 0x6902, 0x6906, 0x007c, 0xa065, 0x0040, 0x16e8, 0x6098,
+ 0x609b, 0x0000, 0x2008, 0x1078, 0x1682, 0x2100, 0x0078, 0x16dc,
+ 0x007c, 0x6003, 0x0103, 0x20a9, 0x001c, 0xac80, 0x0004, 0x20a0,
+ 0x2001, 0x0000, 0x40a4, 0x6828, 0x6016, 0x682c, 0x601e, 0x007c,
+ 0x0e7e, 0x2071, 0x3540, 0x7040, 0xa08c, 0x0080, 0x00c0, 0x1706,
+ 0xa088, 0x3580, 0x2d0a, 0x8000, 0x7042, 0xa006, 0x0e7f, 0x007c,
+ 0x0e7e, 0x2071, 0x3540, 0x2009, 0x3580, 0x7240, 0x8221, 0x8211,
+ 0x0048, 0x1720, 0x2104, 0x8108, 0xad06, 0x00c0, 0x170f, 0x8119,
+ 0x211e, 0x8108, 0x8318, 0x8211, 0x00c8, 0x1718, 0x7442, 0xa006,
+ 0x0e7f, 0x007c, 0x1078, 0x169c, 0x2091, 0x8000, 0x6804, 0x781e,
+ 0xa065, 0x0040, 0x1769, 0x0078, 0x1733, 0x2c00, 0x781e, 0x6000,
+ 0xa065, 0x0040, 0x1769, 0x600c, 0xa306, 0x00c0, 0x172d, 0x6008,
+ 0xa206, 0x00c0, 0x172d, 0x2c28, 0x2001, 0x354f, 0x2004, 0xac06,
+ 0x0040, 0x1769, 0x6804, 0xac06, 0x00c0, 0x1750, 0x6000, 0x2060,
+ 0x6806, 0xa005, 0x00c0, 0x1750, 0x6803, 0x0000, 0x0078, 0x175a,
+ 0x6400, 0x781c, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x175a,
+ 0x2c00, 0x6802, 0x2560, 0x1078, 0x16e9, 0x6017, 0x0005, 0x601f,
+ 0x0020, 0x1078, 0x17d5, 0x6810, 0x8001, 0x6812, 0x2001, 0xffff,
+ 0xa005, 0x007c, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004,
+ 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x16a9, 0x8738, 0xa784,
+ 0x0007, 0x00c0, 0x1774, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f,
+ 0xa784, 0x0f00, 0x00c0, 0x1774, 0x2091, 0x8001, 0x007c, 0x2061,
+ 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1794, 0x78ac, 0x78af,
+ 0x0000, 0xa005, 0x00c0, 0x1795, 0x007c, 0xa08c, 0xfff0, 0x0040,
+ 0x179b, 0x1078, 0x1b81, 0x0079, 0x179d, 0x17ad, 0x17af, 0x17b5,
+ 0x17b9, 0x17ad, 0x17bd, 0x17ad, 0x17ad, 0x17ad, 0x17ad, 0x17c3,
+ 0x17c7, 0x17ad, 0x17ad, 0x17ad, 0x17ad, 0x1078, 0x1b81, 0x1078,
+ 0x176a, 0x2001, 0x8001, 0x0078, 0x17cd, 0x2001, 0x8003, 0x0078,
+ 0x17cd, 0x2001, 0x8004, 0x0078, 0x17cd, 0x1078, 0x176a, 0x2001,
+ 0x8006, 0x0078, 0x17cd, 0x2001, 0x800c, 0x0078, 0x17cd, 0x1078,
+ 0x176a, 0x2001, 0x800d, 0x0078, 0x17cd, 0x70c2, 0x2061, 0x0000,
+ 0x601b, 0x0001, 0x2091, 0x4080, 0x007c, 0x2c04, 0x6082, 0x2c08,
+ 0x2063, 0x0000, 0x7864, 0x8000, 0x7866, 0x7868, 0xa005, 0x796a,
+ 0x0040, 0x17e5, 0x2c02, 0x0078, 0x17e6, 0x796e, 0x007c, 0x0c7e,
+ 0x2061, 0x3500, 0x6883, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6064,
+ 0x8000, 0x6066, 0x6068, 0xa005, 0x616a, 0x0040, 0x17fa, 0x2d02,
+ 0x0078, 0x17fb, 0x616e, 0x0c7f, 0x007c, 0x1078, 0x180e, 0x0040,
+ 0x180d, 0x0c7e, 0x6098, 0xa065, 0x0040, 0x1808, 0x1078, 0x16dc,
+ 0x0c7f, 0x609b, 0x0000, 0x1078, 0x1682, 0x007c, 0x786c, 0xa065,
+ 0x0040, 0x1820, 0x2091, 0x8000, 0x7864, 0x8001, 0x7866, 0x2c04,
+ 0x786e, 0xa005, 0x00c0, 0x181e, 0x786a, 0x8000, 0x2091, 0x8001,
+ 0x007c, 0x7898, 0xa005, 0x00c0, 0x186f, 0x7974, 0x70d0, 0x0005,
+ 0x0005, 0x72d0, 0xa206, 0x00c0, 0x1826, 0x2200, 0xa106, 0x00c0,
+ 0x183d, 0x7804, 0xa005, 0x0040, 0x186f, 0x7807, 0x0000, 0x0068,
+ 0x186f, 0x2091, 0x4080, 0x0078, 0x186f, 0x1078, 0x1679, 0x0040,
+ 0x186f, 0x7a7c, 0x7b78, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399,
+ 0x0000, 0x2009, 0x0040, 0x1078, 0x1649, 0x0040, 0x1866, 0x1078,
+ 0x1682, 0x7880, 0x8000, 0x7882, 0xa086, 0x0002, 0x00c0, 0x186f,
+ 0x2091, 0x8000, 0x78af, 0x0002, 0x7883, 0x0000, 0x7898, 0xa085,
+ 0x0003, 0x789a, 0x2091, 0x8001, 0x0078, 0x186f, 0x7883, 0x0000,
+ 0x1078, 0x199c, 0x6000, 0xa084, 0x0007, 0x0079, 0x1870, 0x007c,
+ 0x1878, 0x1887, 0x18a7, 0x1878, 0x18b9, 0x1878, 0x1878, 0x1878,
+ 0x2039, 0x0400, 0x78a8, 0xa705, 0x78aa, 0x6004, 0xa705, 0x6006,
+ 0x1078, 0x18f7, 0x6018, 0x78a6, 0x1078, 0x1984, 0x007c, 0x78a8,
+ 0xa084, 0x0100, 0x0040, 0x188e, 0x0078, 0x1878, 0x78ab, 0x0000,
+ 0x6000, 0x8007, 0xa084, 0x00ff, 0x789e, 0x8001, 0x609b, 0x0000,
+ 0x0040, 0x18a4, 0x1078, 0x18f7, 0x0040, 0x18a4, 0x78a8, 0xa085,
+ 0x0100, 0x78aa, 0x0078, 0x18a6, 0x1078, 0x191b, 0x007c, 0x78a8,
+ 0xa08c, 0x0e00, 0x00c0, 0x18b0, 0xa084, 0x0100, 0x00c0, 0x18b2,
+ 0x0078, 0x1878, 0x1078, 0x18f7, 0x00c0, 0x18b8, 0x1078, 0x191b,
+ 0x007c, 0x78a8, 0xa084, 0x0100, 0x0040, 0x18c0, 0x0078, 0x1878,
+ 0x78ab, 0x0000, 0x6710, 0x20a9, 0x0001, 0x6014, 0xa084, 0x00ff,
+ 0xa005, 0x0040, 0x18dd, 0xa7bc, 0xff00, 0x20a9, 0x0008, 0xa08e,
+ 0x0001, 0x0040, 0x18dd, 0x2039, 0x0000, 0x20a9, 0x0080, 0xa08e,
+ 0x0002, 0x0040, 0x18dd, 0x0078, 0x18f4, 0x1078, 0x169c, 0x2d00,
+ 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084,
+ 0xffde, 0x680a, 0x2d00, 0xa080, 0x0010, 0x2068, 0x2091, 0x8001,
+ 0x0070, 0x18f4, 0x0078, 0x18e0, 0x1078, 0x1682, 0x007c, 0x78a0,
+ 0xa06d, 0x00c0, 0x1902, 0x2c00, 0x78a2, 0x78a6, 0x609b, 0x0000,
+ 0x0078, 0x190e, 0x2c00, 0x689a, 0x609b, 0x0000, 0x78a2, 0x2d00,
+ 0x6002, 0x78a4, 0xad06, 0x00c0, 0x190e, 0x6002, 0x789c, 0x8001,
+ 0x789e, 0x00c0, 0x191a, 0x78a8, 0xa084, 0x0000, 0x78aa, 0x78a4,
+ 0x2060, 0xa006, 0x007c, 0xa02e, 0x2530, 0x6118, 0xa184, 0x0060,
+ 0x619e, 0x0040, 0x1927, 0x0e7e, 0x1078, 0x2f16, 0x0e7f, 0x6592,
+ 0x65a2, 0x6696, 0x66a6, 0x60ab, 0x0000, 0x60af, 0x0000, 0x6710,
+ 0x1078, 0x169c, 0x2091, 0x8000, 0x6808, 0xa084, 0x0001, 0x0040,
+ 0x1949, 0x2091, 0x8001, 0x1078, 0x16e9, 0x2091, 0x8000, 0x1078,
+ 0x17d5, 0x2091, 0x8001, 0x78a3, 0x0000, 0x78a7, 0x0000, 0x0078,
+ 0x1983, 0x6020, 0xa096, 0x0001, 0x00c0, 0x1950, 0x8000, 0x6022,
+ 0x6a10, 0x6814, 0x2091, 0x8001, 0xa202, 0x0048, 0x195f, 0x0040,
+ 0x195f, 0x2039, 0x0200, 0x1078, 0x1984, 0x0078, 0x1983, 0x2c08,
+ 0x2091, 0x8000, 0x6800, 0xa065, 0x0040, 0x1967, 0x6102, 0x6902,
+ 0x00c0, 0x196b, 0x6906, 0x2160, 0x6003, 0x0000, 0x6810, 0x8000,
+ 0x6812, 0x2091, 0x8001, 0x6808, 0xa08c, 0x0040, 0x0040, 0x197d,
+ 0xa086, 0x0040, 0x680a, 0x1078, 0x16f8, 0x1078, 0x1a23, 0x78a7,
+ 0x0000, 0x78a3, 0x0000, 0x007c, 0x6004, 0xa705, 0x6006, 0x2091,
+ 0x8000, 0x1078, 0x17d5, 0x2091, 0x8001, 0x78a4, 0xa065, 0x0040,
+ 0x1997, 0x6098, 0x78a6, 0x609b, 0x0000, 0x0078, 0x1987, 0x78a3,
+ 0x0000, 0x78a7, 0x0000, 0x007c, 0x7970, 0x7874, 0x8000, 0xa10a,
+ 0x00c8, 0x19a3, 0xa006, 0x7876, 0x70d2, 0x7804, 0xa005, 0x0040,
+ 0x19b1, 0x8001, 0x7806, 0x00c0, 0x19b1, 0x0068, 0x19b1, 0x2091,
+ 0x4080, 0x007c, 0x0068, 0x19cc, 0x2029, 0x0000, 0x786c, 0xa065,
+ 0x0040, 0x19c7, 0x1078, 0x19cd, 0x0040, 0x19c7, 0x057e, 0x1078,
+ 0x19e3, 0x057f, 0x00c0, 0x19c7, 0x8528, 0x0078, 0x19b6, 0x85ff,
+ 0x0040, 0x19cc, 0x2091, 0x4080, 0x007c, 0x7b84, 0x7988, 0x72d4,
+ 0x0005, 0x0005, 0x70d4, 0xa206, 0x00c0, 0x19cf, 0x2200, 0xa102,
+ 0x00c0, 0x19dd, 0x2300, 0xa005, 0x007c, 0x0048, 0x19e1, 0xa302,
+ 0x007c, 0x8002, 0x007c, 0x1078, 0x1a15, 0x2009, 0x001c, 0x6024,
+ 0xa005, 0x0040, 0x19ed, 0x2009, 0x0040, 0x1078, 0x161b, 0x0040,
+ 0x1a06, 0x7894, 0x8000, 0x7896, 0xa086, 0x0002, 0x00c0, 0x1a14,
+ 0x2091, 0x8000, 0x78af, 0x0003, 0x7897, 0x0000, 0x7898, 0xa085,
+ 0x0300, 0x789a, 0x2091, 0x8001, 0x0078, 0x1a14, 0x7897, 0x0000,
+ 0x1078, 0x17fd, 0x7984, 0x7888, 0x8000, 0xa10a, 0x00c8, 0x1a11,
+ 0xa006, 0x788a, 0x70d6, 0xa006, 0x007c, 0x8107, 0x8004, 0x8004,
+ 0x7a90, 0x7b8c, 0xa210, 0xa399, 0x0000, 0x007c, 0x2009, 0x3568,
+ 0x2091, 0x8000, 0x200a, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3540,
+ 0x2091, 0x8000, 0x2104, 0xa086, 0x0000, 0x00c0, 0x1a3e, 0x2009,
+ 0x3512, 0x2104, 0xa005, 0x00c0, 0x1a3e, 0x7830, 0xa084, 0x00c0,
+ 0x00c0, 0x1a3e, 0x0018, 0x1a3e, 0x781b, 0x0044, 0x2091, 0x8001,
+ 0x0f7f, 0x007c, 0x127e, 0x2091, 0x2300, 0x2071, 0x3540, 0x2079,
+ 0x0100, 0x2019, 0x2ddb, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040,
+ 0x1a5a, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318,
+ 0x0078, 0x1a4d, 0x789b, 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000,
+ 0x78af, 0x0220, 0x0070, 0x1a66, 0x0078, 0x1a5e, 0x7003, 0x0000,
+ 0x1078, 0x1b65, 0x7004, 0xa084, 0x000f, 0xa085, 0x6280, 0x7806,
+ 0x780f, 0x9200, 0x7843, 0x00d8, 0x7853, 0x0080, 0x780b, 0x0008,
+ 0x7047, 0x357f, 0x7043, 0x0000, 0x127f, 0x2000, 0x007c, 0xa18c,
+ 0x000f, 0x2011, 0x0101, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012,
+ 0x1078, 0x1b65, 0x007c, 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b,
+ 0x0070, 0x1a94, 0x0078, 0x1a8f, 0xa18c, 0x0e00, 0x2204, 0xa084,
+ 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2009, 0x0101, 0x20a9, 0x0005,
+ 0x8213, 0x0070, 0x1aa5, 0x0078, 0x1aa0, 0xa294, 0x00e0, 0x2104,
+ 0xa084, 0xff1f, 0xa205, 0x200a, 0x007c, 0x2011, 0x0101, 0x20a9,
+ 0x000c, 0x810b, 0x0070, 0x1ab6, 0x0078, 0x1ab1, 0xa18c, 0xf000,
+ 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x007c, 0x2011, 0x0102,
+ 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x8103, 0x8003,
+ 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x62ac, 0x63ac,
+ 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061,
+ 0x0100, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c,
+ 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a,
+ 0x60a4, 0xa085, 0x0020, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003,
+ 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0x62ae,
+ 0x2010, 0x60a4, 0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000,
+ 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040, 0x1b43, 0x2061, 0x3f80,
+ 0x1078, 0x1b4b, 0x0040, 0x1b31, 0x20a9, 0x0000, 0x2061, 0x3e80,
+ 0x0c7e, 0x1078, 0x1b4b, 0x0040, 0x1b1d, 0x0c7f, 0x8c60, 0x0070,
+ 0x1b1b, 0x0078, 0x1b10, 0x0078, 0x1b43, 0x007f, 0xa082, 0x3e80,
+ 0x2071, 0x3540, 0x70ba, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6,
+ 0x60a7, 0x0000, 0x2001, 0x0004, 0x70a2, 0x1078, 0x1a1e, 0x0078,
+ 0x1b3f, 0x2071, 0x3540, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6,
+ 0x60a7, 0x0000, 0x2001, 0x0006, 0x70a2, 0x1078, 0x1a1e, 0x2001,
+ 0x0000, 0x0078, 0x1b45, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005,
+ 0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005, 0x0040, 0x1b62, 0x2060,
+ 0x600c, 0xa306, 0x00c0, 0x1b5f, 0x6008, 0xa206, 0x00c0, 0x1b5f,
+ 0x6010, 0xa106, 0x00c0, 0x1b5f, 0xa006, 0x0078, 0x1b64, 0x6000,
+ 0x0078, 0x1b4c, 0xa085, 0x0001, 0x007c, 0x2011, 0x3541, 0x220c,
+ 0xa18c, 0x000f, 0x2011, 0x013b, 0x2204, 0xa084, 0x0100, 0x0040,
+ 0x1b80, 0x2019, 0x0112, 0x201b, 0x1000, 0x2021, 0x013a, 0x2122,
+ 0x2013, 0x0080, 0x2013, 0x008c, 0x2013, 0x0000, 0x201b, 0x0000,
+ 0x007c, 0x0068, 0x1b81, 0x007e, 0x2071, 0x0000, 0x7018, 0xa084,
+ 0x0001, 0x00c0, 0x1b86, 0x007f, 0x2e08, 0x2071, 0x0010, 0x70ca,
+ 0x007f, 0x70c6, 0x70c3, 0x8002, 0x2071, 0x0000, 0x701b, 0x0001,
+ 0x2091, 0x4080, 0x007f, 0x2070, 0x007f, 0x0078, 0x1b9d, 0x107e,
+ 0x007e, 0x127e, 0x2091, 0x2300, 0x7f3c, 0x7e58, 0x7c30, 0x7d38,
+ 0xa594, 0x003f, 0xa484, 0x4000, 0x0040, 0x1bb4, 0xa784, 0x007c,
+ 0x00c0, 0x2da7, 0x1078, 0x1b81, 0xa49c, 0x000f, 0xa382, 0x0004,
+ 0x0050, 0x1bbc, 0x1078, 0x1b81, 0x8507, 0xa084, 0x000f, 0x0079,
+ 0x1bc1, 0x1fed, 0x209d, 0x20c3, 0x22e9, 0x2576, 0x25be, 0x25f5,
+ 0x2670, 0x26ca, 0x274f, 0x1be7, 0x1bd1, 0x1e56, 0x1f20, 0x2555,
+ 0x1bd1, 0x1078, 0x1b81, 0x0018, 0x1ba4, 0x127f, 0x2091, 0x8001,
+ 0x007f, 0x107f, 0x007c, 0x7003, 0x0000, 0x703f, 0x0000, 0x7030,
+ 0xa005, 0x0040, 0x1be5, 0x7033, 0x0000, 0x0018, 0x1ba4, 0x705c,
+ 0xa005, 0x00c0, 0x1ca5, 0x70a0, 0xa084, 0x0007, 0x0079, 0x1bf0,
+ 0x1cd1, 0x1bf8, 0x1c06, 0x1c27, 0x1c4d, 0x1c79, 0x1c77, 0x1bf8,
+ 0x7808, 0xa084, 0xfffd, 0x780a, 0x2009, 0x0046, 0x1078, 0x241b,
+ 0x00c0, 0x1c04, 0x7003, 0x0004, 0x0078, 0x1bd3, 0x1078, 0x2d69,
+ 0x00c0, 0x1c25, 0x70b4, 0x8007, 0x789b, 0x007e, 0x78aa, 0x789b,
+ 0x0010, 0x78ab, 0x000c, 0x789b, 0x0060, 0x78ab, 0x0001, 0x785b,
+ 0x0004, 0x2009, 0x00f7, 0x1078, 0x2419, 0x00c0, 0x1c25, 0x7003,
+ 0x0004, 0x70c3, 0x000f, 0x7033, 0x3570, 0x0078, 0x1bd3, 0x1078,
+ 0x2d69, 0x00c0, 0x1c4b, 0x71b4, 0x8107, 0x789b, 0x007e, 0x78aa,
+ 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab,
+ 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002, 0x785b, 0x0004, 0x2009,
+ 0x00f7, 0x1078, 0x2419, 0x00c0, 0x1c4b, 0x7003, 0x0004, 0x70c3,
+ 0x000f, 0x7033, 0x3570, 0x0078, 0x1bd3, 0x1078, 0x2d69, 0x00c0,
+ 0x1c75, 0x71b4, 0x8107, 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010,
+ 0xa18c, 0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0020, 0x71b8,
+ 0x79aa, 0x78ab, 0x000d, 0x789b, 0x0060, 0x78ab, 0x0004, 0x785b,
+ 0x0004, 0x2009, 0x00f7, 0x1078, 0x2419, 0x00c0, 0x1c75, 0x7003,
+ 0x0004, 0x70c3, 0x000f, 0x7033, 0x3570, 0x0078, 0x1bd3, 0x0078,
+ 0x1c27, 0x1078, 0x2d69, 0x00c0, 0x1bd3, 0x70bc, 0x2068, 0x789b,
+ 0x0010, 0x6f10, 0x1078, 0x2cac, 0x2c50, 0x6810, 0x007e, 0x8007,
+ 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2048,
+ 0x0c7e, 0x2060, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x0c7f,
+ 0x007f, 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, 0x6e18, 0x2041,
+ 0x0001, 0x2001, 0x0004, 0x0078, 0x1dcc, 0x1078, 0x2d69, 0x00c0,
+ 0x1bd3, 0x789b, 0x0010, 0x705c, 0x2068, 0x6f10, 0x1078, 0x2cac,
+ 0x2c50, 0x6008, 0xa085, 0x0010, 0x600a, 0x6820, 0xa005, 0x0040,
+ 0x1cc1, 0xa082, 0x0006, 0x0048, 0x1cbf, 0x0078, 0x1cc1, 0x6823,
+ 0x0005, 0x6810, 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, 0x2031,
+ 0x0020, 0x2041, 0x0001, 0x1078, 0x2dc8, 0x2001, 0x0003, 0x0078,
+ 0x1dcc, 0x0018, 0x1ba4, 0x7440, 0xa485, 0x0000, 0x0040, 0x1ceb,
+ 0xa080, 0x3580, 0x2030, 0x7144, 0x8108, 0xa12a, 0x0048, 0x1ce2,
+ 0x2009, 0x3580, 0x2164, 0x6504, 0x85ff, 0x00c0, 0x1cf8, 0x8421,
+ 0x00c0, 0x1cdc, 0x7146, 0x7003, 0x0000, 0x703f, 0x0000, 0x0078,
+ 0x1bd3, 0x7640, 0xa6b0, 0x3580, 0x7144, 0x2600, 0x0078, 0x1ce7,
+ 0x7146, 0x2568, 0x2558, 0x753e, 0x2c50, 0x6034, 0xa085, 0x0000,
+ 0x00c0, 0x1cf5, 0x6708, 0x7736, 0xa784, 0x013f, 0x0040, 0x1d2a,
+ 0xa784, 0x0021, 0x00c0, 0x1cf5, 0xa784, 0x0002, 0x0040, 0x1d17,
+ 0xa784, 0x0004, 0x0040, 0x1cf5, 0xa7bc, 0xfffb, 0x670a, 0xa784,
+ 0x0008, 0x00c0, 0x1cf5, 0xa784, 0x0010, 0x00c0, 0x1cf5, 0xa784,
+ 0x0100, 0x0040, 0x1d2a, 0x6018, 0xa005, 0x00c0, 0x1cf5, 0xa7bc,
+ 0xfeff, 0x670a, 0x681f, 0x0000, 0x6e18, 0xa684, 0x000e, 0x6118,
+ 0x0040, 0x1d3a, 0x601c, 0xa102, 0x0048, 0x1d3d, 0x0040, 0x1d3d,
+ 0x0078, 0x1cf1, 0x81ff, 0x00c0, 0x1cf1, 0xa784, 0x0080, 0x00c0,
+ 0x1d43, 0x700c, 0x6022, 0xa7bc, 0xff7f, 0x670a, 0x6b10, 0x8307,
+ 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2060,
+ 0x2048, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x2a60, 0x0018,
+ 0x1ba4, 0x789b, 0x0010, 0xa046, 0x1078, 0x2d69, 0x00c0, 0x1bd3,
+ 0x6b10, 0xa39c, 0x0007, 0xa39d, 0x00c0, 0x704c, 0xa084, 0x8000,
+ 0x0040, 0x1d6e, 0xa684, 0x0001, 0x0040, 0x1d74, 0xa39c, 0xffbf,
+ 0xa684, 0x000e, 0x00c0, 0x2901, 0xa684, 0x0010, 0x0040, 0x1d7e,
+ 0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2907, 0x7baa, 0x8840,
+ 0xa684, 0x000e, 0x00c0, 0x1d89, 0xa7bd, 0x0010, 0x670a, 0x0078,
+ 0x1dca, 0x714c, 0xa18c, 0x0800, 0x0040, 0x290d, 0x2011, 0x0021,
+ 0x8004, 0x8004, 0x0048, 0x1da0, 0x2011, 0x0022, 0x8004, 0x0048,
+ 0x1da0, 0x2011, 0x0020, 0x8004, 0x0048, 0x1da0, 0x0040, 0x1dca,
+ 0x7aaa, 0x8840, 0x1078, 0x2d82, 0x6a10, 0x610c, 0x8108, 0xa18c,
+ 0x00ff, 0xa1e0, 0x3e80, 0x2c64, 0x8cff, 0x0040, 0x1dc1, 0x6010,
+ 0xa206, 0x00c0, 0x1dab, 0x60b4, 0x8001, 0x60b6, 0x00c0, 0x1da6,
+ 0x0c7e, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078,
+ 0x1cd1, 0x1078, 0x2d69, 0x00c0, 0x1bd3, 0x2a60, 0x610e, 0x79aa,
+ 0x8840, 0x712e, 0x2001, 0x0001, 0x007e, 0x7150, 0xa184, 0x0018,
+ 0x0040, 0x1de0, 0xa184, 0x0010, 0x0040, 0x1dda, 0x1078, 0x2ad7,
+ 0x00c0, 0x1de0, 0xa184, 0x0008, 0x0040, 0x1de0, 0x1078, 0x29f1,
+ 0x007f, 0x7002, 0xa68c, 0x0060, 0x88ff, 0x0040, 0x1de9, 0xa18d,
+ 0x0004, 0x795a, 0x69b2, 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b,
+ 0x0061, 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa, 0x157e, 0x137e,
+ 0x147e, 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80,
+ 0x000a, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6810, 0x8007,
+ 0x789b, 0x007e, 0x78aa, 0x6d90, 0x7dd6, 0x7dde, 0x6e94, 0x7ed2,
+ 0x7eda, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1e18, 0x0098, 0x1e20,
+ 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x2d82, 0x0078, 0x1bdb,
+ 0x7200, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x1e2d, 0x781b,
+ 0x0049, 0x1078, 0x2d82, 0x0078, 0x1e3e, 0x6ab0, 0xa295, 0x2000,
+ 0x7a5a, 0x781b, 0x0049, 0x1078, 0x2d82, 0x7200, 0x2500, 0xa605,
+ 0x0040, 0x1e3e, 0xa284, 0x0007, 0x1079, 0x1e4c, 0xad80, 0x0008,
+ 0x7032, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x1e4a, 0x6018,
+ 0x8000, 0x601a, 0x0078, 0x1bd3, 0x1e54, 0x30f3, 0x30f3, 0x30e2,
+ 0x30f3, 0x1e54, 0x1e54, 0x1e54, 0x1078, 0x1b81, 0x7808, 0xa084,
+ 0xfffd, 0x780a, 0x0f7e, 0x2079, 0x3500, 0x7898, 0x0f7f, 0xa084,
+ 0x0001, 0x0040, 0x1e7c, 0x70a0, 0xa086, 0x0001, 0x00c0, 0x1e6b,
+ 0x70a2, 0x0078, 0x1f04, 0x70a0, 0xa086, 0x0005, 0x00c0, 0x1e7a,
+ 0x70bc, 0x2068, 0x6817, 0x0004, 0x6813, 0x0000, 0x681c, 0xa085,
+ 0x0008, 0x681e, 0x70a3, 0x0000, 0x157e, 0x2011, 0x0004, 0x71a0,
+ 0xa186, 0x0001, 0x0040, 0x1e9e, 0xa186, 0x0007, 0x00c0, 0x1e8e,
+ 0x2009, 0x352b, 0x200b, 0x0005, 0x0078, 0x1e9e, 0x2009, 0x3513,
+ 0x2104, 0x2009, 0x3512, 0x200a, 0x2009, 0x352b, 0x200b, 0x0001,
+ 0x70a3, 0x0000, 0x70a7, 0x0001, 0x0078, 0x1ea0, 0x70a3, 0x0000,
+ 0x1078, 0x2eca, 0x20a9, 0x0010, 0x2039, 0x0000, 0x1078, 0x2bb1,
+ 0xa7b8, 0x0100, 0x0070, 0x1eae, 0x0078, 0x1ea6, 0x7000, 0x2020,
+ 0x0079, 0x1eb2, 0x1ee0, 0x1ec9, 0x1ec9, 0x1ebc, 0x1ee0, 0x1ee0,
+ 0x1eba, 0x1eba, 0x1078, 0x1b81, 0x2021, 0x3557, 0x2404, 0xa005,
+ 0x0040, 0x1ec9, 0xad06, 0x00c0, 0x1ec9, 0x6800, 0x2022, 0x0078,
+ 0x1ed9, 0x681c, 0xa084, 0x0001, 0x00c0, 0x1ed5, 0x6f10, 0x1078,
+ 0x2cac, 0x1078, 0x28e4, 0x0078, 0x1ed9, 0x7054, 0x2060, 0x6800,
+ 0x6002, 0x6a16, 0x681c, 0xa085, 0x0008, 0x681e, 0x1078, 0x17e7,
+ 0x2021, 0x3f80, 0x1078, 0x1f0a, 0x2021, 0x3557, 0x1078, 0x1f0a,
+ 0x20a9, 0x0000, 0x2021, 0x3e80, 0x1078, 0x1f0a, 0x8420, 0x0070,
+ 0x1ef3, 0x0078, 0x1eec, 0x20a9, 0x0080, 0x2061, 0x3680, 0x6018,
+ 0x6110, 0xa102, 0x6012, 0x601b, 0x0000, 0xace0, 0x0010, 0x0070,
+ 0x1f03, 0x0078, 0x1ef7, 0x157f, 0x7003, 0x0000, 0x703f, 0x0000,
+ 0x0078, 0x1bd3, 0x047e, 0x2404, 0xa005, 0x0040, 0x1f1c, 0x2068,
+ 0x6800, 0x007e, 0x6a16, 0x681c, 0xa085, 0x0008, 0x681e, 0x1078,
+ 0x17e7, 0x007f, 0x0078, 0x1f0c, 0x047f, 0x2023, 0x0000, 0x007c,
+ 0xa282, 0x0003, 0x0050, 0x1f26, 0x1078, 0x1b81, 0x2300, 0x0079,
+ 0x1f29, 0x1f2c, 0x1f9f, 0x1fad, 0xa282, 0x0002, 0x0040, 0x1f32,
+ 0x1078, 0x1b81, 0x70a0, 0x70a3, 0x0000, 0x70c3, 0x0000, 0x0079,
+ 0x1f39, 0x1f41, 0x1f41, 0x1f43, 0x1f77, 0x2913, 0x1f41, 0x1f77,
+ 0x1f41, 0x1078, 0x1b81, 0x77b4, 0x1078, 0x2bb1, 0x77b4, 0xa7bc,
+ 0x0f00, 0x1078, 0x2cac, 0x6018, 0xa005, 0x0040, 0x1f6e, 0x2021,
+ 0x3f80, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x1fc8, 0x0040,
+ 0x1f6e, 0x157e, 0x20a9, 0x0000, 0x2021, 0x3e80, 0x047e, 0x2009,
+ 0x0004, 0x2011, 0x0010, 0x1078, 0x1fc8, 0x047f, 0x0040, 0x1f6d,
+ 0x8420, 0x0070, 0x1f6d, 0x0078, 0x1f5e, 0x157f, 0x8738, 0xa784,
+ 0x0007, 0x00c0, 0x1f49, 0x0078, 0x1bdb, 0x0078, 0x1bdb, 0x77b4,
+ 0x1078, 0x2cac, 0x6018, 0xa005, 0x0040, 0x1f9d, 0x2021, 0x3f80,
+ 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x1fc8, 0x0040, 0x1f9d,
+ 0x157e, 0x20a9, 0x0000, 0x2021, 0x3e80, 0x047e, 0x2009, 0x0005,
+ 0x2011, 0x0020, 0x1078, 0x1fc8, 0x047f, 0x0040, 0x1f9c, 0x8420,
+ 0x0070, 0x1f9c, 0x0078, 0x1f8d, 0x157f, 0x0078, 0x1bdb, 0x2200,
+ 0x0079, 0x1fa2, 0x1fa5, 0x1fa7, 0x1fa7, 0x1078, 0x1b81, 0x70a3,
+ 0x0000, 0x70a7, 0x0001, 0x0078, 0x1bd3, 0x2200, 0x0079, 0x1fb0,
+ 0x1fb5, 0x1fa7, 0x1fb3, 0x1078, 0x1b81, 0x1078, 0x2428, 0x7000,
+ 0xa086, 0x0001, 0x00c0, 0x28ba, 0x1078, 0x28fa, 0x6008, 0xa084,
+ 0xffef, 0x600a, 0x1078, 0x28ad, 0x0040, 0x28ba, 0x0078, 0x1cd1,
+ 0x2404, 0xa005, 0x0040, 0x1fe9, 0x2068, 0x2d04, 0x007e, 0x6810,
+ 0xa706, 0x0040, 0x1fd7, 0x2d20, 0x007f, 0x0078, 0x1fc9, 0x007f,
+ 0x2022, 0x6916, 0x681c, 0xa205, 0x681e, 0x1078, 0x17e7, 0x6010,
+ 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x28fa,
+ 0x007c, 0xa085, 0x0001, 0x0078, 0x1fe8, 0x2300, 0x0079, 0x1ff0,
+ 0x1ff5, 0x1ff3, 0x2038, 0x1078, 0x1b81, 0x78e4, 0xa005, 0x00d0,
+ 0x2018, 0x0018, 0x2018, 0x2008, 0xa084, 0x0030, 0x00c0, 0x2004,
+ 0x781b, 0x0049, 0x0078, 0x1bd3, 0x78ec, 0xa084, 0x0003, 0x0040,
+ 0x2000, 0x2100, 0xa084, 0x0007, 0x0079, 0x200e, 0x2026, 0x202c,
+ 0x2020, 0x2016, 0x2d63, 0x2d63, 0x2016, 0x2032, 0x1078, 0x1b81,
+ 0x7000, 0xa005, 0x0040, 0x1bdb, 0x2001, 0x0003, 0x0078, 0x22fd,
+ 0x1078, 0x2b94, 0x781b, 0x0055, 0x0078, 0x1bd3, 0x1078, 0x2b94,
+ 0x781b, 0x00dc, 0x0078, 0x1bd3, 0x1078, 0x2b94, 0x781b, 0x00e3,
+ 0x0078, 0x1bd3, 0x1078, 0x2b94, 0x781b, 0x009d, 0x0078, 0x1bd3,
+ 0xa584, 0x000f, 0x00c0, 0x2062, 0x1078, 0x2428, 0x7000, 0x0079,
+ 0x2041, 0x2049, 0x2056, 0x2049, 0x28ba, 0x204b, 0x28ba, 0x2049,
+ 0x2049, 0x1078, 0x1b81, 0x71a0, 0x70a3, 0x0000, 0xa186, 0x0004,
+ 0x00c0, 0x2054, 0x0078, 0x2913, 0x0078, 0x28ba, 0x1078, 0x28fa,
+ 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x28ad, 0x0040, 0x28ba,
+ 0x0078, 0x1cd1, 0x78e4, 0xa005, 0x00d0, 0x2018, 0x0018, 0x2018,
+ 0x2008, 0xa084, 0x0030, 0x00c0, 0x2071, 0x781b, 0x0049, 0x0078,
+ 0x1bd3, 0x78ec, 0xa084, 0x0003, 0x0040, 0x206d, 0x2100, 0xa184,
+ 0x0007, 0x0079, 0x207b, 0x208b, 0x2091, 0x2085, 0x2083, 0x2d63,
+ 0x2d63, 0x2083, 0x2d5b, 0x1078, 0x1b81, 0x1078, 0x2b9c, 0x781b,
+ 0x0055, 0x0078, 0x1bd3, 0x1078, 0x2b9c, 0x781b, 0x00dc, 0x0078,
+ 0x1bd3, 0x1078, 0x2b9c, 0x781b, 0x00e3, 0x0078, 0x1bd3, 0x1078,
+ 0x2b9c, 0x781b, 0x009d, 0x0078, 0x1bd3, 0x2300, 0x0079, 0x20a0,
+ 0x20a5, 0x20a3, 0x20a7, 0x1078, 0x1b81, 0x0078, 0x2670, 0x6817,
+ 0x0008, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x2670,
+ 0x78ec, 0xa084, 0x0003, 0x0040, 0x2670, 0xa184, 0x0007, 0x0079,
+ 0x20b9, 0x2026, 0x202c, 0x2020, 0x2d3b, 0x2d63, 0x2d63, 0x20c1,
+ 0x2d5b, 0x1078, 0x1b81, 0xa282, 0x0005, 0x0050, 0x20c9, 0x1078,
+ 0x1b81, 0x2300, 0x0079, 0x20cc, 0x20cf, 0x22d1, 0x22dd, 0x2200,
+ 0x0079, 0x20d2, 0x20d7, 0x20d9, 0x20ec, 0x20d7, 0x22b6, 0x1078,
+ 0x1b81, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020,
+ 0x0048, 0x2b75, 0xa08a, 0x0004, 0x00c8, 0x2b75, 0x0079, 0x20e8,
+ 0x2b75, 0x2b75, 0x2b75, 0x2b17, 0x789b, 0x0018, 0x79a8, 0xa184,
+ 0x0080, 0x0040, 0x2101, 0xa184, 0x0018, 0x0040, 0x20fd, 0x0078,
+ 0x2b75, 0x7000, 0xa005, 0x00c0, 0x20f7, 0x2011, 0x0003, 0x0078,
+ 0x275d, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x00c8, 0x2b75, 0x0079,
+ 0x2109, 0x211b, 0x2119, 0x2131, 0x2133, 0x21c5, 0x2b75, 0x2b75,
+ 0x21c7, 0x2b75, 0x2b75, 0x22b2, 0x22b2, 0x2b75, 0x2b75, 0x2b75,
+ 0x22b4, 0x1078, 0x1b81, 0xa684, 0x1000, 0x0040, 0x2128, 0x2001,
+ 0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x009a, 0x0078, 0x1bd3,
+ 0x6814, 0xa084, 0x8000, 0x0040, 0x212f, 0x6817, 0x0003, 0x0078,
+ 0x2d3b, 0x1078, 0x1b81, 0x691c, 0x691e, 0xa684, 0x1800, 0x00c0,
+ 0x214d, 0x681c, 0xa084, 0x0001, 0x00c0, 0x2155, 0x6814, 0xa086,
+ 0x0008, 0x00c0, 0x2145, 0x6817, 0x0000, 0xa684, 0x0400, 0x0040,
+ 0x21c1, 0x781b, 0x0058, 0x0078, 0x1bd3, 0xa684, 0x1000, 0x0040,
+ 0x2155, 0x781b, 0x0058, 0x0078, 0x1bd3, 0xa684, 0x0060, 0x0040,
+ 0x21bd, 0xa684, 0x0800, 0x0040, 0x21bd, 0xa684, 0x8000, 0x00c0,
+ 0x2163, 0x0078, 0x217d, 0xa6b4, 0x7fff, 0x7e5a, 0x6eb2, 0x789b,
+ 0x0074, 0x7aac, 0x79ac, 0x78ac, 0x801b, 0x00c8, 0x2170, 0x8000,
+ 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b94, 0x2100, 0xa302,
+ 0x68ae, 0x6b90, 0x2200, 0xa303, 0x68aa, 0xa684, 0x4000, 0x0040,
+ 0x2185, 0xa6b4, 0xbfff, 0x7e5a, 0x6eb2, 0x7000, 0xa086, 0x0003,
+ 0x00c0, 0x2192, 0x1078, 0x2f3d, 0x1078, 0x30e2, 0x781b, 0x0067,
+ 0x0078, 0x1bd3, 0xa006, 0x1078, 0x3197, 0x6aac, 0x69a8, 0x6c94,
+ 0x6b90, 0x2200, 0xa105, 0x0040, 0x21a1, 0x2200, 0xa422, 0x2100,
+ 0xa31b, 0x7cd2, 0x7bd6, 0x2300, 0xa405, 0x00c0, 0x21af, 0xa6b5,
+ 0x4000, 0x7e5a, 0x6eb2, 0x781b, 0x0067, 0x0078, 0x1bd3, 0x781b,
+ 0x0067, 0x2200, 0xa115, 0x00c0, 0x21b9, 0x1078, 0x30f3, 0x0078,
+ 0x1bd3, 0x1078, 0x3120, 0x0078, 0x1bd3, 0x781b, 0x006a, 0x0078,
+ 0x1bd3, 0x781b, 0x0058, 0x0078, 0x1bd3, 0x1078, 0x1b81, 0x0078,
+ 0x2224, 0x691c, 0xa184, 0x0100, 0x0040, 0x21df, 0xa18c, 0xfeff,
+ 0x691e, 0x0c7e, 0x7048, 0x2060, 0x6000, 0xa084, 0xefff, 0x6002,
+ 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078, 0x2213, 0xa184,
+ 0x0200, 0x0040, 0x2213, 0xa18c, 0xfdff, 0x691e, 0x0c7e, 0x7048,
+ 0x2060, 0x6000, 0xa084, 0xdfff, 0x6002, 0x6004, 0xa084, 0xffef,
+ 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2213,
+ 0x1078, 0x2ca8, 0x1078, 0x29f1, 0x88ff, 0x0040, 0x2213, 0x789b,
+ 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684,
+ 0x0400, 0x00c0, 0x220f, 0x781b, 0x0055, 0x0078, 0x1bd3, 0x781b,
+ 0x0069, 0x0078, 0x1bd3, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x221c,
+ 0x781b, 0x0058, 0x0078, 0x1bd3, 0x781b, 0x006a, 0x0078, 0x1bd3,
+ 0x0078, 0x2b7b, 0x0078, 0x2b7b, 0x2019, 0x0000, 0x7990, 0xa18c,
+ 0x0007, 0x0040, 0x2222, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff,
+ 0xa286, 0x0001, 0x00c0, 0x2247, 0x2300, 0x7ca8, 0xa400, 0x2018,
+ 0xa102, 0x0040, 0x223f, 0x0048, 0x223f, 0x0078, 0x2241, 0x0078,
+ 0x21c9, 0x24a8, 0x7aa8, 0x00f0, 0x2241, 0x0078, 0x222d, 0xa284,
+ 0x00f0, 0xa086, 0x0020, 0x00c0, 0x22a3, 0x8318, 0x8318, 0x2300,
+ 0xa102, 0x0040, 0x2257, 0x0048, 0x2257, 0x0078, 0x22a0, 0xa286,
+ 0x0023, 0x0040, 0x2222, 0x6818, 0xa084, 0xfff1, 0x681a, 0x7e58,
+ 0xa684, 0xfff1, 0xa085, 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085,
+ 0x0010, 0x600a, 0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48,
+ 0x0c7f, 0xa184, 0x0010, 0x0040, 0x227b, 0x1078, 0x2ca8, 0x1078,
+ 0x2ad7, 0x0078, 0x228a, 0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008,
+ 0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2213, 0x1078, 0x2ca8,
+ 0x1078, 0x29f1, 0x88ff, 0x0040, 0x2213, 0x789b, 0x0060, 0x2800,
+ 0x78aa, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x229c,
+ 0x781b, 0x0055, 0x0078, 0x1bd3, 0x781b, 0x0069, 0x0078, 0x1bd3,
+ 0x7aa8, 0x0078, 0x222d, 0x8318, 0x2300, 0xa102, 0x0040, 0x22ac,
+ 0x0048, 0x22ac, 0x0078, 0x222d, 0xa284, 0x0080, 0x00c0, 0x2b81,
+ 0x0078, 0x2b7b, 0x0078, 0x2b81, 0x0078, 0x2b75, 0x789b, 0x0018,
+ 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040, 0x22c1, 0x1078,
+ 0x1b81, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a,
+ 0x0004, 0x00c8, 0x2b75, 0x0079, 0x22cd, 0x2b75, 0x2944, 0x2b75,
+ 0x2a72, 0xa282, 0x0000, 0x00c0, 0x22d7, 0x1078, 0x1b81, 0x1078,
+ 0x2b94, 0x781b, 0x0069, 0x0078, 0x1bd3, 0xa282, 0x0003, 0x00c0,
+ 0x22e3, 0x1078, 0x1b81, 0x1078, 0x2ba4, 0x781b, 0x0069, 0x0078,
+ 0x1bd3, 0xa282, 0x0004, 0x0050, 0x22ef, 0x1078, 0x1b81, 0x2300,
+ 0x0079, 0x22f2, 0x22f5, 0x23d2, 0x2403, 0xa286, 0x0003, 0x0040,
+ 0x22fb, 0x1078, 0x1b81, 0x2001, 0x0000, 0x703a, 0x7000, 0xa084,
+ 0x0007, 0x0079, 0x2303, 0x230b, 0x230d, 0x230d, 0x2513, 0x253b,
+ 0x24dd, 0x230b, 0x230b, 0x1078, 0x1b81, 0xa684, 0x1000, 0x00c0,
+ 0x2315, 0x1078, 0x2eca, 0x0040, 0x23ac, 0x7868, 0xa08c, 0x00ff,
+ 0x0040, 0x235d, 0xa186, 0x0008, 0x00c0, 0x232c, 0x1078, 0x28fa,
+ 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x28ad, 0x0040, 0x235d,
+ 0x1078, 0x2eca, 0x0078, 0x2344, 0xa186, 0x0028, 0x00c0, 0x235d,
+ 0x1078, 0x2eca, 0x6008, 0xa084, 0xffef, 0x600a, 0x6018, 0xa005,
+ 0x0040, 0x2344, 0x8001, 0x601a, 0xa005, 0x0040, 0x2344, 0x8001,
+ 0xa005, 0x0040, 0x2344, 0x601e, 0x681c, 0xa084, 0x0001, 0x0040,
+ 0x1bdb, 0x681c, 0xa084, 0xfffe, 0x681e, 0x7054, 0x0c7e, 0x2060,
+ 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0,
+ 0x235a, 0x6002, 0x6006, 0x0078, 0x1bdb, 0x017e, 0x1078, 0x2428,
+ 0x017f, 0xa684, 0xdf00, 0x681a, 0x6827, 0x0000, 0x6f10, 0x81ff,
+ 0x0040, 0x23ac, 0xa186, 0x0002, 0x00c0, 0x23a4, 0xa684, 0x0800,
+ 0x00c0, 0x237a, 0xa684, 0x0060, 0x0040, 0x237a, 0x78d8, 0x7adc,
+ 0x682e, 0x6a2a, 0x8717, 0xa294, 0x000f, 0x8213, 0x8213, 0x8213,
+ 0xa290, 0x3600, 0xa290, 0x0000, 0x221c, 0xa384, 0x0100, 0x00c0,
+ 0x238b, 0x0078, 0x2391, 0x8210, 0x2204, 0xa085, 0x0018, 0x2012,
+ 0x8211, 0xa384, 0x0400, 0x0040, 0x239e, 0x689c, 0xa084, 0x0100,
+ 0x00c0, 0x239e, 0x1078, 0x249c, 0x0078, 0x1bdb, 0x6008, 0xa085,
+ 0x0002, 0x600a, 0x0078, 0x23ac, 0xa186, 0x0018, 0x0040, 0x23ac,
+ 0xa186, 0x0014, 0x0040, 0x1bdb, 0x6912, 0x6814, 0xa084, 0x8000,
+ 0x0040, 0x23b4, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x1078,
+ 0x28eb, 0x1078, 0x28fa, 0x00c0, 0x23c1, 0x6008, 0xa084, 0xffef,
+ 0x600a, 0x681c, 0xa084, 0x0001, 0x00c0, 0x23ca, 0x1078, 0x28e4,
+ 0x0078, 0x23ce, 0x7054, 0x2060, 0x6800, 0x6002, 0x1078, 0x17e7,
+ 0x0078, 0x1bdb, 0xa282, 0x0004, 0x0048, 0x23d8, 0x1078, 0x1b81,
+ 0x2200, 0x0079, 0x23db, 0x23df, 0x23e1, 0x23ee, 0x23e1, 0x1078,
+ 0x1b81, 0x7000, 0xa086, 0x0005, 0x0040, 0x23ea, 0x1078, 0x2b94,
+ 0x781b, 0x0069, 0x781b, 0x006a, 0x0078, 0x1bd3, 0x7890, 0x8007,
+ 0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c,
+ 0x00ff, 0xa186, 0x0003, 0x0040, 0x23ff, 0x0078, 0x2b75, 0x781b,
+ 0x006a, 0x0078, 0x1bd3, 0x681c, 0xa085, 0x0004, 0x681e, 0x82ff,
+ 0x00c0, 0x240e, 0x1078, 0x2b94, 0x0078, 0x2415, 0x8211, 0x0040,
+ 0x2413, 0x1078, 0x1b81, 0x1078, 0x2ba4, 0x781b, 0x0069, 0x0078,
+ 0x1bd3, 0x1078, 0x2d82, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2425,
+ 0x0018, 0x2425, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c,
+ 0xa684, 0x0060, 0x00c0, 0x2432, 0x682f, 0x0000, 0x682b, 0x0000,
+ 0x0078, 0x249b, 0xa684, 0x0800, 0x00c0, 0x2441, 0x68b0, 0xa084,
+ 0x4800, 0xa635, 0xa684, 0x0800, 0x00c0, 0x2441, 0x1078, 0x2eca,
+ 0x007c, 0xa684, 0x0020, 0x0040, 0x246d, 0x78d0, 0x8003, 0x00c8,
+ 0x244f, 0xa006, 0x1078, 0x3197, 0x78d4, 0x1078, 0x31fc, 0xa684,
+ 0x4000, 0x0040, 0x2459, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078,
+ 0x243e, 0x68b0, 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0,
+ 0x2453, 0x7038, 0xa005, 0x00c0, 0x2467, 0x703b, 0x0007, 0x79d8,
+ 0x7adc, 0x692e, 0x6a2a, 0x0078, 0x243e, 0xa684, 0x4000, 0x0040,
+ 0x2477, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078, 0x243e, 0x68b0,
+ 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2471, 0x7038,
+ 0xa005, 0x00c0, 0x2485, 0x703b, 0x0007, 0x79d8, 0x7adc, 0x78d0,
+ 0x80f3, 0x00c8, 0x248c, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291,
+ 0x0000, 0x692e, 0x6a2a, 0x2100, 0xa205, 0x00c0, 0x2499, 0x0078,
+ 0x243e, 0x1078, 0x3197, 0x007c, 0xa384, 0x0200, 0x0040, 0x24a4,
+ 0x6008, 0xa085, 0x0002, 0x600a, 0x6817, 0x0006, 0x6a28, 0x692c,
+ 0x6a3a, 0x693e, 0x682b, 0x0300, 0x682f, 0x0000, 0x6833, 0x2000,
+ 0x6893, 0x0000, 0x6897, 0x0020, 0x7000, 0x0079, 0x24b7, 0x24bf,
+ 0x24c1, 0x24ca, 0x24bf, 0x24bf, 0x24bf, 0x24bf, 0x24bf, 0x1078,
+ 0x1b81, 0x681c, 0xa084, 0x0001, 0x00c0, 0x24ca, 0x1078, 0x28e4,
+ 0x0078, 0x24d0, 0x7054, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60,
+ 0x2021, 0x3557, 0x2404, 0xa005, 0x0040, 0x24d9, 0x2020, 0x0078,
+ 0x24d2, 0x2d22, 0x206b, 0x0000, 0x007c, 0x77b4, 0x1078, 0x2bb1,
+ 0xa7bc, 0x0f00, 0x1078, 0x2cac, 0x6018, 0xa005, 0x0040, 0x250c,
+ 0x0d7e, 0x2001, 0x3f90, 0x2068, 0x0d7f, 0x2021, 0x3f80, 0x2009,
+ 0x0004, 0x2011, 0x0010, 0x1078, 0x1fc8, 0x0040, 0x250c, 0x157e,
+ 0x20a9, 0x0000, 0x2021, 0x3e80, 0x047e, 0x2009, 0x0004, 0x2011,
+ 0x0010, 0x1078, 0x1fc8, 0x047f, 0x0040, 0x250b, 0x8420, 0x0070,
+ 0x250b, 0x0078, 0x24fc, 0x157f, 0x8738, 0xa784, 0x0007, 0x00c0,
+ 0x24e2, 0x0078, 0x1bdb, 0x1078, 0x28eb, 0x1078, 0x28fa, 0x6827,
+ 0x0000, 0x789b, 0x000e, 0x6f10, 0x6813, 0x0002, 0x1078, 0x31cd,
+ 0xa684, 0x0800, 0x0040, 0x2528, 0x6918, 0xa18d, 0x2000, 0x691a,
+ 0x6814, 0xa084, 0x8000, 0x0040, 0x252f, 0x6817, 0x0000, 0x2021,
+ 0x3557, 0x6800, 0x2022, 0x6a38, 0x693c, 0x6a2a, 0x692e, 0x1078,
+ 0x17e7, 0x0078, 0x1bdb, 0x1078, 0x2428, 0x6827, 0x0000, 0x789b,
+ 0x000e, 0x6f10, 0x1078, 0x2d87, 0xa08c, 0x00ff, 0x6912, 0x6814,
+ 0xa084, 0x8000, 0x0040, 0x254e, 0x7038, 0x6816, 0xa68c, 0xdf00,
+ 0x691a, 0x70a3, 0x0000, 0x0078, 0x1bdb, 0xa006, 0x1078, 0x2eca,
+ 0x6813, 0x0000, 0x6817, 0x0001, 0xa68c, 0xdf00, 0x691a, 0x6827,
+ 0x0000, 0x7000, 0x0079, 0x2564, 0x256c, 0x256e, 0x256e, 0x2570,
+ 0x2570, 0x2570, 0x256c, 0x256c, 0x1078, 0x1b81, 0x1078, 0x28fa,
+ 0x6008, 0xa084, 0xffef, 0x600a, 0x0078, 0x28c5, 0x2300, 0x0079,
+ 0x2579, 0x257c, 0x257e, 0x25bc, 0x1078, 0x1b81, 0x7000, 0x0079,
+ 0x2581, 0x2589, 0x258b, 0x258b, 0x2596, 0x258b, 0x259d, 0x2589,
+ 0x2589, 0x1078, 0x1b81, 0xa684, 0x2000, 0x00c0, 0x2596, 0xa6b5,
+ 0x2000, 0x7e5a, 0x1078, 0x30f3, 0x0078, 0x2d3b, 0x6814, 0xa084,
+ 0x8000, 0x0040, 0x259d, 0x6817, 0x0007, 0x2009, 0x3518, 0x210c,
+ 0xa186, 0x0000, 0x0040, 0x25b2, 0xa186, 0x0001, 0x0040, 0x25b6,
+ 0x2009, 0x352b, 0x200b, 0x000b, 0x70a3, 0x0001, 0x781b, 0x0046,
+ 0x0078, 0x1bd3, 0x781b, 0x00dd, 0x0078, 0x1bd3, 0x2009, 0x352b,
+ 0x200b, 0x000a, 0x0078, 0x1bd3, 0x1078, 0x1b81, 0x2300, 0x0079,
+ 0x25c1, 0x25c4, 0x25c6, 0x25e9, 0x1078, 0x1b81, 0x7000, 0x0079,
+ 0x25c9, 0x25d1, 0x25d3, 0x25d3, 0x25de, 0x25d3, 0x25e5, 0x25d1,
+ 0x25d1, 0x1078, 0x1b81, 0xa684, 0x2000, 0x00c0, 0x25de, 0xa6b5,
+ 0x2000, 0x7e5a, 0x1078, 0x30f3, 0x0078, 0x2d3b, 0x6814, 0xa084,
+ 0x8000, 0x0040, 0x25e5, 0x6817, 0x0007, 0x781b, 0x00e4, 0x0078,
+ 0x1bd3, 0x681c, 0xa085, 0x0004, 0x681e, 0xa6b5, 0x0800, 0x1078,
+ 0x2b94, 0x781b, 0x0069, 0x0078, 0x1bd3, 0x2300, 0x0079, 0x25f8,
+ 0x25fb, 0x25fd, 0x25ff, 0x1078, 0x1b81, 0x1078, 0x1b81, 0xa684,
+ 0x0400, 0x00c0, 0x261e, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab,
+ 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xa184, 0x0020, 0x0040,
+ 0x2616, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x261a, 0x2001, 0x0014,
+ 0x0078, 0x22fd, 0xa184, 0x0007, 0x0079, 0x2656, 0x7a90, 0xa294,
+ 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x2654, 0x789b,
+ 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x2645, 0x7ba8, 0x7ba8,
+ 0xa386, 0x0001, 0x00c0, 0x2638, 0x2009, 0xfff7, 0x0078, 0x263e,
+ 0xa386, 0x0003, 0x00c0, 0x2645, 0x2009, 0xffef, 0x0c7e, 0x7048,
+ 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab,
+ 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x691c, 0xa18c,
+ 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d3b, 0x2026, 0x202c,
+ 0x2660, 0x2668, 0x265e, 0x265e, 0x265e, 0x2d3b, 0x1078, 0x1b81,
+ 0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d43,
+ 0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d3b,
+ 0x79e4, 0xa184, 0x0030, 0x0040, 0x267a, 0x78ec, 0xa084, 0x0003,
+ 0x00c0, 0x2682, 0x6814, 0xa085, 0x8000, 0x6816, 0x2001, 0x0014,
+ 0x0078, 0x22fd, 0xa184, 0x0007, 0x0079, 0x2686, 0x2d3b, 0x2d3b,
+ 0x268e, 0x2d3b, 0x2d63, 0x2d63, 0x2d3b, 0x2d3b, 0xa684, 0x0400,
+ 0x00c0, 0x26bf, 0x681c, 0xa084, 0x0001, 0x0040, 0x2d43, 0xa68c,
+ 0x2060, 0xa18c, 0xfffb, 0x795a, 0x69b2, 0x789b, 0x0060, 0x78ab,
+ 0x0000, 0x789b, 0x0061, 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa,
+ 0x157e, 0x137e, 0x147e, 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000,
+ 0x80ac, 0xad80, 0x000a, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f,
+ 0x6810, 0x8007, 0x789b, 0x007e, 0x78aa, 0x0078, 0x2d43, 0x6814,
+ 0xa084, 0x8000, 0x0040, 0x26c6, 0x6817, 0x0008, 0x781b, 0x00d8,
+ 0x0078, 0x1bd3, 0x2300, 0x0079, 0x26cd, 0x26d2, 0x274d, 0x26d0,
+ 0x1078, 0x1b81, 0x7000, 0xa084, 0x0007, 0x0079, 0x26d7, 0x26df,
+ 0x26e1, 0x26fd, 0x26df, 0x26df, 0x24dd, 0x26df, 0x26df, 0x1078,
+ 0x1b81, 0x691c, 0xa18d, 0x0001, 0x691e, 0x6800, 0x6006, 0xa005,
+ 0x00c0, 0x26eb, 0x6002, 0x6818, 0xa084, 0x000e, 0x0040, 0x26f7,
+ 0x7014, 0x68b6, 0x712c, 0xa188, 0x3e80, 0x0078, 0x26f9, 0x2009,
+ 0x3f80, 0x2104, 0x6802, 0x2d0a, 0x7156, 0x6eb2, 0xa684, 0x0060,
+ 0x0040, 0x274b, 0xa684, 0x0800, 0x00c0, 0x270f, 0xa684, 0x7fff,
+ 0x68b2, 0x6890, 0x6894, 0x1078, 0x2eca, 0x0078, 0x274b, 0xa684,
+ 0x0020, 0x0040, 0x2721, 0xa006, 0x1078, 0x3197, 0x78d0, 0x8003,
+ 0x00c8, 0x271d, 0x78d4, 0x1078, 0x31fc, 0x79d8, 0x7adc, 0x0078,
+ 0x2725, 0x1078, 0x2cb9, 0x1078, 0x3197, 0xa684, 0x8000, 0x0040,
+ 0x274b, 0xa684, 0x7fff, 0x68b2, 0x789b, 0x0074, 0x1078, 0x2d87,
+ 0x2010, 0x1078, 0x2d87, 0x2008, 0xa684, 0x0020, 0x00c0, 0x2743,
+ 0x1078, 0x2d87, 0x801b, 0x00c8, 0x273e, 0x8000, 0xa084, 0x003f,
+ 0xa108, 0xa291, 0x0000, 0x6b94, 0x2100, 0xa302, 0x68ae, 0x6b90,
+ 0x2200, 0xa303, 0x68aa, 0x0078, 0x1bdb, 0x0078, 0x2b81, 0x7033,
+ 0x0000, 0xa282, 0x0005, 0x0050, 0x2757, 0x1078, 0x1b81, 0x2300,
+ 0x0079, 0x275a, 0x275d, 0x2767, 0x278a, 0x2200, 0x0079, 0x2760,
+ 0x2765, 0x2b81, 0x2765, 0x27b3, 0x2804, 0x1078, 0x1b81, 0x7000,
+ 0xa086, 0x0001, 0x00c0, 0x2774, 0x1078, 0x28fa, 0x1078, 0x2eca,
+ 0x7034, 0x600a, 0x0078, 0x2779, 0x7000, 0xa086, 0x0003, 0x0040,
+ 0x276e, 0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e, 0x7032,
+ 0x2200, 0x0079, 0x2783, 0x2b81, 0x2788, 0x27b3, 0x2788, 0x2b81,
+ 0x1078, 0x1b81, 0x7000, 0xa086, 0x0001, 0x00c0, 0x2797, 0x1078,
+ 0x28fa, 0x1078, 0x2eca, 0x7034, 0x600a, 0x0078, 0x279c, 0x7000,
+ 0xa086, 0x0003, 0x0040, 0x2791, 0x7003, 0x0005, 0x2001, 0x3f90,
+ 0x2068, 0x703e, 0x7032, 0x2200, 0x0079, 0x27a6, 0x27ad, 0x27ab,
+ 0x27ad, 0x27ab, 0x27ad, 0x1078, 0x1b81, 0x1078, 0x2ba4, 0x781b,
+ 0x0069, 0x0078, 0x1bd3, 0x7000, 0xa086, 0x0001, 0x00c0, 0x27c0,
+ 0x1078, 0x28fa, 0x1078, 0x2eca, 0x7034, 0x600a, 0x0078, 0x27c5,
+ 0x7000, 0xa086, 0x0003, 0x0040, 0x27ba, 0x7003, 0x0002, 0x7a80,
+ 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215,
+ 0x2069, 0x3f80, 0x2d04, 0x2d08, 0x7156, 0x2068, 0xa005, 0x0040,
+ 0x27e0, 0x6810, 0xa206, 0x0040, 0x27f9, 0x6800, 0x0078, 0x27d3,
+ 0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e, 0x7032, 0x157e,
+ 0x20a9, 0x002f, 0x2003, 0x0000, 0x8000, 0x0070, 0x27f1, 0x0078,
+ 0x27ea, 0x157f, 0x6a12, 0x68b3, 0x0700, 0x681f, 0x0800, 0x6823,
+ 0x0003, 0x6eb0, 0x7e5a, 0x681c, 0xa084, 0x0c00, 0x0040, 0x285a,
+ 0x1078, 0x2b9c, 0x0078, 0x285a, 0x7000, 0xa086, 0x0001, 0x00c0,
+ 0x2811, 0x1078, 0x28fa, 0x1078, 0x2eca, 0x7034, 0x600a, 0x0078,
+ 0x2816, 0x7000, 0xa086, 0x0003, 0x0040, 0x280b, 0x7003, 0x0002,
+ 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007,
+ 0xa215, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0xa1e8, 0x3e80, 0x2d04,
+ 0x2d08, 0x7156, 0x2068, 0xa005, 0x0040, 0x2835, 0x6810, 0xa206,
+ 0x0040, 0x284e, 0x6800, 0x0078, 0x2828, 0x7003, 0x0005, 0x2001,
+ 0x3f90, 0x2068, 0x703e, 0x7032, 0x157e, 0x20a9, 0x002f, 0x2003,
+ 0x0000, 0x8000, 0x0070, 0x2846, 0x0078, 0x283f, 0x157f, 0x6a12,
+ 0x68b3, 0x0700, 0x681f, 0x0800, 0x6823, 0x0003, 0x6eb0, 0x7e5a,
+ 0x681c, 0xa084, 0x0c00, 0x0040, 0x285a, 0x1078, 0x2b98, 0x7e58,
+ 0x0078, 0x285a, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003,
+ 0x8003, 0xa080, 0x3600, 0x2060, 0x704a, 0x6000, 0x704e, 0x6004,
+ 0x7052, 0xa684, 0x0060, 0x0040, 0x2891, 0x6b94, 0x6c90, 0x69a8,
+ 0x68ac, 0xa105, 0x00c0, 0x287f, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde,
+ 0xa6b4, 0xb7ff, 0x7e5a, 0x1078, 0x30f3, 0x0078, 0x2891, 0x68ac,
+ 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040, 0x2891, 0x7bd2,
+ 0x7bda, 0x7cd6, 0x7cde, 0x68ac, 0xa6b4, 0xbfff, 0x7e5a, 0x1078,
+ 0x3120, 0x077f, 0x1078, 0x2cac, 0x2009, 0x006a, 0xa684, 0x0008,
+ 0x0040, 0x289c, 0x2009, 0x0069, 0xa6b5, 0x2000, 0x7e5a, 0x791a,
+ 0x2d00, 0x703e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+ 0xa080, 0x3600, 0x2048, 0x0078, 0x1bd3, 0x6020, 0xa005, 0x0040,
+ 0x28b9, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a, 0x7010,
+ 0x6026, 0x007c, 0xa006, 0x1078, 0x2eca, 0x6813, 0x0000, 0x6817,
+ 0x0001, 0x681f, 0x0040, 0x681b, 0x0100, 0x7000, 0xa084, 0x0007,
+ 0x0079, 0x28ca, 0x28d2, 0x28d4, 0x28d4, 0x28e0, 0x28dc, 0x28d2,
+ 0x28d2, 0x28d2, 0x1078, 0x1b81, 0x1078, 0x28eb, 0x1078, 0x28e4,
+ 0x1078, 0x17e7, 0x0078, 0x1bdb, 0x70a3, 0x0000, 0x0078, 0x1bdb,
+ 0x6817, 0x0000, 0x0078, 0x2513, 0x6800, 0xa005, 0x00c0, 0x28e9,
+ 0x6002, 0x6006, 0x007c, 0x6010, 0xa005, 0x0040, 0x28f4, 0x8001,
+ 0x00d0, 0x28f4, 0x1078, 0x1b81, 0x6012, 0x6008, 0xa084, 0xffef,
+ 0x600a, 0x007c, 0x6018, 0xa005, 0x0040, 0x2900, 0x8001, 0x601a,
+ 0x007c, 0x1078, 0x2d82, 0x6817, 0x0018, 0x0078, 0x2931, 0x1078,
+ 0x2d82, 0x6817, 0x0019, 0x0078, 0x2931, 0x1078, 0x2d82, 0x6817,
+ 0x001a, 0x0078, 0x2931, 0x77b4, 0x1078, 0x2cac, 0x71b8, 0xa18c,
+ 0x00ff, 0xa1e8, 0x3e80, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0,
+ 0x2923, 0x0078, 0x1bdb, 0x6810, 0x72b4, 0xa206, 0x0040, 0x292b,
+ 0x6800, 0x0078, 0x291c, 0x6800, 0x200a, 0x6817, 0x0005, 0x70bf,
+ 0x0000, 0x1078, 0x28eb, 0x681c, 0xa084, 0x0001, 0x00c0, 0x293a,
+ 0x1078, 0x28e4, 0x1078, 0x28fa, 0x681b, 0x0000, 0x681f, 0x0020,
+ 0x1078, 0x17e7, 0x0078, 0x1bdb, 0xa282, 0x0003, 0x00c0, 0x2b75,
+ 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x691c, 0xa18d,
+ 0x0080, 0x691e, 0xa184, 0x0100, 0x0040, 0x29a4, 0xa18c, 0xfeff,
+ 0x691e, 0xa6b4, 0x00ff, 0x0040, 0x298e, 0xa682, 0x000f, 0x0048,
+ 0x2965, 0x0040, 0x2965, 0x2031, 0x000f, 0x852b, 0x852b, 0x1078,
+ 0x2c2f, 0x0040, 0x296f, 0x1078, 0x2a3e, 0x0078, 0x2997, 0x1078,
+ 0x2bea, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078,
+ 0x2a62, 0x0c7f, 0x691c, 0xa18d, 0x0100, 0x691e, 0x7e58, 0xa6b5,
+ 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x298a, 0x781b, 0x0055,
+ 0x0078, 0x1bd3, 0x781b, 0x0069, 0x0078, 0x1bd3, 0x0c7e, 0x2960,
+ 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x2a62, 0x0c7f, 0x7e58,
+ 0xa684, 0x0400, 0x00c0, 0x29a0, 0x781b, 0x0058, 0x0078, 0x1bd3,
+ 0x781b, 0x006a, 0x0078, 0x1bd3, 0x0c7e, 0x7048, 0x2060, 0x6100,
+ 0xa18c, 0x1000, 0x0040, 0x29e4, 0x6208, 0x8217, 0xa294, 0x00ff,
+ 0xa282, 0x000f, 0x0048, 0x29b8, 0x0040, 0x29b8, 0x2011, 0x000f,
+ 0x2600, 0xa202, 0x00c8, 0x29bd, 0x2230, 0x6208, 0xa294, 0x00ff,
+ 0x7018, 0xa086, 0x0028, 0x00c0, 0x29cd, 0xa282, 0x0019, 0x00c8,
+ 0x29d3, 0x2011, 0x0019, 0x0078, 0x29d3, 0xa282, 0x000c, 0x00c8,
+ 0x29d3, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8, 0x29d8, 0x2228,
+ 0x1078, 0x2bee, 0x852b, 0x852b, 0x1078, 0x2c2f, 0x0040, 0x29e4,
+ 0x1078, 0x2a3e, 0x0078, 0x29e8, 0x1078, 0x2bea, 0x1078, 0x2a62,
+ 0x7858, 0xa085, 0x0004, 0x785a, 0x0c7f, 0x781b, 0x0069, 0x0078,
+ 0x1bd3, 0x0c7e, 0x2960, 0x6000, 0xa084, 0x1000, 0x00c0, 0x2a0c,
+ 0x6010, 0xa084, 0x000f, 0x00c0, 0x2a06, 0xa18c, 0x0002, 0x00c0,
+ 0x2a06, 0xa18c, 0xfff5, 0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032,
+ 0x2019, 0x0000, 0x0078, 0x2a2e, 0x6208, 0xa294, 0x00ff, 0x7018,
+ 0xa086, 0x0028, 0x00c0, 0x2a1c, 0xa282, 0x0019, 0x00c8, 0x2a22,
+ 0x2011, 0x0019, 0x0078, 0x2a22, 0xa282, 0x000c, 0x00c8, 0x2a22,
+ 0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000f,
+ 0x0048, 0x2a2e, 0x0040, 0x2a2e, 0x2019, 0x000f, 0x78ab, 0x0001,
+ 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005,
+ 0x681c, 0xa085, 0x0100, 0x681e, 0x0c7f, 0x007c, 0x0c7e, 0x7148,
+ 0x2160, 0x2008, 0xa084, 0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a,
+ 0x7eae, 0x6612, 0x78a4, 0xa084, 0xfff8, 0xa18c, 0x0007, 0xa105,
+ 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004,
+ 0xa084, 0x00ff, 0xa605, 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006,
+ 0x0c7f, 0x007c, 0x0c7e, 0x7048, 0x2060, 0x6018, 0x789a, 0x78a4,
+ 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886,
+ 0x0c7f, 0x007c, 0xa282, 0x0002, 0x00c0, 0x2b75, 0x7aa8, 0x691c,
+ 0xa18d, 0x0080, 0x691e, 0xa184, 0x0200, 0x0040, 0x2ab7, 0xa18c,
+ 0xfdff, 0x691e, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8, 0x2b75,
+ 0x1078, 0x2afe, 0x1078, 0x2a62, 0xa980, 0x0001, 0x200c, 0x1078,
+ 0x2ca8, 0x1078, 0x29f1, 0x88ff, 0x0040, 0x2aaa, 0x789b, 0x0060,
+ 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400,
+ 0x00c0, 0x2aa6, 0x781b, 0x0055, 0x0078, 0x1bd3, 0x781b, 0x0069,
+ 0x0078, 0x1bd3, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x2ab3, 0x781b,
+ 0x0058, 0x0078, 0x1bd3, 0x781b, 0x006a, 0x0078, 0x1bd3, 0xa282,
+ 0x0002, 0x00c8, 0x2abf, 0xa284, 0x0001, 0x0040, 0x2ac9, 0x7148,
+ 0xa188, 0x0000, 0x210c, 0xa18c, 0x2000, 0x00c0, 0x2ac9, 0x2011,
+ 0x0000, 0x1078, 0x2bdc, 0x1078, 0x2afe, 0x1078, 0x2a62, 0x7858,
+ 0xa085, 0x0004, 0x785a, 0x781b, 0x0069, 0x0078, 0x1bd3, 0x0c7e,
+ 0x027e, 0x2960, 0x6000, 0x2011, 0x0001, 0xa084, 0x2000, 0x00c0,
+ 0x2aee, 0x6014, 0xa084, 0x0040, 0x00c0, 0x2aec, 0xa18c, 0xffef,
+ 0x6106, 0xa006, 0x0078, 0x2afb, 0x2011, 0x0000, 0x78ab, 0x0001,
+ 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x681c,
+ 0xa085, 0x0200, 0x681e, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7048,
+ 0x2060, 0x82ff, 0x0040, 0x2b06, 0x2011, 0x0040, 0x6018, 0xa080,
+ 0x0002, 0x789a, 0x78a4, 0xa084, 0xffbf, 0xa205, 0x78a6, 0x6016,
+ 0x788a, 0x6004, 0xa084, 0xffef, 0x6006, 0x0c7f, 0x007c, 0x007e,
+ 0x7000, 0xa086, 0x0003, 0x0040, 0x2b20, 0x007f, 0x0078, 0x2b23,
+ 0x007f, 0x0078, 0x2b71, 0xa684, 0x0020, 0x0040, 0x2b71, 0x7888,
+ 0xa084, 0x0040, 0x0040, 0x2b71, 0x78a8, 0x8001, 0x0040, 0x2b30,
+ 0x7bb8, 0xa384, 0x003f, 0x831b, 0x00c8, 0x2b37, 0x8000, 0xa005,
+ 0x0040, 0x2b58, 0x831b, 0x00c8, 0x2b40, 0x8001, 0x0040, 0x2b6d,
+ 0xa006, 0x1078, 0x3197, 0x78b4, 0x1078, 0x31fc, 0x0078, 0x2b71,
+ 0xa684, 0x4000, 0x0040, 0x2b58, 0x78b8, 0x801b, 0x00c8, 0x2b51,
+ 0x8000, 0xa084, 0x003f, 0x00c0, 0x2b6d, 0xa6b4, 0xbfff, 0x7e5a,
+ 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108, 0x00c8, 0x2b61, 0xa291,
+ 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x3197, 0x781b,
+ 0x0067, 0x1078, 0x3061, 0x0078, 0x1bd3, 0x781b, 0x0067, 0x0078,
+ 0x1bd3, 0x781b, 0x006a, 0x0078, 0x1bd3, 0x1078, 0x2ba8, 0x781b,
+ 0x0069, 0x0078, 0x1bd3, 0x1078, 0x2b94, 0x781b, 0x0069, 0x0078,
+ 0x1bd3, 0x6823, 0x0002, 0x1078, 0x2b9c, 0x691c, 0xa18d, 0x0020,
+ 0x691e, 0x6814, 0xa084, 0x8000, 0x0040, 0x2b90, 0x6817, 0x0005,
+ 0x781b, 0x0069, 0x0078, 0x1bd3, 0x2001, 0x0005, 0x0078, 0x2baa,
+ 0x2001, 0x000c, 0x0078, 0x2baa, 0x2001, 0x0006, 0x0078, 0x2baa,
+ 0x2001, 0x000d, 0x0078, 0x2baa, 0x2001, 0x0009, 0x0078, 0x2baa,
+ 0x2001, 0x0007, 0x789b, 0x007f, 0x78aa, 0xa6b5, 0x0008, 0x7e5a,
+ 0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703,
+ 0xa0e0, 0x3600, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f,
+ 0x0040, 0x2bca, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085,
+ 0x0008, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040,
+ 0x0040, 0x2bda, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085,
+ 0x0010, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001,
+ 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab,
+ 0x0004, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0010,
+ 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa,
+ 0x789b, 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007, 0xa084,
+ 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c,
+ 0xfff0, 0x2001, 0x3546, 0x2004, 0xa082, 0x0028, 0x0040, 0x2c18,
+ 0x2021, 0x2c8f, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x2c1e,
+ 0x2021, 0x2c9b, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064,
+ 0x2404, 0xa084, 0xfff0, 0xa106, 0x0040, 0x2c2d, 0x8420, 0x2300,
+ 0xa210, 0x0070, 0x2c2d, 0x0078, 0x2c20, 0x157f, 0x007c, 0x157e,
+ 0x2011, 0x3546, 0x2214, 0xa282, 0x0032, 0x0048, 0x2c43, 0x0040,
+ 0x2c47, 0x2021, 0x2c81, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
+ 0x0032, 0x0078, 0x2c57, 0xa282, 0x0028, 0x0040, 0x2c4f, 0x2021,
+ 0x2c8f, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x2c55, 0x2021,
+ 0x2c9b, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2200,
+ 0xa502, 0x0040, 0x2c67, 0x0048, 0x2c67, 0x8420, 0x2300, 0xa210,
+ 0x0070, 0x2c64, 0x0078, 0x2c57, 0x157f, 0xa006, 0x007c, 0x157f,
+ 0xa582, 0x0064, 0x00c8, 0x2c70, 0x7808, 0xa085, 0x0070, 0x780a,
+ 0x78ec, 0xa084, 0x0300, 0x0040, 0x2c7e, 0x2404, 0xa09e, 0x1201,
+ 0x00c0, 0x2c7e, 0x2001, 0x2101, 0x0078, 0x2c7f, 0x2404, 0xa005,
+ 0x007c, 0x1201, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404, 0x5604,
+ 0x6605, 0x6805, 0x7806, 0x7a06, 0x0a07, 0x0c07, 0x0e07, 0x3202,
+ 0x4202, 0x5202, 0x6202, 0x7202, 0x6605, 0x7605, 0x7805, 0x7a05,
+ 0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202, 0x4202, 0x5202, 0x5404,
+ 0x6404, 0x7404, 0x7604, 0x7804, 0x7a04, 0x7c04, 0x7e04, 0x7f04,
+ 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784,
+ 0x0007, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e0, 0x3680,
+ 0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b, 0x00c8, 0x2cc0, 0x8000,
+ 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x007c, 0x0f7e, 0x2079,
+ 0x0100, 0x2009, 0x3540, 0x2091, 0x8000, 0x2104, 0x0079, 0x2cd0,
+ 0x2d02, 0x2cda, 0x2cda, 0x2cda, 0x2cda, 0x2cda, 0x2cd8, 0x2cd8,
+ 0x1078, 0x1b81, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004, 0x00c0,
+ 0x2cdc, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0, 0x2ce3,
+ 0x68b0, 0xa085, 0x4000, 0x68b2, 0x7858, 0xa085, 0x4000, 0x785a,
+ 0x7830, 0xa084, 0x0080, 0x00c0, 0x2d02, 0x0018, 0x2d02, 0x6818,
+ 0xa084, 0x0020, 0x00c0, 0x2d00, 0x781b, 0x00dd, 0x0078, 0x2d02,
+ 0x781b, 0x00e4, 0x2091, 0x8001, 0x0f7f, 0x007c, 0x0c7e, 0x6810,
+ 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e0, 0x3600,
+ 0x6004, 0xa084, 0x000a, 0x00c0, 0x2d39, 0x6108, 0xa194, 0xff00,
+ 0x0040, 0x2d39, 0xa18c, 0x00ff, 0x2001, 0x0019, 0xa106, 0x0040,
+ 0x2d28, 0x2001, 0x0032, 0xa106, 0x0040, 0x2d2c, 0x0078, 0x2d30,
+ 0x2009, 0x0020, 0x0078, 0x2d32, 0x2009, 0x003f, 0x0078, 0x2d32,
+ 0x2011, 0x0000, 0x2100, 0xa205, 0x600a, 0x6004, 0xa085, 0x0002,
+ 0x6006, 0x0c7f, 0x007c, 0x781b, 0x006a, 0x0078, 0x1bd3, 0x781b,
+ 0x0069, 0x0078, 0x1bd3, 0x781b, 0x0058, 0x0078, 0x1bd3, 0x781b,
+ 0x0055, 0x0078, 0x1bd3, 0x781b, 0x00dd, 0x0078, 0x1bd3, 0x781b,
+ 0x00dc, 0x0078, 0x1bd3, 0x781b, 0x00e4, 0x0078, 0x1bd3, 0x781b,
+ 0x00e3, 0x0078, 0x1bd3, 0x781b, 0x009e, 0x0078, 0x1bd3, 0x781b,
+ 0x009d, 0x0078, 0x1bd3, 0x70a3, 0x0001, 0x781b, 0x0046, 0x0078,
+ 0x1bd3, 0x007e, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2d80, 0x7808,
+ 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec,
+ 0xa084, 0x0021, 0x0040, 0x2d80, 0x7808, 0xa085, 0x0002, 0x780a,
+ 0x007f, 0x007c, 0x7808, 0xa085, 0x0002, 0x780a, 0x007c, 0x7830,
+ 0xa084, 0x0040, 0x00c0, 0x2d87, 0x0098, 0x2d90, 0x78ac, 0x007c,
+ 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005,
+ 0x78ec, 0xa084, 0x0021, 0x0040, 0x2d9f, 0x0098, 0x2d9d, 0x78ac,
+ 0x007e, 0x7808, 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0xa784,
+ 0x0070, 0x0040, 0x2dab, 0x6817, 0x0003, 0x7858, 0xa084, 0x3f00,
+ 0x681a, 0x682f, 0x0000, 0x682b, 0x0000, 0x784b, 0x0008, 0x78e4,
+ 0xa005, 0x00d0, 0x2018, 0xa084, 0x0020, 0x0040, 0x2018, 0x78ec,
+ 0xa084, 0x0003, 0x0040, 0x2018, 0x0018, 0x2018, 0x0078, 0x2b7b,
+ 0x0c7e, 0x6810, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+ 0xa080, 0x3600, 0x2060, 0x2048, 0x704a, 0x6000, 0x704e, 0x6004,
+ 0x7052, 0x0c7f, 0x007c, 0x0020, 0x0020, 0x0000, 0x0020, 0x0000,
+ 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
+ 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
+ 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
+ 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0062, 0x0009, 0x0014,
+ 0x0014, 0x9847, 0x0014, 0x0014, 0x98f5, 0x98e7, 0x0014, 0x0014,
+ 0x0080, 0x00bf, 0x0100, 0x0402, 0x2008, 0xf880, 0xa20a, 0x0014,
+ 0x300b, 0xa20c, 0x0014, 0xa200, 0x8838, 0x817e, 0x842a, 0x84a0,
+ 0x3806, 0x8839, 0x28c2, 0x9cc3, 0xa805, 0x0864, 0xa83b, 0x3008,
+ 0x28c1, 0x9cc3, 0xa201, 0x300c, 0x2847, 0x8161, 0x846a, 0x8000,
+ 0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2, 0x9ca0, 0xa8f3, 0x0864,
+ 0xa829, 0x300c, 0xa801, 0x3008, 0x28e1, 0x9ca0, 0x280d, 0xa204,
+ 0x64c0, 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677,
+ 0xa80f, 0x786e, 0x883e, 0xa80c, 0x282b, 0xa205, 0x64a0, 0x67a0,
+ 0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, 0xa801, 0x883e,
+ 0x2069, 0x28c1, 0x9cc3, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8dc,
+ 0xa207, 0x0014, 0xa203, 0x8000, 0x84a8, 0x85a4, 0x1872, 0x849a,
+ 0x883c, 0x1fe2, 0xf601, 0xa208, 0x856e, 0x866f, 0x0704, 0x3008,
+ 0x9ca0, 0x0014, 0xa202, 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2,
+ 0xf848, 0x8174, 0x86eb, 0x85eb, 0x872e, 0x87a9, 0x883f, 0x08e6,
+ 0xa8f1, 0xf861, 0xa8e8, 0xf801, 0x0014, 0xf881, 0x0016, 0x85b2,
+ 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532, 0xf221, 0x0014,
+ 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0xa206, 0x6865, 0x817f,
+ 0x842a, 0x1dc1, 0x8823, 0x0016, 0x6042, 0x8008, 0xa8fa, 0x8000,
+ 0x84a4, 0x8160, 0x842a, 0xf021, 0x3008, 0x84a8, 0x1dc6, 0x20d7,
+ 0x8822, 0x0016, 0x8000, 0x2848, 0x1011, 0xa8fc, 0x3008, 0x8000,
+ 0xa000, 0x2802, 0x1011, 0xa8fd, 0xa887, 0x3008, 0x283d, 0x1011,
+ 0xa8fd, 0xa209, 0x0017, 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1,
+ 0x0014, 0x26e0, 0x873a, 0xfaa2, 0x19f2, 0x1fe2, 0x0014, 0xa20b,
+ 0x0014, 0xa20d, 0x817e, 0x842a, 0x84a0, 0x3806, 0x0210, 0x9ccd,
+ 0x0704, 0x0000, 0x127e, 0x2091, 0x2200, 0x2049, 0x2eca, 0x7000,
+ 0x7204, 0xa205, 0x720c, 0xa215, 0x7008, 0xa084, 0xfffd, 0xa205,
+ 0x0040, 0x2edc, 0x0078, 0x2ee1, 0x7003, 0x0000, 0x127f, 0x2000,
+ 0x007c, 0x7000, 0xa084, 0x0001, 0x00c0, 0x2f0f, 0x7108, 0x8104,
+ 0x00c8, 0x2eee, 0x1078, 0x2fab, 0x0078, 0x2ee6, 0x700c, 0xa08c,
+ 0x007f, 0x0040, 0x2f0f, 0x7004, 0x8004, 0x00c8, 0x2f06, 0x7014,
+ 0xa005, 0x00c0, 0x2f02, 0x7010, 0xa005, 0x0040, 0x2f06, 0xa102,
+ 0x00c8, 0x2ee6, 0x7007, 0x0010, 0x0078, 0x2f0f, 0x8aff, 0x0040,
+ 0x2f0f, 0x1078, 0x316e, 0x00c0, 0x2f09, 0x0040, 0x2ee6, 0x1078,
+ 0x2f59, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x6424, 0x84ff,
+ 0x0040, 0x2f33, 0x2c70, 0x2039, 0x2f38, 0x2704, 0xae68, 0x680c,
+ 0xa630, 0x6808, 0xa529, 0x8421, 0x0040, 0x2f33, 0x8738, 0x2704,
+ 0xa005, 0x00c0, 0x2f1e, 0x7098, 0xa075, 0x0040, 0x2f33, 0x2039,
+ 0x2f35, 0x0078, 0x2f1d, 0x007c, 0x0000, 0x0004, 0x0008, 0x000c,
+ 0x0010, 0x0014, 0x0018, 0x001c, 0x0000, 0x127e, 0x2091, 0x2200,
+ 0x2079, 0x3500, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002,
+ 0x7003, 0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007, 0x0002,
+ 0x7003, 0x0000, 0x2049, 0x0000, 0x78b3, 0x0000, 0x127f, 0x2000,
+ 0x007c, 0x2049, 0x2f59, 0x7004, 0x8004, 0x00c8, 0x2f85, 0x7007,
+ 0x0012, 0x7108, 0x7008, 0xa106, 0x00c0, 0x2f61, 0xa184, 0x0030,
+ 0x0040, 0x2f6e, 0xa086, 0x0030, 0x00c0, 0x2f61, 0x7000, 0xa084,
+ 0x0001, 0x00c0, 0x2f85, 0x7008, 0xa084, 0x000c, 0x00c0, 0x2f83,
+ 0x710c, 0xa184, 0x0300, 0x00c0, 0x2f83, 0xa184, 0x007f, 0x00c0,
+ 0x2f59, 0x0078, 0x2f85, 0x6817, 0x0003, 0x7007, 0x0012, 0x7007,
+ 0x0008, 0x7004, 0xa084, 0x0008, 0x00c0, 0x2f89, 0x7007, 0x0012,
+ 0x7108, 0x8104, 0x0048, 0x2f8e, 0x78b3, 0x0000, 0x7003, 0x0000,
+ 0x2049, 0x0000, 0x007c, 0x107e, 0x007e, 0x127e, 0x157e, 0x2091,
+ 0x2200, 0x7108, 0x1078, 0x2fab, 0x157f, 0x127f, 0x2091, 0x8001,
+ 0x007f, 0x107f, 0x007c, 0x7204, 0x2118, 0x7108, 0x700c, 0xa084,
+ 0x0300, 0x00c0, 0x2fed, 0xa184, 0x000c, 0x00c0, 0x2fed, 0x8213,
+ 0x8213, 0x8213, 0x8213, 0xa284, 0x0100, 0xa10d, 0x810b, 0x810b,
+ 0x810f, 0xa184, 0x0007, 0x0079, 0x2fc5, 0x2fcf, 0x2fdf, 0x2fed,
+ 0x2fdf, 0x3001, 0x3001, 0x2fed, 0x2fff, 0x1078, 0x1b81, 0x7007,
+ 0x0002, 0x8aff, 0x00c0, 0x2fd8, 0x2049, 0x0000, 0x0078, 0x2fdc,
+ 0x1078, 0x316e, 0x00c0, 0x2fd8, 0x78b3, 0x0000, 0x007c, 0x7007,
+ 0x0002, 0x8aff, 0x00c0, 0x2fe6, 0x0078, 0x2fea, 0x1078, 0x316e,
+ 0x00c0, 0x2fe6, 0x78b3, 0x0000, 0x007c, 0x7007, 0x0002, 0x1078,
+ 0x2f59, 0x1078, 0x2cc6, 0x6814, 0xa084, 0x8000, 0x0040, 0x2ffa,
+ 0x6817, 0x0002, 0x007c, 0x1078, 0x1b81, 0x1078, 0x1b81, 0x1078,
+ 0x3053, 0x7210, 0x7114, 0x700c, 0xa09c, 0x007f, 0x2800, 0xa300,
+ 0xa211, 0xa189, 0x0000, 0x78b0, 0xa005, 0x0040, 0x3013, 0x78b3,
+ 0x0000, 0x0078, 0x3036, 0x1078, 0x3053, 0x2704, 0x2c58, 0xac60,
+ 0x630c, 0x2200, 0xa322, 0x6308, 0x2100, 0xa31b, 0x2400, 0xa305,
+ 0x0040, 0x302c, 0x00c8, 0x302c, 0x8412, 0x8210, 0x830a, 0xa189,
+ 0x0000, 0x2b60, 0x0078, 0x3013, 0x2b60, 0x8a07, 0xa7ba, 0x2f35,
+ 0xa73d, 0x2c00, 0x6882, 0x6f86, 0x6c8e, 0x6b8a, 0x7007, 0x0012,
+ 0x1078, 0x2f59, 0x007c, 0x8738, 0x2704, 0xa005, 0x00c0, 0x3047,
+ 0x6098, 0xa005, 0x0040, 0x3050, 0x2060, 0x2039, 0x2f35, 0x8a51,
+ 0x0040, 0x304f, 0x7008, 0xa084, 0x00c0, 0xa086, 0x00c0, 0x007c,
+ 0x2051, 0x0000, 0x007c, 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0,
+ 0x3060, 0x2039, 0x2f3b, 0x6000, 0xa064, 0x00c0, 0x3060, 0x2d60,
+ 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x6880, 0x2060,
+ 0x6884, 0x6b88, 0x6c8c, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff,
+ 0xa0b8, 0x2f35, 0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040,
+ 0x0040, 0x307c, 0xa6b5, 0x0001, 0x0f7e, 0x2079, 0x0100, 0x7858,
+ 0x0f7f, 0xa084, 0x0040, 0x0040, 0x308b, 0xa684, 0x0001, 0x00c0,
+ 0x308b, 0xa6b5, 0x0001, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
+ 0x00c0, 0x308d, 0x7000, 0xa005, 0x0040, 0x3098, 0x1078, 0x1b81,
+ 0x2400, 0xa305, 0x00c0, 0x309e, 0x0078, 0x30db, 0x2c58, 0x2704,
+ 0xac60, 0x6004, 0xa400, 0x007e, 0x701a, 0x6000, 0xa301, 0x701e,
+ 0x2009, 0x04fd, 0x2104, 0xa086, 0x04fd, 0x007f, 0x00c0, 0x30cb,
+ 0xa084, 0x0001, 0x0040, 0x30cb, 0xa684, 0x0001, 0x00c0, 0x30cb,
+ 0x7013, 0x0001, 0x7017, 0x0000, 0x7602, 0x7007, 0x0001, 0x78b3,
+ 0x0001, 0xa4a0, 0x0001, 0xa399, 0x0000, 0x6004, 0xa400, 0x701a,
+ 0x6000, 0xa301, 0x701e, 0x620c, 0x2400, 0xa202, 0x7012, 0x6208,
+ 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078,
+ 0x303b, 0x0078, 0x30dd, 0x1078, 0x316e, 0x00c0, 0x30db, 0x127f,
+ 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007,
+ 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x30e9, 0x7003, 0x0008,
+ 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f,
+ 0x2049, 0x30f3, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
+ 0x30fc, 0x7000, 0xa005, 0x0040, 0x3107, 0x1078, 0x1b81, 0x7e08,
+ 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, 0x0040, 0x3111, 0xa6b5,
+ 0x0001, 0x6824, 0xa005, 0x0040, 0x311d, 0x2050, 0x2039, 0x2f38,
+ 0x2d60, 0x1078, 0x316e, 0x00c0, 0x3119, 0x127f, 0x2000, 0x007c,
+ 0x127e, 0x007e, 0x017e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f,
+ 0x047f, 0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, 0x0040,
+ 0x3133, 0xa6b5, 0x0001, 0x2049, 0x3120, 0x6824, 0xa055, 0x0040,
+ 0x316b, 0x2d70, 0x2e60, 0x2039, 0x2f38, 0x2704, 0xae68, 0x680c,
+ 0xa422, 0x6808, 0xa31b, 0x0048, 0x3158, 0x8a51, 0x00c0, 0x314a,
+ 0x1078, 0x1b81, 0x8738, 0x2704, 0xa005, 0x00c0, 0x313e, 0x7098,
+ 0xa075, 0x2060, 0x0040, 0x316b, 0x2039, 0x2f35, 0x0078, 0x313d,
+ 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x690c, 0x2400, 0xa122,
+ 0x6908, 0x2300, 0xa11b, 0x00c8, 0x3167, 0x1078, 0x1b81, 0x2071,
+ 0x0020, 0x0078, 0x308b, 0x127f, 0x2000, 0x007c, 0x7008, 0xa084,
+ 0x00c0, 0xa086, 0x00c0, 0x0040, 0x3196, 0x2704, 0xac08, 0x2104,
+ 0x701e, 0x8108, 0x2104, 0x701a, 0x8108, 0x2104, 0x7016, 0x8108,
+ 0x2104, 0x7012, 0x0f7e, 0x2079, 0x0100, 0x7858, 0x0f7f, 0xa084,
+ 0x0040, 0x0040, 0x3191, 0xa684, 0x0001, 0x00c0, 0x3191, 0xa6b5,
+ 0x0001, 0x7602, 0x7007, 0x0001, 0x1078, 0x303b, 0x007c, 0x127e,
+ 0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x3197, 0x0d7f, 0x087f,
+ 0x7108, 0xa184, 0x00c0, 0x00c0, 0x31ad, 0x6824, 0xa005, 0x0040,
+ 0x31bd, 0x0078, 0x2ee1, 0x0078, 0x31bd, 0x7108, 0x8104, 0x00c8,
+ 0x31b5, 0x1078, 0x2fab, 0x0078, 0x31a0, 0x7007, 0x0010, 0x7108,
+ 0x8104, 0x00c8, 0x31b7, 0x1078, 0x2fab, 0x7008, 0xa086, 0x0002,
+ 0x00c0, 0x31a0, 0x7000, 0xa005, 0x00c0, 0x31a0, 0x7003, 0x0000,
+ 0x2049, 0x0000, 0x127f, 0x2000, 0x007c, 0x127e, 0x147e, 0x137e,
+ 0x157e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x31cd, 0xad80,
+ 0x0010, 0x20a0, 0x2099, 0x0031, 0x700c, 0xa084, 0x007f, 0x6826,
+ 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0040, 0x31eb,
+ 0x8000, 0x80ac, 0x53a5, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
+ 0x00c0, 0x31ed, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f,
+ 0x147f, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091,
+ 0x2200, 0x0d7f, 0x2049, 0x31fc, 0x6880, 0x2060, 0x6884, 0x6b88,
+ 0x6c8c, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0xa0b8, 0x2f35,
+ 0x7e08, 0xa6b5, 0x0004, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
+ 0x00c0, 0x3215, 0x2c58, 0x2704, 0xac60, 0x6004, 0xa400, 0x701a,
+ 0x6000, 0xa301, 0x701e, 0x7013, 0x0001, 0x7017, 0x0000, 0x7602,
+ 0x7007, 0x0001, 0x007f, 0x8007, 0x2009, 0x0031, 0x200a, 0x00a0,
+ 0x322f, 0x7108, 0x7007, 0x0002, 0x810c, 0x00c8, 0x322f, 0x810c,
+ 0x0048, 0x323c, 0x0078, 0x2fed, 0xa4a0, 0x0001, 0xa399, 0x0000,
+ 0x6b8a, 0x6c8e, 0x7007, 0x0004, 0x2049, 0x0000, 0x7003, 0x0000,
+ 0x127f, 0x2000, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086,
+ 0x818e, 0x00c8, 0x3254, 0xa200, 0x00f0, 0x324f, 0x8086, 0x818e,
+ 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x327a, 0xa11a,
+ 0x00c8, 0x327a, 0x8213, 0x818d, 0x0048, 0x326d, 0xa11a, 0x00c8,
+ 0x326e, 0x00f0, 0x3262, 0x0078, 0x3272, 0xa11a, 0x2308, 0x8210,
+ 0x00f0, 0x3262, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f,
+ 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x3276,
+ 0x00e0, 0x32c2, 0x2091, 0x6000, 0x7820, 0x8001, 0x7822, 0x00c0,
+ 0x32bc, 0x7824, 0x7822, 0x2091, 0x8000, 0x2069, 0x3540, 0x6800,
+ 0xa084, 0x0007, 0x0040, 0x32a4, 0xa086, 0x0002, 0x0040, 0x32a4,
+ 0x6830, 0xa00d, 0x0040, 0x32a4, 0x2104, 0xa005, 0x0040, 0x32a4,
+ 0x8001, 0x200a, 0x0040, 0x3372, 0x2061, 0x3680, 0x20a9, 0x0080,
+ 0x6034, 0xa005, 0x0040, 0x32b6, 0x8001, 0x6036, 0x00c0, 0x32b6,
+ 0x6010, 0xa005, 0x0040, 0x32b6, 0x1078, 0x1a23, 0xace0, 0x0010,
+ 0x0070, 0x32bc, 0x0078, 0x32a8, 0x1078, 0x32d7, 0x1078, 0x32c5,
+ 0x1078, 0x32fc, 0x2091, 0x8001, 0x007c, 0x783c, 0x8001, 0x783e,
+ 0x00c0, 0x32d6, 0x7840, 0x783e, 0x7848, 0xa005, 0x0040, 0x32d6,
+ 0x8001, 0x784a, 0x00c0, 0x32d6, 0x1078, 0x1a23, 0x007c, 0x7834,
+ 0x8001, 0x7836, 0x00c0, 0x32fb, 0x7838, 0x7836, 0x2091, 0x8000,
+ 0x7844, 0xa005, 0x00c0, 0x32e6, 0x2001, 0x0101, 0x8001, 0x7846,
+ 0xa080, 0x3e80, 0x2040, 0x2004, 0xa065, 0x0040, 0x32fb, 0x6020,
+ 0xa005, 0x0040, 0x32f7, 0x8001, 0x6022, 0x0040, 0x332b, 0x6000,
+ 0x2c40, 0x0078, 0x32ec, 0x007c, 0x7828, 0x8001, 0x782a, 0x00c0,
+ 0x332a, 0x782c, 0x782a, 0x7830, 0xa005, 0x00c0, 0x3309, 0x2001,
+ 0x0080, 0x8001, 0x7832, 0x8003, 0x8003, 0x8003, 0x8003, 0xa090,
+ 0x3680, 0xa298, 0x0002, 0x2304, 0xa084, 0x0008, 0x0040, 0x332a,
+ 0xa290, 0x0009, 0x2204, 0xa005, 0x0040, 0x3322, 0x8001, 0x2012,
+ 0x00c0, 0x332a, 0x2304, 0xa084, 0xfff7, 0xa085, 0x0080, 0x201a,
+ 0x1078, 0x1a23, 0x007c, 0x2069, 0x3540, 0x6800, 0xa005, 0x0040,
+ 0x3335, 0x683c, 0xac06, 0x0040, 0x3372, 0x6017, 0x0006, 0x60b0,
+ 0xa084, 0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff, 0xa085, 0x0060,
+ 0x601e, 0x6000, 0x2042, 0x6710, 0x6fb6, 0x1078, 0x169c, 0x6818,
+ 0xa005, 0x0040, 0x334d, 0x8001, 0x681a, 0x6808, 0xa084, 0xffef,
+ 0x680a, 0x6810, 0x8001, 0x00d0, 0x3357, 0x1078, 0x1b81, 0x6812,
+ 0x602f, 0x0000, 0x602b, 0x0000, 0x2c68, 0x1078, 0x17e7, 0x2069,
+ 0x3540, 0x2001, 0x0006, 0x68a2, 0x7944, 0xa184, 0x0100, 0x00c0,
+ 0x336d, 0x69ba, 0x2001, 0x0004, 0x68a2, 0x1078, 0x1a1e, 0x2091,
+ 0x8001, 0x007c, 0x2009, 0x354f, 0x2164, 0x2069, 0x0100, 0x6017,
+ 0x0006, 0x6858, 0xa084, 0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff,
+ 0xa085, 0x0048, 0x601e, 0x602f, 0x0000, 0x602b, 0x0000, 0x6830,
+ 0xa084, 0x0040, 0x0040, 0x33ac, 0x684b, 0x0004, 0x20a9, 0x0014,
+ 0x6848, 0xa084, 0x0004, 0x0040, 0x3399, 0x0070, 0x3399, 0x0078,
+ 0x3390, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001,
+ 0x0040, 0x33a6, 0x0070, 0x33a6, 0x0078, 0x339d, 0x20a9, 0x00fa,
+ 0x0070, 0x33ac, 0x0078, 0x33a8, 0x6808, 0xa084, 0xfffd, 0x680a,
+ 0x681b, 0x0046, 0x2009, 0x3568, 0x200b, 0x0007, 0x784c, 0x784a,
+ 0x2091, 0x8001, 0x007c, 0x2079, 0x3500, 0x1078, 0x3404, 0x1078,
+ 0x33cc, 0x1078, 0x33e1, 0x1078, 0x33f6, 0x7833, 0x0000, 0x7847,
+ 0x0000, 0x784b, 0x0000, 0x007c, 0x2019, 0x000a, 0x2011, 0x3546,
+ 0x2204, 0xa086, 0x0032, 0x0040, 0x33de, 0x2019, 0x000c, 0x2204,
+ 0xa086, 0x003c, 0x0040, 0x33de, 0x2019, 0x0008, 0x7b2a, 0x7b2e,
+ 0x007c, 0x2019, 0x0030, 0x2011, 0x3546, 0x2204, 0xa086, 0x0032,
+ 0x0040, 0x33f3, 0x2019, 0x0039, 0x2204, 0xa086, 0x003c, 0x0040,
+ 0x33f3, 0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x000d,
+ 0x2011, 0x3546, 0x2204, 0xa086, 0x003c, 0x0040, 0x3401, 0x2019,
+ 0x000a, 0x7b3e, 0x7b42, 0x007c, 0x2019, 0x2faf, 0x2011, 0x3546,
+ 0x2204, 0xa086, 0x0032, 0x0040, 0x3416, 0x2019, 0x3971, 0x2204,
+ 0xa086, 0x003c, 0x0040, 0x3416, 0x2019, 0x2626, 0x7b22, 0x7b26,
+ 0x007c, 0xda3e
+};
+
+unsigned short sbus_risc_code_length01 = 0x241a;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 84638f786..25490f2ad 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -162,7 +162,11 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
"Scanner ",
"Optical Device ",
"Medium Changer ",
- "Communications "
+ "Communications ",
+ "Unknown ",
+ "Unknown ",
+ "Unknown ",
+ "Enclosure ",
};
/*
@@ -241,6 +245,7 @@ static struct dev_info device_list[] =
{"SONY","CD-ROM CDU-541","4.3d", BLIST_NOLUN},
{"SONY","CD-ROM CDU-55S","1.0i", BLIST_NOLUN},
{"SONY","CD-ROM CDU-561","1.7x", BLIST_NOLUN},
+{"SONY","CD-ROM CDU-8012","*", BLIST_NOLUN},
{"TANDBERG","TDC 3600","U07", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
{"TEAC","CD-R55S","1.0H", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
{"TEAC","CD-ROM","1.06", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1
@@ -276,12 +281,11 @@ static struct dev_info device_list[] =
{"EMULEX","MD21/S2 ESDI","*", BLIST_SINGLELUN},
{"CANON","IPUBJD","*", BLIST_SPARSELUN},
{"nCipher","Fastness Crypto","*", BLIST_FORCELUN},
+{"NEC","PD-1 ODX654P","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"MATSHITA","PD","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"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...
*/
@@ -763,6 +767,7 @@ int scan_scsis_single (int channel, int dev, int lun, int *max_dev_lun,
case TYPE_PROCESSOR:
case TYPE_SCANNER:
case TYPE_MEDIUM_CHANGER:
+ case TYPE_ENCLOSURE:
SDpnt->writeable = 1;
break;
case TYPE_WORM:
@@ -1925,10 +1930,12 @@ void scsi_build_commandblocks(Scsi_Device * SDpnt)
SDpnt->device_queue = NULL;
for(j=0;j<SDpnt->queue_depth;j++){
- SCpnt = (Scsi_Cmnd *)
+ SCpnt = (Scsi_Cmnd *)
scsi_init_malloc(sizeof(Scsi_Cmnd),
GFP_ATOMIC |
(host->unchecked_isa_dma ? GFP_DMA : 0));
+ if (NULL == SCpnt)
+ break; /* If not, the next line will oops ... */
memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout));
SCpnt->host = host;
SCpnt->device = SDpnt;
@@ -1951,6 +1958,12 @@ void scsi_build_commandblocks(Scsi_Device * SDpnt)
SCpnt->state = SCSI_STATE_UNUSED;
SCpnt->owner = SCSI_OWNER_NOBODY;
}
+ if (j < SDpnt->queue_depth) { /* low on space (D.Gilbert 990424) */
+ printk("scsi_build_commandblocks: want=%d, space for=%d blocks\n",
+ SDpnt->queue_depth, j);
+ SDpnt->queue_depth = j;
+ /* Still problem if 0==j , continue anyway ... */
+ }
SDpnt->has_cmdblocks = 1;
}
@@ -2475,7 +2488,8 @@ static void resize_dma_pool(void)
}
else if (SDpnt->type == TYPE_SCANNER ||
SDpnt->type == TYPE_PROCESSOR ||
- SDpnt->type == TYPE_MEDIUM_CHANGER) {
+ SDpnt->type == TYPE_MEDIUM_CHANGER ||
+ SDpnt->type == TYPE_ENCLOSURE) {
new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth;
}
else {
@@ -3297,7 +3311,7 @@ int init_module(void)
/* One bit per sector to indicate free/busy */
size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap);
- dma_malloc_freelist = (unsigned char *) scsi_init_malloc(size, GFP_ATOMIC);
+ dma_malloc_freelist = (FreeSectorBitmap *) scsi_init_malloc(size, GFP_ATOMIC);
memset(dma_malloc_freelist, 0, size);
/* One pointer per page for the page list */
diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
index 046e13b24..2966ca4cd 100644
--- a/drivers/scsi/scsi.h
+++ b/drivers/scsi/scsi.h
@@ -39,7 +39,7 @@
# define FALSE 0
#endif
-#define MAX_SCSI_DEVICE_CODE 10
+#define MAX_SCSI_DEVICE_CODE 14
extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
#ifdef DEBUG
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index a3d7c3538..bdff5d78c 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -563,6 +563,7 @@ void scsi_sleep (int timeout)
struct semaphore sem = MUTEX_LOCKED;
struct timer_list timer;
+ init_timer(&timer);
timer.data = (unsigned long) &sem;
timer.expires = jiffies + timeout;
timer.function = (void (*)(unsigned long))scsi_sleep_done;
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 638270fe7..6587d5b53 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -131,15 +131,16 @@ static int ioctl_internal_command(Scsi_Device *dev, char * cmd,
else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n");
break;
case NOT_READY: /* This happens if there is no disc in drive */
- if(dev->removable){
+ if(dev->removable && (cmd[0] != TEST_UNIT_READY)){
printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n");
break;
- };
+ }
case UNIT_ATTENTION:
if (dev->removable){
dev->changed = 1;
SCpnt->result = 0; /* This is no longer considered an error */
- printk(KERN_INFO "Disc change detected.\n");
+ /* gag this error, VFS will log it anyway /axboe */
+ /* printk(KERN_INFO "Disc change detected.\n"); */
break;
};
default: /* Fall through for non-removable media */
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 13f511b96..e32d6f6cf 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -708,17 +708,23 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
*/
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;
}
+ if (rscsi_disks[dev].sector_size == 4096)
+ if((block & 7) || (SCpnt->request.nr_sectors & 7)) {
+ printk("sd.cBad block number/count requested");
+ SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
+ goto repeat;
+ }
switch (SCpnt->request.cmd)
{
@@ -984,6 +990,13 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
cmd[1] = (SCpnt->lun << 5) & 0xe0;
+ if (rscsi_disks[dev].sector_size == 4096){
+ if(block & 7) panic("sd.c:Bad block number requested");
+ if(this_count & 7) panic("sd.c:Bad block number requested");
+ block = block >> 3;
+ this_count = block >> 3;
+ }
+
if (rscsi_disks[dev].sector_size == 2048){
if(block & 3) panic("sd.c:Bad block number requested");
if(this_count & 3) panic("sd.c:Bad block number requested");
@@ -1335,6 +1348,7 @@ static int sd_init_onedisk(int i)
if (rscsi_disks[i].sector_size != 512 &&
rscsi_disks[i].sector_size != 1024 &&
rscsi_disks[i].sector_size != 2048 &&
+ rscsi_disks[i].sector_size != 4096 &&
rscsi_disks[i].sector_size != 256)
{
printk ("%s : unsupported sector size %d.\n",
@@ -1394,6 +1408,8 @@ static int sd_init_onedisk(int i)
nbuff, hard_sector, rscsi_disks[i].capacity,
mb, sz_quot, sz_rem);
}
+ if(rscsi_disks[i].sector_size == 4096)
+ rscsi_disks[i].capacity <<= 3;
if(rscsi_disks[i].sector_size == 2048)
rscsi_disks[i].capacity <<= 2; /* Change into 512 byte sectors */
if(rscsi_disks[i].sector_size == 1024)
diff --git a/drivers/scsi/sd_ioctl.c b/drivers/scsi/sd_ioctl.c
index 26ea27a33..ca19c6f6b 100644
--- a/drivers/scsi/sd_ioctl.c
+++ b/drivers/scsi/sd_ioctl.c
@@ -108,6 +108,11 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
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 --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 8eb3894cd..fd63ef0f6 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -4,7 +4,45 @@
* to allow user process control of SCSI devices.
* Development Sponsored by Killy Corp. NY NY
*
- * Borrows code from st driver.
+ * Original driver (sg.c):
+ * Copyright (C) 1992 Lawrence Foard
+ * 2.x extensions to driver:
+ * Copyright (C) 1998, 1999 Douglas Gilbert
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * Borrows code from st driver. Thanks to Alessandro Rubini's "dd" book.
+ */
+ static char * sg_version_str = "Version: 2.1.32 (990501)";
+/*
+ * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au)
+ * - scatter list logic replaces previous large atomic SG_BIG_BUFF
+ * sized allocation. See notes in <scsi/sg.h> include file.
+ *
+ * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
+ * the kernel/module needs to be built with CONFIG_SCSI_LOGGING
+ * (otherwise the macros compile to empty statements), then do
+ * something like: 'echo "scsi log all" > /proc/scsi/scsi' to log
+ * everything or 'echo "scsi log {token} #N" > /proc/scsi/scsi'
+ * where {token} is one of [error,timeout,scan,mlqueue,mlcomplete,
+ * llqueue,llcomplete,hlqueue,hlcomplete,ioctl] and #N is 0...7
+ * (with 0 meaning off). For example: 'scsi log timeout 7 >
+ * /proc/scsi/scsi' to get all logging messages from this driver.
+ * Should use hlcomplete but it is too "noisy" (sd uses it).
+ *
+ * - This driver obtains memory (heap) for the low-level driver to
+ * transfer/dma to and from. It is obtained from up to 4 sources:
+ * - 1 SG_SCATTER_SZ sized buffer on open() (per fd)
+ * [could be less if SG_SCATTER_SZ bytes not available]
+ * - obtain heap as required on write()s (get_free_pages)
+ * - obtain heap from the shared scsi dma pool
+ * - obtain heap from kernel directly (kmalloc) [last choice]
+ * the 'alt_address' field in the scatter_list structure and the
+ * related 'mem_src' indicate the source of the heap allocation.
+ *
*/
#include <linux/module.h>
@@ -28,541 +66,838 @@
#include <scsi/scsi_ioctl.h>
#include <scsi/sg.h>
-int sg_big_buff = SG_BIG_BUFF; /* for now, sg_big_buff is read-only through sysctl */
+
+int sg_big_buff = SG_SCATTER_SZ; /* sg_big_buff is ro through sysctl */
+/* N.B. This global is here to keep existing software happy. It now holds
+ the size of the "first buffer" of the most recent sucessful sg_open().
+ Only available when 'sg' compiled into kernel (rather than a module).
+ This should probably be deprecated (use SG_GET_RESERVED_SIZE instead). */
+
+#define SG_SECTOR_SZ 512
+#define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
+
+#define SG_LOW_POOL_THRESHHOLD 30
+#define SG_MAX_POOL_SECTORS 320 /* Max. number of pool sectors to take */
+
+static int sg_pool_secs_avail = SG_MAX_POOL_SECTORS;
+
+/* #define SG_DEBUG */ /* for counting varieties of allocations */
+
+#ifdef SG_DEBUG
+static int sg_num_kmal = 0;
+static int sg_num_pool = 0;
+static int sg_num_page = 0;
+#endif
+
+#define SG_HEAP_FB 0 /* heap obtained at open() (one buffer per fd) */
+#define SG_HEAP_PAGE 1 /* heap from kernel via get_free_pages() */
+#define SG_HEAP_KMAL 2 /* heap from kernel via kmalloc() */
+#define SG_HEAP_POOL 3 /* heap from scsi dma pool (mid-level) */
+
static int sg_init(void);
static int sg_attach(Scsi_Device *);
+static void sg_finish(void);
static int sg_detect(Scsi_Device *);
static void sg_detach(Scsi_Device *);
struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", NULL, 0xff,
- SCSI_GENERIC_MAJOR, 0, 0, 0, 0,
- sg_detect, sg_init,
- NULL, sg_attach, sg_detach};
-
-#ifdef SG_BIG_BUFF
-static char *big_buff = NULL;
-static struct wait_queue *big_wait; /* wait for buffer available */
-static int big_inuse=0;
-#endif
-
-struct scsi_generic
-{
- Scsi_Device *device;
- int users; /* how many people have it open? */
- struct wait_queue *generic_wait; /* wait for device to be available */
- struct wait_queue *read_wait; /* wait for response */
- struct wait_queue *write_wait; /* wait for free buffer */
- int timeout; /* current default value for device */
- int buff_len; /* length of current buffer */
- char *buff; /* the buffer */
- struct sg_header header; /* header of pending command */
- char exclude; /* opened for exclusive access */
- char pending; /* don't accept writes now */
- char complete; /* command complete allow a read */
-};
+ SCSI_GENERIC_MAJOR, 0, 0, 0, 0,
+ sg_detect, sg_init,
+ sg_finish, sg_attach, sg_detach};
-static struct scsi_generic *scsi_generics=NULL;
-static void sg_free(char *buff,int size);
-static int sg_ioctl(struct inode * inode,struct file * file,
- unsigned int cmd_in, unsigned long arg)
+typedef struct sg_scatter_hold /* holding area for scsi scatter gather info */
{
- int dev = MINOR(inode->i_rdev);
- int result;
-
- if ((dev<0) || (dev>=sg_template.dev_max))
- return -ENXIO;
+ unsigned short use_sg; /* Number of pieces of scatter-gather */
+ unsigned short sglist_len; /* size of malloc'd scatter-gather list */
+ unsigned bufflen; /* Size of data buffer */
+ unsigned b_malloc_len; /* actual len malloc'ed in buffer */
+ void * buffer; /* Data buffer or scatter list (12 bytes) */
+ char mem_src; /* heap whereabouts of 'buffer' */
+} Sg_scatter_hold; /* 20 bytes long on i386 */
+
+struct sg_device; /* forward declarations */
+struct sg_fd;
+
+typedef struct sg_request /* SG_MAX_QUEUE requests outstanding per file */
+{
+ Scsi_Cmnd * my_cmdp; /* NULL -> ready to read, else id */
+ struct sg_request * nextrp; /* NULL -> tail request (slist) */
+ struct sg_fd * parentfp; /* NULL -> not in use */
+ Sg_scatter_hold data; /* hold buffers, perhaps scatter list */
+ struct sg_header header; /* scsi command+info <include/sg.h> */
+ char fb_used; /* 1 -> using fst_buf, normally 0 (used) */
+} Sg_request; /* around 72 bytes long on i386 */
+
+typedef struct sg_fd /* holds the state of a file descriptor */
+{
+ struct sg_fd * nextfp; /* NULL when last opened fd on this device */
+ struct sg_device * parentdp; /* owning device */
+ struct wait_queue * read_wait; /* queue read until command done */
+ int timeout; /* defaults to SG_DEFAULT_TIMEOUT */
+ char * fst_buf; /* try to grab SG_SCATTER_SZ sized buffer on open */
+ int fb_size; /* actual size of allocated fst_buf */
+ Sg_request * headrp; /* head of request slist, NULL->empty */
+ struct fasync_struct * async_qp; /* used by asynchronous notification */
+ Sg_request req_arr[SG_MAX_QUEUE]; /* used as singly-linked list */
+ char low_dma; /* as in parent but possible overridden to 1 */
+ char force_packid; /* 1 -> pack_id input to read(), 0 -> ignored */
+ char closed; /* 1 -> fd closed but request(s) outstanding */
+ char my_mem_src; /* heap whereabouts of this sg_fb object */
+ char cmd_q; /* 1 -> allow command queuing, 0 -> don't */
+ char underrun_flag; /* 1 -> flag underruns, 0 -> don't, 2 -> test */
+} Sg_fd; /* around 1192 bytes long on i386 */
+
+typedef struct sg_device /* holds the state of each scsi generic device */
+{
+ Scsi_Device * device;
+ struct wait_queue * generic_wait;/* queue open if O_EXCL on prev. open */
+ int sg_tablesize; /* adapter's max scatter-gather table size */
+ Sg_fd * headfp; /* first open fd belonging to this device */
+ kdev_t i_rdev; /* holds device major+minor number */
+ char exclude; /* opened for exclusive access */
+ char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */
+ unsigned char merge_fd; /* 0->sequencing per fd (def) else fd count */
+} Sg_device; /* around 24 bytes long on i386 */
+
+
+static int sg_fasync(int fd, struct file * filp, int mode);
+static void sg_command_done(Scsi_Cmnd * SCpnt);
+static int sg_sc_build(Sg_request * srp, int max_buff_size,
+ const char * inp, int num_write_xfer);
+static int sg_sc_undo_rem(Sg_request * srp, char * outp,
+ int num_read_xfer);
+static char * sg_malloc(Sg_request * srp, int size, int * retSzp,
+ int * mem_srcp);
+static void sg_free(Sg_request * srp, char * buff, int size, int mem_src);
+static char * sg_low_malloc(int rqSz, int lowDma, int mem_src,
+ int * retSzp);
+static void sg_low_free(char * buff, int size, int mem_src);
+static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev, int get_reserved);
+static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
+static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id);
+static Sg_request * sg_add_request(Sg_fd * sfp);
+static int sg_remove_request(Sg_fd * sfp, const Sg_request * srp);
+static int sg_fb_in_use(const Sg_fd * sfp);
+static void sg_clr_scpnt(Scsi_Cmnd * SCpnt);
+static void sg_shorten_timeout(Scsi_Cmnd * scpnt);
+static void sg_debug(const Sg_device * sdp, const Sg_fd * sfp, int part_of);
+static void sg_debug_all(const Sg_fd * sfp);
+
+static Sg_device * sg_dev_arr = NULL;
+static const int size_sg_header = sizeof(struct sg_header);
- /*
- * If we are in the middle of error recovery, then don't allow any
- * access to this device. Also, error recovery *may* have taken the
- * device offline, in which case all further access is prohibited.
- */
- if( !scsi_block_when_processing_errors(scsi_generics[dev].device) )
- {
- return -ENXIO;
- }
- switch(cmd_in)
- {
- case SG_SET_TIMEOUT:
- result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
- if (result) return result;
-
- get_user(scsi_generics[dev].timeout, (int *) arg);
- return 0;
- case SG_GET_TIMEOUT:
- return scsi_generics[dev].timeout;
- case SG_EMULATED_HOST:
- return put_user(scsi_generics[dev].device->host->hostt->emulated, (int *) arg);
- case SCSI_IOCTL_SEND_COMMAND:
- /*
- Allow SCSI_IOCTL_SEND_COMMAND without checking suser() since the
- user already has read/write access to the generic device and so
- can execute arbitrary SCSI commands.
- */
- return scsi_ioctl_send_command(scsi_generics[dev].device, (void *) arg);
- default:
- return scsi_ioctl(scsi_generics[dev].device, cmd_in, (void *) arg);
- }
-}
static int sg_open(struct inode * inode, struct file * filp)
{
- int dev=MINOR(inode->i_rdev);
- int flags=filp->f_flags;
- if (dev>=sg_template.dev_max || !scsi_generics[dev].device)
- return -ENXIO;
+ int dev = MINOR(inode->i_rdev);
+ int flags = filp->f_flags;
+ Sg_device * sdp;
+ Sg_fd * sfp;
- if( !scsi_block_when_processing_errors(scsi_generics[dev].device) )
- {
+ if ((NULL == sg_dev_arr) || (dev < 0) || (dev >= sg_template.dev_max))
return -ENXIO;
- }
-
- if (O_RDWR!=(flags & O_ACCMODE))
- return -EACCES;
-
- /*
- * If we want exclusive access, then wait until the device is not
- * busy, and then set the flag to prevent anyone else from using it.
- */
- if (flags & O_EXCL)
- {
- while(scsi_generics[dev].users)
- {
- if (flags & O_NONBLOCK)
- return -EBUSY;
- interruptible_sleep_on(&scsi_generics[dev].generic_wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- }
- scsi_generics[dev].exclude=1;
+ sdp = &sg_dev_arr[dev];
+ if ((! sdp->device) || (! sdp->device->host))
+ return -ENXIO;
+ if (sdp->i_rdev != inode->i_rdev)
+ printk("sg_open: inode maj=%d, min=%d sdp maj=%d, min=%d\n",
+ MAJOR(inode->i_rdev), MINOR(inode->i_rdev),
+ MAJOR(sdp->i_rdev), MINOR(sdp->i_rdev));
+ if(! scsi_block_when_processing_errors(sdp->device))
+ return -ENXIO;
+/* if (O_RDWR != (flags & O_ACCMODE)) */
+/* return -EACCES; May just want to get to a ioctl, so remove */
+
+ SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
+ /* If we want exclusive access, then wait until the device is not
+ * busy, and then set the flag to prevent anyone else from using it. */
+ if (flags & O_EXCL) {
+ if (O_RDONLY == (flags & O_ACCMODE))
+ return -EACCES; /* Can't lock it with read only access */
+ while (sdp->headfp) {
+ if (flags & O_NONBLOCK)
+ return -EBUSY;
+ interruptible_sleep_on(&sdp->generic_wait);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ }
+ sdp->exclude = 1;
}
- else
- /*
- * Wait until nobody has an exclusive open on
- * this device.
- */
- while(scsi_generics[dev].exclude)
- {
- if (flags & O_NONBLOCK)
- return -EBUSY;
- interruptible_sleep_on(&scsi_generics[dev].generic_wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- }
-
- /*
- * OK, we should have grabbed the device. Mark the thing so
+ else { /* Wait until nobody has an exclusive open on this device. */
+ while (sdp->exclude) {
+ if (flags & O_NONBLOCK)
+ return -EBUSY;
+ interruptible_sleep_on(&sdp->generic_wait);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ }
+ }
+ /* OK, we should have grabbed the device. Mark the thing so
* that other processes know that we have it, and initialize the
- * state variables to known values.
- */
- if (!scsi_generics[dev].users
- && scsi_generics[dev].pending
- && scsi_generics[dev].complete)
- {
- if (scsi_generics[dev].buff != NULL)
- sg_free(scsi_generics[dev].buff,scsi_generics[dev].buff_len);
- scsi_generics[dev].buff=NULL;
- scsi_generics[dev].pending=0;
- }
- if (!scsi_generics[dev].users)
- scsi_generics[dev].timeout=SG_DEFAULT_TIMEOUT;
- if (scsi_generics[dev].device->host->hostt->module)
- __MOD_INC_USE_COUNT(scsi_generics[dev].device->host->hostt->module);
+ * state variables to known values. */
+ if (! sdp->headfp) { /* no existing opens on this device */
+ sdp->sgdebug = 0;
+ sdp->sg_tablesize = sdp->device->host->sg_tablesize;
+ sdp->merge_fd = 0; /* A little tricky if SG_DEF_MERGE_FD set */
+ }
+ if ((sfp = sg_add_sfp(sdp, dev, O_RDWR == (flags & O_ACCMODE)))) {
+ filp->private_data = sfp;
+#if SG_DEF_MERGE_FD
+ if (0 == sdp->merge_fd)
+ sdp->merge_fd = 1;
+#endif
+ }
+ else {
+ if (flags & O_EXCL) sdp->exclude = 0; /* undo if error */
+ return -ENOMEM;
+ }
+
+ if (sdp->device->host->hostt->module)
+ __MOD_INC_USE_COUNT(sdp->device->host->hostt->module);
if (sg_template.module)
__MOD_INC_USE_COUNT(sg_template.module);
- scsi_generics[dev].users++;
return 0;
}
-static int sg_close(struct inode * inode, struct file * filp)
+/* Following function was formerly called 'sg_close' */
+static int sg_release(struct inode * inode, struct file * filp)
{
- int dev=MINOR(inode->i_rdev);
- scsi_generics[dev].users--;
- if (scsi_generics[dev].device->host->hostt->module)
- __MOD_DEC_USE_COUNT(scsi_generics[dev].device->host->hostt->module);
+ Sg_device * sdp;
+ Sg_fd * sfp;
+
+ if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
+ return -ENXIO;
+ SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", MINOR(sdp->i_rdev)));
+ sg_fasync(-1, filp, 0); /* remove filp from async notification list */
+ sg_remove_sfp(sdp, sfp);
+ if (! sdp->headfp) {
+ filp->private_data = NULL;
+ sdp->merge_fd = 0;
+ }
+
+ if (sdp->device->host->hostt->module)
+ __MOD_DEC_USE_COUNT(sdp->device->host->hostt->module);
if(sg_template.module)
__MOD_DEC_USE_COUNT(sg_template.module);
- scsi_generics[dev].exclude=0;
- wake_up(&scsi_generics[dev].generic_wait);
+ sdp->exclude = 0;
+ wake_up_interruptible(&sdp->generic_wait);
return 0;
}
-static char *sg_malloc(int size)
+/* Read back the results of a SCSI command which was sent in a prior
+ write(). */
+static ssize_t sg_read(struct file * filp, char * buf,
+ size_t count, loff_t *ppos)
{
- if (size<=4096)
- return (char *) scsi_malloc(size);
-#ifdef SG_BIG_BUFF
- if (size<=SG_BIG_BUFF)
- {
- while(big_inuse)
- {
- interruptible_sleep_on(&big_wait);
- if (signal_pending(current))
- return NULL;
- }
- big_inuse=1;
- return big_buff;
+ int k;
+ Sg_device * sdp;
+ Sg_fd * sfp;
+ Sg_request * srp;
+ int req_pack_id = -1;
+ struct sg_header * shp = (struct sg_header *)buf;
+
+ if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
+ return -ENXIO;
+ SCSI_LOG_TIMEOUT(3, printk("sg_read: dev=%d, count=%d\n",
+ MINOR(sdp->i_rdev), (int)count));
+
+ /* If we are in the middle of error recovery, don't let anyone
+ * else try and use this device. Also, if error recovery fails, it
+ * may try and take the device offline, in which case all further
+ * access to the device is prohibited. */
+ if(! scsi_block_when_processing_errors(sdp->device))
+ return -ENXIO;
+
+ if (ppos != &filp->f_pos)
+ ; /* FIXME: Hmm. Seek to the right place, or fail? */
+ if ((k = verify_area(VERIFY_WRITE, buf, count)))
+ return k;
+ if (sfp->force_packid && (count >= size_sg_header))
+ req_pack_id = shp->pack_id;
+ srp = sg_get_request(sfp, req_pack_id);
+ while(! srp) {
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ interruptible_sleep_on(&sfp->read_wait);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ srp = sg_get_request(sfp, req_pack_id);
}
-#endif
- return NULL;
+ if (2 != sfp->underrun_flag)
+ srp->header.pack_len = srp->header.reply_len; /* Why ????? */
+
+ /* Now copy the result back to the user buffer. */
+ if (count >= size_sg_header) {
+ __copy_to_user(buf, &srp->header, size_sg_header);
+ buf += size_sg_header;
+ if (count > srp->header.reply_len)
+ count = srp->header.reply_len;
+ if (count > size_sg_header) /* release does copy_to_user */
+ sg_sc_undo_rem(srp, buf, count - size_sg_header);
+ else
+ sg_sc_undo_rem(srp, NULL, 0);
+ }
+ else {
+ count = (srp->header.result == 0) ? 0 : -EIO;
+ sg_sc_undo_rem(srp, NULL, 0);
+ }
+ return count;
}
-static void sg_free(char *buff,int size)
+static ssize_t sg_write(struct file * filp, const char * buf,
+ size_t count, loff_t *ppos)
{
-#ifdef SG_BIG_BUFF
- if (buff==big_buff)
- {
- big_inuse=0;
- wake_up(&big_wait);
- return;
+ unsigned long flags;
+ int mxsize, cmd_size, k;
+ unsigned char cmnd[MAX_COMMAND_SIZE];
+ int input_size;
+ unsigned char opcode;
+ Scsi_Cmnd * SCpnt;
+ Sg_device * sdp;
+ Sg_fd * sfp;
+ Sg_request * srp;
+
+ if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
+ return -ENXIO;
+ SCSI_LOG_TIMEOUT(3, printk("sg_write: dev=%d, count=%d\n",
+ MINOR(sdp->i_rdev), (int)count));
+
+/* If we are in the middle of error recovery, don't let anyone
+ * else try and use this device. Also, if error recovery fails, it
+ * may try and take the device offline, in which case all further
+ * access to the device is prohibited. */
+ if(! scsi_block_when_processing_errors(sdp->device) )
+ return -ENXIO;
+
+ if (ppos != &filp->f_pos)
+ ; /* FIXME: Hmm. Seek to the right place, or fail? */
+
+ if ((k = verify_area(VERIFY_READ, buf, count)))
+ return k; /* protects following copy_from_user()s + get_user()s */
+/* The minimum scsi command length is 6 bytes. If we get anything
+ * less than this, it is clearly bogus. */
+ if (count < (size_sg_header + 6))
+ return -EIO;
+
+ srp = sg_add_request(sfp);
+ if (! srp) {
+ SCSI_LOG_TIMEOUT(1, printk("sg_write: queue full, domain error\n"));
+ return -EDOM;
}
-#endif
- scsi_free(buff,size);
+ __copy_from_user(&srp->header, buf, size_sg_header);
+ buf += size_sg_header;
+ srp->header.pack_len = count;
+ __get_user(opcode, buf);
+ cmd_size = COMMAND_SIZE(opcode);
+ if ((opcode >= 0xc0) && srp->header.twelve_byte)
+ cmd_size = 12;
+ SCSI_LOG_TIMEOUT(4, printk("sg_write: scsi opcode=0x%02x, cmd_size=%d\n",
+ (int)opcode, cmd_size));
+/* Determine buffer size. */
+ input_size = count - cmd_size;
+ mxsize = (input_size > srp->header.reply_len) ? input_size :
+ srp->header.reply_len;
+/* Don't include the command header itself in the size. */
+ mxsize -= size_sg_header;
+ input_size -= size_sg_header;
+/* Verify user has actually passed enough bytes for this command. */
+ if (input_size < 0) {
+ sg_sc_undo_rem(srp, NULL, 0);
+ return -EIO;
+ }
+
+/* If we cannot allocate the buffer, report an error. */
+ if ((k = sg_sc_build(srp, mxsize, buf + cmd_size, input_size))) {
+ SCSI_LOG_TIMEOUT(1, printk("sg_write: build err=%d\n", k));
+ sg_sc_undo_rem(srp, NULL, 0);
+ return k;
+ }
+
+/* SCSI_LOG_TIMEOUT(7, printk("sg_write: allocating device\n")); */
+/* Grab a command pointer for the device we want to talk to. If we
+ * don't want to block, just return with the appropriate message. */
+ if (! (SCpnt = scsi_allocate_device(NULL, sdp->device,
+ !(filp->f_flags & O_NONBLOCK)))) {
+ sg_sc_undo_rem(srp, NULL, 0);
+ return -EAGAIN;
+ }
+/* SCSI_LOG_TIMEOUT(7, printk("sg_write: device allocated\n")); */
+
+ srp->my_cmdp = SCpnt;
+ SCpnt->request.rq_dev = sdp->i_rdev;
+ SCpnt->request.rq_status = RQ_ACTIVE;
+ SCpnt->sense_buffer[0] = 0;
+ SCpnt->cmd_len = cmd_size;
+ /* Now copy the SCSI command from the user's address space. */
+ __copy_from_user(cmnd, buf, cmd_size);
+
+/* Set the LUN field in the command structure. */
+ cmnd[1]= (cmnd[1] & 0x1f) | (sdp->device->lun << 5);
+/* SCSI_LOG_TIMEOUT(7, printk("sg_write: do cmd\n")); */
+/* Now pass the actual command down to the low-level driver. We
+ * do not do any more here - when the interrupt arrives, we will
+ * then do the post-processing. */
+ spin_lock_irqsave(&io_request_lock, flags);
+ SCpnt->use_sg = srp->data.use_sg;
+ SCpnt->sglist_len = srp->data.sglist_len;
+ SCpnt->bufflen = srp->data.bufflen;
+ if (1 == sfp->underrun_flag)
+ SCpnt->underflow = srp->data.bufflen;
+ else
+ SCpnt->underflow = 0;
+ SCpnt->buffer = srp->data.buffer;
+ srp->data.use_sg = 0;
+ srp->data.sglist_len = 0;
+ srp->data.bufflen = 0;
+ srp->data.buffer = NULL;
+ scsi_do_cmd(SCpnt, (void *)cmnd,
+ (void *)SCpnt->buffer, mxsize,
+ sg_command_done, sfp->timeout, SG_DEFAULT_RETRIES);
+ /* 'mxsize' overwrites SCpnt->bufflen, hence need for b_malloc_len */
+ spin_unlock_irqrestore(&io_request_lock, flags);
+/* SCSI_LOG_TIMEOUT(6, printk("sg_write: sent scsi cmd to mid-level\n")); */
+ return count;
}
-/*
- * Read back the results of a previous command. We use the pending and
- * complete semaphores to tell us whether the buffer is available for us
- * and whether the command is actually done.
- */
-static ssize_t sg_read(struct file *filp, char *buf,
- size_t count, loff_t *ppos)
+static int sg_ioctl(struct inode * inode, struct file * filp,
+ unsigned int cmd_in, unsigned long arg)
{
- struct inode *inode = filp->f_dentry->d_inode;
- int dev=MINOR(inode->i_rdev);
- int i;
- struct scsi_generic *device=&scsi_generics[dev];
+ int result, val;
+ Sg_device * sdp;
+ Sg_fd * sfp;
+ Sg_request * srp;
- /*
- * If we are in the middle of error recovery, don't let anyone
- * else try and use this device. Also, if error recovery fails, it
- * may try and take the device offline, in which case all further
- * access to the device is prohibited.
- */
- if( !scsi_block_when_processing_errors(scsi_generics[dev].device) )
- {
+ if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
+ return -ENXIO;
+ SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: dev=%d, cmd=0x%x\n",
+ MINOR(sdp->i_rdev), (int)cmd_in));
+ /* If we are in the middle of error recovery, then don't allow any
+ * access to this device. Also, error recovery *may* have taken the
+ * device offline, in which case all further access is prohibited. */
+ if(! scsi_block_when_processing_errors(sdp->device) )
return -ENXIO;
- }
- if (ppos != &filp->f_pos) {
- /* FIXME: Hmm. Seek to the right place, or fail? */
+ switch(cmd_in)
+ {
+ case SG_SET_TIMEOUT:
+ return get_user(sfp->timeout, (int *)arg);
+ case SG_GET_TIMEOUT:
+ return sfp->timeout; /* strange ..., for backward compatibility */
+ case SG_SET_FORCE_LOW_DMA:
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ if (val) {
+ if ((0 == sfp->low_dma) && (0 == sg_fb_in_use(sfp))) {
+ sg_low_free(sfp->fst_buf, sfp->fb_size, SG_HEAP_PAGE);
+ sfp->fst_buf = sg_low_malloc(SG_SCATTER_SZ, 1,
+ SG_HEAP_PAGE, &sfp->fb_size);
+ }
+ sfp->low_dma = 1;
+ if (! sfp->fst_buf)
+ return -ENOMEM;
+ }
+ else
+ sfp->low_dma = sdp->device->host->unchecked_isa_dma;
+ return 0;
+ case SG_GET_LOW_DMA:
+ return put_user((int)sfp->low_dma, (int *)arg);
+ case SG_GET_SCSI_ID:
+ result = verify_area(VERIFY_WRITE, (void *)arg, sizeof(Sg_scsi_id));
+ if (result) return result;
+ else {
+ Sg_scsi_id * sg_idp = (Sg_scsi_id *)arg;
+ __put_user((int)sdp->device->host->host_no, &sg_idp->host_no);
+ __put_user((int)sdp->device->channel, &sg_idp->channel);
+ __put_user((int)sdp->device->id, &sg_idp->scsi_id);
+ __put_user((int)sdp->device->lun, &sg_idp->lun);
+ __put_user((int)sdp->device->type, &sg_idp->scsi_type);
+ __put_user(0, &sg_idp->unused1);
+ __put_user(0, &sg_idp->unused2);
+ __put_user(0, &sg_idp->unused3);
+ return 0;
+ }
+ case SG_SET_FORCE_PACK_ID:
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ sfp->force_packid = val ? 1 : 0;
+ return 0;
+ case SG_GET_PACK_ID:
+ result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
+ if (result) return result;
+ srp = sfp->headrp;
+ while (srp) {
+ if (! srp->my_cmdp) {
+ __put_user(srp->header.pack_id, (int *)arg);
+ return 0;
+ }
+ srp = srp->nextrp;
+ }
+ __put_user(-1, (int *)arg);
+ return 0;
+ case SG_GET_NUM_WAITING:
+ srp = sfp->headrp;
+ val = 0;
+ while (srp) {
+ if (! srp->my_cmdp)
+ ++val;
+ srp = srp->nextrp;
+ }
+ return put_user(val, (int *)arg);
+ case SG_GET_SG_TABLESIZE:
+ return put_user(sdp->sg_tablesize, (int *)arg);
+ case SG_SET_RESERVED_SIZE:
+ /* currently ignored, future extension */
+ if (O_RDWR != (filp->f_flags & O_ACCMODE))
+ return -EACCES;
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ /* logic should go here */
+ return 0;
+ case SG_GET_RESERVED_SIZE:
+ return put_user(sfp->fb_size, (int *)arg);
+ case SG_GET_MERGE_FD:
+ return put_user((int)sdp->merge_fd, (int *)arg);
+ case SG_SET_MERGE_FD:
+ if (O_RDWR != (filp->f_flags & O_ACCMODE))
+ return -EACCES; /* require write access since effect wider
+ then just this fd */
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ val = val ? 1 : 0;
+ if ((val ^ (0 != sdp->merge_fd)) &&
+ sdp->headfp && sdp->headfp->nextfp)
+ return -EBUSY; /* too much work if multiple fds already */
+ sdp->merge_fd = val;
+ return 0;
+ case SG_SET_COMMAND_Q:
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ sfp->cmd_q = val ? 1 : 0;
+ return 0;
+ case SG_GET_COMMAND_Q:
+ return put_user((int)sfp->cmd_q, (int *)arg);
+ case SG_SET_UNDERRUN_FLAG:
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ sfp->underrun_flag = val;
+ return 0;
+ case SG_GET_UNDERRUN_FLAG:
+ return put_user((int)sfp->underrun_flag, (int *)arg);
+ case SG_EMULATED_HOST:
+ return put_user(sdp->device->host->hostt->emulated, (int *)arg);
+ case SCSI_IOCTL_SEND_COMMAND:
+ /* Allow SCSI_IOCTL_SEND_COMMAND without checking suser() since the
+ user already has read/write access to the generic device and so
+ can execute arbitrary SCSI commands. */
+ if (O_RDWR != (filp->f_flags & O_ACCMODE))
+ return -EACCES; /* require write access since these could be
+ dangerous */
+ return scsi_ioctl_send_command(sdp->device, (void *)arg);
+ case SG_SET_DEBUG:
+ result = get_user(val, (int *)arg);
+ if (result) return result;
+ sdp->sgdebug = (char)val;
+ if (9 == sdp->sgdebug)
+ sg_debug(sdp, sfp, 0);
+ else if (sdp->sgdebug > 9)
+ sg_debug_all(sfp);
+ return 0;
+ case SCSI_IOCTL_GET_IDLUN:
+ case SCSI_IOCTL_GET_BUS_NUMBER:
+ case SCSI_IOCTL_PROBE_HOST:
+ case SG_GET_TRANSFORM:
+ return scsi_ioctl(sdp->device, cmd_in, (void *)arg);
+ default:
+ if (O_RDWR != (filp->f_flags & O_ACCMODE))
+ return -EACCES; /* require write access since these could be
+ dangerous */
+ return scsi_ioctl(sdp->device, cmd_in, (void *)arg);
}
+}
- if ((i=verify_area(VERIFY_WRITE,buf,count)))
- return i;
-
- /*
- * Wait until the command is actually done.
- */
- while(!device->pending || !device->complete)
- {
- if (filp->f_flags & O_NONBLOCK)
- {
- return -EAGAIN;
- }
- interruptible_sleep_on(&device->read_wait);
- if (signal_pending(current))
- {
- return -ERESTARTSYS;
- }
- }
-
- /*
- * Now copy the result back to the user buffer.
- */
- device->header.pack_len=device->header.reply_len;
-
- if (count>=sizeof(struct sg_header))
- {
- copy_to_user(buf,&device->header,sizeof(struct sg_header));
- buf+=sizeof(struct sg_header);
- if (count>device->header.pack_len)
- count=device->header.pack_len;
- if (count > sizeof(struct sg_header)) {
- copy_to_user(buf,device->buff,count-sizeof(struct sg_header));
- }
+static unsigned int sg_poll(struct file * filp, poll_table * wait)
+{
+ unsigned int res = 0;
+ Sg_device * sdp;
+ Sg_fd * sfp;
+ Sg_request * srp;
+ int count = 0;
+
+ if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
+ return POLLERR;
+ poll_wait(filp, &sfp->read_wait, wait);
+ srp = sfp->headrp;
+ while (srp) { /* if any read waiting, flag it */
+ if (! (res || srp->my_cmdp))
+ res = POLLIN | POLLRDNORM;
+ ++count;
+ srp = srp->nextrp;
}
- else
- count= device->header.result==0 ? 0 : -EIO;
-
- /*
- * Clean up, and release the device so that we can send another
- * command.
- */
- sg_free(device->buff,device->buff_len);
- device->buff = NULL;
- device->pending=0;
- wake_up(&device->write_wait);
- return count;
+ if (0 == sfp->cmd_q) {
+ if (0 == count)
+ res |= POLLOUT | POLLWRNORM;
+ }
+ else if (count < SG_MAX_QUEUE)
+ res |= POLLOUT | POLLWRNORM;
+ SCSI_LOG_TIMEOUT(3, printk("sg_poll: dev=%d, res=0x%x\n",
+ MINOR(sdp->i_rdev), (int)res));
+ return res;
}
-/*
- * This function is called by the interrupt handler when we
+static int sg_fasync(int fd, struct file * filp, int mode)
+{
+ int retval;
+ Sg_device * sdp;
+ Sg_fd * sfp;
+
+ if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
+ return -ENXIO;
+ SCSI_LOG_TIMEOUT(3, printk("sg_fasync: dev=%d, mode=%d\n",
+ MINOR(sdp->i_rdev), mode));
+
+ retval = fasync_helper(fd, filp, mode, &sfp->async_qp);
+ return (retval < 0) ? retval : 0;
+}
+
+/* This function is called by the interrupt handler when we
* actually have a command that is complete. Change the
- * flags to indicate that we have a result.
- */
+ * flags to indicate that we have a result. */
static void sg_command_done(Scsi_Cmnd * SCpnt)
{
int dev = MINOR(SCpnt->request.rq_dev);
- struct scsi_generic *device = &scsi_generics[dev];
- if (!device->pending)
- {
- printk("unexpected done for sg %d\n",dev);
+ Sg_device * sdp;
+ Sg_fd * sfp;
+ Sg_request * srp = NULL;
+ int closed = 0;
+
+ if ((NULL == sg_dev_arr) || (dev < 0) || (dev >= sg_template.dev_max)) {
+ SCSI_LOG_TIMEOUT(1, printk("sg__done: bad args dev=%d\n", dev));
scsi_release_command(SCpnt);
SCpnt = NULL;
- return;
+ return;
}
-
- /*
- * See if the command completed normally, or whether something went
- * wrong.
- */
- memcpy(device->header.sense_buffer, SCpnt->sense_buffer,
- sizeof(SCpnt->sense_buffer));
- switch (host_byte(SCpnt->result)) {
+ sdp = &sg_dev_arr[dev];
+ if (NULL == sdp->device)
+ return; /* Get out of here quick ... */
+
+ sfp = sdp->headfp;
+ while (sfp) {
+ srp = sfp->headrp;
+ while (srp) {
+ if (SCpnt == srp->my_cmdp)
+ break;
+ srp = srp->nextrp;
+ }
+ if (srp)
+ break;
+ sfp = sfp->nextfp;
+ }
+ if (! srp) {
+ SCSI_LOG_TIMEOUT(1, printk("sg__done: req missing, dev=%d\n", dev));
+ scsi_release_command(SCpnt);
+ SCpnt = NULL;
+ return;
+ }
+/* First transfer ownership of data buffers to sg_device object. */
+ srp->data.use_sg = SCpnt->use_sg;
+ srp->data.sglist_len = SCpnt->sglist_len;
+ srp->data.bufflen = SCpnt->bufflen;
+ srp->data.buffer = SCpnt->buffer;
+ if (2 == sfp->underrun_flag)
+ srp->header.pack_len = SCpnt->underflow;
+ sg_clr_scpnt(SCpnt);
+ srp->my_cmdp = NULL;
+
+ SCSI_LOG_TIMEOUT(4,
+ printk("sg__done: dev=%d, scsi_stat=%d, res=0x%x\n",
+ dev, (int)status_byte(SCpnt->result), (int)SCpnt->result));
+/* See if the command completed normally, or whether something went wrong. */
+ memcpy(srp->header.sense_buffer, SCpnt->sense_buffer,
+ sizeof(SCpnt->sense_buffer));
+ switch (host_byte(SCpnt->result))
+ {
case DID_OK:
- device->header.result = 0;
+ case DID_PASSTHROUGH: /* just guessing */
+ case DID_SOFT_ERROR: /* just guessing */
+ srp->header.result = 0;
break;
case DID_NO_CONNECT:
case DID_BUS_BUSY:
case DID_TIME_OUT:
- device->header.result = EBUSY;
+ srp->header.result = EBUSY;
break;
case DID_BAD_TARGET:
case DID_ABORT:
case DID_PARITY:
case DID_RESET:
case DID_BAD_INTR:
- device->header.result = EIO;
+ srp->header.result = EIO;
break;
case DID_ERROR:
- /*
- * There really should be DID_UNDERRUN and DID_OVERRUN error values,
+ /* There really should be DID_UNDERRUN and DID_OVERRUN error values,
* and a means for callers of scsi_do_cmd to indicate whether an
* underrun or overrun should signal an error. Until that can be
* implemented, this kludge allows for returning useful error values
* except in cases that return DID_ERROR that might be due to an
- * underrun.
- */
+ * underrun. */
if (SCpnt->sense_buffer[0] == 0 &&
- status_byte(SCpnt->result) == GOOD)
- device->header.result = 0;
- else device->header.result = EIO;
+ status_byte(SCpnt->result) == GOOD)
+ srp->header.result = 0;
+ else
+ srp->header.result = EIO;
break;
+ default:
+ SCSI_LOG_TIMEOUT(1, printk(
+ "sg: unexpected host_byte=%d, dev=%d in 'done'\n",
+ host_byte(SCpnt->result), dev));
+ srp->header.result = EIO;
+ break;
+ }
+
+/* Following if statement is a patch supplied by Eric Youngdale */
+ if (driver_byte(SCpnt->result) != 0
+ && (SCpnt->sense_buffer[0] & 0x7f) == 0x70
+ && (SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION
+ && sdp->device->removable) {
+/* Detected disc change. Set the bit - this may be used if there are */
+/* filesystems using this device. */
+ sdp->device->changed = 1;
}
- /*
- * Now wake up the process that is waiting for the
- * result.
- */
- device->complete=1;
+/* Pick up error and status information */
+ srp->header.target_status = status_byte(SCpnt->result);
+ if ((sdp->sgdebug > 0) &&
+ ((CHECK_CONDITION == srp->header.target_status) ||
+ (COMMAND_TERMINATED == srp->header.target_status)))
+ print_sense("sg_command_done", SCpnt);
+ srp->header.host_status = host_byte(SCpnt->result);
+ srp->header.driver_status = driver_byte(SCpnt->result);
+
scsi_release_command(SCpnt);
SCpnt = NULL;
- wake_up(&scsi_generics[dev].read_wait);
+ if (sfp->closed) { /* whoops this fd already released, cleanup */
+ closed = 1;
+ SCSI_LOG_TIMEOUT(1,
+ printk("sg__done: already closed, freeing ...\n"));
+/* should check if module is unloaded <<<<<<< */
+ sg_sc_undo_rem(srp, NULL, 0);
+ if (NULL == sfp->headrp) {
+ SCSI_LOG_TIMEOUT(1,
+ printk("sg__done: already closed, final cleanup\n"));
+ sg_remove_sfp(sdp, sfp);
+ }
+ }
+/* Now wake up the process that is waiting for the result. */
+ /* A. Rubini says this is preferable+faster than wake_up() */
+ wake_up_interruptible(&sfp->read_wait);
+ if ((sfp->async_qp) && (! closed))
+ kill_fasync(sfp->async_qp, SIGPOLL);
}
-static ssize_t sg_write(struct file *filp, const char *buf,
- size_t count, loff_t *ppos)
+static void sg_debug_all(const Sg_fd * sfp)
{
- unsigned long flags;
- struct inode *inode = filp->f_dentry->d_inode;
- int bsize,size,amt,i;
- unsigned char cmnd[MAX_COMMAND_SIZE];
- kdev_t devt = inode->i_rdev;
- int dev = MINOR(devt);
- struct scsi_generic * device=&scsi_generics[dev];
- int input_size;
- unsigned char opcode;
- Scsi_Cmnd * SCpnt;
-
- /*
- * If we are in the middle of error recovery, don't let anyone
- * else try and use this device. Also, if error recovery fails, it
- * may try and take the device offline, in which case all further
- * access to the device is prohibited.
- */
- if( !scsi_block_when_processing_errors(scsi_generics[dev].device) )
- {
- return -ENXIO;
- }
-
- if (ppos != &filp->f_pos) {
- /* FIXME: Hmm. Seek to the right place, or fail? */
- }
-
- if ((i=verify_area(VERIFY_READ,buf,count)))
- return i;
- /*
- * The minimum scsi command length is 6 bytes. If we get anything
- * less than this, it is clearly bogus.
- */
- if (count<(sizeof(struct sg_header) + 6))
- return -EIO;
-
- /*
- * If we still have a result pending from a previous command,
- * wait until the result has been read by the user before sending
- * another command.
- */
- while(device->pending)
- {
- if (filp->f_flags & O_NONBLOCK)
- return -EAGAIN;
-#ifdef DEBUG
- printk("sg_write: sleeping on pending request\n");
-#endif
- interruptible_sleep_on(&device->write_wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- }
-
- /*
- * Mark the device flags for the new state.
- */
- device->pending=1;
- device->complete=0;
- copy_from_user(&device->header,buf,sizeof(struct sg_header));
-
- device->header.pack_len=count;
- buf+=sizeof(struct sg_header);
-
- /*
- * Now we need to grab the command itself from the user's buffer.
- */
- get_user(opcode, buf);
- size=COMMAND_SIZE(opcode);
- if (opcode >= 0xc0 && device->header.twelve_byte) size = 12;
-
- /*
- * Determine buffer size.
- */
- input_size = device->header.pack_len - size;
- if( input_size > device->header.reply_len)
- {
- bsize = input_size;
- } else {
- bsize = device->header.reply_len;
- }
-
- /*
- * Don't include the command header itself in the size.
- */
- bsize-=sizeof(struct sg_header);
- input_size-=sizeof(struct sg_header);
-
- /*
- * Verify that the user has actually passed enough bytes for this command.
- */
- if( input_size < 0 )
- {
- device->pending=0;
- wake_up( &device->write_wait );
- return -EIO;
- }
-
- /*
- * Allocate a buffer that is large enough to hold the data
- * that has been requested. Round up to an even number of sectors,
- * since scsi_malloc allocates in chunks of 512 bytes.
- */
- amt=bsize;
- if (!bsize)
- bsize++;
- bsize=(bsize+511) & ~511;
-
- /*
- * If we cannot allocate the buffer, report an error.
- */
- if ((bsize<0) || !(device->buff=sg_malloc(device->buff_len=bsize)))
- {
- device->pending=0;
- wake_up(&device->write_wait);
- return -ENOMEM;
+ const Sg_device * sdp = sg_dev_arr;
+ int k;
+
+ if (NULL == sg_dev_arr) {
+ printk("sg_debug_all: sg_dev_arr NULL, death is imminent\n");
+ return;
}
-
-#ifdef DEBUG
- printk("allocating device\n");
+ if (! sfp)
+ printk("sg_debug_all: sfp (file descriptor pointer) NULL\n");
+
+ printk("sg_debug_all: dev_max=%d, %s\n",
+ sg_template.dev_max, sg_version_str);
+ printk(" scsi_dma_free_sectors=%u, sg_pool_secs_aval=%d\n",
+ scsi_dma_free_sectors, sg_pool_secs_avail);
+ printk(" sg_big_buff=%d\n", sg_big_buff);
+#ifdef SG_DEBUG
+ printk(" malloc counts, kmallocs=%d, dma_pool=%d, pages=%d\n",
+ sg_num_kmal, sg_num_pool, sg_num_page);
#endif
-
- /*
- * Grab a device pointer for the device we want to talk to. If we
- * don't want to block, just return with the appropriate message.
- */
- if (!(SCpnt=scsi_allocate_device(NULL,device->device, !(filp->f_flags & O_NONBLOCK))))
- {
- device->pending=0;
- wake_up(&device->write_wait);
- sg_free(device->buff,device->buff_len);
- device->buff = NULL;
- return -EAGAIN;
- }
-#ifdef DEBUG
- printk("device allocated\n");
-#endif
-
- SCpnt->request.rq_dev = devt;
- SCpnt->request.rq_status = RQ_ACTIVE;
- SCpnt->sense_buffer[0]=0;
- SCpnt->cmd_len = size;
-
- /*
- * Now copy the SCSI command from the user's address space.
- */
- copy_from_user(cmnd,buf,size);
- buf+=size;
-
- /*
- * If we are writing data, copy the data we are writing. The pack_len
- * field also includes the length of the header and the command,
- * so we need to subtract these off.
- */
- if (input_size > 0) copy_from_user(device->buff, buf, input_size);
-
- /*
- * Set the LUN field in the command structure.
- */
- cmnd[1]= (cmnd[1] & 0x1f) | (device->device->lun<<5);
-
-#ifdef DEBUG
- printk("do cmd\n");
-#endif
-
- /*
- * Now pass the actual command down to the low-level driver. We
- * do not do any more here - when the interrupt arrives, we will
- * then do the post-processing.
- */
- spin_lock_irqsave(&io_request_lock, flags);
- scsi_do_cmd (SCpnt,(void *) cmnd,
- (void *) device->buff,amt,
- sg_command_done,device->timeout,SG_DEFAULT_RETRIES);
- spin_unlock_irqrestore(&io_request_lock, flags);
-
-#ifdef DEBUG
- printk("done cmd\n");
-#endif
-
- return count;
+ for (k = 0; k < sg_template.dev_max; ++k, ++sdp) {
+ if (sdp->headfp) {
+ if (! sfp)
+ sfp = sdp->headfp; /* just to keep things going */
+ else if (sdp == sfp->parentdp)
+ printk(" ***** Invoking device follows *****\n");
+ sg_debug(sdp, sfp, 1);
+ }
+ }
}
-static unsigned int sg_poll(struct file *file, poll_table * wait)
+static void sg_debug(const Sg_device * sdp, const Sg_fd * sfp, int part_of)
{
- int dev = MINOR(file->f_dentry->d_inode->i_rdev);
- struct scsi_generic *device = &scsi_generics[dev];
- unsigned int mask = 0;
+ Sg_fd * fp;
+ Sg_request * srp;
+ int dev;
+ int k;
+
+ if (! sfp)
+ printk("sg_debug: sfp (file descriptor pointer) NULL\n");
+ if (! sdp) {
+ printk("sg_debug: sdp pointer (to device) NULL\n");
+ return;
+ }
+ else if (! sdp->device) {
+ printk("sg_debug: device detached ??\n");
+ return;
+ }
+ dev = MINOR(sdp->i_rdev);
- poll_wait(file, &scsi_generics[dev].read_wait, wait);
- poll_wait(file, &scsi_generics[dev].write_wait, wait);
- if(device->pending && device->complete)
- mask |= POLLIN | POLLRDNORM;
- if(!device->pending)
- mask |= POLLOUT | POLLWRNORM;
+ if (part_of)
+ printk(" >>> device=%d(sg%c), ", dev, 'a' + dev);
+ else
+ printk("sg_debug: device=%d(sg%c), ", dev, 'a' + dev);
+ printk("scsi%d chan=%d id=%d lun=%d em=%d\n", sdp->device->host->host_no,
+ sdp->device->channel, sdp->device->id, sdp->device->lun,
+ sdp->device->host->hostt->emulated);
+ printk(" sg_tablesize=%d, excl=%d, sgdebug=%d, merge_fd=%d\n",
+ sdp->sg_tablesize, sdp->exclude, sdp->sgdebug, sdp->merge_fd);
+ if (! part_of) {
+ printk(" scsi_dma_free_sectors=%u, sg_pool_secs_aval=%d\n",
+ scsi_dma_free_sectors, sg_pool_secs_avail);
+#ifdef SG_DEBUG
+ printk(" mallocs: kmallocs=%d, dma_pool=%d, pages=%d\n",
+ sg_num_kmal, sg_num_pool, sg_num_page);
+#endif
+ }
- return mask;
+ fp = sdp->headfp;
+ for (k = 1; fp; fp = fp->nextfp, ++k) {
+ if (sfp == fp)
+ printk(" *** Following data belongs to invoking FD ***\n");
+ else if (! fp->parentdp)
+ printk(">> Following FD has NULL parent pointer ???\n");
+ printk(" FD(%d): timeout=%d, fb_size=%d, cmd_q=%d\n",
+ k, fp->timeout, fp->fb_size, (int)fp->cmd_q);
+ printk(" low_dma=%d, force_packid=%d, urun_flag=%d, closed=%d\n",
+ (int)fp->low_dma, (int)fp->force_packid,
+ (int)fp->underrun_flag, (int)fp->closed);
+ srp = fp->headrp;
+ if (NULL == srp)
+ printk(" No requests active\n");
+ while (srp) {
+ if (srp->fb_used)
+ printk("using 1st buff >> ");
+ else
+ printk(" ");
+ if (srp->my_cmdp)
+ printk("written: pack_id=%d, bufflen=%d, use_sg=%d\n",
+ srp->header.pack_id, srp->my_cmdp->bufflen,
+ srp->my_cmdp->use_sg);
+ else
+ printk("to_read: pack_id=%d, bufflen=%d, use_sg=%d\n",
+ srp->header.pack_id, srp->data.bufflen, srp->data.use_sg);
+ if (! srp->parentfp)
+ printk(">> request has NULL parent pointer ???\n");
+ srp = srp->nextrp;
+ }
+ }
}
static struct file_operations sg_fops = {
@@ -574,24 +909,30 @@ static struct file_operations sg_fops = {
sg_ioctl, /* ioctl */
NULL, /* mmap */
sg_open, /* open */
- NULL, /* flush */
- sg_close, /* release */
- NULL /* fsync */
+ NULL, /* flush */
+ sg_release, /* release, was formerly sg_close */
+ NULL, /* fsync */
+ sg_fasync, /* fasync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+ NULL, /* lock */
};
-static int sg_detect(Scsi_Device * SDp){
-
- switch (SDp->type) {
- case TYPE_DISK:
- case TYPE_MOD:
- case TYPE_ROM:
- case TYPE_WORM:
- case TYPE_TAPE: break;
- default:
- printk("Detected scsi generic sg%c at scsi%d, channel %d, id %d, lun %d\n",
- 'a'+sg_template.dev_noticed,
- SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
+static int sg_detect(Scsi_Device * scsidp)
+{
+ switch (scsidp->type) {
+ case TYPE_DISK:
+ case TYPE_MOD:
+ case TYPE_ROM:
+ case TYPE_WORM:
+ case TYPE_TAPE: break;
+ default:
+ printk("Detected scsi generic sg%c at scsi%d,"
+ " channel %d, id %d, lun %d\n",
+ 'a'+sg_template.dev_noticed,
+ scsidp->host->host_no, scsidp->channel,
+ scsidp->id, scsidp->lun);
}
sg_template.dev_noticed++;
return 1;
@@ -605,84 +946,108 @@ static int sg_init()
if (sg_template.dev_noticed == 0) return 0;
if(!sg_registered) {
- if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))
- {
- printk("Unable to get major %d for generic SCSI device\n",
- SCSI_GENERIC_MAJOR);
- return 1;
- }
- sg_registered++;
+ if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))
+ {
+ printk("Unable to get major %d for generic SCSI device\n",
+ SCSI_GENERIC_MAJOR);
+ return 1;
+ }
+ sg_registered++;
}
/* If we have already been through here, return */
- if(scsi_generics) return 0;
-
-#ifdef DEBUG
- printk("sg: Init generic device.\n");
-#endif
-
-#ifdef SG_BIG_BUFF
- big_buff= (char *) scsi_init_malloc(SG_BIG_BUFF, GFP_ATOMIC | GFP_DMA);
-#endif
-
- scsi_generics = (struct scsi_generic *)
- scsi_init_malloc((sg_template.dev_noticed + SG_EXTRA_DEVS)
- * sizeof(struct scsi_generic), GFP_ATOMIC);
- memset(scsi_generics, 0, (sg_template.dev_noticed + SG_EXTRA_DEVS)
- * sizeof(struct scsi_generic));
-
+ if(sg_dev_arr) return 0;
+
+ SCSI_LOG_TIMEOUT(3, printk("sg_init\n"));
+ sg_dev_arr = (Sg_device *)
+ scsi_init_malloc((sg_template.dev_noticed + SG_EXTRA_DEVS)
+ * sizeof(Sg_device), GFP_ATOMIC);
+ if (NULL == sg_dev_arr) {
+ printk("sg_init: no space for sg_dev_arr\n");
+ return 1;
+ }
sg_template.dev_max = sg_template.dev_noticed + SG_EXTRA_DEVS;
return 0;
}
-static int sg_attach(Scsi_Device * SDp)
+static int sg_attach(Scsi_Device * scsidp)
{
- struct scsi_generic * gpnt;
- int i;
+ Sg_device * sdp = sg_dev_arr;
+ int k;
- if(sg_template.nr_dev >= sg_template.dev_max)
+ if ((sg_template.nr_dev >= sg_template.dev_max) || (! sdp))
{
- SDp->attached--;
- return 1;
+ scsidp->attached--;
+ return 1;
}
- for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++)
- if(!gpnt->device) break;
+ for(k = 0; k < sg_template.dev_max; k++, sdp++)
+ if(! sdp->device) break;
- if(i >= sg_template.dev_max) panic ("scsi_devices corrupt (sg)");
+ if(k >= sg_template.dev_max) panic ("scsi_devices corrupt (sg)");
- scsi_generics[i].device=SDp;
- scsi_generics[i].users=0;
- scsi_generics[i].generic_wait=NULL;
- scsi_generics[i].read_wait=NULL;
- scsi_generics[i].write_wait=NULL;
- scsi_generics[i].buff=NULL;
- scsi_generics[i].exclude=0;
- scsi_generics[i].pending=0;
- scsi_generics[i].timeout=SG_DEFAULT_TIMEOUT;
+ SCSI_LOG_TIMEOUT(3, printk("sg_attach: dev=%d \n", k));
+ sdp->device = scsidp;
+ sdp->generic_wait = NULL;
+ sdp->headfp= NULL;
+ sdp->exclude = 0;
+ sdp->merge_fd = 0; /* Cope with SG_DEF_MERGE_FD on open */
+ sdp->sgdebug = 0;
+ sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
+ sdp->i_rdev = MKDEV(SCSI_GENERIC_MAJOR, k);
sg_template.nr_dev++;
return 0;
-};
-
-
+}
-static void sg_detach(Scsi_Device * SDp)
+/* Called at 'finish' of init process, after all attaches */
+static void sg_finish(void)
{
- struct scsi_generic * gpnt;
- int i;
+ SCSI_LOG_TIMEOUT(3, printk("sg_finish: dma_free_sectors=%u\n",
+ scsi_dma_free_sectors));
+}
- for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++)
- if(gpnt->device == SDp) {
- gpnt->device = NULL;
- SDp->attached--;
- sg_template.nr_dev--;
- /*
- * avoid associated device /dev/sg? bying incremented
- * each time module is inserted/removed , <dan@lectra.fr>
- */
- sg_template.dev_noticed--;
- return;
- }
+static void sg_detach(Scsi_Device * scsidp)
+{
+ Sg_device * sdp = sg_dev_arr;
+ unsigned long flags = 0;
+ Sg_fd * sfp;
+ Sg_request * srp;
+ int k;
+
+ if (NULL == sdp) return; /* all is not well ... */
+ for (k = 0; k < sg_template.dev_max; k++, sdp++) {
+ if(sdp->device != scsidp)
+ continue; /* dirty but lowers nesting */
+ if (sdp->headfp) {
+/* Need to stop sg_command_done() playing with this list during this loop */
+ spin_lock_irqsave(&io_request_lock, flags);
+ sfp = sdp->headfp;
+ while (sfp) {
+ srp = sfp->headrp;
+ while (srp) {
+ if (srp->my_cmdp)
+ sg_shorten_timeout(srp->my_cmdp);
+ srp = srp->nextrp;
+ }
+ sfp = sfp->nextfp;
+ }
+ spin_unlock_irqrestore(&io_request_lock, flags);
+ SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty, sleep(3)\n", k));
+ scsi_sleep(3); /* sleep 3 jiffies, hoping for timeout to go off */
+ }
+ else {
+ SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k));
+ sdp->device = NULL;
+ }
+ scsidp->attached--;
+ sg_template.nr_dev--;
+ /*
+ * avoid associated device /dev/sg? bying incremented
+ * each time module is inserted/removed , <dan@lectra.fr>
+ */
+ sg_template.dev_noticed--;
+ return;
+ }
return;
}
@@ -698,34 +1063,561 @@ void cleanup_module( void)
scsi_unregister_module(MODULE_SCSI_DEV, &sg_template);
unregister_chrdev(SCSI_GENERIC_MAJOR, "sg");
- if(scsi_generics != NULL) {
- scsi_init_free((char *) scsi_generics,
- (sg_template.dev_noticed + SG_EXTRA_DEVS)
- * sizeof(struct scsi_generic));
+ if(sg_dev_arr != NULL) {
+/* Really worrying situation of writes still pending and get here */
+/* Strategy: shorten timeout on release + wait on detach ... */
+ scsi_init_free((char *) sg_dev_arr,
+ (sg_template.dev_noticed + SG_EXTRA_DEVS)
+ * sizeof(Sg_device));
+ sg_dev_arr = NULL;
}
sg_template.dev_max = 0;
-#ifdef SG_BIG_BUFF
- if(big_buff != NULL)
- scsi_init_free(big_buff, SG_BIG_BUFF);
-#endif
}
#endif /* MODULE */
-/*
- * Overrides for Emacs so that we almost follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
+
+#if 0
+extern void scsi_times_out (Scsi_Cmnd * SCpnt);
+extern void scsi_old_times_out (Scsi_Cmnd * SCpnt);
+#endif
+
+/* Can't see clean way to abort a command so shorten timeout to 1 jiffy */
+static void sg_shorten_timeout(Scsi_Cmnd * scpnt)
+{
+#if 0 /* scsi_syms.c is very miserly about exported functions */
+ scsi_delete_timer(scpnt);
+ if (! scpnt)
+ return;
+ scpnt->timeout_per_command = 1; /* try 1 jiffy (perhaps 0 jiffies) */
+ if (scpnt->host->hostt->use_new_eh_code)
+ scsi_add_timer(scpnt, scpnt->timeout_per_command, scsi_times_out);
+ else
+ scsi_add_timer(scpnt, scpnt->timeout_per_command,
+ scsi_old_times_out);
+#else
+ scsi_sleep(HZ); /* just sleep 1 second and hope ... */
+#endif
+}
+
+static int sg_sc_build(Sg_request * srp, int max_buff_size,
+ const char * inp, int num_write_xfer)
+{
+ int ret_sz, mem_src;
+ int blk_size = max_buff_size;
+ char * p = NULL;
+
+ if ((blk_size < 0) || (! srp))
+ return -EFAULT;
+
+ SCSI_LOG_TIMEOUT(4, printk("sg_sc_build: m_b_s=%d, num_write_xfer=%d\n",
+ max_buff_size, num_write_xfer));
+ if (0 == blk_size)
+ ++blk_size; /* don't know why */
+/* round request up to next highest SG_SECTOR_SZ byte boundary */
+ blk_size = (blk_size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK);
+ SCSI_LOG_TIMEOUT(5, printk("sg_sc_build: blk_size=%d\n", blk_size));
+
+ if (blk_size <= SG_SCATTER_SZ) {
+ mem_src = SG_HEAP_FB;
+ p = sg_malloc(srp, blk_size, &ret_sz, &mem_src);
+ if (! p)
+ return -ENOMEM;
+ if (blk_size == ret_sz) { /* got it on the first attempt */
+ srp->data.buffer = p;
+ srp->data.bufflen = blk_size;
+ srp->data.mem_src = mem_src;
+ srp->data.b_malloc_len = blk_size;
+ if (inp && (num_write_xfer > 0))
+ __copy_from_user(srp->data.buffer, inp, num_write_xfer);
+ return 0;
+ }
+ }
+ else {
+ mem_src = SG_HEAP_PAGE;
+ p = sg_malloc(srp, SG_SCATTER_SZ, &ret_sz, &mem_src);
+ if (! p)
+ return -ENOMEM;
+ }
+/* Want some local declarations, so start new block ... */
+ { /* lets try and build a scatter gather list */
+ struct scatterlist * sclp;
+ int k, rem_sz, num, nxt;
+ int sc_bufflen = PAGE_SIZE;
+ int mx_sc_elems = (sc_bufflen / sizeof(struct scatterlist)) - 1;
+ int sg_tablesize = srp->parentfp->parentdp->sg_tablesize;
+ int first = 1;
+
+ k = SG_HEAP_KMAL; /* want to protect mem_src, use k as scratch */
+ srp->data.buffer = (struct scatterlist *)sg_malloc(srp,
+ sc_bufflen, &num, &k);
+ srp->data.mem_src = (char)k;
+ /* N.B. ret_sz and mem_src carried into this block ... */
+ if (! srp->data.buffer)
+ return -ENOMEM;
+ else if (num != sc_bufflen) {
+ sc_bufflen = num;
+ mx_sc_elems = (sc_bufflen / sizeof(struct scatterlist)) - 1;
+ }
+ srp->data.sglist_len = sc_bufflen;
+ memset(srp->data.buffer, 0, sc_bufflen);
+ for (k = 0, sclp = srp->data.buffer, rem_sz = blk_size, nxt =0;
+ (k < sg_tablesize) && (rem_sz > 0) && (k < mx_sc_elems);
+ ++k, rem_sz -= ret_sz, ++sclp) {
+ if (first)
+ first = 0;
+ else {
+ num = (rem_sz > SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz;
+ mem_src = SG_HEAP_PAGE;
+ p = sg_malloc(srp, num, &ret_sz, &mem_src);
+ if (! p)
+ break;
+ }
+ sclp->address = p;
+ sclp->length = ret_sz;
+ sclp->alt_address = (char *)(long)mem_src;
+
+ if(inp && (num_write_xfer > 0)) {
+ num = (ret_sz > num_write_xfer) ? num_write_xfer : ret_sz;
+ __copy_from_user(sclp->address, inp, num);
+ num_write_xfer -= num;
+ inp += num;
+ }
+ SCSI_LOG_TIMEOUT(5,
+ printk("sg_sc_build: k=%d, a=0x%p, len=%d, ms=%d\n",
+ k, sclp->address, ret_sz, mem_src));
+ } /* end of for loop */
+ srp->data.use_sg = k;
+ SCSI_LOG_TIMEOUT(5,
+ printk("sg_sc_build: use_sg=%d, rem_sz=%d\n", k, rem_sz));
+ srp->data.bufflen = blk_size;
+ if (rem_sz > 0) /* must have failed */
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int sg_sc_undo_rem(Sg_request * srp, char * outp,
+ int num_read_xfer)
+{
+ if (! srp)
+ return -EFAULT;
+ SCSI_LOG_TIMEOUT(4, printk("sg_sc_undo_rem: num_read_xfer=%d\n",
+ num_read_xfer));
+ if (! outp)
+ num_read_xfer = 0;
+ if(srp->data.use_sg) {
+ int k, num, mem_src;
+ struct scatterlist * sclp = (struct scatterlist *)srp->data.buffer;
+
+ for (k = 0; (k < srp->data.use_sg) && sclp->address; ++k, ++sclp) {
+ if (num_read_xfer > 0) {
+ num = (int)sclp->length;
+ if (num > num_read_xfer) {
+ __copy_to_user(outp, sclp->address, num_read_xfer);
+ outp += num_read_xfer;
+ num_read_xfer = 0;
+ }
+ else {
+ __copy_to_user(outp, sclp->address, num);
+ outp += num;
+ num_read_xfer -= num;
+ }
+ }
+ mem_src = (int)(long)sclp->alt_address;
+ SCSI_LOG_TIMEOUT(5,
+ printk("sg_sc_undo_rem: k=%d, a=0x%p, len=%d, ms=%d\n",
+ k, sclp->address, sclp->length, mem_src));
+ sg_free(srp, sclp->address, sclp->length, mem_src);
+ }
+ sg_free(srp, srp->data.buffer, srp->data.sglist_len,
+ srp->data.mem_src);
+ }
+ else {
+ if (num_read_xfer > 0)
+ __copy_to_user(outp, srp->data.buffer, num_read_xfer);
+ sg_free(srp, srp->data.buffer, srp->data.b_malloc_len,
+ srp->data.mem_src);
+ }
+ if (0 == sg_remove_request(srp->parentfp, srp)) {
+ SCSI_LOG_TIMEOUT(1, printk("sg_sc_undo_rem: srp=0x%p not found\n",
+ srp));
+ }
+ return 0;
+}
+
+static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id)
+{
+ Sg_request * resp = NULL;
+
+ resp = sfp->headrp;
+ while (resp) {
+ if ((! resp->my_cmdp) &&
+ ((-1 == pack_id) || (resp->header.pack_id == pack_id)))
+ return resp;
+ resp = resp->nextrp;
+ }
+ return resp;
+}
+
+/* always adds to end of list */
+static Sg_request * sg_add_request(Sg_fd * sfp)
+{
+ int k;
+ Sg_request * resp = NULL;
+ Sg_request * rp;
+
+ resp = sfp->headrp;
+ rp = sfp->req_arr;
+ if (! resp) {
+ resp = rp;
+ sfp->headrp = resp;
+ }
+ else {
+ if (0 == sfp->cmd_q)
+ resp = NULL; /* command queuing disallowed */
+ else {
+ for (k = 0, rp; k < SG_MAX_QUEUE; ++k, ++rp) {
+ if (! rp->parentfp)
+ break;
+ }
+ if (k < SG_MAX_QUEUE) {
+ while (resp->nextrp) resp = resp->nextrp;
+ resp->nextrp = rp;
+ resp = rp;
+ }
+ else
+ resp = NULL;
+ }
+ }
+ if (resp) {
+ resp->parentfp = sfp;
+ resp->nextrp = NULL;
+ resp->fb_used = 0;
+ memset(&resp->data, 0, sizeof(Sg_scatter_hold));
+ memset(&resp->header, 0, sizeof(struct sg_header));
+ resp->my_cmdp = NULL;
+ }
+ return resp;
+}
+
+/* Return of 1 for found; 0 for not found */
+static int sg_remove_request(Sg_fd * sfp, const Sg_request * srp)
+{
+ Sg_request * prev_rp;
+ Sg_request * rp;
+
+ if ((! sfp) || (! srp) || (! sfp->headrp))
+ return 0;
+ prev_rp = sfp->headrp;
+ if (srp == prev_rp) {
+ prev_rp->parentfp = NULL;
+ sfp->headrp = prev_rp->nextrp;
+ return 1;
+ }
+ while ((rp = prev_rp->nextrp)) {
+ if (srp == rp) {
+ rp->parentfp = NULL;
+ prev_rp->nextrp = rp->nextrp;
+ return 1;
+ }
+ prev_rp = rp;
+ }
+ return 0;
+}
+
+static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev, int get_reserved)
+{
+ Sg_fd * sfp;
+
+ if (sdp->merge_fd) {
+ ++sdp->merge_fd;
+ return sdp->headfp;
+ }
+ sfp = (Sg_fd *)sg_low_malloc(sizeof(Sg_fd), 0, SG_HEAP_KMAL, 0);
+ if (sfp) {
+ memset(sfp, 0, sizeof(Sg_fd));
+ sfp->my_mem_src = SG_HEAP_KMAL;
+ }
+ else
+ return NULL;
+
+ sfp->timeout = SG_DEFAULT_TIMEOUT;
+ sfp->force_packid = SG_DEF_FORCE_PACK_ID;
+ sfp->low_dma = (SG_DEF_FORCE_LOW_DMA == 0) ?
+ sdp->device->host->unchecked_isa_dma : 1;
+ sfp->cmd_q = SG_DEF_COMMAND_Q;
+ sfp->underrun_flag = SG_DEF_UNDERRUN_FLAG;
+ if (get_reserved)
+ sfp->fst_buf = sg_low_malloc(SG_SCATTER_SZ, sfp->low_dma,
+ SG_HEAP_PAGE, &sfp->fb_size);
+ else
+ sfp->fst_buf = NULL;
+ if (! sfp->fst_buf)
+ sfp->fb_size = 0;
+ sfp->parentdp = sdp;
+ if (! sdp->headfp)
+ sdp->headfp = sfp;
+ else { /* add to tail of existing list */
+ Sg_fd * pfp = sdp->headfp;
+ while (pfp->nextfp)
+ pfp = pfp->nextfp;
+ pfp->nextfp = sfp;
+ }
+ sg_big_buff = sfp->fb_size; /* show sysctl most recent "fb" size */
+ SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p, m_s=%d\n",
+ sfp, (int)sfp->my_mem_src));
+ SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: fb_sz=%d, fst_buf=0x%p\n",
+ sfp->fb_size, sfp->fst_buf));
+ return sfp;
+}
+
+static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
+{
+ Sg_request * srp;
+ Sg_request * tsrp;
+ int dirty = 0;
+ int res = 0;
+
+ if (sdp->merge_fd) {
+ if (--sdp->merge_fd)
+ return 0; /* if merge_fd then dec merge_fd counter */
+ }
+ srp = sfp->headrp;
+ if (srp) {
+/* Need to stop sg_command_done() playing with this list during this loop */
+ while (srp) {
+ tsrp = srp->nextrp;
+ if (! srp->my_cmdp)
+ sg_sc_undo_rem(srp, NULL, 0);
+ else
+ ++dirty;
+ srp = tsrp;
+ }
+ }
+ if (0 == dirty) {
+ Sg_fd * fp;
+ Sg_fd * prev_fp = sdp->headfp;
+
+ if (sfp == prev_fp)
+ sdp->headfp = prev_fp->nextfp;
+ else {
+ while ((fp = prev_fp->nextfp)) {
+ if (sfp == fp) {
+ prev_fp->nextfp = fp->nextfp;
+ break;
+ }
+ prev_fp = fp;
+ }
+ }
+SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: fb_sz=%d, fst_buf=0x%p\n",
+ sfp->fb_size, sfp->fst_buf));
+ sg_low_free(sfp->fst_buf, sfp->fb_size, SG_HEAP_PAGE);
+ sfp->parentdp = NULL;
+ sfp->fst_buf = NULL;
+ sfp->fb_size = 0;
+ SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: sfp=0x%p\n", sfp));
+ sg_low_free((char *)sfp, sizeof(Sg_fd), sfp->my_mem_src);
+ res = 1;
+ }
+ else {
+ sfp->closed = 1; /* flag dirty state on this fd */
+ SCSI_LOG_TIMEOUT(1, printk(
+ "sg_remove_sfp: worrisome, %d writes pending\n", dirty));
+ }
+ return res;
+}
+
+static int sg_fb_in_use(const Sg_fd * sfp)
+{
+ const Sg_request * srp = sfp->headrp;
+
+ while (srp) {
+ if (srp->fb_used)
+ return 1;
+ srp = srp->nextrp;
+ }
+ return 0;
+}
+
+/* If retSzp==NULL want exact size or fail */
+/* sg_low_malloc() should always be called from a process context allowing
+ GFP_KERNEL to be used instead of GFP_ATOMIC */
+static char * sg_low_malloc(int rqSz, int lowDma, int mem_src, int * retSzp)
+{
+ char * resp = NULL;
+ int page_mask = lowDma ? (GFP_KERNEL | GFP_DMA) : GFP_KERNEL;
+
+ if (rqSz <= 0)
+ return resp;
+ if (SG_HEAP_KMAL == mem_src) {
+ page_mask = lowDma ? (GFP_ATOMIC | GFP_DMA) : GFP_ATOMIC;
+ /* Seen kmalloc(..,GFP_KERNEL) hang for 40 secs! */
+ resp = kmalloc(rqSz, page_mask);
+ if (resp && retSzp) *retSzp = rqSz;
+#ifdef SG_DEBUG
+ if (resp) ++sg_num_kmal;
+#endif
+ return resp;
+ }
+ if (SG_HEAP_POOL == mem_src) {
+ int num_sect = rqSz / SG_SECTOR_SZ;
+
+ if (0 != (rqSz & SG_SECTOR_MSK)) {
+ if (! retSzp)
+ return resp;
+ ++num_sect;
+ rqSz = num_sect * SG_SECTOR_SZ;
+ }
+ while (num_sect > 0) {
+ if ((num_sect <= sg_pool_secs_avail) &&
+ (scsi_dma_free_sectors > (SG_LOW_POOL_THRESHHOLD + num_sect))) {
+ resp = scsi_malloc(rqSz);
+ if (resp) {
+ if (retSzp) *retSzp = rqSz;
+ sg_pool_secs_avail -= num_sect;
+#ifdef SG_DEBUG
+ ++sg_num_pool;
+#endif
+ return resp;
+ }
+ }
+ if (! retSzp)
+ return resp;
+ num_sect /= 2; /* try half as many */
+ rqSz = num_sect * SG_SECTOR_SZ;
+ }
+ }
+ else if (SG_HEAP_PAGE == mem_src) {
+ int order, a_size;
+ int resSz = rqSz;
+
+ for (order = 0, a_size = PAGE_SIZE;
+ a_size < rqSz; order++, a_size <<= 1)
+ ;
+ resp = (char *)__get_free_pages(page_mask, order);
+ while ((! resp) && order && retSzp) {
+ --order;
+ a_size >>= 1; /* divide by 2, until PAGE_SIZE */
+ resp = (char *)__get_free_pages(page_mask, order); /* try half */
+ resSz = a_size;
+ }
+ if (retSzp) *retSzp = resSz;
+#ifdef SG_DEBUG
+ if (resp) ++sg_num_page;
+#endif
+ }
+ else
+ printk("sg_low_malloc: bad mem_src=%d, rqSz=%df\n", mem_src, rqSz);
+ return resp;
+}
+
+static char * sg_malloc(Sg_request * srp, int size, int * retSzp,
+ int * mem_srcp)
+{
+ char * resp = NULL;
+
+ if (retSzp) *retSzp = size;
+ if (size <= 0)
+ ;
+ else {
+ Sg_fd * sfp = srp->parentfp;
+ int low_dma = sfp->low_dma;
+ int l_ms = -1; /* invalid value */
+
+ switch (*mem_srcp)
+ {
+ case SG_HEAP_PAGE:
+ case SG_HEAP_FB:
+ l_ms = (size < PAGE_SIZE) ? SG_HEAP_POOL : SG_HEAP_PAGE;
+ resp = sg_low_malloc(size, low_dma, l_ms, 0);
+ if (resp)
+ break;
+ if ((size <= sfp->fb_size) && (0 == sg_fb_in_use(sfp))) {
+ SCSI_LOG_TIMEOUT(6,
+ printk("sg_malloc: scsi_malloc failed, get fst_buf\n"));
+ resp = sfp->fst_buf;
+ srp->fb_used = 1;
+ l_ms = SG_HEAP_FB;
+ break;
+ }
+ resp = sg_low_malloc(size, low_dma, l_ms, &size);
+ if (! resp) {
+ l_ms = (SG_HEAP_POOL == l_ms) ? SG_HEAP_PAGE : SG_HEAP_POOL;
+ resp = sg_low_malloc(size, low_dma, l_ms, &size);
+ if (! resp) {
+ l_ms = SG_HEAP_KMAL;
+ resp = sg_low_malloc(size, low_dma, l_ms, &size);
+ }
+ }
+ if (resp && retSzp) *retSzp = size;
+ break;
+ case SG_HEAP_KMAL:
+ l_ms = SG_HEAP_PAGE;
+ resp = sg_low_malloc(size, low_dma, l_ms, 0);
+ if (resp)
+ break;
+ l_ms = SG_HEAP_POOL;
+ resp = sg_low_malloc(size, low_dma, l_ms, &size);
+ if (resp && retSzp) *retSzp = size;
+ break;
+ default:
+ SCSI_LOG_TIMEOUT(1, printk("sg_malloc: bad ms=%d\n", *mem_srcp));
+ break;
+ }
+ if (resp) *mem_srcp = l_ms;
+ }
+ SCSI_LOG_TIMEOUT(6, printk("sg_malloc: size=%d, ms=%d, ret=0x%p\n",
+ size, *mem_srcp, resp));
+ return resp;
+}
+
+static void sg_low_free(char * buff, int size, int mem_src)
+{
+ if (! buff)
+ return;
+ if (SG_HEAP_POOL == mem_src) {
+ int num_sect = size / SG_SECTOR_SZ;
+ scsi_free(buff, size);
+ sg_pool_secs_avail += num_sect;
+ }
+ else if (SG_HEAP_KMAL == mem_src)
+ kfree(buff); /* size not used */
+ else if (SG_HEAP_PAGE == mem_src) {
+ int order, a_size;
+
+ for (order = 0, a_size = PAGE_SIZE;
+ a_size < size; order++, a_size <<= 1)
+ ;
+ free_pages((unsigned long)buff, order);
+ }
+ else
+ printk("sg_low_free: bad mem_src=%d, buff=0x%p, rqSz=%df\n",
+ mem_src, buff, size);
+}
+
+static void sg_free(Sg_request * srp, char * buff, int size, int mem_src)
+{
+ Sg_fd * sfp = srp->parentfp;
+
+ SCSI_LOG_TIMEOUT(6,
+ printk("sg_free: buff=0x%p, size=%d\n", buff, size));
+ if ((! sfp) || (! buff) || (size <= 0))
+ ;
+ else if (sfp->fst_buf == buff) {
+ srp->fb_used = 0;
+ SCSI_LOG_TIMEOUT(6, printk("sg_free: left cause fst_buf\n"));
+ }
+ else
+ sg_low_free(buff, size, mem_src);
+}
+
+static void sg_clr_scpnt(Scsi_Cmnd * SCpnt)
+{
+ SCpnt->use_sg = 0;
+ SCpnt->sglist_len = 0;
+ SCpnt->bufflen = 0;
+ SCpnt->buffer = NULL;
+ SCpnt->underflow = 0;
+ SCpnt->request.rq_dev = MKDEV(0, 0); /* "sg" _disowns_ command blk */
+}
+
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 2eaad47d8..b01ab7f1c 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -82,7 +82,8 @@ retry:
switch(SCpnt->sense_buffer[2] & 0xf) {
case UNIT_ATTENTION:
scsi_CDs[target].device->changed = 1;
- printk(KERN_INFO "sr%d: disc change detected.\n", target);
+ if (!quiet)
+ printk(KERN_INFO "sr%d: disc change detected.\n", target);
if (retries++ < 10)
goto retry;
err = -ENOMEDIUM;
@@ -105,12 +106,13 @@ retry:
spin_unlock_irqrestore(&io_request_lock, flags);
goto retry;
} else {
- /* 20 secs are enouth? */
+ /* 20 secs are enough? */
err = -ENOMEDIUM;
break;
}
}
- printk(KERN_INFO "sr%d: CDROM not ready. Make sure there is a disc in the drive.\n",target);
+ if (!quiet)
+ printk(KERN_INFO "sr%d: CDROM not ready. Make sure there is a disc in the drive.\n",target);
#ifdef DEBUG
print_sense("sr", SCpnt);
#endif
@@ -120,9 +122,11 @@ retry:
if (!quiet)
printk(KERN_ERR "sr%d: CDROM (ioctl) reports ILLEGAL "
"REQUEST.\n", target);
- if (SCpnt->sense_buffer[12] == 0x20 &&
+ if ((SCpnt->sense_buffer[12] == 0x20 ||
+ SCpnt->sense_buffer[12] == 0x24) &&
SCpnt->sense_buffer[13] == 0x00) {
/* sense: Invalid command operation code */
+ /* or Invalid field in cdb */
err = -EDRIVE_CANT_DO_THIS;
} else {
err = -EINVAL;
@@ -408,7 +412,7 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void* arg)
spin_unlock_irqrestore(&io_request_lock, flags);
if(!buffer) return -ENOMEM;
- result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0);
+ result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1);
tochdr->cdth_trk0 = buffer[2];
tochdr->cdth_trk1 = buffer[3];
@@ -872,6 +876,11 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
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 --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index ebebcc777..75bec4a43 100644
--- a/drivers/scsi/sr_vendor.c
+++ b/drivers/scsi/sr_vendor.c
@@ -175,7 +175,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
cmd[1] = (scsi_CDs[minor].device->lun << 5);
cmd[8] = 12;
cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 12, 0);
+ rc = sr_do_ioctl(minor, cmd, buffer, 12, 1);
if (rc != 0)
break;
if ((buffer[0] << 8) + buffer[1] < 0x0a) {
@@ -199,7 +199,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
cmd[0] = 0xde;
cmd[1] = (scsi_CDs[minor].device->lun << 5) | 0x03;
cmd[2] = 0xb0;
- rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 0);
+ rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 1);
if (rc != 0)
break;
if (buffer[14] != 0 && buffer[14] != 0xb0) {
@@ -223,7 +223,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
memset(cmd,0,12);
cmd[0] = 0xc7;
cmd[1] = (scsi_CDs[minor].device->lun << 5) | 3;
- rc = sr_do_ioctl(minor, cmd, buffer, 4, 0);
+ rc = sr_do_ioctl(minor, cmd, buffer, 4, 1);
if (rc == -EINVAL) {
printk(KERN_INFO "sr%d: Hmm, seems the drive "
"doesn't support multisession CD's\n",minor);
@@ -248,7 +248,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
cmd[1] = (scsi_CDs[minor].device->lun << 5);
cmd[8] = 0x04;
cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 0);
+ rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 1);
if (rc != 0) {
break;
}
@@ -263,7 +263,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
cmd[6] = rc & 0x7f; /* number of last session */
cmd[8] = 0x0c;
cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 12, 0);
+ rc = sr_do_ioctl(minor, cmd, buffer, 12, 1);
if (rc != 0) {
break;
}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 8ffabde7e..c53e2e790 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -8,10 +8,10 @@
order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
- Copyright 1992 - 1998 Kai Makisara
+ Copyright 1992 - 1999 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Thu Dec 3 20:27:46 1998 by makisara@home
+ Last modified: Sun Mar 7 09:03:17 1999 by makisara@home
Some small formal changes - aeb, 950809
*/
@@ -1094,8 +1094,11 @@ st_write(struct file * filp, const char * buf, size_t count, loff_t *ppos)
#endif
/* Write must be integral number of blocks */
- if (STp->block_size != 0 && (count % STp->block_size) != 0)
+ if (STp->block_size != 0 && (count % STp->block_size) != 0) {
+ printk(KERN_WARNING "st%d: Write not multiple of tape block size.\n",
+ dev);
return (-EIO);
+ }
if (STp->can_partitions &&
(retval = update_partition(inode)) < 0)
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
new file mode 100644
index 000000000..166a66df2
--- /dev/null
+++ b/drivers/scsi/sym53c416.c
@@ -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=<PORTBASE>[,<IRQ>]
+ *
+ * This program is free software; you can redistribute 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <asm/dma.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <linux/blk.h>
+#include <linux/version.h>
+#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=<base>[,<irq>]\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 --git a/drivers/scsi/sym53c416.h b/drivers/scsi/sym53c416.h
new file mode 100644
index 000000000..49abc83ca
--- /dev/null
+++ b/drivers/scsi/sym53c416.h
@@ -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 <linux/version.h>
+#endif
+
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+
+#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 --git a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c
new file mode 100644
index 000000000..7ad601b1a
--- /dev/null
+++ b/drivers/scsi/sym53c8xx.c
@@ -0,0 +1,11768 @@
+/******************************************************************************
+** High Performance device driver for the Symbios 53C896 controller.
+**
+** Copyright (C) 1998 Gerard Roudier <groudier@club-internet.fr>
+**
+** This driver also supports all the Symbios 53C8XX controller family,
+** except 53C810 revisions < 16, 53C825 revisions < 16 and all
+** revisions of 53C815 controllers.
+**
+** This driver is based on the Linux port of the FreeBSD ncr driver.
+**
+** Copyright (C) 1994 Wolfgang Stanglmeier
+**
+**-----------------------------------------------------------------------------
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**-----------------------------------------------------------------------------
+**
+** The Linux port of the FreeBSD ncr driver has been achieved in
+** november 1995 by:
+**
+** Gerard Roudier <groudier@club-internet.fr>
+**
+** Being given that this driver originates from the FreeBSD version, and
+** in order to keep synergy on both, any suggested enhancements and corrections
+** received on Linux are automatically a potential candidate for the FreeBSD
+** version.
+**
+** The original driver has been written for 386bsd and FreeBSD by
+** Wolfgang Stanglmeier <wolf@cologne.de>
+** Stefan Esser <se@mi.Uni-Koeln.de>
+**
+**-----------------------------------------------------------------------------
+**
+** Major contributions:
+** --------------------
+**
+** NVRAM detection and reading.
+** Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
+**
+*******************************************************************************
+*/
+
+/*
+** April 2 1999, sym53c8xx version 1.3c
+**
+** Supported SCSI features:
+** Synchronous data transfers
+** Wide16 SCSI BUS
+** Disconnection/Reselection
+** Tagged command queuing
+** SCSI Parity checking
+**
+** Supported NCR chips:
+** 53C810A (8 bits, Fast 10, no rom BIOS)
+** 53C825A (Wide, Fast 10, on-board rom BIOS)
+** 53C860 (8 bits, Fast 20, no rom BIOS)
+** 53C875 (Wide, Fast 20, on-board rom BIOS)
+** 53C876 (Wide, Fast 20 Dual, on-board rom BIOS)
+** 53C895 (Wide, Fast 40, on-board rom BIOS)
+** 53C896 (Wide, Fast 40 Dual, on-board rom BIOS)
+**
+** Other features:
+** Memory mapped IO
+** Module
+** Shared IRQ
+*/
+
+/*
+** Name and version of the driver
+*/
+#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.3c"
+
+/* #define DEBUG_896R1 */
+#define SCSI_NCR_OPTIMIZE_896
+/* #define SCSI_NCR_OPTIMIZE_896_1 */
+
+#define SCSI_NCR_DEBUG_FLAGS (0)
+
+#define NAME53C "sym53c"
+#define NAME53C8XX "sym53c8xx"
+
+/*==========================================================
+**
+** Include files
+**
+**==========================================================
+*/
+
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)
+#include <asm/spinlock.h>
+#endif
+#include <linux/delay.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <linux/stat.h>
+
+#include <linux/version.h>
+#include <linux/blk.h>
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,35)
+#include <linux/init.h>
+#else
+#ifndef __initdata
+#define __initdata
+#endif
+#ifndef __initfunc
+#define __initfunc(__arginit) __arginit
+#endif
+#endif
+
+#if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92)
+#include <linux/bios32.h>
+#endif
+
+#include "scsi.h"
+#include "hosts.h"
+#include "constants.h"
+#include "sd.h"
+
+#include <linux/types.h>
+
+/*
+** Define BITS_PER_LONG for earlier linux versions.
+*/
+#ifndef BITS_PER_LONG
+#if (~0UL) == 0xffffffffUL
+#define BITS_PER_LONG 32
+#else
+#define BITS_PER_LONG 64
+#endif
+#endif
+
+/*
+** Define the BSD style u_int32 and u_int64 type.
+** Are in fact u_int32_t and u_int64_t :-)
+*/
+typedef u32 u_int32;
+typedef u64 u_int64;
+
+#include "sym53c8xx.h"
+
+/*==========================================================
+**
+** A la VMS/CAM-3 queue management.
+** Implemented from linux list management.
+**
+**==========================================================
+*/
+
+typedef struct xpt_quehead {
+ struct xpt_quehead *flink; /* Forward pointer */
+ struct xpt_quehead *blink; /* Backward pointer */
+} XPT_QUEHEAD;
+
+#define xpt_que_init(ptr) do { \
+ (ptr)->flink = (ptr); (ptr)->blink = (ptr); \
+} while (0)
+
+static inline void __xpt_que_add(struct xpt_quehead * new,
+ struct xpt_quehead * blink,
+ struct xpt_quehead * flink)
+{
+ flink->blink = new;
+ new->flink = flink;
+ new->blink = blink;
+ blink->flink = new;
+}
+
+static inline void __xpt_que_del(struct xpt_quehead * blink,
+ struct xpt_quehead * flink)
+{
+ flink->blink = blink;
+ blink->flink = flink;
+}
+
+static inline int xpt_que_empty(struct xpt_quehead *head)
+{
+ return head->flink == head;
+}
+
+static inline void xpt_que_splice(struct xpt_quehead *list,
+ struct xpt_quehead *head)
+{
+ struct xpt_quehead *first = list->flink;
+
+ if (first != list) {
+ struct xpt_quehead *last = list->blink;
+ struct xpt_quehead *at = head->flink;
+
+ first->blink = head;
+ head->flink = first;
+
+ last->flink = at;
+ at->blink = last;
+ }
+}
+
+#define xpt_que_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+
+#define xpt_insque(new, pos) __xpt_que_add(new, pos, (pos)->flink)
+
+#define xpt_remque(el) __xpt_que_del((el)->blink, (el)->flink)
+
+#define xpt_insque_head(new, head) __xpt_que_add(new, head, (head)->flink)
+
+static inline struct xpt_quehead *xpt_remque_head(struct xpt_quehead *head)
+{
+ struct xpt_quehead *elem = head->flink;
+
+ if (elem != head)
+ __xpt_que_del(head, elem->flink);
+ else
+ elem = 0;
+ return elem;
+}
+
+#define xpt_insque_tail(new, head) __xpt_que_add(new, (head)->blink, head)
+
+static inline struct xpt_quehead *xpt_remque_tail(struct xpt_quehead *head)
+{
+ struct xpt_quehead *elem = head->blink;
+
+ if (elem != head)
+ __xpt_que_del(elem->blink, head);
+ else
+ elem = 0;
+ return elem;
+}
+
+/*==========================================================
+**
+** On x86 architecture, write buffers management does
+** not reorder writes to memory. So, using compiler
+** optimization barriers is enough to guarantee some
+** ordering when the CPU is writing data accessed by
+** the NCR.
+** On Alpha architecture, explicit memory barriers have
+** to be used.
+** Other architectures are defaulted to mb() macro if
+** defined, otherwise use compiler barrier.
+**
+**==========================================================
+*/
+
+#if defined(__i386__)
+#define MEMORY_BARRIER() barrier()
+#elif defined(__alpha__)
+#define MEMORY_BARRIER() mb()
+#else
+# ifdef mb
+# define MEMORY_BARRIER() mb()
+# else
+# define MEMORY_BARRIER() barrier()
+# endif
+#endif
+
+/*==========================================================
+**
+** Configuration and Debugging
+**
+**==========================================================
+*/
+
+/*
+** SCSI address of this device.
+** The boot routines should have set it.
+** If not, use this.
+*/
+
+#ifndef SCSI_NCR_MYADDR
+#define SCSI_NCR_MYADDR (7)
+#endif
+
+/*
+** The maximum number of tags per logic unit.
+** Used only for devices that support tags.
+*/
+
+#ifndef SCSI_NCR_MAX_TAGS
+#define SCSI_NCR_MAX_TAGS (8)
+#endif
+
+/*
+** TAGS are actually limited to 64 tags/lun.
+** We need to deal with power of 2, for alignment constraints.
+*/
+#if SCSI_NCR_MAX_TAGS > 64
+#undef SCSI_NCR_MAX_TAGS
+#define SCSI_NCR_MAX_TAGS (64)
+#endif
+
+#define NO_TAG (255)
+
+/*
+** Choose appropriate type for tag bitmap.
+*/
+#if SCSI_NCR_MAX_TAGS > 32
+typedef u_int64 tagmap_t;
+#else
+typedef u_int32 tagmap_t;
+#endif
+
+/*
+** Number of targets supported by the driver.
+** n permits target numbers 0..n-1.
+** Default is 16, meaning targets #0..#15.
+** #7 .. is myself.
+*/
+
+#ifdef SCSI_NCR_MAX_TARGET
+#define MAX_TARGET (SCSI_NCR_MAX_TARGET)
+#else
+#define MAX_TARGET (16)
+#endif
+
+/*
+** Number of logic units supported by the driver.
+** n enables logic unit numbers 0..n-1.
+** The common SCSI devices require only
+** one lun, so take 1 as the default.
+*/
+
+#ifdef SCSI_NCR_MAX_LUN
+#define MAX_LUN SCSI_NCR_MAX_LUN
+#else
+#define MAX_LUN (1)
+#endif
+
+/*
+** Asynchronous pre-scaler (ns). Shall be 40 for
+** the SCSI timings to be compliant.
+*/
+
+#ifndef SCSI_NCR_MIN_ASYNC
+#define SCSI_NCR_MIN_ASYNC (40)
+#endif
+
+/*
+** The maximum number of jobs scheduled for starting.
+** We allocate 4 entries more than the value we announce
+** to the SCSI upper layer. Guess why ! :-)
+*/
+
+#ifdef SCSI_NCR_CAN_QUEUE
+#define MAX_START (SCSI_NCR_CAN_QUEUE + 4)
+#else
+#define MAX_START (MAX_TARGET + 7 * SCSI_NCR_MAX_TAGS)
+#endif
+
+/*
+** The maximum number of segments a transfer is split into.
+** We support up to 127 segments for both read and write.
+** Since we try to avoid phase mismatches by testing the PHASE
+** before each MOV, the both DATA_IN and DATA_OUT scripts do
+** not fit in the 4K on-chip RAM. For this reason, the data
+** scripts are broken into 2 sub-scripts.
+** 80 (MAX_SCATTERL) segments are moved from a sub-script
+** in on-chip RAM. This makes data transfers shorter than
+** 80k (assuming 1k fs) as fast as possible.
+** The 896 allows to handle phase mismatches from SCRIPTS.
+** So, for this chip, we use a simple array of MOV's.
+** Perhaps, using a simple array of MOV's and going with
+** the phase mismatch interrupt is also the best solution
+** for the 895 in Ultra2-mode, since the PHASE test + MOV
+** latency may be enough to fill the SCSI offset for very
+** fast disks like the Cheatah Wide LVD and so, may waste
+** SCSI BUS bandwitch.
+*/
+
+#define MAX_SCATTER (SCSI_NCR_MAX_SCATTER)
+
+#ifdef SCSI_NCR_OPTIMIZE_896
+#define SCR_SG_SIZE (2)
+#define MAX_SCATTERL MAX_SCATTER
+#define MAX_SCATTERH 0
+#else
+#if (MAX_SCATTER > 80)
+#define SCR_SG_SIZE (4)
+#define MAX_SCATTERL 80
+#define MAX_SCATTERH (MAX_SCATTER - MAX_SCATTERL)
+#else
+#define MAX_SCATTERL MAX_SCATTER
+#define MAX_SCATTERH 0
+#endif
+#endif /* SCSI_NCR_OPTIMIZE_896 */
+
+/*
+** Io mapped or memory mapped.
+*/
+
+#if defined(SCSI_NCR_IOMAPPED)
+#define NCR_IOMAPPED
+#endif
+
+/*
+** other
+*/
+
+#define NCR_SNOOP_TIMEOUT (1000000)
+
+/*==========================================================
+**
+** Miscallaneous BSDish defines.
+**
+**==========================================================
+*/
+
+#define u_char unsigned char
+#define u_short unsigned short
+#define u_int unsigned int
+#define u_long unsigned long
+
+#ifndef bcopy
+#define bcopy(s, d, n) memcpy((d), (s), (n))
+#endif
+
+#ifndef bzero
+#define bzero(d, n) memset((d), 0, (n))
+#endif
+
+#ifndef offsetof
+#define offsetof(t, m) ((size_t) (&((t *)0)->m))
+#endif
+
+/*==========================================================
+**
+** Debugging tags
+**
+**==========================================================
+*/
+
+#define DEBUG_ALLOC (0x0001)
+#define DEBUG_PHASE (0x0002)
+#define DEBUG_POLL (0x0004)
+#define DEBUG_QUEUE (0x0008)
+#define DEBUG_RESULT (0x0010)
+#define DEBUG_SCATTER (0x0020)
+#define DEBUG_SCRIPT (0x0040)
+#define DEBUG_TINY (0x0080)
+#define DEBUG_TIMING (0x0100)
+#define DEBUG_NEGO (0x0200)
+#define DEBUG_TAGS (0x0400)
+#define DEBUG_FREEZE (0x0800)
+#define DEBUG_RESTART (0x1000)
+
+/*
+** Enable/Disable debug messages.
+** Can be changed at runtime too.
+*/
+
+#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
+static int ncr_debug = SCSI_NCR_DEBUG_FLAGS;
+ #define DEBUG_FLAGS ncr_debug
+#else
+ #define DEBUG_FLAGS SCSI_NCR_DEBUG_FLAGS
+#endif
+
+/*
+** SMP threading.
+**
+** Assuming that SMP systems are generally high end systems and may
+** use several SCSI adapters, we are using one lock per controller
+** instead of some global one. For the moment (linux-2.1.95), driver's
+** entry points are called with the 'io_request_lock' lock held, so:
+** - We are uselessly loosing a couple of micro-seconds to lock the
+** controller data structure.
+** - But the driver is not broken by design for SMP and so can be
+** more resistant to bugs or bad changes in the IO sub-system code.
+** - A small advantage could be that the interrupt code is grained as
+** wished (e.g.: threaded by controller).
+*/
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)
+
+spinlock_t sym53c8xx_lock;
+#define NCR_LOCK_DRIVER(flags) spin_lock_irqsave(&sym53c8xx_lock, flags)
+#define NCR_UNLOCK_DRIVER(flags) spin_unlock_irqrestore(&sym53c8xx_lock,flags)
+
+#define NCR_INIT_LOCK_NCB(np) spin_lock_init(&np->smp_lock);
+#define NCR_LOCK_NCB(np, flags) spin_lock_irqsave(&np->smp_lock, flags)
+#define NCR_UNLOCK_NCB(np, flags) spin_unlock_irqrestore(&np->smp_lock, flags)
+
+# if LINUX_VERSION_CODE < LinuxVersionCode(2,3,99)
+
+# define NCR_LOCK_SCSI_DONE(np, flags) \
+ spin_lock_irqsave(&io_request_lock, flags)
+# define NCR_UNLOCK_SCSI_DONE(np, flags) \
+ spin_unlock_irqrestore(&io_request_lock, flags)
+
+# else
+
+# define NCR_LOCK_SCSI_DONE(np, flags) do {;} while (0)
+# define NCR_UNLOCK_SCSI_DONE(np, flags) do {;} while (0)
+
+# endif
+
+#else
+
+#define NCR_LOCK_DRIVER(flags) do { save_flags(flags); cli(); } while (0)
+#define NCR_UNLOCK_DRIVER(flags) do { restore_flags(flags); } while (0)
+
+#define NCR_INIT_LOCK_NCB(np) do { } while (0)
+#define NCR_LOCK_NCB(np, flags) do { save_flags(flags); cli(); } while (0)
+#define NCR_UNLOCK_NCB(np, flags) do { restore_flags(flags); } while (0)
+
+#define NCR_LOCK_SCSI_DONE(np, flags) do {;} while (0)
+#define NCR_UNLOCK_SCSI_DONE(np, flags) do {;} while (0)
+
+#endif
+
+/*
+** Address translation
+**
+** The driver has to provide bus memory addresses to
+** the script processor. Because some architectures use
+** different physical addressing scheme from the PCI BUS,
+** we use virt_to_bus() instead of virt_to_phys().
+*/
+
+#define vtobus(p) virt_to_bus(p)
+
+/*
+** Memory mapped IO
+**
+** Since linux-2.1, we must use ioremap() to map the io memory space.
+** iounmap() to unmap it. That allows portability.
+** Linux 1.3.X and 2.0.X allow to remap physical pages addresses greater
+** than the highest physical memory address to kernel virtual pages with
+** vremap() / vfree(). That was not portable but worked with i386
+** architecture.
+*/
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0)
+#define ioremap vremap
+#define iounmap vfree
+#endif
+
+#ifdef __sparc__
+#define remap_pci_mem(base, size) ((u_long) __va(base))
+#define unmap_pci_mem(vaddr, size)
+#define pcivtobus(p) ((p) & pci_dvma_mask)
+#else /* __sparc__ */
+#define pcivtobus(p) (p)
+
+#if !defined(NCR_IOMAPPED) || defined(__i386__)
+__initfunc(
+static u_long remap_pci_mem(u_long base, u_long size)
+)
+{
+ u_long page_base = ((u_long) base) & PAGE_MASK;
+ u_long page_offs = ((u_long) base) - page_base;
+ u_long page_remapped = (u_long) ioremap(page_base, page_offs+size);
+
+ return page_remapped? (page_remapped + page_offs) : 0UL;
+}
+
+__initfunc(
+static void unmap_pci_mem(u_long vaddr, u_long size)
+)
+{
+ if (vaddr)
+ iounmap((void *) (vaddr & PAGE_MASK));
+}
+#endif /* !NCR_IOMAPPED || __i386__ */
+#endif /* __sparc__ */
+
+/*
+** Insert a delay in micro-seconds and milli-seconds.
+** -------------------------------------------------
+** Under Linux, udelay() is restricted to delay < 1 milli-second.
+** In fact, it generally works for up to 1 second delay.
+** Since 2.1.105, the mdelay() function is provided for delays
+** in milli-seconds.
+** Under 2.0 kernels, udelay() is an inline function that is very
+** inaccurate on Pentium processors.
+*/
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,105)
+#define UDELAY udelay
+#define MDELAY mdelay
+#else
+static void UDELAY(long us) { udelay(us); }
+static void MDELAY(long ms) { while (ms--) UDELAY(1000); }
+#endif
+
+/*
+** Simple power of two buddy-like allocator
+** ----------------------------------------
+** This simple code is not intended to be fast, but to provide
+** power of 2 aligned memory allocations.
+** Since the SCRIPTS processor only supplies 8 bit arithmetic,
+** this allocator allows simple and fast address calculations
+** from the SCRIPTS code. In addition, cache line alignment
+** is guaranteed for power of 2 cache line size.
+*/
+
+#define MEMO_SHIFT 4 /* 16 bytes minimum memory chunk */
+#define MEMO_PAGE_ORDER 0 /* 1 PAGE maximum (for now (ever?) */
+typedef unsigned long addr; /* Enough bits to bit-hack addresses */
+
+#define MEMO_FREE_UNUSED /* Free unused pages immediately */
+
+struct m_link {
+ struct m_link *next; /* Simple links are enough */
+};
+
+#ifndef GFP_DMA_32BIT
+#define GFP_DMA_32BIT 0 /* Will this flag ever exist */
+#endif
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0)
+#define get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order)
+#else
+#define get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order, 0)
+#endif
+
+/*
+** Lists of available memory chunks.
+** Starts with 16 bytes chunks until 1 PAGE chunks.
+*/
+static struct m_link h[PAGE_SHIFT-MEMO_SHIFT+MEMO_PAGE_ORDER+1];
+
+/*
+** Allocate a memory area aligned on the lowest power of 2
+** greater than the requested size.
+*/
+static void *__m_alloc(int size)
+{
+ int i = 0;
+ int s = (1 << MEMO_SHIFT);
+ int j;
+ addr a ;
+
+ if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
+ return 0;
+
+ while (size > s) {
+ s <<= 1;
+ ++i;
+ }
+
+ j = i;
+ while (!h[j].next) {
+ if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
+ h[j].next = (struct m_link *)get_pages(MEMO_PAGE_ORDER);
+ if (h[j].next)
+ h[j].next->next = 0;
+ break;
+ }
+ ++j;
+ s <<= 1;
+ }
+ a = (addr) h[j].next;
+ if (a) {
+ h[j].next = h[j].next->next;
+ while (j > i) {
+ j -= 1;
+ s >>= 1;
+ h[j].next = (struct m_link *) (a+s);
+ h[j].next->next = 0;
+ }
+ }
+#ifdef DEBUG
+ printk("m_alloc(%d) = %p\n", size, (void *) a);
+#endif
+ return (void *) a;
+}
+
+/*
+** Free a memory area allocated using m_alloc().
+** Coalesce buddies.
+** Free pages that become unused if MEMO_FREE_UNUSED is defined.
+*/
+static void __m_free(void *ptr, int size)
+{
+ int i = 0;
+ int s = (1 << MEMO_SHIFT);
+ struct m_link *q;
+ addr a, b;
+
+#ifdef DEBUG
+ printk("m_free(%p, %d)\n", ptr, size);
+#endif
+
+ if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
+ return;
+
+ while (size > s) {
+ s <<= 1;
+ ++i;
+ }
+
+ a = (addr) ptr;
+
+ while (1) {
+#ifdef MEMO_FREE_UNUSED
+ if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
+ free_pages(a, MEMO_PAGE_ORDER);
+ break;
+ }
+#endif
+ b = a ^ s;
+ q = &h[i];
+ while (q->next && q->next != (struct m_link *) b) {
+ q = q->next;
+ }
+ if (!q->next) {
+ ((struct m_link *) a)->next = h[i].next;
+ h[i].next = (struct m_link *) a;
+ break;
+ }
+ q->next = q->next->next;
+ a = a & b;
+ s <<= 1;
+ ++i;
+ }
+}
+
+#define MEMO_WARN 1
+
+/*
+** The memory pool is shared by all instances.
+** We use a global SMP LOCK to be SMP safe.
+*/
+
+static void *m_calloc(int size, char *name, int uflags)
+{
+ u_long flags;
+ void *p;
+
+ NCR_LOCK_DRIVER(flags);
+ p = __m_alloc(size);
+ NCR_UNLOCK_DRIVER(flags);
+
+ if (DEBUG_FLAGS & DEBUG_ALLOC)
+ printk ("new %s[%d] @%p.\n", name, size, p);
+
+ if (p)
+ memset(p, 0, size);
+ else if (uflags & MEMO_WARN)
+ printk (NAME53C8XX ": failed to allocate %s[%d]\n", name, size);
+
+ return p;
+}
+
+static void m_free(void *ptr, int size, char *name)
+{
+ u_long flags;
+
+ if (DEBUG_FLAGS & DEBUG_ALLOC)
+ printk ("freeing %s[%d] @%p.\n", name, size, ptr);
+
+ NCR_LOCK_DRIVER(flags);
+ __m_free(ptr, size);
+ NCR_UNLOCK_DRIVER(flags);
+}
+
+/*
+** Transfer direction
+**
+** Low-level scsi drivers under Linux do not receive the expected
+** data transfer direction from upper scsi drivers.
+** The driver will only check actual data direction for common
+** scsi opcodes. Other ones may cause problem, since they may
+** depend on device type or be vendor specific.
+** I would prefer to never trust the device for data direction,
+** but that is not possible.
+**
+** The original driver requires the expected direction to be known.
+** The Linux version of the driver has been enhanced in order to
+** be able to transfer data in the direction choosen by the target.
+*/
+
+#define XFER_IN (1)
+#define XFER_OUT (2)
+
+/*
+** Head of list of NCR boards
+**
+** For kernel version < 1.3.70, host is retrieved by its irq level.
+** For later kernels, the internal host control block address
+** (struct ncb) is used as device id parameter of the irq stuff.
+*/
+
+static struct Scsi_Host *first_host = NULL;
+
+
+/*
+** /proc directory entry and proc_info function
+*/
+
+static struct proc_dir_entry proc_scsi_sym53c8xx = {
+ PROC_SCSI_SYM53C8XX, 9, NAME53C8XX,
+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+#ifdef SCSI_NCR_PROC_INFO_SUPPORT
+static int sym53c8xx_proc_info(char *buffer, char **start, off_t offset,
+ int length, int hostno, int func);
+#endif
+
+/*
+** Driver setup.
+**
+** This structure is initialized from linux config options.
+** It can be overridden at boot-up by the boot command line.
+*/
+#define SCSI_NCR_MAX_EXCLUDES 8
+struct ncr_driver_setup {
+ u_char master_parity;
+ u_char scsi_parity;
+ u_char disconnection;
+ u_char special_features;
+ u_char ultra_scsi;
+ u_char force_sync_nego;
+ u_char reverse_probe;
+ u_char pci_fix_up;
+ u_char use_nvram;
+ u_char verbose;
+ u_char default_tags;
+ u_short default_sync;
+ u_short debug;
+ u_char burst_max;
+ u_char led_pin;
+ u_char max_wide;
+ u_char settle_delay;
+ u_char diff_support;
+ u_char irqm;
+ u_char bus_check;
+ u_char optimize;
+ u_char recovery;
+ u_int excludes[SCSI_NCR_MAX_EXCLUDES];
+ char tag_ctrl[100];
+};
+
+static struct ncr_driver_setup
+ driver_setup = SCSI_NCR_DRIVER_SETUP;
+
+#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
+static struct ncr_driver_setup
+ driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP;
+# ifdef MODULE
+char *sym53c8xx = 0; /* command line passed by insmod */
+# if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
+MODULE_PARM(sym53c8xx, "s");
+# endif
+# endif
+#endif
+
+/*
+** Other Linux definitions
+*/
+#define SetScsiResult(cmd, h_sts, s_sts) \
+ cmd->result = (((h_sts) << 16) + ((s_sts) & 0x7f))
+
+static void sym53c8xx_select_queue_depths(
+ struct Scsi_Host *host, struct scsi_device *devlist);
+static void sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);
+static void sym53c8xx_timeout(unsigned long np);
+
+#define initverbose (driver_setup.verbose)
+#define bootverbose (np->verbose)
+
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+/*
+** Symbios NvRAM data format
+*/
+#define SYMBIOS_NVRAM_SIZE 368
+#define SYMBIOS_NVRAM_ADDRESS 0x100
+
+struct Symbios_nvram {
+/* Header 6 bytes */
+ u_short type; /* 0x0000 */
+ u_short byte_count; /* excluding header/trailer */
+ u_short checksum;
+
+/* Controller set up 20 bytes */
+ u_char v_major; /* 0x00 */
+ u_char v_minor; /* 0x30 */
+ u_int32 boot_crc;
+ u_short flags;
+#define SYMBIOS_SCAM_ENABLE (1)
+#define SYMBIOS_PARITY_ENABLE (1<<1)
+#define SYMBIOS_VERBOSE_MSGS (1<<2)
+#define SYMBIOS_CHS_MAPPING (1<<3)
+#define SYMBIOS_NO_NVRAM (1<<3) /* ??? */
+ u_short flags1;
+#define SYMBIOS_SCAN_HI_LO (1)
+ u_short term_state;
+#define SYMBIOS_TERM_CANT_PROGRAM (0)
+#define SYMBIOS_TERM_ENABLED (1)
+#define SYMBIOS_TERM_DISABLED (2)
+ u_short rmvbl_flags;
+#define SYMBIOS_RMVBL_NO_SUPPORT (0)
+#define SYMBIOS_RMVBL_BOOT_DEVICE (1)
+#define SYMBIOS_RMVBL_MEDIA_INSTALLED (2)
+ u_char host_id;
+ u_char num_hba; /* 0x04 */
+ u_char num_devices; /* 0x10 */
+ u_char max_scam_devices; /* 0x04 */
+ u_char num_valid_scam_devives; /* 0x00 */
+ u_char rsvd;
+
+/* Boot order 14 bytes * 4 */
+ struct Symbios_host{
+ u_short type; /* 4:8xx / 0:nok */
+ u_short device_id; /* PCI device id */
+ u_short vendor_id; /* PCI vendor id */
+ u_char bus_nr; /* PCI bus number */
+ u_char device_fn; /* PCI device/function number << 3*/
+ u_short word8;
+ u_short flags;
+#define SYMBIOS_INIT_SCAN_AT_BOOT (1)
+ u_short io_port; /* PCI io_port address */
+ } host[4];
+
+/* Targets 8 bytes * 16 */
+ struct Symbios_target {
+ u_char flags;
+#define SYMBIOS_DISCONNECT_ENABLE (1)
+#define SYMBIOS_SCAN_AT_BOOT_TIME (1<<1)
+#define SYMBIOS_SCAN_LUNS (1<<2)
+#define SYMBIOS_QUEUE_TAGS_ENABLED (1<<3)
+ u_char rsvd;
+ u_char bus_width; /* 0x08/0x10 */
+ u_char sync_offset;
+ u_short sync_period; /* 4*period factor */
+ u_short timeout;
+ } target[16];
+/* Scam table 8 bytes * 4 */
+ struct Symbios_scam {
+ u_short id;
+ u_short method;
+#define SYMBIOS_SCAM_DEFAULT_METHOD (0)
+#define SYMBIOS_SCAM_DONT_ASSIGN (1)
+#define SYMBIOS_SCAM_SET_SPECIFIC_ID (2)
+#define SYMBIOS_SCAM_USE_ORDER_GIVEN (3)
+ u_short status;
+#define SYMBIOS_SCAM_UNKNOWN (0)
+#define SYMBIOS_SCAM_DEVICE_NOT_FOUND (1)
+#define SYMBIOS_SCAM_ID_NOT_SET (2)
+#define SYMBIOS_SCAM_ID_VALID (3)
+ u_char target_id;
+ u_char rsvd;
+ } scam[4];
+
+ u_char spare_devices[15*8];
+ u_char trailer[6]; /* 0xfe 0xfe 0x00 0x00 0x00 0x00 */
+};
+typedef struct Symbios_nvram Symbios_nvram;
+typedef struct Symbios_host Symbios_host;
+typedef struct Symbios_target Symbios_target;
+typedef struct Symbios_scam Symbios_scam;
+
+/*
+** Tekram NvRAM data format.
+*/
+#define TEKRAM_NVRAM_SIZE 64
+#define TEKRAM_NVRAM_ADDRESS 0
+
+struct Tekram_nvram {
+ struct Tekram_target {
+ u_char flags;
+#define TEKRAM_PARITY_CHECK (1)
+#define TEKRAM_SYNC_NEGO (1<<1)
+#define TEKRAM_DISCONNECT_ENABLE (1<<2)
+#define TEKRAM_START_CMD (1<<3)
+#define TEKRAM_TAGGED_COMMANDS (1<<4)
+#define TEKRAM_WIDE_NEGO (1<<5)
+ u_char sync_index;
+ u_short word2;
+ } target[16];
+ u_char host_id;
+ u_char flags;
+#define TEKRAM_MORE_THAN_2_DRIVES (1)
+#define TEKRAM_DRIVES_SUP_1GB (1<<1)
+#define TEKRAM_RESET_ON_POWER_ON (1<<2)
+#define TEKRAM_ACTIVE_NEGATION (1<<3)
+#define TEKRAM_IMMEDIATE_SEEK (1<<4)
+#define TEKRAM_SCAN_LUNS (1<<5)
+#define TEKRAM_REMOVABLE_FLAGS (3<<6) /* 0: disable; 1: boot device; 2:all */
+ u_char boot_delay_index;
+ u_char max_tags_index;
+ u_short flags1;
+#define TEKRAM_F2_F6_ENABLED (1)
+ u_short spare[29];
+};
+typedef struct Tekram_nvram Tekram_nvram;
+typedef struct Tekram_target Tekram_target;
+
+static u_char Tekram_sync[12] __initdata = {25,31,37,43,50,62,75,125,12,15,18,21};
+
+#endif /* SCSI_NCR_NVRAM_SUPPORT */
+
+/*
+** Structures used by sym53c8xx_detect/sym53c8xx_pci_init to
+** transmit device configuration to the ncr_attach() function.
+*/
+typedef struct {
+ int bus;
+ u_char device_fn;
+ u_long base;
+ u_long base_2;
+ u_long io_port;
+ int irq;
+/* port and reg fields to use INB, OUTB macros */
+ u_long base_io;
+ volatile struct ncr_reg *reg;
+} ncr_slot;
+
+typedef struct {
+ int type;
+#define SCSI_NCR_SYMBIOS_NVRAM (1)
+#define SCSI_NCR_TEKRAM_NVRAM (2)
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+ union {
+ Symbios_nvram Symbios;
+ Tekram_nvram Tekram;
+ } data;
+#endif
+} ncr_nvram;
+
+/*
+** Structure used by sym53c8xx_detect/sym53c8xx_pci_init
+** to save data on each detected board for ncr_attach().
+*/
+typedef struct {
+ ncr_slot slot;
+ ncr_chip chip;
+ ncr_nvram *nvram;
+ u_char host_id;
+#ifdef SCSI_NCR_PQS_PDS_SUPPORT
+ u_char pqs_pds;
+#endif
+ int attach_done;
+} ncr_device;
+
+/*==========================================================
+**
+** assert ()
+**
+**==========================================================
+**
+** modified copy from 386bsd:/usr/include/sys/assert.h
+**
+**----------------------------------------------------------
+*/
+
+#define assert(expression) { \
+ if (!(expression)) { \
+ (void)panic( \
+ "assertion \"%s\" failed: file \"%s\", line %d\n", \
+ #expression, \
+ __FILE__, __LINE__); \
+ } \
+}
+
+/*==========================================================
+**
+** Big/Little endian support.
+**
+**==========================================================
+*/
+
+/*
+** If the NCR uses big endian addressing mode over the
+** PCI, actual io register addresses for byte and word
+** accesses must be changed according to lane routing.
+** Btw, ncr_offb() and ncr_offw() macros only apply to
+** constants and so donnot generate bloated code.
+*/
+
+#if defined(SCSI_NCR_BIG_ENDIAN)
+
+#define ncr_offb(o) (((o)&~3)+((~((o)&3))&3))
+#define ncr_offw(o) (((o)&~3)+((~((o)&3))&2))
+
+#else
+
+#define ncr_offb(o) (o)
+#define ncr_offw(o) (o)
+
+#endif
+
+/*
+** If the CPU and the NCR use same endian-ness adressing,
+** no byte reordering is needed for script patching.
+** Macro cpu_to_scr() is to be used for script patching.
+** Macro scr_to_cpu() is to be used for getting a DWORD
+** from the script.
+*/
+
+#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define cpu_to_scr(dw) cpu_to_le32(dw)
+#define scr_to_cpu(dw) le32_to_cpu(dw)
+
+#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define cpu_to_scr(dw) cpu_to_be32(dw)
+#define scr_to_cpu(dw) be32_to_cpu(dw)
+
+#else
+
+#define cpu_to_scr(dw) (dw)
+#define scr_to_cpu(dw) (dw)
+
+#endif
+
+/*==========================================================
+**
+** Access to the controller chip.
+**
+** If NCR_IOMAPPED is defined, the driver will use
+** normal IOs instead of the MEMORY MAPPED IO method
+** recommended by PCI specifications.
+** If all PCI bridges, host brigdes and architectures
+** would have been correctly designed for PCI, this
+** option would be useless.
+**
+**==========================================================
+*/
+
+/*
+** If the CPU and the NCR use same endian-ness adressing,
+** no byte reordering is needed for accessing chip io
+** registers. Functions suffixed by '_raw' are assumed
+** to access the chip over the PCI without doing byte
+** reordering. Functions suffixed by '_l2b' are
+** assumed to perform little-endian to big-endian byte
+** reordering, those suffixed by '_b2l' blah, blah,
+** blah, ...
+*/
+
+#if defined(NCR_IOMAPPED)
+
+/*
+** IO mapped only input / ouput
+*/
+
+#define INB_OFF(o) inb (np->base_io + ncr_offb(o))
+#define OUTB_OFF(o, val) outb ((val), np->base_io + ncr_offb(o))
+
+#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) inw_l2b (np->base_io + ncr_offw(o))
+#define INL_OFF(o) inl_l2b (np->base_io + (o))
+
+#define OUTW_OFF(o, val) outw_b2l ((val), np->base_io + ncr_offw(o))
+#define OUTL_OFF(o, val) outl_b2l ((val), np->base_io + (o))
+
+#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) inw_b2l (np->base_io + ncr_offw(o))
+#define INL_OFF(o) inl_b2l (np->base_io + (o))
+
+#define OUTW_OFF(o, val) outw_l2b ((val), np->base_io + ncr_offw(o))
+#define OUTL_OFF(o, val) outl_l2b ((val), np->base_io + (o))
+
+#else
+
+#define INW_OFF(o) inw_raw (np->base_io + ncr_offw(o))
+#define INL_OFF(o) inl_raw (np->base_io + (o))
+
+#define OUTW_OFF(o, val) outw_raw ((val), np->base_io + ncr_offw(o))
+#define OUTL_OFF(o, val) outl_raw ((val), np->base_io + (o))
+
+#endif /* ENDIANs */
+
+#else /* defined NCR_IOMAPPED */
+
+/*
+** MEMORY mapped IO input / output
+*/
+
+#define INB_OFF(o) readb((char *)np->reg + ncr_offb(o))
+#define OUTB_OFF(o, val) writeb((val), (char *)np->reg + ncr_offb(o))
+
+#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) readw_l2b((char *)np->reg + ncr_offw(o))
+#define INL_OFF(o) readl_l2b((char *)np->reg + (o))
+
+#define OUTW_OFF(o, val) writew_b2l((val), (char *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val) writel_b2l((val), (char *)np->reg + (o))
+
+#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) readw_b2l((char *)np->reg + ncr_offw(o))
+#define INL_OFF(o) readl_b2l((char *)np->reg + (o))
+
+#define OUTW_OFF(o, val) writew_l2b((val), (char *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val) writel_l2b((val), (char *)np->reg + (o))
+
+#else
+
+#define INW_OFF(o) readw_raw((char *)np->reg + ncr_offw(o))
+#define INL_OFF(o) readl_raw((char *)np->reg + (o))
+
+#define OUTW_OFF(o, val) writew_raw((val), (char *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val) writel_raw((val), (char *)np->reg + (o))
+
+#endif
+
+#endif /* defined NCR_IOMAPPED */
+
+#define INB(r) INB_OFF (offsetof(struct ncr_reg,r))
+#define INW(r) INW_OFF (offsetof(struct ncr_reg,r))
+#define INL(r) INL_OFF (offsetof(struct ncr_reg,r))
+
+#define OUTB(r, val) OUTB_OFF (offsetof(struct ncr_reg,r), (val))
+#define OUTW(r, val) OUTW_OFF (offsetof(struct ncr_reg,r), (val))
+#define OUTL(r, val) OUTL_OFF (offsetof(struct ncr_reg,r), (val))
+
+/*
+** Set bit field ON, OFF
+*/
+
+#define OUTONB(r, m) OUTB(r, INB(r) | (m))
+#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m))
+#define OUTONW(r, m) OUTW(r, INW(r) | (m))
+#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m))
+#define OUTONL(r, m) OUTL(r, INL(r) | (m))
+#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m))
+
+
+/*==========================================================
+**
+** Command control block states.
+**
+**==========================================================
+*/
+
+#define HS_IDLE (0)
+#define HS_BUSY (1)
+#define HS_NEGOTIATE (2) /* sync/wide data transfer*/
+#define HS_DISCONNECT (3) /* Disconnected by target */
+
+#define HS_DONEMASK (0x80)
+#define HS_COMPLETE (4|HS_DONEMASK)
+#define HS_SEL_TIMEOUT (5|HS_DONEMASK) /* Selection timeout */
+#define HS_RESET (6|HS_DONEMASK) /* SCSI reset */
+#define HS_ABORTED (7|HS_DONEMASK) /* Transfer aborted */
+#define HS_TIMEOUT (8|HS_DONEMASK) /* Software timeout */
+#define HS_FAIL (9|HS_DONEMASK) /* SCSI or PCI bus errors */
+#define HS_UNEXPECTED (10|HS_DONEMASK)/* Unexpected disconnect */
+
+#define DSA_INVALID 0xffffffff
+
+/*==========================================================
+**
+** Software Interrupt Codes
+**
+**==========================================================
+*/
+
+#define SIR_BAD_STATUS (1)
+#define SIR_SEL_ATN_NO_MSG_OUT (2)
+#define SIR_NEGO_SYNC (3)
+#define SIR_NEGO_WIDE (4)
+#define SIR_NEGO_FAILED (5)
+#define SIR_NEGO_PROTO (6)
+#define SIR_REJECT_RECEIVED (7)
+#define SIR_REJECT_TO_SEND (8)
+#define SIR_IGN_RESIDUE (9)
+#define SIR_MISSING_SAVE (10)
+#define SIR_RESEL_NO_MSG_IN (11)
+#define SIR_RESEL_NO_IDENTIFY (12)
+#define SIR_RESEL_BAD_LUN (13)
+#define SIR_UNUSED_14 (14)
+#define SIR_RESEL_BAD_I_T_L (15)
+#define SIR_RESEL_BAD_I_T_L_Q (16)
+#define SIR_UNUSED_17 (17)
+#define SIR_RESEL_ABORTED (18)
+#define SIR_MSG_OUT_DONE (19)
+#define SIR_MAX (19)
+
+/*==========================================================
+**
+** Extended error codes.
+** xerr_status field of struct ccb.
+**
+**==========================================================
+*/
+
+#define XE_OK (0)
+#define XE_EXTRA_DATA (1) /* unexpected data phase */
+#define XE_BAD_PHASE (2) /* illegal phase (4/5) */
+
+/*==========================================================
+**
+** Negotiation status.
+** nego_status field of struct ccb.
+**
+**==========================================================
+*/
+
+#define NS_SYNC (1)
+#define NS_WIDE (2)
+
+/*==========================================================
+**
+** "Special features" of targets.
+** quirks field of struct tcb.
+** actualquirks field of struct ccb.
+**
+**==========================================================
+*/
+
+#define QUIRK_AUTOSAVE (0x01)
+#define QUIRK_NOMSG (0x02)
+#define QUIRK_NOSYNC (0x10)
+#define QUIRK_NOWIDE16 (0x20)
+
+/*==========================================================
+**
+** Capability bits in Inquire response byte 7.
+**
+**==========================================================
+*/
+
+#define INQ7_QUEUE (0x02)
+#define INQ7_SYNC (0x10)
+#define INQ7_WIDE16 (0x20)
+
+/*==========================================================
+**
+** A CCB hashed table is used to retrieve CCB address
+** from DSA value.
+**
+**==========================================================
+*/
+
+#define CCB_HASH_SHIFT 8
+#define CCB_HASH_SIZE (1UL << CCB_HASH_SHIFT)
+#define CCB_HASH_MASK (CCB_HASH_SIZE-1)
+#define CCB_HASH_CODE(dsa) (((dsa) >> 11) & CCB_HASH_MASK)
+
+/*==========================================================
+**
+** Declaration of structs.
+**
+**==========================================================
+*/
+
+struct tcb;
+struct lcb;
+struct ccb;
+struct ncb;
+struct script;
+
+typedef struct ncb * ncb_p;
+typedef struct tcb * tcb_p;
+typedef struct lcb * lcb_p;
+typedef struct ccb * ccb_p;
+
+struct link {
+ ncrcmd l_cmd;
+ ncrcmd l_paddr;
+};
+
+struct usrcmd {
+ u_long target;
+ u_long lun;
+ u_long data;
+ u_long cmd;
+};
+
+#define UC_SETSYNC 10
+#define UC_SETTAGS 11
+#define UC_SETDEBUG 12
+#define UC_SETORDER 13
+#define UC_SETWIDE 14
+#define UC_SETFLAG 15
+#define UC_CLEARPROF 16
+#define UC_SETVERBOSE 17
+
+#define UF_TRACE (0x01)
+#define UF_NODISC (0x02)
+#define UF_NOSCAN (0x04)
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+/*
+** profiling data (per host)
+*/
+
+struct profile {
+ u_long num_trans;
+ u_long num_disc;
+ u_long num_disc0;
+ u_long num_break;
+ u_long num_int;
+ u_long num_fly;
+ u_long num_kbytes;
+#if 000
+ u_long num_br1k;
+ u_long num_br2k;
+ u_long num_br4k;
+ u_long num_br8k;
+ u_long num_brnk;
+#endif
+};
+#endif
+
+/*========================================================================
+**
+** Declaration of structs: target control block
+**
+**========================================================================
+*/
+struct tcb {
+ /*----------------------------------------------------------------
+ ** LUN tables.
+ ** An array of bus addresses is used on reselection by
+ ** the SCRIPT.
+ **----------------------------------------------------------------
+ */
+ u_int32 *luntbl; /* lcbs bus address table */
+ u_int32 b_luntbl; /* bus address of this table */
+ lcb_p lp[MAX_LUN]; /* The lcb's of this tcb */
+
+ /*----------------------------------------------------------------
+ ** Target capabilities.
+ **----------------------------------------------------------------
+ */
+ u_char inq_done; /* Target capabilities received */
+ u_char inq_byte7; /* Contains these capabilities */
+
+ /*----------------------------------------------------------------
+ ** Pointer to the ccb used for negotiation.
+ ** Prevent from starting a negotiation for all queued commands
+ ** when tagged command queuing is enabled.
+ **----------------------------------------------------------------
+ */
+ ccb_p nego_cp;
+
+ /*----------------------------------------------------------------
+ ** statistical data
+ **----------------------------------------------------------------
+ */
+ u_long transfers;
+ u_long bytes;
+
+ /*----------------------------------------------------------------
+ ** negotiation of wide and synch transfer and device quirks.
+ ** sval and wval are read from SCRIPTS and so have alignment
+ ** constraints.
+ **----------------------------------------------------------------
+ */
+/*0*/ u_char minsync;
+/*1*/ u_char sval;
+/*2*/ u_short period;
+/*0*/ u_char maxoffs;
+/*1*/ u_char quirks;
+/*2*/ u_char widedone;
+/*3*/ u_char wval;
+
+ /*----------------------------------------------------------------
+ ** User settable limits and options.
+ ** These limits are read from the NVRAM if present.
+ **----------------------------------------------------------------
+ */
+ u_char usrsync;
+ u_char usrwide;
+ u_char usrtags;
+ u_char usrflag;
+};
+
+/*========================================================================
+**
+** Declaration of structs: lun control block
+**
+**========================================================================
+*/
+struct lcb {
+ /*----------------------------------------------------------------
+ ** On reselection, SCRIPTS use this value as a JUMP address
+ ** after the IDENTIFY has been successfully received.
+ ** This field is set to 'resel_tag' if TCQ is enabled and
+ ** to 'resel_notag' if TCQ is disabled.
+ ** (Must be at zero due to bad lun handling on reselection)
+ **----------------------------------------------------------------
+ */
+/*0*/ u_int32 resel_task;
+
+ /*----------------------------------------------------------------
+ ** Task table used by the script processor to retrieve the
+ ** task corresponding to a reselected nexus. The TAG is used
+ ** as offset to determine the corresponding entry.
+ ** Each entry contains the associated CCB bus address.
+ **----------------------------------------------------------------
+ */
+ u_int32 tasktbl_0; /* Used if TCQ not enabled */
+ u_int32 *tasktbl;
+ u_int32 b_tasktbl;
+
+ /*----------------------------------------------------------------
+ ** CCB queue management.
+ **----------------------------------------------------------------
+ */
+ XPT_QUEHEAD busy_ccbq; /* Queue of busy CCBs */
+ XPT_QUEHEAD wait_ccbq; /* Queue of waiting for IO CCBs */
+ u_char busyccbs; /* CCBs busy for this lun */
+ u_char queuedccbs; /* CCBs queued to the controller*/
+ u_char queuedepth; /* Queue depth for this lun */
+ u_char scdev_depth; /* SCSI device queue depth */
+ u_char maxnxs; /* Max possible nexuses */
+
+ /*----------------------------------------------------------------
+ ** Control of tagged command queuing.
+ ** Tags allocation is performed using a circular buffer.
+ ** This avoids using a loop for tag allocation.
+ **----------------------------------------------------------------
+ */
+ u_char ia_tag; /* Tag allocation index */
+ u_char if_tag; /* Tag release index */
+ u_char cb_tags[SCSI_NCR_MAX_TAGS]; /* Circular tags buffer */
+ u_char usetags; /* Command queuing is active */
+ u_char maxtags; /* Max NR of tags asked by user */
+ u_char numtags; /* Current number of tags */
+ u_char inq_byte7; /* Store unit CmdQ capabitility */
+
+ /*----------------------------------------------------------------
+ ** QUEUE FULL and ORDERED tag control.
+ **----------------------------------------------------------------
+ */
+ u_short num_good; /* Nr of GOOD since QUEUE FULL */
+ tagmap_t tags_umap; /* Used tags bitmap */
+ tagmap_t tags_smap; /* Tags in use at 'tag_stime' */
+ u_long tags_stime; /* Last time we set smap=umap */
+};
+
+/*========================================================================
+**
+** Declaration of structs: actions for a task.
+**
+**========================================================================
+**
+** It is part of the CCB and is called by the scripts processor to
+** start or restart the data structure (nexus).
+**
+**------------------------------------------------------------------------
+*/
+struct action {
+ u_int32 start;
+ u_int32 restart;
+};
+
+/*========================================================================
+**
+** Declaration of structs: Phase mismatch context.
+**
+**========================================================================
+**
+** It is part of the CCB and is used as parameters for the DATA
+** pointer. We need two contexts to handle correctly the SAVED
+** DATA POINTER.
+**
+**------------------------------------------------------------------------
+*/
+struct pm_ctx {
+ struct scr_tblmove sg; /* Updated interrupted SG block */
+ u_int32 ret; /* SCRIPT return address */
+};
+
+/*========================================================================
+**
+** Declaration of structs: global HEADER.
+**
+**========================================================================
+**
+** In earlier driver versions, this substructure was copied from the
+** ccb to a global address after selection (or reselection) and copied
+** back before disconnect. Since we are now using LOAD/STORE DSA
+** RELATIVE instructions, the script is able to access directly these
+** fields, and so, this header is no more copied.
+**
+**------------------------------------------------------------------------
+*/
+
+struct head {
+ /*----------------------------------------------------------------
+ ** Start and restart SCRIPTS addresses (must be at 0).
+ **----------------------------------------------------------------
+ */
+ struct action go;
+
+ /*----------------------------------------------------------------
+ ** Saved data pointer.
+ ** Points to the position in the script responsible for the
+ ** actual transfer of data.
+ ** It's written after reception of a SAVE_DATA_POINTER message.
+ ** The goalpointer points after the last transfer command.
+ **----------------------------------------------------------------
+ */
+ u_int32 savep;
+ u_int32 lastp;
+ u_int32 goalp;
+
+ /*----------------------------------------------------------------
+ ** Alternate data pointer.
+ ** They are copied back to savep/lastp/goalp by the SCRIPTS
+ ** when the direction is unknown and the device claims data out.
+ **----------------------------------------------------------------
+ */
+ u_int32 wlastp;
+ u_int32 wgoalp;
+
+ /*----------------------------------------------------------------
+ ** Status fields.
+ **----------------------------------------------------------------
+ */
+ u_char scr_st[4]; /* script status */
+ u_char status[4]; /* host status */
+};
+
+/*
+** The status bytes are used by the host and the script processor.
+**
+** The last four bytes (status[4]) are copied to the scratchb register
+** (declared as scr0..scr3 in ncr_reg.h) just after the select/reselect,
+** and copied back just after disconnecting.
+** Inside the script the XX_REG are used.
+**
+** The first four bytes (scr_st[4]) are used inside the script by
+** "LOAD/STORE" commands.
+** Because source and destination must have the same alignment
+** in a DWORD, the fields HAVE to be at the choosen offsets.
+** xerr_st 0 (0x34) scratcha
+** sync_st 1 (0x05) sxfer
+** wide_st 3 (0x03) scntl3
+*/
+
+/*
+** Last four bytes (script)
+*/
+#define QU_REG scr0
+#define HS_REG scr1
+#define HS_PRT nc_scr1
+#define SS_REG scr2
+#define SS_PRT nc_scr2
+#define HF_REG scr3
+#define HF_PRT nc_scr3
+
+/*
+** Last four bytes (host)
+*/
+#define actualquirks phys.header.status[0]
+#define host_status phys.header.status[1]
+#define scsi_status phys.header.status[2]
+#define host_flags phys.header.status[3]
+
+/*
+** Host flags
+*/
+#define HF_IN_PM0 1u
+#define HF_IN_PM1 (1u<<1)
+#define HF_ACT_PM (1u<<2)
+#define HF_DP_SAVED (1u<<3)
+#define HF_PAR_ERR (1u<<4)
+#define HF_DATA_ST (1u<<5)
+#define HF_PM_TO_C (1u<<6)
+
+/*
+** First four bytes (script)
+*/
+#define xerr_st header.scr_st[0]
+#define sync_st header.scr_st[1]
+#define nego_st header.scr_st[2]
+#define wide_st header.scr_st[3]
+
+/*
+** First four bytes (host)
+*/
+#define xerr_status phys.xerr_st
+#define nego_status phys.nego_st
+
+/*==========================================================
+**
+** Declaration of structs: Data structure block
+**
+**==========================================================
+**
+** During execution of a ccb by the script processor,
+** the DSA (data structure address) register points
+** to this substructure of the ccb.
+** This substructure contains the header with
+** the script-processor-changable data and
+** data blocks for the indirect move commands.
+**
+**----------------------------------------------------------
+*/
+
+struct dsb {
+
+ /*
+ ** Header.
+ */
+
+ struct head header;
+
+ /*
+ ** Table data for Script
+ */
+
+ struct scr_tblsel select;
+ struct scr_tblmove smsg ;
+ struct scr_tblmove cmd ;
+ struct scr_tblmove sense ;
+ struct scr_tblmove data [MAX_SCATTER];
+
+ /*
+ ** Phase mismatch contexts.
+ ** We need two to handle correctly the
+ ** SAVED DATA POINTER.
+ */
+
+ struct pm_ctx pm0;
+ struct pm_ctx pm1;
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ /*
+ ** Disconnection counter
+ */
+ u_int32 num_disc;
+#endif
+};
+
+
+/*========================================================================
+**
+** Declaration of structs: Command control block.
+**
+**========================================================================
+*/
+struct ccb {
+ /*----------------------------------------------------------------
+ ** This is the data structure which is pointed by the DSA
+ ** register when it is executed by the script processor.
+ ** It must be the first entry.
+ **----------------------------------------------------------------
+ */
+ struct dsb phys;
+
+ /*----------------------------------------------------------------
+ ** The general SCSI driver provides a
+ ** pointer to a control block.
+ **----------------------------------------------------------------
+ */
+ Scsi_Cmnd *cmd; /* SCSI command */
+ u_long tlimit; /* Deadline for this job */
+ int data_len; /* Total data length */
+
+ /*----------------------------------------------------------------
+ ** Message areas.
+ ** We prepare a message to be sent after selection.
+ ** We may use a second one if the command is rescheduled
+ ** due to CHECK_CONDITION or QUEUE FULL status.
+ ** Contents are IDENTIFY and SIMPLE_TAG.
+ ** While negotiating sync or wide transfer,
+ ** a SDTR or WDTR message is appended.
+ **----------------------------------------------------------------
+ */
+ u_char scsi_smsg [8];
+ u_char scsi_smsg2[8];
+
+ /*----------------------------------------------------------------
+ ** Other fields.
+ **----------------------------------------------------------------
+ */
+ u_long p_ccb; /* BUS address of this CCB */
+ u_char sensecmd[6]; /* Sense command */
+ u_char tag; /* Tag for this transfer */
+ /* 255 means no tag */
+ u_char target;
+ u_char lun;
+ u_char queued;
+ u_char auto_sense;
+ ccb_p link_ccb; /* Host adapter CCB chain */
+ ccb_p link_ccbh; /* Host adapter CCB hash chain */
+ XPT_QUEHEAD link_ccbq; /* Link to unit CCB queue */
+ u_int32 startp; /* Initial data pointer */
+};
+
+#define CCB_PHYS(cp,lbl) (cp->p_ccb + offsetof(struct ccb, lbl))
+
+
+/*========================================================================
+**
+** Declaration of structs: NCR device descriptor
+**
+**========================================================================
+*/
+struct ncb {
+ /*----------------------------------------------------------------
+ ** Idle task and invalid task actions and their bus
+ ** addresses.
+ **----------------------------------------------------------------
+ */
+ struct action idletask;
+ struct action notask;
+ struct action bad_i_t_l;
+ struct action bad_i_t_l_q;
+ u_long p_idletask;
+ u_long p_notask;
+ u_long p_bad_i_t_l;
+ u_long p_bad_i_t_l_q;
+
+ /*----------------------------------------------------------------
+ ** Dummy lun table to protect us against target returning bad
+ ** lun number on reselection.
+ **----------------------------------------------------------------
+ */
+ u_int32 *badluntbl; /* Table physical address */
+ u_int32 resel_badlun; /* SCRIPT handler BUS address */
+
+ /*----------------------------------------------------------------
+ ** Bit 32-63 of the on-chip RAM bus address in LE format.
+ ** The START_RAM64 script loads the MMRS and MMWS from this
+ ** field.
+ **----------------------------------------------------------------
+ */
+ u_int32 scr_ram_seg;
+
+ /*----------------------------------------------------------------
+ ** CCBs management queues.
+ **----------------------------------------------------------------
+ */
+ Scsi_Cmnd *waiting_list; /* Commands waiting for a CCB */
+ /* when lcb is not allocated. */
+ Scsi_Cmnd *done_list; /* Commands waiting for done() */
+ /* callback to be invoked. */
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)
+ spinlock_t smp_lock; /* Lock for SMP threading */
+#endif
+
+ /*----------------------------------------------------------------
+ ** Chip and controller indentification.
+ **----------------------------------------------------------------
+ */
+ int unit; /* Unit number */
+ char chip_name[8]; /* Chip name */
+ char inst_name[16]; /* ncb instance name */
+
+ /*----------------------------------------------------------------
+ ** Initial value of some IO register bits.
+ ** These values are assumed to have been set by BIOS, and may
+ ** be used for probing adapter implementation differences.
+ **----------------------------------------------------------------
+ */
+ u_char sv_scntl0, sv_scntl3, sv_dmode, sv_dcntl, sv_ctest3, sv_ctest4,
+ sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4;
+
+ /*----------------------------------------------------------------
+ ** Actual initial value of IO register bits used by the
+ ** driver. They are loaded at initialisation according to
+ ** features that are to be enabled.
+ **----------------------------------------------------------------
+ */
+ u_char rv_scntl0, rv_scntl3, rv_dmode, rv_dcntl, rv_ctest3, rv_ctest4,
+ rv_ctest5, rv_stest2, rv_ccntl0, rv_ccntl1;
+
+ /*----------------------------------------------------------------
+ ** Target data.
+ ** Target control block bus address array used by the SCRIPT
+ ** on reselection.
+ **----------------------------------------------------------------
+ */
+ struct tcb target[MAX_TARGET];
+ u_int32 *targtbl;
+
+ /*----------------------------------------------------------------
+ ** Virtual and physical bus addresses of the chip.
+ **----------------------------------------------------------------
+ */
+ u_long base_va; /* MMIO base virtual address */
+ u_long base_ba; /* MMIO base bus address */
+ u_long base_io; /* IO space base address */
+ u_long base_ws; /* (MM)IO window size */
+ u_long base2_ba; /* On-chip RAM bus address. */
+ u_int irq; /* IRQ number */
+ volatile /* Pointer to volatile for */
+ struct ncr_reg *reg; /* memory mapped IO. */
+
+ /*----------------------------------------------------------------
+ ** SCRIPTS virtual and physical bus addresses.
+ ** 'script' is loaded in the on-chip RAM if present.
+ ** 'scripth' stays in main memory for all chips except the
+ ** 53C896 that provides 8K on-chip RAM.
+ **----------------------------------------------------------------
+ */
+ struct script *script0; /* Copies of script and scripth */
+ struct scripth *scripth0; /* relocated for this ncb. */
+ u_long p_script; /* Actual script and scripth */
+ u_long p_scripth; /* bus addresses. */
+ u_long p_scripth0;
+
+ /*----------------------------------------------------------------
+ ** General controller parameters and configuration.
+ **----------------------------------------------------------------
+ */
+ u_short device_id; /* PCI device id */
+ u_char revision_id; /* PCI device revision id */
+ u_int features; /* Chip features map */
+ u_char myaddr; /* SCSI id of the adapter */
+ u_char maxburst; /* log base 2 of dwords burst */
+ u_char maxwide; /* Maximum transfer width */
+ u_char minsync; /* Minimum sync period factor */
+ u_char maxsync; /* Maximum sync period factor */
+ u_char maxoffs; /* Max scsi offset */
+ u_char multiplier; /* Clock multiplier (1,2,4) */
+ u_char clock_divn; /* Number of clock divisors */
+ u_long clock_khz; /* SCSI clock frequency in KHz */
+
+ /*----------------------------------------------------------------
+ ** Start queue management.
+ ** It is filled up by the host processor and accessed by the
+ ** SCRIPTS processor in order to start SCSI commands.
+ **----------------------------------------------------------------
+ */
+ u_int32 *squeue; /* Start queue */
+ u_short squeueput; /* Next free slot of the queue */
+ u_short actccbs; /* Number of allocated CCBs */
+ u_short queuedepth; /* Start queue depth */
+
+ /*----------------------------------------------------------------
+ ** Command completion queue.
+ ** It is the same size as the start queue to avoid overflow.
+ **----------------------------------------------------------------
+ */
+ u_short dqueueget; /* Next position to scan */
+ u_int32 *dqueue; /* Completion (done) queue */
+
+ /*----------------------------------------------------------------
+ ** Timeout handler.
+ **----------------------------------------------------------------
+ */
+ struct timer_list timer; /* Timer handler link header */
+ u_long lasttime;
+ u_long settle_time; /* Resetting the SCSI BUS */
+
+ /*----------------------------------------------------------------
+ ** Debugging and profiling.
+ **----------------------------------------------------------------
+ */
+ struct ncr_reg regdump; /* Register dump */
+ u_long regtime; /* Time it has been done */
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ struct profile profile; /* Profiling data */
+#endif
+
+ /*----------------------------------------------------------------
+ ** Miscellaneous buffers accessed by the scripts-processor.
+ ** They shall be DWORD aligned, because they may be read or
+ ** written with a script command.
+ **----------------------------------------------------------------
+ */
+ u_char msgout[8]; /* Buffer for MESSAGE OUT */
+ u_char msgin [8]; /* Buffer for MESSAGE IN */
+ u_int32 lastmsg; /* Last SCSI message sent */
+ u_char scratch; /* Scratch for SCSI receive */
+
+ /*----------------------------------------------------------------
+ ** Miscellaneous configuration and status parameters.
+ **----------------------------------------------------------------
+ */
+ u_char scsi_mode; /* Current SCSI BUS mode */
+ u_char order; /* Tag order to use */
+ u_char verbose; /* Verbosity for this controller*/
+ u_int32 ncr_cache; /* Used for cache test at init. */
+
+ /*----------------------------------------------------------------
+ ** CCB lists and queue.
+ **----------------------------------------------------------------
+ */
+ ccb_p ccbh[CCB_HASH_SIZE]; /* CCB hashed by DSA value */
+ struct ccb *ccbc; /* CCB chain */
+ XPT_QUEHEAD free_ccbq; /* Queue of available CCBs */
+
+ /*----------------------------------------------------------------
+ ** We need the LCB in order to handle disconnections and
+ ** to count active CCBs for task management. So, we use
+ ** a unique CCB for LUNs we donnot have the LCB yet.
+ ** This queue normally should have at most 1 element.
+ **----------------------------------------------------------------
+ */
+ XPT_QUEHEAD b0_ccbq;
+
+ /*----------------------------------------------------------------
+ ** We use a different scatter function for 896 rev 1.
+ **----------------------------------------------------------------
+ */
+ int (*scatter) (ccb_p, Scsi_Cmnd *);
+
+ /*----------------------------------------------------------------
+ ** Fields that should be removed or changed.
+ **----------------------------------------------------------------
+ */
+ struct usrcmd user; /* Command from user */
+ u_char release_stage; /* Synchronisation stage on release */
+};
+
+#define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl))
+#define NCB_SCRIPTH_PHYS(np,lbl) (np->p_scripth + offsetof (struct scripth,lbl))
+#define NCB_SCRIPTH0_PHYS(np,lbl) (np->p_scripth0+offsetof (struct scripth,lbl))
+
+/*==========================================================
+**
+**
+** Script for NCR-Processor.
+**
+** Use ncr_script_fill() to create the variable parts.
+** Use ncr_script_copy_and_bind() to make a copy and
+** bind to physical addresses.
+**
+**
+**==========================================================
+**
+** We have to know the offsets of all labels before
+** we reach them (for forward jumps).
+** Therefore we declare a struct here.
+** If you make changes inside the script,
+** DONT FORGET TO CHANGE THE LENGTHS HERE!
+**
+**----------------------------------------------------------
+*/
+
+/*
+** Script fragments which are loaded into the on-chip RAM
+** of 825A, 875, 876, 895 and 896 chips.
+*/
+struct script {
+ ncrcmd start [ 10];
+ ncrcmd getjob_begin [ 4];
+ ncrcmd getjob_end [ 4];
+ ncrcmd select [ 4];
+ ncrcmd wf_sel_done [ 2];
+ ncrcmd send_ident [ 2];
+ ncrcmd select2 [ 6];
+ ncrcmd command [ 2];
+ ncrcmd dispatch [ 26];
+ ncrcmd sel_no_cmd [ 10];
+ ncrcmd init [ 6];
+ ncrcmd clrack [ 4];
+ ncrcmd databreak [ 2];
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ncrcmd dataphase [ 4];
+#else
+ ncrcmd dataphase [ 2];
+#endif
+ ncrcmd status [ 8];
+ ncrcmd msg_in [ 2];
+ ncrcmd msg_in2 [ 16];
+ ncrcmd msg_bad [ 6];
+ ncrcmd complete [ 8];
+ ncrcmd complete2 [ 6];
+ ncrcmd done [ 14];
+ ncrcmd done_end [ 2];
+ ncrcmd save_dp [ 8];
+ ncrcmd restore_dp [ 4];
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ncrcmd disconnect [ 32];
+#else
+ ncrcmd disconnect [ 20];
+#endif
+ ncrcmd idle [ 2];
+ ncrcmd ungetjob [ 4];
+ ncrcmd reselect [ 4];
+ ncrcmd reselected [ 44];
+ ncrcmd resel_tag [ 6];
+ ncrcmd resel_go [ 6];
+ ncrcmd resel_notag [ 4];
+ ncrcmd resel_dsa [ 8];
+ ncrcmd data_in [MAX_SCATTERL * SCR_SG_SIZE];
+ ncrcmd data_in2 [ 4];
+ ncrcmd data_out [MAX_SCATTERL * SCR_SG_SIZE];
+ ncrcmd data_out2 [ 4];
+ ncrcmd pm0_data [ 16];
+ ncrcmd pm1_data [ 16];
+
+ /* Data area */
+ ncrcmd saved_dsa [ 1];
+ ncrcmd done_pos [ 1];
+ ncrcmd startpos [ 1];
+ ncrcmd targtbl [ 1];
+};
+
+/*
+** Script fragments which stay in main memory for all chips
+** except for the 896 that support 8K on-chip RAM.
+*/
+struct scripth {
+ ncrcmd start64 [ 2];
+ ncrcmd select_no_atn [ 4];
+ ncrcmd wf_sel_done_no_atn [ 4];
+ ncrcmd cancel [ 4];
+ ncrcmd msg_reject [ 8];
+ ncrcmd msg_ign_residue [ 24];
+ ncrcmd msg_extended [ 10];
+ ncrcmd msg_ext_2 [ 10];
+ ncrcmd msg_wdtr [ 14];
+ ncrcmd send_wdtr [ 4];
+ ncrcmd msg_ext_3 [ 10];
+ ncrcmd msg_sdtr [ 14];
+ ncrcmd send_sdtr [ 4];
+ ncrcmd nego_bad_phase [ 4];
+ ncrcmd msg_out_abort [ 12];
+ ncrcmd msg_out [ 6];
+ ncrcmd msg_out_done [ 4];
+ ncrcmd no_data [ 16];
+#if MAX_SCATTERH != 0
+ ncrcmd hdata_in [MAX_SCATTERH * SCR_SG_SIZE];
+ ncrcmd hdata_in2 [ 2];
+ ncrcmd hdata_out [MAX_SCATTERH * SCR_SG_SIZE];
+ ncrcmd hdata_out2 [ 2];
+#endif
+ ncrcmd abort_resel [ 16];
+ ncrcmd resend_ident [ 4];
+ ncrcmd ident_break [ 4];
+ ncrcmd ident_break_atn [ 4];
+ ncrcmd sdata_in [ 6];
+ ncrcmd data_io [ 2];
+ ncrcmd data_io_com [ 8];
+ ncrcmd data_io_out [ 10];
+ ncrcmd bad_identify [ 12];
+ ncrcmd bad_i_t_l [ 4];
+ ncrcmd bad_i_t_l_q [ 4];
+ ncrcmd bad_status [ 10];
+ ncrcmd tweak_pmj [ 12];
+ ncrcmd pm_handle [ 20];
+ ncrcmd pm_handle1 [ 4];
+ ncrcmd pm_save [ 4];
+ ncrcmd pm0_save [ 10];
+ ncrcmd pm1_save [ 10];
+
+ /* Data area */
+ ncrcmd pm0_data_addr [ 1];
+ ncrcmd pm1_data_addr [ 1];
+ /* End of data area */
+
+ ncrcmd start_ram [ 1];
+ ncrcmd script0_ba [ 4];
+
+ ncrcmd start_ram64 [ 3];
+ ncrcmd script0_ba64 [ 3];
+ ncrcmd scripth0_ba64 [ 6];
+ ncrcmd ram_seg64 [ 1];
+
+ ncrcmd snooptest [ 6];
+ ncrcmd snoopend [ 2];
+};
+
+/*==========================================================
+**
+**
+** Function headers.
+**
+**
+**==========================================================
+*/
+
+static ccb_p ncr_alloc_ccb (ncb_p np);
+static void ncr_complete (ncb_p np, ccb_p cp);
+static void ncr_exception (ncb_p np);
+static void ncr_free_ccb (ncb_p np, ccb_p cp);
+static ccb_p ncr_ccb_from_dsa(ncb_p np, u_long dsa);
+static void ncr_init_tcb (ncb_p np, u_char tn);
+static lcb_p ncr_alloc_lcb (ncb_p np, u_char tn, u_char ln);
+static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln,
+ u_char *inq_data);
+static void ncr_getclock (ncb_p np, int mult);
+static void ncr_selectclock (ncb_p np, u_char scntl3);
+static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln);
+static void ncr_init (ncb_p np, int reset, char * msg, u_long code);
+static void ncr_int_sbmc (ncb_p np);
+static void ncr_int_par (ncb_p np, u_short sist);
+static void ncr_int_ma (ncb_p np);
+static void ncr_int_sir (ncb_p np);
+static void ncr_int_sto (ncb_p np);
+static void ncr_int_udc (ncb_p np);
+static u_long ncr_lookup (char* id);
+static void ncr_negotiate (struct ncb* np, struct tcb* tp);
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+static void ncb_profile (ncb_p np, ccb_p cp);
+#endif
+static void ncr_script_copy_and_bind
+ (ncb_p np, ncrcmd *src, ncrcmd *dst, int len);
+static void ncr_script_fill (struct script * scr, struct scripth * scripth);
+static int ncr_scatter_896R1 (ccb_p cp, Scsi_Cmnd *cmd);
+static int ncr_scatter (ccb_p cp, Scsi_Cmnd *cmd);
+static void ncr_getsync (ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p);
+static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer);
+static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln);
+static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack);
+static int ncr_show_msg (u_char * msg);
+static int ncr_snooptest (ncb_p np);
+static void ncr_timeout (ncb_p np);
+static void ncr_wakeup (ncb_p np, u_long code);
+static int ncr_wakeup_done (ncb_p np);
+static void ncr_start_next_ccb (ncb_p np, lcb_p lp, int maxn);
+static void ncr_put_start_queue(ncb_p np, ccb_p cp);
+static void ncr_soft_reset (ncb_p np);
+static void ncr_start_reset (ncb_p np);
+static int ncr_reset_scsi_bus (ncb_p np, int enab_int, int settle_delay);
+
+#ifdef SCSI_NCR_USER_COMMAND_SUPPORT
+static void ncr_usercmd (ncb_p np);
+#endif
+
+static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device);
+static void ncr_free_resources(ncb_p np);
+
+static void insert_into_waiting_list(ncb_p np, Scsi_Cmnd *cmd);
+static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd *cmd);
+static void process_waiting_list(ncb_p np, int sts);
+
+#define remove_from_waiting_list(np, cmd) \
+ retrieve_from_waiting_list(1, (np), (cmd))
+#define requeue_waiting_list(np) process_waiting_list((np), DID_OK)
+#define reset_waiting_list(np) process_waiting_list((np), DID_RESET)
+
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+static void ncr_get_nvram (ncr_device *devp, ncr_nvram *nvp);
+static int ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram);
+static int ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram *nvram);
+#endif
+
+/*==========================================================
+**
+**
+** Global static data.
+**
+**
+**==========================================================
+*/
+
+static inline char *ncr_name (ncb_p np)
+{
+ return np->inst_name;
+}
+
+
+/*==========================================================
+**
+**
+** Scripts for NCR-Processor.
+**
+** Use ncr_script_bind for binding to physical addresses.
+**
+**
+**==========================================================
+**
+** NADDR generates a reference to a field of the controller data.
+** PADDR generates a reference to another part of the script.
+** RADDR generates a reference to a script processor register.
+** FADDR generates a reference to a script processor register
+** with offset.
+**
+**----------------------------------------------------------
+*/
+
+#define RELOC_SOFTC 0x40000000
+#define RELOC_LABEL 0x50000000
+#define RELOC_REGISTER 0x60000000
+#if 0
+#define RELOC_KVAR 0x70000000
+#endif
+#define RELOC_LABELH 0x80000000
+#define RELOC_MASK 0xf0000000
+
+#define NADDR(label) (RELOC_SOFTC | offsetof(struct ncb, label))
+#define PADDR(label) (RELOC_LABEL | offsetof(struct script, label))
+#define PADDRH(label) (RELOC_LABELH | offsetof(struct scripth, label))
+#define RADDR(label) (RELOC_REGISTER | REG(label))
+#define FADDR(label,ofs)(RELOC_REGISTER | ((REG(label))+(ofs)))
+#define KVAR(which) (RELOC_KVAR | (which))
+
+#define SCR_DATA_ZERO 0xf00ff00f
+
+#ifdef RELOC_KVAR
+#define SCRIPT_KVAR_JIFFIES (0)
+#define SCRIPT_KVAR_FIRST SCRIPT_KVAR_JIFFIES
+#define SCRIPT_KVAR_LAST SCRIPT_KVAR_JIFFIES
+/*
+ * Kernel variables referenced in the scripts.
+ * THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY.
+ */
+static void *script_kvars[] __initdata =
+ { (void *)&jiffies };
+#endif
+
+static struct script script0 __initdata = {
+/*--------------------------< START >-----------------------*/ {
+ /*
+ ** This NOP will be patched with LED ON
+ ** SCR_REG_REG (gpreg, SCR_AND, 0xfe)
+ */
+ SCR_NO_OP,
+ 0,
+ /*
+ ** Clear SIGP.
+ */
+ SCR_FROM_REG (ctest2),
+ 0,
+ /*
+ ** Start the next job.
+ **
+ ** @DSA = start point for this job.
+ ** SCRATCHA = address of this job in the start queue.
+ **
+ ** We will restore startpos with SCRATCHA if we fails the
+ ** arbitration or if it is the idle job.
+ **
+ ** The below GETJOB_BEGIN to GETJOB_END section of SCRIPTS
+ ** is a critical path. If it is partially executed, it then
+ ** may happen that the job address is not yet in the DSA
+ ** and the the next queue position points to the next JOB.
+ */
+ SCR_LOAD_ABS (scratcha, 4),
+ PADDR (startpos),
+ SCR_LOAD_ABS (dsa, 4),
+ PADDR (startpos),
+ SCR_LOAD_REL (temp, 4),
+ 4,
+}/*-------------------------< GETJOB_BEGIN >------------------*/,{
+ SCR_STORE_ABS (temp, 4),
+ PADDR (startpos),
+ SCR_LOAD_REL (dsa, 4),
+ 0,
+}/*-------------------------< GETJOB_END >--------------------*/,{
+ SCR_LOAD_REL (temp, 4),
+ 0,
+ SCR_RETURN,
+ 0,
+
+}/*-------------------------< SELECT >----------------------*/,{
+ /*
+ ** DSA contains the address of a scheduled
+ ** data structure.
+ **
+ ** SCRATCHA contains the address of the start queue
+ ** entry which points to the next job.
+ **
+ ** Set Initiator mode.
+ **
+ ** (Target mode is left as an exercise for the reader)
+ */
+
+ SCR_CLR (SCR_TRG),
+ 0,
+ /*
+ ** And try to select this target.
+ */
+ SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select),
+ PADDR (ungetjob),
+ /*
+ ** Now there are 4 possibilities:
+ **
+ ** (1) The ncr looses arbitration.
+ ** This is ok, because it will try again,
+ ** when the bus becomes idle.
+ ** (But beware of the timeout function!)
+ **
+ ** (2) The ncr is reselected.
+ ** Then the script processor takes the jump
+ ** to the RESELECT label.
+ **
+ ** (3) The ncr wins arbitration.
+ ** Then it will execute SCRIPTS instruction until
+ ** the next instruction that checks SCSI phase.
+ ** Then will stop and wait for selection to be
+ ** complete or selection time-out to occur.
+ **
+ ** After having won arbitration, the ncr SCRIPTS
+ ** processor is able to execute instructions while
+ ** the SCSI core is performing SCSI selection. But
+ ** some script instruction that is not waiting for
+ ** a valid phase (or selection timeout) to occur
+ ** breaks the selection procedure, by probably
+ ** affecting timing requirements.
+ ** So we have to wait immediately for the next phase
+ ** or the selection to complete or time-out.
+ */
+}/*-------------------------< WF_SEL_DONE >----------------------*/,{
+ SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ SIR_SEL_ATN_NO_MSG_OUT,
+}/*-------------------------< SEND_IDENT >----------------------*/,{
+ /*
+ ** Selection complete.
+ ** Send the IDENTIFY and SIMPLE_TAG messages
+ ** (and the M_X_SYNC_REQ / M_X_WIDE_REQ message)
+ */
+ SCR_MOVE_TBL ^ SCR_MSG_OUT,
+ offsetof (struct dsb, smsg),
+}/*-------------------------< SELECT2 >----------------------*/,{
+ /*
+ ** load the savep (saved pointer) into
+ ** the actual data pointer.
+ */
+ SCR_LOAD_REL (temp, 4),
+ offsetof (struct ccb, phys.header.savep),
+ /*
+ ** Initialize the status registers
+ */
+ SCR_LOAD_REL (scr0, 4),
+ offsetof (struct ccb, phys.header.status),
+ /*
+ ** Anticipate the COMMAND phase.
+ ** This is the PHASE we expect at this point.
+ */
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_COMMAND)),
+ PADDR (sel_no_cmd),
+
+}/*-------------------------< COMMAND >--------------------*/,{
+ /*
+ ** ... and send the command
+ */
+ SCR_MOVE_TBL ^ SCR_COMMAND,
+ offsetof (struct dsb, cmd),
+
+}/*-----------------------< DISPATCH >----------------------*/,{
+ /*
+ ** MSG_IN is the only phase that shall be
+ ** entered at least once for each (re)selection.
+ ** So we test it first.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
+ PADDR (msg_in),
+ SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT)),
+ PADDR (dataphase),
+ SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN)),
+ PADDR (dataphase),
+ SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)),
+ PADDR (status),
+ SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)),
+ PADDR (command),
+ SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)),
+ PADDRH (msg_out),
+ /*
+ ** Discard one illegal phase byte, if required.
+ */
+ SCR_LOAD_REG (scratcha, XE_BAD_PHASE),
+ 0,
+ SCR_STORE_REL (scratcha, 1),
+ offsetof (struct ccb, xerr_status),
+ SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_OUT)),
+ 8,
+ SCR_MOVE_ABS (1) ^ SCR_ILG_OUT,
+ NADDR (scratch),
+ SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_IN)),
+ 8,
+ SCR_MOVE_ABS (1) ^ SCR_ILG_IN,
+ NADDR (scratch),
+ SCR_JUMP,
+ PADDR (dispatch),
+
+}/*---------------------< SEL_NO_CMD >----------------------*/,{
+ /*
+ ** The target does not switch to command
+ ** phase after IDENTIFY has been sent.
+ **
+ ** If it stays in MSG OUT phase send it
+ ** the IDENTIFY again.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
+ PADDRH (resend_ident),
+ /*
+ ** If target does not switch to MSG IN phase
+ ** and we sent a negotiation, assert the
+ ** failure immediately.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
+ PADDR (dispatch),
+ SCR_FROM_REG (HS_REG),
+ 0,
+ SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
+ SIR_NEGO_FAILED,
+ /*
+ ** Jump to dispatcher.
+ */
+ SCR_JUMP,
+ PADDR (dispatch),
+
+}/*-------------------------< INIT >------------------------*/,{
+ /*
+ ** Wait for the SCSI RESET signal to be
+ ** inactive before restarting operations,
+ ** since the chip may hang on SEL_ATN
+ ** if SCSI RESET is active.
+ */
+ SCR_FROM_REG (sstat0),
+ 0,
+ SCR_JUMPR ^ IFTRUE (MASK (IRST, IRST)),
+ -8,
+ SCR_JUMP,
+ PADDR (start),
+}/*-------------------------< CLRACK >----------------------*/,{
+ /*
+ ** Terminate possible pending message phase.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP,
+ PADDR (dispatch),
+
+}/*-------------------------< DATABREAK >-------------------*/,{
+ /*
+ ** Jump to dispatcher.
+ */
+ SCR_JUMP,
+ PADDR (dispatch),
+
+}/*-------------------------< DATAPHASE >------------------*/,{
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ SCR_REG_REG (HF_REG, SCR_OR, HF_DATA_ST),
+ 0,
+#endif
+ SCR_RETURN,
+ 0,
+
+}/*-------------------------< STATUS >--------------------*/,{
+ /*
+ ** get the status
+ */
+ SCR_MOVE_ABS (1) ^ SCR_STATUS,
+ NADDR (scratch),
+ /*
+ ** save status to scsi_status.
+ ** mark as complete.
+ */
+ SCR_TO_REG (SS_REG),
+ 0,
+ SCR_LOAD_REG (HS_REG, HS_COMPLETE),
+ 0,
+ SCR_JUMP,
+ PADDR (dispatch),
+}/*-------------------------< MSG_IN >--------------------*/,{
+ /*
+ ** Get the first byte of the message.
+ **
+ ** The script processor doesn't negate the
+ ** ACK signal after this transfer.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ NADDR (msgin[0]),
+}/*-------------------------< MSG_IN2 >--------------------*/,{
+ /*
+ ** Handle this message.
+ */
+ SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)),
+ PADDR (complete),
+ SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)),
+ PADDR (disconnect),
+ SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)),
+ PADDR (save_dp),
+ SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)),
+ PADDR (restore_dp),
+ SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)),
+ PADDRH (msg_extended),
+ SCR_JUMP ^ IFTRUE (DATA (M_NOOP)),
+ PADDR (clrack),
+ SCR_JUMP ^ IFTRUE (DATA (M_REJECT)),
+ PADDRH (msg_reject),
+ SCR_JUMP ^ IFTRUE (DATA (M_IGN_RESIDUE)),
+ PADDRH (msg_ign_residue),
+ /*
+ ** Rest of the messages left as
+ ** an exercise ...
+ **
+ ** Unimplemented messages:
+ ** fall through to MSG_BAD.
+ */
+}/*-------------------------< MSG_BAD >------------------*/,{
+ /*
+ ** unimplemented message - reject it.
+ */
+ SCR_INT,
+ SIR_REJECT_TO_SEND,
+ SCR_SET (SCR_ATN),
+ 0,
+ SCR_JUMP,
+ PADDR (clrack),
+
+}/*-------------------------< COMPLETE >-----------------*/,{
+ /*
+ ** Complete message.
+ **
+ ** Copy the data pointer to LASTP in header.
+ */
+ SCR_STORE_REL (temp, 4),
+ offsetof (struct ccb, phys.header.lastp),
+ /*
+ ** When we terminate the cycle by clearing ACK,
+ ** the target may disconnect immediately.
+ **
+ ** We don't want to be told of an
+ ** "unexpected disconnect",
+ ** so we disable this feature.
+ */
+ SCR_REG_REG (scntl2, SCR_AND, 0x7f),
+ 0,
+ /*
+ ** Terminate cycle ...
+ */
+ SCR_CLR (SCR_ACK|SCR_ATN),
+ 0,
+ /*
+ ** ... and wait for the disconnect.
+ */
+ SCR_WAIT_DISC,
+ 0,
+}/*-------------------------< COMPLETE2 >-----------------*/,{
+ /*
+ ** Save host status to header.
+ */
+ SCR_STORE_REL (scr0, 4),
+ offsetof (struct ccb, phys.header.status),
+
+ /*
+ ** If command resulted in not GOOD status,
+ ** call the C code if needed.
+ */
+ SCR_FROM_REG (SS_REG),
+ 0,
+ SCR_CALL ^ IFFALSE (DATA (S_GOOD)),
+ PADDRH (bad_status),
+
+}/*------------------------< DONE >-----------------*/,{
+ /*
+ ** Copy the DSA to the DONE QUEUE and
+ ** signal completion to the host.
+ ** If we are interrupted between DONE
+ ** and DONE_END, we must reset, otherwise
+ ** the completed CCB will be lost.
+ */
+ SCR_STORE_ABS (dsa, 4),
+ PADDR (saved_dsa),
+ SCR_LOAD_ABS (dsa, 4),
+ PADDR (done_pos),
+ SCR_LOAD_ABS (scratcha, 4),
+ PADDR(saved_dsa),
+ SCR_STORE_REL (scratcha, 4),
+ 0,
+ /*
+ ** The instruction below reads the DONE QUEUE next
+ ** free position from memory.
+ ** In addition it ensures that all PCI posted writes
+ ** are flushed and so the DSA value of the done
+ ** CCB is visible by the CPU before INTFLY is raised.
+ */
+ SCR_LOAD_REL (temp, 4),
+ 4,
+ SCR_INT_FLY,
+ 0,
+ SCR_STORE_ABS (temp, 4),
+ PADDR (done_pos),
+}/*------------------------< DONE_END >-----------------*/,{
+ SCR_JUMP,
+ PADDR (start),
+
+}/*-------------------------< SAVE_DP >------------------*/,{
+ /*
+ ** Clear ACK immediately.
+ ** No need to delay it.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ /*
+ ** Keep track we received a SAVE DP, so
+ ** we will switch to the other PM context
+ ** on the next PM since the DP may point
+ ** to the current PM context.
+ */
+ SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED),
+ 0,
+ /*
+ ** SAVE_DP message:
+ ** Copy the data pointer to SAVEP in header.
+ */
+ SCR_STORE_REL (temp, 4),
+ offsetof (struct ccb, phys.header.savep),
+ SCR_JUMP,
+ PADDR (dispatch),
+}/*-------------------------< RESTORE_DP >---------------*/,{
+ /*
+ ** RESTORE_DP message:
+ ** Copy SAVEP in header to actual data pointer.
+ */
+ SCR_LOAD_REL (temp, 4),
+ offsetof (struct ccb, phys.header.savep),
+ SCR_JUMP,
+ PADDR (clrack),
+
+}/*-------------------------< DISCONNECT >---------------*/,{
+ /*
+ ** DISCONNECTing ...
+ **
+ ** disable the "unexpected disconnect" feature,
+ ** and remove the ACK signal.
+ */
+ SCR_REG_REG (scntl2, SCR_AND, 0x7f),
+ 0,
+ SCR_CLR (SCR_ACK|SCR_ATN),
+ 0,
+ /*
+ ** Wait for the disconnect.
+ */
+ SCR_WAIT_DISC,
+ 0,
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ /*
+ ** Count the disconnects.
+ ** Disconnect without DATA PHASE having been
+ ** entered are counted in bits 8..15.
+ */
+ SCR_LOAD_REL (scratcha, 4),
+ offsetof (struct ccb, phys.num_disc),
+ SCR_FROM_REG (HF_REG),
+ 0,
+ SCR_JUMPR ^ IFTRUE (MASK (HF_DATA_ST, HF_DATA_ST)),
+ 8,
+ SCR_REG_REG (scratcha1, SCR_ADD, 0x01),
+ 0,
+ SCR_REG_REG (scratcha, SCR_ADD, 0x01),
+ 0,
+ SCR_STORE_REL (scratcha, 4),
+ offsetof (struct ccb, phys.num_disc),
+#endif
+ /*
+ ** Status is: DISCONNECTED.
+ */
+ SCR_LOAD_REG (HS_REG, HS_DISCONNECT),
+ 0,
+ /*
+ ** Save host status to header.
+ */
+ SCR_STORE_REL (scr0, 4),
+ offsetof (struct ccb, phys.header.status),
+ /*
+ ** If QUIRK_AUTOSAVE is set,
+ ** do an "save pointer" operation.
+ */
+ SCR_FROM_REG (QU_REG),
+ 0,
+ SCR_JUMP ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)),
+ PADDR (start),
+ /*
+ ** like SAVE_DP message:
+ ** Remember we saved the data pointer.
+ ** Copy data pointer to SAVEP in header.
+ */
+ SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED),
+ 0,
+ SCR_STORE_REL (temp, 4),
+ offsetof (struct ccb, phys.header.savep),
+ SCR_JUMP,
+ PADDR (start),
+
+}/*-------------------------< IDLE >------------------------*/,{
+ /*
+ ** Nothing to do?
+ ** Wait for reselect.
+ ** This NOP will be patched with LED OFF
+ ** SCR_REG_REG (gpreg, SCR_OR, 0x01)
+ */
+ SCR_NO_OP,
+ 0,
+}/*-------------------------< UNGETJOB >-----------------*/,{
+ /*
+ ** We are not able to restart the SCRIPTS if we are
+ ** interrupted and these instruction haven't been
+ ** all executed. BTW, this is very unlikely to
+ ** happen, but we check that from the C code.
+ */
+ SCR_LOAD_REG (dsa, 0xff),
+ 0,
+ SCR_STORE_ABS (scratcha, 4),
+ PADDR (startpos),
+}/*-------------------------< RESELECT >--------------------*/,{
+ /*
+ ** make the host status invalid.
+ */
+ SCR_CLR (SCR_TRG),
+ 0,
+ /*
+ ** Sleep waiting for a reselection.
+ ** If SIGP is set, special treatment.
+ **
+ ** Zu allem bereit ..
+ */
+ SCR_WAIT_RESEL,
+ PADDR(start),
+}/*-------------------------< RESELECTED >------------------*/,{
+ /*
+ ** This NOP will be patched with LED ON
+ ** SCR_REG_REG (gpreg, SCR_AND, 0xfe)
+ */
+ SCR_NO_OP,
+ 0,
+ /*
+ ** load the target id into the sdid
+ */
+ SCR_REG_SFBR (ssid, SCR_AND, 0x8F),
+ 0,
+ SCR_TO_REG (sdid),
+ 0,
+ /*
+ ** load the target control block address
+ */
+ SCR_LOAD_ABS (dsa, 4),
+ PADDR (targtbl),
+ SCR_SFBR_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_AND, 0x3c),
+ 0,
+ SCR_LOAD_REL (dsa, 4),
+ 0,
+ /*
+ ** Load the synchronous transfer registers.
+ */
+ SCR_LOAD_REL (scntl3, 1),
+ offsetof(struct tcb, wval),
+ SCR_LOAD_REL (sxfer, 1),
+ offsetof(struct tcb, sval),
+ /*
+ ** If MESSAGE IN phase as expected,
+ ** read the data directly from the BUS DATA lines.
+ ** This helps to support very old SCSI devices that
+ ** may reselect without sending an IDENTIFY.
+ */
+ SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ SIR_RESEL_NO_MSG_IN,
+ SCR_FROM_REG (sbdl),
+ 0,
+ /*
+ ** If message phase but not an IDENTIFY,
+ ** get some help from the C code.
+ ** Old SCSI device may behave so.
+ */
+ SCR_INT ^ IFFALSE (MASK (0x80, 0x80)),
+ SIR_RESEL_NO_IDENTIFY,
+ /*
+ ** It is an IDENTIFY message,
+ ** Load the LUN control block address.
+ ** Avoid nasty address calculation if LUN #0.
+ */
+ SCR_LOAD_REL (dsa, 4),
+ offsetof(struct tcb, b_luntbl),
+ SCR_JUMPR ^ IFTRUE (MASK (0x0, 0x3f)),
+ 24,
+ SCR_SFBR_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_AND, 0xfc),
+ 0,
+ SCR_LOAD_REL (dsa, 4),
+ 0,
+ /*
+ ** Load the reselect task action for this LUN.
+ ** Load the tasks DSA array for this LUN.
+ ** Call the action.
+ */
+ SCR_LOAD_REL (temp, 4),
+ offsetof(struct lcb, resel_task),
+ SCR_LOAD_REL (dsa, 4),
+ offsetof(struct lcb, b_tasktbl),
+ SCR_RETURN,
+ 0,
+
+}/*-------------------------< RESEL_TAG >-------------------*/,{
+ /*
+ ** Read IDENTIFY + SIMPLE + TAG using a single MOVE.
+ ** Agressive optimization, is'nt it?
+ ** No need to test the SIMPLE TAG message, since the
+ ** driver only supports conformant devices for tags. ;-)
+ */
+ SCR_MOVE_ABS (3) ^ SCR_MSG_IN,
+ NADDR (msgin),
+ /*
+ ** Read the TAG from the SIDL.
+ ** Still an aggressive optimization. ;-)
+ ** Compute the CCB indirect jump address which
+ ** is (#TAG*2 & 0xfc) due to tag numbering using
+ ** 1,3,5..MAXTAGS*2+1 actual values.
+ */
+ SCR_REG_SFBR (sidl, SCR_SHL, 0),
+ 0,
+ /*
+ ** Retrieve the DSA of this task.
+ ** JUMP indirectly to the restart point of the CCB.
+ */
+ SCR_SFBR_REG (dsa, SCR_AND, 0xfc),
+ 0,
+}/*-------------------------< RESEL_GO >-------------------*/,{
+ SCR_LOAD_REL (dsa, 4),
+ 0,
+ SCR_LOAD_REL (temp, 4),
+ offsetof(struct ccb, phys.header.go.restart),
+ SCR_RETURN,
+ 0,
+}/*-------------------------< RESEL_NOTAG >-------------------*/,{
+ /*
+ ** No tag expected.
+ ** Read an throw away the IDENTIFY.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ NADDR (msgin),
+ /*
+ ** JUMP indirectly to the restart point of the CCB.
+ */
+ SCR_JUMP,
+ PADDR (resel_go),
+
+}/*-------------------------< RESEL_DSA >-------------------*/,{
+ /*
+ ** Ack the IDENTIFY or TAG previously received.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ /*
+ ** load the savep (saved pointer) into
+ ** the actual data pointer.
+ */
+ SCR_LOAD_REL (temp, 4),
+ offsetof (struct ccb, phys.header.savep),
+ /*
+ ** Initialize the status registers
+ */
+ SCR_LOAD_REL (scr0, 4),
+ offsetof (struct ccb, phys.header.status),
+ /*
+ ** Jump to dispatcher.
+ */
+ SCR_JUMP,
+ PADDR (dispatch),
+
+}/*-------------------------< DATA_IN >--------------------*/,{
+/*
+** Because the size depends on the
+** #define MAX_SCATTERL parameter,
+** it is filled in at runtime.
+**
+** ##===========< i=0; i<MAX_SCATTERL >=========
+** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)),
+** || PADDR (databreak),
+** || SCR_MOVE_TBL ^ SCR_DATA_IN,
+** || offsetof (struct dsb, data[ i]),
+** ##==========================================
+**
+**---------------------------------------------------------
+*/
+0
+}/*-------------------------< DATA_IN2 >-------------------*/,{
+ SCR_CALL,
+ PADDR (databreak),
+ SCR_JUMP,
+ PADDRH (no_data),
+}/*-------------------------< DATA_OUT >--------------------*/,{
+/*
+** Because the size depends on the
+** #define MAX_SCATTERL parameter,
+** it is filled in at runtime.
+**
+** ##===========< i=0; i<MAX_SCATTERL >=========
+** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)),
+** || PADDR (databreak),
+** || SCR_MOVE_TBL ^ SCR_DATA_OUT,
+** || offsetof (struct dsb, data[ i]),
+** ##==========================================
+**
+**---------------------------------------------------------
+*/
+0
+}/*-------------------------< DATA_OUT2 >-------------------*/,{
+ SCR_CALL,
+ PADDR (databreak),
+ SCR_JUMP,
+ PADDRH (no_data),
+
+}/*-------------------------< PM0_DATA >--------------------*/,{
+ /*
+ ** Keep track we are executing the PM0 DATA
+ ** mini-script.
+ */
+ SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0),
+ 0,
+ /*
+ ** MOVE the data according to the actual
+ ** DATA direction.
+ */
+ SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_IN)),
+ 16,
+ SCR_MOVE_TBL ^ SCR_DATA_IN,
+ offsetof (struct ccb, phys.pm0.sg),
+ SCR_JUMPR,
+ 8,
+ SCR_MOVE_TBL ^ SCR_DATA_OUT,
+ offsetof (struct ccb, phys.pm0.sg),
+ /*
+ ** Clear the flag that told we were in
+ ** the PM0 DATA mini-script.
+ */
+ SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM0)),
+ 0,
+ /*
+ ** Return to the previous DATA script which
+ ** is guaranteed by design (if no bug) to be
+ ** the main DATA script for this transfer.
+ */
+ SCR_LOAD_REL (temp, 4),
+ offsetof (struct ccb, phys.pm0.ret),
+ SCR_RETURN,
+ 0,
+}/*-------------------------< PM1_DATA >--------------------*/,{
+ /*
+ ** Keep track we are executing the PM1 DATA
+ ** mini-script.
+ */
+ SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1),
+ 0,
+ /*
+ ** MOVE the data according to the actual
+ ** DATA direction.
+ */
+ SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_IN)),
+ 16,
+ SCR_MOVE_TBL ^ SCR_DATA_IN,
+ offsetof (struct ccb, phys.pm1.sg),
+ SCR_JUMPR,
+ 8,
+ SCR_MOVE_TBL ^ SCR_DATA_OUT,
+ offsetof (struct ccb, phys.pm1.sg),
+ /*
+ ** Clear the flag that told we were in
+ ** the PM1 DATA mini-script.
+ */
+ SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM1)),
+ 0,
+ /*
+ ** Return to the previous DATA script which
+ ** is guaranteed by design (if no bug) to be
+ ** the main DATA script for this transfer.
+ */
+ SCR_LOAD_REL (temp, 4),
+ offsetof (struct ccb, phys.pm1.ret),
+ SCR_RETURN,
+ 0,
+
+}/*-------------------------< SAVED_DSA >-------------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< DONE_POS >--------------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< STARTPOS >--------------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< TARGTBL >---------------------*/,{
+ SCR_DATA_ZERO,
+}/*--------------------------------------------------------*/
+};
+
+static struct scripth scripth0 __initdata = {
+/*------------------------< START64 >-----------------------*/{
+ /*
+ ** SCRIPT entry point for the 896.
+ ** For now, there is no specific stuff for that
+ ** chip at this point, but this may come.
+ */
+ SCR_JUMP,
+ PADDR (init),
+}/*------------------------< SELECT_NO_ATN >-----------------*/,{
+ /*
+ ** Set Initiator mode.
+ ** And try to select this target without ATN.
+ */
+
+ SCR_CLR (SCR_TRG),
+ 0,
+ SCR_SEL_TBL ^ offsetof (struct dsb, select),
+ PADDR (ungetjob),
+}/*------------------------< WF_SEL_DONE_NO_ATN >-----------------*/,{
+ /*
+ ** Wait immediately for the next phase or
+ ** the selection to complete or time-out.
+ */
+ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ 0,
+ SCR_JUMP,
+ PADDR (select2),
+
+}/*-------------------------< CANCEL >------------------------*/,{
+ /*
+ ** Load the host status.
+ */
+ SCR_LOAD_REG (HS_REG, HS_ABORTED),
+ 0,
+ SCR_JUMP,
+ PADDR (complete2),
+
+}/*-------------------------< MSG_REJECT >---------------*/,{
+ /*
+ ** If a negotiation was in progress,
+ ** negotiation failed.
+ ** Otherwise just make host log this message
+ */
+ SCR_FROM_REG (HS_REG),
+ 0,
+ SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)),
+ SIR_REJECT_RECEIVED,
+ SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
+ SIR_NEGO_FAILED,
+ SCR_JUMP,
+ PADDR (clrack),
+
+}/*-------------------------< MSG_IGN_RESIDUE >----------*/,{
+ /*
+ ** Terminate cycle
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ PADDR (dispatch),
+ /*
+ ** get residue size.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ NADDR (msgin[1]),
+ /*
+ ** Size is 0 .. ignore message.
+ */
+ SCR_JUMP ^ IFTRUE (DATA (0)),
+ PADDR (clrack),
+ /*
+ ** Size is not 1 .. have to interrupt.
+ */
+ SCR_JUMPR ^ IFFALSE (DATA (1)),
+ 40,
+ /*
+ ** Check for residue byte in swide register
+ */
+ SCR_FROM_REG (scntl2),
+ 0,
+ SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)),
+ 16,
+ /*
+ ** There IS data in the swide register.
+ ** Discard it.
+ */
+ SCR_REG_REG (scntl2, SCR_OR, WSR),
+ 0,
+ SCR_JUMP,
+ PADDR (clrack),
+ /*
+ ** Load again the size to the sfbr register.
+ */
+ SCR_FROM_REG (scratcha),
+ 0,
+ SCR_INT,
+ SIR_IGN_RESIDUE,
+ SCR_JUMP,
+ PADDR (clrack),
+
+}/*-------------------------< MSG_EXTENDED >-------------*/,{
+ /*
+ ** Terminate cycle
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ PADDR (dispatch),
+ /*
+ ** get length.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ NADDR (msgin[1]),
+ /*
+ */
+ SCR_JUMP ^ IFTRUE (DATA (3)),
+ PADDRH (msg_ext_3),
+ SCR_JUMP ^ IFFALSE (DATA (2)),
+ PADDR (msg_bad),
+}/*-------------------------< MSG_EXT_2 >----------------*/,{
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ PADDR (dispatch),
+ /*
+ ** get extended message code.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ NADDR (msgin[2]),
+ SCR_JUMP ^ IFTRUE (DATA (M_X_WIDE_REQ)),
+ PADDRH (msg_wdtr),
+ /*
+ ** unknown extended message
+ */
+ SCR_JUMP,
+ PADDR (msg_bad)
+}/*-------------------------< MSG_WDTR >-----------------*/,{
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ PADDR (dispatch),
+ /*
+ ** get data bus width
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ NADDR (msgin[3]),
+ /*
+ ** let the host do the real work.
+ */
+ SCR_INT,
+ SIR_NEGO_WIDE,
+ /*
+ ** let the target fetch our answer.
+ */
+ SCR_SET (SCR_ATN),
+ 0,
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ PADDRH (nego_bad_phase),
+
+}/*-------------------------< SEND_WDTR >----------------*/,{
+ /*
+ ** Send the M_X_WIDE_REQ
+ */
+ SCR_MOVE_ABS (4) ^ SCR_MSG_OUT,
+ NADDR (msgout),
+ SCR_JUMP,
+ PADDRH (msg_out_done),
+
+}/*-------------------------< MSG_EXT_3 >----------------*/,{
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ PADDR (dispatch),
+ /*
+ ** get extended message code.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ NADDR (msgin[2]),
+ SCR_JUMP ^ IFTRUE (DATA (M_X_SYNC_REQ)),
+ PADDRH (msg_sdtr),
+ /*
+ ** unknown extended message
+ */
+ SCR_JUMP,
+ PADDR (msg_bad)
+
+}/*-------------------------< MSG_SDTR >-----------------*/,{
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ PADDR (dispatch),
+ /*
+ ** get period and offset
+ */
+ SCR_MOVE_ABS (2) ^ SCR_MSG_IN,
+ NADDR (msgin[3]),
+ /*
+ ** let the host do the real work.
+ */
+ SCR_INT,
+ SIR_NEGO_SYNC,
+ /*
+ ** let the target fetch our answer.
+ */
+ SCR_SET (SCR_ATN),
+ 0,
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ PADDRH (nego_bad_phase),
+
+}/*-------------------------< SEND_SDTR >-------------*/,{
+ /*
+ ** Send the M_X_SYNC_REQ
+ */
+ SCR_MOVE_ABS (5) ^ SCR_MSG_OUT,
+ NADDR (msgout),
+ SCR_JUMP,
+ PADDRH (msg_out_done),
+
+}/*-------------------------< NEGO_BAD_PHASE >------------*/,{
+ SCR_INT,
+ SIR_NEGO_PROTO,
+ SCR_JUMP,
+ PADDR (dispatch),
+
+}/*-------------------------< MSG_OUT_ABORT >-------------*/,{
+ /*
+ ** After ABORT message,
+ **
+ ** expect an immediate disconnect, ...
+ */
+ SCR_REG_REG (scntl2, SCR_AND, 0x7f),
+ 0,
+ SCR_CLR (SCR_ACK|SCR_ATN),
+ 0,
+ SCR_WAIT_DISC,
+ 0,
+ SCR_INT,
+ SIR_MSG_OUT_DONE,
+ /*
+ ** ... and set the status to "ABORTED"
+ */
+ SCR_LOAD_REG (HS_REG, HS_ABORTED),
+ 0,
+ SCR_JUMP,
+ PADDR (complete2),
+
+}/*-------------------------< MSG_OUT >-------------------*/,{
+ /*
+ ** The target requests a message.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
+ NADDR (msgout),
+ /*
+ ** If it was no ABORT message ...
+ */
+ SCR_JUMP ^ IFTRUE (DATA (M_ABORT)),
+ PADDRH (msg_out_abort),
+ /*
+ ** ... wait for the next phase
+ ** if it's a message out, send it again, ...
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
+ PADDRH (msg_out),
+}/*-------------------------< MSG_OUT_DONE >--------------*/,{
+ /*
+ ** ... else clear the message ...
+ */
+ SCR_INT,
+ SIR_MSG_OUT_DONE,
+ /*
+ ** ... and process the next phase
+ */
+ SCR_JUMP,
+ PADDR (dispatch),
+
+}/*-------------------------< NO_DATA >--------------------*/,{
+ /*
+ ** The target wants to tranfer too much data
+ ** or in the wrong direction.
+ ** Remember that in extended error.
+ */
+ SCR_LOAD_REG (scratcha, XE_EXTRA_DATA),
+ 0,
+ SCR_STORE_REL (scratcha, 1),
+ offsetof (struct ccb, xerr_status),
+ /*
+ ** Discard one data byte, if required.
+ */
+ SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)),
+ 8,
+ SCR_MOVE_ABS (1) ^ SCR_DATA_OUT,
+ NADDR (scratch),
+ SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)),
+ 8,
+ SCR_MOVE_ABS (1) ^ SCR_DATA_IN,
+ NADDR (scratch),
+ /*
+ ** .. and repeat as required.
+ */
+ SCR_CALL,
+ PADDR (databreak),
+ SCR_JUMP,
+ PADDRH (no_data),
+
+#if MAX_SCATTERH != 0
+
+}/*-------------------------< HDATA_IN >-------------------*/,{
+/*
+** Because the size depends on the
+** #define MAX_SCATTERH parameter,
+** it is filled in at runtime.
+**
+** ##==< i=MAX_SCATTERL; i<MAX_SCATTERL+MAX_SCATTERH >==
+** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)),
+** || PADDR (databreak),
+** || SCR_MOVE_TBL ^ SCR_DATA_IN,
+** || offsetof (struct dsb, data[ i]),
+** ##===================================================
+**
+**---------------------------------------------------------
+*/
+0
+}/*-------------------------< HDATA_IN2 >------------------*/,{
+ SCR_JUMP,
+ PADDR (data_in),
+
+}/*-------------------------< HDATA_OUT >-------------------*/,{
+/*
+** Because the size depends on the
+** #define MAX_SCATTERH parameter,
+** it is filled in at runtime.
+**
+** ##==< i=MAX_SCATTERL; i<MAX_SCATTERL+MAX_SCATTERH >==
+** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)),
+** || PADDR (databreak),
+** || SCR_MOVE_TBL ^ SCR_DATA_OUT,
+** || offsetof (struct dsb, data[ i]),
+** ##===================================================
+**
+**---------------------------------------------------------
+*/
+0
+}/*-------------------------< HDATA_OUT2 >------------------*/,{
+ SCR_JUMP,
+ PADDR (data_out),
+
+#endif /* MAX_SCATTERH */
+
+}/*-------------------------< ABORT_RESEL >----------------*/,{
+ SCR_SET (SCR_ATN),
+ 0,
+ SCR_CLR (SCR_ACK),
+ 0,
+ /*
+ ** send the abort/abortag/reset message
+ ** we expect an immediate disconnect
+ */
+ SCR_REG_REG (scntl2, SCR_AND, 0x7f),
+ 0,
+ SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
+ NADDR (msgout),
+ SCR_CLR (SCR_ACK|SCR_ATN),
+ 0,
+ SCR_WAIT_DISC,
+ 0,
+ SCR_INT,
+ SIR_RESEL_ABORTED,
+ SCR_JUMP,
+ PADDR (start),
+}/*-------------------------< RESEND_IDENT >-------------------*/,{
+ /*
+ ** The target stays in MSG OUT phase after having acked
+ ** Identify [+ Tag [+ Extended message ]]. Targets shall
+ ** behave this way on parity error.
+ ** We must send it again all the messages.
+ */
+ SCR_SET (SCR_ATN), /* Shall be asserted 2 deskew delays before the */
+ 0, /* 1rst ACK = 90 ns. Hope the NCR is'nt too fast */
+ SCR_JUMP,
+ PADDR (send_ident),
+}/*-------------------------< IDENT_BREAK >-------------------*/,{
+ SCR_CLR (SCR_ATN),
+ 0,
+ SCR_JUMP,
+ PADDR (select2),
+}/*-------------------------< IDENT_BREAK_ATN >----------------*/,{
+ SCR_SET (SCR_ATN),
+ 0,
+ SCR_JUMP,
+ PADDR (select2),
+}/*-------------------------< SDATA_IN >-------------------*/,{
+ SCR_MOVE_TBL ^ SCR_DATA_IN,
+ offsetof (struct dsb, sense),
+ SCR_CALL,
+ PADDR (databreak),
+ SCR_JUMP,
+ PADDRH (no_data),
+
+}/*-------------------------< DATA_IO >--------------------*/,{
+ /*
+ ** We jump here if the data direction was unknown at the
+ ** time we had to queue the command to the scripts processor.
+ ** Pointers had been set as follow in this situation:
+ ** savep --> DATA_IO
+ ** lastp --> start pointer when DATA_IN
+ ** goalp --> goal pointer when DATA_IN
+ ** wlastp --> start pointer when DATA_OUT
+ ** wgoalp --> goal pointer when DATA_OUT
+ ** This script sets savep/lastp/goalp according to the
+ ** direction chosen by the target.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)),
+ PADDRH(data_io_out),
+}/*-------------------------< DATA_IO_COM >-----------------*/,{
+ /*
+ ** Direction is DATA IN.
+ ** Warning: we jump here, even when phase is DATA OUT.
+ */
+ SCR_LOAD_REL (scratcha, 4),
+ offsetof (struct ccb, phys.header.lastp),
+ SCR_STORE_REL (scratcha, 4),
+ offsetof (struct ccb, phys.header.savep),
+
+ /*
+ ** Jump to the SCRIPTS according to actual direction.
+ */
+ SCR_LOAD_REL (temp, 4),
+ offsetof (struct ccb, phys.header.savep),
+ SCR_RETURN,
+ 0,
+}/*-------------------------< DATA_IO_OUT >-----------------*/,{
+ /*
+ ** Direction is DATA OUT.
+ */
+ SCR_LOAD_REL (scratcha, 4),
+ offsetof (struct ccb, phys.header.wlastp),
+ SCR_STORE_REL (scratcha, 4),
+ offsetof (struct ccb, phys.header.lastp),
+ SCR_LOAD_REL (scratcha, 4),
+ offsetof (struct ccb, phys.header.wgoalp),
+ SCR_STORE_REL (scratcha, 4),
+ offsetof (struct ccb, phys.header.goalp),
+ SCR_JUMP,
+ PADDRH(data_io_com),
+
+}/*-------------------------< BAD_IDENTIFY >---------------*/,{
+ /*
+ ** If message phase but not an IDENTIFY,
+ ** get some help from the C code.
+ ** Old SCSI device may behave so.
+ */
+ SCR_JUMPR ^ IFTRUE (MASK (0x80, 0x80)),
+ 16,
+ SCR_INT,
+ SIR_RESEL_NO_IDENTIFY,
+ SCR_JUMP,
+ PADDRH (abort_resel),
+ /*
+ ** Message is an IDENTIFY, but lun is unknown.
+ ** Read the message, since we got it directly
+ ** from the SCSI BUS data lines.
+ ** Signal problem to C code for logging the event.
+ ** Send a M_ABORT to clear all pending tasks.
+ */
+ SCR_INT,
+ SIR_RESEL_BAD_LUN,
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ NADDR (msgin),
+ SCR_JUMP,
+ PADDRH (abort_resel),
+}/*-------------------------< BAD_I_T_L >------------------*/,{
+ /*
+ ** We donnot have a task for that I_T_L.
+ ** Signal problem to C code for logging the event.
+ ** Send a M_ABORT message.
+ */
+ SCR_INT,
+ SIR_RESEL_BAD_I_T_L,
+ SCR_JUMP,
+ PADDRH (abort_resel),
+}/*-------------------------< BAD_I_T_L_Q >----------------*/,{
+ /*
+ ** We donnot have a task that matches the tag.
+ ** Signal problem to C code for logging the event.
+ ** Send a M_ABORTTAG message.
+ */
+ SCR_INT,
+ SIR_RESEL_BAD_I_T_L_Q,
+ SCR_JUMP,
+ PADDRH (abort_resel),
+}/*-------------------------< BAD_STATUS >-----------------*/,{
+ /*
+ ** If command resulted in either QUEUE FULL,
+ ** CHECK CONDITION or COMMAND TERMINATED,
+ ** call the C code.
+ */
+ SCR_LOAD_ABS (scratcha, 4),
+ PADDR (startpos),
+ SCR_INT ^ IFTRUE (DATA (S_QUEUE_FULL)),
+ SIR_BAD_STATUS,
+ SCR_INT ^ IFTRUE (DATA (S_CHECK_COND)),
+ SIR_BAD_STATUS,
+ SCR_INT ^ IFTRUE (DATA (S_TERMINATED)),
+ SIR_BAD_STATUS,
+ SCR_RETURN,
+ 0,
+
+}/*-------------------------< TWEAK_PMJ >------------------*/,{
+ /*
+ ** Disable PM handling from SCRIPTS for the data phase
+ ** and so force PM to be handled from C code if HF_PM_TO_C
+ ** flag is set.
+ */
+ SCR_FROM_REG(HF_REG),
+ 0,
+ SCR_JUMPR ^ IFTRUE (MASK (HF_PM_TO_C, HF_PM_TO_C)),
+ 16,
+ SCR_REG_REG (ccntl0, SCR_OR, ENPMJ),
+ 0,
+ SCR_RETURN,
+ 0,
+ SCR_REG_REG (ccntl0, SCR_AND, (~ENPMJ)),
+ 0,
+ SCR_RETURN,
+ 0,
+
+}/*-------------------------< PM_HANDLE >------------------*/,{
+ /*
+ ** Phase mismatch handling.
+ **
+ ** Since we have to deal with 2 SCSI data pointers
+ ** (current and saved), we need at least 2 contexts.
+ ** Each context (pm0 and pm1) has a saved area, a
+ ** SAVE mini-script and a DATA phase mini-script.
+ */
+ /*
+ ** Get the PM handling flags.
+ */
+ SCR_FROM_REG (HF_REG),
+ 0,
+ /*
+ ** If no flags (1rst PM for example), avoid
+ ** all the below heavy flags testing.
+ ** This makes the normal case a bit faster.
+ */
+ SCR_JUMP ^ IFTRUE (MASK (0, (HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED))),
+ PADDRH (pm_handle1),
+ /*
+ ** If we received a SAVE DP, switch to the
+ ** other PM context since the savep may point
+ ** to the current PM context.
+ */
+ SCR_JUMPR ^ IFFALSE (MASK (HF_DP_SAVED, HF_DP_SAVED)),
+ 8,
+ SCR_REG_REG (sfbr, SCR_XOR, HF_ACT_PM),
+ 0,
+ /*
+ ** If we have been interrupt in a PM DATA mini-script,
+ ** we take the return address from the corresponding
+ ** saved area.
+ ** This ensure the return address always points to the
+ ** main DATA script for this transfer.
+ */
+ SCR_JUMP ^ IFTRUE (MASK (0, (HF_IN_PM0 | HF_IN_PM1))),
+ PADDRH (pm_handle1),
+ SCR_JUMPR ^ IFFALSE (MASK (HF_IN_PM0, HF_IN_PM0)),
+ 16,
+ SCR_LOAD_REL (ia, 4),
+ offsetof(struct ccb, phys.pm0.ret),
+ SCR_JUMP,
+ PADDRH (pm_save),
+ SCR_LOAD_REL (ia, 4),
+ offsetof(struct ccb, phys.pm1.ret),
+ SCR_JUMP,
+ PADDRH (pm_save),
+}/*-------------------------< PM_HANDLE1 >-----------------*/,{
+ /*
+ ** Normal case.
+ ** Update the return address so that it
+ ** will point after the interrupted MOVE.
+ */
+ SCR_REG_REG (ia, SCR_ADD, 8),
+ 0,
+ SCR_REG_REG (ia1, SCR_ADDC, 0),
+ 0,
+}/*-------------------------< PM_SAVE >--------------------*/,{
+ /*
+ ** Clear all the flags that told us if we were
+ ** interrupted in a PM DATA mini-script and/or
+ ** we received a SAVE DP.
+ */
+ SCR_SFBR_REG (HF_REG, SCR_AND, (~(HF_IN_PM0|HF_IN_PM1|HF_DP_SAVED))),
+ 0,
+ /*
+ ** Choose the current PM context.
+ */
+ SCR_JUMP ^ IFTRUE (MASK (HF_ACT_PM, HF_ACT_PM)),
+ PADDRH (pm1_save),
+}/*-------------------------< PM0_SAVE >-------------------*/,{
+ /*
+ ** Save the remaining byte count, the updated
+ ** address and the return address.
+ */
+ SCR_STORE_REL (rbc, 4),
+ offsetof(struct ccb, phys.pm0.sg.size),
+ SCR_STORE_REL (ua, 4),
+ offsetof(struct ccb, phys.pm0.sg.addr),
+ SCR_STORE_REL (ia, 4),
+ offsetof(struct ccb, phys.pm0.ret),
+ /*
+ ** Set the current pointer at the PM0 DATA mini-script.
+ */
+ SCR_LOAD_ABS (temp, 4),
+ PADDRH (pm0_data_addr),
+ SCR_JUMP,
+ PADDR (databreak),
+}/*-------------------------< PM1_SAVE >-------------------*/,{
+ /*
+ ** Save the remaining byte count, the updated
+ ** address and the return address.
+ */
+ SCR_STORE_REL (rbc, 4),
+ offsetof(struct ccb, phys.pm1.sg.size),
+ SCR_STORE_REL (ua, 4),
+ offsetof(struct ccb, phys.pm1.sg.addr),
+ SCR_STORE_REL (ia, 4),
+ offsetof(struct ccb, phys.pm1.ret),
+ /*
+ ** Set the current pointer at the PM1 DATA mini-script.
+ */
+ SCR_LOAD_ABS (temp, 4),
+ PADDRH (pm1_data_addr),
+ SCR_JUMP,
+ PADDR (databreak),
+}/*-------------------------< PM0_DATA_ADDR >---------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< PM1_DATA_ADDR >---------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< START_RAM >-------------------*/,{
+ /*
+ ** Load the script into on-chip RAM,
+ ** and jump to start point.
+ */
+ SCR_COPY (sizeof (struct script)),
+}/*-------------------------< SCRIPT0_BA >--------------------*/,{
+ 0,
+ PADDR (start),
+ SCR_JUMP,
+ PADDR (init),
+
+}/*-------------------------< START_RAM64 >--------------------*/,{
+ /*
+ ** Load the RAM and start for 64 bit PCI (896).
+ ** Both scripts (script and scripth) are loaded into
+ ** the RAM which is 8K (4K for 825A/875/895).
+ ** We also need to load some 32-63 bit segments
+ ** address of the SCRIPTS processor.
+ ** LOAD/STORE ABSOLUTE always refers to on-chip RAM
+ ** in our implementation. The main memory is
+ ** accessed using LOAD/STORE DSA RELATIVE.
+ */
+ SCR_LOAD_REL (mmws, 4),
+ offsetof (struct ncb, scr_ram_seg),
+ SCR_COPY (sizeof(struct script)),
+}/*-------------------------< SCRIPT0_BA64 >--------------------*/,{
+ 0,
+ PADDR (start),
+ SCR_COPY (sizeof(struct scripth)),
+}/*-------------------------< SCRIPTH0_BA64 >--------------------*/,{
+ 0,
+ PADDRH (start64),
+ SCR_LOAD_REL (mmrs, 4),
+ offsetof (struct ncb, scr_ram_seg),
+ SCR_JUMP64,
+ PADDRH (start64),
+}/*-------------------------< RAM_SEG64 >--------------------*/,{
+ 0,
+}/*-------------------------< SNOOPTEST >-------------------*/,{
+ /*
+ ** Read the variable.
+ */
+ SCR_LOAD_REL (scratcha, 4),
+ offsetof(struct ncb, ncr_cache),
+ SCR_STORE_REL (temp, 4),
+ offsetof(struct ncb, ncr_cache),
+ SCR_LOAD_REL (temp, 4),
+ offsetof(struct ncb, ncr_cache),
+}/*-------------------------< SNOOPEND >-------------------*/,{
+ /*
+ ** And stop.
+ */
+ SCR_INT,
+ 99,
+}/*--------------------------------------------------------*/
+};
+
+/*==========================================================
+**
+**
+** Fill in #define dependent parts of the script
+**
+**
+**==========================================================
+*/
+
+__initfunc(
+void ncr_script_fill (struct script * scr, struct scripth * scrh)
+)
+{
+ int i;
+ ncrcmd *p;
+
+#if MAX_SCATTERH != 0
+ p = scrh->hdata_in;
+ for (i=0; i<MAX_SCATTERH; i++) {
+#if SCR_SG_SIZE == 4
+ *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN));
+ *p++ =PADDR (databreak);
+#endif
+ *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN;
+ *p++ =offsetof (struct dsb, data[i]);
+ };
+ assert ((u_long)p == (u_long)&scrh->hdata_in + sizeof (scrh->hdata_in));
+#endif
+
+ p = scr->data_in;
+ for (i=MAX_SCATTERH; i<MAX_SCATTERH+MAX_SCATTERL; i++) {
+#if SCR_SG_SIZE == 4
+ *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN));
+ *p++ =PADDR (databreak);
+#endif
+ *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN;
+ *p++ =offsetof (struct dsb, data[i]);
+ };
+ assert ((u_long)p == (u_long)&scr->data_in + sizeof (scr->data_in));
+
+#if MAX_SCATTERH != 0
+ p = scrh->hdata_out;
+ for (i=0; i<MAX_SCATTERH; i++) {
+#if SCR_SG_SIZE == 4
+ *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT));
+ *p++ =PADDR (databreak);
+#endif
+ *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT;
+ *p++ =offsetof (struct dsb, data[i]);
+ };
+ assert ((u_long)p==(u_long)&scrh->hdata_out + sizeof (scrh->hdata_out));
+#endif
+
+ p = scr->data_out;
+ for (i=MAX_SCATTERH; i<MAX_SCATTERH+MAX_SCATTERL; i++) {
+#if SCR_SG_SIZE == 4
+ *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT));
+ *p++ =PADDR (databreak);
+#endif
+ *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT;
+ *p++ =offsetof (struct dsb, data[i]);
+ };
+
+ assert ((u_long)p == (u_long)&scr->data_out + sizeof (scr->data_out));
+}
+
+/*==========================================================
+**
+**
+** Copy and rebind a script.
+**
+**
+**==========================================================
+*/
+
+__initfunc(
+static void ncr_script_copy_and_bind (ncb_p np,ncrcmd *src,ncrcmd *dst,int len)
+)
+{
+ ncrcmd opcode, new, old, tmp1, tmp2;
+ ncrcmd *start, *end;
+ int relocs;
+ int opchanged = 0;
+
+ start = src;
+ end = src + len/4;
+
+ while (src < end) {
+
+ opcode = *src++;
+ *dst++ = cpu_to_scr(opcode);
+
+ /*
+ ** If we forget to change the length
+ ** in struct script, a field will be
+ ** padded with 0. This is an illegal
+ ** command.
+ */
+
+ if (opcode == 0) {
+ printk (KERN_INFO "%s: ERROR0 IN SCRIPT at %d.\n",
+ ncr_name(np), (int) (src-start-1));
+ MDELAY (10000);
+ continue;
+ };
+
+ /*
+ ** We use the bogus value 0xf00ff00f ;-)
+ ** to reserve data area in SCRIPTS.
+ */
+ if (opcode == SCR_DATA_ZERO) {
+ dst[-1] = 0;
+ continue;
+ }
+
+ if (DEBUG_FLAGS & DEBUG_SCRIPT)
+ printk (KERN_INFO "%p: <%x>\n",
+ (src-1), (unsigned)opcode);
+
+ /*
+ ** We don't have to decode ALL commands
+ */
+ switch (opcode >> 28) {
+
+ case 0xf:
+ /*
+ ** LOAD / STORE DSA relative, don't relocate.
+ */
+ relocs = 0;
+ break;
+ case 0xe:
+ /*
+ ** LOAD / STORE absolute.
+ */
+ relocs = 1;
+ break;
+ case 0xc:
+ /*
+ ** COPY has TWO arguments.
+ */
+ relocs = 2;
+ tmp1 = src[0];
+ tmp2 = src[1];
+#ifdef RELOC_KVAR
+ if ((tmp1 & RELOC_MASK) == RELOC_KVAR)
+ tmp1 = 0;
+ if ((tmp2 & RELOC_MASK) == RELOC_KVAR)
+ tmp2 = 0;
+#endif
+ if ((tmp1 ^ tmp2) & 3) {
+ printk (KERN_ERR"%s: ERROR1 IN SCRIPT at %d.\n",
+ ncr_name(np), (int) (src-start-1));
+ MDELAY (1000);
+ }
+ /*
+ ** If PREFETCH feature not enabled, remove
+ ** the NO FLUSH bit if present.
+ */
+ if ((opcode & SCR_NO_FLUSH) &&
+ !(np->features & FE_PFEN)) {
+ dst[-1] = cpu_to_scr(opcode & ~SCR_NO_FLUSH);
+ ++opchanged;
+ }
+ break;
+
+ case 0x0:
+ /*
+ ** MOVE (absolute address)
+ */
+ relocs = 1;
+ break;
+
+ case 0x8:
+ /*
+ ** JUMP / CALL
+ ** dont't relocate if relative :-)
+ */
+ if (opcode & 0x00800000)
+ relocs = 0;
+ else if ((opcode & 0xf8400000) == 0x80400000)/*JUMP64*/
+ relocs = 2;
+ else
+ relocs = 1;
+ break;
+
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ relocs = 1;
+ break;
+
+ default:
+ relocs = 0;
+ break;
+ };
+
+ if (!relocs) {
+ *dst++ = cpu_to_scr(*src++);
+ continue;
+ }
+ while (relocs--) {
+ old = *src++;
+
+ switch (old & RELOC_MASK) {
+ case RELOC_REGISTER:
+ new = (old & ~RELOC_MASK) + pcivtobus(np->base_ba);
+ break;
+ case RELOC_LABEL:
+ new = (old & ~RELOC_MASK) + np->p_script;
+ break;
+ case RELOC_LABELH:
+ new = (old & ~RELOC_MASK) + np->p_scripth;
+ break;
+ case RELOC_SOFTC:
+ new = (old & ~RELOC_MASK) + vtobus(np);
+ break;
+#ifdef RELOC_KVAR
+ case RELOC_KVAR:
+ if (((old & ~RELOC_MASK) < SCRIPT_KVAR_FIRST) ||
+ ((old & ~RELOC_MASK) > SCRIPT_KVAR_LAST))
+ panic("ncr KVAR out of range");
+ new = vtobus(script_kvars[old & ~RELOC_MASK]);
+#endif
+ break;
+ case 0:
+ /* Don't relocate a 0 address. */
+ if (old == 0) {
+ new = old;
+ break;
+ }
+ /* fall through */
+ default:
+ panic("ncr_script_copy_and_bind: "
+ "weird relocation %x\n", old);
+ break;
+ }
+
+ *dst++ = cpu_to_scr(new);
+ }
+ };
+}
+
+/*==========================================================
+**
+**
+** Auto configuration: attach and init a host adapter.
+**
+**
+**==========================================================
+*/
+
+/*
+** Linux host data structure.
+*/
+
+struct host_data {
+ struct ncb *ncb;
+};
+
+/*
+** Print something which allows to retrieve the controler type, unit,
+** target, lun concerned by a kernel message.
+*/
+
+static void PRINT_TARGET(ncb_p np, int target)
+{
+ printk(KERN_INFO "%s-<%d,*>: ", ncr_name(np), target);
+}
+
+static void PRINT_LUN(ncb_p np, int target, int lun)
+{
+ printk(KERN_INFO "%s-<%d,%d>: ", ncr_name(np), target, lun);
+}
+
+static void PRINT_ADDR(Scsi_Cmnd *cmd)
+{
+ struct host_data *host_data = (struct host_data *) cmd->host->hostdata;
+ PRINT_LUN(host_data->ncb, cmd->target, cmd->lun);
+}
+
+/*==========================================================
+**
+** NCR chip clock divisor table.
+** Divisors are multiplied by 10,000,000 in order to make
+** calculations more simple.
+**
+**==========================================================
+*/
+
+#define _5M 5000000
+static u_long div_10M[] =
+ {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};
+
+
+/*===============================================================
+**
+** Prepare io register values used by ncr_init() according
+** to selected and supported features.
+**
+** NCR chips allow burst lengths of 2, 4, 8, 16, 32, 64, 128
+** transfers. 32,64,128 are only supported by 825A, 875, 895
+** and 896 chips.
+** We use log base 2 (burst length) as internal code, with
+** value 0 meaning "burst disabled".
+**
+**===============================================================
+*/
+
+/*
+ * Burst length from burst code.
+ */
+#define burst_length(bc) (!(bc))? 0 : 1 << (bc)
+
+/*
+ * Burst code from io register bits.
+ */
+#define burst_code(dmode, ctest4, ctest5) \
+ (ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1
+
+/*
+ * Set initial io register bits from burst code.
+ */
+static inline void ncr_init_burst(ncb_p np, u_char bc)
+{
+ np->rv_ctest4 &= ~0x80;
+ np->rv_dmode &= ~(0x3 << 6);
+ np->rv_ctest5 &= ~0x4;
+
+ if (!bc) {
+ np->rv_ctest4 |= 0x80;
+ }
+ else {
+ --bc;
+ np->rv_dmode |= ((bc & 0x3) << 6);
+ np->rv_ctest5 |= (bc & 0x4);
+ }
+}
+
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+
+/*
+** Get target set-up from Symbios format NVRAM.
+*/
+
+__initfunc(
+static void
+ ncr_Symbios_setup_target(ncb_p np, int target, Symbios_nvram *nvram)
+)
+{
+ tcb_p tp = &np->target[target];
+ Symbios_target *tn = &nvram->target[target];
+
+ tp->usrsync = tn->sync_period ? (tn->sync_period + 3) / 4 : 255;
+ tp->usrwide = tn->bus_width == 0x10 ? 1 : 0;
+ tp->usrtags =
+ (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? SCSI_NCR_MAX_TAGS : 0;
+
+ if (!(tn->flags & SYMBIOS_DISCONNECT_ENABLE))
+ tp->usrflag |= UF_NODISC;
+ if (!(tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME))
+ tp->usrflag |= UF_NOSCAN;
+}
+
+/*
+** Get target set-up from Tekram format NVRAM.
+*/
+
+__initfunc(
+static void
+ ncr_Tekram_setup_target(ncb_p np, int target, Tekram_nvram *nvram)
+)
+{
+ tcb_p tp = &np->target[target];
+ struct Tekram_target *tn = &nvram->target[target];
+ int i;
+
+ if (tn->flags & TEKRAM_SYNC_NEGO) {
+ i = tn->sync_index & 0xf;
+ tp->usrsync = i < 12 ? Tekram_sync[i] : 255;
+ }
+
+ tp->usrwide = (tn->flags & TEKRAM_WIDE_NEGO) ? 1 : 0;
+
+ if (tn->flags & TEKRAM_TAGGED_COMMANDS) {
+ tp->usrtags = 2 << nvram->max_tags_index;
+ }
+
+ if (!(tn->flags & TEKRAM_DISCONNECT_ENABLE))
+ tp->usrflag = UF_NODISC;
+
+ /* If any device does not support parity, we will not use this option */
+ if (!(tn->flags & TEKRAM_PARITY_CHECK))
+ np->rv_scntl0 &= ~0x0a; /* SCSI parity checking disabled */
+}
+#endif /* SCSI_NCR_NVRAM_SUPPORT */
+
+__initfunc(
+static int ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
+)
+{
+ u_char burst_max;
+ u_long period;
+ int i;
+
+ /*
+ ** Save assumed BIOS setting
+ */
+
+ np->sv_scntl0 = INB(nc_scntl0) & 0x0a;
+ np->sv_scntl3 = INB(nc_scntl3) & 0x07;
+ np->sv_dmode = INB(nc_dmode) & 0xce;
+ np->sv_dcntl = INB(nc_dcntl) & 0xa8;
+ np->sv_ctest3 = INB(nc_ctest3) & 0x01;
+ np->sv_ctest4 = INB(nc_ctest4) & 0x80;
+ np->sv_ctest5 = INB(nc_ctest5) & 0x24;
+ np->sv_gpcntl = INB(nc_gpcntl);
+ np->sv_stest2 = INB(nc_stest2) & 0x20;
+ np->sv_stest4 = INB(nc_stest4);
+
+ /*
+ ** Wide ?
+ */
+
+ np->maxwide = (np->features & FE_WIDE)? 1 : 0;
+
+ /*
+ ** Get the frequency of the chip's clock.
+ ** Find the right value for scntl3.
+ */
+
+ if (np->features & FE_QUAD)
+ np->multiplier = 4;
+ else if (np->features & FE_DBLR)
+ np->multiplier = 2;
+ else
+ np->multiplier = 1;
+
+ np->clock_khz = (np->features & FE_CLK80)? 80000 : 40000;
+ np->clock_khz *= np->multiplier;
+
+ if (np->clock_khz != 40000)
+ ncr_getclock(np, np->multiplier);
+
+ /*
+ * Divisor to be used for async (timer pre-scaler).
+ */
+ i = np->clock_divn - 1;
+ while (--i >= 0) {
+ if (10ul * SCSI_NCR_MIN_ASYNC * np->clock_khz > div_10M[i]) {
+ ++i;
+ break;
+ }
+ }
+ np->rv_scntl3 = i+1;
+
+ /*
+ * Minimum synchronous period factor supported by the chip.
+ * Btw, 'period' is in tenths of nanoseconds.
+ */
+
+ period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz;
+ if (period <= 250) np->minsync = 10;
+ else if (period <= 303) np->minsync = 11;
+ else if (period <= 500) np->minsync = 12;
+ else np->minsync = (period + 40 - 1) / 40;
+
+ /*
+ * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2).
+ */
+
+ if (np->minsync < 25 && !(np->features & (FE_ULTRA|FE_ULTRA2)))
+ np->minsync = 25;
+ else if (np->minsync < 12 && !(np->features & FE_ULTRA2))
+ np->minsync = 12;
+
+ /*
+ * Maximum synchronous period factor supported by the chip.
+ */
+
+ period = (11 * div_10M[np->clock_divn - 1]) / (4 * np->clock_khz);
+ np->maxsync = period > 2540 ? 254 : period / 10;
+
+ /*
+ ** 64 bit (53C896) ?
+ */
+ if (np->features & FE_64BIT)
+#if BITS_PER_LONG > 32
+ np->rv_ccntl1 |= (XTIMOD | EXTIBMV);
+#else
+ np->rv_ccntl1 |= (DDAC);
+#endif
+
+ /*
+ ** Phase mismatch handled by SCRIPTS (53C896) ?
+ */
+ if (np->features & FE_NOPM)
+ np->rv_ccntl0 |= (ENPMJ);
+
+ /*
+ ** Prepare initial value of other IO registers
+ */
+#if defined SCSI_NCR_TRUST_BIOS_SETTING
+ np->rv_scntl0 = np->sv_scntl0;
+ np->rv_dmode = np->sv_dmode;
+ np->rv_dcntl = np->sv_dcntl;
+ np->rv_ctest3 = np->sv_ctest3;
+ np->rv_ctest4 = np->sv_ctest4;
+ np->rv_ctest5 = np->sv_ctest5;
+ burst_max = burst_code(np->sv_dmode, np->sv_ctest4, np->sv_ctest5);
+#else
+
+ /*
+ ** Select burst length (dwords)
+ */
+ burst_max = driver_setup.burst_max;
+ if (burst_max == 255)
+ burst_max = burst_code(np->sv_dmode, np->sv_ctest4, np->sv_ctest5);
+ if (burst_max > 7)
+ burst_max = 7;
+ if (burst_max > np->maxburst)
+ burst_max = np->maxburst;
+
+ /*
+ ** DEL 352 - 53C810 Rev x11 - Part Number 609-0392140 - ITEM 2.
+ ** This chip and the 860 Rev 1 may wrongly use PCI cache line
+ ** based transactions on LOAD/STORE instructions. So we have
+ ** to prevent these chips from using such PCI transactions in
+ ** this driver. The generic sym53c8xx driver that does not use
+ ** LOAD/STORE instructions does not need this work-around.
+ */
+ if ((np->device_id == PCI_DEVICE_ID_NCR_53C810 &&
+ np->revision_id >= 0x10 && np->revision_id <= 0x11) ||
+ (np->device_id == PCI_DEVICE_ID_NCR_53C860 &&
+ np->revision_id <= 0x1))
+ np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP);
+
+ /*
+ ** Select all supported special features.
+ ** If we are using on-board RAM for scripts, prefetch (PFEN)
+ ** does not help, but burst op fetch (BOF) does.
+ ** Disabling PFEN makes sure BOF will be used.
+ */
+ if (np->features & FE_ERL)
+ np->rv_dmode |= ERL; /* Enable Read Line */
+ if (np->features & FE_BOF)
+ np->rv_dmode |= BOF; /* Burst Opcode Fetch */
+ if (np->features & FE_ERMP)
+ np->rv_dmode |= ERMP; /* Enable Read Multiple */
+#ifdef SCSI_NCR_OPTIMIZE_896
+ if ((np->features & FE_PFEN) && !np->base2_ba)
+#else
+ if (np->features & FE_PFEN)
+#endif
+ np->rv_dcntl |= PFEN; /* Prefetch Enable */
+ if (np->features & FE_CLSE)
+ np->rv_dcntl |= CLSE; /* Cache Line Size Enable */
+ if (np->features & FE_WRIE)
+ np->rv_ctest3 |= WRIE; /* Write and Invalidate */
+ if (np->features & FE_DFS)
+ np->rv_ctest5 |= DFS; /* Dma Fifo Size */
+
+ /*
+ ** Select some other
+ */
+ if (driver_setup.master_parity)
+ np->rv_ctest4 |= MPEE; /* Master parity checking */
+ if (driver_setup.scsi_parity)
+ np->rv_scntl0 |= 0x0a; /* full arb., ena parity, par->ATN */
+
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+ /*
+ ** Get parity checking, host ID and verbose mode from NVRAM
+ **/
+ if (nvram) {
+ switch(nvram->type) {
+ case SCSI_NCR_TEKRAM_NVRAM:
+ np->myaddr = nvram->data.Tekram.host_id & 0x0f;
+ break;
+ case SCSI_NCR_SYMBIOS_NVRAM:
+ if (!(nvram->data.Symbios.flags & SYMBIOS_PARITY_ENABLE))
+ np->rv_scntl0 &= ~0x0a;
+ np->myaddr = nvram->data.Symbios.host_id & 0x0f;
+ if (nvram->data.Symbios.flags & SYMBIOS_VERBOSE_MSGS)
+ np->verbose += 1;
+ break;
+ }
+ }
+#endif
+ /*
+ ** Get SCSI addr of host adapter (set by bios?).
+ */
+ if (np->myaddr == 255) {
+ np->myaddr = INB(nc_scid) & 0x07;
+ if (!np->myaddr)
+ np->myaddr = SCSI_NCR_MYADDR;
+ }
+
+#endif /* SCSI_NCR_TRUST_BIOS_SETTING */
+
+ /*
+ * Prepare initial io register bits for burst length
+ */
+ ncr_init_burst(np, burst_max);
+
+ /*
+ ** Set differential mode and LED support.
+ ** Ignore these features for boards known to use a
+ ** specific GPIO wiring (Tekram only for now) and
+ ** for the 896 that drives the LED directly.
+ ** Probe initial setting of GPREG and GPCNTL for
+ ** other ones.
+ */
+ if (!nvram || nvram->type != SCSI_NCR_TEKRAM_NVRAM) {
+ switch(driver_setup.diff_support) {
+ case 3:
+ if (INB(nc_gpreg) & 0x08)
+ break;
+ case 2:
+ np->rv_stest2 |= 0x20;
+ break;
+ case 1:
+ np->rv_stest2 |= (np->sv_stest2 & 0x20);
+ break;
+ default:
+ break;
+ }
+ }
+ if ((driver_setup.led_pin ||
+ (nvram && nvram->type == SCSI_NCR_SYMBIOS_NVRAM)) &&
+ !(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01))
+ np->features |= FE_LED0;
+
+ /*
+ ** Set irq mode.
+ */
+ switch(driver_setup.irqm & 3) {
+ case 2:
+ np->rv_dcntl |= IRQM;
+ break;
+ case 1:
+ np->rv_dcntl |= (np->sv_dcntl & IRQM);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ ** Configure targets according to driver setup.
+ ** If NVRAM present get targets setup from NVRAM.
+ ** Allow to override sync, wide and NOSCAN from
+ ** boot command line.
+ */
+ for (i = 0 ; i < MAX_TARGET ; i++) {
+ tcb_p tp = &np->target[i];
+
+ tp->usrsync = 255;
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+ if (nvram) {
+ switch(nvram->type) {
+ case SCSI_NCR_TEKRAM_NVRAM:
+ ncr_Tekram_setup_target(np, i, &nvram->data.Tekram);
+ break;
+ case SCSI_NCR_SYMBIOS_NVRAM:
+ ncr_Symbios_setup_target(np, i, &nvram->data.Symbios);
+ break;
+ }
+ if (driver_setup.use_nvram & 0x2)
+ tp->usrsync = driver_setup.default_sync;
+ if (driver_setup.use_nvram & 0x4)
+ tp->usrwide = driver_setup.max_wide;
+ if (driver_setup.use_nvram & 0x8)
+ tp->usrflag &= ~UF_NOSCAN;
+ }
+ else {
+#else
+ if (1) {
+#endif
+ tp->usrsync = driver_setup.default_sync;
+ tp->usrwide = driver_setup.max_wide;
+ tp->usrtags = SCSI_NCR_MAX_TAGS;
+ if (!driver_setup.disconnection)
+ np->target[i].usrflag = UF_NODISC;
+ }
+ }
+
+ /*
+ ** Announce all that stuff to user.
+ */
+
+ i = nvram ? nvram->type : 0;
+ printk(KERN_INFO "%s: %sID %d, Fast-%d%s%s\n", ncr_name(np),
+ i == SCSI_NCR_SYMBIOS_NVRAM ? "Symbios format NVRAM, " :
+ (i == SCSI_NCR_TEKRAM_NVRAM ? "Tekram format NVRAM, " : ""),
+ np->myaddr,
+ np->minsync < 12 ? 40 : (np->minsync < 25 ? 20 : 10),
+ (np->rv_scntl0 & 0xa) ? ", Parity Checking" : ", NO Parity",
+ (np->rv_stest2 & 0x20) ? ", Differential" : "");
+
+ if (bootverbose > 1) {
+ printk (KERN_INFO "%s: initial SCNTL3/DMODE/DCNTL/CTEST3/4/5 = "
+ "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n",
+ ncr_name(np), np->sv_scntl3, np->sv_dmode, np->sv_dcntl,
+ np->sv_ctest3, np->sv_ctest4, np->sv_ctest5);
+
+ printk (KERN_INFO "%s: final SCNTL3/DMODE/DCNTL/CTEST3/4/5 = "
+ "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n",
+ ncr_name(np), np->rv_scntl3, np->rv_dmode, np->rv_dcntl,
+ np->rv_ctest3, np->rv_ctest4, np->rv_ctest5);
+ }
+
+ if (bootverbose && np->base2_ba)
+ printk (KERN_INFO "%s: on-chip RAM at 0x%lx\n",
+ ncr_name(np), np->base2_ba);
+
+ return 0;
+}
+
+
+#ifdef SCSI_NCR_DEBUG_NVRAM
+
+__initfunc(
+void ncr_display_Symbios_nvram(ncb_p np, Symbios_nvram *nvram)
+)
+{
+ int i;
+
+ /* display Symbios nvram host data */
+ printk(KERN_DEBUG "%s: HOST ID=%d%s%s%s%s%s\n",
+ ncr_name(np), nvram->host_id & 0x0f,
+ (nvram->flags & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"",
+ (nvram->flags & SYMBIOS_PARITY_ENABLE) ? " PARITY" :"",
+ (nvram->flags & SYMBIOS_VERBOSE_MSGS) ? " VERBOSE" :"",
+ (nvram->flags & SYMBIOS_CHS_MAPPING) ? " CHS_ALT" :"",
+ (nvram->flags1 & SYMBIOS_SCAN_HI_LO) ? " HI_LO" :"");
+
+ /* display Symbios nvram drive data */
+ for (i = 0 ; i < 15 ; i++) {
+ struct Symbios_target *tn = &nvram->target[i];
+ printk(KERN_DEBUG "%s-%d:%s%s%s%s WIDTH=%d SYNC=%d TMO=%d\n",
+ ncr_name(np), i,
+ (tn->flags & SYMBIOS_DISCONNECT_ENABLE) ? " DISC" : "",
+ (tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME) ? " SCAN_BOOT" : "",
+ (tn->flags & SYMBIOS_SCAN_LUNS) ? " SCAN_LUNS" : "",
+ (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? " TCQ" : "",
+ tn->bus_width,
+ tn->sync_period / 4,
+ tn->timeout);
+ }
+}
+
+static u_char Tekram_boot_delay[7] __initdata = {3, 5, 10, 20, 30, 60, 120};
+
+__initfunc(
+void ncr_display_Tekram_nvram(ncb_p np, Tekram_nvram *nvram)
+)
+{
+ int i, tags, boot_delay;
+ char *rem;
+
+ /* display Tekram nvram host data */
+ tags = 2 << nvram->max_tags_index;
+ boot_delay = 0;
+ if (nvram->boot_delay_index < 6)
+ boot_delay = Tekram_boot_delay[nvram->boot_delay_index];
+ switch((nvram->flags & TEKRAM_REMOVABLE_FLAGS) >> 6) {
+ default:
+ case 0: rem = ""; break;
+ case 1: rem = " REMOVABLE=boot device"; break;
+ case 2: rem = " REMOVABLE=all"; break;
+ }
+
+ printk(KERN_DEBUG
+ "%s: HOST ID=%d%s%s%s%s%s%s%s%s%s BOOT DELAY=%d tags=%d\n",
+ ncr_name(np), nvram->host_id & 0x0f,
+ (nvram->flags1 & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"",
+ (nvram->flags & TEKRAM_MORE_THAN_2_DRIVES) ? " >2DRIVES" :"",
+ (nvram->flags & TEKRAM_DRIVES_SUP_1GB) ? " >1GB" :"",
+ (nvram->flags & TEKRAM_RESET_ON_POWER_ON) ? " RESET" :"",
+ (nvram->flags & TEKRAM_ACTIVE_NEGATION) ? " ACT_NEG" :"",
+ (nvram->flags & TEKRAM_IMMEDIATE_SEEK) ? " IMM_SEEK" :"",
+ (nvram->flags & TEKRAM_SCAN_LUNS) ? " SCAN_LUNS" :"",
+ (nvram->flags1 & TEKRAM_F2_F6_ENABLED) ? " F2_F6" :"",
+ rem, boot_delay, tags);
+
+ /* display Tekram nvram drive data */
+ for (i = 0; i <= 15; i++) {
+ int sync, j;
+ struct Tekram_target *tn = &nvram->target[i];
+ j = tn->sync_index & 0xf;
+ sync = j < 12 ? Tekram_sync[j] : 255;
+ printk(KERN_DEBUG "%s-%d:%s%s%s%s%s%s PERIOD=%d\n",
+ ncr_name(np), i,
+ (tn->flags & TEKRAM_PARITY_CHECK) ? " PARITY" : "",
+ (tn->flags & TEKRAM_SYNC_NEGO) ? " SYNC" : "",
+ (tn->flags & TEKRAM_DISCONNECT_ENABLE) ? " DISC" : "",
+ (tn->flags & TEKRAM_START_CMD) ? " START" : "",
+ (tn->flags & TEKRAM_TAGGED_COMMANDS) ? " TCQ" : "",
+ (tn->flags & TEKRAM_WIDE_NEGO) ? " WIDE" : "",
+ sync);
+ }
+}
+#endif /* SCSI_NCR_DEBUG_NVRAM */
+
+/*
+** Host attach and initialisations.
+**
+** Allocate host data and ncb structure.
+** Request IO region and remap MMIO region.
+** Do chip initialization.
+** If all is OK, install interrupt handling and
+** start the timer daemon.
+*/
+
+__initfunc(
+static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
+)
+{
+ struct host_data *host_data;
+ ncb_p np = 0;
+ struct Scsi_Host *instance = 0;
+ u_long flags = 0;
+ ncr_nvram *nvram = device->nvram;
+ int i;
+
+#ifdef __sparc__
+printk(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=0x%x\n",
+ device->chip.name, unit, device->chip.revision_id, device->slot.base,
+ device->slot.io_port, device->slot.irq);
+#else
+printk(KERN_INFO NAME53C "%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n",
+ device->chip.name, unit, device->chip.revision_id, device->slot.base,
+ device->slot.io_port, device->slot.irq);
+#endif
+
+ /*
+ ** Allocate host_data structure
+ */
+ if (!(instance = scsi_register(tpnt, sizeof(*host_data))))
+ goto attach_error;
+ host_data = (struct host_data *) instance->hostdata;
+
+ /*
+ ** Allocate the host control block.
+ */
+ np = m_calloc(sizeof(struct ncb), "NCB", MEMO_WARN);
+ if (!np)
+ goto attach_error;
+ NCR_INIT_LOCK_NCB(np);
+ host_data->ncb = np;
+
+ /*
+ ** Store input informations in the host data structure.
+ */
+ strncpy(np->chip_name, device->chip.name, sizeof(np->chip_name) - 1);
+ np->unit = unit;
+ np->verbose = driver_setup.verbose;
+ sprintf(np->inst_name, NAME53C "%s-%d", np->chip_name, np->unit);
+ np->device_id = device->chip.device_id;
+ np->revision_id = device->chip.revision_id;
+ np->features = device->chip.features;
+ np->clock_divn = device->chip.nr_divisor;
+ np->maxoffs = device->chip.offset_max;
+ np->maxburst = device->chip.burst_max;
+ np->myaddr = device->host_id;
+
+ /*
+ ** Allocate the start queue.
+ */
+ np->squeue = (ncrcmd *)
+ m_calloc(sizeof(ncrcmd)*(MAX_START*2), "SQUEUE", MEMO_WARN);
+ if (!np->squeue)
+ goto attach_error;
+
+ /*
+ ** Allocate the done queue.
+ */
+ np->dqueue = (ncrcmd *)
+ m_calloc(sizeof(ncrcmd)*(MAX_START*2), "DQUEUE", MEMO_WARN);
+ if (!np->dqueue)
+ goto attach_error;
+
+ /*
+ ** Allocate the target bus address array.
+ */
+ np->targtbl = (u_int32 *) m_calloc(256, "TARGTBL", MEMO_WARN);
+ if (!np->targtbl)
+ goto attach_error;
+
+ /*
+ ** Allocate SCRIPTS areas
+ */
+ np->script0 = (struct script *)
+ m_calloc(sizeof(struct script), "SCRIPT", MEMO_WARN);
+ if (!np->script0)
+ goto attach_error;
+ np->scripth0 = (struct scripth *)
+ m_calloc(sizeof(struct scripth), "SCRIPTH", MEMO_WARN);
+ if (!np->scripth0)
+ goto attach_error;
+
+ /*
+ ** Initialyze the CCB free queue and,
+ ** allocate some CCB. We need at least ONE.
+ */
+ xpt_que_init(&np->free_ccbq);
+ xpt_que_init(&np->b0_ccbq);
+ if (!ncr_alloc_ccb(np))
+ goto attach_error;
+
+ /*
+ ** Initialize timer structure
+ **
+ */
+ init_timer(&np->timer);
+ np->timer.data = (unsigned long) np;
+ np->timer.function = sym53c8xx_timeout;
+
+ /*
+ ** Try to map the controller chip to
+ ** virtual and physical memory.
+ */
+
+ np->base_ba = device->slot.base;
+ np->base_ws = (np->features & FE_IO256)? 256 : 128;
+ np->base2_ba = (np->features & FE_RAM)? device->slot.base_2 : 0;
+
+#ifndef NCR_IOMAPPED
+ np->base_va = remap_pci_mem(np->base_ba, np->base_ws);
+ if (!np->base_va) {
+ printk(KERN_ERR "%s: can't map PCI MMIO region\n",ncr_name(np));
+ goto attach_error;
+ }
+ else if (bootverbose > 1)
+ printk(KERN_INFO "%s: using memory mapped IO\n", ncr_name(np));
+
+ /*
+ ** Make the controller's registers available.
+ ** Now the INB INW INL OUTB OUTW OUTL macros
+ ** can be used safely.
+ */
+
+ np->reg = (struct ncr_reg *) np->base_va;
+
+#endif /* !defined NCR_IOMAPPED */
+
+ /*
+ ** Try to map the controller chip into iospace.
+ */
+
+ if (device->slot.io_port) {
+ request_region(device->slot.io_port, np->base_ws, NAME53C8XX);
+ np->base_io = device->slot.io_port;
+ }
+
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+ if (nvram) {
+ switch(nvram->type) {
+ case SCSI_NCR_SYMBIOS_NVRAM:
+#ifdef SCSI_NCR_DEBUG_NVRAM
+ ncr_display_Symbios_nvram(np, &nvram->data.Symbios);
+#endif
+ break;
+ case SCSI_NCR_TEKRAM_NVRAM:
+#ifdef SCSI_NCR_DEBUG_NVRAM
+ ncr_display_Tekram_nvram(np, &nvram->data.Tekram);
+#endif
+ break;
+ default:
+ nvram = 0;
+#ifdef SCSI_NCR_DEBUG_NVRAM
+ printk(KERN_DEBUG "%s: NVRAM: None or invalid data.\n", ncr_name(np));
+#endif
+ }
+ }
+#endif
+
+ /*
+ ** Do chip dependent initialization.
+ */
+ if (np->base2_ba && sizeof(struct script) > 4096) {
+ printk(KERN_ERR "%s: script too large.\n", ncr_name(np));
+ goto attach_error;
+ }
+ (void) ncr_prepare_setting(np, nvram);
+
+ /*
+ ** Patch script to physical addresses
+ */
+ ncr_script_fill (&script0, &scripth0);
+
+ np->p_script = vtobus(np->script0);
+ np->p_scripth = vtobus(np->scripth0);
+ np->p_scripth0 = np->p_scripth;
+
+ if (np->base2_ba) {
+ np->p_script = pcivtobus(np->base2_ba);
+ if (np->features & FE_RAM8K) {
+ np->p_scripth = np->p_script + 4096;
+#if BITS_PER_LONG > 32
+ np->scr_ram_seg = cpu_to_scr(np->base2_ba >> 32);
+#endif
+ }
+ }
+
+ ncr_script_copy_and_bind (np, (ncrcmd *) &script0, (ncrcmd *) np->script0, sizeof(struct script));
+ ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, (ncrcmd *) np->scripth0, sizeof(struct scripth));
+
+ /*
+ ** Patch some variables in SCRIPTS
+ */
+ np->scripth0->pm0_data_addr[0] =
+ cpu_to_scr(NCB_SCRIPT_PHYS(np, pm0_data));
+ np->scripth0->pm1_data_addr[0] =
+ cpu_to_scr(NCB_SCRIPT_PHYS(np, pm1_data));
+
+ np->scripth0->script0_ba[0] = cpu_to_scr(vtobus(np->script0));
+ np->scripth0->script0_ba64[0] = cpu_to_scr(vtobus(np->script0));
+ np->scripth0->scripth0_ba64[0] = cpu_to_scr(vtobus(np->scripth0));
+ np->scripth0->ram_seg64[0] = np->scr_ram_seg;
+
+ /*
+ ** Prepare the idle and invalid task actions.
+ */
+ np->idletask.start = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle));
+ np->idletask.restart = cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_i_t_l));
+ np->p_idletask = vtobus(&np->idletask);
+
+ np->notask.start = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle));
+ np->notask.restart = cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_i_t_l));
+ np->p_notask = vtobus(&np->notask);
+
+ np->bad_i_t_l.start = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle));
+ np->bad_i_t_l.restart = cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_i_t_l));
+ np->p_bad_i_t_l = vtobus(&np->bad_i_t_l);
+
+ np->bad_i_t_l_q.start = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle));
+ np->bad_i_t_l_q.restart = cpu_to_scr(NCB_SCRIPTH_PHYS (np,bad_i_t_l_q));
+ np->p_bad_i_t_l_q = vtobus(&np->bad_i_t_l_q);
+
+ /*
+ ** Allocate and prepare the bad lun table.
+ */
+ np->badluntbl = m_calloc(256, "BADLUNTBL", MEMO_WARN);
+ if (!np->badluntbl)
+ goto attach_error;
+
+ assert (offsetof(struct lcb, resel_task) == 0);
+ np->resel_badlun = cpu_to_scr(NCB_SCRIPTH_PHYS(np, bad_identify));
+
+ for (i = 0 ; i < 64 ; i++)
+ np->badluntbl[i] = cpu_to_scr(vtobus(&np->resel_badlun));
+
+ /*
+ ** Prepare the target bus address array.
+ */
+ np->script0->targtbl[0] = cpu_to_scr(vtobus(np->targtbl));
+ for (i = 0 ; i < MAX_TARGET ; i++) {
+ np->targtbl[i] = cpu_to_scr(vtobus(&np->target[i]));
+ np->target[i].b_luntbl = cpu_to_scr(vtobus(np->badluntbl));
+ }
+
+ /*
+ ** Patch the script for LED support.
+ */
+
+ if (np->features & FE_LED0) {
+ np->script0->idle[0] =
+ cpu_to_scr(SCR_REG_REG(gpreg, SCR_OR, 0x01));
+ np->script0->reselected[0] =
+ cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe));
+ np->script0->start[0] =
+ cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe));
+ }
+
+ /*
+ ** DEL 472 - 53C896 Rev 1 - Part Number 609-0393055 - ITEM 5.
+ */
+ if (np->device_id == PCI_DEVICE_ID_NCR_53C896 &&
+ np->revision_id <= 0x1 && (np->features & FE_NOPM)) {
+ np->scatter = ncr_scatter_896R1;
+#ifndef SCSI_NCR_PROFILE_SUPPORT
+#define XXX 0
+#else
+#define XXX 3
+#endif
+ np->script0->dataphase[XXX] = cpu_to_scr(SCR_JUMP);
+ np->script0->dataphase[XXX+1] =
+ cpu_to_scr(NCB_SCRIPTH_PHYS (np, tweak_pmj));
+#undef XXX
+ }
+ else
+#ifdef DEBUG_896R1
+ np->scatter = ncr_scatter_896R1;
+#else
+ np->scatter = ncr_scatter;
+#endif
+
+ /*
+ ** Reset chip.
+ ** We should use ncr_soft_reset(), but we donnot want to do
+ ** so, since we may not be safe if ABRT interrupt occurs due
+ ** to the BIOS or previous O/S having enable this interrupt.
+ */
+ OUTB (nc_istat, SRST);
+ UDELAY(10);
+ OUTB (nc_istat, 0);
+
+ /*
+ ** Now check the cache handling of the pci chipset.
+ */
+
+ if (ncr_snooptest (np)) {
+ printk (KERN_ERR "CACHE INCORRECTLY CONFIGURED.\n");
+ goto attach_error;
+ };
+
+ /*
+ ** Install the interrupt handler.
+ */
+ if (request_irq(device->slot.irq, sym53c8xx_intr,
+ ((driver_setup.irqm & 0x10) ? 0 : SA_SHIRQ) |
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,2,0)
+ ((driver_setup.irqm & 0x20) ? 0 : SA_INTERRUPT),
+#else
+ 0,
+#endif
+ NAME53C8XX, np)) {
+ printk(KERN_ERR "%s: request irq %d failure\n",
+ ncr_name(np), device->slot.irq);
+ goto attach_error;
+ }
+ np->irq = device->slot.irq;
+
+ /*
+ ** After SCSI devices have been opened, we cannot
+ ** reset the bus safely, so we do it here.
+ ** Interrupt handler does the real work.
+ ** Process the reset exception,
+ ** if interrupts are not enabled yet.
+ ** Then enable disconnects.
+ */
+ NCR_LOCK_NCB(np, flags);
+ if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) {
+ printk(KERN_ERR "%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np));
+
+ NCR_UNLOCK_NCB(np, flags);
+ goto attach_error;
+ }
+ ncr_exception (np);
+
+ /*
+ ** The middle-level SCSI driver does not
+ ** wait for devices to settle.
+ ** Wait synchronously if more than 2 seconds.
+ */
+ if (driver_setup.settle_delay > 2) {
+ printk(KERN_INFO "%s: waiting %d seconds for scsi devices to settle...\n",
+ ncr_name(np), driver_setup.settle_delay);
+ MDELAY (1000 * driver_setup.settle_delay);
+ }
+
+ /*
+ ** start the timeout daemon
+ */
+ np->lasttime=0;
+ ncr_timeout (np);
+
+ /*
+ ** use SIMPLE TAG messages by default
+ */
+#ifdef SCSI_NCR_ALWAYS_SIMPLE_TAG
+ np->order = M_SIMPLE_TAG;
+#endif
+
+ /*
+ ** Done.
+ */
+ if (!first_host)
+ first_host = instance;
+
+ /*
+ ** Fill Linux host instance structure
+ ** and return success.
+ */
+ instance->max_channel = 0;
+ instance->max_id = np->maxwide ? 16 : 8;
+ instance->max_lun = SCSI_NCR_MAX_LUN;
+#ifndef NCR_IOMAPPED
+ instance->base = (char *) np->reg;
+#endif
+ instance->irq = np->irq;
+ instance->unique_id = np->base_io;
+ instance->io_port = np->base_io;
+ instance->n_io_port = np->base_ws;
+ instance->dma_channel = 0;
+ instance->select_queue_depths = sym53c8xx_select_queue_depths;
+
+ NCR_UNLOCK_NCB(np, flags);
+
+ /*
+ ** Now let the generic SCSI driver
+ ** look for the SCSI devices on the bus ..
+ */
+ return 0;
+
+attach_error:
+ if (!instance) return -1;
+ printk(KERN_INFO "%s: giving up ...\n", ncr_name(np));
+ if (np)
+ ncr_free_resources(np);
+ scsi_unregister(instance);
+
+ return -1;
+ }
+
+
+/*
+** Free controller resources.
+*/
+static void ncr_free_resources(ncb_p np)
+{
+ ccb_p cp;
+ tcb_p tp;
+ lcb_p lp;
+ int target, lun;
+
+ if (np->irq)
+ free_irq(np->irq, np);
+ if (np->base_io)
+ release_region(np->base_io, np->base_ws);
+#ifndef NCR_IOMAPPED
+ if (np->base_va)
+ unmap_pci_mem(np->base_va, np->base_ws);
+#endif
+ if (np->scripth0)
+ m_free(np->scripth0, sizeof(struct scripth), "SCRIPTH");
+ if (np->script0)
+ m_free(np->script0, sizeof(struct script), "SCRIPT");
+ if (np->squeue)
+ m_free(np->squeue, sizeof(ncrcmd)*(MAX_START*2), "SQUEUE");
+ if (np->dqueue)
+ m_free(np->dqueue, sizeof(ncrcmd)*(MAX_START*2),"DQUEUE");
+
+ while ((cp = np->ccbc) != NULL) {
+ np->ccbc = cp->link_ccb;
+ m_free(cp, sizeof(*cp), "CCB");
+ }
+
+ if (np->badluntbl)
+ m_free(np->badluntbl, 256,"BADLUNTBL");
+
+ for (target = 0; target < MAX_TARGET ; target++) {
+ tp = &np->target[target];
+ for (lun = 0 ; lun < MAX_LUN ; lun++) {
+ lp = tp->lp[lun];
+ if (!lp)
+ continue;
+ if (lp->tasktbl != &lp->tasktbl_0)
+ m_free(lp->tasktbl, 256, "TASKTBL");
+ m_free(lp, sizeof(*lp), "LCB");
+ }
+ }
+
+ m_free(np, sizeof(*np), "NCB");
+}
+
+
+/*==========================================================
+**
+**
+** Done SCSI commands list management.
+**
+** We donnot enter the scsi_done() callback immediately
+** after a command has been seen as completed but we
+** insert it into a list which is flushed outside any kind
+** of driver critical section.
+** This allows to do minimal stuff under interrupt and
+** inside critical sections and to also avoid locking up
+** on recursive calls to driver entry points under SMP.
+** In fact, the only kernel point which is entered by the
+** driver with a driver lock set is get_free_pages(GFP_ATOMIC...)
+** that shall not reenter the driver under any circumstance.
+**
+**==========================================================
+*/
+static inline void ncr_queue_done_cmd(ncb_p np, Scsi_Cmnd *cmd)
+{
+ cmd->host_scribble = (char *) np->done_list;
+ np->done_list = cmd;
+}
+
+static inline void ncr_flush_done_cmds(Scsi_Cmnd *lcmd)
+{
+ Scsi_Cmnd *cmd;
+
+ while (lcmd) {
+ cmd = lcmd;
+ lcmd = (Scsi_Cmnd *) cmd->host_scribble;
+ cmd->scsi_done(cmd);
+ }
+}
+
+
+/*==========================================================
+**
+**
+** Start execution of a SCSI command.
+** This is called from the generic SCSI driver.
+**
+**
+**==========================================================
+*/
+static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd)
+{
+/* Scsi_Device *device = cmd->device; */
+ tcb_p tp = &np->target[cmd->target];
+ lcb_p lp = tp->lp[cmd->lun];
+ ccb_p cp;
+
+ int segments;
+ u_char nego, idmsg, *msgptr;
+ u_int msglen;
+ int direction;
+ u_int32 lastp, goalp;
+
+ /*---------------------------------------------
+ **
+ ** Some shortcuts ...
+ **
+ **---------------------------------------------
+ */
+ if ((cmd->target == np->myaddr ) ||
+ (cmd->target >= MAX_TARGET) ||
+ (cmd->lun >= MAX_LUN )) {
+ return(DID_BAD_TARGET);
+ }
+
+ /*---------------------------------------------
+ **
+ ** Complete the 1st TEST UNIT READY command
+ ** with error condition if the device is
+ ** flagged NOSCAN, in order to speed up
+ ** the boot.
+ **
+ **---------------------------------------------
+ */
+ if (cmd->cmnd[0] == 0 && (tp->usrflag & UF_NOSCAN)) {
+ tp->usrflag &= ~UF_NOSCAN;
+ return DID_BAD_TARGET;
+ }
+
+ if (DEBUG_FLAGS & DEBUG_TINY) {
+ PRINT_ADDR(cmd);
+ printk ("CMD=%x ", cmd->cmnd[0]);
+ }
+
+ /*---------------------------------------------------
+ **
+ ** Assign a ccb / bind cmd.
+ ** If resetting, shorten settle_time if necessary
+ ** in order to avoid spurious timeouts.
+ ** If resetting or no free ccb,
+ ** insert cmd into the waiting list.
+ **
+ **----------------------------------------------------
+ */
+ if (np->settle_time && cmd->timeout_per_command >= HZ &&
+ np->settle_time > jiffies + cmd->timeout_per_command - HZ) {
+ np->settle_time = jiffies + cmd->timeout_per_command - HZ;
+ }
+
+ if (np->settle_time || !(cp=ncr_get_ccb (np, cmd->target, cmd->lun))) {
+ insert_into_waiting_list(np, cmd);
+ return(DID_OK);
+ }
+ cp->cmd = cmd;
+
+ /*---------------------------------------------------
+ **
+ ** Enable tagged queue if asked by scsi ioctl
+ **
+ **----------------------------------------------------
+ */
+#if 0 /* This stuff was only usefull for linux-1.2.13 */
+ if (lp && !lp->numtags && cmd->device && cmd->device->tagged_queue) {
+ lp->numtags = tp->usrtags;
+ ncr_setup_tags (np, cp->target, cp->lun);
+ }
+#endif
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ cp->phys.num_disc = 0;
+#endif
+
+ /*---------------------------------------------------
+ **
+ ** negotiation required?
+ **
+ **---------------------------------------------------
+ */
+
+ nego = 0;
+
+ if ((!tp->widedone || !tp->period) && !tp->nego_cp && tp->inq_done && lp) {
+
+ /*
+ ** negotiate wide transfers ?
+ */
+
+ if (!tp->widedone) {
+ if (tp->inq_byte7 & INQ7_WIDE16) {
+ nego = NS_WIDE;
+ } else
+ tp->widedone=1;
+ };
+
+ /*
+ ** negotiate synchronous transfers?
+ */
+
+ if (!nego && !tp->period) {
+ if (tp->inq_byte7 & INQ7_SYNC) {
+ nego = NS_SYNC;
+ } else {
+ tp->period =0xffff;
+ PRINT_TARGET(np, cp->target);
+ printk ("target did not report SYNC.\n");
+ };
+ };
+
+ /*
+ ** remember nego is pending for the target.
+ ** Avoid to start a nego for all queued commands
+ ** when tagged command queuing is enabled.
+ */
+
+ if (nego)
+ tp->nego_cp = cp;
+ };
+
+ /*----------------------------------------------------
+ **
+ ** Build the identify / tag / sdtr message
+ **
+ **----------------------------------------------------
+ */
+
+ idmsg = M_IDENTIFY | cp->lun;
+
+ if (cp ->tag != NO_TAG || (lp && !(tp->usrflag & UF_NODISC)))
+ idmsg |= 0x40;
+
+ msgptr = cp->scsi_smsg;
+ msglen = 0;
+ msgptr[msglen++] = idmsg;
+
+ if (cp->tag != NO_TAG) {
+ char order = np->order;
+
+ /*
+ ** Force ordered tag if necessary to avoid timeouts
+ ** and to preserve interactivity.
+ */
+ if (lp && lp->tags_stime + (3*HZ) <= jiffies) {
+ if (lp->tags_smap) {
+ order = M_ORDERED_TAG;
+ if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){
+ PRINT_ADDR(cmd);
+ printk("ordered tag forced.\n");
+ }
+ }
+ lp->tags_stime = jiffies;
+ lp->tags_smap = lp->tags_umap;
+ }
+
+ if (order == 0) {
+ /*
+ ** Ordered write ops, unordered read ops.
+ */
+ switch (cmd->cmnd[0]) {
+ case 0x08: /* READ_SMALL (6) */
+ case 0x28: /* READ_BIG (10) */
+ case 0xa8: /* READ_HUGE (12) */
+ order = M_SIMPLE_TAG;
+ break;
+ default:
+ order = M_ORDERED_TAG;
+ }
+ }
+ msgptr[msglen++] = order;
+ /*
+ ** Actual tags are numbered 1,3,5,..2*MAXTAGS+1,
+ ** since we may have to deal with devices that have
+ ** problems with #TAG 0 or too great #TAG numbers.
+ */
+ msgptr[msglen++] = (cp->tag << 1) + 1;
+ }
+
+ switch (nego) {
+ case NS_SYNC:
+ msgptr[msglen++] = M_EXTENDED;
+ msgptr[msglen++] = 3;
+ msgptr[msglen++] = M_X_SYNC_REQ;
+ msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0;
+ msgptr[msglen++] = tp->maxoffs;
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("sync msgout: ");
+ ncr_show_msg (&cp->scsi_smsg [msglen-5]);
+ printk (".\n");
+ };
+ break;
+ case NS_WIDE:
+ msgptr[msglen++] = M_EXTENDED;
+ msgptr[msglen++] = 2;
+ msgptr[msglen++] = M_X_WIDE_REQ;
+ msgptr[msglen++] = tp->usrwide;
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("wide msgout: ");
+ ncr_show_msg (&cp->scsi_smsg [msglen-4]);
+ printk (".\n");
+ };
+ break;
+ };
+
+ cp->host_flags = 0;
+
+ /*----------------------------------------------------
+ **
+ ** Build the data descriptors
+ **
+ **----------------------------------------------------
+ */
+
+ segments = np->scatter (cp, cp->cmd);
+
+ if (segments < 0) {
+ ncr_free_ccb(np, cp);
+ return(DID_ERROR);
+ }
+
+ /*----------------------------------------------------
+ **
+ ** Determine xfer direction.
+ **
+ **----------------------------------------------------
+ */
+ if (!cp->data_len)
+ direction = 0;
+ else {
+ switch((int) cmd->cmnd[0]) {
+ case 0x08: /* READ(6) 08 */
+ case 0x28: /* READ(10) 28 */
+ case 0xA8: /* READ(12) A8 */
+ direction = XFER_IN;
+ break;
+ case 0x0A: /* WRITE(6) 0A */
+ case 0x2A: /* WRITE(10) 2A */
+ case 0xAA: /* WRITE(12) AA */
+ direction = XFER_OUT;
+ break;
+ default:
+ direction = (XFER_IN|XFER_OUT);
+ break;
+ }
+ }
+
+ /*----------------------------------------------------
+ **
+ ** Set the DATA POINTER.
+ **
+ **----------------------------------------------------
+ */
+
+ /*
+ ** Default to no data transfer.
+ */
+ lastp = goalp = NCB_SCRIPTH_PHYS (np, no_data);
+
+ /*
+ ** Compute data out pointers, if needed.
+ */
+ if (direction & XFER_OUT) {
+ goalp = NCB_SCRIPT_PHYS (np, data_out2) + 8;
+#if MAX_SCATTERH != 0
+ if (segments <= MAX_SCATTERL)
+ lastp = goalp - 8 - (segments * (SCR_SG_SIZE*4));
+ else {
+ lastp = NCB_SCRIPTH_PHYS (np, hdata_out2);
+ lastp -= (segments - MAX_SCATTERL) * (SCR_SG_SIZE*4);
+ }
+#else
+ lastp = goalp - 8 - (segments * (SCR_SG_SIZE*4));
+#endif
+ /*
+ ** If actual data direction is unknown, save pointers
+ ** in header. The SCRIPTS will swap them to current
+ ** if target decision will be data out.
+ */
+ if (direction & XFER_IN) {
+ cp->phys.header.wgoalp = cpu_to_scr(goalp);
+ cp->phys.header.wlastp = cpu_to_scr(lastp);
+ }
+ }
+
+ /*
+ ** Compute data in pointers, if needed.
+ */
+ if (direction & XFER_IN) {
+ goalp = NCB_SCRIPT_PHYS (np, data_in2) + 8;
+#if MAX_SCATTERH != 0
+ if (segments <= MAX_SCATTERL)
+ lastp = goalp - 8 - (segments * (SCR_SG_SIZE*4));
+ else {
+ lastp = NCB_SCRIPTH_PHYS (np, hdata_in2);
+ lastp -= (segments - MAX_SCATTERL) * (SCR_SG_SIZE*4);
+ }
+#else
+ lastp = goalp - 8 - (segments * (SCR_SG_SIZE*4));
+#endif
+ }
+
+ /*
+ ** Set all pointers values needed by SCRIPTS.
+ ** If direction is unknown, start at data_io.
+ */
+ cp->phys.header.lastp = cpu_to_scr(lastp);
+ cp->phys.header.goalp = cpu_to_scr(goalp);
+
+ if ((direction & (XFER_IN|XFER_OUT)) == (XFER_IN|XFER_OUT))
+ cp->phys.header.savep =
+ cpu_to_scr(NCB_SCRIPTH_PHYS (np, data_io));
+ else
+ cp->phys.header.savep= cpu_to_scr(lastp);
+
+ /*
+ ** Save the initial data pointer in order to be able
+ ** to redo the command.
+ */
+ cp->startp = cp->phys.header.savep;
+
+ /*----------------------------------------------------
+ **
+ ** fill in ccb
+ **
+ **----------------------------------------------------
+ **
+ **
+ ** physical -> virtual backlink
+ ** Generic SCSI command
+ */
+
+ /*
+ ** Startqueue
+ */
+ cp->phys.header.go.start = cpu_to_scr(NCB_SCRIPT_PHYS (np,select));
+ cp->phys.header.go.restart = cpu_to_scr(NCB_SCRIPT_PHYS (np,resel_dsa));
+ /*
+ ** select
+ */
+ cp->phys.select.sel_id = cp->target;
+ cp->phys.select.sel_scntl3 = tp->wval;
+ cp->phys.select.sel_sxfer = tp->sval;
+ /*
+ ** message
+ */
+ cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg));
+ cp->phys.smsg.size = cpu_to_scr(msglen);
+
+ /*
+ ** command
+ */
+ cp->phys.cmd.addr = cpu_to_scr(vtobus (&cmd->cmnd[0]));
+ cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len);
+
+ /*
+ ** status
+ */
+ cp->actualquirks = tp->quirks;
+ cp->host_status = nego ? HS_NEGOTIATE : HS_BUSY;
+ cp->scsi_status = S_ILLEGAL;
+
+ cp->xerr_status = XE_OK;
+ cp->nego_status = nego;
+
+ /*----------------------------------------------------
+ **
+ ** Critical region: start this job.
+ **
+ **----------------------------------------------------
+ */
+
+ /*
+ ** activate this job.
+ */
+
+ /* Compute a time limit greater than the middle-level driver one */
+ if (cmd->timeout_per_command > 0)
+ cp->tlimit = jiffies + cmd->timeout_per_command + HZ;
+ else
+ cp->tlimit = jiffies + 86400 * HZ;/* No timeout=24 hours */
+
+ /*
+ ** insert next CCBs into start queue.
+ ** 2 max at a time is enough to flush the CCB wait queue.
+ */
+ cp->auto_sense = 0;
+ if (lp)
+ ncr_start_next_ccb(np, lp, 2);
+ else
+ ncr_put_start_queue(np, cp);
+
+ /*
+ ** Command is successfully queued.
+ */
+
+ return(DID_OK);
+}
+
+
+/*==========================================================
+**
+**
+** Insert a CCB into the start queue and wake up the
+** SCRIPTS processor.
+**
+**
+**==========================================================
+*/
+
+static void ncr_start_next_ccb(ncb_p np, lcb_p lp, int maxn)
+{
+ XPT_QUEHEAD *qp;
+ ccb_p cp;
+
+ while (maxn-- && lp->queuedccbs < lp->queuedepth) {
+ qp = xpt_remque_head(&lp->wait_ccbq);
+ if (!qp)
+ break;
+ ++lp->queuedccbs;
+ cp = xpt_que_entry(qp, struct ccb, link_ccbq);
+ xpt_insque_tail(qp, &lp->busy_ccbq);
+ lp->tasktbl[cp->tag == NO_TAG ? 0 : cp->tag] =
+ cpu_to_scr(cp->p_ccb);
+ ncr_put_start_queue(np, cp);
+ }
+}
+
+static void ncr_put_start_queue(ncb_p np, ccb_p cp)
+{
+ u_short qidx;
+
+ /*
+ ** insert into start queue.
+ */
+ qidx = np->squeueput + 2;
+ if (qidx >= MAX_START*2) qidx = 0;
+
+ np->squeue [qidx] = cpu_to_scr(np->p_idletask);
+ MEMORY_BARRIER();
+ np->squeue [np->squeueput] = cpu_to_scr(cp->p_ccb);
+
+ np->squeueput = qidx;
+ cp->queued = 1;
+
+ if (DEBUG_FLAGS & DEBUG_QUEUE)
+ printk ("%s: queuepos=%d.\n", ncr_name (np), np->squeueput);
+
+ /*
+ ** Script processor may be waiting for reselect.
+ ** Wake it up.
+ */
+ MEMORY_BARRIER();
+ OUTB (nc_istat, SIGP);
+}
+
+
+/*==========================================================
+**
+** Soft reset the chip.
+**
+** Some 896 and 876 chip revisions may hang-up if we set
+** the SRST (soft reset) bit at the wrong time when SCRIPTS
+** are running.
+** So, we need to abort the current operation prior to
+** soft resetting the chip.
+**
+**==========================================================
+*/
+
+static void ncr_soft_reset(ncb_p np)
+{
+ u_char istat;
+ int i;
+
+ OUTB (nc_istat, CABRT);
+ for (i = 1000000 ; i ; --i) {
+ istat = INB (nc_istat);
+ if (istat & SIP) {
+ INW (nc_sist);
+ continue;
+ }
+ if (istat & DIP) {
+ OUTB (nc_istat, 0);
+ INB (nc_dstat);
+ break;
+ }
+ }
+ if (!i)
+ printk("%s: unable to abort current chip operation.\n",
+ ncr_name(np));
+ OUTB (nc_istat, SRST);
+ UDELAY(10);
+ OUTB (nc_istat, 0);
+}
+
+/*==========================================================
+**
+**
+** Start reset process.
+** If reset in progress do nothing.
+** The interrupt handler will reinitialize the chip.
+** The timeout handler will wait for settle_time before
+** clearing it and so resuming command processing.
+**
+**
+**==========================================================
+*/
+static void ncr_start_reset(ncb_p np)
+{
+ if (!np->settle_time) {
+ (void) ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay);
+ }
+ }
+
+static int ncr_reset_scsi_bus(ncb_p np, int enab_int, int settle_delay)
+{
+ u_int32 term;
+ int retv = 0;
+
+ np->settle_time = jiffies + settle_delay * HZ;
+
+ if (bootverbose > 1)
+ printk("%s: resetting, "
+ "command processing suspended for %d seconds\n",
+ ncr_name(np), settle_delay);
+
+ ncr_soft_reset(np); /* Soft reset the chip */
+ UDELAY (2000); /* The 895/6 need time for the bus mode to settle */
+ if (enab_int)
+ OUTW (nc_sien, RST);
+ /*
+ ** Enable Tolerant, reset IRQD if present and
+ ** properly set IRQ mode, prior to resetting the bus.
+ */
+ OUTB (nc_stest3, TE);
+ OUTB (nc_dcntl, (np->rv_dcntl & IRQM));
+ OUTB (nc_scntl1, CRST);
+ UDELAY (200);
+
+ if (!driver_setup.bus_check)
+ goto out;
+ /*
+ ** Check for no terminators or SCSI bus shorts to ground.
+ ** Read SCSI data bus, data parity bits and control signals.
+ ** We are expecting RESET to be TRUE and other signals to be
+ ** FALSE.
+ */
+ term = INB(nc_sstat0); /* rst, sdp0 */
+ term = ((term & 2) << 7) + ((term & 1) << 16);
+ term |= ((INB(nc_sstat2) & 0x01) << 25) | /* sdp1 */
+ (INW(nc_sbdl) << 9) | /* d15-0 */
+ INB(nc_sbcl); /* req, ack, bsy, sel, atn, msg, cd, io */
+
+ if (!(np->features & FE_WIDE))
+ term &= 0x3ffff;
+
+ if (term != (2<<7)) {
+ printk("%s: suspicious SCSI data while resetting the BUS.\n",
+ ncr_name(np));
+ printk("%s: %sdp0,d7-0,rst,req,ack,bsy,sel,atn,msg,c/d,i/o = "
+ "0x%lx, expecting 0x%lx\n",
+ ncr_name(np),
+ (np->features & FE_WIDE) ? "dp1,d15-8," : "",
+ (u_long)term, (u_long)(2<<7));
+ if (driver_setup.bus_check == 1)
+ retv = 1;
+ }
+out:
+ OUTB (nc_scntl1, 0);
+ return retv;
+}
+
+/*==========================================================
+**
+**
+** Reset the SCSI BUS.
+** This is called from the generic SCSI driver.
+**
+**
+**==========================================================
+*/
+static int ncr_reset_bus (ncb_p np, Scsi_Cmnd *cmd, int sync_reset)
+{
+/* Scsi_Device *device = cmd->device; */
+ ccb_p cp;
+ int found;
+
+/*
+ * Return immediately if reset is in progress.
+ */
+ if (np->settle_time) {
+ return SCSI_RESET_PUNT;
+ }
+/*
+ * Start the reset process.
+ * The script processor is then assumed to be stopped.
+ * Commands will now be queued in the waiting list until a settle
+ * delay of 2 seconds will be completed.
+ */
+ ncr_start_reset(np);
+/*
+ * First, look in the wakeup list
+ */
+ for (found=0, cp=np->ccbc; cp; cp=cp->link_ccb) {
+ /*
+ ** look for the ccb of this command.
+ */
+ if (cp->host_status == HS_IDLE) continue;
+ if (cp->cmd == cmd) {
+ found = 1;
+ break;
+ }
+ }
+/*
+ * Then, look in the waiting list
+ */
+ if (!found && retrieve_from_waiting_list(0, np, cmd))
+ found = 1;
+/*
+ * Wake-up all awaiting commands with DID_RESET.
+ */
+ reset_waiting_list(np);
+/*
+ * Wake-up all pending commands with HS_RESET -> DID_RESET.
+ */
+ ncr_wakeup(np, HS_RESET);
+/*
+ * If the involved command was not in a driver queue, and the
+ * scsi driver told us reset is synchronous, and the command is not
+ * currently in the waiting list, complete it with DID_RESET status,
+ * in order to keep it alive.
+ */
+ if (!found && sync_reset && !retrieve_from_waiting_list(0, np, cmd)) {
+ SetScsiResult(cmd, DID_RESET, 0);
+ ncr_queue_done_cmd(np, cmd);
+ }
+
+ return SCSI_RESET_SUCCESS;
+}
+
+/*==========================================================
+**
+**
+** Abort an SCSI command.
+** This is called from the generic SCSI driver.
+**
+**
+**==========================================================
+*/
+static int ncr_abort_command (ncb_p np, Scsi_Cmnd *cmd)
+{
+/* Scsi_Device *device = cmd->device; */
+ ccb_p cp;
+ int found;
+ int retv;
+
+/*
+ * First, look for the scsi command in the waiting list
+ */
+ if (remove_from_waiting_list(np, cmd)) {
+ SetScsiResult(cmd, DID_ABORT, 0);
+ ncr_queue_done_cmd(np, cmd);
+ return SCSI_ABORT_SUCCESS;
+ }
+
+/*
+ * Then, look in the wakeup list
+ */
+ for (found=0, cp=np->ccbc; cp; cp=cp->link_ccb) {
+ /*
+ ** look for the ccb of this command.
+ */
+ if (cp->host_status == HS_IDLE) continue;
+ if (cp->cmd == cmd) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ return SCSI_ABORT_NOT_RUNNING;
+ }
+
+ if (np->settle_time) {
+ return SCSI_ABORT_SNOOZE;
+ }
+
+ /*
+ ** If the CCB is active, patch schedule jumps for the
+ ** script to abort the command.
+ */
+
+ cp->tlimit = 0;
+ switch(cp->host_status) {
+ case HS_BUSY:
+ case HS_NEGOTIATE:
+ printk ("%s: abort ccb=%p (cancel)\n", ncr_name (np), cp);
+ cp->phys.header.go.start =
+ cpu_to_scr(NCB_SCRIPTH_PHYS (np, cancel));
+ retv = SCSI_ABORT_PENDING;
+ break;
+ case HS_DISCONNECT:
+ cp->phys.header.go.restart =
+ cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_i_t_l_q));
+ retv = SCSI_ABORT_PENDING;
+ break;
+ default:
+ retv = SCSI_ABORT_NOT_RUNNING;
+ break;
+
+ }
+
+ /*
+ ** If there are no requests, the script
+ ** processor will sleep on SEL_WAIT_RESEL.
+ ** Let's wake it up, since it may have to work.
+ */
+ OUTB (nc_istat, SIGP);
+
+ return retv;
+}
+
+/*==========================================================
+**
+** Linux release module stuff.
+**
+** Called before unloading the module
+** Detach the host.
+** We have to free resources and halt the NCR chip
+**
+**==========================================================
+*/
+
+#ifdef MODULE
+static int ncr_detach(ncb_p np)
+{
+ int i;
+
+ printk("%s: detaching ...\n", ncr_name(np));
+
+/*
+** Stop the ncr_timeout process
+** Set release_stage to 1 and wait that ncr_timeout() set it to 2.
+*/
+ np->release_stage = 1;
+ for (i = 50 ; i && np->release_stage != 2 ; i--) MDELAY (100);
+ if (np->release_stage != 2)
+ printk("%s: the timer seems to be already stopped\n",
+ ncr_name(np));
+ else np->release_stage = 2;
+
+/*
+** Reset NCR chip.
+** We should use ncr_soft_reset(), but we donnot want to do
+** so, since we may not be safe if interrupts occur.
+*/
+
+ printk("%s: resetting chip\n", ncr_name(np));
+ OUTB (nc_istat, SRST);
+ UDELAY (100);
+ OUTB (nc_istat, 0 );
+
+/*
+** Restore bios setting for automatic clock detection.
+*/
+ OUTB(nc_dmode, np->sv_dmode);
+ OUTB(nc_dcntl, np->sv_dcntl);
+ OUTB(nc_ctest3, np->sv_ctest3);
+ OUTB(nc_ctest4, np->sv_ctest4);
+ OUTB(nc_ctest5, np->sv_ctest5);
+ OUTB(nc_gpcntl, np->sv_gpcntl);
+ OUTB(nc_stest2, np->sv_stest2);
+
+ ncr_selectclock(np, np->sv_scntl3);
+/*
+** Free host resources
+*/
+ ncr_free_resources(np);
+
+ return 1;
+}
+#endif
+
+/*==========================================================
+**
+**
+** Complete execution of a SCSI command.
+** Signal completion to the generic SCSI driver.
+**
+**
+**==========================================================
+*/
+
+void ncr_complete (ncb_p np, ccb_p cp)
+{
+ Scsi_Cmnd *cmd;
+ tcb_p tp;
+ lcb_p lp;
+
+ /*
+ ** Sanity check
+ */
+ if (!cp || !cp->cmd)
+ return;
+
+ /*
+ ** Gather profiling data
+ */
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ncb_profile (np, cp);
+#endif
+
+ if (DEBUG_FLAGS & DEBUG_TINY)
+ printk ("CCB=%lx STAT=%x/%x\n", (unsigned long)cp,
+ cp->host_status,cp->scsi_status);
+
+ /*
+ ** Get command, target and lun pointers.
+ */
+
+ cmd = cp->cmd;
+ cp->cmd = NULL;
+ tp = &np->target[cp->target];
+ lp = tp->lp[cp->lun];
+
+ /*
+ ** We donnot queue more than 1 ccb per target
+ ** with negotiation at any time. If this ccb was
+ ** used for negotiation, clear this info in the tcb.
+ */
+
+ if (cp == tp->nego_cp)
+ tp->nego_cp = 0;
+
+ /*
+ ** If auto-sense performed, change scsi status.
+ */
+ if (cp->auto_sense) {
+ cp->scsi_status = cp->auto_sense;
+ }
+
+ /*
+ ** Check for parity errors.
+ */
+
+ if (cp->host_flags & HF_PAR_ERR) {
+ PRINT_ADDR(cmd);
+ printk ("unrecovered SCSI parity error.\n");
+ if (cp->host_status==HS_COMPLETE)
+ cp->host_status = HS_FAIL;
+ }
+
+ /*
+ ** Check for extended errors.
+ */
+
+ if (cp->xerr_status != XE_OK) {
+ PRINT_ADDR(cmd);
+ switch (cp->xerr_status) {
+ case XE_EXTRA_DATA:
+ printk ("extraneous data discarded.\n");
+ break;
+ case XE_BAD_PHASE:
+ printk ("illegal scsi phase (4/5).\n");
+ break;
+ default:
+ printk ("extended error %d.\n", cp->xerr_status);
+ break;
+ }
+ if (cp->host_status==HS_COMPLETE)
+ cp->host_status = HS_FAIL;
+ }
+
+ /*
+ ** Print out any error for debugging purpose.
+ */
+ if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) {
+ if (cp->host_status!=HS_COMPLETE || cp->scsi_status!=S_GOOD) {
+ PRINT_ADDR(cmd);
+ printk ("ERROR: cmd=%x host_status=%x scsi_status=%x\n",
+ cmd->cmnd[0], cp->host_status, cp->scsi_status);
+ }
+ }
+
+ /*
+ ** Check the status.
+ */
+ if ( (cp->host_status == HS_COMPLETE)
+ && (cp->scsi_status == S_GOOD ||
+ cp->scsi_status == S_COND_MET)) {
+ /*
+ ** All went well (GOOD status).
+ ** CONDITION MET status is returned on
+ ** `Pre-Fetch' or `Search data' success.
+ */
+ SetScsiResult(cmd, DID_OK, cp->scsi_status);
+
+ /*
+ ** @RESID@
+ ** Could dig out the correct value for resid,
+ ** but it would be quite complicated.
+ */
+ /* if (cp->phys.header.lastp != cp->phys.header.goalp) */
+
+ /*
+ ** Allocate the lcb if not yet.
+ */
+ if (!lp)
+ ncr_alloc_lcb (np, cp->target, cp->lun);
+
+ /*
+ ** On standard INQUIRY response (EVPD and CmDt
+ ** not set), setup logical unit according to
+ ** announced capabilities (we need the 1rst 7 bytes).
+ */
+ if (cmd->cmnd[0] == 0x12 && !(cmd->cmnd[1] & 0x3) &&
+ cmd->cmnd[4] >= 7 && !cmd->use_sg) {
+ ncr_setup_lcb (np, cp->target, cp->lun,
+ (char *) cmd->request_buffer);
+ }
+
+ tp->bytes += cp->data_len;
+ tp->transfers ++;
+
+ /*
+ ** If tags was reduced due to queue full,
+ ** increase tags if 1000 good status received.
+ */
+ if (lp && lp->usetags && lp->numtags < lp->maxtags) {
+ ++lp->num_good;
+ if (lp->num_good >= 1000) {
+ lp->num_good = 0;
+ ++lp->numtags;
+ ncr_setup_tags (np, cp->target, cp->lun);
+ }
+ }
+ } else if ((cp->host_status == HS_COMPLETE)
+ && (cp->scsi_status == S_CHECK_COND)) {
+ /*
+ ** Check condition code
+ */
+ SetScsiResult(cmd, DID_OK, S_CHECK_COND);
+
+ if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) {
+ u_char * p = (u_char*) & cmd->sense_buffer;
+ int i;
+ PRINT_ADDR(cmd);
+ printk ("sense data:");
+ for (i=0; i<14; i++) printk (" %x", *p++);
+ printk (".\n");
+ }
+
+ } else if ((cp->host_status == HS_COMPLETE)
+ && (cp->scsi_status == S_BUSY ||
+ cp->scsi_status == S_QUEUE_FULL)) {
+
+ /*
+ ** Target is busy.
+ */
+ SetScsiResult(cmd, DID_OK, cp->scsi_status);
+
+ } else if ((cp->host_status == HS_SEL_TIMEOUT)
+ || (cp->host_status == HS_TIMEOUT)) {
+
+ /*
+ ** No response
+ */
+ SetScsiResult(cmd, DID_TIME_OUT, cp->scsi_status);
+
+ } else if (cp->host_status == HS_RESET) {
+
+ /*
+ ** SCSI bus reset
+ */
+ SetScsiResult(cmd, DID_RESET, cp->scsi_status);
+
+ } else if (cp->host_status == HS_ABORTED) {
+
+ /*
+ ** Transfer aborted
+ */
+ SetScsiResult(cmd, DID_ABORT, cp->scsi_status);
+
+ } else {
+
+ /*
+ ** Other protocol messes
+ */
+ PRINT_ADDR(cmd);
+ printk ("COMMAND FAILED (%x %x) @%p.\n",
+ cp->host_status, cp->scsi_status, cp);
+
+ SetScsiResult(cmd, DID_ERROR, cp->scsi_status);
+ }
+
+ /*
+ ** trace output
+ */
+
+ if (tp->usrflag & UF_TRACE) {
+ u_char * p;
+ int i;
+ PRINT_ADDR(cmd);
+ printk (" CMD:");
+ p = (u_char*) &cmd->cmnd[0];
+ for (i=0; i<cmd->cmd_len; i++) printk (" %x", *p++);
+
+ if (cp->host_status==HS_COMPLETE) {
+ switch (cp->scsi_status) {
+ case S_GOOD:
+ printk (" GOOD");
+ break;
+ case S_CHECK_COND:
+ printk (" SENSE:");
+ p = (u_char*) &cmd->sense_buffer;
+ for (i=0; i<14; i++)
+ printk (" %x", *p++);
+ break;
+ default:
+ printk (" STAT: %x\n", cp->scsi_status);
+ break;
+ }
+ } else printk (" HOSTERROR: %x", cp->host_status);
+ printk ("\n");
+ }
+
+ /*
+ ** Free this ccb
+ */
+ ncr_free_ccb (np, cp);
+
+ /*
+ ** requeue awaiting scsi commands for this lun.
+ */
+ if (lp && lp->queuedccbs < lp->queuedepth &&
+ !xpt_que_empty(&lp->wait_ccbq))
+ ncr_start_next_ccb(np, lp, 2);
+
+ /*
+ ** requeue awaiting scsi commands for this controller.
+ */
+ if (np->waiting_list)
+ requeue_waiting_list(np);
+
+ /*
+ ** signal completion to generic driver.
+ */
+ ncr_queue_done_cmd(np, cmd);
+}
+
+/*==========================================================
+**
+**
+** Signal all (or one) control block done.
+**
+**
+**==========================================================
+*/
+
+/*
+** The NCR has completed CCBs.
+** Look at the DONE QUEUE.
+*/
+int ncr_wakeup_done (ncb_p np)
+{
+ ccb_p cp;
+ int i, n;
+ u_long dsa;
+
+ n = 0;
+ i = np->dqueueget;
+ while (1) {
+ dsa = scr_to_cpu(np->dqueue[i]);
+ if (!dsa)
+ break;
+ np->dqueue[i] = 0;
+ if ((i = i+2) >= MAX_START*2)
+ i = 0;
+
+ cp = ncr_ccb_from_dsa(np, dsa);
+ if (cp) {
+ ncr_complete (np, cp);
+ ++n;
+ }
+ else
+ printk (KERN_ERR "%s: bad DSA (%lx) in done queue.\n",
+ ncr_name(np), dsa);
+ }
+ np->dqueueget = i;
+
+ return n;
+}
+
+/*
+** Complete all active CCBs.
+*/
+void ncr_wakeup (ncb_p np, u_long code)
+{
+ ccb_p cp = np->ccbc;
+
+ while (cp) {
+ if (cp->host_status != HS_IDLE) {
+ cp->host_status = code;
+ ncr_complete (np, cp);
+ }
+ cp = cp->link_ccb;
+ }
+}
+
+/*==========================================================
+**
+**
+** Start NCR chip.
+**
+**
+**==========================================================
+*/
+
+void ncr_init (ncb_p np, int reset, char * msg, u_long code)
+{
+ int i;
+ u_long phys;
+
+ /*
+ ** Reset chip if asked, otherwise just clear fifos.
+ */
+
+ if (reset)
+ ncr_soft_reset(np);
+ else {
+ OUTB (nc_stest3, TE|CSF);
+ OUTONB (nc_ctest3, CLF);
+ }
+
+ /*
+ ** Message.
+ */
+
+ if (msg) printk (KERN_INFO "%s: restart (%s).\n", ncr_name (np), msg);
+
+ /*
+ ** Clear Start Queue
+ */
+ phys = vtobus(np->squeue);
+ np->queuedepth = MAX_START - 1; /* 1 entry needed as end marker */
+ for (i = 0; i < MAX_START*2; i += 2) {
+ np->squeue[i] = cpu_to_scr(np->p_idletask);
+ np->squeue[i+1] = cpu_to_scr(phys + (i+2)*4);
+ }
+ np->squeue[MAX_START*2-1] = cpu_to_scr(phys);
+
+
+ /*
+ ** Start at first entry.
+ */
+ np->squeueput = 0;
+ np->script0->startpos[0] = cpu_to_scr(phys);
+
+ /*
+ ** Clear Done Queue
+ */
+ phys = vtobus(np->dqueue);
+ for (i = 0; i < MAX_START*2; i += 2) {
+ np->dqueue[i] = 0;
+ np->dqueue[i+1] = cpu_to_scr(phys + (i+2)*4);
+ }
+ np->dqueue[MAX_START*2-1] = cpu_to_scr(phys);
+
+ /*
+ ** Start at first entry.
+ */
+ np->script0->done_pos[0] = cpu_to_scr(phys);
+ np->dqueueget = 0;
+
+ /*
+ ** Wakeup all pending jobs.
+ */
+ ncr_wakeup (np, code);
+
+ /*
+ ** Init chip.
+ */
+
+ OUTB (nc_istat, 0x00 ); /* Remove Reset, abort */
+ UDELAY (2000); /* The 895 needs time for the bus mode to settle */
+
+ OUTB (nc_scntl0, np->rv_scntl0 | 0xc0);
+ /* full arb., ena parity, par->ATN */
+ OUTB (nc_scntl1, 0x00); /* odd parity, and remove CRST!! */
+
+ ncr_selectclock(np, np->rv_scntl3); /* Select SCSI clock */
+
+ OUTB (nc_scid , RRE|np->myaddr); /* Adapter SCSI address */
+ OUTW (nc_respid, 1ul<<np->myaddr); /* Id to respond to */
+ OUTB (nc_istat , SIGP ); /* Signal Process */
+ OUTB (nc_dmode , np->rv_dmode); /* Burst length, dma mode */
+ OUTB (nc_ctest5, np->rv_ctest5); /* Large fifo + large burst */
+
+ OUTB (nc_dcntl , NOCOM|np->rv_dcntl); /* Protect SFBR */
+ OUTB (nc_ctest3, np->rv_ctest3); /* Write and invalidate */
+ OUTB (nc_ctest4, np->rv_ctest4); /* Master parity checking */
+
+ OUTB (nc_stest2, EXT|np->rv_stest2); /* Extended Sreq/Sack filtering */
+ OUTB (nc_stest3, TE); /* TolerANT enable */
+ OUTB (nc_stime0, 0x0c); /* HTH disabled STO 0.25 sec */
+
+ /*
+ ** DEL 441 - 53C876 Rev 5 - Part Number 609-0392787/2788 - ITEM 2.
+ ** Disable overlapped arbitration.
+ ** The 896 Rev 1 needs also this work-around to be applied.
+ */
+ if (np->device_id == PCI_DEVICE_ID_NCR_53C875 &&
+ np->revision_id >= 0x10 && np->revision_id <= 0x15)
+ OUTB (nc_ctest0, (1<<5));
+ else if (np->device_id == PCI_DEVICE_ID_NCR_53C896 &&
+ np->revision_id <= 0x1)
+ np->rv_ccntl0 |= DPR;
+
+ /*
+ ** If 64 bit (53C896) enable 40 bit address table
+ ** indirect addressing for MOVE.
+ */
+
+ if (np->features & FE_64BIT) {
+ OUTB (nc_ccntl1, np->rv_ccntl1);
+ }
+
+ /*
+ ** If phase mismatch handled by scripts (53C896),
+ ** set PM jump addresses.
+ */
+
+ if (np->features & FE_NOPM) {
+ printk(KERN_INFO "%s: handling phase mismatch from SCRIPTS.\n",
+ ncr_name(np));
+ OUTB (nc_ccntl0, np->rv_ccntl0);
+ OUTL (nc_pmjad1, NCB_SCRIPTH_PHYS (np, pm_handle));
+ OUTL (nc_pmjad2, NCB_SCRIPTH_PHYS (np, pm_handle));
+ }
+
+ /*
+ ** Enable GPIO0 pin for writing if LED support from SCRIPTS.
+ ** Also set GPIO5 and clear GPIO6 if hardware LED control.
+ */
+
+ if (np->features & FE_LED0)
+ OUTB(nc_gpcntl, INB(nc_gpcntl) & ~0x01);
+ else if (np->features & FE_LEDC)
+ OUTB(nc_gpcntl, (INB(nc_gpcntl) & ~0x41) | 0x20);
+
+
+ /*
+ ** enable ints
+ */
+
+ OUTW (nc_sien , STO|HTH|MA|SGE|UDC|RST|PAR);
+ OUTB (nc_dien , MDPE|BF|SSI|SIR|IID);
+
+ /*
+ ** For 895/6 enable SBMC interrupt and save current SCSI bus mode.
+ */
+ if (np->features & FE_ULTRA2) {
+ OUTONW (nc_sien, SBMC);
+ np->scsi_mode = INB (nc_stest4) & SMODE;
+ }
+
+ /*
+ ** Fill in target structure.
+ ** Reinitialize usrsync.
+ ** Reinitialize usrwide.
+ ** Prepare sync negotiation according to actual SCSI bus mode.
+ */
+
+ for (i=0;i<MAX_TARGET;i++) {
+ tcb_p tp = &np->target[i];
+
+ tp->sval = 0;
+ tp->wval = np->rv_scntl3;
+
+ if (tp->usrsync != 255) {
+ if (tp->usrsync <= np->maxsync) {
+ if (tp->usrsync < np->minsync) {
+ tp->usrsync = np->minsync;
+ }
+ }
+ else
+ tp->usrsync = 255;
+ };
+
+ if (tp->usrwide > np->maxwide)
+ tp->usrwide = np->maxwide;
+
+ ncr_negotiate (np, tp);
+ }
+
+ /*
+ ** Start script processor.
+ */
+ MEMORY_BARRIER();
+ if (np->base2_ba) {
+ if (bootverbose)
+ printk ("%s: Downloading SCSI SCRIPTS.\n",
+ ncr_name(np));
+ if (np->features & FE_RAM8K)
+ phys = NCB_SCRIPTH0_PHYS (np, start_ram64);
+ else
+ phys = NCB_SCRIPTH_PHYS (np, start_ram);
+ }
+ else
+ phys = NCB_SCRIPT_PHYS (np, init);
+
+ OUTL (nc_dsa, vtobus(np));
+ OUTL (nc_dsp, phys);
+}
+
+/*==========================================================
+**
+** Prepare the negotiation values for wide and
+** synchronous transfers.
+**
+**==========================================================
+*/
+
+static void ncr_negotiate (struct ncb* np, struct tcb* tp)
+{
+ /*
+ ** minsync unit is 4ns !
+ */
+
+ u_long minsync = tp->usrsync;
+
+ /*
+ ** SCSI bus mode limit
+ */
+
+ if (np->scsi_mode && np->scsi_mode == SMODE_SE) {
+ if (minsync < 12) minsync = 12;
+ }
+
+ /*
+ ** our limit ..
+ */
+
+ if (minsync < np->minsync)
+ minsync = np->minsync;
+
+ /*
+ ** divider limit
+ */
+
+ if (minsync > np->maxsync)
+ minsync = 255;
+
+ tp->minsync = minsync;
+ tp->maxoffs = (minsync<255 ? np->maxoffs : 0);
+
+ /*
+ ** period=0: has to negotiate sync transfer
+ */
+
+ tp->period=0;
+
+ /*
+ ** widedone=0: has to negotiate wide transfer
+ */
+ tp->widedone=0;
+}
+
+/*==========================================================
+**
+** Get clock factor and sync divisor for a given
+** synchronous factor period.
+** Returns the clock factor (in sxfer) and scntl3
+** synchronous divisor field.
+**
+**==========================================================
+*/
+
+static void ncr_getsync(ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p)
+{
+ u_long clk = np->clock_khz; /* SCSI clock frequency in kHz */
+ int div = np->clock_divn; /* Number of divisors supported */
+ u_long fak; /* Sync factor in sxfer */
+ u_long per; /* Period in tenths of ns */
+ u_long kpc; /* (per * clk) */
+
+ /*
+ ** Compute the synchronous period in tenths of nano-seconds
+ */
+ if (sfac <= 10) per = 250;
+ else if (sfac == 11) per = 303;
+ else if (sfac == 12) per = 500;
+ else per = 40 * sfac;
+
+ /*
+ ** Look for the greatest clock divisor that allows an
+ ** input speed faster than the period.
+ */
+ kpc = per * clk;
+ while (--div >= 0)
+ if (kpc >= (div_10M[div] << 2)) break;
+
+ /*
+ ** Calculate the lowest clock factor that allows an output
+ ** speed not faster than the period.
+ */
+ fak = (kpc - 1) / div_10M[div] + 1;
+
+#if 0 /* This optimization does not seem very usefull */
+
+ per = (fak * div_10M[div]) / clk;
+
+ /*
+ ** Why not to try the immediate lower divisor and to choose
+ ** the one that allows the fastest output speed ?
+ ** We dont want input speed too much greater than output speed.
+ */
+ if (div >= 1 && fak < 8) {
+ u_long fak2, per2;
+ fak2 = (kpc - 1) / div_10M[div-1] + 1;
+ per2 = (fak2 * div_10M[div-1]) / clk;
+ if (per2 < per && fak2 <= 8) {
+ fak = fak2;
+ per = per2;
+ --div;
+ }
+ }
+#endif
+
+ if (fak < 4) fak = 4; /* Should never happen, too bad ... */
+
+ /*
+ ** Compute and return sync parameters for the ncr
+ */
+ *fakp = fak - 4;
+ *scntl3p = ((div+1) << 4) + (sfac < 25 ? 0x80 : 0);
+}
+
+
+/*==========================================================
+**
+** Set actual values, sync status and patch all ccbs of
+** a target according to new sync/wide agreement.
+**
+**==========================================================
+*/
+
+static void ncr_set_sync_wide_status (ncb_p np, u_char target)
+{
+ ccb_p cp;
+ tcb_p tp = &np->target[target];
+
+ /*
+ ** set actual value and sync_status
+ */
+ OUTB (nc_sxfer, tp->sval);
+ OUTB (nc_scntl3, tp->wval);
+
+ /*
+ ** patch ALL ccbs of this target.
+ */
+ for (cp = np->ccbc; cp; cp = cp->link_ccb) {
+ if (cp->host_status == HS_IDLE)
+ continue;
+ if (cp->target != target)
+ continue;
+ cp->phys.select.sel_scntl3 = tp->wval;
+ cp->phys.select.sel_sxfer = tp->sval;
+ };
+}
+
+/*==========================================================
+**
+** Switch sync mode for current job and it's target
+**
+**==========================================================
+*/
+
+static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer)
+{
+ tcb_p tp;
+ u_char target = INB (nc_sdid) & 0x0f;
+ u_char idiv;
+
+ assert (cp);
+ if (!cp) return;
+
+ assert (target == (cp->target & 0xf));
+
+ tp = &np->target[target];
+
+ if (!scntl3 || !(sxfer & 0x1f))
+ scntl3 = np->rv_scntl3;
+ scntl3 = (scntl3 & 0xf0) | (tp->wval & EWS) | (np->rv_scntl3 & 0x07);
+
+ /*
+ ** Deduce the value of controller sync period from scntl3.
+ ** period is in tenths of nano-seconds.
+ */
+
+ idiv = ((scntl3 >> 4) & 0x7);
+ if ((sxfer & 0x1f) && idiv)
+ tp->period = (((sxfer>>5)+4)*div_10M[idiv-1])/np->clock_khz;
+ else
+ tp->period = 0xffff;
+
+ /*
+ ** Stop there if sync parameters are unchanged
+ */
+ if (tp->sval == sxfer && tp->wval == scntl3) return;
+ tp->sval = sxfer;
+ tp->wval = scntl3;
+
+ /*
+ ** Bells and whistles ;-)
+ */
+ PRINT_TARGET(np, target);
+ if (sxfer & 0x01f) {
+ unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0);
+ unsigned mb10 = (f10 + tp->period/2) / tp->period;
+ char *scsi;
+
+ /*
+ ** Disable extended Sreq/Sack filtering
+ */
+ if (tp->period <= 2000) OUTOFFB (nc_stest2, EXT);
+
+ /*
+ ** Bells and whistles ;-)
+ */
+ if (tp->period < 500) scsi = "FAST-40";
+ else if (tp->period < 1000) scsi = "FAST-20";
+ else if (tp->period < 2000) scsi = "FAST-10";
+ else scsi = "FAST-5";
+
+ printk ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi,
+ tp->widedone > 1 ? "WIDE " : "",
+ mb10 / 10, mb10 % 10, tp->period / 10, sxfer & 0x1f);
+ } else
+ printk ("%sasynchronous.\n", tp->widedone > 1 ? "wide " : "");
+
+ /*
+ ** set actual value and sync_status
+ ** patch ALL ccbs of this target.
+ */
+ ncr_set_sync_wide_status(np, target);
+}
+
+/*==========================================================
+**
+** Switch wide mode for current job and it's target
+** SCSI specs say: a SCSI device that accepts a WDTR
+** message shall reset the synchronous agreement to
+** asynchronous mode.
+**
+**==========================================================
+*/
+
+static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack)
+{
+ u_short target = INB (nc_sdid) & 0x0f;
+ tcb_p tp;
+ u_char scntl3;
+ u_char sxfer;
+
+ assert (cp);
+ if (!cp) return;
+
+ assert (target == (cp->target & 0xf));
+
+ tp = &np->target[target];
+ tp->widedone = wide+1;
+ scntl3 = (tp->wval & (~EWS)) | (wide ? EWS : 0);
+
+ sxfer = ack ? 0 : tp->sval;
+
+ /*
+ ** Stop there if sync/wide parameters are unchanged
+ */
+ if (tp->sval == sxfer && tp->wval == scntl3) return;
+ tp->sval = sxfer;
+ tp->wval = scntl3;
+
+ /*
+ ** Bells and whistles ;-)
+ */
+ if (bootverbose >= 2) {
+ PRINT_TARGET(np, target);
+ if (scntl3 & EWS)
+ printk ("WIDE SCSI (16 bit) enabled.\n");
+ else
+ printk ("WIDE SCSI disabled.\n");
+ }
+
+ /*
+ ** set actual value and sync_status
+ ** patch ALL ccbs of this target.
+ */
+ ncr_set_sync_wide_status(np, target);
+}
+
+/*==========================================================
+**
+** Switch tagged mode for a target.
+**
+**==========================================================
+*/
+
+static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln)
+{
+ tcb_p tp = &np->target[tn];
+ lcb_p lp = tp->lp[ln];
+ u_char reqtags, maxdepth;
+
+ /*
+ ** Just in case ...
+ */
+ if ((!tp) || (!lp))
+ return;
+
+ /*
+ ** If SCSI device queue depth is not yet set, leave here.
+ */
+ if (!lp->scdev_depth)
+ return;
+
+ /*
+ ** Donnot allow more tags than the SCSI driver can queue
+ ** for this device.
+ ** Donnot allow more tags than we can handle.
+ */
+ maxdepth = lp->scdev_depth;
+ if (maxdepth > lp->maxnxs) maxdepth = lp->maxnxs;
+ if (lp->maxtags > maxdepth) lp->maxtags = maxdepth;
+ if (lp->numtags > maxdepth) lp->numtags = maxdepth;
+
+ /*
+ ** only devices conformant to ANSI Version >= 2
+ ** only devices capable of tagged commands
+ ** only if enabled by user ..
+ */
+ if ((lp->inq_byte7 & INQ7_QUEUE) && lp->numtags > 1) {
+ reqtags = lp->numtags;
+ } else {
+ reqtags = 1;
+ };
+
+ /*
+ ** Update max number of tags
+ */
+ lp->numtags = reqtags;
+ if (lp->numtags > lp->maxtags)
+ lp->maxtags = lp->numtags;
+
+ /*
+ ** If we want to switch tag mode, we must wait
+ ** for no CCB to be active.
+ */
+ if (reqtags > 1 && lp->usetags) { /* Stay in tagged mode */
+ if (lp->queuedepth == reqtags) /* Already announced */
+ return;
+ lp->queuedepth = reqtags;
+ }
+ else if (reqtags <= 1 && !lp->usetags) { /* Stay in untagged mode */
+ lp->queuedepth = reqtags;
+ return;
+ }
+ else { /* Want to switch tag mode */
+ if (lp->busyccbs) /* If not yet safe, return */
+ return;
+ lp->queuedepth = reqtags;
+ lp->usetags = reqtags > 1 ? 1 : 0;
+ }
+
+ /*
+ ** Patch the lun mini-script, according to tag mode.
+ */
+ lp->resel_task = lp->usetags?
+ cpu_to_scr(NCB_SCRIPT_PHYS(np, resel_tag)) :
+ cpu_to_scr(NCB_SCRIPT_PHYS(np, resel_notag));
+
+ /*
+ ** Announce change to user.
+ */
+ if (bootverbose) {
+ PRINT_LUN(np, tn, ln);
+ if (lp->usetags)
+ printk("tagged command queue depth set to %d\n", reqtags);
+ else
+ printk("tagged command queueing disabled\n");
+ }
+}
+
+/*----------------------------------------------------
+**
+** handle user commands
+**
+**----------------------------------------------------
+*/
+
+#ifdef SCSI_NCR_USER_COMMAND_SUPPORT
+
+static void ncr_usercmd (ncb_p np)
+{
+ u_char t;
+ tcb_p tp;
+
+ switch (np->user.cmd) {
+
+ case 0: return;
+
+ case UC_SETSYNC:
+ for (t=0; t<MAX_TARGET; t++) {
+ if (!((np->user.target>>t)&1)) continue;
+ tp = &np->target[t];
+ tp->usrsync = np->user.data;
+ ncr_negotiate (np, tp);
+ };
+ break;
+
+ case UC_SETTAGS:
+ for (t=0; t<MAX_TARGET; t++) {
+ int ln;
+ if (!((np->user.target>>t)&1)) continue;
+ np->target[t].usrtags = np->user.data;
+ for (ln = 0; ln < MAX_LUN; ln++) {
+ lcb_p lp = np->target[t].lp[ln];
+ if (!lp)
+ continue;
+ lp->maxtags = lp->numtags = np->user.data;
+ ncr_setup_tags (np, t, ln);
+ }
+ };
+ break;
+
+ case UC_SETDEBUG:
+#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
+ ncr_debug = np->user.data;
+#endif
+ break;
+
+ case UC_SETORDER:
+ np->order = np->user.data;
+ break;
+
+ case UC_SETVERBOSE:
+ np->verbose = np->user.data;
+ break;
+
+ case UC_SETWIDE:
+ for (t=0; t<MAX_TARGET; t++) {
+ u_long size;
+ if (!((np->user.target>>t)&1)) continue;
+ tp = &np->target[t];
+ size = np->user.data;
+ if (size > np->maxwide) size=np->maxwide;
+ tp->usrwide = size;
+ ncr_negotiate (np, tp);
+ };
+ break;
+
+ case UC_SETFLAG:
+ for (t=0; t<MAX_TARGET; t++) {
+ if (!((np->user.target>>t)&1)) continue;
+ tp = &np->target[t];
+ tp->usrflag = np->user.data;
+ };
+ break;
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ case UC_CLEARPROF:
+ bzero(&np->profile, sizeof(np->profile));
+ break;
+#endif
+ }
+ np->user.cmd=0;
+}
+#endif
+
+/*==========================================================
+**
+**
+** ncr timeout handler.
+**
+**
+**==========================================================
+**
+** Misused to keep the driver running when
+** interrupts are not configured correctly.
+**
+**----------------------------------------------------------
+*/
+
+static void ncr_timeout (ncb_p np)
+{
+ u_long thistime = jiffies;
+
+ /*
+ ** If release process in progress, let's go
+ ** Set the release stage from 1 to 2 to synchronize
+ ** with the release process.
+ */
+
+ if (np->release_stage) {
+ if (np->release_stage == 1) np->release_stage = 2;
+ return;
+ }
+
+ np->timer.expires = jiffies + SCSI_NCR_TIMER_INTERVAL;
+ add_timer(&np->timer);
+
+ /*
+ ** If we are resetting the ncr, wait for settle_time before
+ ** clearing it. Then command processing will be resumed.
+ */
+ if (np->settle_time) {
+ if (np->settle_time <= thistime) {
+ if (bootverbose > 1)
+ printk("%s: command processing resumed\n", ncr_name(np));
+ np->settle_time = 0;
+ requeue_waiting_list(np);
+ }
+ return;
+ }
+
+ /*
+ ** Nothing to do for now, but that may come.
+ */
+ if (np->lasttime + 4*HZ < thistime) {
+ np->lasttime = thistime;
+ }
+
+#ifdef SCSI_NCR_BROKEN_INTR
+ if (INB(nc_istat) & (INTF|SIP|DIP)) {
+
+ /*
+ ** Process pending interrupts.
+ */
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("{");
+ ncr_exception (np);
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("}");
+ }
+#endif /* SCSI_NCR_BROKEN_INTR */
+}
+
+/*==========================================================
+**
+** log message for real hard errors
+**
+** "ncr0 targ 0?: ERROR (ds:si) (so-si-sd) (sxfer/scntl3) @ name (dsp:dbc)."
+** " reg: r0 r1 r2 r3 r4 r5 r6 ..... rf."
+**
+** exception register:
+** ds: dstat
+** si: sist
+**
+** SCSI bus lines:
+** so: control lines as driver by NCR.
+** si: control lines as seen by NCR.
+** sd: scsi data lines as seen by NCR.
+**
+** wide/fastmode:
+** sxfer: (see the manual)
+** scntl3: (see the manual)
+**
+** current script command:
+** dsp: script adress (relative to start of script).
+** dbc: first word of script command.
+**
+** First 16 register of the chip:
+** r0..rf
+**
+**==========================================================
+*/
+
+static void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat)
+{
+ u_int32 dsp;
+ int script_ofs;
+ int script_size;
+ char *script_name;
+ u_char *script_base;
+ int i;
+
+ dsp = INL (nc_dsp);
+
+ if (dsp > np->p_script && dsp <= np->p_script + sizeof(struct script)) {
+ script_ofs = dsp - np->p_script;
+ script_size = sizeof(struct script);
+ script_base = (u_char *) np->script0;
+ script_name = "script";
+ }
+ else if (np->p_scripth < dsp &&
+ dsp <= np->p_scripth + sizeof(struct scripth)) {
+ script_ofs = dsp - np->p_scripth;
+ script_size = sizeof(struct scripth);
+ script_base = (u_char *) np->scripth0;
+ script_name = "scripth";
+ } else {
+ script_ofs = dsp;
+ script_size = 0;
+ script_base = 0;
+ script_name = "mem";
+ }
+
+ printk ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n",
+ ncr_name (np), (unsigned)INB (nc_sdid)&0x0f, dstat, sist,
+ (unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl), (unsigned)INB (nc_sbdl),
+ (unsigned)INB (nc_sxfer),(unsigned)INB (nc_scntl3), script_name, script_ofs,
+ (unsigned)INL (nc_dbc));
+
+ if (((script_ofs & 3) == 0) &&
+ (unsigned)script_ofs < script_size) {
+ printk ("%s: script cmd = %08x\n", ncr_name(np),
+ scr_to_cpu((int) *(ncrcmd *)(script_base + script_ofs)));
+ }
+
+ printk ("%s: regdump:", ncr_name(np));
+ for (i=0; i<16;i++)
+ printk (" %02x", (unsigned)INB_OFF(i));
+ printk (".\n");
+}
+
+/*============================================================
+**
+** ncr chip exception handler.
+**
+**============================================================
+**
+** In normal situations, interrupt conditions occur one at
+** a time. But when something bad happens on the SCSI BUS,
+** the chip may raise several interrupt flags before
+** stopping and interrupting the CPU. The additionnal
+** interrupt flags are stacked in some extra registers
+** after the SIP and/or DIP flag has been raised in the
+** ISTAT. After the CPU has read the interrupt condition
+** flag from SIST or DSTAT, the chip unstacks the other
+** interrupt flags and sets the corresponding bits in
+** SIST or DSTAT. Since the chip starts stacking once the
+** SIP or DIP flag is set, there is a small window of time
+** where the stacking does not occur.
+**
+** Typically, multiple interrupt conditions may happen in
+** the following situations:
+**
+** - SCSI parity error + Phase mismatch (PAR|MA)
+** When an parity error is detected in input phase
+** and the device switches to msg-in phase inside a
+** block MOV.
+** - SCSI parity error + Unexpected disconnect (PAR|UDC)
+** When a stupid device does not want to handle the
+** recovery of an SCSI parity error.
+** - Some combinations of STO, PAR, UDC, ...
+** When using non compliant SCSI stuff, when user is
+** doing non compliant hot tampering on the BUS, when
+** something really bad happens to a device, etc ...
+**
+** The heuristic suggested by SYMBIOS to handle
+** multiple interrupts is to try unstacking all
+** interrupts conditions and to handle them on some
+** priority based on error severity.
+** This will work when the unstacking has been
+** successful, but we cannot be 100 % sure of that,
+** since the CPU may have been faster to unstack than
+** the chip is able to stack. Hmmm ... But it seems that
+** such a situation is very unlikely to happen.
+**
+** If this happen, for example STO catched by the CPU
+** then UDC happenning before the CPU have restarted
+** the SCRIPTS, the driver may wrongly complete the
+** same command on UDC, since the SCRIPTS didn't restart
+** and the DSA still points to the same command.
+** We avoid this situation by setting the DSA to an
+** invalid value when the CCB is completed and before
+** restarting the SCRIPTS.
+**
+** Another issue is that we need some section of our
+** recovery procedures to be somehow uninterruptible and
+** that the SCRIPTS processor does not provides such a
+** feature. For this reason, we handle recovery preferently
+** from the C code and check against some SCRIPTS
+** critical sections from the C code.
+**
+** Hopefully, the interrupt handling of the driver is now
+** able to resist to weird BUS error conditions, but donnot
+** ask me for any guarantee that it will never fail. :-)
+** Use at your own decision and risk.
+**
+**============================================================
+*/
+
+void ncr_exception (ncb_p np)
+{
+ u_char istat, istatc;
+ u_char dstat;
+ u_short sist;
+ int i;
+
+#ifdef SCSI_NCR_OPTIMIZE_896_1
+ /*
+ ** This optimization when used with a 896 that handles
+ ** phase mismatch from the SCRIPTS allows to only do
+ ** PCI memory writes transactions from the CPU and so to
+ ** take advantage of PCI posted writes.
+ ** Who wants his 500 MHz CPU to wait several micro-seconds
+ ** for the PCI BUS to be granted when this can be avoided?
+ ** I don't, even for my slow 233 MHz PII. :-)
+ **
+ ** We assume we have been called for command completion.
+ ** If no completion found, go with normal handling.
+ ** Ordering is ensured by the SCRIPTS performing a read
+ ** from main memory prior to raising INTFLY.
+ ** We have to raise SIGP since the chip may be currently
+ ** going to a wait reselect instruction. IMO, SIGP should
+ ** not be clearable in ISTAT since it can be polled and
+ ** cleared by reading CTEST2. This tiny chip misdesign is a
+ ** penalty here.
+ **
+ ** The MA interrupt and interrupt sharing may also have
+ ** adverse effects on this optimization, so we only want
+ ** to use it if it is enabled by user.
+ ** (BTW, this optimization seems to even have some goodness
+ ** with my 895 that unfortunately suffers of the MA int.).
+ */
+ if (driver_setup.optimize & 1) {
+ OUTB(nc_istat, (INTF | SIGP));
+ if (ncr_wakeup_done (np)) {
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ++np->profile.num_fly;
+#endif
+ return;
+ }
+ }
+#endif /* SCSI_NCR_OPTIMIZE_896_1 */
+
+ /*
+ ** interrupt on the fly ?
+ */
+ istat = INB (nc_istat);
+ if (istat & INTF) {
+ OUTB (nc_istat, (istat & SIGP) | INTF);
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("F ");
+ (void)ncr_wakeup_done (np);
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ++np->profile.num_fly;
+#endif
+ };
+
+ if (!(istat & (SIP|DIP)))
+ return;
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ++np->profile.num_int;
+#endif
+
+#if 0 /* We should never get this one */
+ if (istat & CABRT)
+ OUTB (nc_istat, CABRT);
+#endif
+
+ /*
+ ** Steinbach's Guideline for Systems Programming:
+ ** Never test for an error condition you don't know how to handle.
+ */
+
+ /*========================================================
+ ** PAR and MA interrupts may occur at the same time,
+ ** and we need to know of both in order to handle
+ ** this situation properly. We try to unstack SCSI
+ ** interrupts for that reason. BTW, I dislike a LOT
+ ** such a loop inside the interrupt routine.
+ ** Even if DMA interrupt stacking is very unlikely to
+ ** happen, we also try unstacking these ones, since
+ ** this has no performance impact.
+ **=========================================================
+ */
+ sist = 0;
+ dstat = 0;
+ istatc = istat;
+ do {
+ if (istatc & SIP)
+ sist |= INW (nc_sist);
+ if (istatc & DIP)
+ dstat |= INB (nc_dstat);
+ istatc = INB (nc_istat);
+ istat |= istatc;
+ } while (istatc & (SIP|DIP));
+
+ if (DEBUG_FLAGS & DEBUG_TINY)
+ printk ("<%d|%x:%x|%x:%x>",
+ (int)INB(nc_scr0),
+ dstat,sist,
+ (unsigned)INL(nc_dsp),
+ (unsigned)INL(nc_dbc));
+
+ /*========================================================
+ ** First, interrupts we want to service cleanly.
+ **
+ ** Phase mismatch (MA) is the most frequent interrupt
+ ** for chip earlier than the 896 and so we have to service
+ ** it as quickly as possible.
+ ** A SCSI parity error (PAR) may be combined with a phase
+ ** mismatch condition (MA).
+ ** Programmed interrupts (SIR) are used to call the C code
+ ** from SCRIPTS.
+ ** The single step interrupt (SSI) is not used in this
+ ** driver.
+ **=========================================================
+ */
+
+ if (!(sist & (STO|GEN|HTH|SGE|UDC|SBMC|RST)) &&
+ !(dstat & (MDPE|BF|ABRT|IID))) {
+ if (sist & PAR) ncr_int_par (np, sist);
+ else if (sist & MA) ncr_int_ma (np);
+ else if (dstat & SIR) ncr_int_sir (np);
+ else if (dstat & SSI) OUTONB (nc_dcntl, (STD|NOCOM));
+ else goto unknown_int;
+ return;
+ };
+
+ /*========================================================
+ ** Now, interrupts that donnot happen in normal
+ ** situations and that we may need to recover from.
+ **
+ ** On SCSI RESET (RST), we reset everything.
+ ** On SCSI BUS MODE CHANGE (SBMC), we complete all
+ ** active CCBs with RESET status, prepare all devices
+ ** for negotiating again and restart the SCRIPTS.
+ ** On STO and UDC, we complete the CCB with the corres-
+ ** ponding status and restart the SCRIPTS.
+ **=========================================================
+ */
+
+ if (sist & RST) {
+ ncr_init (np, 1, bootverbose ? "scsi reset" : NULL, HS_RESET);
+ return;
+ };
+
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
+ OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
+
+ if (!(sist & (GEN|HTH|SGE)) &&
+ !(dstat & (MDPE|BF|ABRT|IID))) {
+ if (sist & SBMC) ncr_int_sbmc (np);
+ else if (sist & STO) ncr_int_sto (np);
+ else if (sist & UDC) ncr_int_udc (np);
+ else goto unknown_int;
+ return;
+ };
+
+ /*=========================================================
+ ** Now, interrupts we are not able to recover cleanly.
+ **
+ ** Do the register dump.
+ ** Log message for hard errors.
+ ** Reset everything.
+ **=========================================================
+ */
+ if (jiffies - np->regtime > 10*HZ) {
+ np->regtime = jiffies;
+ for (i = 0; i<sizeof(np->regdump); i++)
+ ((char*)&np->regdump)[i] = INB_OFF(i);
+ np->regdump.nc_dstat = dstat;
+ np->regdump.nc_sist = sist;
+ };
+
+ ncr_log_hard_error(np, sist, dstat);
+
+ if ((sist & (GEN|HTH|SGE)) ||
+ (dstat & (MDPE|BF|ABRT|IID))) {
+ ncr_start_reset(np);
+ return;
+ };
+
+unknown_int:
+ /*=========================================================
+ ** We just miss the cause of the interrupt. :(
+ ** Print a message. The timeout will do the real work.
+ **=========================================================
+ */
+ printk( "%s: unknown interrupt(s) ignored, "
+ "ISTAT=0x%x DSTAT=0x%x SIST=0x%x\n",
+ ncr_name(np), istat, dstat, sist);
+}
+
+
+/*==========================================================
+**
+** generic recovery from scsi interrupt
+**
+**==========================================================
+**
+** The doc says that when the chip gets an SCSI interrupt,
+** it tries to stop in an orderly fashion, by completing
+** an instruction fetch that had started or by flushing
+** the DMA fifo for a write to memory that was executing.
+** Such a fashion is not enough to know if the instruction
+** that was just before the current DSP value has been
+** executed or not.
+**
+** There are 3 small SCRIPTS sections that deal with the
+** start queue and the done queue that may break any
+** assomption from the C code if we are interrupted
+** inside, so we reset if it happens. Btw, since these
+** SCRIPTS sections are executed while the SCRIPTS hasn't
+** started SCSI operations, it is very unlikely to happen.
+**
+** All the driver data structures are supposed to be
+** allocated from the same 4 GB memory window, so there
+** is a 1 to 1 relationship between DSA and driver data
+** structures. Since we are careful :) to invalidate the
+** DSA when we complete a command or when the SCRIPTS
+** pushes a DSA into a queue, we can trust it when it
+** points to a CCB.
+**
+**----------------------------------------------------------
+*/
+static void ncr_recover_scsi_int (ncb_p np, u_char hsts)
+{
+ u_int32 dsp = INL (nc_dsp);
+ u_int32 dsa = INL (nc_dsa);
+ u_char scntl1 = INB (nc_scntl1);
+ ccb_p cp = ncr_ccb_from_dsa(np, dsa);
+
+ /*
+ ** If we are connected to the SCSI BUS, we only
+ ** can reset the BUS.
+ */
+ if (scntl1 & ISCON)
+ goto reset_all;
+
+ /*
+ ** If we haven't been interrupted inside the SCRIPTS
+ ** critical pathes, we can safely restart the SCRIPTS
+ ** and trust the DSA value if it matches a CCB.
+ */
+ if ((!(dsp > NCB_SCRIPT_PHYS (np, getjob_begin) &&
+ dsp < NCB_SCRIPT_PHYS (np, getjob_end) + 1)) &&
+ (!(dsp > NCB_SCRIPT_PHYS (np, ungetjob) &&
+ dsp < NCB_SCRIPT_PHYS (np, reselect) + 1)) &&
+ (!(dsp > NCB_SCRIPT_PHYS (np, done) &&
+ dsp < NCB_SCRIPT_PHYS (np, done_end) + 1))) {
+ if (cp) {
+ cp->host_status = hsts;
+ ncr_complete (np, cp);
+ }
+ OUTL (nc_dsa, DSA_INVALID);
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
+ OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start));
+ }
+ else
+ goto reset_all;
+
+ return;
+
+reset_all:
+ ncr_start_reset(np);
+}
+
+/*==========================================================
+**
+** ncr chip exception handler for selection timeout
+**
+**==========================================================
+**
+** There seems to be a bug in the 53c810.
+** Although a STO-Interrupt is pending,
+** it continues executing script commands.
+** But it will fail and interrupt (IID) on
+** the next instruction where it's looking
+** for a valid phase.
+**
+**----------------------------------------------------------
+*/
+
+void ncr_int_sto (ncb_p np)
+{
+ u_int32 dsp = INL (nc_dsp);
+
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("T");
+
+ if (dsp == NCB_SCRIPT_PHYS (np, wf_sel_done) + 8 ||
+ dsp == NCB_SCRIPTH_PHYS (np, wf_sel_done_no_atn) + 8 ||
+ !(driver_setup.recovery & 1))
+ ncr_recover_scsi_int(np, HS_SEL_TIMEOUT);
+ else
+ ncr_start_reset(np);
+}
+
+/*==========================================================
+**
+** ncr chip exception handler for unexpected disconnect
+**
+**==========================================================
+**
+**----------------------------------------------------------
+*/
+void ncr_int_udc (ncb_p np)
+{
+ printk ("%s: unexpected disconnect\n", ncr_name(np));
+ ncr_recover_scsi_int(np, HS_UNEXPECTED);
+}
+
+/*==========================================================
+**
+** ncr chip exception handler for SCSI bus mode change
+**
+**==========================================================
+**
+** spi2-r12 11.2.3 says a transceiver mode change must
+** generate a reset event and a device that detects a reset
+** event shall initiate a hard reset. It says also that a
+** device that detects a mode change shall set data transfer
+** mode to eight bit asynchronous, etc...
+** So, just resetting should be enough.
+**
+**
+**----------------------------------------------------------
+*/
+
+static void ncr_int_sbmc (ncb_p np)
+{
+ u_char scsi_mode = INB (nc_stest4) & SMODE;
+
+ printk("%s: SCSI bus mode change from %x to %x.\n",
+ ncr_name(np), np->scsi_mode, scsi_mode);
+
+ np->scsi_mode = scsi_mode;
+
+
+ /*
+ ** Suspend command processing for 1 second and
+ ** reinitialize all except the chip.
+ */
+ np->settle_time = jiffies + HZ;
+ ncr_init (np, 0, bootverbose ? "scsi mode change" : NULL, HS_RESET);
+}
+
+/*==========================================================
+**
+** ncr chip exception handler for SCSI parity error.
+**
+**==========================================================
+**
+** When the chip detects a SCSI parity error and is
+** currently executing a (CH)MOV instruction, it does
+** not interrupt immediately, but tries to finish the
+** transfer of the current scatter entry before
+** interrupting. The following situations may occur:
+**
+** - The complete scatter entry has been transferred
+** without the device having changed phase.
+** The chip will then interrupt with the DSP pointing
+** to the instruction that follows the MOV.
+**
+** - A phase mismatch occurs before the MOV finished
+** and phase errors are to be handled by the C code.
+** The chip will then interrupt with both PAR and MA
+** conditions set.
+**
+** - A phase mismatch occurs before the MOV finished
+** and phase errors are to be handled by SCRIPTS (896).
+** The chip will load the DSP with the phase mismatch
+** JUMP address and interrupt the host processor.
+**
+**----------------------------------------------------------
+*/
+
+static void ncr_int_par (ncb_p np, u_short sist)
+{
+ u_char hsts = INB (HS_PRT);
+ u_int32 dsp = INL (nc_dsp);
+ u_int32 dbc = INL (nc_dbc);
+ u_int32 dsa = INL (nc_dsa);
+ u_char sbcl = INB (nc_sbcl);
+ u_char cmd = dbc >> 24;
+ int phase = cmd & 7;
+
+ printk("%s: SCSI parity error detected: SCR1=%d DBC=%x SBCL=%x\n",
+ ncr_name(np), hsts, dbc, sbcl);
+
+ /*
+ ** Check that the chip is connected to the SCSI BUS.
+ */
+ if (!(INB (nc_scntl1) & ISCON)) {
+ if (!(driver_setup.recovery & 1)) {
+ ncr_recover_scsi_int(np, HS_FAIL);
+ return;
+ }
+ goto reset_all;
+ }
+
+ /*
+ ** If the nexus is not clearly identified, reset the bus.
+ ** We will try to do better later.
+ */
+ if (!ncr_ccb_from_dsa(np, dsa))
+ goto reset_all;
+
+ /*
+ ** Check instruction was a MOV, direction was INPUT and
+ ** ATN is asserted.
+ */
+ if ((cmd & 0xc0) || !(phase & 1) || !(sbcl & 0x8))
+ goto reset_all;
+
+ /*
+ ** Keep track of the parity error.
+ */
+ OUTONB (HF_PRT, HF_PAR_ERR);
+
+ /*
+ ** Prepare the message to send to the device.
+ */
+ np->msgout[0] = (phase == 7) ? M_PARITY : M_ID_ERROR;
+
+ /*
+ ** If the old phase was DATA IN phase, we have to deal with
+ ** the 3 situations described above.
+ ** For other input phases (MSG IN and STATUS), the device
+ ** must resend the whole thing that failed parity checking
+ ** or signal error. So, jumping to dispatcher should be OK.
+ */
+ if (phase == 1) {
+ /* Phase mismatch handled by SCRIPTS */
+ if (dsp == NCB_SCRIPTH_PHYS (np, pm_handle))
+ OUTL (nc_dsp, dsp);
+ /* Phase mismatch handled by the C code */
+ else if (sist & MA)
+ ncr_int_ma (np);
+ /* No phase mismatch occurred */
+ else {
+ OUTL (nc_temp, dsp);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, databreak));
+ }
+ }
+ else
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack));
+ return;
+
+reset_all:
+ ncr_start_reset(np);
+ return;
+}
+
+/*==========================================================
+**
+**
+** ncr chip exception handler for phase errors.
+**
+**
+**==========================================================
+**
+** We have to construct a new transfer descriptor,
+** to transfer the rest of the current block.
+**
+**----------------------------------------------------------
+*/
+
+static void ncr_int_ma (ncb_p np)
+{
+ u_int32 dbc;
+ u_int32 rest;
+ u_int32 dsp;
+ u_int32 dsa;
+ u_int32 nxtdsp;
+ u_int32 *vdsp;
+ u_int32 oadr, olen;
+ u_int32 *tblp;
+ u_int32 newcmd;
+ u_int delta;
+ u_char cmd;
+ u_char hflags, hflags0;
+ struct pm_ctx *pm;
+ ccb_p cp;
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ ++np->profile.num_break;
+#endif
+
+ dsp = INL (nc_dsp);
+ dbc = INL (nc_dbc);
+ dsa = INL (nc_dsa);
+
+ cmd = dbc >> 24;
+ rest = dbc & 0xffffff;
+ delta = 0;
+
+ /*
+ ** locate matching cp.
+ */
+ cp = ncr_ccb_from_dsa(np, dsa);
+
+ /*
+ ** Donnot take into account dma fifo and various buffers in
+ ** DATA IN phase since the chip flushes everything before
+ ** raising the MA interrupt for interrupted INPUT phases.
+ */
+ if ((cmd & 7) != 1) {
+ u_int32 dfifo;
+ u_char ss0, ss2;
+
+ /*
+ ** Read DFIFO, CTEST[4-6] using 1 PCI bus ownership.
+ */
+ dfifo = INL(nc_dfifo);
+
+ /*
+ ** Calculate remaining bytes in DMA fifo.
+ ** (CTEST5 = dfifo >> 16)
+ */
+ if (dfifo & (DFS << 16))
+ delta = ((((dfifo >> 8) & 0x300) |
+ (dfifo & 0xff)) - rest) & 0x3ff;
+ else
+ delta = ((dfifo & 0xff) - rest) & 0x7f;
+
+ /*
+ ** The data in the dma fifo has not been transfered to
+ ** the target -> add the amount to the rest
+ ** and clear the data.
+ ** Check the sstat2 register in case of wide transfer.
+ */
+ rest += delta;
+ ss0 = INB (nc_sstat0);
+ if (ss0 & OLF) rest++;
+ if (ss0 & ORF) rest++;
+ if (cp && (cp->phys.select.sel_scntl3 & EWS)) {
+ ss2 = INB (nc_sstat2);
+ if (ss2 & OLF1) rest++;
+ if (ss2 & ORF1) rest++;
+ };
+
+ /*
+ ** Clear fifos.
+ */
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* dma fifo */
+ OUTB (nc_stest3, TE|CSF); /* scsi fifo */
+ };
+
+ /*
+ ** log the information
+ */
+
+ if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE))
+ printk ("P%x%x RL=%d D=%d ", cmd&7, INB(nc_sbcl)&7,
+ (unsigned) rest, (unsigned) delta);
+
+ /*
+ ** try to find the interrupted script command,
+ ** and the address at which to continue.
+ */
+ vdsp = 0;
+ nxtdsp = 0;
+ if (dsp > np->p_script &&
+ dsp <= np->p_script + sizeof(struct script)) {
+ vdsp = (u_int32 *)((char*)np->script0 + (dsp-np->p_script-8));
+ nxtdsp = dsp;
+ }
+ else if (dsp > np->p_scripth &&
+ dsp <= np->p_scripth + sizeof(struct scripth)) {
+ vdsp = (u_int32 *)((char*)np->scripth0 + (dsp-np->p_scripth-8));
+ nxtdsp = dsp;
+ }
+
+ /*
+ ** log the information
+ */
+ if (DEBUG_FLAGS & DEBUG_PHASE) {
+ printk ("\nCP=%p DSP=%x NXT=%x VDSP=%p CMD=%x ",
+ cp, (unsigned)dsp, (unsigned)nxtdsp, vdsp, cmd);
+ };
+
+ if (!vdsp) {
+ printk ("%s: interrupted SCRIPT address not found.\n",
+ ncr_name (np));
+ goto reset_all;
+ }
+
+ if (!cp) {
+ printk ("%s: SCSI phase error fixup: CCB already dequeued.\n",
+ ncr_name (np));
+ goto reset_all;
+ }
+
+ /*
+ ** get old startaddress and old length.
+ */
+
+ oadr = scr_to_cpu(vdsp[1]);
+
+ if (cmd & 0x10) { /* Table indirect */
+ tblp = (u_int32 *) ((char*) &cp->phys + oadr);
+ olen = scr_to_cpu(tblp[0]);
+ oadr = scr_to_cpu(tblp[1]);
+ } else {
+ tblp = (u_int32 *) 0;
+ olen = scr_to_cpu(vdsp[0]) & 0xffffff;
+ };
+
+ if (DEBUG_FLAGS & DEBUG_PHASE) {
+ printk ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n",
+ (unsigned) (scr_to_cpu(vdsp[0]) >> 24),
+ tblp,
+ (unsigned) olen,
+ (unsigned) oadr);
+ };
+
+ /*
+ ** check cmd against assumed interrupted script command.
+ */
+
+ if (cmd != (scr_to_cpu(vdsp[0]) >> 24)) {
+ PRINT_ADDR(cp->cmd);
+ printk ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n",
+ (unsigned)cmd, (unsigned)scr_to_cpu(vdsp[0]) >> 24);
+
+ goto reset_all;
+ };
+
+ /*
+ ** if old phase not dataphase, leave here.
+ */
+
+ if (cmd & 0x06) {
+ PRINT_ADDR(cp->cmd);
+ printk ("phase change %x-%x %d@%08x resid=%d.\n",
+ cmd&7, INB(nc_sbcl)&7, (unsigned)olen,
+ (unsigned)oadr, (unsigned)rest);
+ goto unexpected_phase;
+ };
+
+ /*
+ ** Choose the correct PM save area.
+ **
+ ** Look at the PM_SAVE SCRIPT if you want to understand
+ ** this stuff. The equivalent code is implemented in
+ ** SCRIPTS for the 896 that is able to handle PM from
+ ** the SCRIPTS processor.
+ */
+
+ hflags0 = INB (HF_PRT);
+ hflags = hflags0;
+
+ if (hflags & (HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED)) {
+ if (hflags & HF_IN_PM0)
+ nxtdsp = scr_to_cpu(cp->phys.pm0.ret);
+ else if (hflags & HF_IN_PM1)
+ nxtdsp = scr_to_cpu(cp->phys.pm1.ret);
+
+ if (hflags & HF_DP_SAVED)
+ hflags ^= HF_ACT_PM;
+ }
+
+ if (!(hflags & HF_ACT_PM)) {
+ pm = &cp->phys.pm0;
+ newcmd = NCB_SCRIPT_PHYS(np, pm0_data);
+ }
+ else {
+ pm = &cp->phys.pm1;
+ newcmd = NCB_SCRIPT_PHYS(np, pm1_data);
+ }
+
+ hflags &= ~(HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED);
+ if (hflags != hflags0)
+ OUTB (HF_PRT, hflags);
+
+ /*
+ ** fillin the phase mismatch context
+ */
+
+ pm->sg.addr = cpu_to_scr(oadr + olen - rest);
+ pm->sg.size = cpu_to_scr(rest);
+ pm->ret = cpu_to_scr(nxtdsp);
+
+ if (DEBUG_FLAGS & DEBUG_PHASE) {
+ PRINT_ADDR(cp->cmd);
+ printk ("PM %x %x %x / %x %x %x.\n",
+ hflags0, hflags, newcmd,
+ (unsigned)scr_to_cpu(pm->sg.addr),
+ (unsigned)scr_to_cpu(pm->sg.size),
+ (unsigned)scr_to_cpu(pm->ret));
+ }
+
+ /*
+ ** fake the return address (to the patch).
+ ** and restart script processor at dispatcher.
+ */
+
+ OUTL (nc_temp, newcmd);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, databreak));
+ return;
+
+ /*
+ ** Unexpected phase changes that occurs when the current phase
+ ** is not a DATA IN or DATA OUT phase are due to error conditions.
+ ** Such event may only happen when the SCRIPTS is using a
+ ** multibyte SCSI MOVE.
+ **
+ ** Phase change Some possible cause
+ **
+ ** COMMAND --> MSG IN SCSI parity error detected by target.
+ ** COMMAND --> STATUS Bad command or refused by target.
+ ** MSG OUT --> MSG IN Message rejected by target.
+ ** MSG OUT --> COMMAND Bogus target that discards extended
+ ** negotiation messages.
+ **
+ ** The code below does not care of the new phase and so
+ ** trusts the target. Why to annoy it ?
+ ** If the interrupted phase is COMMAND phase, we restart at
+ ** dispatcher.
+ ** If a target does not get all the messages after selection,
+ ** the code assumes blindly that the target discards extended
+ ** messages and clears the negotiation status.
+ ** If the target does not want all our response to negotiation,
+ ** we force a SIR_NEGO_PROTO interrupt (it is a hack that avoids
+ ** bloat for such a should_not_happen situation).
+ ** In all other situation, we reset the BUS.
+ ** Are these assumptions reasonnable ? (Wait and see ...)
+ */
+unexpected_phase:
+ dsp -= 8;
+ nxtdsp = 0;
+
+ switch (cmd & 7) {
+ case 2: /* COMMAND phase */
+ nxtdsp = NCB_SCRIPT_PHYS (np, dispatch);
+ break;
+#if 0
+ case 3: /* STATUS phase */
+ nxtdsp = NCB_SCRIPT_PHYS (np, dispatch);
+ break;
+#endif
+ case 6: /* MSG OUT phase */
+ /*
+ ** If the device may want to use untagged when we want
+ ** tagged, we prepare an IDENTIFY without disc. granted,
+ ** since we will not be able to handle reselect.
+ ** Otherwise, we just don't care.
+ */
+ if (dsp == NCB_SCRIPT_PHYS (np, send_ident)) {
+ if (cp->tag != NO_TAG && olen - rest <= 3) {
+ cp->host_status = HS_BUSY;
+ np->msgout[0] = M_IDENTIFY | cp->lun;
+ nxtdsp = NCB_SCRIPTH_PHYS (np, ident_break_atn);
+ }
+ else
+ nxtdsp = NCB_SCRIPTH_PHYS (np, ident_break);
+ }
+ else if (dsp == NCB_SCRIPTH_PHYS (np, send_wdtr) ||
+ dsp == NCB_SCRIPTH_PHYS (np, send_sdtr)) {
+ nxtdsp = NCB_SCRIPTH_PHYS (np, nego_bad_phase);
+ }
+ break;
+#if 0
+ case 7: /* MSG IN phase */
+ nxtdsp = NCB_SCRIPT_PHYS (np, clrack);
+ break;
+#endif
+ }
+
+ if (nxtdsp) {
+ OUTL (nc_dsp, nxtdsp);
+ return;
+ }
+
+reset_all:
+ ncr_start_reset(np);
+}
+
+/*==========================================================
+**
+** ncr chip handler for QUEUE FULL and CHECK CONDITION
+**
+**==========================================================
+**
+** On QUEUE FULL status, we set the actual tagged command
+** queue depth to the number of disconnected CCBs that is
+** hopefully a good value to avoid further QUEUE FULL.
+**
+** On CHECK CONDITION or COMMAND TERMINATED, we use the
+** CCB of the failed command for performing a REQUEST
+** SENSE SCSI command.
+**
+** We do not want to change the order commands will be
+** actually queued to the device after we received a
+** QUEUE FULL status. We also want to properly deal with
+** contingent allegiance condition. For these reasons,
+** we remove from the start queue all commands for this
+** LUN that haven't been yet queued to the device and
+** put them back in the correponding LUN queue, then
+** requeue the CCB that failed in front of the LUN queue.
+** I just hope this not to be performed too often. :)
+**
+**----------------------------------------------------------
+*/
+
+static void ncr_sir_to_redo(ncb_p np, int num, ccb_p cp)
+{
+ Scsi_Cmnd *cmd = cp->cmd;
+ tcb_p tp = &np->target[cp->target];
+ lcb_p lp = tp->lp[cp->lun];
+ ccb_p cp2;
+ int busyccbs = 1;
+ u_int32 startp;
+ u_char s_status = INB (SS_PRT);
+
+ /*
+ ** Remove all CCBs queued to the chip for that LUN and put
+ ** them back in the LUN CCB wait queue.
+ */
+ if (lp) {
+ int i = np->squeueput;
+ int j = (INL (nc_scratcha) - vtobus(np->squeue)) / 4;
+ int k = np->squeueput;
+
+ busyccbs = lp->queuedccbs;
+ while (1) {
+ if (i == j)
+ break;
+ if (i == 0)
+ i = MAX_START*2;
+ i = i - 2;
+ cp2 = ncr_ccb_from_dsa(np, scr_to_cpu(np->squeue[i]));
+ if (!cp2)
+ continue;
+ if (cp2->target != cp->target || cp2->lun != cp->lun)
+ continue;
+ xpt_remque(&cp2->link_ccbq);
+ xpt_insque_head(&cp2->link_ccbq, &lp->wait_ccbq);
+ --lp->queuedccbs;
+ cp2->queued = 0;
+ np->squeue[i] = DSA_INVALID;
+ k = i;
+ }
+
+ /*
+ ** Requeue the interrupted CCB in front of
+ ** the LUN CCB wait queue.
+ */
+ xpt_remque(&cp->link_ccbq);
+ xpt_insque_head(&cp->link_ccbq, &lp->wait_ccbq);
+ --lp->queuedccbs;
+ cp->queued = 0;
+
+ /*
+ ** Repair the startqueue if necessary.
+ */
+ if (k != np->squeueput) {
+ j = k;
+ while (1) {
+ j += 2;
+ if (j >= MAX_START*2)
+ j = 0;
+ if (np->squeue[j] == DSA_INVALID)
+ continue;
+ np->squeue[k] = np->squeue[j];
+ if (j == np->squeueput)
+ break;
+ k += 2;
+ if (k >= MAX_START*2)
+ k = 0;
+ }
+ np->squeueput = k;
+ }
+ }
+
+ /*
+ ** Now we can restart the SCRIPTS processor safely.
+ */
+ MEMORY_BARRIER();
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start));
+
+ switch(s_status) {
+ default: /* Just for safety, should never happen */
+ case S_QUEUE_FULL:
+ if (!lp || !lp->queuedccbs) {
+ ncr_complete(np, cp);
+ break;
+ }
+ if (bootverbose >= 1) {
+ PRINT_ADDR(cmd);
+ printk ("QUEUE FULL! %d busy, %d disconnected CCBs\n",
+ busyccbs, lp->queuedccbs);
+ }
+ /*
+ ** Decrease number of tags to the number of
+ ** disconnected commands.
+ */
+ if (lp->queuedccbs < lp->numtags) {
+ lp->numtags = lp->queuedccbs;
+ lp->num_good = 0;
+ ncr_setup_tags (np, cp->target, cp->lun);
+ }
+ /*
+ ** Repair the offending CCB.
+ */
+ cp->phys.header.savep = cp->startp;
+ cp->host_status = HS_BUSY;
+ cp->scsi_status = S_ILLEGAL;
+ cp->host_flags &= HF_PM_TO_C;
+
+ break;
+
+ case S_TERMINATED:
+ case S_CHECK_COND:
+ /*
+ ** If we were requesting sense, give up.
+ */
+ if (cp->auto_sense) {
+ ncr_complete(np, cp);
+ break;
+ }
+
+ /*
+ ** Device returned CHECK CONDITION status.
+ ** Prepare all needed data strutures for getting
+ ** sense data.
+ */
+
+ /*
+ ** identify message
+ */
+ cp->scsi_smsg2[0] = M_IDENTIFY | cp->lun;
+ cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg2));
+ cp->phys.smsg.size = cpu_to_scr(1);
+
+ /*
+ ** sense command
+ */
+ cp->phys.cmd.addr = cpu_to_scr(CCB_PHYS (cp, sensecmd));
+ cp->phys.cmd.size = cpu_to_scr(6);
+
+ /*
+ ** patch requested size into sense command
+ */
+ cp->sensecmd[0] = 0x03;
+ cp->sensecmd[1] = cp->lun << 5;
+ cp->sensecmd[4] = sizeof(cmd->sense_buffer);
+
+ /*
+ ** sense data
+ */
+ cp->phys.sense.addr =
+ cpu_to_scr(vtobus (&cmd->sense_buffer[0]));
+ cp->phys.sense.size =
+ cpu_to_scr(sizeof(cmd->sense_buffer));
+
+ /*
+ ** requeue the command.
+ */
+ startp = cpu_to_scr(NCB_SCRIPTH_PHYS (np, sdata_in));
+
+ cp->phys.header.savep = startp;
+ cp->phys.header.goalp = startp + 24;
+ cp->phys.header.lastp = startp;
+ cp->phys.header.wgoalp = startp + 24;
+ cp->phys.header.wlastp = startp;
+
+ cp->host_status = HS_BUSY;
+ cp->scsi_status = S_ILLEGAL;
+ cp->host_flags = 0;
+ cp->auto_sense = s_status;
+
+ cp->phys.header.go.start =
+ cpu_to_scr(NCB_SCRIPT_PHYS (np, select));
+
+ /*
+ ** Select without ATN for quirky devices.
+ */
+ if (tp->quirks & QUIRK_NOMSG)
+ cp->phys.header.go.start =
+ cpu_to_scr(NCB_SCRIPTH_PHYS (np, select_no_atn));
+
+ /*
+ ** If lp not yet allocated, requeue the command.
+ */
+ if (!lp)
+ ncr_put_start_queue(np, cp);
+ break;
+ }
+
+ /*
+ ** requeue awaiting scsi commands for this lun.
+ */
+ if (lp)
+ ncr_start_next_ccb(np, lp, 1);
+
+ return;
+}
+
+
+/*==========================================================
+**
+**
+** ncr chip exception handler for programmed interrupts.
+**
+**
+**==========================================================
+*/
+
+static int ncr_show_msg (u_char * msg)
+{
+ u_char i;
+ printk ("%x",*msg);
+ if (*msg==M_EXTENDED) {
+ for (i=1;i<8;i++) {
+ if (i-1>msg[1]) break;
+ printk ("-%x",msg[i]);
+ };
+ return (i+1);
+ } else if ((*msg & 0xf0) == 0x20) {
+ printk ("-%x",msg[1]);
+ return (2);
+ };
+ return (1);
+}
+
+
+void ncr_int_sir (ncb_p np)
+{
+ u_char scntl3;
+ u_char chg, ofs, per, fak, wide;
+ u_char num = INB (nc_dsps);
+ ccb_p cp=0;
+ u_long dsa = INL (nc_dsa);
+ u_char target = INB (nc_sdid) & 0x0f;
+ tcb_p tp = &np->target[target];
+
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("I#%d", num);
+
+ switch (num) {
+ case SIR_SEL_ATN_NO_MSG_OUT:
+ /*
+ ** The device didn't go to MSG OUT phase after having
+ ** been selected with ATN. We donnot want to handle
+ ** that.
+ */
+ printk ("%s:%d: No MSG OUT phase after selection with ATN.\n",
+ ncr_name (np), target);
+ goto out_stuck;
+ case SIR_RESEL_NO_MSG_IN:
+ case SIR_RESEL_NO_IDENTIFY:
+ /*
+ ** If devices reselecting without sending an IDENTIFY
+ ** message still exist, this should help.
+ ** We just assume lun=0, 1 CCB, no tag.
+ */
+ if (tp->lp[0]) {
+ OUTL (nc_dsa, scr_to_cpu(tp->lp[0]->tasktbl[0]));
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, resel_go));
+ return;
+ }
+ case SIR_RESEL_BAD_LUN:
+ np->msgout[0] = M_RESET;
+ goto out;
+ case SIR_RESEL_BAD_I_T_L:
+ np->msgout[0] = M_ABORT;
+ goto out;
+ case SIR_RESEL_BAD_I_T_L_Q:
+ np->msgout[0] = M_ABORT_TAG;
+ goto out;
+ case SIR_RESEL_ABORTED:
+ np->lastmsg = np->msgout[0];
+ np->msgout[0] = M_NOOP;
+ printk ("%s:%d: message %d sent on bad reselection.\n",
+ ncr_name (np), target, np->lastmsg);
+ goto out;
+ case SIR_MSG_OUT_DONE:
+ np->lastmsg = np->msgout[0];
+ np->msgout[0] = M_NOOP;
+ /* Should we really care of that */
+ if (np->lastmsg == M_PARITY || np->lastmsg == M_ID_ERROR)
+ OUTOFFB (HF_PRT, HF_PAR_ERR);
+ goto out;
+ case SIR_BAD_STATUS:
+ cp = ncr_ccb_from_dsa(np, dsa);
+ if (!cp)
+ goto out;
+ ncr_sir_to_redo(np, num, cp);
+ return;
+ default:
+ /*
+ ** lookup the ccb
+ */
+ cp = ncr_ccb_from_dsa(np, dsa);
+ if (!cp)
+ goto out;
+ }
+
+ switch (num) {
+/*-----------------------------------------------------------------------------
+**
+** Was Sie schon immer ueber transfermode negotiation wissen wollten ...
+**
+** We try to negotiate sync and wide transfer only after
+** a successfull inquire command. We look at byte 7 of the
+** inquire data to determine the capabilities of the target.
+**
+** When we try to negotiate, we append the negotiation message
+** to the identify and (maybe) simple tag message.
+** The host status field is set to HS_NEGOTIATE to mark this
+** situation.
+**
+** If the target doesn't answer this message immidiately
+** (as required by the standard), the SIR_NEGO_FAIL interrupt
+** will be raised eventually.
+** The handler removes the HS_NEGOTIATE status, and sets the
+** negotiated value to the default (async / nowide).
+**
+** If we receive a matching answer immediately, we check it
+** for validity, and set the values.
+**
+** If we receive a Reject message immediately, we assume the
+** negotiation has failed, and fall back to standard values.
+**
+** If we receive a negotiation message while not in HS_NEGOTIATE
+** state, it's a target initiated negotiation. We prepare a
+** (hopefully) valid answer, set our parameters, and send back
+** this answer to the target.
+**
+** If the target doesn't fetch the answer (no message out phase),
+** we assume the negotiation has failed, and fall back to default
+** settings.
+**
+** When we set the values, we adjust them in all ccbs belonging
+** to this target, in the controller's register, and in the "phys"
+** field of the controller's struct ncb.
+**
+** Possible cases: hs sir msg_in value send goto
+** We try to negotiate:
+** -> target doesnt't msgin NEG FAIL noop defa. - dispatch
+** -> target rejected our msg NEG FAIL reject defa. - dispatch
+** -> target answered (ok) NEG SYNC sdtr set - clrack
+** -> target answered (!ok) NEG SYNC sdtr defa. REJ--->msg_bad
+** -> target answered (ok) NEG WIDE wdtr set - clrack
+** -> target answered (!ok) NEG WIDE wdtr defa. REJ--->msg_bad
+** -> any other msgin NEG FAIL noop defa. - dispatch
+**
+** Target tries to negotiate:
+** -> incoming message --- SYNC sdtr set SDTR -
+** -> incoming message --- WIDE wdtr set WDTR -
+** We sent our answer:
+** -> target doesn't msgout --- PROTO ? defa. - dispatch
+**
+**-----------------------------------------------------------------------------
+*/
+
+ case SIR_NEGO_FAILED:
+ /*-------------------------------------------------------
+ **
+ ** Negotiation failed.
+ ** Target doesn't send an answer message,
+ ** or target rejected our message.
+ **
+ ** Remove negotiation request.
+ **
+ **-------------------------------------------------------
+ */
+ OUTB (HS_PRT, HS_BUSY);
+
+ /* fall through */
+
+ case SIR_NEGO_PROTO:
+ /*-------------------------------------------------------
+ **
+ ** Negotiation failed.
+ ** Target doesn't fetch the answer message.
+ **
+ **-------------------------------------------------------
+ */
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("negotiation failed sir=%x status=%x.\n",
+ num, cp->nego_status);
+ };
+
+ /*
+ ** any error in negotiation:
+ ** fall back to default mode.
+ */
+ switch (cp->nego_status) {
+
+ case NS_SYNC:
+ ncr_setsync (np, cp, 0, 0xe0);
+ break;
+
+ case NS_WIDE:
+ ncr_setwide (np, cp, 0, 0);
+ break;
+
+ };
+ np->msgin [0] = M_NOOP;
+ np->msgout[0] = M_NOOP;
+ cp->nego_status = 0;
+ break;
+
+ case SIR_NEGO_SYNC:
+ /*
+ ** Synchronous request message received.
+ */
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("sync msgin: ");
+ (void) ncr_show_msg (np->msgin);
+ printk (".\n");
+ };
+
+ /*
+ ** get requested values.
+ */
+
+ chg = 0;
+ per = np->msgin[3];
+ ofs = np->msgin[4];
+ if (ofs==0) per=255;
+
+ /*
+ ** if target sends SDTR message,
+ ** it CAN transfer synch.
+ */
+
+ if (ofs)
+ tp->inq_byte7 |= INQ7_SYNC;
+
+ /*
+ ** check values against driver limits.
+ */
+
+ if (per < np->minsync)
+ {chg = 1; per = np->minsync;}
+ if (per < tp->minsync)
+ {chg = 1; per = tp->minsync;}
+ if (ofs > tp->maxoffs)
+ {chg = 1; ofs = tp->maxoffs;}
+
+ /*
+ ** Check against controller limits.
+ */
+ fak = 7;
+ scntl3 = 0;
+ if (ofs != 0) {
+ ncr_getsync(np, per, &fak, &scntl3);
+ if (fak > 7) {
+ chg = 1;
+ ofs = 0;
+ }
+ }
+ if (ofs == 0) {
+ fak = 7;
+ per = 0;
+ scntl3 = 0;
+ tp->minsync = 0;
+ }
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n",
+ per, scntl3, ofs, fak, chg);
+ }
+
+ if (INB (HS_PRT) == HS_NEGOTIATE) {
+ OUTB (HS_PRT, HS_BUSY);
+ switch (cp->nego_status) {
+
+ case NS_SYNC:
+ /*
+ ** This was an answer message
+ */
+ if (chg) {
+ /*
+ ** Answer wasn't acceptable.
+ */
+ ncr_setsync (np, cp, 0, 0xe0);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad));
+ } else {
+ /*
+ ** Answer is ok.
+ */
+ ncr_setsync (np, cp, scntl3, (fak<<5)|ofs);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack));
+ };
+ return;
+
+ case NS_WIDE:
+ ncr_setwide (np, cp, 0, 0);
+ break;
+ };
+ };
+
+ /*
+ ** It was a request. Set value and
+ ** prepare an answer message
+ */
+
+ ncr_setsync (np, cp, scntl3, (fak<<5)|ofs);
+
+ np->msgout[0] = M_EXTENDED;
+ np->msgout[1] = 3;
+ np->msgout[2] = M_X_SYNC_REQ;
+ np->msgout[3] = per;
+ np->msgout[4] = ofs;
+
+ cp->nego_status = NS_SYNC;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("sync msgout: ");
+ (void) ncr_show_msg (np->msgout);
+ printk (".\n");
+ }
+
+ if (!ofs) {
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad));
+ return;
+ }
+ np->msgin [0] = M_NOOP;
+
+ break;
+
+ case SIR_NEGO_WIDE:
+ /*
+ ** Wide request message received.
+ */
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("wide msgin: ");
+ (void) ncr_show_msg (np->msgin);
+ printk (".\n");
+ };
+
+ /*
+ ** get requested values.
+ */
+
+ chg = 0;
+ wide = np->msgin[3];
+
+ /*
+ ** if target sends WDTR message,
+ ** it CAN transfer wide.
+ */
+
+ if (wide)
+ tp->inq_byte7 |= INQ7_WIDE16;
+
+ /*
+ ** check values against driver limits.
+ */
+
+ if (wide > tp->usrwide)
+ {chg = 1; wide = tp->usrwide;}
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("wide: wide=%d chg=%d.\n", wide, chg);
+ }
+
+ if (INB (HS_PRT) == HS_NEGOTIATE) {
+ OUTB (HS_PRT, HS_BUSY);
+ switch (cp->nego_status) {
+
+ case NS_WIDE:
+ /*
+ ** This was an answer message
+ */
+ if (chg) {
+ /*
+ ** Answer wasn't acceptable.
+ */
+ ncr_setwide (np, cp, 0, 1);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad));
+ } else {
+ /*
+ ** Answer is ok.
+ */
+ ncr_setwide (np, cp, wide, 1);
+ OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack));
+ };
+ return;
+
+ case NS_SYNC:
+ ncr_setsync (np, cp, 0, 0xe0);
+ break;
+ };
+ };
+
+ /*
+ ** It was a request, set value and
+ ** prepare an answer message
+ */
+
+ ncr_setwide (np, cp, wide, 1);
+
+ np->msgout[0] = M_EXTENDED;
+ np->msgout[1] = 2;
+ np->msgout[2] = M_X_WIDE_REQ;
+ np->msgout[3] = wide;
+
+ np->msgin [0] = M_NOOP;
+
+ cp->nego_status = NS_WIDE;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_ADDR(cp->cmd);
+ printk ("wide msgout: ");
+ (void) ncr_show_msg (np->msgin);
+ printk (".\n");
+ }
+ break;
+
+/*--------------------------------------------------------------------
+**
+** Processing of special messages
+**
+**--------------------------------------------------------------------
+*/
+
+ case SIR_REJECT_RECEIVED:
+ /*-----------------------------------------------
+ **
+ ** We received a M_REJECT message.
+ **
+ **-----------------------------------------------
+ */
+
+ PRINT_ADDR(cp->cmd);
+ printk ("M_REJECT received (%x:%x).\n",
+ (unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]);
+ break;
+
+ case SIR_REJECT_TO_SEND:
+ /*-----------------------------------------------
+ **
+ ** We received an unknown message
+ **
+ **-----------------------------------------------
+ */
+
+ PRINT_ADDR(cp->cmd);
+ printk ("M_REJECT to send for ");
+ (void) ncr_show_msg (np->msgin);
+ printk (".\n");
+ np->msgout[0] = M_REJECT;
+ break;
+
+/*--------------------------------------------------------------------
+**
+** Processing of special messages
+**
+**--------------------------------------------------------------------
+*/
+
+ case SIR_IGN_RESIDUE:
+ /*-----------------------------------------------
+ **
+ ** We received an IGNORE RESIDUE message,
+ ** which couldn't be handled by the script.
+ **
+ **-----------------------------------------------
+ */
+
+ PRINT_ADDR(cp->cmd);
+ printk ("M_IGN_RESIDUE received, but not yet implemented.\n");
+ break;
+#if 0
+ case SIR_MISSING_SAVE:
+ /*-----------------------------------------------
+ **
+ ** We received an DISCONNECT message,
+ ** but the datapointer wasn't saved before.
+ **
+ **-----------------------------------------------
+ */
+
+ PRINT_ADDR(cp->cmd);
+ printk ("M_DISCONNECT received, but datapointer not saved: "
+ "data=%x save=%x goal=%x.\n",
+ (unsigned) INL (nc_temp),
+ (unsigned) scr_to_cpu(np->header.savep),
+ (unsigned) scr_to_cpu(np->header.goalp));
+ break;
+#endif
+ };
+
+out:
+ OUTONB (nc_dcntl, (STD|NOCOM));
+out_stuck:
+}
+
+/*==========================================================
+**
+**
+** Aquire a control block
+**
+**
+**==========================================================
+*/
+
+static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln)
+{
+ tcb_p tp = &np->target[tn];
+ lcb_p lp = tp->lp[ln];
+ u_char tag = NO_TAG;
+ XPT_QUEHEAD *qp;
+ ccb_p cp = (ccb_p) 0;
+
+ /*
+ ** Allocate a new CCB if needed.
+ */
+ if (xpt_que_empty(&np->free_ccbq))
+ (void) ncr_alloc_ccb(np);
+
+ /*
+ ** Look for a free CCB
+ */
+ qp = xpt_remque_head(&np->free_ccbq);
+ if (!qp)
+ goto out;
+ cp = xpt_que_entry(qp, struct ccb, link_ccbq);
+
+ /*
+ ** If the LCB is not yet available and we already
+ ** have queued a CCB for a LUN without LCB,
+ ** give up. Otherwise all is fine. :-)
+ */
+ if (!lp) {
+ if (xpt_que_empty(&np->b0_ccbq))
+ xpt_insque_head(&cp->link_ccbq, &np->b0_ccbq);
+ else
+ goto out_free;
+ } else {
+ /*
+ ** Tune tag mode if asked by user.
+ */
+ if (lp->queuedepth != lp->numtags) {
+ ncr_setup_tags(np, tn, ln);
+ }
+
+ /*
+ ** Get a tag for this nexus if required.
+ ** Keep from using more tags than we can handle.
+ */
+ if (lp->usetags) {
+ if (lp->busyccbs < lp->maxnxs) {
+ tag = lp->cb_tags[lp->ia_tag];
+ ++lp->ia_tag;
+ if (lp->ia_tag == SCSI_NCR_MAX_TAGS)
+ lp->ia_tag = 0;
+ lp->tags_umap |= (((tagmap_t) 1) << tag);
+ }
+ else
+ goto out_free;
+ }
+
+ /*
+ ** Put the CCB in the LUN wait queue and
+ ** count it as busy.
+ */
+ xpt_insque_tail(&cp->link_ccbq, &lp->wait_ccbq);
+ ++lp->busyccbs;
+ }
+
+ /*
+ ** Remember all informations needed to free this CCB.
+ */
+ cp->tag = tag;
+ cp->target = tn;
+ cp->lun = ln;
+
+ if (DEBUG_FLAGS & DEBUG_TAGS) {
+ PRINT_LUN(np, tn, ln);
+ printk ("ccb @%p using tag %d.\n", cp, tag);
+ }
+
+out:
+ return cp;
+out_free:
+ xpt_insque_head(&cp->link_ccbq, &np->free_ccbq);
+ return (ccb_p) 0;
+}
+
+/*==========================================================
+**
+**
+** Release one control block
+**
+**
+**==========================================================
+*/
+
+static void ncr_free_ccb (ncb_p np, ccb_p cp)
+{
+ tcb_p tp = &np->target[cp->target];
+ lcb_p lp = tp->lp[cp->lun];
+
+ if (DEBUG_FLAGS & DEBUG_TAGS) {
+ PRINT_LUN(np, cp->target, cp->lun);
+ printk ("ccb @%p freeing tag %d.\n", cp, cp->tag);
+ }
+
+ /*
+ ** If lun control block available, make available
+ ** the task slot and the tag if any.
+ ** Decrement counters.
+ */
+ if (lp) {
+ if (cp->tag != NO_TAG) {
+ lp->cb_tags[lp->if_tag++] = cp->tag;
+ if (lp->if_tag == SCSI_NCR_MAX_TAGS)
+ lp->if_tag = 0;
+ lp->tags_umap &= ~(((tagmap_t) 1) << cp->tag);
+ lp->tags_smap &= lp->tags_umap;
+ lp->tasktbl[cp->tag] = cpu_to_scr(np->p_bad_i_t_l_q);
+ } else {
+ lp->tasktbl[0] = cpu_to_scr(np->p_bad_i_t_l);
+ }
+ --lp->busyccbs;
+ if (cp->queued) {
+ --lp->queuedccbs;
+ }
+ }
+
+ /*
+ ** Make this CCB available.
+ */
+ xpt_remque(&cp->link_ccbq);
+ xpt_insque_head(&cp->link_ccbq, &np->free_ccbq);
+ cp -> host_status = HS_IDLE;
+ cp -> queued = 0;
+}
+
+/*------------------------------------------------------------------------
+** Allocate a CCB and initialize its fixed part.
+**------------------------------------------------------------------------
+**------------------------------------------------------------------------
+*/
+static ccb_p ncr_alloc_ccb(ncb_p np)
+{
+ ccb_p cp = 0;
+ int hcode;
+
+ /*
+ ** Allocate memory for this CCB.
+ */
+ cp = m_calloc(sizeof(struct ccb), "CCB", MEMO_WARN);
+ if (!cp)
+ return 0;
+
+ /*
+ ** Count it and initialyze it.
+ */
+ np->actccbs++;
+
+ /*
+ ** Remember virtual and bus address of this ccb.
+ */
+ cp->p_ccb = vtobus(cp);
+
+ /*
+ ** Insert this ccb into the hashed list.
+ */
+ hcode = CCB_HASH_CODE(cp->p_ccb);
+ cp->link_ccbh = np->ccbh[hcode];
+ np->ccbh[hcode] = cp;
+
+ /*
+ ** Initialyze the start and restart actions.
+ */
+ cp->phys.header.go.start = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle));
+ cp->phys.header.go.restart = cpu_to_scr(NCB_SCRIPTH_PHYS(np,bad_i_t_l));
+
+ /*
+ ** Chain into wakeup list and free ccb queue.
+ */
+ cp->link_ccb = np->ccbc;
+ np->ccbc = cp;
+
+ xpt_insque_head(&cp->link_ccbq, &np->free_ccbq);
+
+ return cp;
+}
+
+/*------------------------------------------------------------------------
+** Look up a CCB from a DSA value.
+**------------------------------------------------------------------------
+**------------------------------------------------------------------------
+*/
+static ccb_p ncr_ccb_from_dsa(ncb_p np, u_long dsa)
+{
+ int hcode;
+ ccb_p cp;
+
+ hcode = CCB_HASH_CODE(dsa);
+ cp = np->ccbh[hcode];
+ while (cp) {
+ if (cp->p_ccb == dsa)
+ break;
+ cp = cp->link_ccbh;
+ }
+
+ return cp;
+}
+
+/*==========================================================
+**
+**
+** Allocation of resources for Targets/Luns/Tags.
+**
+**
+**==========================================================
+*/
+
+
+/*------------------------------------------------------------------------
+** Target control block initialisation.
+**------------------------------------------------------------------------
+** This data structure is fully initialized after a SCSI command
+** has been successfully completed for this target.
+**------------------------------------------------------------------------
+*/
+static void ncr_init_tcb (ncb_p np, u_char tn)
+{
+ tcb_p tp = &np->target[tn];
+
+ /*
+ ** Already bone.
+ */
+ if (tp->luntbl)
+ return;
+ /*
+ ** Allocate the lcb bus address array.
+ */
+ tp->luntbl = m_calloc(256, "LUNTBL", MEMO_WARN);
+ if (!tp->luntbl)
+ return;
+
+ /*
+ ** Compute the bus address of this table.
+ */
+ tp->b_luntbl = cpu_to_scr(vtobus(tp->luntbl));
+
+ /*
+ ** Check some alignments required by the chip.
+ */
+ assert (( (offsetof(struct ncr_reg, nc_sxfer) ^
+ offsetof(struct tcb , sval )) &3) == 0);
+ assert (( (offsetof(struct ncr_reg, nc_scntl3) ^
+ offsetof(struct tcb , wval )) &3) == 0);
+}
+
+/*------------------------------------------------------------------------
+** Lun control block allocation and initialization.
+**------------------------------------------------------------------------
+** This data structure is allocated and initialized after a SCSI
+** command has been successfully completed for this target/lun.
+**------------------------------------------------------------------------
+*/
+static lcb_p ncr_alloc_lcb (ncb_p np, u_char tn, u_char ln)
+{
+ tcb_p tp = &np->target[tn];
+ lcb_p lp = tp->lp[ln];
+
+ /*
+ ** Already done, return.
+ */
+ if (lp)
+ return lp;
+
+ /*
+ ** Initialize the target control block if not yet.
+ */
+ ncr_init_tcb(np, tn);
+ if (!tp->luntbl)
+ goto fail;
+
+ /*
+ ** Allocate the lcb.
+ */
+ lp = m_calloc(sizeof(struct lcb), "LCB", MEMO_WARN);
+ if (!lp)
+ goto fail;
+ tp->lp[ln] = lp;
+
+ /*
+ ** Make it available to the chip.
+ */
+ tp->luntbl[ln] = cpu_to_scr(vtobus(lp));
+
+ /*
+ ** Initialize the CCB queue headers.
+ */
+ xpt_que_init(&lp->busy_ccbq);
+ xpt_que_init(&lp->wait_ccbq);
+
+ /*
+ ** Set max CCBs to 1 and use the default task array
+ ** by default.
+ */
+ lp->maxnxs = 1;
+ lp->tasktbl = &lp->tasktbl_0;
+ lp->b_tasktbl = cpu_to_scr(vtobus(lp->tasktbl));
+ lp->tasktbl[0] = cpu_to_scr(np->p_notask);
+ lp->resel_task = cpu_to_scr(NCB_SCRIPT_PHYS(np, resel_notag));
+
+ /*
+ ** Initialize command queuing control.
+ */
+ lp->busyccbs = 1;
+ lp->queuedccbs = 1;
+ lp->queuedepth = 1;
+fail:
+ return lp;
+}
+
+
+/*------------------------------------------------------------------------
+** Lun control block setup on INQUIRY data received.
+**------------------------------------------------------------------------
+** We only support WIDE, SYNC for targets and CMDQ for logical units.
+** This setup is done on each INQUIRY since we are expecting user
+** will play with CHANGE DEFINITION commands. :-)
+**------------------------------------------------------------------------
+*/
+static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln, u_char *inq_data)
+{
+ tcb_p tp = &np->target[tn];
+ lcb_p lp = tp->lp[ln];
+ u_char inq_byte7;
+ int i;
+
+ /*
+ ** If no lcb, try to allocate it.
+ */
+ if (!lp && !(lp = ncr_alloc_lcb(np, tn, ln)))
+ goto fail;
+
+ /*
+ ** Get device quirks from a speciality table.
+ */
+ tp->quirks = ncr_lookup (inq_data);
+ if (tp->quirks && bootverbose) {
+ PRINT_LUN(np, tn, ln);
+ printk ("quirks=%x.\n", tp->quirks);
+ }
+
+ /*
+ ** Evaluate trustable target/unit capabilities.
+ ** We only believe device version >= SCSI-2 that
+ ** use appropriate response data format (2).
+ ** But it seems that some CCS devices also
+ ** support SYNC and I donnot want to frustrate
+ ** anybody. ;-)
+ */
+ inq_byte7 = 0;
+ if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2)
+ inq_byte7 = inq_data[7];
+ else if ((inq_data[2] & 0x7) == 1 && (inq_data[3] & 0xf) == 1)
+ inq_byte7 = INQ7_SYNC;
+
+ /*
+ ** Throw away announced LUN capabilities if we are told
+ ** that there is no real device supported by the logical unit.
+ */
+ if ((inq_data[0] & 0xe0) > 0x20 || (inq_data[0] & 0x1f) == 0x1f)
+ inq_byte7 &= (INQ7_SYNC | INQ7_WIDE16);
+
+ /*
+ ** If user is wanting SYNC, force this feature.
+ */
+ if (driver_setup.force_sync_nego)
+ inq_byte7 |= INQ7_SYNC;
+
+ /*
+ ** Prepare negotiation if SIP capabilities have changed.
+ */
+ tp->inq_done = 1;
+ if ((inq_byte7 ^ tp->inq_byte7) & (INQ7_SYNC | INQ7_WIDE16)) {
+ tp->inq_byte7 = inq_byte7;
+ ncr_negotiate(np, tp);
+ }
+
+ /*
+ ** If unit supports tagged commands, allocate and
+ ** initialyze the task table if not yet.
+ */
+ if ((inq_byte7 & INQ7_QUEUE) && lp->tasktbl == &lp->tasktbl_0) {
+ lp->tasktbl = m_calloc(256, "TASKTBL", MEMO_WARN);
+ if (!lp->tasktbl) {
+ lp->tasktbl = &lp->tasktbl_0;
+ goto fail;
+ }
+ lp->b_tasktbl = cpu_to_scr(vtobus(lp->tasktbl));
+ for (i = 0 ; i < 64 ; i++)
+ lp->tasktbl[i] = cpu_to_scr(np->p_notask);
+ for (i = 0 ; i < SCSI_NCR_MAX_TAGS ; i++)
+ lp->cb_tags[i] = i;
+ lp->maxnxs = SCSI_NCR_MAX_TAGS;
+ lp->tags_stime = jiffies;
+ }
+
+ /*
+ ** Adjust tagged queueing status if needed.
+ */
+ if ((inq_byte7 ^ lp->inq_byte7) & INQ7_QUEUE) {
+ lp->inq_byte7 = inq_byte7;
+ lp->numtags = lp->maxtags;
+ ncr_setup_tags (np, tn, ln);
+ }
+
+fail:
+ return lp;
+}
+
+/*==========================================================
+**
+**
+** Build Scatter Gather Block
+**
+**
+**==========================================================
+**
+** The transfer area may be scattered among
+** several non adjacent physical pages.
+**
+** We may use MAX_SCATTER blocks.
+**
+**----------------------------------------------------------
+*/
+
+/*
+** We try to reduce the number of interrupts caused
+** by unexpected phase changes due to disconnects.
+** A typical harddisk may disconnect before ANY block.
+** If we wanted to avoid unexpected phase changes at all
+** we had to use a break point every 512 bytes.
+** Of course the number of scatter/gather blocks is
+** limited.
+** Under Linux, the scatter/gatter blocks are provided by
+** the generic driver. We just have to copy addresses and
+** sizes to the data segment array.
+*/
+
+/*
+** For 64 bit systems, we use the 8 upper bits of the size field
+** to provide bus address bits 32-39 to the SCRIPTS processor.
+** This allows the 896 to access up to 1 tera-bytes of memory.
+** For 32 bit chips on 64 bit systems, we must be provided with
+** memory addresses that fit into the first 32 bit bus address
+** range and so, this does not matter and we expect an error from
+** the chip if this ever happen.
+**
+** We use a separate function for the case Linux does not provide
+** a scatter list in order to allow better code optimization
+** for the case we have a scatter list (BTW, for now this just wastes
+** about 40 bytes of code for x86, but my guess is that the scatter
+** code will get more complex later).
+*/
+
+#if BITS_PER_LONG > 32
+#define SCATTER_ONE(data, badd, len) \
+ (data)->addr = cpu_to_scr(badd); \
+ (data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len);
+#else
+#define SCATTER_ONE(data, badd, len) \
+ (data)->addr = cpu_to_scr(badd); \
+ (data)->size = cpu_to_scr(len);
+#endif
+
+#define CROSS_16MB(p, n) (((((u_long) p) + n - 1) ^ ((u_long) p)) & ~0xffffff)
+
+static int ncr_scatter_no_sglist(ccb_p cp, Scsi_Cmnd *cmd)
+{
+ struct scr_tblmove *data = &cp->phys.data[MAX_SCATTER-1];
+ int segment;
+
+ cp->data_len = cmd->request_bufflen;
+
+ if (cmd->request_bufflen) {
+ u_long baddr = vtobus(cmd->request_buffer);
+ SCATTER_ONE(data, baddr, cmd->request_bufflen);
+ if (CROSS_16MB(baddr, cmd->request_bufflen)) {
+ cp->host_flags |= HF_PM_TO_C;
+#ifdef DEBUG_896R1
+printk("He! we are crossing a 16 MB boundary (0x%lx, 0x%x)\n",
+ baddr, cmd->request_bufflen);
+#endif
+ }
+ segment = 1;
+ }
+ else
+ segment = 0;
+
+ return segment;
+}
+
+/*
+** DEL 472 - 53C896 Rev 1 - Part Number 609-0393055 - ITEM 5.
+**
+** We disable data phase mismatch handling from SCRIPTS for data
+** transfers that contains scatter/gather entries that cross
+** a 16 MB boundary.
+** We use a different scatter function for 896 rev. 1 that needs
+** such a work-around. Doing so, we do not affect performance for
+** other chips.
+** This problem should not be triggered for disk IOs under Linux,
+** since such IOs are performed using pages and buffers that are
+** nicely power-of-two sized and aligned. But, since this may change
+** at any time, a work-around was required.
+*/
+static int ncr_scatter_896R1(ccb_p cp, Scsi_Cmnd *cmd)
+{
+ int segn;
+ int use_sg = (int) cmd->use_sg;
+
+ cp->data_len = 0;
+
+ if (!use_sg)
+ segn = ncr_scatter_no_sglist(cp, cmd);
+ else if (use_sg > MAX_SCATTER)
+ segn = -1;
+ else {
+ struct scatterlist *scatter = (struct scatterlist *)cmd->buffer;
+ struct scr_tblmove *data = &cp->phys.data[MAX_SCATTER - use_sg];
+
+ for (segn = 0; segn < use_sg; segn++) {
+ u_long baddr = vtobus(scatter[segn].address);
+ SCATTER_ONE(&data[segn],
+ baddr,
+ scatter[segn].length);
+ if (CROSS_16MB(baddr, scatter[segn].length)) {
+ cp->host_flags |= HF_PM_TO_C;
+#ifdef DEBUG_896R1
+printk("He! we are crossing a 16 MB boundary (0x%lx, 0x%x)\n",
+ baddr, scatter[segn].length);
+#endif
+ }
+ cp->data_len += scatter[segn].length;
+ }
+ }
+
+ return segn;
+}
+
+static int ncr_scatter(ccb_p cp, Scsi_Cmnd *cmd)
+{
+ int segment;
+ int use_sg = (int) cmd->use_sg;
+
+ cp->data_len = 0;
+
+ if (!use_sg)
+ segment = ncr_scatter_no_sglist(cp, cmd);
+ else if (use_sg > MAX_SCATTER)
+ segment = -1;
+ else {
+ struct scatterlist *scatter = (struct scatterlist *)cmd->buffer;
+ struct scr_tblmove *data = &cp->phys.data[MAX_SCATTER - use_sg];
+
+ for (segment = 0; segment < use_sg; segment++) {
+ u_long baddr = vtobus(scatter[segment].address);
+ SCATTER_ONE(&data[segment],
+ baddr,
+ scatter[segment].length);
+ cp->data_len += scatter[segment].length;
+ }
+ }
+
+ return segment;
+}
+
+/*==========================================================
+**
+**
+** Test the pci bus snoop logic :-(
+**
+** Has to be called with interrupts disabled.
+**
+**
+**==========================================================
+*/
+
+#ifndef NCR_IOMAPPED
+__initfunc(
+static int ncr_regtest (struct ncb* np)
+)
+{
+ register volatile u_int32 data;
+ /*
+ ** ncr registers may NOT be cached.
+ ** write 0xffffffff to a read only register area,
+ ** and try to read it back.
+ */
+ data = 0xffffffff;
+ OUTL_OFF(offsetof(struct ncr_reg, nc_dstat), data);
+ data = INL_OFF(offsetof(struct ncr_reg, nc_dstat));
+#if 1
+ if (data == 0xffffffff) {
+#else
+ if ((data & 0xe2f0fffd) != 0x02000080) {
+#endif
+ printk ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n",
+ (unsigned) data);
+ return (0x10);
+ };
+ return (0);
+}
+#endif
+
+__initfunc(
+static int ncr_snooptest (struct ncb* np)
+)
+{
+ u_int32 ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc;
+ int i, err=0;
+#ifndef NCR_IOMAPPED
+ if (np->reg) {
+ err |= ncr_regtest (np);
+ if (err) return (err);
+ }
+#endif
+ /*
+ ** init
+ */
+ pc = NCB_SCRIPTH0_PHYS (np, snooptest);
+ host_wr = 1;
+ ncr_wr = 2;
+ /*
+ ** Set memory and register.
+ */
+ np->ncr_cache = cpu_to_scr(host_wr);
+ OUTL (nc_temp, ncr_wr);
+ /*
+ ** Start script (exchange values)
+ */
+ OUTL (nc_dsa, vtobus(np));
+ OUTL (nc_dsp, pc);
+ /*
+ ** Wait 'til done (with timeout)
+ */
+ for (i=0; i<NCR_SNOOP_TIMEOUT; i++)
+ if (INB(nc_istat) & (INTF|SIP|DIP))
+ break;
+ /*
+ ** Save termination position.
+ */
+ pc = INL (nc_dsp);
+ /*
+ ** Read memory and register.
+ */
+ host_rd = scr_to_cpu(np->ncr_cache);
+ ncr_rd = INL (nc_scratcha);
+ ncr_bk = INL (nc_temp);
+
+ /*
+ ** check for timeout
+ */
+ if (i>=NCR_SNOOP_TIMEOUT) {
+ printk ("CACHE TEST FAILED: timeout.\n");
+ return (0x20);
+ };
+ /*
+ ** Check termination position.
+ */
+ if (pc != NCB_SCRIPTH0_PHYS (np, snoopend)+8) {
+ printk ("CACHE TEST FAILED: script execution failed.\n");
+ printk ("start=%08lx, pc=%08lx, end=%08lx\n",
+ (u_long) NCB_SCRIPTH0_PHYS (np, snooptest), (u_long) pc,
+ (u_long) NCB_SCRIPTH0_PHYS (np, snoopend) +8);
+ return (0x40);
+ };
+ /*
+ ** Show results.
+ */
+ if (host_wr != ncr_rd) {
+ printk ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n",
+ (int) host_wr, (int) ncr_rd);
+ err |= 1;
+ };
+ if (host_rd != ncr_wr) {
+ printk ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n",
+ (int) ncr_wr, (int) host_rd);
+ err |= 2;
+ };
+ if (ncr_bk != ncr_wr) {
+ printk ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n",
+ (int) ncr_wr, (int) ncr_bk);
+ err |= 4;
+ };
+ return (err);
+}
+
+/*==========================================================
+**
+**
+** Profiling the drivers and targets performance.
+**
+**
+**==========================================================
+*/
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+
+static void ncb_profile (ncb_p np, ccb_p cp)
+{
+ int num_disc = (cp->phys.num_disc & 0xff);
+ int num_disc0 = (cp->phys.num_disc >> 8);
+
+ ++np->profile.num_trans;
+ np->profile.num_disc += num_disc;
+ np->profile.num_disc0 += num_disc0;
+ np->profile.num_kbytes += (cp->data_len >> 10);
+#if 000
+ if (num_disc > num_disc0) {
+ if (cp->data_len <= 1024)
+ np->profile.num_br1k += (num_disc - num_disc0);
+ else if (cp->data_len <= 2048)
+ np->profile.num_br2k += (num_disc - num_disc0);
+ else if (cp->data_len <= 4096)
+ np->profile.num_br4k += (num_disc - num_disc0);
+ else if (cp->data_len <= 8192)
+ np->profile.num_br8k += (num_disc - num_disc0);
+ else
+ np->profile.num_brnk += (num_disc - num_disc0);
+ }
+#endif
+}
+
+#endif /* SCSI_NCR_PROFILE_SUPPORT */
+
+/*==========================================================
+**
+**
+** Device lookup.
+**
+** @GENSCSI@ should be integrated to scsiconf.c
+**
+**
+**==========================================================
+*/
+
+struct table_entry {
+ char * manufacturer;
+ char * model;
+ char * version;
+ u_long info;
+};
+
+static struct table_entry device_tab[] =
+{
+#if 0
+ {"", "", "", QUIRK_NOMSG},
+#endif
+ {"SONY", "SDT-5000", "3.17", QUIRK_NOMSG},
+ {"WangDAT", "Model 2600", "01.7", QUIRK_NOMSG},
+ {"WangDAT", "Model 3200", "02.2", QUIRK_NOMSG},
+ {"WangDAT", "Model 1300", "02.4", QUIRK_NOMSG},
+ {"", "", "", 0} /* catch all: must be last entry. */
+};
+
+static u_long ncr_lookup(char * id)
+{
+ struct table_entry * p = device_tab;
+ char *d, *r, c;
+
+ for (;;p++) {
+
+ d = id+8;
+ r = p->manufacturer;
+ while ((c=*r++)) if (c!=*d++) break;
+ if (c) continue;
+
+ d = id+16;
+ r = p->model;
+ while ((c=*r++)) if (c!=*d++) break;
+ if (c) continue;
+
+ d = id+32;
+ r = p->version;
+ while ((c=*r++)) if (c!=*d++) break;
+ if (c) continue;
+
+ return (p->info);
+ }
+}
+
+/*==========================================================
+**
+** Determine the ncr's clock frequency.
+** This is essential for the negotiation
+** of the synchronous transfer rate.
+**
+**==========================================================
+**
+** Note: we have to return the correct value.
+** THERE IS NO SAFE DEFAULT VALUE.
+**
+** Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock.
+** 53C860 and 53C875 rev. 1 support fast20 transfers but
+** do not have a clock doubler and so are provided with a
+** 80 MHz clock. All other fast20 boards incorporate a doubler
+** and so should be delivered with a 40 MHz clock.
+** The recent fast40 chips (895/896) use a 40 Mhz base clock
+** and provide a clock quadrupler (160 Mhz). The code below
+** tries to deal as cleverly as possible with all this stuff.
+**
+**----------------------------------------------------------
+*/
+
+/*
+ * Select NCR SCSI clock frequency
+ */
+static void ncr_selectclock(ncb_p np, u_char scntl3)
+{
+ if (np->multiplier < 2) {
+ OUTB(nc_scntl3, scntl3);
+ return;
+ }
+
+ if (bootverbose >= 2)
+ printk ("%s: enabling clock multiplier\n", ncr_name(np));
+
+ OUTB(nc_stest1, DBLEN); /* Enable clock multiplier */
+ if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */
+ int i = 20;
+ while (!(INB(nc_stest4) & LCKFRQ) && --i > 0)
+ UDELAY (20);
+ if (!i)
+ printk("%s: the chip cannot lock the frequency\n", ncr_name(np));
+ } else /* Wait 20 micro-seconds for doubler */
+ UDELAY (20);
+ OUTB(nc_stest3, HSC); /* Halt the scsi clock */
+ OUTB(nc_scntl3, scntl3);
+ OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */
+ OUTB(nc_stest3, 0x00); /* Restart scsi clock */
+}
+
+
+/*
+ * calculate NCR SCSI clock frequency (in KHz)
+ */
+__initfunc(
+static unsigned ncrgetfreq (ncb_p np, int gen)
+)
+{
+ unsigned ms = 0;
+
+ /*
+ * Measure GEN timer delay in order
+ * to calculate SCSI clock frequency
+ *
+ * This code will never execute too
+ * many loop iterations (if DELAY is
+ * reasonably correct). It could get
+ * too low a delay (too high a freq.)
+ * if the CPU is slow executing the
+ * loop for some reason (an NMI, for
+ * example). For this reason we will
+ * if multiple measurements are to be
+ * performed trust the higher delay
+ * (lower frequency returned).
+ */
+ OUTB (nc_stest1, 0); /* make sure clock doubler is OFF */
+ OUTW (nc_sien , 0); /* mask all scsi interrupts */
+ (void) INW (nc_sist); /* clear pending scsi interrupt */
+ OUTB (nc_dien , 0); /* mask all dma interrupts */
+ (void) INW (nc_sist); /* another one, just to be sure :) */
+ OUTB (nc_scntl3, 4); /* set pre-scaler to divide by 3 */
+ OUTB (nc_stime1, 0); /* disable general purpose timer */
+ OUTB (nc_stime1, gen); /* set to nominal delay of 1<<gen * 125us */
+ while (!(INW(nc_sist) & GEN) && ms++ < 100000)
+ UDELAY (1000); /* count ms */
+ OUTB (nc_stime1, 0); /* disable general purpose timer */
+ /*
+ * set prescaler to divide by whatever 0 means
+ * 0 ought to choose divide by 2, but appears
+ * to set divide by 3.5 mode in my 53c810 ...
+ */
+ OUTB (nc_scntl3, 0);
+
+ if (bootverbose >= 2)
+ printk ("%s: Delay (GEN=%d): %u msec\n", ncr_name(np), gen, ms);
+ /*
+ * adjust for prescaler, and convert into KHz
+ */
+ return ms ? ((1 << gen) * 4340) / ms : 0;
+}
+
+/*
+ * Get/probe NCR SCSI clock frequency
+ */
+__initfunc(
+static void ncr_getclock (ncb_p np, int mult)
+)
+{
+ unsigned char scntl3 = INB(nc_scntl3);
+ unsigned char stest1 = INB(nc_stest1);
+ unsigned f1;
+
+ np->multiplier = 1;
+ f1 = 40000;
+
+ /*
+ ** True with 875/895/896 with clock multiplier selected
+ */
+ if (mult > 1 && (stest1 & (DBLEN+DBLSEL)) == DBLEN+DBLSEL) {
+ if (bootverbose >= 2)
+ printk ("%s: clock multiplier found\n", ncr_name(np));
+ np->multiplier = mult;
+ }
+
+ /*
+ ** If multiplier not found or scntl3 not 7,5,3,
+ ** reset chip and get frequency from general purpose timer.
+ ** Otherwise trust scntl3 BIOS setting.
+ */
+ if (np->multiplier != mult || (scntl3 & 7) < 3 || !(scntl3 & 1)) {
+ unsigned f2;
+
+ (void) ncrgetfreq (np, 11); /* throw away first result */
+ f1 = ncrgetfreq (np, 11);
+ f2 = ncrgetfreq (np, 11);
+
+ if (bootverbose)
+ printk ("%s: NCR clock is %uKHz, %uKHz\n", ncr_name(np), f1, f2);
+
+ if (f1 > f2) f1 = f2; /* trust lower result */
+
+ if (f1 < 45000) f1 = 40000;
+ else if (f1 < 55000) f1 = 50000;
+ else f1 = 80000;
+
+ if (f1 < 80000 && mult > 1) {
+ if (bootverbose >= 2)
+ printk ("%s: clock multiplier assumed\n", ncr_name(np));
+ np->multiplier = mult;
+ }
+ } else {
+ if ((scntl3 & 7) == 3) f1 = 40000;
+ else if ((scntl3 & 7) == 5) f1 = 80000;
+ else f1 = 160000;
+
+ f1 /= np->multiplier;
+ }
+
+ /*
+ ** Compute controller synchronous parameters.
+ */
+ f1 *= np->multiplier;
+ np->clock_khz = f1;
+}
+
+/*===================== LINUX ENTRY POINTS SECTION ==========================*/
+
+#ifndef uchar
+#define uchar unsigned char
+#endif
+
+#ifndef ushort
+#define ushort unsigned short
+#endif
+
+#ifndef ulong
+#define ulong unsigned long
+#endif
+
+/* ---------------------------------------------------------------------
+**
+** Driver setup from the boot command line
+**
+** ---------------------------------------------------------------------
+*/
+
+#ifdef MODULE
+#define ARG_SEP ' '
+#else
+#define ARG_SEP ','
+#endif
+
+#define OPT_TAGS 1
+#define OPT_MASTER_PARITY 2
+#define OPT_SCSI_PARITY 3
+#define OPT_DISCONNECTION 4
+#define OPT_SPECIAL_FEATURES 5
+#define OPT_ULTRA_SCSI 6
+#define OPT_FORCE_SYNC_NEGO 7
+#define OPT_REVERSE_PROBE 8
+#define OPT_DEFAULT_SYNC 9
+#define OPT_VERBOSE 10
+#define OPT_DEBUG 11
+#define OPT_BURST_MAX 12
+#define OPT_LED_PIN 13
+#define OPT_MAX_WIDE 14
+#define OPT_SETTLE_DELAY 15
+#define OPT_DIFF_SUPPORT 16
+#define OPT_IRQM 17
+#define OPT_PCI_FIX_UP 18
+#define OPT_BUS_CHECK 19
+#define OPT_OPTIMIZE 20
+#define OPT_RECOVERY 21
+#define OPT_SAFE_SETUP 22
+#define OPT_USE_NVRAM 23
+#define OPT_EXCLUDE 24
+
+static char setup_token[] __initdata =
+ "tags:" "mpar:"
+ "spar:" "disc:"
+ "specf:" "ultra:"
+ "fsn:" "revprob:"
+ "sync:" "verb:"
+ "debug:" "burst:"
+ "led:" "wide:"
+ "settle:" "diff:"
+ "irqm:" "pcifix:"
+ "buschk:" "optim:"
+ "recovery:"
+ "safe:" "nvram:"
+ "excl:";
+
+#ifdef MODULE
+#define ARG_SEP ' '
+#else
+#define ARG_SEP ','
+#endif
+
+__initfunc(
+static int get_setup_token(char *p)
+)
+{
+ char *cur = setup_token;
+ char *pc;
+ int i = 0;
+
+ while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
+ ++pc;
+ ++i;
+ if (!strncmp(p, cur, pc - cur))
+ return i;
+ cur = pc;
+ }
+ return 0;
+}
+
+
+__initfunc(
+void sym53c8xx_setup(char *str, int *ints)
+)
+{
+#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
+ char *cur = str;
+ char *pc, *pv;
+ int i, val, c;
+ int xi = 0;
+
+ while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
+ char *pe;
+
+ val = 0;
+ pv = pc;
+ c = *++pv;
+
+ if (c == 'n')
+ val = 0;
+ else if (c == 'y')
+ val = 1;
+ else
+ val = (int) simple_strtoul(pv, &pe, 0);
+
+ switch (get_setup_token(cur)) {
+ case OPT_TAGS:
+ driver_setup.default_tags = val;
+ if (pe && *pe == '/') {
+ i = 0;
+ while (*pe && *pe != ARG_SEP &&
+ i < sizeof(driver_setup.tag_ctrl)-1) {
+ driver_setup.tag_ctrl[i++] = *pe++;
+ }
+ driver_setup.tag_ctrl[i] = '\0';
+ }
+ break;
+ case OPT_MASTER_PARITY:
+ driver_setup.master_parity = val;
+ break;
+ case OPT_SCSI_PARITY:
+ driver_setup.scsi_parity = val;
+ break;
+ case OPT_DISCONNECTION:
+ driver_setup.disconnection = val;
+ break;
+ case OPT_SPECIAL_FEATURES:
+ driver_setup.special_features = val;
+ break;
+ case OPT_ULTRA_SCSI:
+ driver_setup.ultra_scsi = val;
+ break;
+ case OPT_FORCE_SYNC_NEGO:
+ driver_setup.force_sync_nego = val;
+ break;
+ case OPT_REVERSE_PROBE:
+ driver_setup.reverse_probe = val;
+ break;
+ case OPT_DEFAULT_SYNC:
+ driver_setup.default_sync = val;
+ break;
+ case OPT_VERBOSE:
+ driver_setup.verbose = val;
+ break;
+ case OPT_DEBUG:
+ driver_setup.debug = val;
+ break;
+ case OPT_BURST_MAX:
+ driver_setup.burst_max = val;
+ break;
+ case OPT_LED_PIN:
+ driver_setup.led_pin = val;
+ break;
+ case OPT_MAX_WIDE:
+ driver_setup.max_wide = val? 1:0;
+ break;
+ case OPT_SETTLE_DELAY:
+ driver_setup.settle_delay = val;
+ break;
+ case OPT_DIFF_SUPPORT:
+ driver_setup.diff_support = val;
+ break;
+ case OPT_IRQM:
+ driver_setup.irqm = val;
+ break;
+ case OPT_PCI_FIX_UP:
+ driver_setup.pci_fix_up = val;
+ break;
+ case OPT_BUS_CHECK:
+ driver_setup.bus_check = val;
+ break;
+ case OPT_OPTIMIZE:
+ driver_setup.optimize = val;
+ break;
+ case OPT_RECOVERY:
+ driver_setup.recovery = val;
+ break;
+ case OPT_USE_NVRAM:
+ driver_setup.use_nvram = val;
+ break;
+ case OPT_SAFE_SETUP:
+ memcpy(&driver_setup, &driver_safe_setup,
+ sizeof(driver_setup));
+ break;
+ case OPT_EXCLUDE:
+ if (xi < SCSI_NCR_MAX_EXCLUDES)
+ driver_setup.excludes[xi++] = val;
+ break;
+ default:
+ printk("sym53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
+ break;
+ }
+
+ if ((cur = strchr(cur, ARG_SEP)) != NULL)
+ ++cur;
+ }
+#endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
+}
+
+static int sym53c8xx_pci_init(Scsi_Host_Template *tpnt,
+ uchar bus, uchar device_fn, ncr_device *device);
+
+/*
+** Linux entry point for SYM53C8XX devices detection routine.
+**
+** Called by the middle-level scsi drivers at initialization time,
+** or at module installation.
+**
+** Read the PCI configuration and try to attach each
+** detected NCR board.
+**
+** If NVRAM is present, try to attach boards according to
+** the used defined boot order.
+**
+** Returns the number of boards successfully attached.
+*/
+
+__initfunc(
+static void ncr_print_driver_setup(void)
+)
+{
+#define YesNo(y) y ? 'y' : 'n'
+ printk (NAME53C8XX ": setup=disc:%c,specf:%d,ultra:%d,tags:%d,sync:%d,"
+ "burst:%d,wide:%c,diff:%d,revprob:%c,buschk:0x%x\n",
+ YesNo(driver_setup.disconnection),
+ driver_setup.special_features,
+ driver_setup.ultra_scsi,
+ driver_setup.default_tags,
+ driver_setup.default_sync,
+ driver_setup.burst_max,
+ YesNo(driver_setup.max_wide),
+ driver_setup.diff_support,
+ YesNo(driver_setup.reverse_probe),
+ driver_setup.bus_check);
+
+ printk (NAME53C8XX ": setup=mpar:%c,spar:%c,fsn=%c,verb:%d,debug:0x%x,"
+ "led:%c,settle:%d,irqm:0x%x,nvram:0x%x,pcifix:0x%x\n",
+ YesNo(driver_setup.master_parity),
+ YesNo(driver_setup.scsi_parity),
+ YesNo(driver_setup.force_sync_nego),
+ driver_setup.verbose,
+ driver_setup.debug,
+ YesNo(driver_setup.led_pin),
+ driver_setup.settle_delay,
+ driver_setup.irqm,
+ driver_setup.use_nvram,
+ driver_setup.pci_fix_up);
+#undef YesNo
+}
+
+/*===================================================================
+** SYM53C8XX devices description table and chip ids list.
+**===================================================================
+*/
+
+static ncr_chip ncr_chip_table[] __initdata = SCSI_NCR_CHIP_TABLE;
+static ushort ncr_chip_ids[] __initdata = SCSI_NCR_CHIP_IDS;
+
+#ifdef SCSI_NCR_PQS_PDS_SUPPORT
+/*===================================================================
+** Detect all NCR PQS/PDS boards and keep track of their bus nr.
+**
+** The NCR PQS or PDS card is constructed as a DEC bridge
+** behind which sit a proprietary NCR memory controller and
+** four or two 53c875s as separate devices. In its usual mode
+** of operation, the 875s are slaved to the memory controller
+** for all transfers. We can tell if an 875 is part of a
+** PQS/PDS or not since if it is, it will be on the same bus
+** as the memory controller. To operate with the Linux
+** driver, the memory controller is disabled and the 875s
+** freed to function independently. The only wrinkle is that
+** the preset SCSI ID (which may be zero) must be read in from
+** a special configuration space register of the 875
+**===================================================================
+*/
+#define SCSI_NCR_MAX_PQS_BUS 16
+static int pqs_bus[SCSI_NCR_MAX_PQS_BUS] __initdata = { 0 };
+
+__initfunc(
+static void ncr_detect_pqs_pds(void)
+)
+{
+ short index;
+
+ for(index=0; index < SCSI_NCR_MAX_PQS_BUS; index ++) {
+ u_char tmp, bus, device_fn;
+
+ if (pcibios_find_device(0x101a, 0x0009, index, &bus,
+ &device_fn) != PCIBIOS_SUCCESSFUL) {
+ pqs_bus[index] = -1;
+ break;
+ }
+ printk(KERN_INFO NAME53C8XX ": NCR PQS/PDS memory controller detected on bus %d\n", bus);
+ pcibios_read_config_byte(bus, device_fn, 0x44, &tmp);
+ /* bit 1: allow individual 875 configuration */
+ tmp |= 0x2;
+ pcibios_write_config_byte(bus, device_fn, 0x44, tmp);
+ pcibios_read_config_byte(bus, device_fn, 0x45, &tmp);
+ /* bit 2: drive individual 875 interrupts to the bus */
+ tmp |= 0x4;
+ pcibios_write_config_byte(bus, device_fn, 0x45, tmp);
+
+ pqs_bus[index] = bus;
+ }
+}
+#endif /* SCSI_NCR_PQS_PDS_SUPPORT */
+
+/*===================================================================
+** Detect all 53c8xx hosts and then attach them.
+**
+** If we are using NVRAM, once all hosts are detected, we need to
+** check any NVRAM for boot order in case detect and boot order
+** differ and attach them using the order in the NVRAM.
+**
+** If no NVRAM is found or data appears invalid attach boards in
+** the the order they are detected.
+**===================================================================
+*/
+__initfunc(
+int sym53c8xx_detect(Scsi_Host_Template *tpnt)
+)
+{
+ int i, j, chips, hosts, count;
+ u_char bus, device_fn;
+ short index;
+ int attach_count = 0;
+ ncr_device *devtbl, *devp;
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+ ncr_nvram nvram0, nvram, *nvp;
+#endif
+
+ /*
+ ** PCI is required.
+ */
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,92)
+ if (!pci_present())
+#else
+ if (!pcibios_present())
+#endif
+ return 0;
+
+ /*
+ ** Initialize driver general stuff.
+ */
+#ifdef SCSI_NCR_PROC_INFO_SUPPORT
+ tpnt->proc_dir = &proc_scsi_sym53c8xx;
+ tpnt->proc_info = sym53c8xx_proc_info;
+#endif
+
+#if defined(SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT) && defined(MODULE)
+if (sym53c8xx)
+ sym53c8xx_setup(sym53c8xx, (int *) 0);
+#endif
+#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
+ ncr_debug = driver_setup.debug;
+#endif
+
+ if (initverbose >= 2)
+ ncr_print_driver_setup();
+
+ /*
+ ** Allocate the device table since we donnot want to
+ ** overflow the kernel stack.
+ ** 1 x 4K PAGE is enough for more than 40 devices for i386.
+ */
+ devtbl = m_calloc(PAGE_SIZE, "devtbl", MEMO_WARN);
+ if (!devtbl)
+ return 0;
+
+ /*
+ ** Detect all NCR PQS/PDS memory controllers.
+ */
+#ifdef SCSI_NCR_PQS_PDS_SUPPORT
+ ncr_detect_pqs_pds();
+#endif
+
+ /*
+ ** Detect all 53c8xx hosts.
+ ** Save the first Symbios NVRAM content if any
+ ** for the boot order.
+ */
+ chips = sizeof(ncr_chip_ids) / sizeof(ncr_chip_ids[0]);
+ hosts = PAGE_SIZE / sizeof(*devtbl);
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+ nvp = (driver_setup.use_nvram & 0x1) ? &nvram0 : 0;
+#endif
+ j = 0;
+ index = 0;
+ count = 0;
+ while (1) {
+ char *msg = "";
+ if (count >= hosts)
+ break;
+ if (j >= chips)
+ break;
+ i = driver_setup.reverse_probe ? chips - 1 - j : j;
+ if (pcibios_find_device(PCI_VENDOR_ID_NCR, ncr_chip_ids[i],
+ index, &bus, &device_fn)) {
+ ++j;
+ index = 0;
+ continue;
+ }
+ ++index;
+ devp = &devtbl[count];
+ devp->host_id = 255;
+ devp->attach_done = 0;
+ if (sym53c8xx_pci_init(tpnt, bus, device_fn, devp)) {
+ continue;
+ }
+ ++count;
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+ if (nvp) {
+ ncr_get_nvram(devp, nvp);
+ switch(nvp->type) {
+ case SCSI_NCR_SYMBIOS_NVRAM:
+ /*
+ * Switch to the other nvram buffer, so that
+ * nvram0 will contain the first Symbios
+ * format NVRAM content with boot order.
+ */
+ nvp = &nvram;
+ msg = "with Symbios NVRAM";
+ break;
+ case SCSI_NCR_TEKRAM_NVRAM:
+ msg = "with Tekram NVRAM";
+ break;
+ }
+ }
+#endif
+#ifdef SCSI_NCR_PQS_PDS_SUPPORT
+ if (devp->pqs_pds)
+ msg = "(NCR PQS/PDS)";
+#endif
+ printk(KERN_INFO NAME53C8XX ": 53c%s detected %s\n",
+ devp->chip.name, msg);
+ }
+
+ /*
+ ** If we have found a SYMBIOS NVRAM, use first the NVRAM boot
+ ** sequence as device boot order.
+ ** check devices in the boot record against devices detected.
+ ** attach devices if we find a match. boot table records that
+ ** do not match any detected devices will be ignored.
+ ** devices that do not match any boot table will not be attached
+ ** here but will attempt to be attached during the device table
+ ** rescan.
+ */
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+ if (!nvp || nvram0.type != SCSI_NCR_SYMBIOS_NVRAM)
+ goto next;
+ for (i = 0; i < 4; i++) {
+ Symbios_host *h = &nvram0.data.Symbios.host[i];
+ for (j = 0 ; j < count ; j++) {
+ devp = &devtbl[j];
+ if (h->device_fn != devp->slot.device_fn ||
+ h->bus_nr != devp->slot.bus ||
+ h->device_id != devp->chip.device_id)
+ continue;
+ if (devp->attach_done)
+ continue;
+ if (h->flags & SYMBIOS_INIT_SCAN_AT_BOOT) {
+ ncr_get_nvram(devp, nvp);
+ if (!ncr_attach (tpnt, attach_count, devp))
+ attach_count++;
+ }
+ else if (!(driver_setup.use_nvram & 0x80))
+ printk(KERN_INFO NAME53C8XX
+ ": 53c%s state OFF thus not attached\n",
+ devp->chip.name);
+ else
+ continue;
+
+ devp->attach_done = 1;
+ break;
+ }
+ }
+next:
+#endif
+
+ /*
+ ** Rescan device list to make sure all boards attached.
+ ** Devices without boot records will not be attached yet
+ ** so try to attach them here.
+ */
+ for (i= 0; i < count; i++) {
+ devp = &devtbl[i];
+ if (!devp->attach_done) {
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+ ncr_get_nvram(devp, nvp);
+#endif
+ if (!ncr_attach (tpnt, attach_count, devp))
+ attach_count++;
+ }
+ }
+
+ m_free(devtbl, PAGE_SIZE, "devtbl");
+
+ return attach_count;
+}
+
+/*===================================================================
+** Generically read a base address from the PCI configuration space.
+** Return the offset immediately after the base address that has
+** been read. Btw, we blindly assume that the high 32 bits of 64 bit
+** base addresses are set to zero on 32 bit architectures.
+**===================================================================
+*/
+#if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92)
+__initfunc(
+static int
+pci_read_base_address(u_char bus, u_char device_fn, int offset, u_long *base)
+)
+{
+ u_int32 tmp;
+
+ pcibios_read_config_dword(bus, device_fn, offset, &tmp);
+ *base = tmp;
+ offset += sizeof(u_int32);
+ if ((tmp & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+ pcibios_read_config_dword(bus, device_fn, offset, &tmp);
+ *base |= (((u_long)tmp) << 32);
+#endif
+ offset += sizeof(u_int32);
+ }
+ return offset;
+}
+#else /* LINUX_VERSION_CODE > LinuxVersionCode(2,1,92) */
+__initfunc(
+static int
+pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
+)
+{
+ *base = pdev->base_address[index++];
+ if ((*base & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+ *base |= (((u_long)pdev->base_address[index]) << 32);
+#endif
+ ++index;
+ }
+ return index;
+}
+#endif
+
+/*===================================================================
+** Read and check the PCI configuration for any detected NCR
+** boards and save data for attaching after all boards have
+** been detected.
+**===================================================================
+*/
+__initfunc(
+static int sym53c8xx_pci_init(Scsi_Host_Template *tpnt,
+ uchar bus, uchar device_fn, ncr_device *device)
+)
+{
+ u_short vendor_id, device_id, command;
+ u_char cache_line_size, latency_timer;
+ u_char suggested_cache_line_size = 0;
+ u_char revision;
+#if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
+ struct pci_dev *pdev;
+ u_int irq;
+#else
+ u_char irq;
+#endif
+ u_long base, base_2, io_port;
+ int i;
+ ncr_chip *chip;
+
+ printk(KERN_INFO NAME53C8XX ": at PCI bus %d, device %d, function %d\n",
+ bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7);
+ /*
+ ** Read info from the PCI config space.
+ ** pcibios_read_config_xxx() functions are assumed to be used for
+ ** successfully detected PCI devices.
+ */
+#if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
+ pdev = pci_find_slot(bus, device_fn);
+ vendor_id = pdev->vendor;
+ device_id = pdev->device;
+ irq = pdev->irq;
+ i = 0;
+ i = pci_get_base_address(pdev, i, &io_port);
+ i = pci_get_base_address(pdev, i, &base);
+ (void) pci_get_base_address(pdev, i, &base_2);
+#else
+ pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id);
+ pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID, &device_id);
+ pcibios_read_config_byte(bus, device_fn, PCI_INTERRUPT_LINE, &irq);
+ i = PCI_BASE_ADDRESS_0;
+ i = pci_read_base_address(bus, device_fn, i, &io_port);
+ i = pci_read_base_address(bus, device_fn, i, &base);
+ (void) pci_read_base_address(bus, device_fn, i, &base_2);
+#endif
+ pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+ pcibios_read_config_byte(bus, device_fn, PCI_CLASS_REVISION, &revision);
+ pcibios_read_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE,
+ &cache_line_size);
+ pcibios_read_config_byte(bus, device_fn, PCI_LATENCY_TIMER,
+ &latency_timer);
+
+#ifdef SCSI_NCR_PQS_PDS_SUPPORT
+ /*
+ ** Match the BUS number for PQS/PDS devices.
+ ** Read the SCSI ID from a special register mapped
+ ** into the configuration space of the individual
+ ** 875s. This register is set up by the PQS bios
+ */
+ for(i = 0; i < SCSI_NCR_MAX_PQS_BUS && pqs_bus[i] != -1; i++) {
+ u_char tmp;
+ if (pqs_bus[i] == bus) {
+ pcibios_read_config_byte(bus, device_fn, 0x84, &tmp);
+ device->pqs_pds = 1;
+ device->host_id = tmp;
+ break;
+ }
+ }
+#endif /* SCSI_NCR_PQS_PDS_SUPPORT */
+
+ /*
+ ** If user excludes this chip, donnot initialize it.
+ */
+ for (i = 0 ; i < SCSI_NCR_MAX_EXCLUDES ; i++) {
+ if (driver_setup.excludes[i] ==
+ (io_port & PCI_BASE_ADDRESS_IO_MASK))
+ return -1;
+ }
+ /*
+ ** Check if the chip is supported
+ */
+ chip = 0;
+ for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); i++) {
+ if (device_id != ncr_chip_table[i].device_id)
+ continue;
+ if (revision > ncr_chip_table[i].revision_id)
+ continue;
+ if (!(ncr_chip_table[i].features & FE_LDSTR))
+ continue;
+ chip = &device->chip;
+ memcpy(chip, &ncr_chip_table[i], sizeof(*chip));
+ chip->revision_id = revision;
+ break;
+ }
+
+#if defined(__i386__)
+ /*
+ ** Ignore Symbios chips controlled by SISL RAID controller.
+ ** This controller sets value 0x52414944 at RAM end - 16.
+ */
+ if (chip && (base_2 & PCI_BASE_ADDRESS_MEM_MASK)) {
+ unsigned int ram_size, ram_val;
+ u_long ram_ptr;
+
+ if (chip->features & FE_RAM8K)
+ ram_size = 8192;
+ else
+ ram_size = 4096;
+
+ ram_ptr = remap_pci_mem(base_2 & PCI_BASE_ADDRESS_MEM_MASK,
+ ram_size);
+ if (ram_ptr) {
+ ram_val = readl_raw(ram_ptr + ram_size - 16);
+ unmap_pci_mem(ram_ptr, ram_size);
+ if (ram_val == 0x52414944) {
+ printk(NAME53C8XX": not initializing, "
+ "driven by SISL RAID controller.\n");
+ return -1;
+ }
+ }
+ }
+#endif
+
+ if (!chip) {
+ printk(NAME53C8XX ": not initializing, device not supported\n");
+ return -1;
+ }
+
+#ifdef __powerpc__
+ /*
+ ** Fix-up for power/pc.
+ ** Should not be performed by the driver.
+ */
+ if ((command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY))
+ != (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+ printk(NAME53C8XX ": setting%s%s...\n",
+ (command & PCI_COMMAND_IO) ? "" : " PCI_COMMAND_IO",
+ (command & PCI_COMMAND_MEMORY) ? "" : " PCI_COMMAND_MEMORY");
+ command |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+ }
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,2,0)
+ if ( is_prep ) {
+ if (io_port >= 0x10000000) {
+ printk(NAME53C8XX ": reallocating io_port (Wacky IBM)");
+ io_port = (io_port & 0x00FFFFFF) | 0x01000000;
+ pcibios_write_config_dword(bus, device_fn,
+ PCI_BASE_ADDRESS_0, io_port);
+ }
+ if (base >= 0x10000000) {
+ printk(NAME53C8XX ": reallocating base (Wacky IBM)");
+ base = (base & 0x00FFFFFF) | 0x01000000;
+ pcibios_write_config_dword(bus, device_fn,
+ PCI_BASE_ADDRESS_1, base);
+ }
+ if (base_2 >= 0x10000000) {
+ printk(NAME53C8XX ": reallocating base2 (Wacky IBM)");
+ base_2 = (base_2 & 0x00FFFFFF) | 0x01000000;
+ pcibios_write_config_dword(bus, device_fn,
+ PCI_BASE_ADDRESS_2, base_2);
+ }
+ }
+#endif
+#endif /* __powerpc__ */
+
+#ifdef __sparc__
+ /*
+ ** Fix-ups for sparc.
+ **
+ ** I wrote: Should not be performed by the driver,
+ ** Guy wrote: but how can OBP know each and every PCI card,
+ ** if they don't use Fcode?
+ ** I replied: no need to know each and every PCI card, just
+ ** be skilled enough to understand the PCI specs.
+ */
+
+ /*
+ ** PCI configuration is based on configuration registers being
+ ** coherent with hardware and software resource identifications.
+ ** This is fairly simple, but seems still too complex for Sparc.
+ */
+ base = __pa(base);
+ base_2 = __pa(base_2);
+
+ if (!cache_line_size)
+ suggested_cache_line_size = 16;
+
+#endif /* __sparc__ */
+
+#if defined(__i386__) && !defined(MODULE)
+ if (!cache_line_size) {
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,75)
+ extern char x86;
+ switch(x86) {
+#else
+ switch(boot_cpu_data.x86) {
+#endif
+ case 4: suggested_cache_line_size = 4; break;
+ case 6:
+ case 5: suggested_cache_line_size = 8; break;
+ }
+ }
+#endif /* __i386__ */
+
+ /*
+ ** Check availability of IO space, memory space.
+ ** Enable master capability if not yet.
+ */
+#ifdef NCR_IOMAPPED
+ if (!(command & PCI_COMMAND_IO) || !(io_port & 1)) {
+ printk(NAME53C8XX ": I/O base address (0x%lx) disabled.\n",
+ (long) io_port);
+ io_port = 0;
+ }
+#endif
+ if (!(command & PCI_COMMAND_MEMORY)) {
+ printk(NAME53C8XX ": PCI_COMMAND_MEMORY not set.\n");
+ base = 0;
+ base_2 = 0;
+ }
+ io_port &= PCI_BASE_ADDRESS_IO_MASK;
+ base &= PCI_BASE_ADDRESS_MEM_MASK;
+ base_2 &= PCI_BASE_ADDRESS_MEM_MASK;
+
+#ifdef NCR_IOMAPPED
+ if (io_port && check_region (io_port, 128)) {
+ printk(NAME53C8XX ": IO region 0x%lx[0..127] is in use\n",
+ (long) io_port);
+ io_port = 0;
+ }
+ if (!io_port)
+ return -1;
+#else
+ if (!base) {
+ printk(NAME53C8XX ": MMIO base address disabled.\n");
+ return -1;
+ }
+#endif
+
+ /*
+ ** Set MASTER capable and PARITY bit, if not yet.
+ */
+ if ((command & (PCI_COMMAND_MASTER | PCI_COMMAND_PARITY))
+ != (PCI_COMMAND_MASTER | PCI_COMMAND_PARITY)) {
+ printk(NAME53C8XX ": setting%s%s...(fix-up)\n",
+ (command & PCI_COMMAND_MASTER) ? "" : " PCI_COMMAND_MASTER",
+ (command & PCI_COMMAND_PARITY) ? "" : " PCI_COMMAND_PARITY");
+ command |= (PCI_COMMAND_MASTER | PCI_COMMAND_PARITY);
+ pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+ }
+
+ /*
+ ** Fix some features according to driver setup.
+ */
+ if (!(driver_setup.special_features & 1))
+ chip->features &= ~FE_SPECIAL_SET;
+ else {
+ if (driver_setup.special_features & 2)
+ chip->features &= ~FE_WRIE;
+ if (driver_setup.special_features & 4)
+ chip->features &= ~FE_NOPM;
+ }
+ if (driver_setup.ultra_scsi < 2 && (chip->features & FE_ULTRA2)) {
+ chip->features |= FE_ULTRA;
+ chip->features &= ~FE_ULTRA2;
+ }
+ if (driver_setup.ultra_scsi < 1)
+ chip->features &= ~FE_ULTRA;
+ if (!driver_setup.max_wide)
+ chip->features &= ~FE_WIDE;
+
+#ifdef SCSI_NCR_PCI_FIX_UP_SUPPORT
+ /*
+ ** Try to fix up PCI config according to wished features.
+ */
+ if ((driver_setup.pci_fix_up & 1) && (chip->features & FE_CLSE) &&
+ !cache_line_size && suggested_cache_line_size) {
+ cache_line_size = suggested_cache_line_size;
+ pcibios_write_config_byte(bus, device_fn,
+ PCI_CACHE_LINE_SIZE, cache_line_size);
+ printk(NAME53C8XX ": PCI_CACHE_LINE_SIZE set to %d (fix-up).\n",
+ cache_line_size);
+ }
+
+ if ((driver_setup.pci_fix_up & 2) && cache_line_size &&
+ (chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) {
+ printk(NAME53C8XX": setting PCI_COMMAND_INVALIDATE (fix-up)\n");
+ command |= PCI_COMMAND_INVALIDATE;
+ pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+ }
+
+ /*
+ ** Tune PCI LATENCY TIMER according to burst max length transfer.
+ ** (latency timer >= burst length + 6, we add 10 to be quite sure)
+ */
+
+ if ((driver_setup.pci_fix_up & 4) && chip->burst_max) {
+ uchar lt = (1 << chip->burst_max) + 6 + 10;
+ if (latency_timer < lt) {
+ latency_timer = lt;
+ printk(NAME53C8XX
+ ": setting PCI_LATENCY_TIMER to %d (fix-up).\n",
+ latency_timer);
+ pcibios_write_config_byte(bus, device_fn,
+ PCI_LATENCY_TIMER, latency_timer);
+ }
+ }
+
+#endif /* SCSI_NCR_PCI_FIX_UP_SUPPORT */
+
+ /*
+ ** Initialise ncr_device structure with items required by ncr_attach.
+ */
+ device->slot.bus = bus;
+ device->slot.device_fn = device_fn;
+ device->slot.base = base;
+ device->slot.base_2 = base_2;
+ device->slot.io_port = io_port;
+ device->slot.irq = irq;
+ device->attach_done = 0;
+
+ return 0;
+}
+
+
+/*===================================================================
+** Detect and try to read SYMBIOS and TEKRAM NVRAM.
+**
+** Data can be used to order booting of boards.
+**
+** Data is saved in ncr_device structure if NVRAM found. This
+** is then used to find drive boot order for ncr_attach().
+**
+** NVRAM data is passed to Scsi_Host_Template later during
+** ncr_attach() for any device set up.
+*===================================================================
+*/
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+__initfunc(static void ncr_get_nvram(ncr_device *devp, ncr_nvram *nvp))
+{
+ devp->nvram = nvp;
+ if (!nvp)
+ return;
+ /*
+ ** Get access to chip IO registers
+ */
+#ifdef NCR_IOMAPPED
+ request_region(devp->slot.io_port, 128, NAME53C8XX);
+ devp->slot.base_io = devp->slot.io_port;
+#else
+ devp->slot.reg = (struct ncr_reg *) remap_pci_mem(devp->slot.base, 128);
+ if (!devp->slot.reg)
+ return;
+#endif
+
+ /*
+ ** Try to read SYMBIOS nvram.
+ ** Try to read TEKRAM nvram if Symbios nvram not found.
+ */
+ if (!ncr_get_Symbios_nvram(&devp->slot, &nvp->data.Symbios))
+ nvp->type = SCSI_NCR_SYMBIOS_NVRAM;
+ else if (!ncr_get_Tekram_nvram(&devp->slot, &nvp->data.Tekram))
+ nvp->type = SCSI_NCR_TEKRAM_NVRAM;
+ else {
+ nvp->type = 0;
+ devp->nvram = 0;
+ }
+
+ /*
+ ** Release access to chip IO registers
+ */
+#ifdef NCR_IOMAPPED
+ release_region(devp->slot.base_io, 128);
+#else
+ unmap_pci_mem((u_long) devp->slot.reg, 128ul);
+#endif
+
+}
+#endif /* SCSI_NCR_NVRAM_SUPPORT */
+
+/*
+** Linux select queue depths function
+*/
+
+#define DEF_DEPTH (driver_setup.default_tags)
+#define ALL_TARGETS -2
+#define NO_TARGET -1
+#define ALL_LUNS -2
+#define NO_LUN -1
+
+static int device_queue_depth(ncb_p np, int target, int lun)
+{
+ int c, h, t, u, v;
+ char *p = driver_setup.tag_ctrl;
+ char *ep;
+
+ h = -1;
+ t = NO_TARGET;
+ u = NO_LUN;
+ while ((c = *p++) != 0) {
+ v = simple_strtoul(p, &ep, 0);
+ switch(c) {
+ case '/':
+ ++h;
+ t = ALL_TARGETS;
+ u = ALL_LUNS;
+ break;
+ case 't':
+ if (t != target)
+ t = (target == v) ? v : NO_TARGET;
+ u = ALL_LUNS;
+ break;
+ case 'u':
+ if (u != lun)
+ u = (lun == v) ? v : NO_LUN;
+ break;
+ case 'q':
+ if (h == np->unit &&
+ (t == ALL_TARGETS || t == target) &&
+ (u == ALL_LUNS || u == lun))
+ return v;
+ break;
+ case '-':
+ t = ALL_TARGETS;
+ u = ALL_LUNS;
+ break;
+ default:
+ break;
+ }
+ p = ep;
+ }
+ return DEF_DEPTH;
+}
+
+static void sym53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_device *devlist)
+{
+ struct scsi_device *device;
+
+ for (device = devlist; device; device = device->next) {
+ ncb_p np;
+ tcb_p tp;
+ lcb_p lp;
+ int numtags;
+
+ if (device->host != host)
+ continue;
+
+ np = ((struct host_data *) host->hostdata)->ncb;
+ tp = &np->target[device->id];
+ lp = tp->lp[device->lun];
+
+ /*
+ ** Select queue depth from driver setup.
+ ** Donnot use more than configured by user.
+ ** Use at least 2.
+ ** Donnot use more than our maximum.
+ */
+ numtags = device_queue_depth(np, device->id, device->lun);
+ if (numtags > tp->usrtags)
+ numtags = tp->usrtags;
+ if (!device->tagged_supported)
+ numtags = 1;
+ device->queue_depth = numtags;
+ if (device->queue_depth < 2)
+ device->queue_depth = 2;
+ if (device->queue_depth > SCSI_NCR_MAX_TAGS)
+ device->queue_depth = SCSI_NCR_MAX_TAGS;
+
+ /*
+ ** Since the queue depth is not tunable under Linux,
+ ** we need to know this value in order not to
+ ** announce stupid things to user.
+ */
+ if (lp) {
+ lp->numtags = lp->maxtags = numtags;
+ lp->scdev_depth = device->queue_depth;
+ }
+ ncr_setup_tags (np, device->id, device->lun);
+
+#ifdef DEBUG_SYM53C8XX
+printk("sym53c8xx_select_queue_depth: host=%d, id=%d, lun=%d, depth=%d\n",
+ np->unit, device->id, device->lun, device->queue_depth);
+#endif
+ }
+}
+
+/*
+** Linux entry point for info() function
+*/
+const char *sym53c8xx_info (struct Scsi_Host *host)
+{
+ return SCSI_NCR_DRIVER_NAME;
+}
+
+/*
+** Linux entry point of queuecommand() function
+*/
+
+int sym53c8xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
+{
+ ncb_p np = ((struct host_data *) cmd->host->hostdata)->ncb;
+ unsigned long flags;
+ int sts;
+
+#ifdef DEBUG_SYM53C8XX
+printk("sym53c8xx_queue_command\n");
+#endif
+
+ cmd->scsi_done = done;
+ cmd->host_scribble = NULL;
+ cmd->SCp.ptr = NULL;
+ cmd->SCp.buffer = NULL;
+
+ NCR_LOCK_NCB(np, flags);
+
+ if ((sts = ncr_queue_command(np, cmd)) != DID_OK) {
+ SetScsiResult(cmd, sts, 0);
+#ifdef DEBUG_SYM53C8XX
+printk("sym53c8xx : command not queued - result=%d\n", sts);
+#endif
+ }
+#ifdef DEBUG_SYM53C8XX
+ else
+printk("sym53c8xx : command successfully queued\n");
+#endif
+
+ NCR_UNLOCK_NCB(np, flags);
+
+ if (sts != DID_OK)
+ done(cmd);
+
+ return sts;
+}
+
+/*
+** Linux entry point of the interrupt handler.
+** Since linux versions > 1.3.70, we trust the kernel for
+** passing the internal host descriptor as 'dev_id'.
+** Otherwise, we scan the host list and call the interrupt
+** routine for each host that uses this IRQ.
+*/
+
+static void sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs)
+{
+ unsigned long flags;
+ ncb_p np = (ncb_p) dev_id;
+ Scsi_Cmnd *done_list;
+
+#ifdef DEBUG_SYM53C8XX
+ printk("sym53c8xx : interrupt received\n");
+#endif
+
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("[");
+
+ NCR_LOCK_NCB(np, flags);
+ ncr_exception(np);
+ done_list = np->done_list;
+ np->done_list = 0;
+ NCR_UNLOCK_NCB(np, flags);
+
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("]\n");
+
+ if (done_list) {
+ NCR_LOCK_SCSI_DONE(np, flags);
+ ncr_flush_done_cmds(done_list);
+ NCR_UNLOCK_SCSI_DONE(np, flags);
+ }
+}
+
+/*
+** Linux entry point of the timer handler
+*/
+
+static void sym53c8xx_timeout(unsigned long npref)
+{
+ ncb_p np = (ncb_p) npref;
+ unsigned long flags;
+ Scsi_Cmnd *done_list;
+
+ NCR_LOCK_NCB(np, flags);
+ ncr_timeout((ncb_p) np);
+ done_list = np->done_list;
+ np->done_list = 0;
+ NCR_UNLOCK_NCB(np, flags);
+
+ if (done_list) {
+ NCR_LOCK_SCSI_DONE(np, flags);
+ ncr_flush_done_cmds(done_list);
+ NCR_UNLOCK_SCSI_DONE(np, flags);
+ }
+}
+
+/*
+** Linux entry point of reset() function
+*/
+
+#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
+int sym53c8xx_reset(Scsi_Cmnd *cmd, unsigned int reset_flags)
+#else
+int sym53c8xx_reset(Scsi_Cmnd *cmd)
+#endif
+{
+ ncb_p np = ((struct host_data *) cmd->host->hostdata)->ncb;
+ int sts;
+ unsigned long flags;
+ Scsi_Cmnd *done_list;
+
+#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
+ printk("sym53c8xx_reset: pid=%lu reset_flags=%x serial_number=%ld serial_number_at_timeout=%ld\n",
+ cmd->pid, reset_flags, cmd->serial_number, cmd->serial_number_at_timeout);
+#else
+ printk("sym53c8xx_reset: command pid %lu\n", cmd->pid);
+#endif
+
+ NCR_LOCK_NCB(np, flags);
+
+ /*
+ * We have to just ignore reset requests in some situations.
+ */
+#if defined SCSI_RESET_NOT_RUNNING
+ if (cmd->serial_number != cmd->serial_number_at_timeout) {
+ sts = SCSI_RESET_NOT_RUNNING;
+ goto out;
+ }
+#endif
+ /*
+ * If the mid-level driver told us reset is synchronous, it seems
+ * that we must call the done() callback for the involved command,
+ * even if this command was not queued to the low-level driver,
+ * before returning SCSI_RESET_SUCCESS.
+ */
+
+#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
+ sts = ncr_reset_bus(np, cmd,
+ (reset_flags & (SCSI_RESET_SYNCHRONOUS | SCSI_RESET_ASYNCHRONOUS)) == SCSI_RESET_SYNCHRONOUS);
+#else
+ sts = ncr_reset_bus(np, cmd, 0);
+#endif
+
+ /*
+ * Since we always reset the controller, when we return success,
+ * we add this information to the return code.
+ */
+#if defined SCSI_RESET_HOST_RESET
+ if (sts == SCSI_RESET_SUCCESS)
+ sts |= SCSI_RESET_HOST_RESET;
+#endif
+
+out:
+ done_list = np->done_list;
+ np->done_list = 0;
+ NCR_UNLOCK_NCB(np, flags);
+
+ ncr_flush_done_cmds(done_list);
+
+ return sts;
+}
+
+/*
+** Linux entry point of abort() function
+*/
+
+int sym53c8xx_abort(Scsi_Cmnd *cmd)
+{
+ ncb_p np = ((struct host_data *) cmd->host->hostdata)->ncb;
+ int sts;
+ unsigned long flags;
+ Scsi_Cmnd *done_list;
+
+#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
+ printk("sym53c8xx_abort: pid=%lu serial_number=%ld serial_number_at_timeout=%ld\n",
+ cmd->pid, cmd->serial_number, cmd->serial_number_at_timeout);
+#else
+ printk("sym53c8xx_abort: command pid %lu\n", cmd->pid);
+#endif
+
+ NCR_LOCK_NCB(np, flags);
+
+#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
+ /*
+ * We have to just ignore abort requests in some situations.
+ */
+ if (cmd->serial_number != cmd->serial_number_at_timeout) {
+ sts = SCSI_ABORT_NOT_RUNNING;
+ goto out;
+ }
+#endif
+
+ sts = ncr_abort_command(np, cmd);
+out:
+ done_list = np->done_list;
+ np->done_list = 0;
+ NCR_UNLOCK_NCB(np, flags);
+
+ ncr_flush_done_cmds(done_list);
+
+ return sts;
+}
+
+
+#ifdef MODULE
+int sym53c8xx_release(struct Scsi_Host *host)
+{
+#ifdef DEBUG_SYM53C8XX
+printk("sym53c8xx : release\n");
+#endif
+ ncr_detach(((struct host_data *) host->hostdata)->ncb);
+
+ return 1;
+}
+#endif
+
+
+/*
+** Scsi command waiting list management.
+**
+** It may happen that we cannot insert a scsi command into the start queue,
+** in the following circumstances.
+** Too few preallocated ccb(s),
+** maxtags < cmd_per_lun of the Linux host control block,
+** etc...
+** Such scsi commands are inserted into a waiting list.
+** When a scsi command complete, we try to requeue the commands of the
+** waiting list.
+*/
+
+#define next_wcmd host_scribble
+
+static void insert_into_waiting_list(ncb_p np, Scsi_Cmnd *cmd)
+{
+ Scsi_Cmnd *wcmd;
+
+#ifdef DEBUG_WAITING_LIST
+ printk("%s: cmd %lx inserted into waiting list\n", ncr_name(np), (u_long) cmd);
+#endif
+ cmd->next_wcmd = 0;
+ if (!(wcmd = np->waiting_list)) np->waiting_list = cmd;
+ else {
+ while ((wcmd->next_wcmd) != 0)
+ wcmd = (Scsi_Cmnd *) wcmd->next_wcmd;
+ wcmd->next_wcmd = (char *) cmd;
+ }
+}
+
+static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd *cmd)
+{
+ Scsi_Cmnd **pcmd = &np->waiting_list;
+
+ while (*pcmd) {
+ if (cmd == *pcmd) {
+ if (to_remove) {
+ *pcmd = (Scsi_Cmnd *) cmd->next_wcmd;
+ cmd->next_wcmd = 0;
+ }
+#ifdef DEBUG_WAITING_LIST
+ printk("%s: cmd %lx retrieved from waiting list\n", ncr_name(np), (u_long) cmd);
+#endif
+ return cmd;
+ }
+ pcmd = (Scsi_Cmnd **) &(*pcmd)->next_wcmd;
+ }
+ return 0;
+}
+
+static void process_waiting_list(ncb_p np, int sts)
+{
+ Scsi_Cmnd *waiting_list, *wcmd;
+
+ waiting_list = np->waiting_list;
+ np->waiting_list = 0;
+
+#ifdef DEBUG_WAITING_LIST
+ if (waiting_list) printk("%s: waiting_list=%lx processing sts=%d\n", ncr_name(np), (u_long) waiting_list, sts);
+#endif
+ while ((wcmd = waiting_list) != 0) {
+ waiting_list = (Scsi_Cmnd *) wcmd->next_wcmd;
+ wcmd->next_wcmd = 0;
+ if (sts == DID_OK) {
+#ifdef DEBUG_WAITING_LIST
+ printk("%s: cmd %lx trying to requeue\n", ncr_name(np), (u_long) wcmd);
+#endif
+ sts = ncr_queue_command(np, wcmd);
+ }
+ if (sts != DID_OK) {
+#ifdef DEBUG_WAITING_LIST
+ printk("%s: cmd %lx done forced sts=%d\n", ncr_name(np), (u_long) wcmd, sts);
+#endif
+ SetScsiResult(wcmd, sts, 0);
+ ncr_queue_done_cmd(np, wcmd);
+ }
+ }
+}
+
+#undef next_wcmd
+
+#ifdef SCSI_NCR_PROC_INFO_SUPPORT
+
+/*=========================================================================
+** Proc file system stuff
+**
+** A read operation returns profile information.
+** A write operation is a control command.
+** The string is parsed in the driver code and the command is passed
+** to the ncr_usercmd() function.
+**=========================================================================
+*/
+
+#ifdef SCSI_NCR_USER_COMMAND_SUPPORT
+
+#define is_digit(c) ((c) >= '0' && (c) <= '9')
+#define digit_to_bin(c) ((c) - '0')
+#define is_space(c) ((c) == ' ' || (c) == '\t')
+
+static int skip_spaces(char *ptr, int len)
+{
+ int cnt, c;
+
+ for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt--);
+
+ return (len - cnt);
+}
+
+static int get_int_arg(char *ptr, int len, u_long *pv)
+{
+ int cnt, c;
+ u_long v;
+
+ for (v = 0, cnt = len; cnt > 0 && (c = *ptr++) && is_digit(c); cnt--) {
+ v = (v * 10) + digit_to_bin(c);
+ }
+
+ if (pv)
+ *pv = v;
+
+ return (len - cnt);
+}
+
+static int is_keyword(char *ptr, int len, char *verb)
+{
+ int verb_len = strlen(verb);
+
+ if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len))
+ return verb_len;
+ else
+ return 0;
+
+}
+
+#define SKIP_SPACES(min_spaces) \
+ if ((arg_len = skip_spaces(ptr, len)) < (min_spaces)) \
+ return -EINVAL; \
+ ptr += arg_len; len -= arg_len;
+
+#define GET_INT_ARG(v) \
+ if (!(arg_len = get_int_arg(ptr, len, &(v)))) \
+ return -EINVAL; \
+ ptr += arg_len; len -= arg_len;
+
+
+/*
+** Parse a control command
+*/
+
+static int ncr_user_command(ncb_p np, char *buffer, int length)
+{
+ char *ptr = buffer;
+ int len = length;
+ struct usrcmd *uc = &np->user;
+ int arg_len;
+ u_long target;
+
+ bzero(uc, sizeof(*uc));
+
+ if (len > 0 && ptr[len-1] == '\n')
+ --len;
+
+ if ((arg_len = is_keyword(ptr, len, "setsync")) != 0)
+ uc->cmd = UC_SETSYNC;
+ else if ((arg_len = is_keyword(ptr, len, "settags")) != 0)
+ uc->cmd = UC_SETTAGS;
+ else if ((arg_len = is_keyword(ptr, len, "setorder")) != 0)
+ uc->cmd = UC_SETORDER;
+ else if ((arg_len = is_keyword(ptr, len, "setverbose")) != 0)
+ uc->cmd = UC_SETVERBOSE;
+ else if ((arg_len = is_keyword(ptr, len, "setwide")) != 0)
+ uc->cmd = UC_SETWIDE;
+ else if ((arg_len = is_keyword(ptr, len, "setdebug")) != 0)
+ uc->cmd = UC_SETDEBUG;
+ else if ((arg_len = is_keyword(ptr, len, "setflag")) != 0)
+ uc->cmd = UC_SETFLAG;
+ else if ((arg_len = is_keyword(ptr, len, "clearprof")) != 0)
+ uc->cmd = UC_CLEARPROF;
+ else
+ arg_len = 0;
+
+#ifdef DEBUG_PROC_INFO
+printk("ncr_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd);
+#endif
+
+ if (!arg_len)
+ return -EINVAL;
+ ptr += arg_len; len -= arg_len;
+
+ switch(uc->cmd) {
+ case UC_SETSYNC:
+ case UC_SETTAGS:
+ case UC_SETWIDE:
+ case UC_SETFLAG:
+ SKIP_SPACES(1);
+ if ((arg_len = is_keyword(ptr, len, "all")) != 0) {
+ ptr += arg_len; len -= arg_len;
+ uc->target = ~0;
+ } else {
+ GET_INT_ARG(target);
+ uc->target = (1<<target);
+#ifdef DEBUG_PROC_INFO
+printk("ncr_user_command: target=%ld\n", target);
+#endif
+ }
+ break;
+ }
+
+ switch(uc->cmd) {
+ case UC_SETVERBOSE:
+ case UC_SETSYNC:
+ case UC_SETTAGS:
+ case UC_SETWIDE:
+ SKIP_SPACES(1);
+ GET_INT_ARG(uc->data);
+#ifdef DEBUG_PROC_INFO
+printk("ncr_user_command: data=%ld\n", uc->data);
+#endif
+ break;
+ case UC_SETORDER:
+ SKIP_SPACES(1);
+ if ((arg_len = is_keyword(ptr, len, "simple")))
+ uc->data = M_SIMPLE_TAG;
+ else if ((arg_len = is_keyword(ptr, len, "ordered")))
+ uc->data = M_ORDERED_TAG;
+ else if ((arg_len = is_keyword(ptr, len, "default")))
+ uc->data = 0;
+ else
+ return -EINVAL;
+ break;
+ case UC_SETDEBUG:
+ while (len > 0) {
+ SKIP_SPACES(1);
+ if ((arg_len = is_keyword(ptr, len, "alloc")))
+ uc->data |= DEBUG_ALLOC;
+ else if ((arg_len = is_keyword(ptr, len, "phase")))
+ uc->data |= DEBUG_PHASE;
+ else if ((arg_len = is_keyword(ptr, len, "poll")))
+ uc->data |= DEBUG_POLL;
+ else if ((arg_len = is_keyword(ptr, len, "queue")))
+ uc->data |= DEBUG_QUEUE;
+ else if ((arg_len = is_keyword(ptr, len, "result")))
+ uc->data |= DEBUG_RESULT;
+ else if ((arg_len = is_keyword(ptr, len, "scatter")))
+ uc->data |= DEBUG_SCATTER;
+ else if ((arg_len = is_keyword(ptr, len, "script")))
+ uc->data |= DEBUG_SCRIPT;
+ else if ((arg_len = is_keyword(ptr, len, "tiny")))
+ uc->data |= DEBUG_TINY;
+ else if ((arg_len = is_keyword(ptr, len, "timing")))
+ uc->data |= DEBUG_TIMING;
+ else if ((arg_len = is_keyword(ptr, len, "nego")))
+ uc->data |= DEBUG_NEGO;
+ else if ((arg_len = is_keyword(ptr, len, "tags")))
+ uc->data |= DEBUG_TAGS;
+ else if ((arg_len = is_keyword(ptr, len, "freeze")))
+ uc->data |= DEBUG_FREEZE;
+ else if ((arg_len = is_keyword(ptr, len, "restart")))
+ uc->data |= DEBUG_RESTART;
+ else
+ return -EINVAL;
+ ptr += arg_len; len -= arg_len;
+ }
+#ifdef DEBUG_PROC_INFO
+printk("ncr_user_command: data=%ld\n", uc->data);
+#endif
+ break;
+ case UC_SETFLAG:
+ while (len > 0) {
+ SKIP_SPACES(1);
+ if ((arg_len = is_keyword(ptr, len, "trace")))
+ uc->data |= UF_TRACE;
+ else if ((arg_len = is_keyword(ptr, len, "no_disc")))
+ uc->data |= UF_NODISC;
+ else
+ return -EINVAL;
+ ptr += arg_len; len -= arg_len;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (len)
+ return -EINVAL;
+ else {
+ long flags;
+
+ NCR_LOCK_NCB(np, flags);
+ ncr_usercmd (np);
+ NCR_UNLOCK_NCB(np, flags);
+ }
+ return length;
+}
+
+#endif /* SCSI_NCR_USER_COMMAND_SUPPORT */
+
+#ifdef SCSI_NCR_USER_INFO_SUPPORT
+
+struct info_str
+{
+ char *buffer;
+ int length;
+ int offset;
+ int pos;
+};
+
+static void copy_mem_info(struct info_str *info, char *data, int len)
+{
+ if (info->pos + len > info->length)
+ len = info->length - info->pos;
+
+ if (info->pos + len < info->offset) {
+ info->pos += len;
+ return;
+ }
+ if (info->pos < info->offset) {
+ data += (info->offset - info->pos);
+ len -= (info->offset - info->pos);
+ }
+
+ if (len > 0) {
+ memcpy(info->buffer + info->pos, data, len);
+ info->pos += len;
+ }
+}
+
+static int copy_info(struct info_str *info, char *fmt, ...)
+{
+ va_list args;
+ char buf[81];
+ int len;
+
+ va_start(args, fmt);
+ len = vsprintf(buf, fmt, args);
+ va_end(args);
+
+ copy_mem_info(info, buf, len);
+ return len;
+}
+
+/*
+** Copy formatted profile information into the input buffer.
+*/
+
+#define to_ms(t) ((t) * 1000 / HZ)
+
+static int ncr_host_info(ncb_p np, char *ptr, off_t offset, int len)
+{
+ struct info_str info;
+
+ info.buffer = ptr;
+ info.length = len;
+ info.offset = offset;
+ info.pos = 0;
+
+ copy_info(&info, "General information:\n");
+ copy_info(&info, " Chip " NAME53C "%s, ", np->chip_name);
+ copy_info(&info, "device id 0x%x, ", np->device_id);
+ copy_info(&info, "revision id 0x%x\n", np->revision_id);
+
+ copy_info(&info, " IO port address 0x%lx, ", (u_long) np->base_io);
+ copy_info(&info, "IRQ number %d\n", (int) np->irq);
+
+#ifndef NCR_IOMAPPED
+ if (np->reg)
+ copy_info(&info, " Using memory mapped IO at virtual address 0x%lx\n",
+ (u_long) np->reg);
+#endif
+ copy_info(&info, " Synchronous period factor %d, ", (int) np->minsync);
+ copy_info(&info, "max commands per lun %d\n", SCSI_NCR_MAX_TAGS);
+
+ if (driver_setup.debug || driver_setup.verbose > 1) {
+ copy_info(&info, " Debug flags 0x%x, ", driver_setup.debug);
+ copy_info(&info, "verbosity level %d\n", driver_setup.verbose);
+ }
+
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ copy_info(&info, "Profiling information:\n");
+ copy_info(&info, " %-12s = %lu\n", "num_fly", np->profile.num_fly);
+ copy_info(&info, " %-12s = %lu\n", "num_trans",np->profile.num_trans);
+ copy_info(&info, " %-12s = %lu\n", "num_disc", np->profile.num_disc);
+ copy_info(&info, " %-12s = %lu\n", "num_disc0",np->profile.num_disc0);
+ copy_info(&info, " %-12s = %lu\n", "num_break",np->profile.num_break);
+#if 000
+ copy_info(&info, " %-12s = %lu\n", "num_br1k",np->profile.num_br1k);
+ copy_info(&info, " %-12s = %lu\n", "num_br2k",np->profile.num_br2k);
+ copy_info(&info, " %-12s = %lu\n", "num_br4k",np->profile.num_br4k);
+ copy_info(&info, " %-12s = %lu\n", "num_br8k",np->profile.num_br8k);
+ copy_info(&info, " %-12s = %lu\n", "num_brnk",np->profile.num_brnk);
+#endif
+ copy_info(&info, " %-12s = %lu\n", "num_int", np->profile.num_int);
+ copy_info(&info, " %-12s = %lu\n","num_kbytes",np->profile.num_kbytes);
+#endif
+
+ return info.pos > info.offset? info.pos - info.offset : 0;
+}
+
+#endif /* SCSI_NCR_USER_INFO_SUPPORT */
+
+/*
+** Entry point of the scsi proc fs of the driver.
+** - func = 0 means read (returns profile data)
+** - func = 1 means write (parse user control command)
+*/
+
+static int sym53c8xx_proc_info(char *buffer, char **start, off_t offset,
+ int length, int hostno, int func)
+{
+ struct Scsi_Host *host;
+ struct host_data *host_data;
+ ncb_p ncb = 0;
+ int retv;
+
+#ifdef DEBUG_PROC_INFO
+printk("sym53c8xx_proc_info: hostno=%d, func=%d\n", hostno, func);
+#endif
+
+ for (host = first_host; host; host = host->next) {
+ if (host->hostt != first_host->hostt)
+ continue;
+ if (host->host_no == hostno) {
+ host_data = (struct host_data *) host->hostdata;
+ ncb = host_data->ncb;
+ break;
+ }
+ }
+
+ if (!ncb)
+ return -EINVAL;
+
+ if (func) {
+#ifdef SCSI_NCR_USER_COMMAND_SUPPORT
+ retv = ncr_user_command(ncb, buffer, length);
+#else
+ retv = -EINVAL;
+#endif
+ }
+ else {
+ if (start)
+ *start = buffer;
+#ifdef SCSI_NCR_USER_INFO_SUPPORT
+ retv = ncr_host_info(ncb, buffer, offset, length);
+#else
+ retv = -EINVAL;
+#endif
+ }
+
+ return retv;
+}
+
+
+/*=========================================================================
+** End of proc file system stuff
+**=========================================================================
+*/
+#endif
+
+
+#ifdef SCSI_NCR_NVRAM_SUPPORT
+
+/* ---------------------------------------------------------------------
+**
+** Try reading Symbios format nvram
+**
+** ---------------------------------------------------------------------
+**
+** GPOI0 - data in/data out
+** GPIO1 - clock
+**
+** return 0 if NVRAM data OK, 1 if NVRAM data not OK
+** ---------------------------------------------------------------------
+*/
+
+#define SET_BIT 0
+#define CLR_BIT 1
+#define SET_CLK 2
+#define CLR_CLK 3
+
+static u_short nvram_read_data(ncr_slot *np, u_char *data, int len, u_char *gpreg, u_char *gpcntl);
+static void nvram_start(ncr_slot *np, u_char *gpreg);
+static void nvram_write_byte(ncr_slot *np, u_char *ack_data, u_char write_data, u_char *gpreg, u_char *gpcntl);
+static void nvram_read_byte(ncr_slot *np, u_char *read_data, u_char ack_data, u_char *gpreg, u_char *gpcntl);
+static void nvram_readAck(ncr_slot *np, u_char *read_bit, u_char *gpreg, u_char *gpcntl);
+static void nvram_writeAck(ncr_slot *np, u_char write_bit, u_char *gpreg, u_char *gpcntl);
+static void nvram_doBit(ncr_slot *np, u_char *read_bit, u_char write_bit, u_char *gpreg);
+static void nvram_stop(ncr_slot *np, u_char *gpreg);
+static void nvram_setBit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode);
+
+__initfunc(
+static int ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram)
+)
+{
+ static u_char Symbios_trailer[6] = {0xfe, 0xfe, 0, 0, 0, 0};
+ u_char gpcntl, gpreg;
+ u_char old_gpcntl, old_gpreg;
+ u_short csum;
+ u_char ack_data;
+ int retv = 1;
+
+ /* save current state of GPCNTL and GPREG */
+ old_gpreg = INB (nc_gpreg);
+ old_gpcntl = INB (nc_gpcntl);
+ gpcntl = old_gpcntl & 0xfc;
+
+ /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */
+ OUTB (nc_gpreg, old_gpreg);
+ OUTB (nc_gpcntl, gpcntl);
+
+ /* this is to set NVRAM into a known state with GPIO0/1 both low */
+ gpreg = old_gpreg;
+ nvram_setBit(np, 0, &gpreg, CLR_CLK);
+ nvram_setBit(np, 0, &gpreg, CLR_BIT);
+
+ /* now set NVRAM inactive with GPIO0/1 both high */
+ nvram_stop(np, &gpreg);
+
+ /* activate NVRAM */
+ nvram_start(np, &gpreg);
+
+ /* write device code and random address MSB */
+ nvram_write_byte(np, &ack_data,
+ 0xa0 | ((SYMBIOS_NVRAM_ADDRESS >> 7) & 0x0e), &gpreg, &gpcntl);
+ if (ack_data & 0x01)
+ goto out;
+
+ /* write random address LSB */
+ nvram_write_byte(np, &ack_data,
+ (SYMBIOS_NVRAM_ADDRESS & 0x7f) << 1, &gpreg, &gpcntl);
+ if (ack_data & 0x01)
+ goto out;
+
+ /* regenerate START state to set up for reading */
+ nvram_start(np, &gpreg);
+
+ /* rewrite device code and address MSB with read bit set (lsb = 0x01) */
+ nvram_write_byte(np, &ack_data,
+ 0xa1 | ((SYMBIOS_NVRAM_ADDRESS >> 7) & 0x0e), &gpreg, &gpcntl);
+ if (ack_data & 0x01)
+ goto out;
+
+ /* now set up GPIO0 for inputting data */
+ gpcntl |= 0x01;
+ OUTB (nc_gpcntl, gpcntl);
+
+ /* input all active data - only part of total NVRAM */
+ csum = nvram_read_data(np,
+ (u_char *) nvram, sizeof(*nvram), &gpreg, &gpcntl);
+
+ /* finally put NVRAM back in inactive mode */
+ gpcntl &= 0xfe;
+ OUTB (nc_gpcntl, gpcntl);
+ nvram_stop(np, &gpreg);
+
+#ifdef SCSI_NCR_DEBUG_NVRAM
+printk("sym53c8xx: NvRAM marker=%x trailer=%x %x %x %x %x %x byte_count=%d/%d checksum=%x/%x\n",
+ nvram->start_marker,
+ nvram->trailer[0], nvram->trailer[1], nvram->trailer[2],
+ nvram->trailer[3], nvram->trailer[4], nvram->trailer[5],
+ nvram->byte_count, sizeof(*nvram) - 12,
+ nvram->checksum, csum);
+#endif
+
+ /* check valid NVRAM signature, verify byte count and checksum */
+ if (nvram->type == 0 &&
+ !memcmp(nvram->trailer, Symbios_trailer, 6) &&
+ nvram->byte_count == sizeof(*nvram) - 12 &&
+ csum == nvram->checksum)
+ retv = 0;
+out:
+ /* return GPIO0/1 to original states after having accessed NVRAM */
+ OUTB (nc_gpcntl, old_gpcntl);
+ OUTB (nc_gpreg, old_gpreg);
+
+ return retv;
+}
+
+/*
+ * Read Symbios NvRAM data and compute checksum.
+ */
+__initfunc(
+static u_short nvram_read_data(ncr_slot *np, u_char *data, int len, u_char *gpreg, u_char *gpcntl)
+)
+{
+ int x;
+ u_short csum;
+
+ for (x = 0; x < len; x++)
+ nvram_read_byte(np, &data[x], (x == (len - 1)), gpreg, gpcntl);
+
+ for (x = 6, csum = 0; x < len - 6; x++)
+ csum += data[x];
+
+ return csum;
+}
+
+/*
+ * Send START condition to NVRAM to wake it up.
+ */
+__initfunc(
+static void nvram_start(ncr_slot *np, u_char *gpreg)
+)
+{
+ nvram_setBit(np, 1, gpreg, SET_BIT);
+ nvram_setBit(np, 0, gpreg, SET_CLK);
+ nvram_setBit(np, 0, gpreg, CLR_BIT);
+ nvram_setBit(np, 0, gpreg, CLR_CLK);
+}
+
+/*
+ * WRITE a byte to the NVRAM and then get an ACK to see it was accepted OK,
+ * GPIO0 must already be set as an output
+ */
+__initfunc(
+static void nvram_write_byte(ncr_slot *np, u_char *ack_data, u_char write_data, u_char *gpreg, u_char *gpcntl)
+)
+{
+ int x;
+
+ for (x = 0; x < 8; x++)
+ nvram_doBit(np, 0, (write_data >> (7 - x)) & 0x01, gpreg);
+
+ nvram_readAck(np, ack_data, gpreg, gpcntl);
+}
+
+/*
+ * READ a byte from the NVRAM and then send an ACK to say we have got it,
+ * GPIO0 must already be set as an input
+ */
+__initfunc(
+static void nvram_read_byte(ncr_slot *np, u_char *read_data, u_char ack_data, u_char *gpreg, u_char *gpcntl)
+)
+{
+ int x;
+ u_char read_bit;
+
+ *read_data = 0;
+ for (x = 0; x < 8; x++) {
+ nvram_doBit(np, &read_bit, 1, gpreg);
+ *read_data |= ((read_bit & 0x01) << (7 - x));
+ }
+
+ nvram_writeAck(np, ack_data, gpreg, gpcntl);
+}
+
+/*
+ * Output an ACK to the NVRAM after reading,
+ * change GPIO0 to output and when done back to an input
+ */
+__initfunc(
+static void nvram_writeAck(ncr_slot *np, u_char write_bit, u_char *gpreg, u_char *gpcntl)
+)
+{
+ OUTB (nc_gpcntl, *gpcntl & 0xfe);
+ nvram_doBit(np, 0, write_bit, gpreg);
+ OUTB (nc_gpcntl, *gpcntl);
+}
+
+/*
+ * Input an ACK from NVRAM after writing,
+ * change GPIO0 to input and when done back to an output
+ */
+__initfunc(
+static void nvram_readAck(ncr_slot *np, u_char *read_bit, u_char *gpreg, u_char *gpcntl)
+)
+{
+ OUTB (nc_gpcntl, *gpcntl | 0x01);
+ nvram_doBit(np, read_bit, 1, gpreg);
+ OUTB (nc_gpcntl, *gpcntl);
+}
+
+/*
+ * Read or write a bit to the NVRAM,
+ * read if GPIO0 input else write if GPIO0 output
+ */
+__initfunc(
+static void nvram_doBit(ncr_slot *np, u_char *read_bit, u_char write_bit, u_char *gpreg)
+)
+{
+ nvram_setBit(np, write_bit, gpreg, SET_BIT);
+ nvram_setBit(np, 0, gpreg, SET_CLK);
+ if (read_bit)
+ *read_bit = INB (nc_gpreg);
+ nvram_setBit(np, 0, gpreg, CLR_CLK);
+ nvram_setBit(np, 0, gpreg, CLR_BIT);
+}
+
+/*
+ * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZzzzz!!
+ */
+__initfunc(
+static void nvram_stop(ncr_slot *np, u_char *gpreg)
+)
+{
+ nvram_setBit(np, 0, gpreg, SET_CLK);
+ nvram_setBit(np, 1, gpreg, SET_BIT);
+}
+
+/*
+ * Set/clear data/clock bit in GPIO0
+ */
+__initfunc(
+static void nvram_setBit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode)
+)
+{
+ UDELAY (5);
+ switch (bit_mode){
+ case SET_BIT:
+ *gpreg |= write_bit;
+ break;
+ case CLR_BIT:
+ *gpreg &= 0xfe;
+ break;
+ case SET_CLK:
+ *gpreg |= 0x02;
+ break;
+ case CLR_CLK:
+ *gpreg &= 0xfd;
+ break;
+
+ }
+ OUTB (nc_gpreg, *gpreg);
+ UDELAY (5);
+}
+
+#undef SET_BIT 0
+#undef CLR_BIT 1
+#undef SET_CLK 2
+#undef CLR_CLK 3
+
+
+/* ---------------------------------------------------------------------
+**
+** Try reading Tekram format nvram
+**
+** ---------------------------------------------------------------------
+**
+** GPOI0 - data in
+** GPIO1 - data out
+** GPIO2 - clock
+** GPIO4 - chip select
+**
+** return 0 if NVRAM data OK, 1 if NVRAM data not OK
+** ---------------------------------------------------------------------
+*/
+
+static u_short Tnvram_read_data(ncr_slot *np, u_short *data, int len, u_char *gpreg);
+static void Tnvram_Send_Command(ncr_slot *np, u_short write_data, u_char *read_bit, u_char *gpreg);
+static void Tnvram_Read_Word(ncr_slot *np, u_short *nvram_data, u_char *gpreg);
+static void Tnvram_Read_Bit(ncr_slot *np, u_char *read_bit, u_char *gpreg);
+static void Tnvram_Write_Bit(ncr_slot *np, u_char write_bit, u_char *gpreg);
+static void Tnvram_Stop(ncr_slot *np, u_char *gpreg);
+static void Tnvram_Clk(ncr_slot *np, u_char *gpreg);
+
+__initfunc(
+static int ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram *nvram)
+)
+{
+ u_char gpcntl, gpreg;
+ u_char old_gpcntl, old_gpreg;
+ u_short csum;
+
+ /* save current state of GPCNTL and GPREG */
+ old_gpreg = INB (nc_gpreg);
+ old_gpcntl = INB (nc_gpcntl);
+
+ /* set up GPREG & GPCNTL to set GPIO0/1/2/4 in to known state, 0 in,
+ 1/2/4 out */
+ gpreg = old_gpreg & 0xe9;
+ OUTB (nc_gpreg, gpreg);
+ gpcntl = (old_gpcntl & 0xe9) | 0x09;
+ OUTB (nc_gpcntl, gpcntl);
+
+ /* input all of NVRAM, 64 words */
+ csum = Tnvram_read_data(np, (u_short *) nvram,
+ sizeof(*nvram) / sizeof(short), &gpreg);
+
+ /* return GPIO0/1/2/4 to original states after having accessed NVRAM */
+ OUTB (nc_gpcntl, old_gpcntl);
+ OUTB (nc_gpreg, old_gpreg);
+
+ /* check data valid */
+ if (csum != 0x1234)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Read Tekram NvRAM data and compute checksum.
+ */
+__initfunc(
+static u_short Tnvram_read_data(ncr_slot *np, u_short *data, int len, u_char *gpreg)
+)
+{
+ u_char read_bit;
+ u_short csum;
+ int x;
+
+ for (x = 0, csum = 0; x < len; x++) {
+
+ /* output read command and address */
+ Tnvram_Send_Command(np, 0x180 | x, &read_bit, gpreg);
+ if (read_bit & 0x01)
+ return 0; /* Force bad checksum */
+
+ Tnvram_Read_Word(np, &data[x], gpreg);
+ csum += data[x];
+
+ Tnvram_Stop(np, gpreg);
+ }
+
+ return csum;
+}
+
+/*
+ * Send read command and address to NVRAM
+ */
+__initfunc(
+static void Tnvram_Send_Command(ncr_slot *np, u_short write_data, u_char *read_bit, u_char *gpreg)
+)
+{
+ int x;
+
+ /* send 9 bits, start bit (1), command (2), address (6) */
+ for (x = 0; x < 9; x++)
+ Tnvram_Write_Bit(np, (u_char) (write_data >> (8 - x)), gpreg);
+
+ *read_bit = INB (nc_gpreg);
+}
+
+/*
+ * READ a byte from the NVRAM
+ */
+__initfunc(
+static void Tnvram_Read_Word(ncr_slot *np, u_short *nvram_data, u_char *gpreg)
+)
+{
+ int x;
+ u_char read_bit;
+
+ *nvram_data = 0;
+ for (x = 0; x < 16; x++) {
+ Tnvram_Read_Bit(np, &read_bit, gpreg);
+
+ if (read_bit & 0x01)
+ *nvram_data |= (0x01 << (15 - x));
+ else
+ *nvram_data &= ~(0x01 << (15 - x));
+ }
+}
+
+/*
+ * Read bit from NVRAM
+ */
+__initfunc(
+static void Tnvram_Read_Bit(ncr_slot *np, u_char *read_bit, u_char *gpreg)
+)
+{
+ UDELAY (2);
+ Tnvram_Clk(np, gpreg);
+ *read_bit = INB (nc_gpreg);
+}
+
+/*
+ * Write bit to GPIO0
+ */
+__initfunc(
+static void Tnvram_Write_Bit(ncr_slot *np, u_char write_bit, u_char *gpreg)
+)
+{
+ if (write_bit & 0x01)
+ *gpreg |= 0x02;
+ else
+ *gpreg &= 0xfd;
+
+ *gpreg |= 0x10;
+
+ OUTB (nc_gpreg, *gpreg);
+ UDELAY (2);
+
+ Tnvram_Clk(np, gpreg);
+}
+
+/*
+ * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZZzzz!!
+ */
+__initfunc(
+static void Tnvram_Stop(ncr_slot *np, u_char *gpreg)
+)
+{
+ *gpreg &= 0xef;
+ OUTB (nc_gpreg, *gpreg);
+ UDELAY (2);
+
+ Tnvram_Clk(np, gpreg);
+}
+
+/*
+ * Pulse clock bit in GPIO0
+ */
+__initfunc(
+static void Tnvram_Clk(ncr_slot *np, u_char *gpreg)
+)
+{
+ OUTB (nc_gpreg, *gpreg | 0x04);
+ UDELAY (2);
+ OUTB (nc_gpreg, *gpreg);
+}
+
+#endif /* SCSI_NCR_NVRAM_SUPPORT */
+
+/*
+** Module stuff
+*/
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = SYM53C8XX;
+#include "scsi_module.c"
+#endif
diff --git a/drivers/scsi/sym53c8xx.h b/drivers/scsi/sym53c8xx.h
new file mode 100644
index 000000000..5bdd608e9
--- /dev/null
+++ b/drivers/scsi/sym53c8xx.h
@@ -0,0 +1,116 @@
+/******************************************************************************
+** High Performance device driver for the Symbios 53C896 controller.
+**
+** Copyright (C) 1998 Gerard Roudier <groudier@club-internet.fr>
+**
+** This driver also supports all the Symbios 53C8XX controller family,
+** except 53C810 revisions < 16, 53C825 revisions < 16 and all
+** revisions of 53C815 controllers.
+**
+** This driver is based on the Linux port of the FreeBSD ncr driver.
+**
+** Copyright (C) 1994 Wolfgang Stanglmeier
+**
+**-----------------------------------------------------------------------------
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**-----------------------------------------------------------------------------
+**
+** The Linux port of the FreeBSD ncr driver has been achieved in
+** november 1995 by:
+**
+** Gerard Roudier <groudier@club-internet.fr>
+**
+** Being given that this driver originates from the FreeBSD version, and
+** in order to keep synergy on both, any suggested enhancements and corrections
+** received on Linux are automatically a potential candidate for the FreeBSD
+** version.
+**
+** The original driver has been written for 386bsd and FreeBSD by
+** Wolfgang Stanglmeier <wolf@cologne.de>
+** Stefan Esser <se@mi.Uni-Koeln.de>
+**
+**-----------------------------------------------------------------------------
+**
+** Major contributions:
+** --------------------
+**
+** NVRAM detection and reading.
+** Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
+**
+*******************************************************************************
+*/
+
+#ifndef SYM53C8XX_H
+#define SYM53C8XX_H
+
+#include "sym53c8xx_defs.h"
+
+/*
+** Define Scsi_Host_Template parameters
+**
+** Used by hosts.c and sym53c8xx.c with module configuration.
+*/
+
+#if defined(HOSTS_C) || defined(MODULE)
+
+#include <scsi/scsicam.h>
+
+int sym53c8xx_abort(Scsi_Cmnd *);
+int sym53c8xx_detect(Scsi_Host_Template *tpnt);
+const char *sym53c8xx_info(struct Scsi_Host *host);
+int sym53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int sym53c8xx_reset(Scsi_Cmnd *, unsigned int);
+
+#ifdef MODULE
+int sym53c8xx_release(struct Scsi_Host *);
+#else
+#define sym53c8xx_release NULL
+#endif
+
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75)
+
+#define SYM53C8XX { name: "", \
+ detect: sym53c8xx_detect, \
+ release: sym53c8xx_release, \
+ info: sym53c8xx_info, \
+ queuecommand: sym53c8xx_queue_command,\
+ abort: sym53c8xx_abort, \
+ reset: sym53c8xx_reset, \
+ bios_param: scsicam_bios_param, \
+ can_queue: SCSI_NCR_CAN_QUEUE, \
+ this_id: 7, \
+ sg_tablesize: SCSI_NCR_SG_TABLESIZE, \
+ cmd_per_lun: SCSI_NCR_CMD_PER_LUN, \
+ use_clustering: DISABLE_CLUSTERING}
+
+#else
+
+#define SYM53C8XX { NULL, NULL, NULL, NULL, \
+ NULL, sym53c8xx_detect, \
+ sym53c8xx_release, sym53c8xx_info, NULL, \
+ sym53c8xx_queue_command,sym53c8xx_abort, \
+ sym53c8xx_reset, NULL, scsicam_bios_param, \
+ SCSI_NCR_CAN_QUEUE, 7, \
+ SCSI_NCR_SG_TABLESIZE, SCSI_NCR_CMD_PER_LUN, \
+ 0, 0, DISABLE_CLUSTERING}
+
+#endif /* LINUX_VERSION_CODE */
+
+#endif /* defined(HOSTS_C) || defined(MODULE) */
+
+#endif /* SYM53C8XX_H */
diff --git a/drivers/scsi/sym53c8xx_defs.h b/drivers/scsi/sym53c8xx_defs.h
new file mode 100644
index 000000000..3b30e1bb5
--- /dev/null
+++ b/drivers/scsi/sym53c8xx_defs.h
@@ -0,0 +1,1195 @@
+/******************************************************************************
+** High Performance device driver for the Symbios 53C896 controller.
+**
+** Copyright (C) 1998 Gerard Roudier <groudier@club-internet.fr>
+**
+** This driver also supports all the Symbios 53C8XX controller family,
+** except 53C810 revisions < 16, 53C825 revisions < 16 and all
+** revisions of 53C815 controllers.
+**
+** This driver is based on the Linux port of the FreeBSD ncr driver.
+**
+** Copyright (C) 1994 Wolfgang Stanglmeier
+**
+**-----------------------------------------------------------------------------
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**-----------------------------------------------------------------------------
+**
+** The Linux port of the FreeBSD ncr driver has been achieved in
+** november 1995 by:
+**
+** Gerard Roudier <groudier@club-internet.fr>
+**
+** Being given that this driver originates from the FreeBSD version, and
+** in order to keep synergy on both, any suggested enhancements and corrections
+** received on Linux are automatically a potential candidate for the FreeBSD
+** version.
+**
+** The original driver has been written for 386bsd and FreeBSD by
+** Wolfgang Stanglmeier <wolf@cologne.de>
+** Stefan Esser <se@mi.Uni-Koeln.de>
+**
+**-----------------------------------------------------------------------------
+**
+** Major contributions:
+** --------------------
+**
+** NVRAM detection and reading.
+** Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
+**
+*******************************************************************************
+*/
+
+#ifndef SYM53C8XX_DEFS_H
+#define SYM53C8XX_DEFS_H
+
+/*
+** Check supported Linux versions
+*/
+
+#if !defined(LINUX_VERSION_CODE)
+#include <linux/version.h>
+#endif
+#include <linux/config.h>
+
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+/*
+ * NCR PQS/PDS special device support.
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_PQS_PDS
+#define SCSI_NCR_PQS_PDS_SUPPORT
+#endif
+
+/*
+ * No more an option, enabled by default.
+ */
+#ifndef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
+#define CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
+#endif
+
+/*
+** These options are not tunable from 'make config'
+*/
+#define SCSI_NCR_PROC_INFO_SUPPORT
+
+/*
+** If you want a driver as small as possible, donnot define the
+** following options.
+*/
+#define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
+#define SCSI_NCR_DEBUG_INFO_SUPPORT
+#define SCSI_NCR_PCI_FIX_UP_SUPPORT
+#ifdef SCSI_NCR_PROC_INFO_SUPPORT
+# ifdef CONFIG_SCSI_NCR53C8XX_PROFILE
+# define SCSI_NCR_PROFILE_SUPPORT
+# endif
+# define SCSI_NCR_USER_COMMAND_SUPPORT
+# define SCSI_NCR_USER_INFO_SUPPORT
+#endif
+
+/*==========================================================
+**
+** nvram settings - #define SCSI_NCR_NVRAM_SUPPORT to enable
+**
+**==========================================================
+*/
+
+#ifdef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
+#define SCSI_NCR_NVRAM_SUPPORT
+/* #define SCSI_NCR_DEBUG_NVRAM */
+#endif
+
+/* ---------------------------------------------------------------------
+** Take into account kernel configured parameters.
+** Most of these options can be overridden at startup by a command line.
+** ---------------------------------------------------------------------
+*/
+
+/*
+ * For Ultra2 SCSI support option, use special features and allow 40Mhz
+ * synchronous data transfers.
+ *
+ * Value 5 (default) means:
+ * bit 0 : all features enabled, except:
+ * bit 1 : PCI Write And Invalidate.
+ * bit 2 : Data Phase Mismatch handling from SCRIPTS.
+ *
+ * Use boot options ncr53c8xx=specf:1 if you want all chip features to be
+ * enabled by the driver.
+ */
+#define SCSI_NCR_SETUP_SPECIAL_FEATURES (3)
+#define SCSI_NCR_SETUP_ULTRA_SCSI (2)
+#define SCSI_NCR_MAX_SYNC (40)
+
+/*
+ * Allow tags from 2 to 64, default 8
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_MAX_TAGS
+#if CONFIG_SCSI_NCR53C8XX_MAX_TAGS < 2
+#define SCSI_NCR_MAX_TAGS (2)
+#elif CONFIG_SCSI_NCR53C8XX_MAX_TAGS > 64
+#define SCSI_NCR_MAX_TAGS (64)
+#else
+#define SCSI_NCR_MAX_TAGS CONFIG_SCSI_NCR53C8XX_MAX_TAGS
+#endif
+#else
+#define SCSI_NCR_MAX_TAGS (8)
+#endif
+
+/*
+ * Allow tagged command queuing support if configured with default number
+ * of tags set to max (see above).
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
+#define SCSI_NCR_SETUP_DEFAULT_TAGS CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
+#elif defined CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE
+#define SCSI_NCR_SETUP_DEFAULT_TAGS SCSI_NCR_MAX_TAGS
+#else
+#define SCSI_NCR_SETUP_DEFAULT_TAGS (0)
+#endif
+
+/*
+ * Use normal IO if configured. Forced for alpha and ppc.
+ */
+#if defined(CONFIG_SCSI_NCR53C8XX_IOMAPPED)
+#define SCSI_NCR_IOMAPPED
+#elif defined(__alpha__) || defined(__powerpc__)
+#define SCSI_NCR_IOMAPPED
+#elif defined(__sparc__)
+#undef SCSI_NCR_IOMAPPED
+#endif
+
+/*
+ * Sync transfer frequency at startup.
+ * Allow from 5Mhz to 40Mhz default 20 Mhz.
+ */
+#ifndef CONFIG_SCSI_NCR53C8XX_SYNC
+#define CONFIG_SCSI_NCR53C8XX_SYNC (20)
+#elif CONFIG_SCSI_NCR53C8XX_SYNC > SCSI_NCR_MAX_SYNC
+#undef CONFIG_SCSI_NCR53C8XX_SYNC
+#define CONFIG_SCSI_NCR53C8XX_SYNC SCSI_NCR_MAX_SYNC
+#endif
+
+#if CONFIG_SCSI_NCR53C8XX_SYNC == 0
+#define SCSI_NCR_SETUP_DEFAULT_SYNC (255)
+#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 5
+#define SCSI_NCR_SETUP_DEFAULT_SYNC (50)
+#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 20
+#define SCSI_NCR_SETUP_DEFAULT_SYNC (250/(CONFIG_SCSI_NCR53C8XX_SYNC))
+#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 33
+#define SCSI_NCR_SETUP_DEFAULT_SYNC (11)
+#else
+#define SCSI_NCR_SETUP_DEFAULT_SYNC (10)
+#endif
+
+/*
+ * Disallow disconnections at boot-up
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
+#define SCSI_NCR_SETUP_DISCONNECTION (0)
+#else
+#define SCSI_NCR_SETUP_DISCONNECTION (1)
+#endif
+
+/*
+ * Force synchronous negotiation for all targets
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO
+#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO (1)
+#else
+#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO (0)
+#endif
+
+/*
+ * Disable master parity checking (flawed hardwares need that)
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_MPARITY_CHECK
+#define SCSI_NCR_SETUP_MASTER_PARITY (0)
+#else
+#define SCSI_NCR_SETUP_MASTER_PARITY (1)
+#endif
+
+/*
+ * Disable scsi parity checking (flawed devices may need that)
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_PARITY_CHECK
+#define SCSI_NCR_SETUP_SCSI_PARITY (0)
+#else
+#define SCSI_NCR_SETUP_SCSI_PARITY (1)
+#endif
+
+/*
+ * Vendor specific stuff
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
+#define SCSI_NCR_SETUP_LED_PIN (1)
+#define SCSI_NCR_SETUP_DIFF_SUPPORT (3)
+#else
+#define SCSI_NCR_SETUP_LED_PIN (0)
+#define SCSI_NCR_SETUP_DIFF_SUPPORT (0)
+#endif
+
+/*
+ * Settle time after reset at boot-up
+ */
+#define SCSI_NCR_SETUP_SETTLE_TIME (2)
+
+/*
+** Other parameters not configurable with "make config"
+** Avoid to change these constants, unless you know what you are doing.
+*/
+
+#define SCSI_NCR_ALWAYS_SIMPLE_TAG
+#define SCSI_NCR_MAX_SCATTER (127)
+#define SCSI_NCR_MAX_TARGET (16)
+
+/* No need to use a too large adapter queue */
+#if SCSI_NCR_MAX_TAGS <= 32
+#define SCSI_NCR_CAN_QUEUE (7*SCSI_NCR_MAX_TAGS)
+#else
+#define SCSI_NCR_CAN_QUEUE (250)
+#endif
+
+#define SCSI_NCR_CMD_PER_LUN (SCSI_NCR_MAX_TAGS)
+#define SCSI_NCR_SG_TABLESIZE (SCSI_NCR_MAX_SCATTER)
+
+#define SCSI_NCR_TIMER_INTERVAL (HZ)
+
+#if 1 /* defined CONFIG_SCSI_MULTI_LUN */
+#define SCSI_NCR_MAX_LUN (8)
+#else
+#define SCSI_NCR_MAX_LUN (1)
+#endif
+
+#ifndef HOSTS_C
+
+/*
+** IO functions definition for big/little endian support.
+** For now, the NCR is only supported in little endian addressing mode,
+** and big endian byte ordering is only supported for the PPC.
+** MMIO is not used on PPC.
+*/
+
+#ifdef __BIG_ENDIAN
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0)
+#error "BIG ENDIAN byte ordering needs kernel version >= 2.1.0"
+#endif
+
+#if defined(__powerpc__)
+#define inw_l2b inw
+#define inl_l2b inl
+#define outw_b2l outw
+#define outl_b2l outl
+#elif defined(__sparc__)
+#define readw_l2b readw
+#define readl_l2b readl
+#define writew_b2l writew
+#define writel_b2l writel
+#else
+#error "Support for BIG ENDIAN is only available for PowerPC and SPARC"
+#endif
+
+#else /* little endian */
+
+#if defined(__i386__) /* i386 implements full FLAT memory/MMIO model */
+#define inw_raw inw
+#define inl_raw inl
+#define outw_raw outw
+#define outl_raw outl
+#define readb_raw(a) (*(volatile unsigned char *) (a))
+#define readw_raw(a) (*(volatile unsigned short *) (a))
+#define readl_raw(a) (*(volatile unsigned int *) (a))
+#define writeb_raw(b,a) ((*(volatile unsigned char *) (a)) = (b))
+#define writew_raw(b,a) ((*(volatile unsigned short *) (a)) = (b))
+#define writel_raw(b,a) ((*(volatile unsigned int *) (a)) = (b))
+
+#else /* Other little-endian (for now alpha) */
+#define inw_raw inw
+#define inl_raw inl
+#define outw_raw outw
+#define outl_raw outl
+#define readw_raw readw
+#define readl_raw readl
+#define writew_raw writew
+#define writel_raw writel
+
+#endif
+#endif
+
+#ifdef SCSI_NCR_BIG_ENDIAN
+#error "The NCR in BIG ENDIAN addressing mode is not (yet) supported"
+#endif
+
+/*
+** NCR53C8XX Device Ids
+*/
+
+#ifndef PCI_DEVICE_ID_NCR_53C810
+#define PCI_DEVICE_ID_NCR_53C810 1
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C810AP
+#define PCI_DEVICE_ID_NCR_53C810AP 5
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C815
+#define PCI_DEVICE_ID_NCR_53C815 4
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C820
+#define PCI_DEVICE_ID_NCR_53C820 2
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C825
+#define PCI_DEVICE_ID_NCR_53C825 3
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C860
+#define PCI_DEVICE_ID_NCR_53C860 6
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C875
+#define PCI_DEVICE_ID_NCR_53C875 0xf
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C875J
+#define PCI_DEVICE_ID_NCR_53C875J 0x8f
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C885
+#define PCI_DEVICE_ID_NCR_53C885 0xd
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C895
+#define PCI_DEVICE_ID_NCR_53C895 0xc
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C896
+#define PCI_DEVICE_ID_NCR_53C896 0xb
+#endif
+
+/*
+** NCR53C8XX devices features table.
+*/
+typedef struct {
+ unsigned short device_id;
+ unsigned short revision_id;
+ char *name;
+ unsigned char burst_max;
+ unsigned char offset_max;
+ unsigned char nr_divisor;
+ unsigned int features;
+#define FE_LED0 (1<<0)
+#define FE_WIDE (1<<1)
+#define FE_ULTRA (1<<2)
+#define FE_ULTRA2 (1<<3)
+#define FE_DBLR (1<<4)
+#define FE_QUAD (1<<5)
+#define FE_ERL (1<<6)
+#define FE_CLSE (1<<7)
+#define FE_WRIE (1<<8)
+#define FE_ERMP (1<<9)
+#define FE_BOF (1<<10)
+#define FE_DFS (1<<11)
+#define FE_PFEN (1<<12)
+#define FE_LDSTR (1<<13)
+#define FE_RAM (1<<14)
+#define FE_CLK80 (1<<15)
+#define FE_RAM8K (1<<16)
+#define FE_64BIT (1<<17)
+#define FE_IO256 (1<<18)
+#define FE_NOPM (1<<19)
+#define FE_LEDC (1<<20)
+#define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP)
+#define FE_SCSI_SET (FE_WIDE|FE_ULTRA|FE_ULTRA2|FE_DBLR|FE_QUAD|F_CLK80)
+#define FE_SPECIAL_SET (FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM)
+} ncr_chip;
+
+/*
+** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 3.
+** Memory Read transaction terminated by a retry followed by
+** Memory Read Line command.
+*/
+#define FE_CACHE0_SET (FE_CACHE_SET & ~FE_ERL)
+
+/*
+** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 5.
+** On paper, this errata is harmless. But it is a good reason for
+** using a shorter programmed burst length (64 DWORDS instead of 128).
+*/
+
+#define SCSI_NCR_CHIP_TABLE \
+{ \
+ {PCI_DEVICE_ID_NCR_53C810, 0x0f, "810", 4, 8, 4, \
+ FE_ERL} \
+ , \
+ {PCI_DEVICE_ID_NCR_53C810, 0xff, "810a", 4, 8, 4, \
+ FE_CACHE_SET|FE_LDSTR|FE_PFEN|FE_BOF} \
+ , \
+ {PCI_DEVICE_ID_NCR_53C815, 0xff, "815", 4, 8, 4, \
+ FE_ERL|FE_BOF} \
+ , \
+ {PCI_DEVICE_ID_NCR_53C820, 0xff, "820", 4, 8, 4, \
+ FE_WIDE|FE_ERL} \
+ , \
+ {PCI_DEVICE_ID_NCR_53C825, 0x0f, "825", 4, 8, 4, \
+ FE_WIDE|FE_ERL|FE_BOF} \
+ , \
+ {PCI_DEVICE_ID_NCR_53C825, 0xff, "825a", 6, 8, 4, \
+ FE_WIDE|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} \
+ , \
+ {PCI_DEVICE_ID_NCR_53C860, 0xff, "860", 4, 8, 5, \
+ FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_BOF|FE_LDSTR|FE_PFEN} \
+ , \
+ {PCI_DEVICE_ID_NCR_53C875, 0x01, "875", 6, 16, 5, \
+ FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
+ , \
+ {PCI_DEVICE_ID_NCR_53C875, 0x0f, "875", 6, 16, 5, \
+ FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
+ , \
+ {PCI_DEVICE_ID_NCR_53C875, 0xff, "876", 6, 16, 5, \
+ FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
+ , \
+ {PCI_DEVICE_ID_NCR_53C875J,0xff, "875J", 6, 16, 5, \
+ FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
+ , \
+ {PCI_DEVICE_ID_NCR_53C885, 0xff, "885", 6, 16, 5, \
+ FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
+ , \
+ {PCI_DEVICE_ID_NCR_53C895, 0xff, "895", 6, 31, 7, \
+ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
+ , \
+ {PCI_DEVICE_ID_NCR_53C896, 0xff, "896", 7, 31, 7, \
+ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|\
+ FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM|FE_LEDC}\
+}
+
+/*
+ * List of supported NCR chip ids
+ */
+#define SCSI_NCR_CHIP_IDS \
+{ \
+ PCI_DEVICE_ID_NCR_53C810, \
+ PCI_DEVICE_ID_NCR_53C815, \
+ PCI_DEVICE_ID_NCR_53C820, \
+ PCI_DEVICE_ID_NCR_53C825, \
+ PCI_DEVICE_ID_NCR_53C860, \
+ PCI_DEVICE_ID_NCR_53C875, \
+ PCI_DEVICE_ID_NCR_53C875J, \
+ PCI_DEVICE_ID_NCR_53C885, \
+ PCI_DEVICE_ID_NCR_53C895, \
+ PCI_DEVICE_ID_NCR_53C896 \
+}
+
+/*
+** Initial setup.
+** Can be overriden at startup by a command line.
+*/
+#define SCSI_NCR_DRIVER_SETUP \
+{ \
+ SCSI_NCR_SETUP_MASTER_PARITY, \
+ SCSI_NCR_SETUP_SCSI_PARITY, \
+ SCSI_NCR_SETUP_DISCONNECTION, \
+ SCSI_NCR_SETUP_SPECIAL_FEATURES, \
+ SCSI_NCR_SETUP_ULTRA_SCSI, \
+ SCSI_NCR_SETUP_FORCE_SYNC_NEGO, \
+ 0, \
+ 0, \
+ 1, \
+ 1, \
+ SCSI_NCR_SETUP_DEFAULT_TAGS, \
+ SCSI_NCR_SETUP_DEFAULT_SYNC, \
+ 0x00, \
+ 7, \
+ SCSI_NCR_SETUP_LED_PIN, \
+ 1, \
+ SCSI_NCR_SETUP_SETTLE_TIME, \
+ SCSI_NCR_SETUP_DIFF_SUPPORT, \
+ 0, \
+ 1, \
+ 0, \
+ 0 \
+}
+
+/*
+** Boot fail safe setup.
+** Override initial setup from boot command line:
+** ncr53c8xx=safe:y
+*/
+#define SCSI_NCR_DRIVER_SAFE_SETUP \
+{ \
+ 0, \
+ 1, \
+ 0, \
+ 0, \
+ 0, \
+ 0, \
+ 0, \
+ 0, \
+ 1, \
+ 2, \
+ 0, \
+ 255, \
+ 0x00, \
+ 255, \
+ 0, \
+ 0, \
+ 10, \
+ 1, \
+ 1, \
+ 1, \
+ 0, \
+ 0 \
+}
+
+/**************** ORIGINAL CONTENT of ncrreg.h from FreeBSD ******************/
+
+/*-----------------------------------------------------------------
+**
+** The ncr 53c810 register structure.
+**
+**-----------------------------------------------------------------
+*/
+
+struct ncr_reg {
+/*00*/ u_char nc_scntl0; /* full arb., ena parity, par->ATN */
+
+/*01*/ u_char nc_scntl1; /* no reset */
+ #define ISCON 0x10 /* connected to scsi */
+ #define CRST 0x08 /* force reset */
+
+/*02*/ u_char nc_scntl2; /* no disconnect expected */
+ #define SDU 0x80 /* cmd: disconnect will raise error */
+ #define CHM 0x40 /* sta: chained mode */
+ #define WSS 0x08 /* sta: wide scsi send [W]*/
+ #define WSR 0x01 /* sta: wide scsi received [W]*/
+
+/*03*/ u_char nc_scntl3; /* cnf system clock dependent */
+ #define EWS 0x08 /* cmd: enable wide scsi [W]*/
+ #define ULTRA 0x80 /* cmd: ULTRA enable */
+
+/*04*/ u_char nc_scid; /* cnf host adapter scsi address */
+ #define RRE 0x40 /* r/w:e enable response to resel. */
+ #define SRE 0x20 /* r/w:e enable response to select */
+
+/*05*/ u_char nc_sxfer; /* ### Sync speed and count */
+
+/*06*/ u_char nc_sdid; /* ### Destination-ID */
+
+/*07*/ u_char nc_gpreg; /* ??? IO-Pins */
+
+/*08*/ u_char nc_sfbr; /* ### First byte in phase */
+
+/*09*/ u_char nc_socl;
+ #define CREQ 0x80 /* r/w: SCSI-REQ */
+ #define CACK 0x40 /* r/w: SCSI-ACK */
+ #define CBSY 0x20 /* r/w: SCSI-BSY */
+ #define CSEL 0x10 /* r/w: SCSI-SEL */
+ #define CATN 0x08 /* r/w: SCSI-ATN */
+ #define CMSG 0x04 /* r/w: SCSI-MSG */
+ #define CC_D 0x02 /* r/w: SCSI-C_D */
+ #define CI_O 0x01 /* r/w: SCSI-I_O */
+
+/*0a*/ u_char nc_ssid;
+
+/*0b*/ u_char nc_sbcl;
+
+/*0c*/ u_char nc_dstat;
+ #define DFE 0x80 /* sta: dma fifo empty */
+ #define MDPE 0x40 /* int: master data parity error */
+ #define BF 0x20 /* int: script: bus fault */
+ #define ABRT 0x10 /* int: script: command aborted */
+ #define SSI 0x08 /* int: script: single step */
+ #define SIR 0x04 /* int: script: interrupt instruct. */
+ #define IID 0x01 /* int: script: illegal instruct. */
+
+/*0d*/ u_char nc_sstat0;
+ #define ILF 0x80 /* sta: data in SIDL register lsb */
+ #define ORF 0x40 /* sta: data in SODR register lsb */
+ #define OLF 0x20 /* sta: data in SODL register lsb */
+ #define AIP 0x10 /* sta: arbitration in progress */
+ #define LOA 0x08 /* sta: arbitration lost */
+ #define WOA 0x04 /* sta: arbitration won */
+ #define IRST 0x02 /* sta: scsi reset signal */
+ #define SDP 0x01 /* sta: scsi parity signal */
+
+/*0e*/ u_char nc_sstat1;
+ #define FF3210 0xf0 /* sta: bytes in the scsi fifo */
+
+/*0f*/ u_char nc_sstat2;
+ #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/
+ #define ORF1 0x40 /* sta: data in SODR register msb[W]*/
+ #define OLF1 0x20 /* sta: data in SODL register msb[W]*/
+ #define DM 0x04 /* sta: DIFFSENS mismatch (895/6 only) */
+ #define LDSC 0x02 /* sta: disconnect & reconnect */
+
+/*10*/ u_int32 nc_dsa; /* --> Base page */
+
+/*14*/ u_char nc_istat; /* --> Main Command and status */
+ #define CABRT 0x80 /* cmd: abort current operation */
+ #define SRST 0x40 /* mod: reset chip */
+ #define SIGP 0x20 /* r/w: message from host to ncr */
+ #define SEM 0x10 /* r/w: message between host + ncr */
+ #define CON 0x08 /* sta: connected to scsi */
+ #define INTF 0x04 /* sta: int on the fly (reset by wr)*/
+ #define SIP 0x02 /* sta: scsi-interrupt */
+ #define DIP 0x01 /* sta: host/script interrupt */
+
+/*15*/ u_char nc_istat1; /* 896 only */
+/*16*/ u_char nc_mbox0; /* 896 only */
+/*17*/ u_char nc_mbox1; /* 896 only */
+
+/*18*/ u_char nc_ctest0;
+/*19*/ u_char nc_ctest1;
+
+/*1a*/ u_char nc_ctest2;
+ #define CSIGP 0x40
+
+/*1b*/ u_char nc_ctest3;
+ #define FLF 0x08 /* cmd: flush dma fifo */
+ #define CLF 0x04 /* cmd: clear dma fifo */
+ #define FM 0x02 /* mod: fetch pin mode */
+ #define WRIE 0x01 /* mod: write and invalidate enable */
+
+/*1c*/ u_int32 nc_temp; /* ### Temporary stack */
+
+/*20*/ u_char nc_dfifo;
+/*21*/ u_char nc_ctest4;
+ #define BDIS 0x80 /* mod: burst disable */
+ #define MPEE 0x08 /* mod: master parity error enable */
+
+/*22*/ u_char nc_ctest5;
+ #define DFS 0x20 /* mod: dma fifo size */
+/*23*/ u_char nc_ctest6;
+
+/*24*/ u_int32 nc_dbc; /* ### Byte count and command */
+/*28*/ u_int32 nc_dnad; /* ### Next command register */
+/*2c*/ u_int32 nc_dsp; /* --> Script Pointer */
+/*30*/ u_int32 nc_dsps; /* --> Script pointer save/opcode#2 */
+
+/*34*/ u_char nc_scratcha; /* Temporary register a */
+/*35*/ u_char nc_scratcha1;
+/*36*/ u_char nc_scratcha2;
+/*37*/ u_char nc_scratcha3;
+
+/*38*/ u_char nc_dmode;
+ #define BL_2 0x80 /* mod: burst length shift value +2 */
+ #define BL_1 0x40 /* mod: burst length shift value +1 */
+ #define ERL 0x08 /* mod: enable read line */
+ #define ERMP 0x04 /* mod: enable read multiple */
+ #define BOF 0x02 /* mod: burst op code fetch */
+
+/*39*/ u_char nc_dien;
+/*3a*/ u_char nc_dwt;
+
+/*3b*/ u_char nc_dcntl; /* --> Script execution control */
+ #define CLSE 0x80 /* mod: cache line size enable */
+ #define PFF 0x40 /* cmd: pre-fetch flush */
+ #define PFEN 0x20 /* mod: pre-fetch enable */
+ #define SSM 0x10 /* mod: single step mode */
+ #define IRQM 0x08 /* mod: irq mode (1 = totem pole !) */
+ #define STD 0x04 /* cmd: start dma mode */
+ #define IRQD 0x02 /* mod: irq disable */
+ #define NOCOM 0x01 /* cmd: protect sfbr while reselect */
+
+/*3c*/ u_int32 nc_adder;
+
+/*40*/ u_short nc_sien; /* -->: interrupt enable */
+/*42*/ u_short nc_sist; /* <--: interrupt status */
+ #define SBMC 0x1000/* sta: SCSI Bus Mode Change (895/6 only) */
+ #define STO 0x0400/* sta: timeout (select) */
+ #define GEN 0x0200/* sta: timeout (general) */
+ #define HTH 0x0100/* sta: timeout (handshake) */
+ #define MA 0x80 /* sta: phase mismatch */
+ #define CMP 0x40 /* sta: arbitration complete */
+ #define SEL 0x20 /* sta: selected by another device */
+ #define RSL 0x10 /* sta: reselected by another device*/
+ #define SGE 0x08 /* sta: gross error (over/underflow)*/
+ #define UDC 0x04 /* sta: unexpected disconnect */
+ #define RST 0x02 /* sta: scsi bus reset detected */
+ #define PAR 0x01 /* sta: scsi parity error */
+
+/*44*/ u_char nc_slpar;
+/*45*/ u_char nc_swide;
+/*46*/ u_char nc_macntl;
+/*47*/ u_char nc_gpcntl;
+/*48*/ u_char nc_stime0; /* cmd: timeout for select&handshake*/
+/*49*/ u_char nc_stime1; /* cmd: timeout user defined */
+/*4a*/ u_short nc_respid; /* sta: Reselect-IDs */
+
+/*4c*/ u_char nc_stest0;
+
+/*4d*/ u_char nc_stest1;
+ #define DBLEN 0x08 /* clock doubler running */
+ #define DBLSEL 0x04 /* clock doubler selected */
+
+
+/*4e*/ u_char nc_stest2;
+ #define ROF 0x40 /* reset scsi offset (after gross error!) */
+ #define EXT 0x02 /* extended filtering */
+
+/*4f*/ u_char nc_stest3;
+ #define TE 0x80 /* c: tolerAnt enable */
+ #define HSC 0x20 /* c: Halt SCSI Clock */
+ #define CSF 0x02 /* c: clear scsi fifo */
+
+/*50*/ u_short nc_sidl; /* Lowlevel: latched from scsi data */
+/*52*/ u_char nc_stest4;
+ #define SMODE 0xc0 /* SCSI bus mode (895/6 only) */
+ #define SMODE_HVD 0x40 /* High Voltage Differential */
+ #define SMODE_SE 0x80 /* Single Ended */
+ #define SMODE_LVD 0xc0 /* Low Voltage Differential */
+ #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */
+
+/*53*/ u_char nc_53_;
+/*54*/ u_short nc_sodl; /* Lowlevel: data out to scsi data */
+/*56*/ u_char nc_ccntl0; /* Chip Control 0 (896) */
+ #define ENPMJ 0x80 /* Enable Phase Mismatch Jump */
+ #define PMJCTL 0x40 /* Phase Mismatch Jump Control */
+ #define ENNDJ 0x20 /* Enable Non Data PM Jump */
+ #define DISFC 0x10 /* Disable Auto FIFO Clear */
+ #define DILS 0x02 /* Disable Internal Load/Store */
+ #define DPR 0x01 /* Disable Pipe Req */
+
+/*57*/ u_char nc_ccntl1; /* Chip Control 1 (896) */
+ #define ZMOD 0x80 /* High Impedance Mode */
+ #define DDAC 0x08 /* Disable Dual Address Cycle */
+ #define XTIMOD 0x04 /* 64-bit Table Ind. Indexing Mode */
+ #define EXTIBMV 0x02 /* Enable 64-bit Table Ind. BMOV */
+ #define EXDBMV 0x01 /* Enable 64-bit Direct BMOV */
+
+/*58*/ u_short nc_sbdl; /* Lowlevel: data from scsi data */
+/*5a*/ u_short nc_5a_;
+
+/*5c*/ u_char nc_scr0; /* Working register B */
+/*5d*/ u_char nc_scr1; /* */
+/*5e*/ u_char nc_scr2; /* */
+/*5f*/ u_char nc_scr3; /* */
+
+/*60*/ u_char nc_scrx[64]; /* Working register C-R */
+/*a0*/ u_int32 nc_mmrs; /* Memory Move Read Selector */
+/*a4*/ u_int32 nc_mmws; /* Memory Move Write Selector */
+/*a8*/ u_int32 nc_sfs; /* Script Fetch Selector */
+/*ac*/ u_int32 nc_drs; /* DSA Relative Selector */
+/*b0*/ u_int32 nc_sbms; /* Static Block Move Selector */
+/*b4*/ u_int32 nc_dbms; /* Dynamic Block Move Selector */
+/*b8*/ u_int32 nc_dnad64; /* DMA Next Address 64 */
+/*bc*/ u_int32 nc_bc_;
+
+/*c0*/ u_int32 nc_pmjad1; /* Phase Mismatch Jump Address 1 */
+/*c4*/ u_int32 nc_pmjad2; /* Phase Mismatch Jump Address 2 */
+/*c8*/ u_int32 nc_rbc; /* Remaining Byte Count */
+/*cc*/ u_int32 nc_ua; /* Updated Address */
+/*d0*/ u_int32 nc_esa; /* Entry Storage Address */
+/*d4*/ u_char nc_ia; /* Instruction Address */
+/*d5*/ u_char nc_ia1;
+/*d6*/ u_char nc_ia2;
+/*d7*/ u_char nc_ia3;
+/*d8*/ u_int32 nc_sbc; /* SCSI Byte Count (3 bytes only) */
+/*dc*/ u_int32 nc_csbc; /* Cumulative SCSI Byte Count */
+};
+
+/*-----------------------------------------------------------
+**
+** Utility macros for the script.
+**
+**-----------------------------------------------------------
+*/
+
+#define REGJ(p,r) (offsetof(struct ncr_reg, p ## r))
+#define REG(r) REGJ (nc_, r)
+
+#ifndef TARGET_MODE
+#define TARGET_MODE 0
+#endif
+
+typedef u_int32 ncrcmd;
+
+/*-----------------------------------------------------------
+**
+** SCSI phases
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_DATA_OUT 0x00000000
+#define SCR_DATA_IN 0x01000000
+#define SCR_COMMAND 0x02000000
+#define SCR_STATUS 0x03000000
+#define SCR_ILG_OUT 0x04000000
+#define SCR_ILG_IN 0x05000000
+#define SCR_MSG_OUT 0x06000000
+#define SCR_MSG_IN 0x07000000
+
+/*-----------------------------------------------------------
+**
+** Data transfer via SCSI.
+**
+**-----------------------------------------------------------
+**
+** MOVE_ABS (LEN)
+** <<start address>>
+**
+** MOVE_IND (LEN)
+** <<dnad_offset>>
+**
+** MOVE_TBL
+** <<dnad_offset>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_MOVE_ABS(l) ((0x08000000 ^ (TARGET_MODE << 1ul)) | (l))
+#define SCR_MOVE_IND(l) ((0x28000000 ^ (TARGET_MODE << 1ul)) | (l))
+#define SCR_MOVE_TBL (0x18000000 ^ (TARGET_MODE << 1ul))
+
+struct scr_tblmove {
+ u_int32 size;
+ u_int32 addr;
+};
+
+/*-----------------------------------------------------------
+**
+** Selection
+**
+**-----------------------------------------------------------
+**
+** SEL_ABS | SCR_ID (0..7) [ | REL_JMP]
+** <<alternate_address>>
+**
+** SEL_TBL | << dnad_offset>> [ | REL_JMP]
+** <<alternate_address>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_SEL_ABS 0x40000000
+#define SCR_SEL_ABS_ATN 0x41000000
+#define SCR_SEL_TBL 0x42000000
+#define SCR_SEL_TBL_ATN 0x43000000
+
+struct scr_tblsel {
+ u_char sel_0;
+ u_char sel_sxfer;
+ u_char sel_id;
+ u_char sel_scntl3;
+};
+
+#define SCR_JMP_REL 0x04000000
+#define SCR_ID(id) (((u_int32)(id)) << 16)
+
+/*-----------------------------------------------------------
+**
+** Waiting for Disconnect or Reselect
+**
+**-----------------------------------------------------------
+**
+** WAIT_DISC
+** dummy: <<alternate_address>>
+**
+** WAIT_RESEL
+** <<alternate_address>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_WAIT_DISC 0x48000000
+#define SCR_WAIT_RESEL 0x50000000
+
+/*-----------------------------------------------------------
+**
+** Bit Set / Reset
+**
+**-----------------------------------------------------------
+**
+** SET (flags {|.. })
+**
+** CLR (flags {|.. })
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_SET(f) (0x58000000 | (f))
+#define SCR_CLR(f) (0x60000000 | (f))
+
+#define SCR_CARRY 0x00000400
+#define SCR_TRG 0x00000200
+#define SCR_ACK 0x00000040
+#define SCR_ATN 0x00000008
+
+
+
+
+/*-----------------------------------------------------------
+**
+** Memory to memory move
+**
+**-----------------------------------------------------------
+**
+** COPY (bytecount)
+** << source_address >>
+** << destination_address >>
+**
+** SCR_COPY sets the NO FLUSH option by default.
+** SCR_COPY_F does not set this option.
+**
+** For chips which do not support this option,
+** ncr_copy_and_bind() will remove this bit.
+**-----------------------------------------------------------
+*/
+
+#define SCR_NO_FLUSH 0x01000000
+
+#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n))
+#define SCR_COPY_F(n) (0xc0000000 | (n))
+
+/*-----------------------------------------------------------
+**
+** Register move and binary operations
+**
+**-----------------------------------------------------------
+**
+** SFBR_REG (reg, op, data) reg = SFBR op data
+** << 0 >>
+**
+** REG_SFBR (reg, op, data) SFBR = reg op data
+** << 0 >>
+**
+** REG_REG (reg, op, data) reg = reg op data
+** << 0 >>
+**
+**-----------------------------------------------------------
+** On 810A, 860, 825A, 875, 895 and 896 chips the content
+** of SFBR register can be used as data (SCR_SFBR_DATA).
+** The 896 has additionnal IO registers starting at
+** offset 0x80. Bit 7 of register offset is stored in
+** bit 7 of the SCRIPTS instruction first DWORD.
+**-----------------------------------------------------------
+*/
+
+#define SCR_REG_OFS(ofs) ((((ofs) & 0x7f) << 16ul) + ((ofs) & 0x80))
+
+#define SCR_SFBR_REG(reg,op,data) \
+ (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_SFBR(reg,op,data) \
+ (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_REG(reg,op,data) \
+ (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+
+#define SCR_LOAD 0x00000000
+#define SCR_SHL 0x01000000
+#define SCR_OR 0x02000000
+#define SCR_XOR 0x03000000
+#define SCR_AND 0x04000000
+#define SCR_SHR 0x05000000
+#define SCR_ADD 0x06000000
+#define SCR_ADDC 0x07000000
+
+#define SCR_SFBR_DATA (0x00800000>>8ul) /* Use SFBR as data */
+
+/*-----------------------------------------------------------
+**
+** FROM_REG (reg) SFBR = reg
+** << 0 >>
+**
+** TO_REG (reg) reg = SFBR
+** << 0 >>
+**
+** LOAD_REG (reg, data) reg = <data>
+** << 0 >>
+**
+** LOAD_SFBR(data) SFBR = <data>
+** << 0 >>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_FROM_REG(reg) \
+ SCR_REG_SFBR(reg,SCR_OR,0)
+
+#define SCR_TO_REG(reg) \
+ SCR_SFBR_REG(reg,SCR_OR,0)
+
+#define SCR_LOAD_REG(reg,data) \
+ SCR_REG_REG(reg,SCR_LOAD,data)
+
+#define SCR_LOAD_SFBR(data) \
+ (SCR_REG_SFBR (gpreg, SCR_LOAD, data))
+
+/*-----------------------------------------------------------
+**
+** LOAD from memory to register.
+** STORE from register to memory.
+**
+** Only supported by 810A, 860, 825A, 875, 895 and 896.
+**
+**-----------------------------------------------------------
+**
+** LOAD_ABS (LEN)
+** <<start address>>
+**
+** LOAD_REL (LEN) (DSA relative)
+** <<dsa_offset>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_REG_OFS2(ofs) (((ofs) & 0xff) << 16ul)
+#define SCR_NO_FLUSH2 0x02000000
+#define SCR_DSA_REL2 0x10000000
+
+#define SCR_LOAD_R(reg, how, n) \
+ (0xe1000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_STORE_R(reg, how, n) \
+ (0xe0000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_LOAD_ABS(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_LOAD_REL(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n)
+#define SCR_LOAD_ABS_F(reg, n) SCR_LOAD_R(reg, 0, n)
+#define SCR_LOAD_REL_F(reg, n) SCR_LOAD_R(reg, SCR_DSA_REL2, n)
+
+#define SCR_STORE_ABS(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_STORE_REL(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n)
+#define SCR_STORE_ABS_F(reg, n) SCR_STORE_R(reg, 0, n)
+#define SCR_STORE_REL_F(reg, n) SCR_STORE_R(reg, SCR_DSA_REL2, n)
+
+
+/*-----------------------------------------------------------
+**
+** Waiting for Disconnect or Reselect
+**
+**-----------------------------------------------------------
+**
+** JUMP [ | IFTRUE/IFFALSE ( ... ) ]
+** <<address>>
+**
+** JUMPR [ | IFTRUE/IFFALSE ( ... ) ]
+** <<distance>>
+**
+** CALL [ | IFTRUE/IFFALSE ( ... ) ]
+** <<address>>
+**
+** CALLR [ | IFTRUE/IFFALSE ( ... ) ]
+** <<distance>>
+**
+** RETURN [ | IFTRUE/IFFALSE ( ... ) ]
+** <<dummy>>
+**
+** INT [ | IFTRUE/IFFALSE ( ... ) ]
+** <<ident>>
+**
+** INT_FLY [ | IFTRUE/IFFALSE ( ... ) ]
+** <<ident>>
+**
+** Conditions:
+** WHEN (phase)
+** IF (phase)
+** CARRY
+** DATA (data, mask)
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_NO_OP 0x80000000
+#define SCR_JUMP 0x80080000
+#define SCR_JUMP64 0x80480000
+#define SCR_JUMPR 0x80880000
+#define SCR_CALL 0x88080000
+#define SCR_CALLR 0x88880000
+#define SCR_RETURN 0x90080000
+#define SCR_INT 0x98080000
+#define SCR_INT_FLY 0x98180000
+
+#define IFFALSE(arg) (0x00080000 | (arg))
+#define IFTRUE(arg) (0x00000000 | (arg))
+
+#define WHEN(phase) (0x00030000 | (phase))
+#define IF(phase) (0x00020000 | (phase))
+
+#define DATA(D) (0x00040000 | ((D) & 0xff))
+#define MASK(D,M) (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff))
+
+#define CARRYSET (0x00200000)
+
+/*-----------------------------------------------------------
+**
+** SCSI constants.
+**
+**-----------------------------------------------------------
+*/
+
+/*
+** Messages
+*/
+
+#define M_COMPLETE (0x00)
+#define M_EXTENDED (0x01)
+#define M_SAVE_DP (0x02)
+#define M_RESTORE_DP (0x03)
+#define M_DISCONNECT (0x04)
+#define M_ID_ERROR (0x05)
+#define M_ABORT (0x06)
+#define M_REJECT (0x07)
+#define M_NOOP (0x08)
+#define M_PARITY (0x09)
+#define M_LCOMPLETE (0x0a)
+#define M_FCOMPLETE (0x0b)
+#define M_RESET (0x0c)
+#define M_ABORT_TAG (0x0d)
+#define M_CLEAR_QUEUE (0x0e)
+#define M_INIT_REC (0x0f)
+#define M_REL_REC (0x10)
+#define M_TERMINATE (0x11)
+#define M_SIMPLE_TAG (0x20)
+#define M_HEAD_TAG (0x21)
+#define M_ORDERED_TAG (0x22)
+#define M_IGN_RESIDUE (0x23)
+#define M_IDENTIFY (0x80)
+
+#define M_X_MODIFY_DP (0x00)
+#define M_X_SYNC_REQ (0x01)
+#define M_X_WIDE_REQ (0x03)
+
+/*
+** Status
+*/
+
+#define S_GOOD (0x00)
+#define S_CHECK_COND (0x02)
+#define S_COND_MET (0x04)
+#define S_BUSY (0x08)
+#define S_INT (0x10)
+#define S_INT_COND_MET (0x14)
+#define S_CONFLICT (0x18)
+#define S_TERMINATED (0x20)
+#define S_QUEUE_FULL (0x28)
+#define S_ILLEGAL (0xff)
+#define S_SENSE (0x80)
+
+/*
+ * End of ncrreg from FreeBSD
+ */
+
+#endif /* !defined HOSTS_C */
+
+#endif /* defined SYM53C8XX_DEFS_H */