new ahc driver. Adds support for newer Adaptec controllers. This represents two...
authorsmurph <smurph@openbsd.org>
Wed, 22 Mar 2000 02:50:49 +0000 (02:50 +0000)
committersmurph <smurph@openbsd.org>
Wed, 22 Mar 2000 02:50:49 +0000 (02:50 +0000)
20 files changed:
share/man/man4/ahc.4
sys/arch/i386/isa/ahc_isa.c
sys/dev/eisa/ahc_eisa.c
sys/dev/microcode/Makefile.inc [deleted file]
sys/dev/microcode/aic7xxx/Makefile [new file with mode: 0644]
sys/dev/microcode/aic7xxx/Makefile.inc [deleted file]
sys/dev/microcode/aic7xxx/aic7xxx.reg [new file with mode: 0644]
sys/dev/microcode/aic7xxx/aic7xxx.seq
sys/dev/microcode/aic7xxx/aic7xxx_asm.1 [deleted file]
sys/dev/microcode/aic7xxx/aic7xxx_asm.c [deleted file]
sys/dev/microcode/aic7xxx/aic7xxx_reg.h [deleted file]
sys/dev/microcode/aic7xxx/aic7xxx_seq.h
sys/dev/microcode/aic7xxx/aicasm.c [new file with mode: 0644]
sys/dev/microcode/aic7xxx/aicasm.h [new file with mode: 0644]
sys/dev/microcode/aic7xxx/aicasm_gram.y [new file with mode: 0644]
sys/dev/microcode/aic7xxx/aicasm_scan.l [new file with mode: 0644]
sys/dev/microcode/aic7xxx/aicasm_symbol.c [new file with mode: 0644]
sys/dev/microcode/aic7xxx/aicasm_symbol.h [new file with mode: 0644]
sys/dev/microcode/aic7xxx/sequencer.h [new file with mode: 0644]
sys/dev/microcode/ncr53cxxx/Makefile.inc

index e47d014..46b1444 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: ahc.4,v 1.6 1999/07/09 13:35:48 aaron Exp $
+.\"    $OpenBSD: ahc.4,v 1.7 2000/03/22 03:00:57 smurph Exp $
 .\"    $NetBSD: ahc.4,v 1.1.2.1 1996/08/25 17:22:14 thorpej Exp $
 .\"
 .\" Copyright (c) 1995, 1996
@@ -27,7 +27,7 @@
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
 .\"
-.Dd April 20, 1996
+.Dd March 20, 2000
 .\".Dt AHC 4
 .\".Os FreeBSD
 .Dt AHC 4
@@ -55,12 +55,6 @@ For one or more PCI cards:
 \{For PCI cards:
 .Cd ahc*       at pci? dev ? function ?\}
 .Pp
-To enable tagged queuing:
-.Cd option AHC_TAGENABLE
-.Pp
-To enable SCB paging:
-.Cd options AHC_SCBPAGING_ENABLE
-.Pp
 .ie 0 \{
 For one or more SCSI busses:
 .Cd controller scbus0 at ahc0
@@ -70,96 +64,177 @@ For one or more SCSI busses:
 .Sh DESCRIPTION
 This driver provides access to the
 .Tn SCSI
-bus connected to an Adaptec
-274x, 284x, 2940, 3940, or controllers based on the
+bus(es) connected to Adaptec
 .Tn AIC7770,
 .Tn AIC7850,
 .Tn AIC7860,
 .Tn AIC7870,
+.Tn AIC7880,
+.Tn AIC7890,
+.Tn AIC7891,
+.Tn AIC7895,
+.Tn AIC7896,
 or
-.Tn AIC7880
+.Tn AIC7897
 host adapter chips.
-Features include support for twin and wide busses,
-ultra
-.Tn SCSI,
-two active commands at a time per non-tagged queuing target,
+These chips are found on many motherboards as well as the following
+Adaptec SCSI controller cards:
+.Tn 274X(W),
+.Tn 274X(T),
+.Tn 284X,
+.Tn 2920C,
+.Tn 2930U2,
+.Tn 2940,
+.Tn 2940U,
+.Tn 2940AU,
+.Tn 2940UW,
+.Tn 2940UW Dual,
+.Tn 2940U2W,
+.Tn 2940U2B,
+.Tn 2950U2W,
+.Tn 2950U2B,
+.Tn 3940,
+.Tn 3940U,
+.Tn 3940AU,
+.Tn 3940UW,
+.Tn 3940AUW,
+.Tn 3940U2W,
+.Tn 3950U2,
+and
+.Tn 3985.
+.Pp
+Driver features include support for twin and wide busses,
+fast, ultra and ultra2 synchronous transfers depending on controller type,
 tagged queuing,
-and SCB paging which allows up to 255 active commands on all adapters
-except those using
-.Tn AIC7770
-chips prior to revision E.
-Tagged queuing is enabled with the
-.Dq Dv AHC_TAGENABLE
-configuration option.
-SCB paging is enabled with the
-.Dq Dv AHC_SCBPAGING_ENABLE
+and SCB paging.
+.Pp
+Memory mapped I/O can be enabled for PCI devices with the
+.Dq Dv AHC_ALLOW_MEMIO
 configuration option.
+Memory mapped I/O is more efficient than the alternative, programmed I/O.
+Most PCI BIOSes will map devices so that either technique for communicating
+with the card is available.
+In some cases,
+usually when the PCI device is sitting behind a PCI->PCI bridge,
+the BIOS fails to properly initialize the chip for memory mapped I/O.
+The symptom of this problem is usually a system hang if memory mapped I/O
+is attempted.
+Most modern motherboards perform the initialization correctly and work fine
+with this option enabled.
 .Pp
-Per target configuration performed in the
+Per target configuration performed in the 
 .Tn SCSI-Select
 menu, accessible at boot
-in
+in 
 .No non- Ns Tn EISA
-models or through an
+models,
+or through an 
 .Tn EISA
-configuration utility for
+configuration utility for 
 .Tn EISA
 models,
-is honored by this driver with the stipulation that the
+is honored by this driver with the stipulation that the 
 .Tn BIOS
-must be enabled for
+must be enabled for 
 .Tn EISA
 adaptors.  This includes synchronous/asynchronous transfers,
 maximum synchronous negotiation rate,
 disconnection,
-and the host adapter's SCSI ID.
-.Pp
-Note that I/O addresses are determined automatically by the probe routines,
-but care should be taken when using a 284x
-.Pq Tn VESA No local bus controller
-in an
-.Tn EISA
-system.  Ensure that the jumpers setting the I/O area for the 284x match the
+the host adapter's SCSI ID,
+and,
+in the case of
 .Tn EISA
-slot into which the card is inserted to prevent conflicts with other
-.Tn EISA
-cards.
+Twin Channel controllers,
+the primary channel selection.
+.Pp
+Performance and feature sets vary throughout the aic7xxx product line.
+The following table provides a comparison of the different chips supported
+by the
+.Nm
+driver.  Note that wide and twin channel features, although always supported
+by a particular chip, may be disabled in a particular motherboard or card
+design.
+.Pp
+.Bd -filled -offset indent
+.Bl -column "aic7770 " "10 " "EISA/VL  " "10MHz " "16bit " "SCBs " Features
+.Em "Chip       MIPS    Bus      MaxSync   MaxWidth  SCBs  Features"
+aic7770     10    EISA/VL    10MHz     16Bit     4    1
+aic7850     10    PCI/32     10MHz      8Bit     3
+aic7860     10    PCI/32     20MHz      8Bit     3
+aic7870     10    PCI/32     10MHz     16Bit    16
+aic7880     10    PCI/32     20MHz     16Bit    16 
+aic7890     20    PCI/32     40MHz     16Bit    16        3 4 5 6 7
+aic7891     20    PCI/64     40MHz     16Bit    16        3 4 5 6 7
+aic7895     15    PCI/32     20MHz     16Bit    16      2 3 4 5
+aic7896     20    PCI/32     40MHz     16Bit    16      2 3 4 5 6 7
+aic7897     20    PCI/64     40MHz     16Bit    16      2 3 4 5 6 7
+.El 
+.Pp
+.Bl -enum -compact
+.It
+Multiplexed Twin Channel Device - One controller servicing two busses.
+.It
+Multi-function Twin Channel Device - Two controllers on one chip.
+.It
+Command Channel Secondary DMA Engine - Allows scatter gather list and
+SCB prefetch.
+.It
+64 Byte SCB Support - SCSI CDB is embedded in the SCB to eliminate an extra DMA.
+.It
+Block Move Instruction Support - Doubles the speed of certain sequencer
+operations.
+.It
+.Sq Bayonet
+style Scatter Gather Engine - Improves S/G prefetch performance.
+.It
+Queuing Registers - Allows queuing of new transactions without pausing the
+sequencer.
+.El
+.Ed
+.Pp
+
+.Sh SCSI CONTROL BLOCKS (SCBs)
+Every transaction sent to a device on the SCSI bus is assigned a
+.Sq SCSI Control Block
+(SCB).  The SCB contains all of the information required by the
+controller to process a transaction.  The chip feature table lists
+the number of SCBs that can be stored in on chip memory.  All chips
+with model numbers greater than or equal to 7870 allow for the on chip
+SCB space to be augmented with external SRAM up to a maximum of 255 SCBs.
+Very few Adaptec controller have external SRAM.
+
+If external SRAM is not available, SCBs are a limited resource and
+using them in a straight forward manner would only allow us to
+keep as many transactions as there are SCBs outstanding at a time.
+This would not allow enough concurrency to fully utilize the SCSI
+bus and it's devices.
+The solution to this problem is
+.Em SCB Paging ,
+a concept similar to memory paging.  SCB paging takes advantage of
+the fact that devices usually disconnect from the SCSI bus for long
+periods of time without talking to the controller.  The SCBs
+for disconnected transactions are only of use to the controller
+when the transfer is resumed.  When the host queues another transaction
+for the controller to execute, the controller firmware will use a
+free SCB if one is available.  Otherwise, the state of the most recently
+disconnected (and therefor most likely to stay disconnected) SCB is
+saved, via dma, to host memory, and the local SCB reused to start
+the new transaction.  This allows the controller to queue up to
+255 transactions regardless of the amount of SCB space.  Since the
+local SCB space serves as a cache for disconnected transactions, the
+more SCB space available, the less host bus traffic consumed saving
+and restoring SCB data.
 .Sh BUGS
 Some Quantum drives (at least the Empire 2100 and 1080s) will not run on an
 .Tn AIC7870
 Rev B in synchronous mode at 10MHz.  Controllers with this problem have a
-42 MHz clock crystal on them and run slightly above 10MHz, causing the
-drive much confusion.  Setting a maximum synchronous negotiation rate of 8MHz
-in the
+42 MHz clock crystal on them and run slightly above 10MHz.  This confuses
+the drive and hangs the bus.  Setting a maximum synchronous negotiation rate
+of 8MHz in the 
 .Tn SCSI-Select
 utility
-will allow normal function.
-.if 1 \{
-.Pp
-There are four problems known in this version of this driver as follows.
-All of these problems relate to MI SCSI system.
-.Pp
-Cannot handle SCSI ID greater than 7 with WIDE SCSI adapter.
-.Pp
-It is dangerous to simultaneously access SCSI devices more than half
-number of SCBs. It may cause fatal disk trouble. In this case,
-diagnostics message
-.Dq not queued, error ...
-is displayed to console.
-For example, AHA-274x and AHA-284x have only 4 SCBs, so that using 3 SCSI
-devices is dangerous, using 2 devices is OK.
-.Pp
-When you suddenly access SCSI devices on free physical memory shortage
-conditions, and if there have been very few load on SCSI devices until
-then, it may cause fatal disk trouble. In this case, diagnostics
-message
-.Dq ahc0: Can't malloc SCB
-and
-.Dq not queued, error ...
-is displayed to console.
-.Pp
-SCSI residual handling is not complete.
-\}
+will allow normal operation.
+
 .Sh SEE ALSO
 .Xr aha 4 ,
 .Xr ahb 4
@@ -172,7 +247,9 @@ SCSI residual handling is not complete.
 .Sh AUTHOR
 The
 .Nm
-driver was written by Justin Gibbs.  The
+driver, the
 .Tn AIC7xxx
-sequencer-code assembler was
-written by John Aycock.
+sequencer-code assembler,
+and the firmware running on the aic7xxx chips was written by
+.An Justin T. Gibbs .
+
index a7bb4f3..e504eea 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ahc_isa.c,v 1.4 1999/01/11 05:11:24 millert Exp $     */
+/*     $OpenBSD: ahc_isa.c,v 1.5 2000/03/22 02:57:17 smurph Exp $      */
 /*     $NetBSD: ahc_isa.c,v 1.5 1996/10/21 22:27:39 thorpej Exp $      */
 
 /*
 
 #include <dev/ic/aic7xxxreg.h>
 #include <dev/ic/aic7xxxvar.h>
+#include <dev/ic/smc93cx6var.h>
+
+#ifdef DEBUG
+#define bootverbose    1
+#else
+#define bootverbose    0
+#endif
 
 /* IO port address setting range as EISA slot number */
 #define AHC_ISA_MIN_SLOT       0x1     /* from iobase = 0x1c00 */
@@ -112,9 +119,10 @@ int        ahc_isa_match __P((struct isa_attach_args *, bus_addr_t));
 
 int    ahc_isa_probe __P((struct device *, void *, void *));
 void   ahc_isa_attach __P((struct device *, struct device *, void *));
+void   aha2840_load_seeprom __P((struct ahc_softc *ahc));
 
 struct cfattach ahc_isa_ca = {
-       sizeof(struct ahc_data), ahc_isa_probe, ahc_isa_attach
+       sizeof(struct ahc_softc), ahc_isa_probe, ahc_isa_attach
 };
 
 /*
@@ -144,8 +152,12 @@ ahc_isa_irq(iot, ioh)
 {
        int irq;
        u_char intdef;
+       u_char hcntrl;
+       
+       /* Pause the card preseving the IRQ type */
+       hcntrl = bus_space_read_1(iot, ioh, HCNTRL) & IRQMS;
+       bus_space_write_1(iot, ioh, HCNTRL, hcntrl | PAUSE);
 
-       ahc_reset("ahc_isa", iot, ioh);
        intdef = bus_space_read_1(iot, ioh, INTDEF);
        switch (irq = (intdef & 0xf)) {
        case 9:
@@ -261,7 +273,7 @@ ahc_isa_match(ia, iobase)
        if (ia->ia_irq != IRQUNK &&
            ia->ia_irq != irq) {
                printf("ahc_isa_match: irq mismatch (kernel %d, card %d)\n",
-                   ia->ia_irq, irq);
+                      ia->ia_irq, irq);
                return (0);
        }
 
@@ -334,15 +346,18 @@ ahc_isa_attach(parent, self, aux)
        struct device *parent, *self;
        void *aux;
 {
-       ahc_type type;
-       struct ahc_data *ahc = (void *)self;
+       ahc_chip chip;
+       struct ahc_softc *ahc = (void *)self;
        struct isa_attach_args *ia = aux;
        bus_space_tag_t iot = ia->ia_iot;
        bus_space_handle_t ioh;
        int irq;
        char idstring[EISA_IDSTRINGLEN];
        const char *model;
+       u_char channel = 'A';
 
+       ahc->sc_dmat = ia->ia_dmat;
+       chip = AHC_VL; /* We are a VL Bus Controller */  
        if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
                panic("ahc_isa_attach: could not map slot I/O addresses");
        if (!ahc_isa_idstring(iot, ioh, idstring))
@@ -352,16 +367,16 @@ ahc_isa_attach(parent, self, aux)
 
        if (strcmp(idstring, "ADP7756") == 0) {
                model = EISA_PRODUCT_ADP7756;
-               type = AHC_284;
+               chip |= AHC_AIC7770;
        } else if (strcmp(idstring, "ADP7757") == 0) {
                model = EISA_PRODUCT_ADP7757;
-               type = AHC_284;
+               chip |= AHC_AIC7770;
        } else {
                panic("ahc_isa_attach: Unknown device type %s", idstring);
        }
        printf(": %s\n", model);
 
-       ahc_construct(ahc, iot, ioh, type, AHC_FNONE);
+       ahc_construct(ahc, iot, ioh, chip, AHC_FNONE, AHC_AIC7770_FE, channel);
 
 #ifdef DEBUG
        /*
@@ -372,23 +387,15 @@ ahc_isa_attach(parent, self, aux)
            ahc->pause & IRQMS ?  "Level Sensitive" : "Edge Triggered");
 #endif
 
+       ahc->channel = 'A';
+       ahc->channel_b = 'B';
+       if (ahc_reset(ahc) != 0)
+               return;
        /*
         * Now that we know we own the resources we need, do the 
         * card initialization.
-        *
-        * First, the aic7770 card specific setup.
-        */
-
-       /* XXX
-        * On AHA-284x,
-        * all values are automagically intialized at
-        * POST for these cards, so we can always rely
-        * on the Scratch Ram values.  However, we should
-        * read the SEEPROM here (Dan has the code to do
-        * it) so we can say what kind of translation the
-        * BIOS is using.  Printing out the geometry could
-        * save a lot of users the grief of failed installs.
         */
+       aha2840_load_seeprom(ahc);
 
        /*      
         * See if we have a Rev E or higher aic7770. Anything below a
@@ -462,3 +469,98 @@ ahc_isa_attach(parent, self, aux)
        /* Attach sub-devices - always succeeds */
        ahc_attach(ahc);
 }
+
+/*
+ * Read the 284x SEEPROM.
+ */
+void
+aha2840_load_seeprom(struct ahc_softc *ahc)
+{
+       struct    seeprom_descriptor sd;
+       struct    seeprom_config sc;
+       u_int16_t checksum = 0;
+       u_int8_t  scsi_conf;
+       int       have_seeprom;
+
+       sd.sd_tag = ahc->sc_iot;
+       sd.sd_bsh = ahc->sc_ioh;
+       sd.sd_control_offset = SEECTL_2840;
+       sd.sd_status_offset = STATUS_2840;
+       sd.sd_dataout_offset = STATUS_2840;             
+       sd.sd_chip = C46;
+       sd.sd_MS = 0;
+       sd.sd_RDY = EEPROM_TF;
+       sd.sd_CS = CS_2840;
+       sd.sd_CK = CK_2840;
+       sd.sd_DO = DO_2840;
+       sd.sd_DI = DI_2840;
+
+       if (bootverbose)
+               printf("%s: Reading SEEPROM...", ahc_name(ahc));
+       have_seeprom = read_seeprom(&sd,
+                                   (u_int16_t *)&sc,
+                                   /*start_addr*/0,
+                                   sizeof(sc)/2);
+
+       if (have_seeprom) {
+               /* Check checksum */
+               int i;
+               int maxaddr = (sizeof(sc)/2) - 1;
+               u_int16_t *scarray = (u_int16_t *)&sc;
+
+               for (i = 0; i < maxaddr; i++)
+                       checksum = checksum + scarray[i];
+               if (checksum != sc.checksum) {
+                       if(bootverbose)
+                               printf ("checksum error\n");
+                       have_seeprom = 0;
+               } else if (bootverbose) {
+                       printf("done.\n");
+               }
+       }
+
+       if (!have_seeprom) {
+               if (bootverbose)
+                       printf("%s: No SEEPROM available\n", ahc_name(ahc));
+               ahc->flags |= AHC_USEDEFAULTS;
+       } else {
+               /*
+                * Put the data we've collected down into SRAM
+                * where ahc_init will find it.
+                */
+               int i;
+               int max_targ = (ahc->features & AHC_WIDE) != 0 ? 16 : 8;
+               u_int16_t discenable;
+
+               discenable = 0;
+               for (i = 0; i < max_targ; i++){
+                       u_int8_t target_settings;
+                       target_settings = (sc.device_flags[i] & CFXFER) << 4;
+                       if (sc.device_flags[i] & CFSYNCH)
+                               target_settings |= SOFS;
+                       if (sc.device_flags[i] & CFWIDEB)
+                               target_settings |= WIDEXFER;
+                       if (sc.device_flags[i] & CFDISC)
+                               discenable |= (0x01 << i);
+                       ahc_outb(ahc, TARG_SCSIRATE + i, target_settings);
+               }
+               ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
+               ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
+
+               ahc->our_id = sc.brtime_id & CFSCSIID;
+
+               scsi_conf = (ahc->our_id & 0x7);
+               if (sc.adapter_control & CFSPARITY)
+                       scsi_conf |= ENSPCHK;
+               if (sc.adapter_control & CFRESETB)
+                       scsi_conf |= RESET_SCSI;
+
+               if (sc.bios_control & CF284XEXTEND)             
+                       ahc->flags |= AHC_EXTENDED_TRANS_A;
+               /* Set SCSICONF info */
+               ahc_outb(ahc, SCSICONF, scsi_conf);
+
+               if (sc.adapter_control & CF284XSTERM)
+                       ahc->flags |= AHC_TERM_ENB_A;
+       }
+}
index b0cf4bd..37c3642 100644 (file)
@@ -1,6 +1,6 @@
-/*     $OpenBSD: ahc_eisa.c,v 1.8 1999/01/11 01:57:59 millert Exp $    */
+/*     $OpenBSD: ahc_eisa.c,v 1.9 2000/03/22 02:55:40 smurph Exp $     */
 /*     $NetBSD: ahc_eisa.c,v 1.10 1996/10/21 22:30:58 thorpej Exp $    */
-  
+
 /*
  * Product specific probe and attach routines for:
  *     27/284X and aic7770 motherboard SCSI controllers
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $Id: ahc_eisa.c,v 1.8 1999/01/11 01:57:59 millert Exp $
+ *     $Id: ahc_eisa.c,v 1.9 2000/03/22 02:55:40 smurph Exp $
  */
 
-#if defined(__FreeBSD__)
-#include <eisa.h>
-#endif
-#if NEISA > 0 || defined(__NetBSD__) || defined(__OpenBSD__)
+#include "eisa.h"
+#if NEISA > 0
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#if defined(__FreeBSD__)
-#include <sys/devconf.h>
-#endif
 #include <sys/kernel.h>
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
 #include <sys/device.h>
 #include <machine/bus.h>
 #include <machine/intr.h>
-#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
 
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 
-#if defined(__FreeBSD__)
-
-#include <machine/clock.h>
-
-#include <i386/eisa/eisaconf.h>
-#include <i386/scsi/aic7xxx.h>
-#include <dev/aic7xxx/aic7xxx_reg.h>
-
-#define EISA_DEVICE_ID_ADAPTEC_AIC7770 0x04907770
-#define EISA_DEVICE_ID_ADAPTEC_274x    0x04907771
-#define EISA_DEVICE_ID_ADAPTEC_284xB   0x04907756 /* BIOS enabled */
-#define EISA_DEVICE_ID_ADAPTEC_284x    0x04907757 /* BIOS disabled*/
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-
 #include <dev/eisa/eisareg.h>
 #include <dev/eisa/eisavar.h>
 #include <dev/eisa/eisadevs.h>
-
 #include <dev/ic/aic7xxxreg.h>
 #include <dev/ic/aic7xxxvar.h>
 
-#endif /* defined(__NetBSD__) */
-
 #define AHC_EISA_SLOT_OFFSET   0xc00
 #define AHC_EISA_IOSIZE                0x100
 #define INTDEF                 0x5cul  /* Interrupt Definition Register */
 
-#if defined(__FreeBSD__)
-
-static int     aic7770probe __P((void));
-static int     aic7770_attach __P((struct eisa_device *e_dev));
-
-static struct eisa_driver ahc_eisa_driver = {
-                                       "ahc",
-                                       aic7770probe,
-                                       aic7770_attach,
-                                       /*shutdown*/NULL,
-                                       &ahc_unit
-                                     };
-
-DATA_SET (eisadriver_set, ahc_eisa_driver);
-
-static struct kern_devconf kdc_aic7770 = {
-       0, 0, 0,                /* filled in by dev_attach */
-       "ahc", 0, { MDDT_EISA, 0, "bio" },
-       eisa_generic_externalize, 0, 0, EISA_EXTERNALLEN,
-       &kdc_eisa0,             /* parent */
-       0,                      /* parentdata */
-       DC_UNCONFIGURED,        /* always start out here */
-       NULL,
-       DC_CLS_MISC             /* host adapters aren't special */
-};
-
-
-static char    *aic7770_match __P((eisa_id_t type));
-
-static  char*
-aic7770_match(type)
-       eisa_id_t type;
-{
-       switch(type) {
-               case EISA_DEVICE_ID_ADAPTEC_AIC7770:
-                       return ("Adaptec aic7770 SCSI host adapter");
-                       break;
-               case EISA_DEVICE_ID_ADAPTEC_274x:
-                       return ("Adaptec 274X SCSI host adapter");
-                       break;
-               case EISA_DEVICE_ID_ADAPTEC_284xB:
-               case EISA_DEVICE_ID_ADAPTEC_284x:
-                       return ("Adaptec 284X SCSI host adapter");
-                       break;
-               default:
-                       break;
-       }
-       return (NULL);
-}
-
-static int
-aic7770probe(void)
-{
-       u_long iobase;
-       char intdef;
-       u_long irq;
-       struct eisa_device *e_dev = NULL;
-       int count;
-
-       count = 0;
-       while ((e_dev = eisa_match_dev(e_dev, aic7770_match))) {
-               iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE)
-                        + AHC_EISA_SLOT_OFFSET;
-               ahc_reset(iobase);
-
-               eisa_add_iospace(e_dev, iobase, AHC_EISA_IOSIZE, RESVADDR_NONE);
-               intdef = inb(INTDEF + iobase);
-               switch (intdef & 0xf) {
-                       case 9: 
-                               irq = 9;
-                               break;
-                       case 10:
-                               irq = 10;
-                               break;
-                       case 11:
-                               irq = 11;
-                               break;  
-                       case 12:
-                               irq = 12;
-                               break;
-                       case 14:
-                               irq = 14;
-                               break;
-                       case 15:
-                               irq = 15;
-                               break;
-                       default:
-                               printf("aic7770 at slot %d: illegal "
-                                   "irq setting %d\n", e_dev->ioconf.slot,
-                                   intdef);
-                               continue;
-               }
-               eisa_add_intr(e_dev, irq);
-               eisa_registerdev(e_dev, &ahc_eisa_driver, &kdc_aic7770);
-               if(e_dev->id == EISA_DEVICE_ID_ADAPTEC_284xB
-                  || e_dev->id == EISA_DEVICE_ID_ADAPTEC_284x) {
-                       /* Our real parent is the isa bus.  Say so. */
-                       e_dev->kdc->kdc_parent = &kdc_isa0;
-               }
-               count++;
-       }
-       return count;
-}
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-
 /*
  * Under normal circumstances, these messages are unnecessary
  * and not terribly cosmetic.
@@ -197,16 +65,16 @@ aic7770probe(void)
 #ifdef DEBUG
 #define bootverbose    1
 #else
-#define bootverbose    0
+#define bootverbose    1
 #endif
-  
-int    ahc_eisa_irq __P((bus_space_tag_t, bus_space_handle_t));
-int    ahc_eisa_match __P((struct device *, void *, void *));
-void   ahc_eisa_attach __P((struct device *, struct device *, void *));
+
+int   ahc_eisa_irq __P((bus_space_tag_t, bus_space_handle_t));
+int   ahc_eisa_match __P((struct device *, void *, void *));
+void  ahc_eisa_attach __P((struct device *, struct device *, void *));
 
 
 struct cfattach ahc_eisa_ca = {
-       sizeof(struct ahc_data), ahc_eisa_match, ahc_eisa_attach
+       sizeof(struct ahc_softc), ahc_eisa_match, ahc_eisa_attach
 };
 
 /*
@@ -214,13 +82,17 @@ struct cfattach ahc_eisa_ca = {
  */
 int
 ahc_eisa_irq(iot, ioh)
-       bus_space_tag_t iot;
-       bus_space_handle_t ioh;
+bus_space_tag_t iot;
+bus_space_handle_t ioh;
 {
        int irq;
        u_char intdef;
-
-       ahc_reset("ahc_eisa", iot, ioh);
+       u_char hcntrl;
+       
+       /* Pause the card preseving the IRQ type */
+       hcntrl = bus_space_read_1(iot, ioh, HCNTRL) & IRQMS;
+       bus_space_write_1(iot, ioh, HCNTRL, hcntrl | PAUSE);
+       
        intdef = bus_space_read_1(iot, ioh, INTDEF);
        switch (irq = (intdef & 0xf)) {
        case 9:
@@ -246,8 +118,8 @@ ahc_eisa_irq(iot, ioh)
  */
 int
 ahc_eisa_match(parent, match, aux)
-       struct device *parent;
-       void *match, *aux;
+struct device *parent;
+void *match, *aux;
 {
        struct eisa_attach_args *ea = aux;
        bus_space_tag_t iot = ea->ea_iot;
@@ -256,16 +128,16 @@ ahc_eisa_match(parent, match, aux)
 
        /* must match one of our known ID strings */
        if (strcmp(ea->ea_idstring, "ADP7770") &&
-           strcmp(ea->ea_idstring, "ADP7771")
+                strcmp(ea->ea_idstring, "ADP7771")
 #if 0
-           && strcmp(ea->ea_idstring, "ADP7756") /* not EISA, but VL */
-           && strcmp(ea->ea_idstring, "ADP7757") /* not EISA, but VL */
+                && strcmp(ea->ea_idstring, "ADP7756")  /* not EISA, but VL */
+                && strcmp(ea->ea_idstring, "ADP7757")  /* not EISA, but VL */
 #endif
-           )
+               )
                return (0);
 
        if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
-           AHC_EISA_SLOT_OFFSET, AHC_EISA_IOSIZE, 0, &ioh))
+                         AHC_EISA_SLOT_OFFSET, AHC_EISA_IOSIZE, 0, &ioh))
                return (0);
 
        irq = ahc_eisa_irq(iot, ioh);
@@ -275,72 +147,14 @@ ahc_eisa_match(parent, match, aux)
        return (irq >= 0);
 }
 
-#endif /* defined(__NetBSD__) */
-
-#if defined(__FreeBSD__)
-static int
-aic7770_attach(e_dev)
-       struct eisa_device *e_dev;
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
 void
 ahc_eisa_attach(parent, self, aux)
-       struct device *parent, *self;
-       void *aux;
-#endif
+struct device *parent, *self;
+void *aux;
 {
-       ahc_type type;
-
-#if defined(__FreeBSD__)
-       struct ahc_data *ahc;
-       resvaddr_t *iospace;
-       int unit = e_dev->unit;
-       int irq = ffs(e_dev->ioconf.irq) - 1;
-
-       iospace = e_dev->ioconf.ioaddrs.lh_first;
-
-       if(!iospace)
-               return -1;
-
-       switch(e_dev->id) {
-               case EISA_DEVICE_ID_ADAPTEC_AIC7770:
-                       type = AHC_AIC7770;
-                       break;
-               case EISA_DEVICE_ID_ADAPTEC_274x:
-                       type = AHC_274;
-                       break;          
-               case EISA_DEVICE_ID_ADAPTEC_284xB:
-               case EISA_DEVICE_ID_ADAPTEC_284x:
-                       type = AHC_284;
-                       break;
-               default: 
-                       printf("aic7770_attach: Unknown device type!\n");
-                       return -1;
-                       break;
-       }
-
-       if(!(ahc = ahc_alloc(unit, iospace->addr, type, AHC_FNONE)))
-               return -1;
-
-       eisa_reg_start(e_dev);
-       if(eisa_reg_iospace(e_dev, iospace)) {
-               ahc_free(ahc);
-               return -1;
-       }
-
-       /*
-        * The IRQMS bit enables level sensitive interrupts. Only allow
-        * IRQ sharing if it's set.
-        */
-       if(eisa_reg_intr(e_dev, irq, ahc_intr, (void *)ahc, &bio_imask,
-                        /*shared ==*/ahc->pause & IRQMS)) {
-               ahc_free(ahc);
-               return -1;
-       }
-       eisa_reg_end(e_dev);
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-
-       struct ahc_data *ahc = (void *)self;
+       ahc_chip chip;
+       u_char channel = 'A'; /* Only one channel */
+       struct ahc_softc *ahc = (void *)self;
        struct eisa_attach_args *ea = aux;
        bus_space_tag_t iot = ea->ea_iot;
        bus_space_handle_t ioh;
@@ -348,49 +162,51 @@ ahc_eisa_attach(parent, self, aux)
        eisa_chipset_tag_t ec = ea->ea_ec;
        eisa_intr_handle_t ih;
        const char *model, *intrstr;
-
+       u_int biosctrl;
+       u_int scsiconf;
+       u_int scsiconf1;
+       
+       ahc->sc_dmat = ea->ea_dmat;
        if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
-           AHC_EISA_SLOT_OFFSET, AHC_EISA_IOSIZE, 0, &ioh))
+                         AHC_EISA_SLOT_OFFSET, AHC_EISA_IOSIZE, 0, &ioh))
                panic("ahc_eisa_attach: could not map I/O addresses");
        if ((irq = ahc_eisa_irq(iot, ioh)) < 0)
                panic("ahc_eisa_attach: ahc_eisa_irq failed!");
 
        if (strcmp(ea->ea_idstring, "ADP7770") == 0) {
                model = EISA_PRODUCT_ADP7770;
-               type = AHC_AIC7770;
+               chip = AHC_AIC7770|AHC_EISA;
        } else if (strcmp(ea->ea_idstring, "ADP7771") == 0) {
                model = EISA_PRODUCT_ADP7771;
-               type = AHC_274;
-#if 0
-       } else if (strcmp(ea->ea_idstring, "ADP7756") == 0) {
-               model = EISA_PRODUCT_ADP7756;
-               type = AHC_284;
-       } else if (strcmp(ea->ea_idstring, "ADP7757") == 0) {
-               model = EISA_PRODUCT_ADP7757;
-               type = AHC_284;
-#endif
+               chip = AHC_AIC7770|AHC_EISA;
        } else {
                panic("ahc_eisa_attach: Unknown device type %s",
-                     ea->ea_idstring);
+                               ea->ea_idstring);
        }
        printf(": %s\n", model);
 
-       ahc_construct(ahc, iot, ioh, type, AHC_FNONE);
+       ahc_construct(ahc, iot, ioh, chip, AHC_FNONE, AHC_AIC7770_FE, channel);
+       
+       ahc->channel = 'A';
+       ahc->channel_b = 'B';
+       if (ahc_reset(ahc) != 0)
+               return;
+       
        if (eisa_intr_map(ec, irq, &ih)) {
                printf("%s: couldn't map interrupt (%d)\n",
-                   ahc->sc_dev.dv_xname, irq);
+                      ahc->sc_dev.dv_xname, irq);
                return;
        }
-#endif /* defined(__NetBSD__) */
 
        /*
         * Tell the user what type of interrupts we're using.
         * usefull for debugging irq problems
         */
-       if(bootverbose) {
+       if (bootverbose) {
                printf("%s: Using %s Interrupts\n",
-                   ahc_name(ahc),
-                   ahc->pause & IRQMS ?  "Level Sensitive" : "Edge Triggered");
+                      ahc_name(ahc),
+                      ahc->pause & IRQMS ?
+                      "Level Sensitive" : "Edge Triggered");
        }
 
        /*
@@ -399,36 +215,35 @@ ahc_eisa_attach(parent, self, aux)
         *
         * First, the aic7770 card specific setup.
         */
-       switch( ahc->type ) {
-           case AHC_AIC7770:
-           case AHC_274:
-           {
-               u_char biosctrl = AHC_INB(ahc, HA_274_BIOSCTRL);
-
-               /* Get the primary channel information */
-               ahc->flags |= (biosctrl & CHANNEL_B_PRIMARY);
-
-               if((biosctrl & BIOSMODE) == BIOSDISABLED)
-                       ahc->flags |= AHC_USEDEFAULTS;
-               break;
-           }
-           case AHC_284:
-           {
-               /* XXX
-                * All values are automagically intialized at
-                * POST for these cards, so we can always rely
-                * on the Scratch Ram values.  However, we should
-                * read the SEEPROM here (Dan has the code to do
-                * it) so we can say what kind of translation the
-                * BIOS is using.  Printing out the geometry could
-                * save a lot of users the grief of failed installs.
-                */
-               break;
-           }
-           default:
-               break;
+       biosctrl = ahc_inb(ahc, HA_274_BIOSCTRL);
+       scsiconf = ahc_inb(ahc, SCSICONF);
+       scsiconf1 = ahc_inb(ahc, SCSICONF + 1);
+       
+       /* Get the primary channel information */
+       if ((biosctrl & CHANNEL_B_PRIMARY) != 0)
+               ahc->flags |= AHC_CHANNEL_B_PRIMARY;
+
+       if ((biosctrl & BIOSMODE) == BIOSDISABLED) {
+               ahc->flags |= AHC_USEDEFAULTS;
+       } else if ((ahc->features & AHC_WIDE) != 0) {
+               ahc->our_id = scsiconf1 & HWSCSIID;
+               if (scsiconf & TERM_ENB)
+                       ahc->flags |= AHC_TERM_ENB_A;
+       } else {
+               ahc->our_id = scsiconf & HSCSIID;
+               ahc->our_id_b = scsiconf1 & HSCSIID;
+               if (scsiconf & TERM_ENB)
+                       ahc->flags |= AHC_TERM_ENB_A;
+               if (scsiconf1 & TERM_ENB)
+                       ahc->flags |= AHC_TERM_ENB_B;
        }
-
+       /*
+        * We have no way to tell, so assume extended
+        * translation is enabled.
+        */
+       
+       ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B;
+       
        /*      
         * See if we have a Rev E or higher aic7770. Anything below a
         * Rev E will have a R/O autoflush disable configuration bit.
@@ -436,7 +251,7 @@ ahc_eisa_attach(parent, self, aux)
         * We think it allows 8 bit entries in the QOUTFIFO to support
         * "paging" SCBs so you can have more than 4 commands active at
         * once.
-        */     
+        */
        {
                char *id_string;
                u_char sblkctl;
@@ -446,8 +261,7 @@ ahc_eisa_attach(parent, self, aux)
                sblkctl = sblkctl_orig ^ AUTOFLUSHDIS;
                AHC_OUTB(ahc, SBLKCTL, sblkctl);
                sblkctl = AHC_INB(ahc, SBLKCTL);
-               if(sblkctl != sblkctl_orig)
-               {
+               if (sblkctl != sblkctl_orig) {
                        id_string = "aic7770 >= Rev E, ";
                        /*
                         * Ensure autoflush is enabled
@@ -457,8 +271,7 @@ ahc_eisa_attach(parent, self, aux)
 
                        /* Allow paging on this adapter */
                        ahc->flags |= AHC_PAGESCBS;
-               }
-               else
+               } else
                        id_string = "aic7770 <= Rev C, ";
 
                printf("%s: %s", ahc_name(ahc), id_string);
@@ -474,52 +287,28 @@ ahc_eisa_attach(parent, self, aux)
        /*
         * Generic aic7xxx initialization.
         */
-       if(ahc_init(ahc)){
-#if defined(__FreeBSD__)
-               ahc_free(ahc);
-               /*
-                * The board's IRQ line is not yet enabled so it's safe
-                * to release the irq.
-                */
-               eisa_release_intr(e_dev, irq, ahc_intr);
-               return -1;
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
+       if (ahc_init(ahc)) {
                ahc_free(ahc);
                return;
-#endif
        }
-
        /*
         * Enable the board's BUS drivers
         */
        AHC_OUTB(ahc, BCTL, ENABLE);
 
-#if defined(__FreeBSD__)
-       /*
-        * Enable our interrupt handler.
-        */
-       if(eisa_enable_intr(e_dev, irq)) {
-               ahc_free(ahc);
-               eisa_release_intr(e_dev, irq, ahc_intr);
-               return -1;
-       }
-
-       e_dev->kdc->kdc_state = DC_BUSY; /* host adapters always busy */
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
        intrstr = eisa_intr_string(ec, ih);
        /*
         * The IRQMS bit enables level sensitive interrupts only allow
         * IRQ sharing if its set.
         */
-       ahc->sc_ih = eisa_intr_establish(ec, ih,
-           ahc->pause & IRQMS ? IST_LEVEL : IST_EDGE, IPL_BIO, ahc_intr, ahc
-#ifdef __OpenBSD__
-           , ahc->sc_dev.dv_xname
-#endif
-           );
+       ahc->sc_ih = eisa_intr_establish(ec, ih, ahc->pause & IRQMS
+                                        ? IST_LEVEL : IST_EDGE,
+                                        IPL_BIO, ahc_intr, ahc,
+                                        ahc->sc_dev.dv_xname);
        if (ahc->sc_ih == NULL) {
                printf("%s: couldn't establish interrupt",
-                   ahc->sc_dev.dv_xname);
+                      ahc->sc_dev.dv_xname);
                if (intrstr != NULL)
                        printf(" at %s", intrstr);
                printf("\n");
@@ -529,14 +318,9 @@ ahc_eisa_attach(parent, self, aux)
        if (intrstr != NULL)
                printf("%s: interrupting at %s\n", ahc->sc_dev.dv_xname,
                       intrstr);
-#endif /* defined(__NetBSD__) */
 
        /* Attach sub-devices - always succeeds */
        ahc_attach(ahc);
 
-#if defined(__FreeBSD__)
-       return 0;
-#endif
 }
-
 #endif /* NEISA > 0 */
diff --git a/sys/dev/microcode/Makefile.inc b/sys/dev/microcode/Makefile.inc
deleted file mode 100644 (file)
index d007473..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#      $OpenBSD: Makefile.inc,v 1.3 1997/11/07 08:07:15 niklas Exp $
-
-.include "$S/dev/microcode/aic7xxx/Makefile.inc"
-.include "$S/dev/microcode/ncr53cxxx/Makefile.inc"
diff --git a/sys/dev/microcode/aic7xxx/Makefile b/sys/dev/microcode/aic7xxx/Makefile
new file mode 100644 (file)
index 0000000..2b91caf
--- /dev/null
@@ -0,0 +1,44 @@
+# $OpenBSD: Makefile,v 1.1 2000/03/22 02:50:49 smurph Exp $
+# $FreeBSD: src/sys/dev/aic7xxx/Makefile,v 1.6 1999/08/28 00:41:22 peter Exp $
+
+PROG=  aicasm
+
+CSRCS= aicasm.c aicasm_symbol.c
+GENSRCS= aicasm_gram.c aicasm_scan.c
+
+GENHDRS=       y.tab.h
+
+SRCS=  ${GENSRCS} ${CSRCS}
+CLEANFILES+= ${GENSRCS} ${GENHDRS} y.output
+DPADD+=        ${LIBL}
+LDADD+=        -ll
+
+# Correct path for kernel builds
+# Don't rely on the kernel's .depend file
+.ifdef MAKESRCPATH
+.PATH: ${MAKESRCPATH}
+DEPENDFILE=
+.endif
+
+CFLAGS+= -I/usr/include -I.
+NOMAN= noman
+
+.ifdef DEBUG
+CFLAGS+= -DDEBUG -g
+YFLAGS+= -t
+LFLAGS+= -d
+MFLAGS= -l seq.lst
+.endif
+
+microcode aic7xxxreg.h aic7xxx_seq.h: aic7xxx.seq aic7xxx.reg
+       ./aicasm -I/sys ${MFLAGS} -r tempreg.h -o tempseq.h ${.CURDIR}/aic7xxx.seq
+       grep OpenBSD: ${.CURDIR}/aic7xxx.seq | cat - tempseq.h > aic7xxx_seq.h
+       grep OpenBSD: ${.CURDIR}/aic7xxx.reg | cat - tempreg.h > aic7xxxreg.h
+       mv aic7xxx_seq.h /sys/dev/microcode/aic7xxx/
+.ifdef DEBUG
+       mv seq.lst /sys/dev/microcode/aic7xxx/
+.endif
+       cp aic7xxxreg.h /sys/dev/ic/
+       rm -f tempseq.h tempreg.h
+
+.include <bsd.prog.mk>
diff --git a/sys/dev/microcode/aic7xxx/Makefile.inc b/sys/dev/microcode/aic7xxx/Makefile.inc
deleted file mode 100644 (file)
index 7e89b51..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#      $OpenBSD: Makefile.inc,v 1.5 1996/11/28 23:27:58 niklas Exp $
-#      $NetBSD: Makefile.inc,v 1.4 1996/05/20 00:48:43 thorpej Exp $
-
-.if target(aic7xxx.o)
-PATH: $S/dev/microcode/aic7xxx
-
-aic7xxx.o: aic7xxx_seq.h
-
-aic7xxx_seq.h: aic7xxx_asm $S/dev/microcode/aic7xxx/aic7xxx.seq
-       ./aic7xxx_asm -o ${.TARGET} $S/dev/microcode/aic7xxx/aic7xxx.seq
-
-aic7xxx_asm: $S/dev/microcode/aic7xxx/aic7xxx_asm.c
-       ${HOSTCC} -U_KERNEL -o ${.TARGET} $<
-
-clean::
-       rm -f aic7xxx_asm
-.endif
diff --git a/sys/dev/microcode/aic7xxx/aic7xxx.reg b/sys/dev/microcode/aic7xxx/aic7xxx.reg
new file mode 100644 (file)
index 0000000..e85bfc7
--- /dev/null
@@ -0,0 +1,1485 @@
+/*     $NetBSD$        */
+
+/*
+ * Aic7xxx register and scratch ram definitions.
+ *
+ * Copyright (c) 1994-2000 Justin Gibbs.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * the GNU Public License ("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.
+ *
+ * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.reg,v 1.20 2000/02/09 21:24:59 gibbs Exp $
+ */
+
+/*
+ * This file is processed by the aic7xxx_asm utility for use in assembling
+ * firmware for the aic7xxx family of SCSI host adapters as well as to generate
+ * a C header file for use in the kernel portion of the Aic7xxx driver.
+ *
+ * All page numbers refer to the Adaptec AIC-7770 Data Book available from
+ * Adaptec's Technical Documents Department 1-800-934-2766
+ */
+
+/*
+ * SCSI Sequence Control (p. 3-11).
+ * Each bit, when set starts a specific SCSI sequence on the bus
+ */
+register SCSISEQ {
+       address                 0x000
+       access_mode RW
+       bit     TEMODE          0x80
+       bit     ENSELO          0x40
+       bit     ENSELI          0x20
+       bit     ENRSELI         0x10
+       bit     ENAUTOATNO      0x08
+       bit     ENAUTOATNI      0x04
+       bit     ENAUTOATNP      0x02
+       bit     SCSIRSTO        0x01
+}
+
+/*
+ * SCSI Transfer Control 0 Register (pp. 3-13).
+ * Controls the SCSI module data path.
+ */
+register SXFRCTL0 {
+       address                 0x001
+       access_mode RW
+       bit     DFON            0x80
+       bit     DFPEXP          0x40
+       bit     FAST20          0x20
+       bit     CLRSTCNT        0x10
+       bit     SPIOEN          0x08
+       bit     SCAMEN          0x04
+       bit     CLRCHN          0x02
+}
+
+/*
+ * SCSI Transfer Control 1 Register (pp. 3-14,15).
+ * Controls the SCSI module data path.
+ */
+register SXFRCTL1 {
+       address                 0x002
+       access_mode RW
+       bit     BITBUCKET       0x80
+       bit     SWRAPEN         0x40
+       bit     ENSPCHK         0x20
+       mask    STIMESEL        0x18
+       bit     ENSTIMER        0x04
+       bit     ACTNEGEN        0x02
+       bit     STPWEN          0x01    /* Powered Termination */
+}
+
+/*
+ * SCSI Control Signal Read Register (p. 3-15).
+ * Reads the actual state of the SCSI bus pins
+ */
+register SCSISIGI {
+       address                 0x003
+       access_mode RO
+       bit     CDI             0x80
+       bit     IOI             0x40
+       bit     MSGI            0x20
+       bit     ATNI            0x10
+       bit     SELI            0x08
+       bit     BSYI            0x04
+       bit     REQI            0x02
+       bit     ACKI            0x01
+/*
+ * Possible phases in SCSISIGI
+ */
+       mask    PHASE_MASK      CDI|IOI|MSGI
+       mask    P_DATAOUT       0x00
+       mask    P_DATAIN        IOI
+       mask    P_COMMAND       CDI
+       mask    P_MESGOUT       CDI|MSGI
+       mask    P_STATUS        CDI|IOI
+       mask    P_MESGIN        CDI|IOI|MSGI
+}
+
+/*
+ * SCSI Control Signal Write Register (p. 3-16).
+ * Writing to this register modifies the control signals on the bus.  Only
+ * those signals that are allowed in the current mode (Initiator/Target) are
+ * asserted.
+ */
+register SCSISIGO {
+       address                 0x003
+       access_mode WO
+       bit     CDO             0x80
+       bit     IOO             0x40
+       bit     MSGO            0x20
+       bit     ATNO            0x10
+       bit     SELO            0x08
+       bit     BSYO            0x04
+       bit     REQO            0x02
+       bit     ACKO            0x01
+/*
+ * Possible phases to write into SCSISIG0
+ */
+       mask    PHASE_MASK      CDI|IOI|MSGI
+       mask    P_DATAOUT       0x00
+       mask    P_DATAIN        IOI
+       mask    P_COMMAND       CDI
+       mask    P_MESGOUT       CDI|MSGI
+       mask    P_STATUS        CDI|IOI
+       mask    P_MESGIN        CDI|IOI|MSGI
+}
+
+/* 
+ * SCSI Rate Control (p. 3-17).
+ * Contents of this register determine the Synchronous SCSI data transfer
+ * rate and the maximum synchronous Req/Ack offset.  An offset of 0 in the
+ * SOFS (3:0) bits disables synchronous data transfers.  Any offset value
+ * greater than 0 enables synchronous transfers.
+ */
+register SCSIRATE {
+       address                 0x004
+       access_mode RW
+       bit     WIDEXFER        0x80            /* Wide transfer control */
+       bit     ENABLE_CRC      0x40            /* CRC for D-Phases */
+       bit     SINGLE_EDGE     0x10            /* Disable DT Transfers */
+       mask    SXFR            0x70            /* Sync transfer rate */
+       mask    SXFR_ULTRA2     0x0f            /* Sync transfer rate */
+       mask    SOFS            0x0f            /* Sync offset */
+}
+
+/*
+ * SCSI ID (p. 3-18).
+ * Contains the ID of the board and the current target on the
+ * selected channel.
+ */
+register SCSIID        {
+       address                 0x005
+       access_mode RW
+       mask    TID             0xf0            /* Target ID mask */
+       mask    OID             0x0f            /* Our ID mask */
+       /*
+        * SCSI Maximum Offset (p. 4-61 aic7890/91 Data Book)
+        * The aic7890/91 allow an offset of up to 127 transfers in both wide
+        * and narrow mode.
+        */
+       alias   SCSIOFFSET
+       mask    SOFS_ULTRA2     0x7f            /* Sync offset U2 chips */
+}
+
+/*
+ * SCSI Latched Data (p. 3-19).
+ * Read/Write latches used to transfer data on the SCSI bus during
+ * Automatic or Manual PIO mode.  SCSIDATH can be used for the
+ * upper byte of a 16bit wide asynchronouse data phase transfer.
+ */
+register SCSIDATL {
+       address                 0x006
+       access_mode RW
+}
+
+register SCSIDATH {
+       address                 0x007
+       access_mode RW
+}
+
+/*
+ * SCSI Transfer Count (pp. 3-19,20)
+ * These registers count down the number of bytes transferred
+ * across the SCSI bus.  The counter is decremented only once
+ * the data has been safely transferred.  SDONE in SSTAT0 is
+ * set when STCNT goes to 0
+ */ 
+register STCNT {
+       address                 0x008
+       size    3
+       access_mode RW
+}
+
+/* ALT_MODE register on Ultra160 chips */
+register OPTIONMODE {
+       address                 0x008
+       access_mode RW
+       bit     AUTORATEEN              0x80
+       bit     AUTOACKEN               0x40
+       bit     ATNMGMNTEN              0x20
+       bit     BUSFREEREV              0x10
+       bit     EXPPHASEDIS             0x08
+       bit     SCSIDATL_IMGEN          0x04
+       bit     AUTO_MSGOUT_DE          0x02
+       bit     DIS_MSGIN_DUALEDGE      0x01
+       mask    OPTIONMODE_DEFAULTS     AUTO_MSGOUT_DE|DIS_MSGIN_DUALEDGE
+}
+
+/* ALT_MODE register on Ultra160 chips */
+register TARGCRCCNT {
+       address                 0x00a
+       size    2
+       access_mode RW
+}
+
+/*
+ * Clear SCSI Interrupt 0 (p. 3-20)
+ * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT0.
+ */
+register CLRSINT0 {
+       address                 0x00b
+       access_mode WO
+       bit     CLRSELDO        0x40
+       bit     CLRSELDI        0x20
+       bit     CLRSELINGO      0x10
+       bit     CLRSWRAP        0x08
+       bit     CLRSPIORDY      0x02
+}
+
+/*
+ * SCSI Status 0 (p. 3-21)
+ * Contains one set of SCSI Interrupt codes
+ * These are most likely of interest to the sequencer
+ */
+register SSTAT0        {
+       address                 0x00b
+       access_mode RO
+       bit     TARGET          0x80    /* Board acting as target */
+       bit     SELDO           0x40    /* Selection Done */
+       bit     SELDI           0x20    /* Board has been selected */
+       bit     SELINGO         0x10    /* Selection In Progress */
+       bit     SWRAP           0x08    /* 24bit counter wrap */
+       bit     IOERR           0x08    /* LVD Tranceiver mode changed */
+       bit     SDONE           0x04    /* STCNT = 0x000000 */
+       bit     SPIORDY         0x02    /* SCSI PIO Ready */
+       bit     DMADONE         0x01    /* DMA transfer completed */
+}
+
+/*
+ * Clear SCSI Interrupt 1 (p. 3-23)
+ * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT1.
+ */
+register CLRSINT1 {
+       address                 0x00c
+       access_mode WO
+       bit     CLRSELTIMEO     0x80
+       bit     CLRATNO         0x40
+       bit     CLRSCSIRSTI     0x20
+       bit     CLRBUSFREE      0x08
+       bit     CLRSCSIPERR     0x04
+       bit     CLRPHASECHG     0x02
+       bit     CLRREQINIT      0x01
+}
+
+/*
+ * SCSI Status 1 (p. 3-24)
+ */
+register SSTAT1        {
+       address                 0x00c
+       access_mode RO
+       bit     SELTO           0x80
+       bit     ATNTARG         0x40
+       bit     SCSIRSTI        0x20
+       bit     PHASEMIS        0x10
+       bit     BUSFREE         0x08
+       bit     SCSIPERR        0x04
+       bit     PHASECHG        0x02
+       bit     REQINIT         0x01
+}
+
+/*
+ * SCSI Status 2 (pp. 3-25,26)
+ */
+register SSTAT2 {
+       address                 0x00d
+       access_mode RO
+       bit     OVERRUN         0x80
+       bit     EXP_ACTIVE      0x10    /* SCSI Expander Active */
+       mask    SFCNT           0x1f
+}
+
+/*
+ * SCSI Status 3 (p. 3-26)
+ */
+register SSTAT3 {
+       address                 0x00e
+       access_mode RO
+       mask    SCSICNT         0xf0
+       mask    OFFCNT          0x0f
+}
+
+/*
+ * SCSI ID for the aic7890/91 chips
+ */
+register SCSIID_ULTRA2 {
+       address                 0x00f
+       access_mode RW
+       mask    TID             0xf0            /* Target ID mask */
+       mask    OID             0x0f            /* Our ID mask */
+}
+
+/*
+ * SCSI Interrupt Mode 1 (p. 3-28)
+ * Setting any bit will enable the corresponding function
+ * in SIMODE0 to interrupt via the IRQ pin.
+ */
+register SIMODE0 {
+       address                 0x010
+       access_mode RW
+       bit     ENSELDO         0x40
+       bit     ENSELDI         0x20
+       bit     ENSELINGO       0x10
+       bit     ENSWRAP         0x08
+       bit     ENIOERR         0x08    /* LVD Tranceiver mode changes */
+       bit     ENSDONE         0x04
+       bit     ENSPIORDY       0x02
+       bit     ENDMADONE       0x01
+}
+
+/*
+ * SCSI Interrupt Mode 1 (pp. 3-28,29)
+ * Setting any bit will enable the corresponding function
+ * in SIMODE1 to interrupt via the IRQ pin.
+ */
+register SIMODE1 {
+       address                 0x011
+       access_mode RW
+       bit     ENSELTIMO       0x80
+       bit     ENATNTARG       0x40
+       bit     ENSCSIRST       0x20
+       bit     ENPHASEMIS      0x10
+       bit     ENBUSFREE       0x08
+       bit     ENSCSIPERR      0x04
+       bit     ENPHASECHG      0x02
+       bit     ENREQINIT       0x01
+}
+
+/*
+ * SCSI Data Bus (High) (p. 3-29)
+ * This register reads data on the SCSI Data bus directly.
+ */
+register SCSIBUSL {
+       address                 0x012
+       access_mode RO
+}
+
+register SCSIBUSH {
+       address                 0x013
+       access_mode RO
+}
+
+/*
+ * SCSI/Host Address (p. 3-30)
+ * These registers hold the host address for the byte about to be
+ * transferred on the SCSI bus.  They are counted up in the same
+ * manner as STCNT is counted down.  SHADDR should always be used
+ * to determine the address of the last byte transferred since HADDR
+ * can be skewed by write ahead.
+ */
+register SHADDR {
+       address                 0x014
+       size    4
+       access_mode RO
+}
+
+/*
+ * Selection Timeout Timer (p. 3-30)
+ */
+register SELTIMER {
+       address                 0x018
+       access_mode RW
+       bit     STAGE6          0x20
+       bit     STAGE5          0x10
+       bit     STAGE4          0x08
+       bit     STAGE3          0x04
+       bit     STAGE2          0x02
+       bit     STAGE1          0x01
+       alias   TARGIDIN
+}
+
+/*
+ * Selection/Reselection ID (p. 3-31)
+ * Upper four bits are the device id.  The ONEBIT is set when the re/selecting
+ * device did not set its own ID.
+ */
+register SELID {
+       address                 0x019
+       access_mode RW
+       mask    SELID_MASK      0xf0
+       bit     ONEBIT          0x08
+}
+
+register SCAMCTL {
+       address                 0x01a
+       access_mode RW
+       bit     ENSCAMSELO      0x80
+       bit     CLRSCAMSELID    0x40
+       bit     ALTSTIM         0x20
+       bit     DFLTTID         0x10
+       mask    SCAMLVL         0x03
+}
+
+/*
+ * Target Mode Selecting in ID bitmask (aic7890/91/96/97)
+ */
+register TARGID {
+       address                 0x01b
+       size                    2
+       access_mode RW
+}
+
+/*
+ * Serial Port I/O Cabability register (p. 4-95 aic7860 Data Book)
+ * Indicates if external logic has been attached to the chip to
+ * perform the tasks of accessing a serial eeprom, testing termination
+ * strength, and performing cable detection.  On the aic7860, most of
+ * these features are handled on chip, but on the aic7855 an attached
+ * aic3800 does the grunt work.
+ */
+register SPIOCAP {
+       address                 0x01b
+       access_mode RW
+       bit     SOFT1           0x80
+       bit     SOFT0           0x40
+       bit     SOFTCMDEN       0x20    
+       bit     HAS_BRDCTL      0x10    /* External Board control */
+       bit     SEEPROM         0x08    /* External serial eeprom logic */
+       bit     EEPROM          0x04    /* Writable external BIOS ROM */
+       bit     ROM             0x02    /* Logic for accessing external ROM */
+       bit     SSPIOCPS        0x01    /* Termination and cable detection */
+}
+
+register BRDCTL        {
+       address                 0x01d
+       bit     BRDDAT7         0x80
+       bit     BRDDAT6         0x40
+       bit     BRDDAT5         0x20
+       bit     BRDSTB          0x10
+       bit     BRDCS           0x08
+       bit     BRDRW           0x04
+       bit     BRDCTL1         0x02
+       bit     BRDCTL0         0x01
+       /* 7890 Definitions */
+       bit     BRDDAT4         0x10
+       bit     BRDDAT3         0x08
+       bit     BRDDAT2         0x04
+       bit     BRDRW_ULTRA2    0x02
+       bit     BRDSTB_ULTRA2   0x01
+}
+
+/*
+ * Serial EEPROM Control (p. 4-92 in 7870 Databook)
+ * Controls the reading and writing of an external serial 1-bit
+ * EEPROM Device.  In order to access the serial EEPROM, you must
+ * first set the SEEMS bit that generates a request to the memory
+ * port for access to the serial EEPROM device.  When the memory
+ * port is not busy servicing another request, it reconfigures
+ * to allow access to the serial EEPROM.  When this happens, SEERDY
+ * gets set high to verify that the memory port access has been
+ * granted.  
+ *
+ * After successful arbitration for the memory port, the SEECS bit of 
+ * the SEECTL register is connected to the chip select.  The SEECK, 
+ * SEEDO, and SEEDI are connected to the clock, data out, and data in 
+ * lines respectively.  The SEERDY bit of SEECTL is useful in that it 
+ * gives us an 800 nsec timer.  After a write to the SEECTL register, 
+ * the SEERDY goes high 800 nsec later.  The one exception to this is 
+ * when we first request access to the memory port.  The SEERDY goes 
+ * high to signify that access has been granted and, for this case, has 
+ * no implied timing.
+ *
+ * See 93cx6.c for detailed information on the protocol necessary to 
+ * read the serial EEPROM.
+ */
+register SEECTL {
+       address                 0x01e
+       bit     EXTARBACK       0x80
+       bit     EXTARBREQ       0x40
+       bit     SEEMS           0x20
+       bit     SEERDY          0x10
+       bit     SEECS           0x08
+       bit     SEECK           0x04
+       bit     SEEDO           0x02
+       bit     SEEDI           0x01
+}
+/*
+ * SCSI Block Control (p. 3-32)
+ * Controls Bus type and channel selection.  In a twin channel configuration
+ * addresses 0x00-0x1e are gated to the appropriate channel based on this
+ * register.  SELWIDE allows for the coexistence of 8bit and 16bit devices
+ * on a wide bus.
+ */
+register SBLKCTL {
+       address                 0x01f
+       access_mode RW
+       bit     DIAGLEDEN       0x80    /* Aic78X0 only */
+       bit     DIAGLEDON       0x40    /* Aic78X0 only */
+       bit     AUTOFLUSHDIS    0x20
+       bit     SELBUSB         0x08
+       bit     ENAB40          0x08    /* LVD transceiver active */
+       bit     ENAB20          0x04    /* SE/HVD transceiver active */
+       bit     SELWIDE         0x02
+       bit     XCVR            0x01    /* External transceiver active */
+}
+
+/*
+ * Sequencer Control (p. 3-33)
+ * Error detection mode and speed configuration
+ */
+register SEQCTL {
+       address                 0x060
+       access_mode RW
+       bit     PERRORDIS       0x80
+       bit     PAUSEDIS        0x40
+       bit     FAILDIS         0x20
+       bit     FASTMODE        0x10
+       bit     BRKADRINTEN     0x08
+       bit     STEP            0x04
+       bit     SEQRESET        0x02
+       bit     LOADRAM         0x01
+}
+
+/*
+ * Sequencer RAM Data (p. 3-34)
+ * Single byte window into the Scratch Ram area starting at the address
+ * specified by SEQADDR0 and SEQADDR1.  To write a full word, simply write
+ * four bytes in succession.  The SEQADDRs will increment after the most
+ * significant byte is written
+ */
+register SEQRAM {
+       address                 0x061
+       access_mode RW
+}
+
+/*
+ * Sequencer Address Registers (p. 3-35)
+ * Only the first bit of SEQADDR1 holds addressing information
+ */
+register SEQADDR0 {
+       address                 0x062
+       access_mode RW
+}
+
+register SEQADDR1 {
+       address                 0x063
+       access_mode RW
+       mask    SEQADDR1_MASK   0x01
+}
+
+/*
+ * Accumulator
+ * We cheat by passing arguments in the Accumulator up to the kernel driver
+ */
+register ACCUM {
+       address                 0x064
+       access_mode RW
+       accumulator
+}
+
+register SINDEX        {
+       address                 0x065
+       access_mode RW
+       sindex
+}
+
+register DINDEX {
+       address                 0x066
+       access_mode RW
+}
+
+register ALLONES {
+       address                 0x069
+       access_mode RO
+       allones
+}
+
+register ALLZEROS {
+       address                 0x06a
+       access_mode RO
+       allzeros
+}
+
+register NONE {
+       address                 0x06a
+       access_mode WO
+       none
+}
+
+register FLAGS {
+       address                 0x06b
+       access_mode RO
+       bit     ZERO            0x02
+       bit     CARRY           0x01
+}
+
+register SINDIR        {
+       address                 0x06c
+       access_mode RO
+}
+
+register DINDIR         {
+       address                 0x06d
+       access_mode WO
+}
+
+register FUNCTION1 {
+       address                 0x06e
+       access_mode RW
+}
+
+register STACK {
+       address                 0x06f
+       access_mode RO
+}
+
+/*
+ * Board Control (p. 3-43)
+ */
+register BCTL {
+       address                 0x084
+       access_mode RW
+       bit     ACE             0x08
+       bit     ENABLE          0x01
+}
+
+/*
+ * On the aic78X0 chips, Board Control is replaced by the DSCommand
+ * register (p. 4-64)
+ */
+register DSCOMMAND0 {
+       address                 0x084
+       access_mode RW
+       bit     CACHETHEN       0x80    /* Cache Threshold enable */
+       bit     DPARCKEN        0x40    /* Data Parity Check Enable */
+       bit     MPARCKEN        0x20    /* Memory Parity Check Enable */
+       bit     EXTREQLCK       0x10    /* External Request Lock */
+       /* aic7890/91/96/97 only */
+       bit     INTSCBRAMSEL    0x08    /* Internal SCB RAM Select */
+       bit     RAMPS           0x04    /* External SCB RAM Present */
+       bit     USCBSIZE32      0x02    /* Use 32byte SCB Page Size */
+       bit     CIOPARCKEN      0x01    /* Internal bus parity error enable */
+}
+
+/*
+ * Bus On/Off Time (p. 3-44)
+ */
+register BUSTIME {
+       address                 0x085
+       access_mode RW
+       mask    BOFF            0xf0
+       mask    BON             0x0f
+}
+
+/*
+ * Bus Speed (p. 3-45) aic7770 only
+ */
+register BUSSPD {
+       address                 0x086
+       access_mode RW
+       mask    DFTHRSH         0xc0
+       mask    STBOFF          0x38
+       mask    STBON           0x07
+       mask    DFTHRSH_100     0xc0
+}
+
+/* aic7850/55/60/70/80/95 only */
+register DSPCISTATUS {
+       address                 0x086
+       mask    DFTHRSH_100     0xc0
+}
+
+/* aic7890/91/96/97 only */
+register HS_MAILBOX {
+       address                 0x086
+       mask    HOST_MAILBOX    0xF0
+       mask    SEQ_MAILBOX     0x0F
+}
+
+const  HOST_MAILBOX_SHIFT      4
+const  SEQ_MAILBOX_SHIFT       0
+
+/*
+ * Host Control (p. 3-47) R/W
+ * Overall host control of the device.
+ */
+register HCNTRL {
+       address                 0x087
+       access_mode RW
+       bit     POWRDN          0x40
+       bit     SWINT           0x10
+       bit     IRQMS           0x08
+       bit     PAUSE           0x04
+       bit     INTEN           0x02
+       bit     CHIPRST         0x01
+       bit     CHIPRSTACK      0x01
+}
+
+/*
+ * Host Address (p. 3-48)
+ * This register contains the address of the byte about
+ * to be transferred across the host bus.
+ */
+register HADDR {
+       address                 0x088
+       size    4
+       access_mode RW
+}
+
+register HCNT {
+       address                 0x08c
+       size    3
+       access_mode RW
+}
+
+/*
+ * SCB Pointer (p. 3-49)
+ * Gate one of the four SCBs into the SCBARRAY window.
+ */
+register SCBPTR {
+       address                 0x090
+       access_mode RW
+}
+
+/*
+ * Interrupt Status (p. 3-50)
+ * Status for system interrupts
+ */
+register INTSTAT {
+       address                 0x091
+       access_mode RW
+       bit     BRKADRINT 0x08
+       bit     SCSIINT   0x04
+       bit     CMDCMPLT  0x02
+       bit     SEQINT    0x01
+       mask    BAD_PHASE       SEQINT          /* unknown scsi bus phase */
+       mask    SEND_REJECT     0x10|SEQINT     /* sending a message reject */
+       mask    NO_IDENT        0x20|SEQINT     /* no IDENTIFY after reconnect*/
+       mask    NO_MATCH        0x30|SEQINT     /* no cmd match for reconnect */
+       mask    UPDATE_TMSG_REQ 0x60|SEQINT     /* Update TMSG_REQ values */
+       mask    BAD_STATUS      0x70|SEQINT     /* Bad status from target */
+       mask    RESIDUAL        0x80|SEQINT     /* Residual byte count != 0 */
+       mask    TRACE_POINT     0x90|SEQINT
+       mask    HOST_MSG_LOOP   0xa0|SEQINT     /*
+                                                * The bus is ready for the
+                                                * host to perform another
+                                                * message transaction.  This
+                                                * mechanism is used for things
+                                                * like sync/wide negotiation
+                                                * that require a kernel based
+                                                * message state engine.
+                                                */
+       mask    PERR_DETECTED   0xb0|SEQINT     /*
+                                                * Either the phase_lock
+                                                * or inb_next routine has
+                                                * noticed a parity error.
+                                                */
+       mask    TRACEPOINT      0xd0|SEQINT
+       mask    MSGIN_PHASEMIS  0xe0|SEQINT     /*
+                                                * Target changed phase on us
+                                                * when we were expecting
+                                                * another msgin byte.
+                                                */
+       mask    DATA_OVERRUN    0xf0|SEQINT     /*
+                                                * Target attempted to write
+                                                * beyond the bounds of its
+                                                * command.
+                                                */
+
+       mask    SEQINT_MASK     0xf0|SEQINT     /* SEQINT Status Codes */
+       mask    INT_PEND  (BRKADRINT|SEQINT|SCSIINT|CMDCMPLT)
+}
+
+/*
+ * Hard Error (p. 3-53)
+ * Reporting of catastrophic errors.  You usually cannot recover from
+ * these without a full board reset.
+ */
+register ERROR {
+       address                 0x092
+       access_mode RO
+       bit     CIOPARERR       0x80    /* Ultra2 only */
+       bit     PCIERRSTAT      0x40    /* PCI only */
+       bit     MPARERR         0x20    /* PCI only */
+       bit     DPARERR         0x10    /* PCI only */
+       bit     SQPARERR        0x08
+       bit     ILLOPCODE       0x04
+       bit     ILLSADDR        0x02
+       bit     ILLHADDR        0x01
+}
+
+/*
+ * Clear Interrupt Status (p. 3-52)
+ */
+register CLRINT {
+       address                 0x092
+       access_mode WO
+       bit     CLRPARERR       0x10    /* PCI only */
+       bit     CLRBRKADRINT    0x08
+       bit     CLRSCSIINT      0x04
+       bit     CLRCMDINT       0x02
+       bit     CLRSEQINT       0x01
+}
+
+register DFCNTRL {
+       address                 0x093
+       access_mode RW
+       bit     PRELOADEN       0x80    /* aic7890 only */
+       bit     WIDEODD         0x40
+       bit     SCSIEN          0x20
+       bit     SDMAEN          0x10
+       bit     SDMAENACK       0x10
+       bit     HDMAEN          0x08
+       bit     HDMAENACK       0x08
+       bit     DIRECTION       0x04
+       bit     FIFOFLUSH       0x02
+       bit     FIFORESET       0x01
+}
+
+register DFSTATUS {
+       address                 0x094
+       access_mode RO
+       bit     PRELOAD_AVAIL   0x80
+       bit     DWORDEMP        0x20
+       bit     MREQPEND        0x10
+       bit     HDONE           0x08
+       bit     DFTHRESH        0x04
+       bit     FIFOFULL        0x02
+       bit     FIFOEMP         0x01
+}
+
+register DFWADDR {
+       address                 0x95
+       access_mode RW
+}
+
+register DFRADDR {
+       address                 0x97
+       access_mode RW
+}
+
+register DFDAT {
+       address                 0x099
+       access_mode RW
+}
+
+/*
+ * SCB Auto Increment (p. 3-59)
+ * Byte offset into the SCB Array and an optional bit to allow auto
+ * incrementing of the address during download and upload operations
+ */
+register SCBCNT {
+       address                 0x09a
+       access_mode RW
+       bit     SCBAUTO         0x80
+       mask    SCBCNT_MASK     0x1f
+}
+
+/*
+ * Queue In FIFO (p. 3-60)
+ * Input queue for queued SCBs (commands that the seqencer has yet to start)
+ */
+register QINFIFO {
+       address                 0x09b
+       access_mode RW
+}
+
+/*
+ * Queue In Count (p. 3-60)
+ * Number of queued SCBs
+ */
+register QINCNT        {
+       address                 0x09c
+       access_mode RO
+}
+
+/*
+ * Queue Out FIFO (p. 3-61)
+ * Queue of SCBs that have completed and await the host
+ */
+register QOUTFIFO {
+       address                 0x09d
+       access_mode WO
+}
+
+register CRCCONTROL1 {
+       address                 0x09d
+       access_mode RW
+       bit     CRCONSEEN               0x80
+       bit     CRCVALCHKEN             0x40
+       bit     CRCENDCHKEN             0x20
+       bit     CRCREQCHKEN             0x10
+       bit     TARGCRCENDEN            0x08
+       bit     TARGCRCCNTEN            0x04
+}
+
+
+/*
+ * Queue Out Count (p. 3-61)
+ * Number of queued SCBs in the Out FIFO
+ */
+register QOUTCNT {
+       address                 0x09e
+       access_mode RO
+}
+
+register SCSIPHASE {
+       address                 0x09e
+       access_mode RO
+       bit     STATUS_PHASE    0x20
+       bit     COMMAND_PHASE   0x10
+       bit     MSG_IN_PHASE    0x08
+       bit     MSG_OUT_PHASE   0x04
+       bit     DATA_IN_PHASE   0x02
+       bit     DATA_OUT_PHASE  0x01
+}
+
+/*
+ * Special Function
+ */
+register SFUNCT {
+       address                 0x09f
+       access_mode RW
+       bit     ALT_MODE        0x80
+}
+
+/*
+ * SCB Definition (p. 5-4)
+ */
+scb {
+       address                 0x0a0
+       SCB_CONTROL {
+               size    1
+               bit     TARGET_SCB      0x80
+               bit     DISCENB         0x40
+               bit     TAG_ENB         0x20
+               bit     MK_MESSAGE      0x10
+               bit     ULTRAENB        0x08
+               bit     DISCONNECTED    0x04
+               mask    SCB_TAG_TYPE    0x03
+       }
+       SCB_TCL {
+               size    1
+               bit     SELBUSB         0x08
+               mask    TID             0xf0
+               mask    LID             0x07
+       }
+       SCB_TARGET_STATUS {
+               size    1
+       }
+       SCB_SGCOUNT {
+               size    1
+       }
+       SCB_SGPTR {
+               size    4
+       }
+       SCB_RESID_SGCNT {
+               size    1
+       }
+       SCB_RESID_DCNT  {
+               size    3
+       }
+       SCB_DATAPTR {
+               size    4
+       }
+       SCB_DATACNT {
+               /*
+                * Really only 3 bytes, but padded to make
+                * the kernel's job easier.
+                */
+               size    4
+       }
+       SCB_CMDPTR {
+               alias   SCB_TARGET_PHASES
+               bit     TARGET_DATA_IN  0x1     /* In the second byte */
+               size    4
+       }
+       SCB_CMDLEN {
+               alias   SCB_INITIATOR_TAG
+               size    1
+       }
+       SCB_TAG {
+               size    1
+       }
+       SCB_NEXT {
+               size    1
+       }
+       SCB_SCSIRATE {
+               size    1
+       }
+       SCB_SCSIOFFSET {
+               size    1
+       }
+       SCB_SPARE       {
+               size    3
+       }
+       SCB_CMDSTORE    {
+               size    16
+       }
+       SCB_CMDSTORE_BUSADDR {
+               size    4
+       }
+       SCB_64BYTE_SPARE {
+               size    12
+       }
+}
+
+const  SCB_32BYTE_SIZE 28
+const  SCB_64BYTE_SIZE 48
+
+const  SG_SIZEOF       0x08            /* sizeof(struct ahc_dma) */
+
+/* --------------------- AHA-2840-only definitions -------------------- */
+
+register SEECTL_2840 {
+       address                 0x0c0
+       access_mode RW
+       bit     CS_2840         0x04
+       bit     CK_2840         0x02
+       bit     DO_2840         0x01
+}
+
+register STATUS_2840 {
+       address                 0x0c1
+       access_mode RW
+       bit     EEPROM_TF       0x80
+       mask    BIOS_SEL        0x60
+       mask    ADSEL           0x1e
+       bit     DI_2840         0x01
+}
+
+/* --------------------- AIC-7870-only definitions -------------------- */
+
+register CCHADDR {
+       address                 0x0E0
+       size 8
+}
+
+register CCHCNT {
+       address                 0x0E8
+}
+
+register CCSGRAM {
+       address                 0x0E9
+}
+
+register CCSGADDR {
+       address                 0x0EA
+}
+
+register CCSGCTL {
+       address                 0x0EB
+       bit     CCSGDONE        0x80
+       bit     CCSGEN          0x08
+       bit     FLAG            0x02
+       bit     CCSGRESET       0x01
+}
+
+register CCSCBCNT {
+       address                 0xEF
+}
+
+register CCSCBCTL {
+       address                 0x0EE
+       bit     CCSCBDONE       0x80
+       bit     ARRDONE         0x40    /* SCB Array prefetch done */
+       bit     CCARREN         0x10
+       bit     CCSCBEN         0x08
+       bit     CCSCBDIR        0x04
+       bit     CCSCBRESET      0x01
+}
+
+register CCSCBADDR {
+       address                 0x0ED
+}
+
+register CCSCBRAM {
+       address                 0xEC
+}
+
+/*
+ * SCB bank address (7895/7896/97 only)
+ */
+register SCBBADDR {
+       address                 0x0F0
+       access_mode RW
+}
+
+register CCSCBPTR {
+       address                 0x0F1
+}
+
+register HNSCB_QOFF {
+       address                 0x0F4
+}
+
+register SNSCB_QOFF {
+       address                 0x0F6
+}
+
+register SDSCB_QOFF {
+       address                 0x0F8
+}
+
+register QOFF_CTLSTA {
+       address                 0x0FA
+       bit     SCB_AVAIL       0x40
+       bit     SNSCB_ROLLOVER  0x20
+       bit     SDSCB_ROLLOVER  0x10
+       mask    SCB_QSIZE       0x07
+       mask    SCB_QSIZE_256   0x06
+}
+
+register DFF_THRSH {
+       address                 0x0FB
+       mask    WR_DFTHRSH      0x70
+       mask    RD_DFTHRSH      0x07
+       mask    RD_DFTHRSH_MIN  0x00
+       mask    RD_DFTHRSH_25   0x01
+       mask    RD_DFTHRSH_50   0x02
+       mask    RD_DFTHRSH_63   0x03
+       mask    RD_DFTHRSH_75   0x04
+       mask    RD_DFTHRSH_85   0x05
+       mask    RD_DFTHRSH_90   0x06
+       mask    RD_DFTHRSH_MAX  0x07
+       mask    WR_DFTHRSH_MIN  0x00
+       mask    WR_DFTHRSH_25   0x10
+       mask    WR_DFTHRSH_50   0x20
+       mask    WR_DFTHRSH_63   0x30
+       mask    WR_DFTHRSH_75   0x40
+       mask    WR_DFTHRSH_85   0x50
+       mask    WR_DFTHRSH_90   0x60
+       mask    WR_DFTHRSH_MAX  0x70
+}
+
+register SG_CACHEPTR {
+       access_mode RW
+       address                 0x0fc
+       mask    SG_USER_DATA    0xfc
+       bit     LAST_SEG        0x02
+       bit     LAST_SEG_DONE   0x01
+}
+
+/* ---------------------- Scratch RAM Offsets ------------------------- */
+/* These offsets are either to values that are initialized by the board's
+ * BIOS or are specified by the sequencer code.
+ *
+ * The host adapter card (at least the BIOS) uses 20-2f for SCSI
+ * device information, 32-33 and 5a-5f as well. As it turns out, the
+ * BIOS trashes 20-2f, writing the synchronous negotiation results
+ * on top of the BIOS values, so we re-use those for our per-target
+ * scratchspace (actually a value that can be copied directly into
+ * SCSIRATE).  The kernel driver will enable synchronous negotiation
+ * for all targets that have a value other than 0 in the lower four
+ * bits of the target scratch space.  This should work regardless of
+ * whether the bios has been installed.
+ */
+
+scratch_ram {
+       address                 0x020
+
+       /*
+        * 1 byte per target starting at this address for configuration values
+        */
+       TARG_SCSIRATE {
+               alias           CMDSIZE_TABLE
+               size            16
+       }
+       /*
+        * Bit vector of targets that have ULTRA enabled.
+        */
+       ULTRA_ENB {
+               size            2
+       }
+       /*
+        * Bit vector of targets that have disconnection disabled.
+        */
+       DISC_DSB {
+               size            2
+       }
+       /*
+        * Single byte buffer used to designate the type or message
+        * to send to a target.
+        */
+       MSG_OUT {
+               size            1
+       }
+       /* Parameters for DMA Logic */
+       DMAPARAMS {
+               size            1
+               bit     PRELOADEN       0x80
+               bit     WIDEODD         0x40
+               bit     SCSIEN          0x20
+               bit     SDMAEN          0x10
+               bit     SDMAENACK       0x10
+               bit     HDMAEN          0x08
+               bit     HDMAENACK       0x08
+               bit     DIRECTION       0x04
+               bit     FIFOFLUSH       0x02
+               bit     FIFORESET       0x01
+       }
+       SEQ_FLAGS {
+               size            1
+               bit     IDENTIFY_SEEN           0x80
+               bit     SCBPTR_VALID            0x40
+               bit     DPHASE                  0x20
+               /* Target flags */
+               bit     TARG_CMD_PENDING        0x10
+               bit     CMDPHASE_PENDING        0x08
+               bit     DPHASE_PENDING          0x04
+               bit     SPHASE_PENDING          0x02
+               bit     NO_DISCONNECT           0x01
+       }
+       /*
+        * Temporary storage for the
+        * target/channel/lun of a
+        * reconnecting target
+        */
+       SAVED_TCL {
+               size            1
+       }
+       /* Working value of the number of SG segments left */
+       SG_COUNT {
+               size            1
+       }
+       /* Working value of SG pointer */
+       SG_NEXT {
+               size            4
+       }
+       /*
+        * The last bus phase as seen by the sequencer. 
+        */
+       LASTPHASE {
+               size            1
+               bit     CDI             0x80
+               bit     IOI             0x40
+               bit     MSGI            0x20
+               mask    PHASE_MASK      CDI|IOI|MSGI
+               mask    P_DATAOUT       0x00
+               mask    P_DATAIN        IOI
+               mask    P_COMMAND       CDI
+               mask    P_MESGOUT       CDI|MSGI
+               mask    P_STATUS        CDI|IOI
+               mask    P_MESGIN        CDI|IOI|MSGI
+               mask    P_BUSFREE       0x01
+       }
+       /*
+        * head of list of SCBs awaiting
+        * selection
+        */
+       WAITING_SCBH {
+               size            1
+       }
+       /*
+        * head of list of SCBs that are
+        * disconnected.  Used for SCB
+        * paging.
+        */
+       DISCONNECTED_SCBH {
+               size            1
+       }
+       /*
+        * head of list of SCBs that are
+        * not in use.  Used for SCB paging.
+        */
+       FREE_SCBH {
+               size            1
+       }
+       /*
+        * Address of the hardware scb array in the host.
+        */
+       HSCB_ADDR {
+               size            4
+       }
+       /*
+        * Address of the 256 byte array storing the SCBID of outstanding
+        * untagged SCBs indexed by TCL.
+        */
+       SCBID_ADDR {
+               size            4
+       }
+       /*
+        * Address of the array of command descriptors used to store
+        * information about incoming selections.
+        */
+       TMODE_CMDADDR {
+               size            4
+       }
+       KERNEL_QINPOS {
+               size            1
+       }
+       QINPOS {
+               size            1
+       }
+       QOUTPOS {
+               size            1
+       }
+       /*
+        * Kernel and sequencer offsets into the queue of
+        * incoming target mode command descriptors.  The
+        * queue is full when the KERNEL_TQINPOS == TQINPOS.
+        */
+       KERNEL_TQINPOS {
+               size            1
+       }
+       TQINPOS {                
+               size            1
+       }
+       ARG_1 {
+               size            1
+               mask    SEND_MSG                0x80
+               mask    SEND_SENSE              0x40
+               mask    SEND_REJ                0x20
+               mask    MSGOUT_PHASEMIS         0x10
+               mask    EXIT_MSG_LOOP           0x08
+               mask    CONT_MSG_LOOP           0x04
+               mask    CONT_TARG_SESSION       0x02
+               alias   RETURN_1
+       }
+       ARG_2 {
+               size            1
+               alias   RETURN_2
+       }
+
+       /*
+        * Snapshot of MSG_OUT taken after each message is sent.
+        */
+       LAST_MSG {
+               size            1
+       }
+
+       /*
+        * Number of times we have filled the CCSGRAM with prefetched
+        * SG elements.
+        */
+       PREFETCH_CNT {
+               size            1
+       }
+
+       /*
+        * Interrupt kernel for a message to this target on
+        * the next transaction.  This is usually used for
+        * negotiation requests.
+        */
+       TARGET_MSG_REQUEST {
+               size            2
+       }
+
+       /*
+        * Sequences the kernel driver has okayed for us.  This allows
+        * the driver to do things like prevent initiator or target
+        * operations.
+        */
+       SCSISEQ_TEMPLATE {
+               size            1
+               bit     ENSELO          0x40
+               bit     ENSELI          0x20
+               bit     ENRSELI         0x10
+               bit     ENAUTOATNO      0x08
+               bit     ENAUTOATNI      0x04
+               bit     ENAUTOATNP      0x02
+       }
+
+       /*
+        * Track whether the transfer byte count for
+        * the current data phase is odd.
+        */
+       DATA_COUNT_ODD {
+               size            1
+       }
+
+       /*
+        * The initiator specified tag for this target mode transaction.
+        */
+       INITIATOR_TAG {
+               size            1
+       }
+
+       /*
+        * These are reserved registers in the card's scratch ram.  Some of
+        * the values are specified in the AHA2742 technical reference manual
+        * and are initialized by the BIOS at boot time.
+        */
+       SCSICONF {
+               address         0x05a
+               size            1
+               bit     TERM_ENB        0x80
+               bit     RESET_SCSI      0x40
+               bit     ENSPCHK         0x20
+               mask    HSCSIID         0x07    /* our SCSI ID */
+               mask    HWSCSIID        0x0f    /* our SCSI ID if Wide Bus */
+       }
+       HOSTCONF {
+               address         0x05d
+               size            1
+       }
+       HA_274_BIOSCTRL {
+               address         0x05f
+               size            1
+               mask    BIOSMODE                0x30
+               mask    BIOSDISABLED            0x30    
+               bit     CHANNEL_B_PRIMARY       0x08
+       }
+       /*
+        * Per target SCSI offset values for Ultra2 controllers.
+        */
+       TARG_OFFSET {
+               address         0x070
+               size            16
+       }
+}
+
+const SCB_LIST_NULL    0xff
+const TARGET_CMD_CMPLT 0xfe
+
+const CCSGADDR_MAX     0x80
+const CCSGRAM_MAXSEGS  16
+
+/* Offsets into the SCBID array where different data is stored */
+const QOUTFIFO_OFFSET          0
+const QINFIFO_OFFSET           1
+const UNTAGGEDSCB_OFFSET       2
+
+/* WDTR Message values */
+const BUS_8_BIT                        0x00
+const BUS_16_BIT               0x01
+const BUS_32_BIT               0x02
+
+/* Offset maximums */
+const MAX_OFFSET_8BIT          0x0f
+const MAX_OFFSET_16BIT         0x08
+const MAX_OFFSET_ULTRA2                0x7f
+const HOST_MSG                 0xff
+
+/* Target mode command processing constants */
+const CMD_GROUP_CODE_SHIFT     0x05
+
+const TCL_TARGET_SHIFT         4
+/* The update interval must be a power of 2 */
+const TQINFIFO_UPDATE_CNT      32
+
+const STATUS_BUSY              0x08
+const STATUS_QUEUE_FULL                0x28
+
+/*
+ * Downloaded (kernel inserted) constants
+ */
+
+/*
+ * Number of command descriptors in the command descriptor array.
+ * No longer used, but left here as an example for how downloaded
+ * constantants can be defined.
+const TMODE_NUMCMDS    download
+ */
index 97c3f61..6f5210b 100644 (file)
@@ -1,71 +1,45 @@
-/*     $OpenBSD: aic7xxx.seq,v 1.6 1996/12/03 11:28:32 niklas Exp $    */
-/*     $NetBSD: aic7xxx.seq,v 1.6 1996/10/08 03:04:06 gibbs Exp $      */
-
-/*+M***********************************************************************
- *Adaptec 274x/284x/294x device driver for Linux and FreeBSD.
- *
- *Copyright (c) 1994 John Aycock
- *  The University of Calgary Department of Computer Science.
- *  All rights reserved.
+/*
+ * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD.
  *
- *FreeBSD, Twin, Wide, 2 command per target support, tagged queuing,
- *SCB paging and other optimizations:
- *Copyright (c) 1994, 1995, 1996 Justin Gibbs. All rights reserved.
+ * Copyright (c) 1994-2000 Justin Gibbs.
+ * All rights reserved.
  *
- *Redistribution and use in source and binary forms, with or without
- *modification, are permitted provided that the following conditions
- *are met:
- *1. Redistributions of source code must retain the above copyright
- *   notice, this list of conditions, and the following disclaimer.
- *2. Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *3. All advertising materials mentioning features or use of this software
- *   must display the following acknowledgement:
- *     This product includes software developed by the University of Calgary
- *     Department of Computer Science and its contributors.
- *4. Neither the name of the University nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
  *
- *THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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.
+ * Alternatively, this software may be distributed under the terms of the
+ * the GNU Public License ("GPL").
  *
- * from        Id: aic7xxx.seq,v 1.42 1996/06/09 17:29:11 gibbs Exp
+ * 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.
  *
- *-M************************************************************************/
-
-VERSION AIC7XXX_SEQ_VER "$NetBSD: aic7xxx.seq,v 1.6 1996/10/08 03:04:06 gibbs Exp $"
+ * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.seq,v 1.93 2000/01/07 23:08:20 gibbs Exp $
+ */
 
-#if defined(__OpenBSD__)
-#include <dev/ic/aic7xxxreg.h>
+#include <dev/microcode/aic7xxx/aic7xxx.reg>
 #include <scsi/scsi_message.h>
-#elif defined(__NetBSD__)
-#include "../../ic/aic7xxxreg.h"
-#include "../../../scsi/scsi_message.h"
-#elif defined(__FreeBSD__)
-#include "../../dev/aic7xxx/aic7xxx_reg.h"
-#include "../../scsi/scsi_message.h"
-#endif
-
 /*
- * We can't just use ACCUM in the sequencer code because it
- * must be treated specially by the assembler, and it currently
- * looks for the symbol 'A'.  This is the only register defined in
- * the assembler's symbol space.
- */
-A = ACCUM
+#include <cam/scsi/scsi_message.h>
+*/
 
-/* After starting the selection hardware, we check for reconnecting targets
+/*
+ * A few words on the waiting SCB list:
+ * After starting the selection hardware, we check for reconnecting targets
  * as well as for our selection to complete just in case the reselection wins
  * bus arbitration.  The problem with this is that we must keep track of the
  * SCB that we've already pulled from the QINFIFO and started the selection
@@ -74,311 +48,762 @@ A = ACCUM
  * in scratch ram since a reconnecting target can request sense and this will
  * create yet another SCB waiting for selection.  The solution used here is to 
  * use byte 27 of the SCB as a psuedo-next pointer and to thread a list
- * of SCBs that are awaiting selection.  Since 0-0xfe are valid SCB offsets, 
- * SCB_LIST_NULL is 0xff which is out of range.  The kernel driver must
- * add an entry to this list everytime a request sense occurs.  The sequencer
- * will automatically consume the entries.
+ * of SCBs that are awaiting selection.  Since 0-0xfe are valid SCB indexes, 
+ * SCB_LIST_NULL is 0xff which is out of range.  An entry is also added to
+ * this list everytime a request sense occurs or after completing a non-tagged
+ * command for which a second SCB has been queued.  The sequencer will
+ * automatically consume the entries.
  */
 
-/*
- * We assume that the kernel driver may reset us at any time, even in the
- * middle of a DMA, so clear DFCNTRL too.
- */
 reset:
-       clr     DFCNTRL
-       clr     SCSISIGO                /* De-assert BSY */
-/*
- * We jump to start after every bus free.
- */
-start:
-       and     FLAGS,0x0f              /* clear target specific flags */
-       mvi     SCSISEQ,ENRSELI         /* Always allow reselection */
-       clr     SCSIRATE                /*
-                                        * We don't know the target we will
-                                        * connect to, so default to narrow
-                                        * transfers to avoid parity problems.
-                                        */
+       clr     SCSISIGO;               /* De-assert BSY */
+       mvi     MSG_OUT, MSG_NOOP;      /* No message to send */
+       and     SXFRCTL1, ~BITBUCKET;
+       /* Always allow reselection */
+       and     SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ_TEMPLATE;
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               /* Ensure that no DMA operations are in progress */
+               clr     CCSGCTL;
+               clr     CCSCBCTL;
+       }
+
 poll_for_work:
-       /*
-        * Are we a twin channel device?
-        * For fairness, we check the other bus first,
-        * since we just finished a transaction on the
-        * current channel.
-        */
-       test    FLAGS,TWIN_BUS  jz start2
-       xor     SBLKCTL,SELBUSB                 /* Toggle to the other bus */
-       test    SSTAT0,SELDI    jnz reselect
-       xor     SBLKCTL,SELBUSB                 /* Toggle to the original bus */
-start2:
-       test    SSTAT0,SELDI    jnz reselect
-       cmp     WAITING_SCBH,SCB_LIST_NULL jne start_waiting
-       mov     A, QCNTMASK
-       test    QINCNT,A        jz poll_for_work
+       call    clear_target_state;
+       and     SXFRCTL0, ~SPIOEN;
+       if ((ahc->features & AHC_QUEUE_REGS) == 0) {
+               mov     A, QINPOS;
+       }
+poll_for_work_loop:
+       if ((ahc->features & AHC_QUEUE_REGS) == 0) {
+               and     SEQCTL, ~PAUSEDIS;
+       }
+       test    SSTAT0, SELDO|SELDI     jnz selection;
+       test    SCSISEQ, ENSELO jnz poll_for_work;
+       if ((ahc->features & AHC_TWIN) != 0) {
+               /*
+                * Twin channel devices cannot handle things like SELTO
+                * interrupts on the "background" channel.  So, if we
+                * are selecting, keep polling the current channel util
+                * either a selection or reselection occurs.
+                */
+               xor     SBLKCTL,SELBUSB;        /* Toggle to the other bus */
+               test    SSTAT0, SELDO|SELDI     jnz selection;
+               test    SCSISEQ, ENSELO jnz poll_for_work;
+               xor     SBLKCTL,SELBUSB;        /* Toggle back */
+       }
+       cmp     WAITING_SCBH,SCB_LIST_NULL jne start_waiting;
+test_queue:
+       /* Has the driver posted any work for us? */
+       if ((ahc->features & AHC_QUEUE_REGS) != 0) {
+               test    QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;
+               mov     NONE, SNSCB_QOFF;
+               inc     QINPOS;
+       } else {
+               or      SEQCTL, PAUSEDIS;
+               cmp     KERNEL_QINPOS, A je poll_for_work_loop;
+               inc     QINPOS;
+               and     SEQCTL, ~PAUSEDIS;
+       }
 
 /*
  * We have at least one queued SCB now and we don't have any 
- * SCBs in the list of SCBs awaiting selection.  Set the SCB
- * pointer from the FIFO so we see the right bank of SCB 
- * registers.
+ * SCBs in the list of SCBs awaiting selection.  If we have
+ * any SCBs available for use, pull the tag from the QINFIFO
+ * and get to work on it.
  */
-       mov     SCBPTR,QINFIFO
+       if ((ahc->flags & AHC_PAGESCBS) != 0) {
+               mov     ALLZEROS        call    get_free_or_disc_scb;
+       }
 
+dequeue_scb:
+       add     A, -1, QINPOS;
+       mvi     QINFIFO_OFFSET call fetch_byte;
+
+       if ((ahc->flags & AHC_PAGESCBS) == 0) {
+               /* In the non-paging case, the SCBID == hardware SCB index */
+               mov     SCBPTR, RETURN_2;
+       }
+dma_queued_scb:
 /*
- * See if there is not already an active SCB for this target.  This code
- * locks out on a per target basis instead of target/lun.  Although this
- * is not ideal for devices that have multiple luns active at the same
- * time, it is faster than looping through all SCB's looking for active
- * commands.  It may be benificial to make findscb a more general procedure
- * to see if the added cost of the search is negligible.  This code also 
- * assumes that the kernel driver will clear the active flags on board 
- * initialization, board reset, and a target SELTO.  Tagged commands
- * don't set the active bits since you can queue more than one command
- * at a time.  We do, however, look to see if there are any non-tagged
- * I/Os in progress, and requeue the command if there are.  Tagged and
- * non-tagged commands cannot be mixed to a single target.
+ * DMA the SCB from host ram into the current SCB location.
  */
-
-test_busy:
-       mov     FUNCTION1,SCB_TCL
-       mov     A,FUNCTION1
-       test    SCB_TCL,0x88    jz test_a       /* Id < 8 && A channel */
-
-       test    ACTIVE_B,A      jnz requeue
-       test    SCB_CONTROL,TAG_ENB     jnz start_scb
-       /* Mark the current target as busy */
-       or      ACTIVE_B,A
-       jmp     start_scb
-
-/* Place the currently active SCB back on the queue for later processing */
-requeue:
-       mov     QINFIFO, SCBPTR
-       jmp     poll_for_work
+       mvi     DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
+       mov     RETURN_2         call dma_scb;
 
 /*
- * Pull the first entry off of the waiting for selection list
- * We don't have to "test_busy" because only transactions that
- * have passed that test can be in the waiting_scb list.
+ * Preset the residual fields in case we never go through a data phase.
+ * This isn't done by the host so we can avoid a DMA to clear these
+ * fields for the normal case of I/O that completes without underrun
+ * or overrun conditions.
  */
-start_waiting:
-       mov     SCBPTR,WAITING_SCBH
-       jmp     start_scb2
-
-test_a:
-       test    ACTIVE_A,A jnz requeue
-       test    SCB_CONTROL,TAG_ENB jnz start_scb
-       /* Mark the current target as busy */
-       or      ACTIVE_A,A
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               bmov    SCB_RESID_DCNT, SCB_DATACNT, 3;
+       } else {
+               mov     SCB_RESID_DCNT[0],SCB_DATACNT[0];
+               mov     SCB_RESID_DCNT[1],SCB_DATACNT[1];
+               mov     SCB_RESID_DCNT[2],SCB_DATACNT[2];
+       }
+       mov     SCB_RESID_SGCNT, SCB_SGCOUNT;
 
 start_scb:
-       mov     SCB_NEXT,WAITING_SCBH
-       mov     WAITING_SCBH, SCBPTR
-start_scb2:
-       and     SINDEX,0xf7,SBLKCTL     /* Clear the channel select bit */
-       and     A,0x08,SCB_TCL          /* Get new channel bit */
-       or      SINDEX,A
-       mov     SBLKCTL,SINDEX          /* select channel */
-       mov     SCB_TCL call initialize_scsiid
+       /*
+        * Place us on the waiting list in case our selection
+        * doesn't win during bus arbitration.
+        */
+       mov     SCB_NEXT,WAITING_SCBH;
+       mov     WAITING_SCBH, SCBPTR;
+start_waiting:
+       /*
+        * Pull the first entry off of the waiting SCB list.
+        */
+       mov     SCBPTR, WAITING_SCBH;
+       call    start_selection;
+       jmp     poll_for_work;
 
-/*
- * Enable selection phase as an initiator, and do automatic ATN
- * after the selection.  We do this now so that we can overlap the
- * rest of our work to set up this target with the arbitration and
- * selection bus phases.
- */
 start_selection:
-       mvi     SCSISEQ,0x58            /* ENSELO|ENAUTOATNO|ENRSELI */
-
-/*
- * As soon as we get a successful selection, the target should go
- * into the message out phase since we have ATN asserted.  Prepare
- * the message to send.
- *
- * Messages are stored in scratch RAM starting with a length byte
- * followed by the message itself.
- */
-
-mk_identify:
-       and     A,DISCENB,SCB_CONTROL   /* mask off disconnect privledge */
-
-       and     MSG0,0x7,SCB_TCL        /* lun */
-       or      MSG0,A                  /* or in disconnect privledge */
-       or      MSG0,MSG_IDENTIFYFLAG
-       mvi     MSG_LEN, 1
-
-/*
- * Send a tag message if TAG_ENB is set in the SCB control block.
- * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
- */
-mk_tag:
-       test    SCB_CONTROL,TAG_ENB jz  mk_message
-       mvi     DINDEX, MSG1
-       and     DINDIR,0x23,SCB_CONTROL
-       mov     DINDIR,SCB_TAG
-
-       add     MSG_LEN,COMP_MSG0,DINDEX        /* update message length */
-
+       if ((ahc->features & AHC_TWIN) != 0) {
+               and     SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */
+               and     A,SELBUSB,SCB_TCL;      /* Get new channel bit */
+               or      SINDEX,A;
+               mov     SBLKCTL,SINDEX;         /* select channel */
+       }
+initialize_scsiid:
+       mov     SINDEX, SCSISEQ_TEMPLATE;
+       if ((ahc->flags & AHC_TARGETMODE) != 0) {
+               test    SCB_CONTROL, TARGET_SCB jz . + 4;
+               if ((ahc->features & AHC_ULTRA2) != 0) {
+                       mov     SCSIID_ULTRA2, SCB_CMDPTR[2];
+               } else {
+                       mov     SCSIID, SCB_CMDPTR[2];
+               }
+               or      SINDEX, TEMODE;
+               jmp     initialize_scsiid_fini;
+       }
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               and     A, TID, SCB_TCL;        /* Get target ID */
+               and     SCSIID_ULTRA2, OID;     /* Clear old target */
+               or      SCSIID_ULTRA2, A;
+       } else {
+               and     A, TID, SCB_TCL;        /* Get target ID */
+               and     SCSIID, OID;            /* Clear old target */
+               or      SCSIID, A;
+       }
+initialize_scsiid_fini:
+       mov     SCSISEQ, SINDEX ret;
+
+/*
+ * Initialize transfer settings and clear the SCSI channel.
+ * SINDEX should contain any additional bit's the client wants
+ * set in SXFRCTL0.  We also assume that the current SCB is
+ * a valid SCB for the target we wish to talk to.
+ */
+initialize_channel:
+       or      SXFRCTL0, CLRSTCNT|CLRCHN, SINDEX;
+set_transfer_settings:
+       if ((ahc->features & AHC_ULTRA) != 0) {
+               test    SCB_CONTROL, ULTRAENB jz . + 2;
+               or      SXFRCTL0, FAST20;
+       } 
 /*
- * Interrupt the driver, and allow it to tweak the message buffer
- * if it asks.
+ * Initialize SCSIRATE with the appropriate value for this target.
  */
-mk_message:
-       test    SCB_CONTROL,MK_MESSAGE  jz wait_for_selection
-
-       mvi     INTSTAT,AWAITING_MSG
-
-wait_for_selection:
-       test    SSTAT0,SELDO    jnz select 
-       test    SSTAT0,SELDI    jz wait_for_selection
-
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               bmov    SCSIRATE, SCB_SCSIRATE, 2 ret;
+       } else {
+               mov     SCSIRATE, SCB_SCSIRATE ret;
+       }
+
+selection:
+       test    SSTAT0,SELDO    jnz select_out;
+       mvi     CLRSINT0, CLRSELDI;
+select_in:
+       if ((ahc->flags & AHC_TARGETMODE) != 0) {
+               if ((ahc->flags & AHC_INITIATORMODE) != 0) {
+                       test    SSTAT0, TARGET  jz initiator_reselect;
+               }
+
+               /*
+                * We've just been selected.  Assert BSY and
+                * setup the phase for receiving messages
+                * from the target.
+                */
+               mvi     SCSISIGO, P_MESGOUT|BSYO;
+               mvi     CLRSINT1, CLRBUSFREE;
+
+               /*
+                * Setup the DMA for sending the identify and
+                * command information.
+                */
+               or      SEQ_FLAGS, CMDPHASE_PENDING;
+
+               mov     A, TQINPOS;
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       mvi     DINDEX, CCHADDR;
+                       mvi     TMODE_CMDADDR call set_32byte_addr;
+                       mvi     CCSCBCTL, CCSCBRESET;
+               } else {
+                       mvi     DINDEX, HADDR;
+                       mvi     TMODE_CMDADDR call set_32byte_addr;
+                       mvi     DFCNTRL, FIFORESET;
+               }
+
+               /* Initiator that selected us */
+               and     SAVED_TCL, SELID_MASK, SELID;
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       mov     CCSCBRAM, SAVED_TCL;
+               } else {
+                       mov     DFDAT, SAVED_TCL;
+               }
+
+               /* The Target ID we were selected at */
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       if ((ahc->features & AHC_MULTI_TID) != 0) {
+                               and     CCSCBRAM, OID, TARGIDIN;
+                       } else if ((ahc->features & AHC_ULTRA2) != 0) {
+                               and     CCSCBRAM, OID, SCSIID_ULTRA2;
+                       } else {
+                               and     CCSCBRAM, OID, SCSIID;
+                       }
+               } else {
+                       if ((ahc->features & AHC_MULTI_TID) != 0) {
+                               and     DFDAT, OID, TARGIDIN;
+                       } else if ((ahc->features & AHC_ULTRA2) != 0) {
+                               and     DFDAT, OID, SCSIID_ULTRA2;
+                       } else {
+                               and     DFDAT, OID, SCSIID;
+                       }
+               }
+
+               /* No tag yet */
+               mvi     INITIATOR_TAG, SCB_LIST_NULL;
+
+               /*
+                * If ATN isn't asserted, the target isn't interested
+                * in talking to us.  Go directly to bus free.
+                */
+               test    SCSISIGI, ATNI  jz      target_busfree;
+
+               /*
+                * Watch ATN closely now as we pull in messages from the
+                * initiator.  We follow the guidlines from section 6.5
+                * of the SCSI-2 spec for what messages are allowed when.
+                */
+               call    target_inb;
+
+               /*
+                * Our first message must be one of IDENTIFY, ABORT, or
+                * BUS_DEVICE_RESET.
+                */
+               /* XXX May need to be more lax here for older initiators... */
+               test    DINDEX, MSG_IDENTIFYFLAG jz host_target_message_loop;
+               /* Store for host */
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       mov     CCSCBRAM, DINDEX;
+               } else {
+                       mov     DFDAT, DINDEX;
+               }
+
+               /* Remember for disconnection decision */
+               test    DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2;
+               /* XXX Honor per target settings too */
+               or      SEQ_FLAGS, NO_DISCONNECT;
+
+               test    SCSISIGI, ATNI  jz      ident_messages_done;
+               call    target_inb;
+               /*
+                * If this is a tagged request, the tagged message must
+                * immediately follow the identify.  We test for a valid
+                * tag message by seeing if it is >= MSG_SIMPLE_Q_TAG and
+                * < MSG_IGN_WIDE_RESIDUE.
+                */
+               add     A, -MSG_SIMPLE_Q_TAG, DINDEX;
+               jnc     ident_messages_done;
+               add     A, -MSG_IGN_WIDE_RESIDUE, DINDEX;
+               jc      ident_messages_done;
+               /* Store for host */
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       mov     CCSCBRAM, DINDEX;
+               } else {
+                       mov     DFDAT, DINDEX;
+               }
+               
+               /*
+                * If the initiator doesn't feel like providing a tag number,
+                * we've got a failed selection and must transition to bus
+                * free.
+                */
+               test    SCSISIGI, ATNI  jz      target_busfree;
+
+               /*
+                * Store the tag for the host.
+                */
+               call    target_inb;
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       mov     CCSCBRAM, DINDEX;
+               } else {
+                       mov     DFDAT, DINDEX;
+               }
+               mov     INITIATOR_TAG, DINDEX;
+               jmp     ident_messages_done;
+
+               /*
+                * Pushed message loop to allow the kernel to
+                * run it's own target mode message state engine.
+                */
+host_target_message_loop:
+               mvi     INTSTAT, HOST_MSG_LOOP;
+               nop;
+               cmp     RETURN_1, EXIT_MSG_LOOP je target_ITloop;
+               test    SSTAT0, SPIORDY jz .;
+               jmp     host_target_message_loop;
+
+ident_messages_done:
+               /* If ring buffer is full, return busy or queue full */
+               mov     A, KERNEL_TQINPOS;
+               cmp     TQINPOS, A jne tqinfifo_has_space;
+               mvi     P_STATUS|BSYO call change_phase;
+               cmp     INITIATOR_TAG, SCB_LIST_NULL je . + 3;
+               mvi     STATUS_QUEUE_FULL call target_outb;
+               jmp     target_busfree_wait;
+               mvi     STATUS_BUSY call target_outb;
+               jmp     target_busfree_wait;
+tqinfifo_has_space:    
+               /* Terminate the ident list */
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       mvi     CCSCBRAM, SCB_LIST_NULL;
+               } else {
+                       mvi     DFDAT, SCB_LIST_NULL;
+               }
+               or      SEQ_FLAGS, TARG_CMD_PENDING|IDENTIFY_SEEN;
+               test    SCSISIGI, ATNI  jnz target_mesgout_pending_msg;
+               jmp     target_ITloop;
+               
+/*
+ * We carefully toggle SPIOEN to allow us to return the 
+ * message byte we receive so it can be checked prior to
+ * driving REQ on the bus for the next byte.
+ */
+target_inb:
+               /*
+                * Drive REQ on the bus by enabling SCSI PIO.
+                */
+               or      SXFRCTL0, SPIOEN;
+               /* Wait for the byte */
+               test    SSTAT0, SPIORDY jz .;
+               /* Prevent our read from triggering another REQ */
+               and     SXFRCTL0, ~SPIOEN;
+               /* Save latched contents */
+               mov     DINDEX, SCSIDATL ret;
+       }
+
+if ((ahc->flags & AHC_INITIATORMODE) != 0) {
 /*
  * Reselection has been initiated by a target. Make a note that we've been
- * reselected, but haven't seen an IDENTIFY message from the target
- * yet.
- */
-reselect:
-       clr     MSG_LEN         /* Don't have anything in the mesg buffer */
-       mov     SELID           call initialize_scsiid
-       or      FLAGS,RESELECTED
-       jmp     select2
+ * reselected, but haven't seen an IDENTIFY message from the target yet.
+ */
+initiator_reselect:
+       /* XXX test for and handle ONE BIT condition */
+       and     SAVED_TCL, SELID_MASK, SELID;
+       if ((ahc->features & AHC_TWIN) != 0) {
+               test    SBLKCTL, SELBUSB        jz . + 2;
+               or      SAVED_TCL, SELBUSB;
+       }
+       or      SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;
+       mvi     CLRSINT1,CLRBUSFREE;
+       or      SIMODE1, ENBUSFREE;             /*
+                                                * We aren't expecting a
+                                                * bus free, so interrupt
+                                                * the kernel driver if it
+                                                * happens.
+                                                */
+       jmp     ITloop;
+}
 
 /*
- * After the selection, remove this SCB from the "waiting for selection"
+ * After the selection, remove this SCB from the "waiting SCB"
  * list.  This is achieved by simply moving our "next" pointer into
  * WAITING_SCBH.  Our next pointer will be set to null the next time this
  * SCB is used, so don't bother with it now.
  */
-select:
-       mov     WAITING_SCBH,SCB_NEXT
-       or      FLAGS,SELECTED
-select2:
-/*
- * Set CLRCHN here before the target has entered a data transfer mode -
- * with synchronous SCSI, if you do it later, you blow away some
- * data in the SCSI FIFO that the target has already sent to you.
- */
-       or      SXFRCTL0,CLRCHN
-/*
- * Initialize SCSIRATE with the appropriate value for this target.
- */
-       call    ndx_dtr
-       mov     SCSIRATE,SINDIR
+select_out:
+       /* Turn off the selection hardware */
+       and     SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP,SCSISEQ_TEMPLATE;
+       mvi     CLRSINT0, CLRSELDO;
+       mov     SCBPTR, WAITING_SCBH;
+       mov     WAITING_SCBH,SCB_NEXT;
+       mov     SAVED_TCL, SCB_TCL;
+       if ((ahc->flags & AHC_TARGETMODE) != 0) {
+               test    SSTAT0, TARGET  jz initiator_select;
+
+               /*
+                * We've just re-selected an initiator.
+                * Assert BSY and setup the phase for
+                * sending our identify messages.
+                */
+               mvi     P_MESGIN|BSYO call change_phase;
+               mvi     CLRSINT1,CLRBUSFREE;
+
+               /*
+                * Start out with a simple identify message.
+                */
+               and     A, LID, SCB_TCL;
+               or      A, MSG_IDENTIFYFLAG call target_outb;
+
+               /*
+                * If we are the result of a tagged command, send
+                * a simple Q tag and the tag id.
+                */
+               test    SCB_CONTROL, TAG_ENB    jz . + 3;
+               mvi     MSG_SIMPLE_Q_TAG call target_outb;
+               mov     SCB_INITIATOR_TAG call target_outb;
+               mov     INITIATOR_TAG, SCB_INITIATOR_TAG;
+target_synccmd:
+               /*
+                * Now determine what phases the host wants us
+                * to go through.
+                */
+               mov     SEQ_FLAGS, SCB_TARGET_PHASES;
+               
+
+target_ITloop:
+               /*
+                * Start honoring ATN signals now that
+                * we properly identified ourselves.
+                */
+               test    SCSISIGI, ATNI                  jnz target_mesgout;
+               test    SEQ_FLAGS, CMDPHASE_PENDING     jnz target_cmdphase;
+               test    SEQ_FLAGS, DPHASE_PENDING       jnz target_dphase;
+               test    SEQ_FLAGS, SPHASE_PENDING       jnz target_sphase;
+
+               /*
+                * No more work to do.  Either disconnect or not depending
+                * on the state of NO_DISCONNECT.
+                */
+               test    SEQ_FLAGS, NO_DISCONNECT jz target_disconnect; 
+               if ((ahc->flags & AHC_PAGESCBS) != 0) {
+                       mov     ALLZEROS        call    get_free_or_disc_scb;
+               }
+               mov     RETURN_1, ALLZEROS;
+               call    complete_target_cmd;
+               cmp     RETURN_1, CONT_MSG_LOOP jne .;
+               mvi     DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
+               mov     SCB_TAG  call dma_scb;
+               jmp     target_synccmd;
+
+target_mesgout:
+               mvi     SCSISIGO, P_MESGOUT|BSYO;
+               call    target_inb;
+               /* Local Processing goes here... */
+target_mesgout_pending_msg:
+               jmp     host_target_message_loop;
+               
+target_disconnect:
+               mvi     P_MESGIN|BSYO call change_phase;
+               test    SEQ_FLAGS, DPHASE       jz . + 2;
+               mvi     MSG_SAVEDATAPOINTER call target_outb;
+               mvi     MSG_DISCONNECT call target_outb;
+
+target_busfree_wait:
+               /* Wait for preceeding I/O session to complete. */
+               test    SCSISIGI, ACKI jnz .;
+target_busfree:
+               clr     SCSISIGO;
+               mvi     LASTPHASE, P_BUSFREE;
+               call    complete_target_cmd;
+               jmp     poll_for_work;
+
+target_cmdphase:
+               mvi     P_COMMAND|BSYO call change_phase;
+               call    target_inb;
+               mov     A, DINDEX;
+               /* Store for host */
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       mov     CCSCBRAM, A;
+               } else {
+                       mov     DFDAT, A;
+               }
+
+               /*
+                * Determine the number of bytes to read
+                * based on the command group code via table lookup.
+                * We reuse the first 8 bytes of the TARG_SCSIRATE
+                * BIOS array for this table. Count is one less than
+                * the total for the command since we've already fetched
+                * the first byte.
+                */
+               shr     A, CMD_GROUP_CODE_SHIFT;
+               add     SINDEX, TARG_SCSIRATE, A;
+               mov     A, SINDIR;
+
+               test    A, 0xFF jz command_phase_done;
+command_loop:
+               or      SXFRCTL0, SPIOEN;
+               test    SSTAT0, SPIORDY jz .;
+               cmp     A, 1 jne . + 2;
+               and     SXFRCTL0, ~SPIOEN;      /* Last Byte */
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       mov     CCSCBRAM, SCSIDATL;
+               } else {
+                       mov     DFDAT, SCSIDATL;
+               }
+               dec     A;
+               test    A, 0xFF jnz command_loop;
+
+command_phase_done:
+               and     SEQ_FLAGS, ~CMDPHASE_PENDING;
+               jmp     target_ITloop;
+
+target_dphase:
+               /*
+                * Data direction flags are from the
+                * perspective of the initiator.
+                */
+               test    SCB_TARGET_PHASES[1], TARGET_DATA_IN jz . + 4;
+               mvi     LASTPHASE, P_DATAOUT;
+               mvi     P_DATAIN|BSYO call change_phase;
+               jmp     . + 3;
+               mvi     LASTPHASE, P_DATAIN;
+               mvi     P_DATAOUT|BSYO call change_phase;
+               mov     ALLZEROS call initialize_channel;
+               jmp     p_data;
+
+target_sphase:
+               mvi     P_STATUS|BSYO call change_phase;
+               mvi     LASTPHASE, P_STATUS;
+               mov     SCB_TARGET_STATUS call target_outb;
+               /* XXX Watch for ATN or parity errors??? */
+               mvi     SCSISIGO, P_MESGIN|BSYO;
+               /* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */
+               mov     ALLZEROS call target_outb;
+               jmp     target_busfree_wait;
+       
+complete_target_cmd:
+               test    SEQ_FLAGS, TARG_CMD_PENDING     jnz . + 2;
+               mov     SCB_TAG jmp complete_post;
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       /* Set the valid byte */
+                       mvi     CCSCBADDR, 24;
+                       mov     CCSCBRAM, ALLONES;
+                       mvi     CCHCNT, 28;
+                       or      CCSCBCTL, CCSCBEN|CCSCBRESET;
+                       test    CCSCBCTL, CCSCBDONE jz .;
+                       clr     CCSCBCTL;
+               } else {
+                       /* Set the valid byte */
+                       or      DFCNTRL, FIFORESET;
+                       mvi     DFWADDR, 3; /* Third 64bit word or byte 24 */
+                       mov     DFDAT, ALLONES;
+                       mvi     HCNT[0], 28;
+                       clr     HCNT[1];
+                       clr     HCNT[2];
+                       or      DFCNTRL, HDMAEN|FIFOFLUSH;
+                       call    dma_finish;
+               }
+               inc     TQINPOS;
+               mvi     INTSTAT,CMDCMPLT ret;
+       }
+
+if ((ahc->flags & AHC_INITIATORMODE) != 0) {
+initiator_select:
+       mvi     SPIOEN call     initialize_channel;
 
-/*
- * Initialize Ultra mode setting.
- */
-       mov     FUNCTION1,SCSIID
-       mov     A,FUNCTION1
-       and     SINDEX,0xdf,SXFRCTL0            /* default to Ultra disabled */
-       test    SCSIID, 0x80     jnz ultra_b    /* Target ID > 7 */
-       test    SBLKCTL, SELBUSB jnz ultra_b    /* Second channel device */
-       test    ULTRA_ENB,A      jz  set_sxfrctl0
-       or      SINDEX, ULTRAEN  jmp set_sxfrctl0
-ultra_b:
-       test    ULTRA_ENB_B,A    jz  set_sxfrctl0
-       or      SINDEX, ULTRAEN
-
-set_sxfrctl0:
-       mov     SXFRCTL0,SINDEX
-
-       mvi     SCSISEQ,ENAUTOATNP              /*
-                                                * ATN on parity errors
-                                                * for "in" phases
-                                                */
-       mvi     CLRSINT1,CLRBUSFREE
-       mvi     CLRSINT0,0x60                   /* CLRSELDI|CLRSELDO */
-/*
- * Main loop for information transfer phases.  If BSY is false, then
- * we have a bus free condition, expected or not.  Otherwise, wait
- * for the target to assert REQ before checking MSG, C/D and I/O
- * for the bus phase.
- *
- */
+       /*
+        * We aren't expecting a bus free, so interrupt
+        * the kernel driver if it happens.
+        */
+       mvi     CLRSINT1,CLRBUSFREE;
+       or      SIMODE1, ENBUSFREE;
+
+       /*
+        * As soon as we get a successful selection, the target
+        * should go into the message out phase since we have ATN
+        * asserted.
+        */
+       mvi     MSG_OUT, MSG_IDENTIFYFLAG;
+       or      SEQ_FLAGS, IDENTIFY_SEEN;
+
+       /*
+        * Main loop for information transfer phases.  Wait for the
+        * target to assert REQ before checking MSG, C/D and I/O for
+        * the bus phase.
+        */
 ITloop:
-       test    SSTAT1,BUSFREE  jnz p_busfree
-       test    SSTAT1,REQINIT  jz ITloop
-
-       and     A,PHASE_MASK,SCSISIGI
-       mov     LASTPHASE,A
-       mov     SCSISIGO,A
-
-       cmp     ALLZEROS,A      je p_dataout
-       cmp     A,P_DATAIN      je p_datain
-       cmp     A,P_COMMAND     je p_command
-       cmp     A,P_MESGOUT     je p_mesgout
-       cmp     A,P_STATUS      je p_status
-       cmp     A,P_MESGIN      je p_mesgin
-
-       mvi     INTSTAT,BAD_PHASE       /* unknown phase - signal driver */
-       jmp     ITloop                  /* Try reading the bus again. */
-
-p_dataout:
-       mvi     DMAPARAMS,0x7d                  /*
-                                                * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
-                                                * DIRECTION|FIFORESET
-                                                */
-       jmp     data_phase_init
+       call    phase_lock;
+
+       mov     A, LASTPHASE;
+
+       test    A, ~P_DATAIN    jz p_data;
+       cmp     A,P_COMMAND     je p_command;
+       cmp     A,P_MESGOUT     je p_mesgout;
+       cmp     A,P_STATUS      je p_status;
+       cmp     A,P_MESGIN      je p_mesgin;
+
+       mvi     INTSTAT,BAD_PHASE;
+       jmp     ITloop;                 /* Try reading the bus again. */
+
+await_busfree:
+       and     SIMODE1, ~ENBUSFREE;
+       mov     NONE, SCSIDATL;         /* Ack the last byte */
+       and     SXFRCTL0, ~SPIOEN;
+       test    SSTAT1,REQINIT|BUSFREE  jz .;
+       test    SSTAT1, BUSFREE jnz poll_for_work;
+       mvi     INTSTAT, BAD_PHASE;
+}
+       
+clear_target_state:
+       /*
+        * We assume that the kernel driver may reset us
+        * at any time, even in the middle of a DMA, so
+        * clear DFCNTRL too.
+        */
+       clr     DFCNTRL;
+
+       /*
+        * We don't know the target we will connect to,
+        * so default to narrow transfers to avoid
+        * parity problems.
+        */
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               bmov    SCSIRATE, ALLZEROS, 2;
+       } else {
+               clr     SCSIRATE;
+               and     SXFRCTL0, ~(FAST20);
+       }
+       mvi     LASTPHASE, P_BUSFREE;
+       /* clear target specific flags */
+       clr     SEQ_FLAGS ret;
 
 /*
  * If we re-enter the data phase after going through another phase, the
  * STCNT may have been cleared, so restore it from the residual field.
  */
 data_phase_reinit:
-       mov     STCNT0,SCB_RESID_DCNT0
-       mov     STCNT1,SCB_RESID_DCNT1
-       mov     STCNT2,SCB_RESID_DCNT2
-       jmp     data_phase_loop
-
-p_datain:
-       mvi     DMAPARAMS,0x79          /*
-                                        * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
-                                        * !DIRECTION|FIFORESET
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               /*
+                * The preload circuitry requires us to
+                * reload the address too, so pull it from
+                * the shaddow address.
+                */
+               bmov    HADDR, SHADDR, 4;
+               bmov    HCNT, SCB_RESID_DCNT, 3;
+       } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               bmov    STCNT, SCB_RESID_DCNT, 3;
+       } else {
+               mvi     DINDEX, STCNT;
+               mvi     SCB_RESID_DCNT  call bcopy_3;
+       }
+       and     DATA_COUNT_ODD, 0x1, SCB_RESID_DCNT[0];
+       jmp     data_phase_loop;
+
+p_data:
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               mvi     DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;
+       } else {
+               mvi     DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
+       }
+       test    LASTPHASE, IOI jnz . + 2;
+       or      DMAPARAMS, DIRECTION;
+       call    assert;                 /*
+                                        * Ensure entering a data
+                                        * phase is okay - seen identify, etc.
                                         */
-data_phase_init:
-       call    assert
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               mvi     CCSGADDR, CCSGADDR_MAX;
+       }
+       test    SEQ_FLAGS, DPHASE       jnz data_phase_reinit;
+
+       /* We have seen a data phase */
+       or      SEQ_FLAGS, DPHASE;
 
-       test    FLAGS, DPHASE   jnz data_phase_reinit
-       call    sg_scb2ram
-       or      FLAGS, DPHASE           /* We have seen a data phase */
+       /*
+        * Initialize the DMA address and counter from the SCB.
+        * Also set SG_COUNT and SG_NEXT in memory since we cannot
+        * modify the values in the SCB itself until we see a
+        * save data pointers message.
+        */
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               bmov    HADDR, SCB_DATAPTR, 7;
+       } else {
+               mvi     DINDEX, HADDR;
+               mvi     SCB_DATAPTR     call bcopy_7;
+       }
+       and     DATA_COUNT_ODD, 0x1, SCB_DATACNT[0];
+
+       if ((ahc->features & AHC_ULTRA2) == 0) {
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       bmov    STCNT, HCNT, 3;
+               } else {
+                       call    set_stcnt_from_hcnt;
+               }
+       }
+
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               bmov    SG_COUNT, SCB_SGCOUNT, 5;
+       } else {
+               mvi     DINDEX, SG_COUNT;
+               mvi     SCB_SGCOUNT     call bcopy_5;
+       }
 
 data_phase_loop:
 /* Guard against overruns */
-       test    SG_COUNT, 0xff jnz data_phase_inbounds
+       test    SG_COUNT, 0xff jnz data_phase_inbounds;
 /*
  * Turn on 'Bit Bucket' mode, set the transfer count to
  * 16meg and let the target run until it changes phase.
  * When the transfer completes, notify the host that we
  * had an overrun.
  */
-       or      SXFRCTL1,BITBUCKET
-       mvi     STCNT0,0xff
-       mvi     STCNT1,0xff
-       mvi     STCNT2,0xff
-
+       or      SXFRCTL1,BITBUCKET;
+       and     DMAPARAMS, ~(HDMAEN|SDMAEN);
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               bmov    HCNT, ALLONES, 3;
+       } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               bmov    STCNT, ALLONES, 3;
+       } else {
+               mvi     STCNT[0], 0xFF;
+               mvi     STCNT[1], 0xFF;
+               mvi     STCNT[2], 0xFF;
+       }
 data_phase_inbounds:
-/* If we are the last SG block, don't set wideodd. */
-       cmp     SG_COUNT,0x01 jne data_phase_wideodd
-       and     DMAPARAMS, 0xbf         /* Turn off WIDEODD */
+/* If we are the last SG block, tell the hardware. */
+       cmp     SG_COUNT,0x01 jne data_phase_wideodd;
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               or      SG_CACHEPTR, LAST_SEG;
+       } else {
+               if ((ahc->flags & AHC_TARGETMODE) != 0) {
+                       test    SSTAT0, TARGET jz . + 2;
+                       test    DMAPARAMS, DIRECTION jz data_phase_wideodd;
+               }
+               and     DMAPARAMS, ~WIDEODD;
+       }
 data_phase_wideodd:
-       mov     DMAPARAMS  call dma
-
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               mov     SINDEX, ALLONES;
+               mov     DFCNTRL, DMAPARAMS;
+               test    SSTAT0, SDONE jnz .;/* Wait for preload to complete */
+data_phase_dma_loop:
+               test    SSTAT0, SDONE jnz data_phase_dma_done;
+               test    SSTAT1,PHASEMIS jz data_phase_dma_loop; /* ie. underrun */
+       } else {
+               mov     DMAPARAMS  call dma;
+       }
+
+data_phase_dma_done:
 /* Go tell the host about any overruns */
-       test    SXFRCTL1,BITBUCKET jnz data_phase_overrun
+       test    SXFRCTL1,BITBUCKET jnz data_phase_overrun;
 
-/* Exit if we had an underrun */
-       test    SSTAT0,SDONE    jz data_phase_finish /* underrun STCNT != 0 */
+/* See if we completed this segment */
+       test    STCNT[0], 0xff  jnz data_phase_finish;
+       test    STCNT[1], 0xff  jnz data_phase_finish;
+       test    STCNT[2], 0xff  jnz data_phase_finish;
 
 /*
  * Advance the scatter-gather pointers if needed 
  */
 sg_advance:
-       dec     SG_COUNT        /* one less segment to go */
-
-       test    SG_COUNT, 0xff  jz data_phase_finish /* Are we done? */
-
-       clr     A                       /* add sizeof(struct scatter) */
-       add     SG_NEXT0,SG_SIZEOF,SG_NEXT0
-       adc     SG_NEXT1,A,SG_NEXT1
+       dec     SG_COUNT;       /* one less segment to go */
 
+       test    SG_COUNT, 0xff  jz data_phase_finish; /* Are we done? */
 /*
  * Load a struct scatter and set up the data address and length.
  * If the working value of the SG count is nonzero, then
@@ -387,351 +812,475 @@ sg_advance:
  * This, like all DMA's, assumes little-endian host data storage.
  */
 sg_load:
-       clr     HCNT2
-       clr     HCNT1
-       mvi     HCNT0,SG_SIZEOF
-
-       mov     HADDR0,SG_NEXT0
-       mov     HADDR1,SG_NEXT1
-       mov     HADDR2,SG_NEXT2
-       mov     HADDR3,SG_NEXT3
-
-       or      DFCNTRL,0xd                     /* HDMAEN|DIRECTION|FIFORESET */
-
-/*
- * Wait for DMA from host memory to data FIFO to complete, then disable
- * DMA and wait for it to acknowledge that it's off.
- */
-dma_finish:
-       test    DFSTATUS,HDONE  jz dma_finish
-       /* Turn off DMA preserving WIDEODD */
-       and     DFCNTRL,WIDEODD
-dma_finish2:
-       test    DFCNTRL,HDMAENACK jnz dma_finish2
-
-/*
- * Copy data from FIFO into SCB data pointer and data count.  This assumes
- * that the struct scatterlist has this structure (this and sizeof(struct
- * scatterlist) == 12 are asserted in aic7xxx.c for the Linux driver):
- *
- *     struct scatterlist {
- *             char *address;          four bytes, little-endian order
- *             ...                     four bytes, ignored
- *             unsigned short length;  two bytes, little-endian order
- *     }
- *
- *
- * In FreeBSD, the scatter list entry is only 8 bytes.
- * 
- * struct ahc_dma_seg {
- *       physaddr addr;                  four bytes, little-endian order
- *       long    len;                    four bytes, little endian order
- * };
- */
-
-       mov     HADDR0,DFDAT
-       mov     HADDR1,DFDAT
-       mov     HADDR2,DFDAT
-       mov     HADDR3,DFDAT
-/*
- * For Linux, we must throw away four bytes since there is a 32bit gap
- * in the middle of a struct scatterlist.
- */
-#ifdef __linux__
-       mov     NONE,DFDAT
-       mov     NONE,DFDAT
-       mov     NONE,DFDAT
-       mov     NONE,DFDAT
-#endif
-       mov     HCNT0,DFDAT
-       mov     HCNT1,DFDAT
-       mov     HCNT2,DFDAT
-
-/* Load STCNT as well.  It is a mirror of HCNT */
-       mov     STCNT0,HCNT0
-       mov     STCNT1,HCNT1
-       mov     STCNT2,HCNT2
-        test    SSTAT1,PHASEMIS  jz data_phase_loop
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               /*
+                * Do we have any prefetch left???
+                */
+               cmp     CCSGADDR, CCSGADDR_MAX jne prefetched_segs_avail;
+
+               /*
+                * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes.
+                */
+               add     A, -(CCSGRAM_MAXSEGS + 1), SG_COUNT;
+               mvi     A, CCSGADDR_MAX;
+               jc      . + 2;
+               shl     A, 3, SG_COUNT;
+               mov     CCHCNT, A;
+               bmov    CCHADDR, SG_NEXT, 4;
+               mvi     CCSGCTL, CCSGEN|CCSGRESET;
+               test    CCSGCTL, CCSGDONE jz .;
+               and     CCSGCTL, ~CCSGEN;
+               test    CCSGCTL, CCSGEN jnz .;
+               mvi     CCSGCTL, CCSGRESET;
+prefetched_segs_avail:
+               bmov    HADDR, CCSGRAM, 8;
+       } else {
+               mvi     DINDEX, HADDR;
+               mvi     SG_NEXT call bcopy_4;
+
+               mvi     HCNT[0],SG_SIZEOF;
+               clr     HCNT[1];
+               clr     HCNT[2];
+
+               or      DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
+
+               call    dma_finish;
+
+               /*
+                * Copy data from FIFO into SCB data pointer and data count.
+                * This assumes that the SG segments are of the form:
+                * struct ahc_dma_seg {
+                *      u_int32_t       addr;   four bytes, little-endian order
+                *      u_int32_t       len;    four bytes, little endian order
+                * };
+                */
+               mvi     HADDR   call dfdat_in_7;
+       }
+
+       /* Track odd'ness */
+       test    HCNT[0], 0x1 jz . + 2;
+       xor     DATA_COUNT_ODD, 0x1;
+
+       if ((ahc->features & AHC_ULTRA2) == 0) {
+               /* Load STCNT as well.  It is a mirror of HCNT */
+               if ((ahc->features & AHC_CMD_CHAN) != 0) {
+                       bmov    STCNT, HCNT, 3;
+               } else {
+                       call    set_stcnt_from_hcnt;
+               }
+       }
+
+/* Advance the SG pointer */
+       clr     A;                      /* add sizeof(struct scatter) */
+       add     SG_NEXT[0],SG_SIZEOF;
+       adc     SG_NEXT[1],A;
+
+       if ((ahc->flags & AHC_TARGETMODE) != 0) {
+               test    SSTAT0, TARGET jnz data_phase_loop;
+       }
+       test    SSTAT1, REQINIT jz .;
+       test    SSTAT1,PHASEMIS jz data_phase_loop;
+
+       /* Ensure the last seg is visable at the shaddow layer */
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               mov     DFCNTRL, DMAPARAMS;
+               test    SSTAT0, SDONE jnz .;/* Wait for preload to complete */
+       }
 
 data_phase_finish:
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               call    ultra2_dmafinish;
+       }
 /*
  * After a DMA finishes, save the SG and STCNT residuals back into the SCB
  * We use STCNT instead of HCNT, since it's a reflection of how many bytes 
  * were transferred on the SCSI (as opposed to the host) bus.
  */
-       mov     SCB_RESID_DCNT0,STCNT0
-       mov     SCB_RESID_DCNT1,STCNT1
-       mov     SCB_RESID_DCNT2,STCNT2
-       mov     SCB_RESID_SGCNT, SG_COUNT
-       jmp     ITloop
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               bmov    SCB_RESID_DCNT, STCNT, 3;
+       } else {
+               mov     SCB_RESID_DCNT[0],STCNT[0];
+               mov     SCB_RESID_DCNT[1],STCNT[1];
+               mov     SCB_RESID_DCNT[2],STCNT[2];
+       }
+       mov     SCB_RESID_SGCNT, SG_COUNT;
+
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               or      SXFRCTL0, CLRSTCNT|CLRCHN;
+       }
+
+       if ((ahc->flags & AHC_TARGETMODE) != 0) {
+               test    SEQ_FLAGS, DPHASE_PENDING jz ITloop;
+               and     SEQ_FLAGS, ~DPHASE_PENDING;
+               /*
+                * For data-in phases, wait for any pending acks from the
+                * initiator before changing phase.
+                */
+               test    DFCNTRL, DIRECTION jz target_ITloop;
+               test    SSTAT1, REQINIT jnz .;
+               jmp     target_ITloop;
+       }
+       jmp     ITloop;
 
 data_phase_overrun:
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               call    ultra2_dmafinish;
+               or      SXFRCTL0, CLRSTCNT|CLRCHN;
+       }
 /*
  * Turn off BITBUCKET mode and notify the host
  */
-       and     SXFRCTL1,0x7f           /* ~BITBUCKET */
-       mvi     INTSTAT,DATA_OVERRUN
-       jmp     ITloop
-
+       and     SXFRCTL1, ~BITBUCKET;
+       mvi     INTSTAT,DATA_OVERRUN;
+       jmp     ITloop;
+
+ultra2_dmafinish:
+       if ((ahc->features & AHC_ULTRA2) != 0) {
+               test    DFCNTRL, DIRECTION jnz ultra2_dmafifoempty;
+               and     DFCNTRL, ~SCSIEN;
+               test    DFCNTRL, SCSIEN jnz .;
+ultra2_dmafifoflush:
+               or      DFCNTRL, FIFOFLUSH;
+               /*
+                * The FIFOEMP status bit on the Ultra2 class
+                * of controllers seems to be a bit flaky.
+                * It appears that if the FIFO is full and the
+                * transfer ends with some data in the REQ/ACK
+                * FIFO, FIFOEMP will fall temporarily
+                * as the data is transferred to the PCI bus.
+                * This glitch lasts for fewer than 5 clock cycles,
+                * so we work around the problem by ensuring the
+                * status bit stays false through a full glitch
+                * window.
+                */
+               test    DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+               test    DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+               test    DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+               test    DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+               test    DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+
+ultra2_dmafifoempty:
+               /* Don't clobber an inprogress host data transfer */
+               test    DFSTATUS, MREQPEND      jnz ultra2_dmafifoempty;
+
+ultra2_dmahalt:
+               and     DFCNTRL, ~(SCSIEN|HDMAEN);
+               test    DFCNTRL, HDMAEN jnz .;
+               ret;
+       }
+
+if ((ahc->flags & AHC_INITIATORMODE) != 0) {
 /*
  * Command phase.  Set up the DMA registers and let 'er rip.
  */
 p_command:
-       call    assert
-
-/*
- * Load HADDR and HCNT.
- */
-       mov     HADDR0, SCB_CMDPTR0
-       mov     HADDR1, SCB_CMDPTR1
-       mov     HADDR2, SCB_CMDPTR2
-       mov     HADDR3, SCB_CMDPTR3
-       mov     HCNT0, SCB_CMDLEN
-       clr     HCNT1
-       clr     HCNT2
-
-       mov     STCNT0, HCNT0
-       mov     STCNT1, HCNT1
-       mov     STCNT2, HCNT2
-
-       mvi     0x3d            call dma        # SCSIEN|SDMAEN|HDMAEN|
-                                               #   DIRECTION|FIFORESET
-       jmp     ITloop
+       call    assert;
+
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               mov     HCNT[0], SCB_CMDLEN;
+               bmov    HCNT[1], ALLZEROS, 2;
+               if ((ahc->features & AHC_ULTRA2) == 0) {
+                       bmov    STCNT, HCNT, 3;
+               }
+               add     NONE, -17, SCB_CMDLEN;
+               jc      dma_cmd_data;
+               /*
+                * The data fifo seems to require 4 byte alligned
+                * transfers from the sequencer.  Force this to
+                * be the case by clearing HADDR[0] even though
+                * we aren't going to touch host memeory.
+                */
+               bmov    HADDR[0], ALLZEROS, 1;
+               if ((ahc->features & AHC_ULTRA2) != 0) {
+                       mvi     DFCNTRL, (PRELOADEN|SCSIEN|DIRECTION);
+               } else {
+                       mvi     DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET);
+               }
+               bmov   DFDAT, SCB_CMDSTORE, 16; 
+               jmp     cmd_loop;
+dma_cmd_data:
+               bmov    HADDR, SCB_CMDPTR, 4;
+       } else {
+               mvi     DINDEX, HADDR;
+               mvi     SCB_CMDPTR      call bcopy_5;
+               clr     HCNT[1];
+               clr     HCNT[2];
+       }
+
+       if ((ahc->features & AHC_ULTRA2) == 0) {
+               if ((ahc->features & AHC_CMD_CHAN) == 0) {
+                       call    set_stcnt_from_hcnt;
+               }
+               mvi     DFCNTRL, (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET);
+       } else {
+               mvi     DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
+       }
+cmd_loop:
+       test    SSTAT0, SDONE jnz . + 2;
+       test    SSTAT1, PHASEMIS jz cmd_loop;
+       /*
+        * Wait for our ACK to go-away on it's own
+        * instead of being killed by SCSIEN getting cleared.
+        */
+       test    SCSISIGI, ACKI jnz .;
+       and     DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
+       test    DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .;
+       jmp     ITloop;
 
 /*
  * Status phase.  Wait for the data byte to appear, then read it
  * and store it into the SCB.
  */
 p_status:
-       mvi     SCB_TARGET_STATUS       call inb_first
-       jmp     mesgin_done
+       call    assert;
+
+       mov     SCB_TARGET_STATUS, SCSIDATL;
+       jmp     ITloop;
 
 /*
- * Message out phase.  If there is not an active message, but the target
- * took us into this phase anyway, build a no-op message and send it.
+ * Message out phase.  If MSG_OUT is MSG_IDENTIFYFLAG, build a full
+ * indentify message sequence and send it to the target.  The host may
+ * override this behavior by setting the MK_MESSAGE bit in the SCB
+ * control byte.  This will cause us to interrupt the host and allow
+ * it to handle the message phase completely on its own.  If the bit
+ * associated with this target is set, we will also interrupt the host,
+ * thereby allowing it to send a message on the next selection regardless
+ * of the transaction being sent.
+ * 
+ * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message.
+ * This is done to allow the host to send messages outside of an identify
+ * sequence while protecting the seqencer from testing the MK_MESSAGE bit
+ * on an SCB that might not be for the current nexus. (For example, a
+ * BDR message in responce to a bad reselection would leave us pointed to
+ * an SCB that doesn't have anything to do with the current target).
+ *
+ * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag,
+ * bus device reset).
+ *
+ * When there are no messages to send, MSG_OUT should be set to MSG_NOOP,
+ * in case the target decides to put us in this phase for some strange
+ * reason.
  */
+p_mesgout_retry:
+       or      SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */
 p_mesgout:
-       test    MSG_LEN, 0xff   jnz  p_mesgout_start
-       mvi     MSG_NOOP        call mk_mesg    /* build NOP message */
-
-p_mesgout_start:
+       mov     SINDEX, MSG_OUT;
+       cmp     SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
+       test    SCB_CONTROL,MK_MESSAGE  jnz host_message_loop;
+       mov     FUNCTION1, SCB_TCL;
+       mov     A, FUNCTION1;
+       if ((ahc->features & AHC_HS_MAILBOX) != 0) {
+               /*
+                * Work around a pausing bug in at least the aic7890.
+                * If the host needs to update the TARGET_MSG_REQUEST
+                * bit field, it will set the HS_MAILBOX to 1.  In
+                * response, we pause with a specific interrupt code
+                * asking for the mask to be updated before we continue.
+                * Ugh.
+                */
+               test    HS_MAILBOX, 0xF0        jz . + 2;
+               mvi     INTSTAT, UPDATE_TMSG_REQ;
+               nop;
+       }
+       mov     SINDEX, TARGET_MSG_REQUEST[0];
+       if ((ahc->features & AHC_TWIN) != 0) {
+               /* Second Channel uses high byte bits */
+               test    SCB_TCL, SELBUSB        jz . + 2;
+               mov     SINDEX, TARGET_MSG_REQUEST[1];
+       } else if ((ahc->features & AHC_WIDE) != 0) {
+               test    SCB_TCL, 0x80           jz . + 2; /* target > 7 */
+               mov     SINDEX, TARGET_MSG_REQUEST[1];
+       }
+       test    SINDEX, A       jnz host_message_loop;
+p_mesgout_identify:
+       and     SINDEX,LID,SCB_TCL;     /* lun */
+       and     A,DISCENB,SCB_CONTROL;  /* mask off disconnect privledge */
+       or      SINDEX,A;               /* or in disconnect privledge */
+       or      SINDEX,MSG_IDENTIFYFLAG;
 /*
- * Set up automatic PIO transfer from MSG0.  Bit 3 in
- * SXFRCTL0 (SPIOEN) is already on.
+ * Send a tag message if TAG_ENB is set in the SCB control block.
+ * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
  */
-       mvi     SINDEX,MSG0
-       mov     DINDEX,MSG_LEN
-
+p_mesgout_tag:
+       test    SCB_CONTROL,TAG_ENB jz  p_mesgout_onebyte;
+       mov     SCSIDATL, SINDEX;       /* Send the identify message */
+       call    phase_lock;
+       cmp     LASTPHASE, P_MESGOUT    jne p_mesgout_done;
+       and     SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;
+       call    phase_lock;
+       cmp     LASTPHASE, P_MESGOUT    jne p_mesgout_done;
+       mov     SCB_TAG jmp p_mesgout_onebyte;
 /*
- * When target asks for a byte, drop ATN if it's the last one in
- * the message.  Otherwise, keep going until the message is exhausted.
- *
- * Keep an eye out for a phase change, in case the target issues
- * a MESSAGE REJECT.
+ * Interrupt the driver, and allow it to handle this message
+ * phase and any required retries.
  */
-p_mesgout_loop:
-       test    SSTAT1,PHASEMIS jnz p_mesgout_phasemis
-       test    SSTAT0,SPIORDY  jz p_mesgout_loop
-       test    SSTAT1,PHASEMIS jnz p_mesgout_phasemis
-       cmp     DINDEX,1        jne p_mesgout_outb      /* last byte? */
-       mvi     CLRSINT1,CLRATNO                        /* drop ATN */
-p_mesgout_outb:
-       dec     DINDEX
-       or      CLRSINT0, CLRSPIORDY
-       mov     SCSIDATL,SINDIR
-       
-p_mesgout4:
-       test    DINDEX,0xff     jnz p_mesgout_loop
+p_mesgout_from_host:
+       cmp     SINDEX, HOST_MSG        jne p_mesgout_onebyte;
+       jmp     host_message_loop;
+
+p_mesgout_onebyte:
+       mvi     CLRSINT1, CLRATNO;
+       mov     SCSIDATL, SINDEX;
 
 /*
- * If the next bus phase after ATN drops is message out, it means
+ * If the next bus phase after ATN drops is message out, it means
  * that the target is requesting that the last message(s) be resent.
  */
-p_mesgout_snoop:
-       test    SSTAT1,BUSFREE  jnz p_mesgout_done
-       test    SSTAT1,REQINIT  jz p_mesgout_snoop
-
-       test    SSTAT1,PHASEMIS jnz p_mesgout_done
-
-       or      SCSISIGO,ATNO                   /* turn on ATNO */
+       call    phase_lock;
+       cmp     LASTPHASE, P_MESGOUT    je p_mesgout_retry;
 
-       jmp     ITloop
-
-p_mesgout_phasemis:
-       mvi     CLRSINT1,CLRATNO        /* Be sure to turn ATNO off */
 p_mesgout_done:
-       clr     MSG_LEN                 /* no active msg */
-       jmp     ITloop
+       mvi     CLRSINT1,CLRATNO;       /* Be sure to turn ATNO off */
+       mov     LAST_MSG, MSG_OUT;
+       mvi     MSG_OUT, MSG_NOOP;      /* No message left */
+       jmp     ITloop;
 
 /*
  * Message in phase.  Bytes are read using Automatic PIO mode.
  */
 p_mesgin:
-       mvi     A               call inb_first  /* read the 1st message byte */
-       mov     REJBYTE,A                       /* save it for the driver */
-
-       test    A,MSG_IDENTIFYFLAG      jnz mesgin_identify
-       cmp     A,MSG_DISCONNECT        je mesgin_disconnect
-       cmp     A,MSG_SAVEDATAPOINTER   je mesgin_sdptrs
-       cmp     ALLZEROS,A              je mesgin_complete
-       cmp     A,MSG_RESTOREPOINTERS   je mesgin_rdptrs
-       cmp     A,MSG_EXTENDED          je mesgin_extended
-       cmp     A,MSG_MESSAGE_REJECT    je mesgin_reject
-
-rej_mesgin:
-/*
- * We have no idea what this message in is, and there's no way
- * to pass it up to the kernel, so we issue a message reject and
- * hope for the best.  Since we're now using manual PIO mode to
- * read in the message, there should no longer be a race condition
- * present when we assert ATN.  In any case, rejection should be a
- * rare occurrence - signal the driver when it happens.
- */
-       or      SCSISIGO,ATNO                   /* turn on ATNO */
-       mvi     INTSTAT,SEND_REJECT             /* let driver know */
-
-       mvi     MSG_MESSAGE_REJECT      call mk_mesg
+       mvi     ACCUM           call inb_first; /* read the 1st message byte */
+
+       test    A,MSG_IDENTIFYFLAG      jnz mesgin_identify;
+       cmp     A,MSG_DISCONNECT        je mesgin_disconnect;
+       cmp     A,MSG_SAVEDATAPOINTER   je mesgin_sdptrs;
+       cmp     ALLZEROS,A              je mesgin_complete;
+       cmp     A,MSG_RESTOREPOINTERS   je mesgin_rdptrs;
+       cmp     A,MSG_NOOP              je mesgin_done;
+
+/*
+ * Pushed message loop to allow the kernel to
+ * run it's own message state engine.  To avoid an
+ * extra nop instruction after signaling the kernel,
+ * we perform the phase_lock before checking to see
+ * if we should exit the loop and skip the phase_lock
+ * in the ITloop.  Performing back to back phase_locks
+ * shouldn't hurt, but why do it twice...
+ */
+host_message_loop:
+       mvi     INTSTAT, HOST_MSG_LOOP;
+       call    phase_lock;
+       cmp     RETURN_1, EXIT_MSG_LOOP je ITloop + 1;
+       jmp     host_message_loop;
 
 mesgin_done:
-       call    inb_last                        /*ack & turn auto PIO back on*/
-       jmp     ITloop
+       mov     NONE,SCSIDATL;          /*dummy read from latch to ACK*/
+       jmp     ITloop;
 
 
 mesgin_complete:
 /*
- * We got a "command complete" message, so put the SCB_TAG into QUEUEOUT,
- * and trigger a completion interrupt.  Check status for non zero return
- * and interrupt driver if needed.  This allows the driver to interpret
- * errors only when they occur instead of always uploading the scb.  If
- * the status is SCSI_CHECK, the driver will download a new scb requesting
- * sense to replace the old one, modify the "waiting for selection" SCB list
- * and set RETURN_1 to SEND_SENSE.  If RETURN_1 is set to SEND_SENSE the
- * sequencer imediately jumps to main loop where it will run down the waiting
- * SCB list and process the sense request.  If the kernel driver does not
- * wish to request sense, it need only clear RETURN_1, and the command is
- * allowed to complete.  We don't bother to post to the QOUTFIFO in the
- * error case since it would require extra work in the kernel driver to
- * ensure that the entry was removed before the command complete code tried
- * processing it.
- *
- * First check for residuals
+ * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO,
+ * and trigger a completion interrupt.  Before doing so, check to see if there
+ * is a residual or the status byte is something other than STATUS_GOOD (0).
+ * In either of these conditions, we upload the SCB back to the host so it can
+ * process this information.  In the case of a non zero status byte, we 
+ * additionally interrupt the kernel driver synchronously, allowing it to
+ * decide if sense should be retrieved.  If the kernel driver wishes to request
+ * sense, it will fill the kernel SCB with a request sense command and set
+ * RETURN_1 to SEND_SENSE.  If RETURN_1 is set to SEND_SENSE we redownload
+ * the SCB, and process it as the next command by adding it to the waiting list.
+ * If the kernel driver does not wish to request sense, it need only clear
+ * RETURN_1, and the command is allowed to complete normally.  We don't bother
+ * to post to the QOUTFIFO in the error cases since it would require extra
+ * work in the kernel driver to ensure that the entry was removed before the
+ * command complete code tried processing it.
  */
-       test    SCB_RESID_SGCNT,0xff    jz check_status
-/*
- * If we have a residual count, interrupt and tell the host.  Other
- * alternatives are to pause the sequencer on all command completes (yuck),
- * dma the resid directly to the host (slick, we may have space to do it now)
- * or have the sequencer pause itself when it encounters a non-zero resid 
- * (unecessary pause just to flag the command -yuck-, but takes one instruction
- * and since it shouldn't happen that often is good enough for our purposes).  
- */
-resid:
-       mvi     INTSTAT,RESIDUAL
 
-check_status:
-       test    SCB_TARGET_STATUS,0xff  jz status_ok    /* Good Status? */
-       mvi     INTSTAT,BAD_STATUS                      /* let driver know */
-       cmp     RETURN_1, SEND_SENSE    jne status_ok
-       jmp     mesgin_done
-
-status_ok:
-/* First, mark this target as free. */
-       test    SCB_CONTROL,TAG_ENB jnz test_immediate  /*
-                                                        * Tagged commands
-                                                        * don't busy the
-                                                        * target.
-                                                        */
-       mov     FUNCTION1,SCB_TCL
-       mov     A,FUNCTION1
-       test    SCB_TCL,0x88 jz clear_a
-       xor     ACTIVE_B,A
-       jmp     test_immediate
-
-clear_a:
-       xor     ACTIVE_A,A
-
-test_immediate:
-       test    SCB_CMDLEN,0xff jnz complete  /* Immediate message complete */
 /*
- * Pause the sequencer until the driver gets around to handling the command
- * complete.  This is so that any action that might require carefull timing
- * with the completion of this command can occur.
- */
-       mvi     INTSTAT,IMMEDDONE
-       jmp     start
-complete:
-       mov     QOUTFIFO,SCB_TAG
-       mvi     INTSTAT,CMDCMPLT
-       jmp     mesgin_done
-
-
-/*
- * Is it an extended message?  Copy the message to our message buffer and
- * notify the host.  The host will tell us whether to reject this message,
- * respond to it with the message that the host placed in our message buffer,
- * or simply to do nothing.
- */
-mesgin_extended:
-       mvi     MSGIN_EXT_LEN    call inb_next
-       mvi     MSGIN_EXT_OPCODE call inb_next
-       mov     A, MSGIN_EXT_LEN
-       dec     A       /* Length counts the op code */
-       mvi     SINDEX, MSGIN_EXT_BYTE0
-mesgin_extended_loop:
-       test    A, 0xFF         jz mesgin_extended_intr
-       cmp     SINDEX, MSGIN_EXT_LASTBYTE je mesgin_extended_dump
-       call    inb_next
-       dec     A
-/*
- * We pass the arg to inb in SINDEX, but DINDEX is the one incremented
- * so update SINDEX with DINDEX's value before looping again.
+ * First check for residuals
  */
-       mov     DINDEX          jmp mesgin_extended_loop
-mesgin_extended_dump:
-/* We have no more storage space, so dump the rest */
-       test    A, 0xFF         jz mesgin_extended_intr
-       mvi     NONE            call inb_next
-       dec     A
-       jmp     mesgin_extended_dump
-mesgin_extended_intr:
-       mvi     INTSTAT,EXTENDED_MSG            /* let driver know */
-       cmp     RETURN_1,SEND_REJ je rej_mesgin
-       cmp     RETURN_1,SEND_MSG jne mesgin_done
-/* The kernel has setup a message to be sent */
-       or      SCSISIGO,ATNO                   /* turn on ATNO */
-       jmp     mesgin_done
+       test    SCB_RESID_SGCNT,0xff    jnz upload_scb;
+       test    SCB_TARGET_STATUS,0xff  jz complete;    /* Good Status? */
+upload_scb:
+       mvi     DMAPARAMS, FIFORESET;
+       mov     SCB_TAG         call dma_scb;
+check_status:
+       test    SCB_TARGET_STATUS,0xff  jz complete;    /* Just a residual? */
+       mvi     INTSTAT,BAD_STATUS;                     /* let driver know */
+       nop;
+       cmp     RETURN_1, SEND_SENSE    jne complete;
+       /* This SCB becomes the next to execute as it will retrieve sense */
+       mvi     DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
+       mov     SCB_TAG         call dma_scb;
+add_to_waiting_list:
+       mov     SCB_NEXT,WAITING_SCBH;
+       mov     WAITING_SCBH, SCBPTR;
+       /*
+        * Prepare our selection hardware before the busfree so we have a
+        * high probability of winning arbitration.
+        */
+       call    start_selection;
+       jmp     await_busfree;
 
+complete:
+       /* If we are untagged, clear our address up in host ram */
+       test    SCB_CONTROL, TAG_ENB jnz complete_queue;
+       mov     A, SAVED_TCL;
+       /* fvdl - let ahc_intr clear this to avoid race conditions */
+       /* mvi  UNTAGGEDSCB_OFFSET call post_byte_setup; */
+       /* mvi  SCB_LIST_NULL call post_byte; */
+
+complete_queue:
+       mov     SCB_TAG call complete_post;
+       jmp     await_busfree;
+}
+
+complete_post:
+       /* Post the SCBID in SINDEX and issue an interrupt */
+       call    add_scb_to_free_list;
+       mov     ARG_1, SINDEX;
+       if ((ahc->features & AHC_QUEUE_REGS) != 0) {
+               mov     A, SDSCB_QOFF;
+       } else {
+               mov     A, QOUTPOS;
+       }
+       mvi     QOUTFIFO_OFFSET call post_byte_setup;
+       mov     ARG_1 call post_byte;
+       if ((ahc->features & AHC_QUEUE_REGS) == 0) {
+               inc     QOUTPOS;
+       }
+       mvi     INTSTAT,CMDCMPLT ret;
+
+if ((ahc->flags & AHC_INITIATORMODE) != 0) {
 /*
  * Is it a disconnect message?  Set a flag in the SCB to remind us
  * and await the bus going free.
  */
 mesgin_disconnect:
-       or      SCB_CONTROL,DISCONNECTED
-       test    FLAGS, PAGESCBS jz mesgin_done
-/*
- * Link this SCB into the DISCONNECTED list.  This list holds the
- * candidates for paging out an SCB if one is needed for a new command.
- * Modifying the disconnected list is a critical(pause dissabled) section.
- */
-       mvi     SCB_PREV, SCB_LIST_NULL
-       mvi     SEQCTL,0x50                     /* PAUSEDIS|FASTMODE */
-       mov     SCB_NEXT, DISCONNECTED_SCBH
-       mov     DISCONNECTED_SCBH, SCBPTR
-       cmp     SCB_NEXT,SCB_LIST_NULL je linkdone
-       mov     SCBPTR,SCB_NEXT
-       mov     SCB_PREV,DISCONNECTED_SCBH
-       mov     SCBPTR,DISCONNECTED_SCBH
-linkdone:
-       mvi     SEQCTL,0x10                     /* !PAUSEDIS|FASTMODE */
-       jmp     mesgin_done
+       or      SCB_CONTROL,DISCONNECTED;
+       call    add_scb_to_disc_list;
+       jmp     await_busfree;
 
 /*
- * Save data pointers message?  Copy working values into the SCB,
- * usually in preparation for a disconnect.
+ * Save data pointers message:
+ * Copying RAM values back to SCB, for Save Data Pointers message, but
+ * only if we've actually been into a data phase to change them.  This
+ * protects against bogus data in scratch ram and the residual counts
+ * since they are only initialized when we go into data_in or data_out.
  */
 mesgin_sdptrs:
-       call    sg_ram2scb
-       jmp     mesgin_done
+       test    SEQ_FLAGS, DPHASE       jz mesgin_done;
+
+       /*
+        * The SCB SGPTR becomes the next one we'll download,
+        * and the SCB DATAPTR becomes the current SHADDR.
+        * Use the residual number since STCNT is corrupted by
+        * any message transfer.
+        */
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               bmov    SCB_SGCOUNT, SG_COUNT, 5;
+               bmov    SCB_DATAPTR, SHADDR, 4;
+               bmov    SCB_DATACNT, SCB_RESID_DCNT, 3;
+       } else {
+               mvi     DINDEX, SCB_SGCOUNT;
+               mvi     SG_COUNT call bcopy_5;
+       
+               mvi     DINDEX, SCB_DATAPTR;
+               mvi     SHADDR          call bcopy_4;
+               mvi     SCB_RESID_DCNT  call bcopy_3;
+       }
+       jmp     mesgin_done;
 
 /*
  * Restore pointers message?  Data pointers are recopied from the
@@ -740,11 +1289,12 @@ mesgin_sdptrs:
  * code do the rest.
  */
 mesgin_rdptrs:
-       and     FLAGS,0xef                      /*
-                                                * !DPHASE we'll reload them
+       and     SEQ_FLAGS, ~DPHASE;             /*
+                                                * We'll reload them
                                                 * the next time through
+                                                * the dataphase.
                                                 */
-       jmp     mesgin_done
+       jmp     mesgin_done;
 
 /*
  * Identify message?  For a reconnecting target, this tells us the lun
@@ -752,118 +1302,83 @@ mesgin_rdptrs:
  * clearing the "disconnected" bit so we don't "find" it by accident later.
  */
 mesgin_identify:
-       test    A,0x78  jnz rej_mesgin  /*!DiscPriv|!LUNTAR|!Reserved*/
-
-       and     A,0x07                  /* lun in lower three bits */
-       or      SAVED_TCL,A,SELID          
-       and     SAVED_TCL,0xf7
-       and     A,SELBUSB,SBLKCTL       /* B Channel?? */
-       or      SAVED_TCL,A
-       call    inb_last                /* ACK */
-
+       if ((ahc->features & AHC_WIDE) != 0) {
+               and     A,0x0f;         /* lun in lower four bits */
+       } else {
+               and     A,0x07;         /* lun in lower three bits */
+       }
+       or      SAVED_TCL,A;            /* SAVED_TCL should be complete now */
+
+       mvi     ARG_2, SCB_LIST_NULL;   /* SCBID of prev SCB in disc List */
+       call    get_untagged_SCBID;
+       cmp     ARG_1, SCB_LIST_NULL    je snoop_tag;
+       if ((ahc->flags & AHC_PAGESCBS) != 0) {
+               test    SEQ_FLAGS, SCBPTR_VALID jz use_retrieveSCB;
+       }
+       /*
+        * If the SCB was found in the disconnected list (as is
+        * always the case in non-paging scenarios), SCBPTR is already
+        * set to the correct SCB.  So, simply setup the SCB and get
+        * on with things.
+        */
+       call    rem_scb_from_disc_list;
+       jmp     setup_SCB;
 /*
  * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
- * If we get one, we use the tag returned to switch to find the proper
- * SCB.  With SCB paging, this requires using findSCB for both tagged
+ * If we get one, we use the tag returned to find the proper
+ * SCB.  With SCB paging, this requires using search for both tagged
  * and non-tagged transactions since the SCB may exist in any slot.
  * If we're not using SCB paging, we can use the tag as the direct
  * index to the SCB.
  */
-       mvi     ARG_1,SCB_LIST_NULL     /* Default to no-tag */
+snoop_tag:
+       mov     NONE,SCSIDATL;          /* ACK Identify MSG */
 snoop_tag_loop:
-       test    SSTAT1,BUSFREE          jnz use_findSCB
-       test    SSTAT1,REQINIT          jz snoop_tag_loop
-       test    SSTAT1,PHASEMIS         jnz use_findSCB
-       mvi     A                       call inb_first
-       cmp     A,MSG_SIMPLE_Q_TAG      jne use_findSCB
+       call    phase_lock;
+       cmp     LASTPHASE, P_MESGIN     jne not_found;
+       cmp     SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found;
 get_tag:
-       mvi     ARG_1   call inb_next   /* tag value */
-/*
- * See if the tag is in range.  The tag is < SCBCOUNT if we add
- * the complement of SCBCOUNT to the incomming tag and there is
- * no carry.
- */
-       mov     A,COMP_SCBCOUNT 
-       add     SINDEX,A,ARG_1
-       jc      abort_tag
+       mvi     ARG_1   call inb_next;  /* tag value */
 
-/*
- * Ensure that the SCB the tag points to is for an SCB transaction
- * to the reconnecting target.
- */
-       test    FLAGS, PAGESCBS jz index_by_tag
-       call    inb_last                        /* Ack Tag */
-use_findSCB:
-       mov     ALLZEROS        call findSCB      /* Have to search */
+       /*
+        * Ensure that the SCB the tag points to is for
+        * an SCB transaction to the reconnecting target.
+        */
+use_retrieveSCB:
+       call    retrieveSCB;
 setup_SCB:
-       and     SCB_CONTROL,0xfb          /* clear disconnect bit in SCB */
-       or      FLAGS,IDENTIFY_SEEN       /* make note of IDENTIFY */
-       jmp     ITloop
-index_by_tag:
-       mov     SCBPTR,ARG_1
-       mov     A,SAVED_TCL
-       cmp     SCB_TCL,A               jne abort_tag
-       test    SCB_CONTROL,TAG_ENB     jz  abort_tag
-       call    inb_last                        /* Ack Successful tag */
-       jmp     setup_SCB
-
-abort_tag:
-       or      SCSISIGO,ATNO                   /* turn on ATNO */
-       mvi     INTSTAT,ABORT_TAG               /* let driver know */
-       mvi     MSG_ABORT_TAG   call mk_mesg    /* ABORT TAG message */
-       jmp     mesgin_done
-
-/*
- * Message reject?  Let the kernel driver handle this.  If we have an 
- * outstanding WDTR or SDTR negotiation, assume that it's a response from 
- * the target selecting 8bit or asynchronous transfer, otherwise just ignore 
- * it since we have no clue what it pertains to.
- */
-mesgin_reject:
-       mvi     INTSTAT, REJECT_MSG
-       jmp     mesgin_done
+       mov     A, SAVED_TCL;
+       cmp     SCB_TCL, A      jne not_found_cleanup_scb;
+       test    SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;
+       and     SCB_CONTROL,~DISCONNECTED;
+       or      SEQ_FLAGS,IDENTIFY_SEEN;        /* make note of IDENTIFY */
+       call    set_transfer_settings;
+       /* See if the host wants to send a message upon reconnection */
+       test    SCB_CONTROL, MK_MESSAGE jz mesgin_done;
+       and     SCB_CONTROL, ~MK_MESSAGE;
+       mvi     HOST_MSG        call mk_mesg;
+       jmp     mesgin_done;
+
+not_found_cleanup_scb:
+       test    SCB_CONTROL, DISCONNECTED jz . + 3;
+       call    add_scb_to_disc_list;
+       jmp     not_found;
+       call    add_scb_to_free_list;
+not_found:
+       mvi     INTSTAT, NO_MATCH;
+       jmp     mesgin_done;
 
 /*
  * [ ADD MORE MESSAGE HANDLING HERE ]
  */
 
-/*
- * Bus free phase.  It might be useful to interrupt the device
- * driver if we aren't expecting this.  For now, make sure that
- * ATN isn't being asserted and look for a new command.
- */
-p_busfree:
-       mvi     CLRSINT1,CLRATNO
-       clr     LASTPHASE
-
-/*
- * if this is an immediate command, perform a psuedo command complete to
- * notify the driver.
- */
-       test    SCB_CMDLEN,0xff jz status_ok
-       jmp     start
-
 /*
  * Locking the driver out, build a one-byte message passed in SINDEX
  * if there is no active message already.  SINDEX is returned intact.
  */
 mk_mesg:
-       mvi     SEQCTL,0x50                     /* PAUSEDIS|FASTMODE */
-       test    MSG_LEN,0xff    jz mk_mesg1     /* Should always succeed */
-       
-       /*
-        * Hmmm.  For some reason the mesg buffer is in use.
-        * Tell the driver.  It should look at SINDEX to find
-        * out what we wanted to use the buffer for and resolve
-        * the conflict.
-        */
-       mvi     SEQCTL,0x10                     /* !PAUSEDIS|FASTMODE */
-       mvi     INTSTAT,MSG_BUFFER_BUSY
-
-mk_mesg1:
-       mvi     MSG_LEN,1               /* length = 1 */
-       mov     MSG0,SINDEX             /* 1-byte message */
-       mvi     SEQCTL,0x10     ret     /* !PAUSEDIS|FASTMODE */
+       or      SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */
+       mov     MSG_OUT,SINDEX ret;
 
 /*
  * Functions to read data in Automatic PIO mode.
@@ -880,26 +1395,75 @@ mk_mesg1:
  * and that REQ is already set when inb_first is called.  inb_{first,next}
  * use the same calling convention as inb.
  */
-
+inb_next_wait_perr:
+       mvi     INTSTAT, PERR_DETECTED;
+       jmp     inb_next_wait;
 inb_next:
-       or      CLRSINT0, CLRSPIORDY
-       mov     NONE,SCSIDATL                   /*dummy read from latch to ACK*/
+       mov     NONE,SCSIDATL;          /*dummy read from latch to ACK*/
 inb_next_wait:
-       test    SSTAT1,PHASEMIS jnz mesgin_phasemis
-       test    SSTAT0,SPIORDY  jz inb_next_wait /* wait for next byte */
+       /*
+        * If there is a parity error, wait for the kernel to
+        * see the interrupt and prepare our message response
+        * before continuing.
+        */
+       test    SSTAT1, REQINIT jz inb_next_wait;
+       test    SSTAT1, SCSIPERR jnz inb_next_wait_perr;
+inb_next_check_phase:
+       and     LASTPHASE, PHASE_MASK, SCSISIGI;
+       cmp     LASTPHASE, P_MESGIN jne mesgin_phasemis;
 inb_first:
-       mov     DINDEX,SINDEX
-       test    SSTAT1,PHASEMIS jnz mesgin_phasemis
-       mov     DINDIR,SCSIBUSL ret             /*read byte directly from bus*/
+       mov     DINDEX,SINDEX;
+       mov     DINDIR,SCSIBUSL ret;            /*read byte directly from bus*/
 inb_last:
-       mov     NONE,SCSIDATL ret               /*dummy read from latch to ACK*/
+       mov     NONE,SCSIDATL ret;              /*dummy read from latch to ACK*/
+}
 
+if ((ahc->flags & AHC_TARGETMODE) != 0) {
+/*
+ * Change to a new phase.  If we are changing the state of the I/O signal,
+ * from out to in, wait an additional data release delay before continuing.
+ */
+change_phase:
+       /* Wait for preceeding I/O session to complete. */
+       test    SCSISIGI, ACKI jnz .;
+
+       /* Change the phase */
+       and     DINDEX, IOI, SCSISIGI;
+       mov     SCSISIGO, SINDEX;
+       and     A, IOI, SINDEX;
+
+       /*
+        * If the data direction has changed, from
+        * out (initiator driving) to in (target driving),
+        * we must waitat least a data release delay plus
+        * the normal bus settle delay. [SCSI III SPI 10.11.0]
+        */
+       cmp     DINDEX, A je change_phase_wait;
+       test    SINDEX, IOI jz change_phase_wait;
+       call    change_phase_wait;
+change_phase_wait:
+       nop;
+       nop;
+       nop;
+       nop ret;
+
+/*
+ * Send a byte to an initiator in Automatic PIO mode.
+ */
+target_outb:
+       or      SXFRCTL0, SPIOEN;
+       test    SSTAT0, SPIORDY jz .;
+       mov     SCSIDATL, SINDEX;
+       test    SSTAT0, SPIORDY jz .;
+       and     SXFRCTL0, ~SPIOEN ret;
+}
+       
 mesgin_phasemis:
 /*
  * We expected to receive another byte, but the target changed phase
  */
-       mvi     INTSTAT, MSGIN_PHASEMIS
-       jmp     ITloop
+       mvi     INTSTAT, MSGIN_PHASEMIS;
+       jmp     ITloop;
 
 /*
  * DMA data transfer.  HADDR and HCNT must be loaded first, and
@@ -908,10 +1472,11 @@ mesgin_phasemis:
  * during initialization.
  */
 dma:
-       mov     DFCNTRL,SINDEX
-dma1:
-       test    SSTAT0,DMADONE  jnz dma3
-       test    SSTAT1,PHASEMIS jz dma1         /* ie. underrun */
+       mov     DFCNTRL,SINDEX;
+dma_loop:
+       test    SSTAT0,DMADONE  jnz dma_dmadone;
+       test    SSTAT1,PHASEMIS jz dma_loop;    /* ie. underrun */
+dma_phasemis:
 
 /*
  * We will be "done" DMAing when the transfer count goes to zero, or
@@ -921,157 +1486,378 @@ dma1:
  * magically on STCNT=0 or a phase change, so just wait for FIFO empty
  * status.
  */
-dma3:
-       test    SINDEX,DIRECTION        jnz dma5
-dma4:
-       test    DFSTATUS,FIFOEMP        jz dma4
+dma_checkfifo:
+       test    DFCNTRL,DIRECTION       jnz dma_fifoempty;
+dma_fifoflush:
+       test    DFSTATUS,FIFOEMP        jz dma_fifoflush;
 
+dma_fifoempty:
+       /* Don't clobber an inprogress host data transfer */
+       test    DFSTATUS, MREQPEND      jnz dma_fifoempty;
 /*
  * Now shut the DMA enables off and make sure that the DMA enables are 
  * actually off first lest we get an ILLSADDR.
  */
-dma5:
-       /* disable DMA, but maintain WIDEODD */
-       and     DFCNTRL,WIDEODD
-dma6:
-       test    DFCNTRL,0x38    jnz dma6  /* SCSIENACK|SDMAENACK|HDMAENACK */
+dma_dmadone:
+       and     DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
+dma_halt:
+       /*
+        * Some revisions of the aic7880 have a problem where, if the
+        * data fifo is full, but the PCI input latch is not empty, 
+        * HDMAEN cannot be cleared.  The fix used here is to attempt
+        * to drain the data fifo until there is space for the input
+        * latch to drain and HDMAEN de-asserts.
+        */
+       if ((ahc->features & AHC_ULTRA2) == 0) {
+               mov     NONE, DFDAT;
+       }
+       test    DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;
 return:
-       ret
-
-/*
- * Common SCSI initialization for selection and reselection.  Expects
- * the target SCSI ID to be in the upper four bits of SINDEX, and A's
- * contents are stomped on return.
- */
-initialize_scsiid:
-       and     SINDEX,0xf0             /* Get target ID */
-       and     A,0x0f,SCSIID
-       or      SINDEX,A
-       mov     SCSIID,SINDEX ret
+       ret;
 
 /*
  * Assert that if we've been reselected, then we've seen an IDENTIFY
  * message.
  */
 assert:
-       test    FLAGS,RESELECTED        jz return       /* reselected? */
-       test    FLAGS,IDENTIFY_SEEN     jnz return      /* seen IDENTIFY? */
+       test    SEQ_FLAGS,IDENTIFY_SEEN jnz return;     /* seen IDENTIFY? */
 
-       mvi     INTSTAT,NO_IDENT        ret     /* no - cause a kernel panic */
+       mvi     INTSTAT,NO_IDENT        ret;    /* no - tell the kernel */
 
 /*
- * Locate the SCB matching the target ID/channel/lun in SAVED_TCL, and the tag
- * value in ARG_1.  If ARG_1 == SCB_LIST_NULL, we're looking for a non-tagged
- * SCB.  Have the kernel print a warning message if it can't be found, and
- * generate an ABORT/ABORT_TAG message to the target.  SINDEX should be
- * cleared on call.
+ * Locate a disconnected SCB either by SAVED_TCL (ARG_1 is SCB_LIST_NULL)
+ * or by the SCBID ARG_1.  The search begins at the SCB index passed in
+ * via SINDEX which is an SCB that must be on the disconnected list.  If
+ * the SCB cannot be found, SINDEX will be SCB_LIST_NULL, otherwise, SCBPTR
+ * is set to the proper SCB.
  */
 findSCB:
-       mov     A,SAVED_TCL
-       mov     SCBPTR,SINDEX                   /* switch to next SCB */
-       mvi     SEQCTL,0x50                     /* PAUSEDIS|FASTMODE */
-       cmp     SCB_TCL,A       jne findSCB1 /* target ID/channel/lun match? */
-       test    SCB_CONTROL,DISCONNECTED jz findSCB1 /*should be disconnected*/
-       test    SCB_CONTROL,TAG_ENB jnz findTaggedSCB
-       cmp     ARG_1,SCB_LIST_NULL je foundSCB
-       jmp     findSCB1
-findTaggedSCB:
-       mov     A, ARG_1                        /* Tag passed in ARG_1 */
-       cmp     SCB_TAG,A       jne findSCB1    /* Found it? */
-foundSCB:
-       test    FLAGS,PAGESCBS  jz foundSCB_ret
+       mov     SCBPTR,SINDEX;                  /* Initialize SCBPTR */
+       cmp     ARG_1, SCB_LIST_NULL    jne findSCB_by_SCBID;
+       mov     A, SAVED_TCL;
+       mvi     SCB_TCL jmp findSCB_loop;       /* &SCB_TCL -> SINDEX */
+findSCB_by_SCBID:
+       mov     A, ARG_1;                       /* Tag passed in ARG_1 */
+       mvi     SCB_TAG jmp findSCB_loop;       /* &SCB_TAG -> SINDEX */
+findSCB_next:
+       mov     ARG_2, SCBPTR;
+       cmp     SCB_NEXT, SCB_LIST_NULL je notFound;
+       mov     SCBPTR,SCB_NEXT;
+       dec     SINDEX;         /* Last comparison moved us too far */
+findSCB_loop:
+       cmp     SINDIR, A       jne findSCB_next;
+       mov     SINDEX, SCBPTR  ret;
+notFound:
+       mvi     SINDEX, SCB_LIST_NULL   ret;
+
+/*
+ * Retrieve an SCB by SCBID first searching the disconnected list falling
+ * back to DMA'ing the SCB down from the host.  This routine assumes that
+ * ARG_1 is the SCBID of interrest and that SINDEX is the position in the
+ * disconnected list to start the search from.  If SINDEX is SCB_LIST_NULL,
+ * we go directly to the host for the SCB.
+ */
+retrieveSCB:
+       test    SEQ_FLAGS, SCBPTR_VALID jz retrieve_from_host;
+       mov     SCBPTR  call findSCB;   /* Continue the search */
+       cmp     SINDEX, SCB_LIST_NULL   je retrieve_from_host;
+
+/*
+ * This routine expects SINDEX to contain the index of the SCB to be
+ * removed, SCBPTR to be pointing to that SCB, and ARG_2 to be the
+ * SCBID of the SCB just previous to this one in the list or SCB_LIST_NULL
+ * if it is at the head.
+ */
+rem_scb_from_disc_list:
 /* Remove this SCB from the disconnection list */
-       cmp     SCB_NEXT,SCB_LIST_NULL je unlink_prev
-       mov     SAVED_LINKPTR, SCB_PREV
-       mov     SCBPTR, SCB_NEXT
-       mov     SCB_PREV, SAVED_LINKPTR
-       mov     SCBPTR, SINDEX
-unlink_prev:
-       cmp     SCB_PREV,SCB_LIST_NULL  je rHead/* At the head of the list */
-       mov     SAVED_LINKPTR, SCB_NEXT
-       mov     SCBPTR, SCB_PREV
-       mov     SCB_NEXT, SAVED_LINKPTR
-       mov     SCBPTR, SINDEX
-       mvi     SEQCTL,0x10     ret             /* !PAUSEDIS|FASTMODE */
+       cmp     ARG_2, SCB_LIST_NULL    je rHead;
+       mov     DINDEX, SCB_NEXT;
+       mov     SCBPTR, ARG_2;
+       mov     SCB_NEXT, DINDEX;
+       mov     SCBPTR, SINDEX ret;
 rHead:
-       mov     DISCONNECTED_SCBH,SCB_NEXT
-foundSCB_ret:
-       mvi     SEQCTL,0x10     ret             /* !PAUSEDIS|FASTMODE */
-
-findSCB1:
-       mvi     SEQCTL,0x10                     /* !PAUSEDIS|FASTMODE */
-       inc     SINDEX
-       mov     A,SCBCOUNT
-       cmp     SINDEX,A        jne findSCB
-
-       mvi     INTSTAT,NO_MATCH                /* not found - signal kernel */
-       cmp     RETURN_1,SCB_PAGEDIN je return
-       or      SCSISIGO,ATNO                   /* assert ATNO */
-       cmp     ARG_1,SCB_LIST_NULL jne find_abort_tag
-       mvi     MSG_ABORT       call mk_mesg
-       jmp     ITloop
-find_abort_tag:
-       mvi     MSG_ABORT_TAG   call mk_mesg
-       jmp     ITloop
-
-/*
- * Make a working copy of the scatter-gather parameters from the SCB.
- */
-sg_scb2ram:
-       mov     HADDR0, SCB_DATAPTR0
-       mov     HADDR1, SCB_DATAPTR1
-       mov     HADDR2, SCB_DATAPTR2
-       mov     HADDR3, SCB_DATAPTR3
-       mov     HCNT0, SCB_DATACNT0
-       mov     HCNT1, SCB_DATACNT1
-       mov     HCNT2, SCB_DATACNT2
-
-       mov     STCNT0, HCNT0
-       mov     STCNT1, HCNT1
-       mov     STCNT2, HCNT2
-
-       mov     SG_COUNT,SCB_SGCOUNT
-
-       mov     SG_NEXT0, SCB_SGPTR0
-       mov     SG_NEXT1, SCB_SGPTR1
-       mov     SG_NEXT2, SCB_SGPTR2
-       mov     SG_NEXT3, SCB_SGPTR3 ret
+       mov     DISCONNECTED_SCBH,SCB_NEXT ret;
+
+retrieve_from_host:
+/*
+ * We didn't find it.  Pull an SCB and DMA down the one we want.
+ * We should never get here in the non-paging case.
+ */
+       mov     ALLZEROS        call    get_free_or_disc_scb;
+       mvi     DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
+       /* Jump instead of call as we want to return anyway */
+       mov     ARG_1   jmp dma_scb;
+
+/*
+ * Determine whether a target is using tagged or non-tagged transactions
+ * by first looking for a matching transaction based on the TCL and if
+ * that fails, looking up this device in the host's untagged SCB array.
+ * The TCL to search for is assumed to be in SAVED_TCL.  The value is
+ * returned in ARG_1 (SCB_LIST_NULL for tagged, SCBID for non-tagged).
+ * The SCBPTR_VALID bit is set in SEQ_FLAGS if we found the information
+ * in an SCB instead of having to go to the host.
+ */
+get_untagged_SCBID:
+       cmp     DISCONNECTED_SCBH, SCB_LIST_NULL je get_SCBID_from_host;
+       mvi     ARG_1, SCB_LIST_NULL;
+       mov     DISCONNECTED_SCBH call findSCB;
+       cmp     SINDEX, SCB_LIST_NULL   je get_SCBID_from_host;
+       or      SEQ_FLAGS, SCBPTR_VALID;/* Was in disconnected list */
+       test    SCB_CONTROL, TAG_ENB    jnz . + 2;
+       mov     ARG_1, SCB_TAG  ret;
+       mvi     ARG_1, SCB_LIST_NULL ret;
+
+/*
+ * Fetch a byte from host memory given an index of (A + (256 * SINDEX))
+ * and a base address of SCBID_ADDR.  The byte is returned in RETURN_2.
+ */
+fetch_byte:
+       mov     ARG_2, SINDEX;
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               mvi     DINDEX, CCHADDR;
+               mvi     SCBID_ADDR call set_1byte_addr;
+               mvi     CCHCNT, 1;
+               mvi     CCSGCTL, CCSGEN|CCSGRESET;
+               test    CCSGCTL, CCSGDONE jz .;
+               mvi     CCSGCTL, CCSGRESET;
+               bmov    RETURN_2, CCSGRAM, 1 ret;
+       } else {
+               mvi     DINDEX, HADDR;
+               mvi     SCBID_ADDR call set_1byte_addr;
+               mvi     HCNT[0], 1;
+               clr     HCNT[1];
+               clr     HCNT[2];
+               mvi     DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
+               call    dma_finish;
+               mov     RETURN_2, DFDAT ret;
+       }
+
+/*
+ * Prepare the hardware to post a byte to host memory given an
+ * index of (A + (256 * SINDEX)) and a base address of SCBID_ADDR.
+ */
+post_byte_setup:
+       mov     ARG_2, SINDEX;
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               mvi     DINDEX, CCHADDR;
+               mvi     SCBID_ADDR call set_1byte_addr;
+               mvi     CCHCNT, 1;
+               mvi     CCSCBCTL, CCSCBRESET ret;
+       } else {
+               mvi     DINDEX, HADDR;
+               mvi     SCBID_ADDR call set_1byte_addr;
+               mvi     HCNT[0], 1;
+               clr     HCNT[1];
+               clr     HCNT[2];
+               mvi     DFCNTRL, FIFORESET ret;
+       }
+
+post_byte:
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               bmov    CCSCBRAM, SINDEX, 1;
+               or      CCSCBCTL, CCSCBEN|CCSCBRESET;
+               test    CCSCBCTL, CCSCBDONE jz .;
+               clr     CCSCBCTL ret;
+       } else {
+               mov     DFDAT, SINDEX;
+               or      DFCNTRL, HDMAEN|FIFOFLUSH;
+               jmp     dma_finish;
+       }
+
+get_SCBID_from_host:
+       mov     A, SAVED_TCL;
+       mvi     UNTAGGEDSCB_OFFSET call fetch_byte;
+       mov     RETURN_1,  RETURN_2 ret;
+
+phase_lock_perr:
+       mvi     INTSTAT, PERR_DETECTED;
+phase_lock:     
+       /*
+        * If there is a parity error, wait for the kernel to
+        * see the interrupt and prepare our message response
+        * before continuing.
+        */
+       test    SSTAT1, REQINIT jz phase_lock;
+       test    SSTAT1, SCSIPERR jnz phase_lock_perr;
+phase_lock_latch_phase:
+       and     SCSISIGO, PHASE_MASK, SCSISIGI;
+       and     LASTPHASE, PHASE_MASK, SCSISIGI ret;
+
+if ((ahc->features & AHC_CMD_CHAN) == 0) {
+set_stcnt_from_hcnt:
+       mov     STCNT[0], HCNT[0];
+       mov     STCNT[1], HCNT[1];
+       mov     STCNT[2], HCNT[2] ret;
+
+bcopy_7:
+       mov     DINDIR, SINDIR;
+       mov     DINDIR, SINDIR;
+bcopy_5:
+       mov     DINDIR, SINDIR;
+bcopy_4:
+       mov     DINDIR, SINDIR;
+bcopy_3:
+       mov     DINDIR, SINDIR;
+       mov     DINDIR, SINDIR;
+       mov     DINDIR, SINDIR ret;
+}
+
+if ((ahc->flags & AHC_TARGETMODE) != 0) {
+/*
+ * Setup addr assuming that A is an index into
+ * an array of 32byte objects, SINDEX contains
+ * the base address of that array, and DINDEX
+ * contains the base address of the location
+ * to store the indexed address.
+ */
+set_32byte_addr:
+       shr     ARG_2, 3, A;
+       shl     A, 5;
+       jmp     set_1byte_addr;
+}
+
+/*
+ * Setup addr assuming that A is an index into
+ * an array of 64byte objects, SINDEX contains
+ * the base address of that array, and DINDEX
+ * contains the base address of the location
+ * to store the indexed address.
+ */
+set_64byte_addr:
+       shr     ARG_2, 2, A;
+       shl     A, 6;
+
+/*
+ * Setup addr assuming that A + (ARG_1 * 256) is an
+ * index into an array of 1byte objects, SINDEX contains
+ * the base address of that array, and DINDEX contains
+ * the base address of the location to store the computed
+ * address.
+ */
+set_1byte_addr:
+       add     DINDIR, A, SINDIR;
+       mov     A, ARG_2;
+       adc     DINDIR, A, SINDIR;
+       clr     A;
+       adc     DINDIR, A, SINDIR;
+       adc     DINDIR, A, SINDIR ret;
+
+/*
+ * Either post or fetch and SCB from host memory based on the
+ * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX.
+ */
+dma_scb:
+       mov     A, SINDEX;
+       if ((ahc->features & AHC_CMD_CHAN) != 0) {
+               mvi     DINDEX, CCHADDR;
+               mvi     HSCB_ADDR call set_64byte_addr;
+               mov     CCSCBPTR, SCBPTR;
+               test    DMAPARAMS, DIRECTION jz dma_scb_tohost;
+               mvi     CCHCNT, SCB_64BYTE_SIZE;
+               mvi     CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET;
+               cmp     CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;
+               jmp     dma_scb_finish;
+dma_scb_tohost:
+               mvi     CCHCNT, SCB_32BYTE_SIZE;
+               if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
+                       mvi     CCSCBCTL, CCSCBRESET;
+                       bmov    CCSCBRAM, SCB_CONTROL, SCB_32BYTE_SIZE;
+                       or      CCSCBCTL, CCSCBEN|CCSCBRESET;
+                       test    CCSCBCTL, CCSCBDONE jz .;
+               } else {
+                       mvi     CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;
+                       cmp     CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;
+               }
+dma_scb_finish:
+               clr     CCSCBCTL;
+               test    CCSCBCTL, CCARREN|CCSCBEN jnz .;
+               ret;
+       } else {
+               mvi     DINDEX, HADDR;
+               mvi     HSCB_ADDR call set_64byte_addr;
+               mvi     HCNT[0], SCB_32BYTE_SIZE;
+               clr     HCNT[1];
+               clr     HCNT[2];
+               mov     DFCNTRL, DMAPARAMS;
+               test    DMAPARAMS, DIRECTION    jnz dma_scb_fromhost;
+               /* Fill it with the SCB data */
+copy_scb_tofifo:
+               mvi     SINDEX, SCB_CONTROL;
+               add     A, SCB_32BYTE_SIZE, SINDEX;
+copy_scb_tofifo_loop:
+               mov     DFDAT,SINDIR;
+               mov     DFDAT,SINDIR;
+               mov     DFDAT,SINDIR;
+               mov     DFDAT,SINDIR;
+               mov     DFDAT,SINDIR;
+               mov     DFDAT,SINDIR;
+               mov     DFDAT,SINDIR;
+               cmp     SINDEX, A jne copy_scb_tofifo_loop;
+               or      DFCNTRL, HDMAEN|FIFOFLUSH;
+dma_scb_fromhost:
+               call    dma_finish;
+               /* If we were putting the SCB, we are done */
+               test    DMAPARAMS, DIRECTION    jz      return;
+               mvi     SCB_CONTROL  call dfdat_in_7;
+               call    dfdat_in_7_continued;
+               call    dfdat_in_7_continued;
+               jmp     dfdat_in_7_continued;
+dfdat_in_7:
+               mov     DINDEX,SINDEX;
+dfdat_in_7_continued:
+               mov     DINDIR,DFDAT;
+               mov     DINDIR,DFDAT;
+               mov     DINDIR,DFDAT;
+               mov     DINDIR,DFDAT;
+               mov     DINDIR,DFDAT;
+               mov     DINDIR,DFDAT;
+               mov     DINDIR,DFDAT ret;
+       }
 
-/*
- * Copying RAM values back to SCB, for Save Data Pointers message, but
- * only if we've actually been into a data phase to change them.  This
- * protects against bogus data in scratch ram and the residual counts
- * since they are only initialized when we go into data_in or data_out.
- */
-sg_ram2scb:
-       test    FLAGS, DPHASE   jz return
-       mov     SCB_SGCOUNT,SG_COUNT
-
-       mov     SCB_SGPTR0,SG_NEXT0
-       mov     SCB_SGPTR1,SG_NEXT1
-       mov     SCB_SGPTR2,SG_NEXT2
-       mov     SCB_SGPTR3,SG_NEXT3
-       
-       mov     SCB_DATAPTR0,SHADDR0
-       mov     SCB_DATAPTR1,SHADDR1
-       mov     SCB_DATAPTR2,SHADDR2
-       mov     SCB_DATAPTR3,SHADDR3
 
 /*
- * Use the residual number since STCNT is corrupted by any message transfer
+ * Wait for DMA from host memory to data FIFO to complete, then disable
+ * DMA and wait for it to acknowledge that it's off.
  */
-       mov     SCB_DATACNT0,SCB_RESID_DCNT0
-       mov     SCB_DATACNT1,SCB_RESID_DCNT1
-       mov     SCB_DATACNT2,SCB_RESID_DCNT2 ret
-
+dma_finish:
+       test    DFSTATUS,HDONE  jz dma_finish;
+       /* Turn off DMA */
+       and     DFCNTRL, ~HDMAEN;
+       test    DFCNTRL, HDMAEN jnz .;
+       ret;
+
+add_scb_to_free_list:
+       if ((ahc->flags & AHC_PAGESCBS) != 0) {
+               mov     SCB_NEXT, FREE_SCBH;
+               mvi     SCB_TAG, SCB_LIST_NULL;
+               mov     FREE_SCBH, SCBPTR ret;
+       } else {
+               mvi     SCB_TAG, SCB_LIST_NULL ret;
+       }
+
+if ((ahc->flags & AHC_PAGESCBS) != 0) {
+get_free_or_disc_scb:
+       cmp     FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
+       cmp     DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
+return_error:
+       mvi     SINDEX, SCB_LIST_NULL   ret;
+dequeue_disc_scb:
+       mov     SCBPTR, DISCONNECTED_SCBH;
+dma_up_scb:
+       mvi     DMAPARAMS, FIFORESET;
+       mov     SCB_TAG         call dma_scb;
+unlink_disc_scb:
+       mov     DISCONNECTED_SCBH, SCB_NEXT ret;
+dequeue_free_scb:
+       mov     SCBPTR, FREE_SCBH;
+       mov     FREE_SCBH, SCB_NEXT ret;
+}
+
+add_scb_to_disc_list:
 /*
- * Add the array base TARG_SCRATCH to the target offset (the target address
- * is in SCSIID), and return the result in SINDEX.  The accumulator
- * contains the 3->8 decoding of the target ID on return.
+ * Link this SCB into the DISCONNECTED list.  This list holds the
+ * candidates for paging out an SCB if one is needed for a new command.
+ * Modifying the disconnected list is a critical(pause dissabled) section.
  */
-ndx_dtr:
-       shr     A,SCSIID,4
-       test    SBLKCTL,SELBUSB jz ndx_dtr_2
-       or      A,0x08          /* Channel B entries add 8 */
-ndx_dtr_2:
-       add     SINDEX,TARG_SCRATCH,A ret
+       mov     SCB_NEXT, DISCONNECTED_SCBH;
+       mov     DISCONNECTED_SCBH, SCBPTR ret;
diff --git a/sys/dev/microcode/aic7xxx/aic7xxx_asm.1 b/sys/dev/microcode/aic7xxx/aic7xxx_asm.1
deleted file mode 100644 (file)
index 6ba7a14..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-.\"    $OpenBSD: aic7xxx_asm.1,v 1.6 1999/07/09 13:35:34 aaron Exp $
-.\"
-.\" Copyright (c) 1994, 1995
-.\"    Justin T. Gibbs.  All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. The name of the author may not be used to endorse or promote products
-.\"    derived from this software without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.\"
-.Dd November 11, 1994
-.Dt AIC7XXX_ASM 1
-.Os
-.Sh NAME
-.Nm aic7xxx_asm
-.Nd Assembler for the Adaptec aic7xxx family of asics
-.Sh SYNOPSIS
-.Nm aic7xxx_asm
-.Op Fl d
-.Op Fl D Ar variable=value
-.Op Fl v
-.Op Fl o Ar file
-.Ar source-file
-.Sh DESCRIPTION
-The Adaptec aic7xxx family of asics are single chip SCSI controllers with a
-RISC like command processor.  This assembler parses the language outlined
-in the Adaptec technical document
-.%T "AIC-7770 (EISA/ISA Bus Master Single-Chip SCSI Host Adaptor) Data Book"
-and produces ascii output intended for a C byte array.
-.Pp
-The aic7xxx assembler is required to compile kernels with aic7xxx SCSI
-adaptor support (AHA-274x, AHA-284x, AHA-294x controllers) and is compiled,
-installed, and used automatically in the kernel compile directory when
-necessary.
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl D Ar variable=value
-Define
-.Ar variable
-to be
-.Ar value
-in the global context
-.It Fl d
-Turn on debugging
-.It Fl v
-Print version information
-.It Fl o Ar file
-Redirect assembler output to
-.Ar file
-.Sh AUTHOR
-This aic7770 assembler was written by
-John Aycock (aycock@cpsc.ucalgary.ca)
diff --git a/sys/dev/microcode/aic7xxx/aic7xxx_asm.c b/sys/dev/microcode/aic7xxx/aic7xxx_asm.c
deleted file mode 100644 (file)
index 39df041..0000000
+++ /dev/null
@@ -1,687 +0,0 @@
-/*     $OpenBSD: aic7xxx_asm.c,v 1.7 1997/01/15 23:42:08 millert Exp $ */
-
-/*+M*************************************************************************
- * Adaptec AIC7770/AIC7870 sequencer code assembler.
- *
- * Copyright (c) 1994 John Aycock
- *   The University of Calgary Department of Computer Science.
- *   All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by the University of Calgary
- *      Department of Computer Science and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE 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.
- *
- * Comments are started by `#' and continue to the end of the line; lines
- * may be of the form:
- *      <label>*
- *      <label>*  <undef-sym> = <value>
- *      <label>*  <opcode> <operand>*
- *
- * A <label> is an <undef-sym> ending in a colon.  Spaces, tabs, and commas
- * are token separators.
- *
- *-M*************************************************************************/
-static char id[] = "$Id: aic7xxx_asm.c,v 1.7 1997/01/15 23:42:08 millert Exp $";
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#define MEMORY         448
-#define MAXLINE                1024
-#define MAXTOKEN       32
-#define ADOTOUT                "a.out"
-#define NOVALUE                -1
-
-/*
- * AIC-7770/AIC-7870 register definitions
- */
-#define R_SINDEX       0x65
-#define R_ALLONES      0x69
-#define R_ALLZEROS     0x6a
-#define R_NONE         0x6a
-
-int debug;
-int lineno, LC;
-char *filename;
-unsigned char M[MEMORY][4];
-
-void
-error(char *s)
-{
-       fprintf(stderr, "%s: %s at line %d\n", filename, s, lineno);
-       exit(EXIT_FAILURE);
-}
-
-void *
-Malloc(size_t size)
-{
-       void *p = malloc(size);
-       if (!p)
-               error("out of memory");
-       return(p);
-}
-
-void *
-Realloc(void *ptr, size_t size)
-{
-       void *p = realloc(ptr, size);
-       if (!p)
-               error("out of memory");
-       return(p);
-}
-
-char *
-Strdup(char *s)
-{
-       char *p = (char *)Malloc(strlen(s) + 1);
-       strcpy(p, s);
-       return(p);
-}
-
-typedef struct sym_t {
-       struct sym_t    *next;          /* MUST BE FIRST */
-       char            *name;
-       int             value;
-       int             npatch;
-       int             *patch;
-} sym_t;
-
-sym_t *head;
-
-void
-define(char *name, int value)
-{
-       sym_t *p, *q;
-
-       for (p = head, q = (sym_t *)&head; p; p = p->next) {
-               if (!strcmp(p->name, name))
-                       error("redefined symbol");
-               q = p;
-       }
-
-       p = q->next = (sym_t *)Malloc(sizeof(sym_t));
-       p->next = NULL;
-       p->name = Strdup(name);
-       p->value = value;
-       p->npatch = 0;
-       p->patch = NULL;
-
-       if (debug) {
-               fprintf(stderr, "\"%s\" ", p->name);
-               if (p->value != NOVALUE)
-                       fprintf(stderr, "defined as 0x%x\n", p->value);
-               else
-                       fprintf(stderr, "undefined\n");
-       }
-}
-
-sym_t *
-lookup(char *name)
-{
-       sym_t *p;
-
-       for (p = head; p; p = p->next)
-               if (!strcmp(p->name, name))
-                       return(p);
-       return(NULL);
-}
-
-void
-patch(sym_t *p, int location)
-{
-       p->npatch += 1;
-       p->patch = (int *)Realloc(p->patch, p->npatch * sizeof(int *));
-
-       p->patch[p->npatch - 1] = location;
-}
-
-void backpatch(void)
-{
-       int i;
-       sym_t *p;
-
-       for (p = head; p; p = p->next) {
-
-               if (p->value == NOVALUE) {
-                       fprintf(stderr,
-                               "%s: undefined symbol \"%s\"\n",
-                               filename, p->name);
-                       exit(EXIT_FAILURE);
-               }
-
-               if (p->npatch) {
-                       if (debug)
-                               fprintf(stderr,
-                                       "\"%s\" (0x%x) patched at",
-                                       p->name, p->value);
-
-                       for (i = 0; i < p->npatch; i++) {
-                               M[p->patch[i]][0] &= ~1;
-                               M[p->patch[i]][0] |= ((p->value >> 8) & 1);
-                               M[p->patch[i]][1] = p->value & 0xff;
-
-                               if (debug)
-                                       fprintf(stderr, " 0x%x", p->patch[i]);
-                       }
-
-                       if (debug)
-                               fputc('\n', stderr);
-               }
-       }
-}
-
-/*
- *  Output words in byte-reversed order (least significant first)
- *  since the sequencer RAM is loaded that way.
- */
-void
-output(FILE *fp)
-{
-       int i;
-
-       for (i = 0; i < LC; i++)
-               fprintf(fp, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
-                       M[i][3],
-                       M[i][2],
-                       M[i][1],
-                       M[i][0]);
-       printf("%d out of %d instructions used.\n", LC, MEMORY);
-}
-
-char **
-getl(int *n)
-{
-       int i;
-       char *p, *quote;
-       static char buf[MAXLINE];
-       static char *a[MAXTOKEN];
-
-       i = 0;
-
-       while (fgets(buf, sizeof(buf), stdin)) {
-
-               lineno += 1;
-
-               if (buf[strlen(buf)-1] != '\n')
-                       error("line too long");
-
-               p = strchr(buf, '#');
-               if (p)
-                       *p = '\0';
-               p = buf;
-rescan:
-               quote = strchr(p, '\"');
-               if (quote)
-                       *quote = '\0';
-               for (p = strtok(p, ", \t\n"); p; p = strtok(NULL, ", \t\n"))
-                       if (i < MAXTOKEN-1)
-                               a[i++] = p;
-                       else
-                               error("too many tokens");
-               if (quote) {
-                       quote++;
-                       p = strchr(quote, '\"');
-                       if (!p)
-                               error("unterminated string constant");
-                       else if (i < MAXTOKEN-1) {
-                               a[i++] = quote;
-                               *p = '\0';
-                               p++;
-                       }
-                       else
-                               error("too many tokens");
-                       goto rescan;
-               }
-               if (i) {
-                       *n = i;
-                       return(a);
-               }
-       }
-       return(NULL);
-}
-
-#define A      0x8000          /* `A'ccumulator ok */
-#define I      0x4000          /* use as immediate value */
-#define SL     0x2000          /* shift left */
-#define SR     0x1000          /* shift right */
-#define RL     0x0800          /* rotate left */
-#define RR     0x0400          /* rotate right */
-#define LO     0x8000          /* lookup: ori-{jmp,jc,jnc,call} */
-#define LA     0x4000          /* lookup: and-{jz,jnz} */
-#define LX     0x2000          /* lookup: xor-{je,jne} */
-#define NA     -1              /* not applicable */
-
-struct {
-       char *name;
-       int n;                  /* number of operands, including opcode */
-       unsigned int op;        /* immediate or L?|pos_from_0 */
-       unsigned int dest;      /* NA, pos_from_0, or I|immediate */
-       unsigned int src;       /* NA, pos_from_0, or I|immediate */
-       unsigned int imm;       /* pos_from_0, A|pos_from_0, or I|immediate */
-       unsigned int addr;      /* NA or pos_from_0 */
-       int fmt;                /* instruction format - 1, 2, or 3 */
-} instr[] = {
-/*
- *               N  OP    DEST         SRC             IMM     ADDR    FMT
- */
-       { "mov",  3, 1,    1,           2,              I|0xff, NA,     1 },
-       { "mov",  4, LO|2, NA,          1,              I|0,    3,      3 },
-       { "mvi",  3, 0,    1,           I|R_ALLZEROS,   A|2,    NA,     1 },
-       { "mvi",  4, LO|2, NA,          I|R_ALLZEROS,   1,      3,      3 },
-       { "not",  2, 2,    1,           1,              I|0xff, NA,     1 },
-       { "and",  3, 1,    1,           1,              A|2,    NA,     1 },
-       { "and",  4, 1,    1,           3,              A|2,    NA,     1 },
-       { "or",   3, 0,    1,           1,              A|2,    NA,     1 },
-       { "or",   4, 0,    1,           3,              A|2,    NA,     1 },
-       { "or",   5, LO|3, NA,          1,              2,      4,      3 },
-       { "xor",  3, 2,    1,           1,              A|2,    NA,     1 },
-       { "xor",  4, 2,    1,           3,              A|2,    NA,     1 },
-       { "nop",  1, 1,    I|R_NONE,    I|R_ALLZEROS,   I|0xff, NA,     1 },
-       { "inc",  2, 3,    1,           1,              I|1,    NA,     1 },
-       { "inc",  3, 3,    1,           2,              I|1,    NA,     1 },
-       { "dec",  2, 3,    1,           1,              I|0xff, NA,     1 },
-       { "dec",  3, 3,    1,           2,              I|0xff, NA,     1 },
-       { "jmp",  2, LO|0,   NA,        I|R_SINDEX,     I|0,    1,      3 },
-       { "jc",   2, LO|0,   NA,        I|R_SINDEX,     I|0,    1,      3 },
-       { "jnc",  2, LO|0,   NA,        I|R_SINDEX,     I|0,    1,      3 },
-       { "call", 2, LO|0,   NA,        I|R_SINDEX,     I|0,    1,      3 },
-       { "test", 5, LA|3,   NA,        1,              A|2,    4,      3 },
-       { "cmp",  5, LX|3,   NA,        1,              A|2,    4,      3 },
-       { "ret",  1, 1,  I|R_NONE,      I|R_ALLZEROS,   I|0xff, NA,     1 },
-       { "ret",  1, 1,  I|R_NONE,      I|R_ALLZEROS,   I|0xff, NA,     1 },
-       { "clc",  1, 3,  I|R_NONE,      I|R_ALLZEROS,   I|1,    NA,     1 },
-       { "clc",  4, 3,  2,             I|R_ALLZEROS,   A|3,    NA,     1 },
-       { "stc",  2, 3,  1,             I|R_ALLONES,    I|1,    NA,     1 },
-       { "add",  3, 3,  1,             1,              A|2,    NA,     1 },
-       { "add",  4, 3,  1,             3,              A|2,    NA,     1 },
-       { "adc",  3, 4,  1,             1,              A|2,    NA,     1 },
-       { "adc",  4, 4,  1,             3,              A|2,    NA,     1 },
-       { "shl",  3, 5,  1,             1,              SL|2,   NA,     2 },
-       { "shl",  4, 5,  1,             2,              SL|3,   NA,     2 },
-       { "shr",  3, 5,  1,             1,              SR|2,   NA,     2 },
-       { "shr",  4, 5,  1,             2,              SR|3,   NA,     2 },
-       { "rol",  3, 5,  1,             1,              RL|2,   NA,     2 },
-       { "rol",  4, 5,  1,             2,              RL|3,   NA,     2 },
-       { "ror",  3, 5,  1,             1,              RR|2,   NA,     2 },
-       { "ror",  4, 5,  1,             2,              RR|3,   NA,     2 },
-       /*
-        *  Extensions (note also that mvi allows A)
-        */
-       { "clr",  2, 1,  1,     I|R_ALLZEROS,           I|0xff, NA,     1 },
-       { 0,      0, 0,  0,     0,                      0,      0,      0 }
-};
-
-int
-eval_operand(char **a, int spec)
-{
-       int i;
-       unsigned int want = spec & (LO|LA|LX);
-
-       static struct {
-               unsigned int what;
-               char *name;
-               int value;
-       } jmptab[] = {
-               { LO,   "jmp",          8  },
-               { LO,   "jc",           9  },
-               { LO,   "jnc",          10 },
-               { LO,   "call",         11 },
-               { LA,   "jz",           15 },
-               { LA,   "jnz",          13 },
-               { LX,   "je",           14 },
-               { LX,   "jne",          12 },
-       };
-
-       spec &= ~(LO|LA|LX);
-
-       for (i = 0; i < sizeof(jmptab)/sizeof(jmptab[0]); i++)
-               if (jmptab[i].what == want &&
-                   !strcmp(jmptab[i].name, a[spec]))
-               {
-                       return(jmptab[i].value);
-               }
-
-       if (want)
-               error("invalid jump");
-
-       return(spec);           /* "case 0" - no flags set */
-}
-
-int
-eval_sdi(char **a, int spec)
-{
-       sym_t *p;
-       unsigned val;
-
-       if (spec == NA)
-               return(NA);
-
-       switch (spec & (A|I|SL|SR|RL|RR)) {
-           case SL:
-           case SR:
-           case RL:
-           case RR:
-               if (isdigit(*a[spec &~ (SL|SR|RL|RR)]))
-                       val = strtol(a[spec &~ (SL|SR|RL|RR)], NULL, 0);
-               else {
-                       p = lookup(a[spec &~ (SL|SR|RL|RR)]);
-                       if (!p)
-                               error("undefined symbol used");
-                       val = p->value;
-               }
-
-               switch (spec & (SL|SR|RL|RR)) {         /* blech */
-                   case SL:
-                       if (val > 7)
-                               return(0xf0);
-                       return(((val % 8) << 4) |
-                              (val % 8));
-                   case SR:
-                       if (val > 7)
-                               return(0xf0);
-                       return(((val % 8) << 4) |
-                              (1 << 3) |
-                              ((8 - (val % 8)) % 8));
-                   case RL:
-                       return(val % 8);
-                   case RR:
-                       return((8 - (val % 8)) % 8);
-               }
-           case I:
-               return(spec &~ I);
-           case A:
-               /*
-                *  An immediate field of zero selects
-                *  the accumulator.  Vigorously object
-                *  if zero is given otherwise - it's
-                *  most likely an error.
-                */
-               spec &= ~A;
-               if (!strcmp("A", a[spec]))
-                       return(0);
-               if (isdigit(*a[spec]) &&
-                   strtol(a[spec], NULL, 0) == 0)
-               {
-                       error("immediate value of zero selects accumulator");
-               }
-               /* falls through */
-           case 0:
-               if (isdigit(*a[spec]))
-                       return(strtol(a[spec], NULL, 0));
-               p = lookup(a[spec]);
-               if (p)
-                       return(p->value);
-               error("undefined symbol used");
-       }
-
-       return(NA);             /* shut the compiler up */
-}
-
-int
-eval_addr(char **a, int spec)
-{
-       sym_t *p;
-
-       if (spec == NA)
-               return(NA);
-       if (isdigit(*a[spec]))
-               return(strtol(a[spec], NULL, 0));
-
-       p = lookup(a[spec]);
-
-       if (p) {
-               if (p->value != NOVALUE)
-                       return(p->value);
-               patch(p, LC);
-       } else {
-               define(a[spec], NOVALUE);
-               p = lookup(a[spec]);
-               patch(p, LC);
-       }
-
-       return(NA);             /* will be patched in later */
-}
-
-int
-crack(char **a, int n)
-{
-       int i;
-       int I_imm, I_addr;
-       int I_op, I_dest, I_src, I_ret;
-
-       /*
-        *  Check for "ret" at the end of the line; remove
-        *  it unless it's "ret" alone - we still want to
-        *  look it up in the table.
-        */
-       I_ret = (strcmp(a[n-1], "ret") ? 0 : !0);
-       if (I_ret && n > 1)
-               n -= 1;
-
-       for (i = 0; instr[i].name; i++) {
-               /*
-                *  Look for match in table given constraints,
-                *  currently just the name and the number of
-                *  operands.
-                */
-               if (!strcmp(instr[i].name, *a) && instr[i].n == n)
-                       break;
-       }
-       if (!instr[i].name)
-               error("unknown opcode or wrong number of operands");
-
-       I_op    = eval_operand(a, instr[i].op);
-       I_src   = eval_sdi(a, instr[i].src);
-       I_imm   = eval_sdi(a, instr[i].imm);
-       I_dest  = eval_sdi(a, instr[i].dest);
-       I_addr  = eval_addr(a, instr[i].addr);
-
-       if( LC >= MEMORY )
-               error("Memory exhausted!\n");
-
-       switch (instr[i].fmt) {
-           case 1:
-           case 2:
-               M[LC][0] = (I_op << 1) | I_ret;
-               M[LC][1] = I_dest;
-               M[LC][2] = I_src;
-               M[LC][3] = I_imm;
-               break;
-           case 3:
-               if (I_ret)
-                       error("illegal use of \"ret\"");
-               M[LC][0] = (I_op << 1) | ((I_addr >> 8) & 1);
-               M[LC][1] = I_addr & 0xff;
-               M[LC][2] = I_src;
-               M[LC][3] = I_imm;
-               break;
-       }
-
-       return (1);             /* no two-byte instructions yet */
-}
-
-#undef SL
-#undef SR
-#undef RL
-#undef RR
-#undef LX
-#undef LA
-#undef LO
-#undef I
-#undef A
-
-void
-assemble(FILE *ofile)
-{
-       int n;
-       char **a;
-       sym_t *p;
-
-       while ((a = getl(&n))) {
-
-               while (a[0][strlen(*a)-1] == ':') {
-                       a[0][strlen(*a)-1] = '\0';
-                       p = lookup(*a);
-                       if (p)
-                               p->value = LC;
-                       else
-                               define(*a, LC);
-                       a += 1;
-                       n -= 1;
-               }
-
-               if (!n)                 /* line was all labels */
-                       continue;
-
-               if (n == 3 && !strcmp("VERSION", *a))
-                       fprintf(ofile, "#define %s \"%s\"\n", a[1], a[2]);
-               else {
-                       if (n == 3 && !strcmp("=", a[1]))
-                               define(*a, strtol(a[2], NULL, 0));
-                       else
-                               LC += crack(a, n);
-               }
-       }
-
-       backpatch();
-       output(ofile);
-
-       if (debug)
-               output(stderr);
-}
-
-int
-main(int argc, char **argv)
-{
-       int c;
-       int pid;
-       int ifile;
-       FILE *ofile;
-       int fd[2];
-
-       ofile = NULL;
-       while ((c = getopt(argc, argv, "dho:vD:")) != -1) {
-               switch (c) {
-                   case 'd':
-                       debug = !0;
-                       break;
-                   case 'D':
-                   {
-                       char *p;
-                       if ((p = strchr(optarg, '=')) != NULL) {
-                               *p = '\0';
-                               define(optarg, strtol(p + 1, NULL, 0));
-                       }
-                       else
-                               define(optarg, 1);
-                       break;
-                   }
-                   case 'o':
-                       
-                       if ((ofile = fopen(optarg, "w")) == NULL) {
-                               perror(optarg);
-                               exit(EXIT_FAILURE);
-                       }
-                       break;
-                   case 'h':
-                       printf("usage: %s [-d] [-Dname] [-ooutput] input\n",
-                               *argv);
-                       exit(EXIT_SUCCESS);
-                       break;
-                   case 'v':
-                       printf("%s\n", id);
-                       exit(EXIT_SUCCESS);
-                       break;
-                   default:
-                       exit(EXIT_FAILURE);
-                       break;
-               }
-       }
-
-       if (argc - optind != 1) {
-               fprintf(stderr, "%s: must have one input file\n", *argv);
-               exit(EXIT_FAILURE);
-       }
-       filename = argv[optind];
-
-       
-       if ((ifile = open(filename, O_RDONLY)) < 0) {
-               perror(filename);
-               exit(EXIT_FAILURE);
-       }
-
-       if (!ofile) {
-               if ((ofile = fopen(ADOTOUT, "w")) == NULL) {
-                       perror(ADOTOUT);
-                       exit(EXIT_FAILURE);
-               }
-       }
-
-       if (pipe(fd) < 0) {
-               perror("pipe failed");
-               exit(1);
-       }
-
-       if ((pid = fork()) < 0 ) {
-               perror("fork failed");
-               exit(1);
-       }
-       else if (pid > 0) {             /* Parent */
-               close(fd[1]);           /* Close write end */
-               if (fd[0] != STDIN_FILENO) {
-                       if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) {
-                               perror("dup2 error on stdin");
-                               exit(EXIT_FAILURE);
-                       }
-                       close(fd[0]);
-               }
-               assemble(ofile);
-               exit(EXIT_SUCCESS);
-       }
-       else {                          /* Child */
-               close(fd[0]);           /* Close Read end */
-               if (fd[1] != STDOUT_FILENO) {
-                       if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
-                               perror("dup2 error on stdout");
-                               exit(EXIT_FAILURE);
-                       }
-                       close(fd[1]);
-               }
-               if (ifile != STDIN_FILENO) {
-                       if (dup2(ifile, STDIN_FILENO) != STDIN_FILENO) {
-                               perror("dup2 error on stdin");
-                               exit(EXIT_FAILURE);
-                       }
-                       close(ifile);
-               }
-               execl("/usr/bin/cpp", "/usr/bin/cpp", "-P", "-", "-", NULL);
-       }
-       return(EXIT_SUCCESS);
-}
diff --git a/sys/dev/microcode/aic7xxx/aic7xxx_reg.h b/sys/dev/microcode/aic7xxx/aic7xxx_reg.h
deleted file mode 100644 (file)
index b29f23e..0000000
+++ /dev/null
@@ -1,784 +0,0 @@
-/*     $OpenBSD: aic7xxx_reg.h,v 1.3 1997/11/07 08:07:16 niklas Exp $*/
-
-/*
- * Aic7xxx register and scratch ram definitions.
- *
- * Copyright (c) 1994, 1995, 1996 Justin T. Gibbs.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice immediately at the beginning of the file, without modification,
- *    this list of conditions, and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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.
- *
- */
-
-/*
- * This header is shared by the sequencer code and the kernel level driver.
- *
- * All page numbers refer to the Adaptec AIC-7770 Data Book availible from
- * Adaptec's Technical Documents Department 1-800-934-2766
- */
-
-/*
- * SCSI Sequence Control (p. 3-11).
- * Each bit, when set starts a specific SCSI sequence on the bus
- */
-#define SCSISEQ                        0x000
-#define                TEMODEO         0x80
-#define                ENSELO          0x40
-#define                ENSELI          0x20
-#define                ENRSELI         0x10
-#define                ENAUTOATNO      0x08
-#define                ENAUTOATNI      0x04
-#define                ENAUTOATNP      0x02
-#define                SCSIRSTO        0x01
-
-/*
- * SCSI Transfer Control 0 Register (pp. 3-13).
- * Controls the SCSI module data path.
- */
-#define        SXFRCTL0                0x001
-#define                DFON            0x80
-#define                DFPEXP          0x40
-#define                ULTRAEN         0x20
-#define                CLRSTCNT        0x10
-#define                SPIOEN          0x08
-#define                SCAMEN          0x04
-#define                CLRCHN          0x02
-/*  UNUSED                     0x01 */
-
-/*
- * SCSI Transfer Control 1 Register (pp. 3-14,15).
- * Controls the SCSI module data path.
- */
-#define        SXFRCTL1                0x002
-#define                BITBUCKET       0x80
-#define                SWRAPEN         0x40
-#define                ENSPCHK         0x20
-#define                STIMESEL        0x18
-#define                ENSTIMER        0x04
-#define                ACTNEGEN        0x02
-#define                STPWEN          0x01    /* Powered Termination */
-
-/*
- * SCSI Control Signal Read Register (p. 3-15).
- * Reads the actual state of the SCSI bus pins
- */
-#define SCSISIGI               0x003
-#define                CDI             0x80
-#define                IOI             0x40
-#define                MSGI            0x20
-#define                ATNI            0x10
-#define                SELI            0x08
-#define                BSYI            0x04
-#define                REQI            0x02
-#define                ACKI            0x01
-
-/*
- * Possible phases in SCSISIGI
- */
-#define                PHASE_MASK      0xe0
-#define                P_DATAOUT       0x00
-#define                P_DATAIN        0x40
-#define                P_COMMAND       0x80
-#define                P_MESGOUT       0xa0
-#define                P_STATUS        0xc0
-#define                P_MESGIN        0xe0
-/*
- * SCSI Contol Signal Write Register (p. 3-16).
- * Writing to this register modifies the control signals on the bus.  Only
- * those signals that are allowed in the current mode (Initiator/Target) are
- * asserted.
- */
-#define SCSISIGO               0x003
-#define                CDO             0x80
-#define                IOO             0x40
-#define                MSGO            0x20
-#define                ATNO            0x10
-#define                SELO            0x08
-#define                BSYO            0x04
-#define                REQO            0x02
-#define                ACKO            0x01
-
-/* 
- * SCSI Rate Control (p. 3-17).
- * Contents of this register determine the Synchronous SCSI data transfer
- * rate and the maximum synchronous Req/Ack offset.  An offset of 0 in the
- * SOFS (3:0) bits disables synchronous data transfers.  Any offset value
- * greater than 0 enables synchronous transfers.
- */
-#define SCSIRATE               0x004
-#define                WIDEXFER        0x80            /* Wide transfer control */
-#define                SXFR            0x70            /* Sync transfer rate */
-#define                SOFS            0x0f            /* Sync offset */
-
-/*
- * SCSI ID (p. 3-18).
- * Contains the ID of the board and the current target on the
- * selected channel.
- */
-#define SCSIID                 0x005
-#define                TID             0xf0            /* Target ID mask */
-#define                OID             0x0f            /* Our ID mask */
-
-/*
- * SCSI Latched Data (p. 3-19).
- * Read/Write latchs used to transfer data on the SCSI bus during
- * Automatic or Manual PIO mode.  SCSIDATH can be used for the
- * upper byte of a 16bit wide asyncronouse data phase transfer.
- */
-#define SCSIDATL               0x006
-#define SCSIDATH               0x007
-
-/*
- * SCSI Transfer Count (pp. 3-19,20)
- * These registers count down the number of bytes transfered
- * across the SCSI bus.  The counter is decremented only once
- * the data has been safely transfered.  SDONE in SSTAT0 is
- * set when STCNT goes to 0
- */ 
-#define STCNT                  0x008
-#define STCNT0                 0x008
-#define STCNT1                 0x009
-#define STCNT2                 0x00a
-
-/*
- * Clear SCSI Interrupt 0 (p. 3-20)
- * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT0.
- */
-#define        CLRSINT0                0x00b
-#define                CLRSELDO        0x40
-#define                CLRSELDI        0x20
-#define                CLRSELINGO      0x10
-#define                CLRSWRAP        0x08
-/*  UNUSED                     0x04 */
-#define                CLRSPIORDY      0x02
-/*  UNUSED                     0x01 */
-
-/*
- * SCSI Status 0 (p. 3-21)
- * Contains one set of SCSI Interrupt codes
- * These are most likely of interest to the sequencer
- */
-#define SSTAT0                 0x00b
-#define                TARGET          0x80            /* Board acting as target */
-#define                SELDO           0x40            /* Selection Done */
-#define                SELDI           0x20            /* Board has been selected */
-#define                SELINGO         0x10            /* Selection In Progress */
-#define                SWRAP           0x08            /* 24bit counter wrap */
-#define                SDONE           0x04            /* STCNT = 0x000000 */
-#define                SPIORDY         0x02            /* SCSI PIO Ready */
-#define                DMADONE         0x01            /* DMA transfer completed */
-
-/*
- * Clear SCSI Interrupt 1 (p. 3-23)
- * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT1.
- */
-#define CLRSINT1               0x00c
-#define                CLRSELTIMEO     0x80
-#define                CLRATNO         0x40
-#define                CLRSCSIRSTI     0x20
-/*  UNUSED                     0x10 */
-#define                CLRBUSFREE      0x08
-#define                CLRSCSIPERR     0x04
-#define                CLRPHASECHG     0x02
-#define                CLRREQINIT      0x01
-
-/*
- * SCSI Status 1 (p. 3-24)
- */
-#define SSTAT1                 0x00c
-#define                SELTO           0x80
-#define                ATNTARG         0x40
-#define                SCSIRSTI        0x20
-#define                PHASEMIS        0x10
-#define                BUSFREE         0x08
-#define                SCSIPERR        0x04
-#define                PHASECHG        0x02
-#define                REQINIT         0x01
-
-/*
- * SCSI Interrupt Mode 1 (pp. 3-28,29)
- * Setting any bit will enable the corresponding function
- * in SIMODE1 to interrupt via the IRQ pin.
- */
-#define        SIMODE1                 0x011
-#define                ENSELTIMO       0x80
-#define                ENATNTARG       0x40
-#define                ENSCSIRST       0x20
-#define                ENPHASEMIS      0x10
-#define                ENBUSFREE       0x08
-#define                ENSCSIPERR      0x04
-#define                ENPHASECHG      0x02
-#define                ENREQINIT       0x01
-
-/*
- * SCSI Data Bus (High) (p. 3-29)
- * This register reads data on the SCSI Data bus directly.
- */
-#define        SCSIBUSL                0x012
-#define        SCSIBUSH                0x013
-
-/*
- * SCSI/Host Address (p. 3-30)
- * These registers hold the host address for the byte about to be
- * transfered on the SCSI bus.  They are counted up in the same
- * manner as STCNT is counted down.  SHADDR should always be used
- * to determine the address of the last byte transfered since HADDR
- * can be squewed by write ahead.
- */
-#define        SHADDR                  0x014
-#define        SHADDR0                 0x014
-#define        SHADDR1                 0x015
-#define        SHADDR2                 0x016
-#define        SHADDR3                 0x017
-
-/*
- * Selection/Reselection ID (p. 3-31)
- * Upper four bits are the device id.  The ONEBIT is set when the re/selecting
- * device did not set its own ID.
- */
-#define SELID                  0x019
-#define                SELID_MASK      0xf0
-#define                ONEBIT          0x08
-/*  UNUSED                     0x07 */
-
-/*
- * SCSI Block Control (p. 3-32)
- * Controls Bus type and channel selection.  In a twin channel configuration
- * addresses 0x00-0x1e are gated to the appropriate channel based on this
- * register.  SELWIDE allows for the coexistence of 8bit and 16bit devices
- * on a wide bus.
- */
-#define SBLKCTL                        0x01f
-#define                DIAGLEDEN       0x80    /* Aic78X0 only */
-#define                DIAGLEDON       0x40    /* Aic78X0 only */
-#define                AUTOFLUSHDIS    0x20
-/*  UNUSED                     0x10 */
-#define                SELBUS_MASK     0x0a
-#define                SELBUSB         0x08
-/*  UNUSED                     0x04 */
-#define                SELWIDE         0x02
-/*  UNUSED                     0x01 */
-#define                SELNARROW       0x00
-
-/*
- * Sequencer Control (p. 3-33)
- * Error detection mode and speed configuration
- */
-#define SEQCTL                 0x060
-#define                PERRORDIS       0x80
-#define                PAUSEDIS        0x40
-#define                FAILDIS         0x20
-#define        FASTMODE        0x10
-#define                BRKADRINTEN     0x08
-#define                STEP            0x04
-#define                SEQRESET        0x02
-#define                LOADRAM         0x01
-
-/*
- * Sequencer RAM Data (p. 3-34)
- * Single byte window into the Scratch Ram area starting at the address
- * specified by SEQADDR0 and SEQADDR1.  To write a full word, simply write
- * four bytes in sucessesion.  The SEQADDRs will increment after the most
- * significant byte is written
- */
-#define SEQRAM                 0x061
-
-/*
- * Sequencer Address Registers (p. 3-35)
- * Only the first bit of SEQADDR1 holds addressing information
- */
-#define SEQADDR0               0x062
-#define SEQADDR1               0x063
-#define        SEQADDR1_MASK   0x01
-
-/*
- * Accumulator
- * We cheat by passing arguments in the Accumulator up to the kernel driver
- */
-#define ACCUM                  0x064
-
-#define SINDEX                 0x065
-#define DINDEX                 0x066
-#define ALLZEROS               0x06a
-#define NONE                   0x06a
-#define SINDIR                 0x06c
-#define DINDIR                 0x06d
-#define FUNCTION1              0x06e
-
-/*
- * Host Address (p. 3-48)
- * This register contains the address of the byte about
- * to be transfered across the host bus.
- */
-#define HADDR                  0x088
-#define HADDR0                 0x088
-#define HADDR1                 0x089
-#define HADDR2                 0x08a
-#define HADDR3                 0x08b
-
-#define HCNT                   0x08c
-#define HCNT0                  0x08c
-#define HCNT1                  0x08d
-#define HCNT2                  0x08e
-/*
- * SCB Pointer (p. 3-49)
- * Gate one of the four SCBs into the SCBARRAY window.
- */
-#define SCBPTR                 0x090
-
-/*
- * Board Control (p. 3-43)
- */
-#define BCTL                   0x084
-/*   RSVD                      0xf0 */
-#define                ACE             0x08    /* Support for external processors */
-/*   RSVD                      0x06 */
-#define                ENABLE          0x01
-
-/*
- * On the aic78X0 chips, Board Control is replaced by the DSCommand
- * register (p. 4-64)
- */
-#define        DSCOMMAND               0x084
-#define                CACHETHEN       0x80    /* Cache Threshold enable */
-#define                DPARCKEN        0x40    /* Data Parity Check Enable */
-#define                MPARCKEN        0x20    /* Memory Parity Check Enable */
-#define                EXTREQLCK       0x10    /* External Request Lock */
-
-/*
- * Bus On/Off Time (p. 3-44)
- */
-#define BUSTIME                        0x085
-#define                BOFF            0xf0
-#define                BON             0x0f
-
-/*
- * Bus Speed (p. 3-45)
- */
-#define        BUSSPD                  0x086
-#define                DFTHRSH         0xc0
-#define                STBOFF          0x38
-#define                STBON           0x07
-#define                DFTHRSH_100     0xc0
-
-/*
- * Host Control (p. 3-47) R/W
- * Overal host control of the device.
- */
-#define HCNTRL                 0x087
-/*    UNUSED                   0x80 */
-#define                POWRDN          0x40
-/*    UNUSED                   0x20 */
-#define                SWINT           0x10
-#define                IRQMS           0x08
-#define                PAUSE           0x04
-#define                INTEN           0x02
-#define                CHIPRST         0x01
-#define                CHIPRSTACK      0x01
-
-/*
- * Interrupt Status (p. 3-50)
- * Status for system interrupts
- */
-#define INTSTAT                        0x091
-#define                SEQINT_MASK     0xf1            /* SEQINT Status Codes */
-#define                        BAD_PHASE       0x01    /* unknown scsi bus phase */
-#define                        SEND_REJECT     0x11    /* sending a message reject */
-#define                        NO_IDENT        0x21    /* no IDENTIFY after reconnect*/
-#define                        NO_MATCH        0x31    /* no cmd match for reconnect */
-#define                        SDTR_MSG        0x41    /* SDTR message received */
-#define                        WDTR_MSG        0x51    /* WDTR message received */
-#define                        REJECT_MSG      0x61    /* Reject message received */
-#define                        BAD_STATUS      0x71    /* Bad status from target */
-#define                        RESIDUAL        0x81    /* Residual byte count != 0 */
-#define                        ABORT_TAG       0x91    /* Sent an ABORT_TAG message */
-#define                        AWAITING_MSG    0xa1    /*
-                                                * Kernel requested to specify
-                                                 * a message to this target
-                                                 * (command was null), so tell
-                                                 * it that it can fill the
-                                                 * message buffer.
-                                                 */
-#define                        IMMEDDONE       0xb1    /*
-                                                * An immediate command has
-                                                * completed
-                                                */
-#define                        MSG_BUFFER_BUSY 0xc1    /*
-                                                * Sequencer wants to use the
-                                                * message buffer, but it
-                                                * already contains a message
-                                                */
-#define                        MSGIN_PHASEMIS  0xd1    /*
-                                                * Target changed phase on us
-                                                * when we were expecting
-                                                * another msgin byte.
-                                                */
-#define                        DATA_OVERRUN    0xe1    /*
-                                                * Target attempted to write
-                                                * beyond the bounds of its
-                                                * command.
-                                                */
-#define        BRKADRINT 0x08
-#define                SCSIINT   0x04
-#define                CMDCMPLT  0x02
-#define                SEQINT    0x01
-#define                INT_PEND  (BRKADRINT | SEQINT | SCSIINT | CMDCMPLT)
-
-/*
- * Hard Error (p. 3-53)
- * Reporting of catastrophic errors.  You usually cannot recover from
- * these without a full board reset.
- */
-#define ERROR                  0x092
-/*    UNUSED                   0xf0 */
-#define                PARERR          0x08
-#define                ILLOPCODE       0x04
-#define                ILLSADDR        0x02
-#define                ILLHADDR        0x01
-
-/*
- * Clear Interrupt Status (p. 3-52)
- */
-#define CLRINT                 0x092
-#define                CLRBRKADRINT    0x08
-#define                CLRSCSIINT      0x04
-#define                CLRCMDINT       0x02
-#define                CLRSEQINT       0x01
-
-#define        DFCNTRL                 0x093
-#define                WIDEODD         0x40
-#define                SCSIEN          0x20
-#define                SDMAEN          0x10
-#define                SDMAENACK       0x10
-#define                HDMAEN          0x08
-#define                HDMAENACK       0x08
-#define                DIRECTION       0x04
-#define                FIFOFLUSH       0x02
-#define                FIFORESET       0x01
-
-#define        DFSTATUS                0x094
-#define                HDONE           0x08
-#define                FIFOEMP         0x01
-
-#define        DFDAT                   0x099
-
-/*
- * SCB Auto Increment (p. 3-59)
- * Byte offset into the SCB Array and an optional bit to allow auto
- * incrementing of the address during download and upload operations
- */
-#define SCBCNT                 0x09a
-#define                SCBAUTO         0x80
-#define                SCBCNT_MASK     0x1f
-
-/*
- * Queue In FIFO (p. 3-60)
- * Input queue for queued SCBs (commands that the seqencer has yet to start)
- */
-#define QINFIFO                        0x09b
-
-/*
- * Queue In Count (p. 3-60)
- * Number of queued SCBs
- */
-#define QINCNT                 0x09c
-
-/*
- * Queue Out FIFO (p. 3-61)
- * Queue of SCBs that have completed and await the host
- */
-#define QOUTFIFO               0x09d
-
-/*
- * Queue Out Count (p. 3-61)
- * Number of queued SCBs in the Out FIFO
- */
-#define QOUTCNT                        0x09e
-
-/*
- * SCB Definition (p. 5-4)
- * The two reserved bytes at SCBARRAY+1[23] are expected to be set to
- * zero. Bit 3 in SCBARRAY+0 is used as an internal flag to indicate
- * whether or not to DMA an SCB from host ram. This flag prevents the
- * "re-fetching" of transactions that are requed because the target is
- * busy with another command. We also use bits 6 & 7 to indicate whether
- * or not to initiate SDTR or WDTR repectively when starting this command.
- */
-#define SCBARRAY               0x0a0
-#define        SCB_CONTROL             0x0a0
-#define                NEEDWDTR        0x80
-#define                DISCENB         0x40
-#define                TAG_ENB         0x20
-#define                NEEDSDTR        0x10
-#define                DISCONNECTED    0x04
-#define                SCB_TAG_TYPE    0x03
-#define        SCB_TCL                 0x0a1
-#define        SCB_TARGET_STATUS       0x0a2
-#define        SCB_SGCOUNT             0x0a3
-#define        SCB_SGPTR               0x0a4
-#define                SCB_SGPTR0      0x0a4
-#define                SCB_SGPTR1      0x0a5
-#define                SCB_SGPTR2      0x0a6
-#define                SCB_SGPTR3      0x0a7
-#define        SCB_RESID_SGCNT         0x0a8
-#define SCB_RESID_DCNT         0x0a9
-#define                SCB_RESID_DCNT0 0x0a9
-#define                SCB_RESID_DCNT1 0x0aa
-#define                SCB_RESID_DCNT2 0x0ab
-#define SCB_DATAPTR            0x0ac
-#define                SCB_DATAPTR0    0x0ac
-#define                SCB_DATAPTR1    0x0ad
-#define                SCB_DATAPTR2    0x0ae
-#define                SCB_DATAPTR3    0x0af
-#define        SCB_DATACNT             0x0b0
-#define                SCB_DATACNT0    0x0b0
-#define                SCB_DATACNT1    0x0b1
-#define                SCB_DATACNT2    0x0b2
-/* UNUSED - QUAD PADDING       0x0b3 */
-#define SCB_CMDPTR             0x0b4
-#define                SCB_CMDPTR0     0x0b4
-#define                SCB_CMDPTR1     0x0b5
-#define                SCB_CMDPTR2     0x0b6
-#define                SCB_CMDPTR3     0x0b7
-#define        SCB_CMDLEN              0x0b8
-#define SCB_TAG                        0x0b9
-#define        SCB_NEXT                0x0ba
-#define        SCB_PREV                0x0bb
-
-#ifdef __linux__
-#define        SG_SIZEOF               0x0c            /* sizeof(struct scatterlist) */
-#else
-#define        SG_SIZEOF               0x08            /* sizeof(struct ahc_dma) */
-#endif
-
-/* --------------------- AHA-2840-only definitions -------------------- */
-
-#define        SEECTL_2840             0x0c0
-/*     UNUSED                  0xf8 */
-#define                CS_2840         0x04
-#define                CK_2840         0x02
-#define                DO_2840         0x01
-
-#define        STATUS_2840             0x0c1
-#define                EEPROM_TF       0x80
-#define                BIOS_SEL        0x60
-#define                ADSEL           0x1e
-#define                DI_2840         0x01
-
-/* --------------------- AIC-7870-only definitions -------------------- */
-
-#define DSPCISTATUS            0x086
-
-/*
- * Serial EEPROM Control (p. 4-92 in 7870 Databook)
- * Controls the reading and writing of an external serial 1-bit
- * EEPROM Device.  In order to access the serial EEPROM, you must
- * first set the SEEMS bit that generates a request to the memory
- * port for access to the serial EEPROM device.  When the memory
- * port is not busy servicing another request, it reconfigures
- * to allow access to the serial EEPROM.  When this happens, SEERDY
- * gets set high to verify that the memory port access has been
- * granted.  
- *
- * After successful arbitration for the memory port, the SEECS bit of 
- * the SEECTL register is connected to the chip select.  The SEECK, 
- * SEEDO, and SEEDI are connected to the clock, data out, and data in 
- * lines respectively.  The SEERDY bit of SEECTL is useful in that it 
- * gives us an 800 nsec timer.  After a write to the SEECTL register, 
- * the SEERDY goes high 800 nsec later.  The one exception to this is 
- * when we first request access to the memory port.  The SEERDY goes 
- * high to signify that access has been granted and, for this case, has 
- * no implied timing.
- *
- * See 93cx6.c for detailed information on the protocol necessary to 
- * read the serial EEPROM.
- */
-#define SEECTL                 0x01e
-#define                EXTARBACK       0x80
-#define                EXTARBREQ       0x40
-#define                SEEMS           0x20
-#define                SEERDY          0x10
-#define                SEECS           0x08
-#define                SEECK           0x04
-#define                SEEDO           0x02
-#define                SEEDI           0x01
-
-/* ---------------------- Scratch RAM Offsets ------------------------- */
-/* These offsets are either to values that are initialized by the board's
- * BIOS or are specified by the sequencer code.
- *
- * The host adapter card (at least the BIOS) uses 20-2f for SCSI
- * device information, 32-33 and 5a-5f as well. As it turns out, the
- * BIOS trashes 20-2f, writing the synchronous negotiation results
- * on top of the BIOS values, so we re-use those for our per-target
- * scratchspace (actually a value that can be copied directly into
- * SCSIRATE).  The kernel driver will enable synchronous negotiation
- * for all targets that have a value other than 0 in the lower four
- * bits of the target scratch space.  This should work regardless of
- * whether the bios has been installed.
- */
-
-/*
- * 1 byte per target starting at this address for configuration values
- */
-#define TARG_SCRATCH           0x020
-
-/*
- * The sequencer will stick the frist byte of any rejected message here so
- * we can see what is getting thrown away.  Extended messages put the
- * extended message type in REJBYTE_EXT.
- */
-#define REJBYTE                        0x030
-#define REJBYTE_EXT            0x031
-
-/*
- * Bit vector of targets that have disconnection disabled.
- */
-#define        DISC_DSB                0x032
-#define                DISC_DSB_A      0x032
-#define                DISC_DSB_B      0x033
-
-/*
- * Length of pending message
- */
-#define MSG_LEN                        0x034
-
-/* We reserve 8bytes to store outgoing messages */
-#define MSG0                   0x035
-#define                COMP_MSG0       0xcb      /* 2's complement of MSG0 */
-#define MSG1                   0x036
-#define MSG2                   0x037
-#define MSG3                   0x038
-#define MSG4                   0x039
-#define MSG5                   0x03a
-#define MSG6                   0x03b
-#define MSG7                   0x03c
-
-/*
- * These are offsets into the card's scratch ram.  Some of the values are
- * specified in the AHA2742 technical reference manual and are initialized
- * by the BIOS at boot time.
- */
-#define LASTPHASE              0x03d
-#define ARG_1                  0x03e
-#define                MAXOFFSET       0x01
-#define RETURN_1               0x03f
-#define                SEND_WDTR       0x80
-#define                SEND_SDTR       0x60
-#define                SEND_SENSE      0x40
-#define                SEND_REJ        0x20
-#define                SCB_PAGEDIN     0x10
-
-#define SIGSTATE               0x040
-
-#define DMAPARAMS              0x041   /* Parameters for DMA Logic */
-
-#define        SG_COUNT                0x042
-#define        SG_NEXT                 0x043   /* working value of SG pointer */
-#define                SG_NEXT0        0x043
-#define                SG_NEXT1        0x044
-#define                SG_NEXT2        0x045
-#define                SG_NEXT3        0x046
-
-#define        SCBCOUNT                0x047   /*
-                                        * Number of SCBs supported by
-                                        * this card.
-                                        */
-#define        COMP_SCBCOUNT           0x048   /*
-                                        * Two's compliment of SCBCOUNT
-                                        */
-#define QCNTMASK               0x049   /*
-                                        * Mask of bits to test against
-                                        * when looking at the Queue Count
-                                        * registers.  Works around a bug
-                                        * on aic7850 chips. 
-                                        */
-#define FLAGS                  0x04a
-#define                SINGLE_BUS      0x00
-#define                TWIN_BUS        0x01
-#define                WIDE_BUS        0x02
-#define                PAGESCBS        0x04
-#define                DPHASE          0x10
-#define                SELECTED        0x20
-#define                IDENTIFY_SEEN   0x40
-#define                RESELECTED      0x80
-
-#define        SAVED_TCL               0x04b   /*
-                                        * Temporary storage for the
-                                        * target/channel/lun of a
-                                        * reconnecting target
-                                        */
-#define        ACTIVE_A                0x04c
-#define        ACTIVE_B                0x04d
-#define WAITING_SCBH           0x04e   /*
-                                        * head of list of SCBs awaiting
-                                        * selection
-                                        */
-#define DISCONNECTED_SCBH      0x04f   /*
-                                        * head of list of SCBs that are
-                                        * disconnected.  Used for SCB
-                                        * paging.
-                                        */
-#define                SCB_LIST_NULL   0xff
-
-#define SAVED_LINKPTR          0x050
-#define SAVED_SCBPTR           0x051
-#define ULTRA_ENB              0x052
-#define ULTRA_ENB_B            0x053
-
-#define SCSICONF               0x05a
-#define                RESET_SCSI      0x40
-
-#define HOSTCONF               0x05d
-
-#define HA_274_BIOSCTRL                0x05f
-#define BIOSMODE               0x30
-#define BIOSDISABLED           0x30
-#define CHANNEL_B_PRIMARY      0x08
-
-/* Message codes */
-#define MSG_EXTENDED           0x01
-#define                MSG_SDTR        0x01
-#define                MSG_WDTR        0x03
-#define MSG_SDPTRS             0x02
-#define MSG_RDPTRS             0x03
-#define MSG_DISCONNECT         0x04
-#define MSG_INITIATOR_DET_ERROR        0x05
-#define MSG_ABORT              0x06
-#define        MSG_REJECT              0x07
-#define MSG_NOP                        0x08
-#define MSG_MSG_PARITY_ERROR   0x09
-#define MSG_BUS_DEVICE_RESET   0x0c
-#define MSG_ABORT_TAG          0x0d
-#define MSG_SIMPLE_TAG         0x20
-#define MSG_IDENTIFY           0x80
-
-/* WDTR Message values */
-#define        BUS_8_BIT               0x00
-#define BUS_16_BIT             0x01
-#define BUS_32_BIT             0x02
-
-#define MAX_OFFSET_8BIT                0x0f
-#define MAX_OFFSET_16BIT       0x08
index 1380773..b4ac8f1 100644 (file)
-#define AIC7XXX_SEQ_VER "$OpenBSD: aic7xxx_seq.h,v 1.1 1996/11/28 23:28:00 niklas Exp $"
-#if 0
-#define AIC7XXX_SEQ_VER "$NetBSD: aic7xxx_seq.h,v 1.2 1996/10/08 03:04:07 gibbs Exp $"
-#endif
-       0xff, 0x6a, 0x93, 0x02,
-       0xff, 0x6a, 0x03, 0x02,
-       0x0f, 0x4a, 0x4a, 0x02,
-       0x10, 0x6a, 0x00, 0x00,
-       0xff, 0x6a, 0x04, 0x02,
-       0x01, 0x4a, 0x09, 0x1e,
-       0x08, 0x1f, 0x1f, 0x04,
-       0x20, 0x0b, 0x32, 0x1a,
-       0x08, 0x1f, 0x1f, 0x04,
-       0x20, 0x0b, 0x32, 0x1a,
-       0xff, 0x4e, 0x17, 0x18,
-       0xff, 0x49, 0x64, 0x02,
-       0x00, 0x9c, 0x05, 0x1e,
-       0xff, 0x9b, 0x90, 0x02,
-       0xff, 0xa1, 0x6e, 0x02,
-       0xff, 0x6e, 0x64, 0x02,
-       0x88, 0xa1, 0x19, 0x1e,
-       0x00, 0x4d, 0x15, 0x1a,
-       0x20, 0xa0, 0x1c, 0x1a,
-       0x00, 0x4d, 0x4d, 0x00,
-       0x00, 0x65, 0x1c, 0x10,
-       0xff, 0x90, 0x9b, 0x02,
-       0x00, 0x65, 0x05, 0x10,
-       0xff, 0x4e, 0x90, 0x02,
-       0x00, 0x65, 0x1e, 0x10,
-       0x00, 0x4c, 0x15, 0x1a,
-       0x20, 0xa0, 0x1c, 0x1a,
-       0x00, 0x4c, 0x4c, 0x00,
-       0xff, 0x4e, 0xba, 0x02,
-       0xff, 0x90, 0x4e, 0x02,
-       0xf7, 0x1f, 0x65, 0x02,
-       0x08, 0xa1, 0x64, 0x02,
-       0x00, 0x65, 0x65, 0x00,
-       0xff, 0x65, 0x1f, 0x02,
-       0x00, 0xa1, 0x35, 0x17,
-       0x58, 0x6a, 0x00, 0x00,
-       0x40, 0xa0, 0x64, 0x02,
-       0x07, 0xa1, 0x35, 0x02,
-       0x00, 0x35, 0x35, 0x00,
-       0x80, 0x35, 0x35, 0x00,
-       0x01, 0x6a, 0x34, 0x00,
-       0x20, 0xa0, 0x2e, 0x1e,
-       0x36, 0x6a, 0x66, 0x00,
-       0x23, 0xa0, 0x6d, 0x02,
-       0xff, 0xb9, 0x6d, 0x02,
-       0xcb, 0x66, 0x34, 0x06,
-       0x80, 0xa0, 0x30, 0x1e,
-       0xa1, 0x6a, 0x91, 0x00,
-       0x40, 0x0b, 0x36, 0x1a,
-       0x20, 0x0b, 0x30, 0x1e,
-       0xff, 0x6a, 0x34, 0x02,
-       0x00, 0x19, 0x35, 0x17,
-       0x80, 0x4a, 0x4a, 0x00,
-       0x00, 0x65, 0x38, 0x10,
-       0xff, 0xba, 0x4e, 0x02,
-       0x20, 0x4a, 0x4a, 0x00,
-       0x02, 0x01, 0x01, 0x00,
-       0x00, 0x65, 0x7c, 0x17,
-       0xff, 0x6c, 0x04, 0x02,
-       0xff, 0x05, 0x6e, 0x02,
-       0xff, 0x6e, 0x64, 0x02,
-       0xdf, 0x01, 0x65, 0x02,
-       0x80, 0x05, 0x42, 0x1a,
-       0x08, 0x1f, 0x42, 0x1a,
-       0x00, 0x52, 0x44, 0x1e,
-       0x20, 0x65, 0x44, 0x10,
-       0x00, 0x53, 0x44, 0x1e,
-       0x20, 0x65, 0x65, 0x00,
-       0xff, 0x65, 0x01, 0x02,
-       0x02, 0x6a, 0x00, 0x00,
-       0x08, 0x6a, 0x0c, 0x00,
-       0x60, 0x6a, 0x0b, 0x00,
-       0x08, 0x0c, 0x18, 0x1b,
-       0x01, 0x0c, 0x48, 0x1e,
-       0xe0, 0x03, 0x64, 0x02,
-       0xff, 0x64, 0x3d, 0x02,
-       0xff, 0x64, 0x03, 0x02,
-       0x00, 0x6a, 0x55, 0x1c,
-       0x40, 0x64, 0x5b, 0x1c,
-       0x80, 0x64, 0x8d, 0x1c,
-       0xa0, 0x64, 0x9c, 0x1c,
-       0xc0, 0x64, 0x9a, 0x1c,
-       0xe0, 0x64, 0xb1, 0x1c,
-       0x01, 0x6a, 0x91, 0x00,
-       0x00, 0x65, 0x48, 0x10,
-       0x7d, 0x6a, 0x41, 0x00,
-       0x00, 0x65, 0x5c, 0x10,
-       0xff, 0xa9, 0x08, 0x02,
-       0xff, 0xaa, 0x09, 0x02,
-       0xff, 0xab, 0x0a, 0x02,
-       0x00, 0x65, 0x60, 0x10,
-       0x79, 0x6a, 0x41, 0x00,
-       0x00, 0x65, 0x39, 0x17,
-       0x10, 0x4a, 0x57, 0x1a,
-       0x00, 0x65, 0x60, 0x17,
-       0x10, 0x4a, 0x4a, 0x00,
-       0xff, 0x42, 0x65, 0x1a,
-       0x80, 0x02, 0x02, 0x00,
-       0xff, 0x6a, 0x08, 0x00,
-       0xff, 0x6a, 0x09, 0x00,
-       0xff, 0x6a, 0x0a, 0x00,
-       0x01, 0x42, 0x67, 0x18,
-       0xbf, 0x41, 0x41, 0x02,
-       0x00, 0x41, 0x2d, 0x17,
-       0x80, 0x02, 0x8a, 0x1a,
-       0x04, 0x0b, 0x85, 0x1e,
-       0xff, 0x42, 0x42, 0x06,
-       0xff, 0x42, 0x85, 0x1e,
-       0xff, 0x6a, 0x64, 0x02,
-       0x08, 0x43, 0x43, 0x06,
-       0x00, 0x44, 0x44, 0x08,
-       0xff, 0x6a, 0x8e, 0x02,
-       0xff, 0x6a, 0x8d, 0x02,
-       0x08, 0x6a, 0x8c, 0x00,
-       0xff, 0x43, 0x88, 0x02,
-       0xff, 0x44, 0x89, 0x02,
-       0xff, 0x45, 0x8a, 0x02,
-       0xff, 0x46, 0x8b, 0x02,
-       0x0d, 0x93, 0x93, 0x00,
-       0x08, 0x94, 0x77, 0x1e,
-       0x40, 0x93, 0x93, 0x02,
-       0x08, 0x93, 0x79, 0x1a,
-       0xff, 0x99, 0x88, 0x02,
-       0xff, 0x99, 0x89, 0x02,
-       0xff, 0x99, 0x8a, 0x02,
-       0xff, 0x99, 0x8b, 0x02,
-       0xff, 0x99, 0x8c, 0x02,
-       0xff, 0x99, 0x8d, 0x02,
-       0xff, 0x99, 0x8e, 0x02,
-       0xff, 0x8c, 0x08, 0x02,
-       0xff, 0x8d, 0x09, 0x02,
-       0xff, 0x8e, 0x0a, 0x02,
-       0x10, 0x0c, 0x60, 0x1e,
-       0xff, 0x08, 0xa9, 0x02,
-       0xff, 0x09, 0xaa, 0x02,
-       0xff, 0x0a, 0xab, 0x02,
-       0xff, 0x42, 0xa8, 0x02,
-       0x00, 0x65, 0x48, 0x10,
-       0x7f, 0x02, 0x02, 0x02,
-       0xe1, 0x6a, 0x91, 0x00,
-       0x00, 0x65, 0x48, 0x10,
-       0x00, 0x65, 0x39, 0x17,
-       0xff, 0xb4, 0x88, 0x02,
-       0xff, 0xb5, 0x89, 0x02,
-       0xff, 0xb6, 0x8a, 0x02,
-       0xff, 0xb7, 0x8b, 0x02,
-       0xff, 0xb8, 0x8c, 0x02,
-       0xff, 0x6a, 0x8d, 0x02,
-       0xff, 0x6a, 0x8e, 0x02,
-       0xff, 0x8c, 0x08, 0x02,
-       0xff, 0x8d, 0x09, 0x02,
-       0xff, 0x8e, 0x0a, 0x02,
-       0x3d, 0x6a, 0x2d, 0x17,
-       0x00, 0x65, 0x48, 0x10,
-       0xa2, 0x6a, 0x27, 0x17,
-       0x00, 0x65, 0xbd, 0x10,
-       0xff, 0x34, 0x9e, 0x1a,
-       0x08, 0x6a, 0x1c, 0x17,
-       0x35, 0x6a, 0x65, 0x00,
-       0xff, 0x34, 0x66, 0x02,
-       0x10, 0x0c, 0xae, 0x1a,
-       0x02, 0x0b, 0xa0, 0x1e,
-       0x10, 0x0c, 0xae, 0x1a,
-       0x01, 0x66, 0xa5, 0x18,
-       0x40, 0x6a, 0x0c, 0x00,
-       0xff, 0x66, 0x66, 0x06,
-       0x02, 0x0b, 0x0b, 0x00,
-       0xff, 0x6c, 0x06, 0x02,
-       0xff, 0x66, 0xa0, 0x1a,
-       0x08, 0x0c, 0xaf, 0x1a,
-       0x01, 0x0c, 0xa9, 0x1e,
-       0x10, 0x0c, 0xaf, 0x1a,
-       0x10, 0x03, 0x03, 0x00,
-       0x00, 0x65, 0x48, 0x10,
-       0x40, 0x6a, 0x0c, 0x00,
-       0xff, 0x6a, 0x34, 0x02,
-       0x00, 0x65, 0x48, 0x10,
-       0x64, 0x6a, 0x27, 0x17,
-       0xff, 0x64, 0x30, 0x02,
-       0x80, 0x64, 0xf5, 0x1a,
-       0x04, 0x64, 0xe5, 0x1c,
-       0x02, 0x64, 0xf1, 0x1c,
-       0x00, 0x6a, 0xbf, 0x1c,
-       0x03, 0x64, 0xf3, 0x1c,
-       0x01, 0x64, 0xd2, 0x1c,
-       0x07, 0x64, 0x16, 0x1d,
-       0x10, 0x03, 0x03, 0x00,
-       0x11, 0x6a, 0x91, 0x00,
-       0x07, 0x6a, 0x1c, 0x17,
-       0x00, 0x65, 0x2a, 0x17,
-       0x00, 0x65, 0x48, 0x10,
-       0xff, 0xa8, 0xc1, 0x1e,
-       0x81, 0x6a, 0x91, 0x00,
-       0xff, 0xa2, 0xc5, 0x1e,
-       0x71, 0x6a, 0x91, 0x00,
-       0x40, 0x3f, 0xc5, 0x18,
-       0x00, 0x65, 0xbd, 0x10,
-       0x20, 0xa0, 0xcc, 0x1a,
-       0xff, 0xa1, 0x6e, 0x02,
-       0xff, 0x6e, 0x64, 0x02,
-       0x88, 0xa1, 0xcb, 0x1e,
-       0x00, 0x4d, 0x4d, 0x04,
-       0x00, 0x65, 0xcc, 0x10,
-       0x00, 0x4c, 0x4c, 0x04,
-       0xff, 0xb8, 0xcf, 0x1a,
-       0xb1, 0x6a, 0x91, 0x00,
-       0x00, 0x65, 0x02, 0x10,
-       0xff, 0xb9, 0x9d, 0x02,
-       0x02, 0x6a, 0x91, 0x00,
-       0x00, 0x65, 0xbd, 0x10,
-       0x54, 0x6a, 0x23, 0x17,
-       0x55, 0x6a, 0x23, 0x17,
-       0xff, 0x54, 0x64, 0x02,
-       0xff, 0x64, 0x64, 0x06,
-       0x56, 0x6a, 0x65, 0x00,
-       0xff, 0x64, 0xe0, 0x1e,
-       0x58, 0x65, 0xdc, 0x1c,
-       0x00, 0x65, 0x23, 0x17,
-       0xff, 0x64, 0x64, 0x06,
-       0x00, 0x66, 0xd7, 0x10,
-       0xff, 0x64, 0xe0, 0x1e,
-       0x6a, 0x6a, 0x23, 0x17,
-       0xff, 0x64, 0x64, 0x06,
-       0x00, 0x65, 0xdc, 0x10,
-       0x41, 0x6a, 0x91, 0x00,
-       0x20, 0x3f, 0xba, 0x1c,
-       0x80, 0x3f, 0xbd, 0x18,
-       0x10, 0x03, 0x03, 0x00,
-       0x00, 0x65, 0xbd, 0x10,
-       0x04, 0xa0, 0xa0, 0x00,
-       0x04, 0x4a, 0xbd, 0x1e,
-       0xff, 0x6a, 0xbb, 0x00,
-       0x50, 0x6a, 0x60, 0x00,
-       0xff, 0x4f, 0xba, 0x02,
-       0xff, 0x90, 0x4f, 0x02,
-       0xff, 0xba, 0xef, 0x1c,
-       0xff, 0xba, 0x90, 0x02,
-       0xff, 0x4f, 0xbb, 0x02,
-       0xff, 0x4f, 0x90, 0x02,
-       0x10, 0x6a, 0x60, 0x00,
-       0x00, 0x65, 0xbd, 0x10,
-       0x00, 0x65, 0x6f, 0x17,
-       0x00, 0x65, 0xbd, 0x10,
-       0xef, 0x4a, 0x4a, 0x02,
-       0x00, 0x65, 0xbd, 0x10,
-       0x78, 0x64, 0xba, 0x1a,
-       0x07, 0x64, 0x64, 0x02,
-       0x00, 0x19, 0x4b, 0x00,
-       0xf7, 0x4b, 0x4b, 0x02,
-       0x08, 0x1f, 0x64, 0x02,
-       0x00, 0x4b, 0x4b, 0x00,
-       0x00, 0x65, 0x2a, 0x17,
-       0xff, 0x6a, 0x3e, 0x00,
-       0x08, 0x0c, 0x08, 0x1b,
-       0x01, 0x0c, 0xfd, 0x1e,
-       0x10, 0x0c, 0x08, 0x1b,
-       0x64, 0x6a, 0x27, 0x17,
-       0x20, 0x64, 0x08, 0x19,
-       0x3e, 0x6a, 0x23, 0x17,
-       0xff, 0x48, 0x64, 0x02,
-       0x00, 0x3e, 0x65, 0x06,
-       0x00, 0x65, 0x12, 0x13,
-       0x04, 0x4a, 0x0c, 0x1f,
-       0x00, 0x65, 0x2a, 0x17,
-       0x00, 0x6a, 0x3c, 0x17,
-       0xfb, 0xa0, 0xa0, 0x02,
-       0x40, 0x4a, 0x4a, 0x00,
-       0x00, 0x65, 0x48, 0x10,
-       0xff, 0x3e, 0x90, 0x02,
-       0xff, 0x4b, 0x64, 0x02,
-       0x00, 0xa1, 0x12, 0x19,
-       0x20, 0xa0, 0x12, 0x1f,
-       0x00, 0x65, 0x2a, 0x17,
-       0x00, 0x65, 0x09, 0x11,
-       0x10, 0x03, 0x03, 0x00,
-       0x91, 0x6a, 0x91, 0x00,
-       0x0d, 0x6a, 0x1c, 0x17,
-       0x00, 0x65, 0xbd, 0x10,
-       0x61, 0x6a, 0x91, 0x00,
-       0x00, 0x65, 0xbd, 0x10,
-       0x40, 0x6a, 0x0c, 0x00,
-       0xff, 0x6a, 0x3d, 0x02,
-       0xff, 0xb8, 0xc5, 0x1e,
-       0x00, 0x65, 0x02, 0x10,
-       0x50, 0x6a, 0x60, 0x00,
-       0xff, 0x34, 0x20, 0x1f,
-       0x10, 0x6a, 0x60, 0x00,
-       0xc1, 0x6a, 0x91, 0x00,
-       0x01, 0x6a, 0x34, 0x00,
-       0xff, 0x65, 0x35, 0x02,
-       0x10, 0x6a, 0x60, 0x01,
-       0x02, 0x0b, 0x0b, 0x00,
-       0xff, 0x06, 0x6a, 0x02,
-       0x10, 0x0c, 0x2b, 0x1b,
-       0x02, 0x0b, 0x25, 0x1f,
-       0xff, 0x65, 0x66, 0x02,
-       0x10, 0x0c, 0x2b, 0x1b,
-       0xff, 0x12, 0x6d, 0x03,
-       0xff, 0x06, 0x6a, 0x03,
-       0xd1, 0x6a, 0x91, 0x00,
-       0x00, 0x65, 0x48, 0x10,
-       0xff, 0x65, 0x93, 0x02,
-       0x01, 0x0b, 0x30, 0x1b,
-       0x10, 0x0c, 0x2e, 0x1f,
-       0x04, 0x65, 0x32, 0x1b,
-       0x01, 0x94, 0x31, 0x1f,
-       0x40, 0x93, 0x93, 0x02,
-       0x38, 0x93, 0x33, 0x1b,
-       0xff, 0x6a, 0x6a, 0x03,
-       0xf0, 0x65, 0x65, 0x02,
-       0x0f, 0x05, 0x64, 0x02,
-       0x00, 0x65, 0x65, 0x00,
-       0xff, 0x65, 0x05, 0x03,
-       0x80, 0x4a, 0x34, 0x1f,
-       0x40, 0x4a, 0x34, 0x1b,
-       0x21, 0x6a, 0x91, 0x01,
-       0xff, 0x4b, 0x64, 0x02,
-       0xff, 0x65, 0x90, 0x02,
-       0x50, 0x6a, 0x60, 0x00,
-       0x00, 0xa1, 0x54, 0x19,
-       0x04, 0xa0, 0x54, 0x1f,
-       0x20, 0xa0, 0x44, 0x1b,
-       0xff, 0x3e, 0x46, 0x1d,
-       0x00, 0x65, 0x54, 0x11,
-       0xff, 0x3e, 0x64, 0x02,
-       0x00, 0xb9, 0x54, 0x19,
-       0x04, 0x4a, 0x53, 0x1f,
-       0xff, 0xba, 0x4c, 0x1d,
-       0xff, 0xbb, 0x50, 0x02,
-       0xff, 0xba, 0x90, 0x02,
-       0xff, 0x50, 0xbb, 0x02,
-       0xff, 0x65, 0x90, 0x02,
-       0xff, 0xbb, 0x52, 0x1d,
-       0xff, 0xba, 0x50, 0x02,
-       0xff, 0xbb, 0x90, 0x02,
-       0xff, 0x50, 0xba, 0x02,
-       0xff, 0x65, 0x90, 0x02,
-       0x10, 0x6a, 0x60, 0x01,
-       0xff, 0xba, 0x4f, 0x02,
-       0x10, 0x6a, 0x60, 0x01,
-       0x10, 0x6a, 0x60, 0x00,
-       0x01, 0x65, 0x65, 0x06,
-       0xff, 0x47, 0x64, 0x02,
-       0x00, 0x65, 0x3c, 0x19,
-       0x31, 0x6a, 0x91, 0x00,
-       0x10, 0x3f, 0x34, 0x1d,
-       0x10, 0x03, 0x03, 0x00,
-       0xff, 0x3e, 0x5e, 0x19,
-       0x06, 0x6a, 0x1c, 0x17,
-       0x00, 0x65, 0x48, 0x10,
-       0x0d, 0x6a, 0x1c, 0x17,
-       0x00, 0x65, 0x48, 0x10,
-       0xff, 0xac, 0x88, 0x02,
-       0xff, 0xad, 0x89, 0x02,
-       0xff, 0xae, 0x8a, 0x02,
-       0xff, 0xaf, 0x8b, 0x02,
-       0xff, 0xb0, 0x8c, 0x02,
-       0xff, 0xb1, 0x8d, 0x02,
-       0xff, 0xb2, 0x8e, 0x02,
-       0xff, 0x8c, 0x08, 0x02,
-       0xff, 0x8d, 0x09, 0x02,
-       0xff, 0x8e, 0x0a, 0x02,
-       0xff, 0xa3, 0x42, 0x02,
-       0xff, 0xa4, 0x43, 0x02,
-       0xff, 0xa5, 0x44, 0x02,
-       0xff, 0xa6, 0x45, 0x02,
-       0xff, 0xa7, 0x46, 0x03,
-       0x10, 0x4a, 0x34, 0x1f,
-       0xff, 0x42, 0xa3, 0x02,
-       0xff, 0x43, 0xa4, 0x02,
-       0xff, 0x44, 0xa5, 0x02,
-       0xff, 0x45, 0xa6, 0x02,
-       0xff, 0x46, 0xa7, 0x02,
-       0xff, 0x14, 0xac, 0x02,
-       0xff, 0x15, 0xad, 0x02,
-       0xff, 0x16, 0xae, 0x02,
-       0xff, 0x17, 0xaf, 0x02,
-       0xff, 0xa9, 0xb0, 0x02,
-       0xff, 0xaa, 0xb1, 0x02,
-       0xff, 0xab, 0xb2, 0x03,
-       0x4c, 0x05, 0x64, 0x0a,
-       0x08, 0x1f, 0x7f, 0x1f,
-       0x08, 0x64, 0x64, 0x00,
-       0x20, 0x64, 0x65, 0x07,
+/*
+ * DO NOT EDIT - This file is automatically generated.
+ */
+static u_int8_t seqprog[] = {
+       0xff, 0x6a, 0x06, 0x08,
+       0x08, 0x6a, 0x68, 0x00,
+       0x7f, 0x02, 0x04, 0x08,
+       0x32, 0x58, 0x00, 0x08,
+       0xff, 0x6a, 0xd6, 0x09,
+       0xff, 0x6a, 0xdc, 0x09,
+       0x00, 0x65, 0xea, 0x59,
+       0xf7, 0x01, 0x02, 0x08,
+       0xff, 0x4e, 0xc8, 0x08,
+       0xbf, 0x60, 0xc0, 0x08,
+       0x60, 0x0b, 0x7c, 0x68,
+       0x40, 0x00, 0x0c, 0x68,
+       0x08, 0x1f, 0x3e, 0x10,
+       0x60, 0x0b, 0x7c, 0x68,
+       0x40, 0x00, 0x0c, 0x68,
+       0x08, 0x1f, 0x3e, 0x10,
+       0xff, 0x3e, 0x4a, 0x60,
+       0x40, 0xfa, 0x12, 0x78,
+       0xff, 0xf6, 0xd4, 0x08,
+       0x01, 0x4e, 0x9c, 0x18,
+       0x40, 0x60, 0xc0, 0x00,
+       0x00, 0x4d, 0x12, 0x70,
+       0x01, 0x4e, 0x9c, 0x18,
+       0xbf, 0x60, 0xc0, 0x08,
+       0x00, 0x6a, 0x8e, 0x5d,
+       0xff, 0x4e, 0xc8, 0x18,
+       0x01, 0x6a, 0x9a, 0x5c,
+       0xff, 0x53, 0x20, 0x09,
+       0x0d, 0x6a, 0x6a, 0x00,
+       0x00, 0x53, 0x18, 0x5d,
+       0x03, 0xb0, 0x52, 0x31,
+       0xff, 0xb0, 0x52, 0x09,
+       0xff, 0xb1, 0x54, 0x09,
+       0xff, 0xb2, 0x56, 0x09,
+       0xff, 0xa3, 0x50, 0x09,
+       0xff, 0x3e, 0x74, 0x09,
+       0xff, 0x90, 0x7c, 0x08,
+       0xff, 0x3e, 0x20, 0x09,
+       0x00, 0x65, 0x50, 0x58,
+       0x00, 0x65, 0x0c, 0x40,
+       0xf7, 0x1f, 0xca, 0x08,
+       0x08, 0xa1, 0xc8, 0x08,
+       0x00, 0x65, 0xca, 0x00,
+       0xff, 0x65, 0x3e, 0x08,
+       0xff, 0x58, 0xca, 0x08,
+       0x80, 0xa0, 0x62, 0x78,
+       0xff, 0xb6, 0x1e, 0x08,
+       0xff, 0xb6, 0x0a, 0x08,
+       0x80, 0x65, 0xca, 0x00,
+       0x00, 0x65, 0x70, 0x40,
+       0xf0, 0xa1, 0xc8, 0x08,
+       0x0f, 0x0f, 0x1e, 0x08,
+       0x00, 0x0f, 0x1e, 0x00,
+       0xf0, 0xa1, 0xc8, 0x08,
+       0x0f, 0x05, 0x0a, 0x08,
+       0x00, 0x05, 0x0a, 0x00,
+       0xff, 0x65, 0x00, 0x0c,
+       0x12, 0x65, 0x02, 0x00,
+       0x08, 0xa0, 0x78, 0x78,
+       0x20, 0x01, 0x02, 0x00,
+       0x02, 0xbb, 0x08, 0x34,
+       0xff, 0xbb, 0x08, 0x0c,
+       0x40, 0x0b, 0x0e, 0x69,
+       0x20, 0x6a, 0x16, 0x00,
+       0x80, 0x0b, 0x00, 0x79,
+       0xa4, 0x6a, 0x06, 0x00,
+       0x08, 0x6a, 0x18, 0x00,
+       0x08, 0x36, 0x6c, 0x00,
+       0xff, 0x51, 0xc8, 0x08,
+       0xe0, 0x6a, 0xcc, 0x00,
+       0x49, 0x6a, 0x02, 0x5d,
+       0x01, 0x6a, 0xdc, 0x01,
+       0x88, 0x6a, 0xcc, 0x00,
+       0x49, 0x6a, 0x02, 0x5d,
+       0x01, 0x6a, 0x26, 0x01,
+       0xf0, 0x19, 0x6e, 0x08,
+       0xff, 0x37, 0xd8, 0x09,
+       0xff, 0x37, 0x32, 0x09,
+       0x0f, 0x18, 0xd8, 0x09,
+       0x0f, 0x0f, 0xd8, 0x09,
+       0x0f, 0x05, 0xd8, 0x09,
+       0x0f, 0x18, 0x32, 0x09,
+       0x0f, 0x0f, 0x32, 0x09,
+       0x0f, 0x05, 0x32, 0x09,
+       0xff, 0x6a, 0xb4, 0x00,
+       0x10, 0x03, 0x54, 0x79,
+       0x00, 0x65, 0xf8, 0x58,
+       0x80, 0x66, 0xd4, 0x78,
+       0xff, 0x66, 0xd8, 0x09,
+       0xff, 0x66, 0x32, 0x09,
+       0x40, 0x66, 0xb8, 0x68,
+       0x01, 0x36, 0x6c, 0x00,
+       0x10, 0x03, 0xde, 0x78,
+       0x00, 0x65, 0xf8, 0x58,
+       0xe0, 0x66, 0xc8, 0x18,
+       0x00, 0x65, 0xde, 0x50,
+       0xdd, 0x66, 0xc8, 0x18,
+       0x00, 0x65, 0xde, 0x48,
+       0xff, 0x66, 0xd8, 0x09,
+       0xff, 0x66, 0x32, 0x09,
+       0x10, 0x03, 0x54, 0x79,
+       0x00, 0x65, 0xf8, 0x58,
+       0xff, 0x66, 0xd8, 0x09,
+       0xff, 0x66, 0x32, 0x09,
+       0xff, 0x66, 0xb4, 0x08,
+       0x00, 0x65, 0xde, 0x40,
+       0xa1, 0x6a, 0x22, 0x01,
+       0xff, 0x6a, 0xd4, 0x08,
+       0x08, 0x52, 0x2c, 0x71,
+       0x02, 0x0b, 0xda, 0x78,
+       0x00, 0x65, 0xd4, 0x40,
+       0xff, 0x50, 0xc8, 0x08,
+       0x00, 0x51, 0xee, 0x60,
+       0xc4, 0x6a, 0x1c, 0x5c,
+       0xff, 0x5a, 0xea, 0x70,
+       0x28, 0x6a, 0x32, 0x5c,
+       0x00, 0x65, 0x52, 0x41,
+       0x08, 0x6a, 0x32, 0x5c,
+       0x00, 0x65, 0x52, 0x41,
+       0xff, 0x6a, 0xd8, 0x01,
+       0xff, 0x6a, 0x32, 0x01,
+       0x90, 0x36, 0x6c, 0x00,
+       0x10, 0x03, 0x48, 0x69,
+       0x00, 0x65, 0x2c, 0x41,
+       0x08, 0x01, 0x02, 0x00,
+       0x02, 0x0b, 0xfa, 0x78,
+       0xf7, 0x01, 0x02, 0x08,
+       0xff, 0x06, 0xcc, 0x0c,
+       0xf0, 0x19, 0x6e, 0x08,
+       0x08, 0x1f, 0x06, 0x79,
+       0x08, 0x37, 0x6e, 0x00,
+       0x1a, 0x01, 0x02, 0x00,
+       0x08, 0x6a, 0x18, 0x00,
+       0x08, 0x11, 0x22, 0x00,
+       0x00, 0x65, 0xcc, 0x41,
+       0x32, 0x58, 0x00, 0x08,
+       0x40, 0x6a, 0x16, 0x00,
+       0xff, 0x3e, 0x20, 0x09,
+       0xff, 0xba, 0x7c, 0x08,
+       0xff, 0xa1, 0x6e, 0x08,
+       0x80, 0x0b, 0xc2, 0x79,
+       0xe4, 0x6a, 0x1c, 0x5c,
+       0x08, 0x6a, 0x18, 0x00,
+       0x07, 0xa1, 0xc8, 0x08,
+       0x80, 0x64, 0x32, 0x5c,
+       0x20, 0xa0, 0x28, 0x79,
+       0x20, 0x6a, 0x32, 0x5c,
+       0x00, 0xb8, 0x32, 0x5c,
+       0xff, 0xb8, 0xb4, 0x08,
+       0xff, 0xb4, 0x6c, 0x08,
+       0x10, 0x03, 0x44, 0x69,
+       0x08, 0x36, 0x5c, 0x69,
+       0x04, 0x36, 0x82, 0x69,
+       0x02, 0x36, 0x92, 0x69,
+       0x01, 0x36, 0x4a, 0x79,
+       0x00, 0x6a, 0x8e, 0x5d,
+       0xff, 0x6a, 0xa4, 0x08,
+       0x00, 0x65, 0x9e, 0x59,
+       0x04, 0x52, 0x3c, 0x61,
+       0x0d, 0x6a, 0x6a, 0x00,
+       0x00, 0xb9, 0x18, 0x5d,
+       0x00, 0x65, 0x2a, 0x41,
+       0xa4, 0x6a, 0x06, 0x00,
+       0x00, 0x65, 0xf8, 0x58,
+       0x00, 0x65, 0xd4, 0x40,
+       0xe4, 0x6a, 0x1c, 0x5c,
+       0x20, 0x36, 0x50, 0x79,
+       0x02, 0x6a, 0x32, 0x5c,
+       0x04, 0x6a, 0x32, 0x5c,
+       0x01, 0x03, 0x52, 0x69,
+       0xff, 0x6a, 0x06, 0x08,
+       0x01, 0x6a, 0x7a, 0x00,
+       0x00, 0x65, 0x9e, 0x59,
+       0x00, 0x65, 0x0c, 0x40,
+       0x84, 0x6a, 0x1c, 0x5c,
+       0x00, 0x65, 0xf8, 0x58,
+       0xff, 0x66, 0xc8, 0x08,
+       0xff, 0x64, 0xd8, 0x09,
+       0xff, 0x64, 0x32, 0x09,
+       0x5b, 0x64, 0xc8, 0x28,
+       0x20, 0x64, 0xca, 0x18,
+       0xff, 0x6c, 0xc8, 0x08,
+       0xff, 0x64, 0x7e, 0x79,
+       0x08, 0x01, 0x02, 0x00,
+       0x02, 0x0b, 0x70, 0x79,
+       0x01, 0x64, 0x76, 0x61,
+       0xf7, 0x01, 0x02, 0x08,
+       0xff, 0x06, 0xd8, 0x09,
+       0xff, 0x06, 0x32, 0x09,
+       0xff, 0x64, 0xc8, 0x18,
+       0xff, 0x64, 0x6e, 0x69,
+       0xf7, 0x36, 0x6c, 0x08,
+       0x00, 0x65, 0x2c, 0x41,
+       0x01, 0xb5, 0x8a, 0x79,
+       0x00, 0x6a, 0x7a, 0x00,
+       0x44, 0x6a, 0x1c, 0x5c,
+       0x00, 0x65, 0x8e, 0x41,
+       0x40, 0x6a, 0x7a, 0x00,
+       0x04, 0x6a, 0x1c, 0x5c,
+       0x00, 0x6a, 0x72, 0x58,
+       0x00, 0x65, 0x04, 0x42,
+       0xc4, 0x6a, 0x1c, 0x5c,
+       0xc0, 0x6a, 0x7a, 0x00,
+       0x00, 0xa2, 0x32, 0x5c,
+       0xe4, 0x6a, 0x06, 0x00,
+       0x00, 0x6a, 0x32, 0x5c,
+       0x00, 0x65, 0x52, 0x41,
+       0x10, 0x36, 0xa2, 0x69,
+       0x00, 0xb9, 0x98, 0x43,
+       0x18, 0x6a, 0xda, 0x01,
+       0xff, 0x69, 0xd8, 0x09,
+       0x1c, 0x6a, 0xd0, 0x01,
+       0x09, 0xee, 0xdc, 0x01,
+       0x80, 0xee, 0xaa, 0x79,
+       0xff, 0x6a, 0xdc, 0x09,
+       0x01, 0x93, 0x26, 0x01,
+       0x03, 0x6a, 0x2a, 0x01,
+       0xff, 0x69, 0x32, 0x09,
+       0x1c, 0x6a, 0x18, 0x01,
+       0xff, 0x6a, 0x1a, 0x09,
+       0xff, 0x6a, 0x1c, 0x09,
+       0x0a, 0x93, 0x26, 0x01,
+       0x00, 0x65, 0x7e, 0x5d,
+       0x01, 0x51, 0xa2, 0x18,
+       0x02, 0x6a, 0x22, 0x05,
+       0x08, 0x6a, 0x72, 0x58,
+       0x08, 0x6a, 0x18, 0x00,
+       0x08, 0x11, 0x22, 0x00,
+       0x80, 0x6a, 0x68, 0x00,
+       0x80, 0x36, 0x6c, 0x00,
+       0x00, 0x65, 0xe6, 0x5c,
+       0xff, 0x3d, 0xc8, 0x08,
+       0xbf, 0x64, 0x04, 0x7a,
+       0x80, 0x64, 0xd8, 0x72,
+       0xa0, 0x64, 0x12, 0x73,
+       0xc0, 0x64, 0x0a, 0x73,
+       0xe0, 0x64, 0x5a, 0x73,
+       0x01, 0x6a, 0x22, 0x01,
+       0x00, 0x65, 0xcc, 0x41,
+       0xf7, 0x11, 0x22, 0x08,
+       0xff, 0x06, 0xd4, 0x08,
+       0xf7, 0x01, 0x02, 0x08,
+       0x09, 0x0c, 0xe4, 0x79,
+       0x08, 0x0c, 0x0c, 0x68,
+       0x01, 0x6a, 0x22, 0x01,
+       0xff, 0x6a, 0x26, 0x09,
+       0x02, 0x6a, 0x08, 0x30,
+       0xff, 0x6a, 0x08, 0x08,
+       0xdf, 0x01, 0x02, 0x08,
+       0x01, 0x6a, 0x7a, 0x00,
+       0xff, 0x6a, 0x6c, 0x0c,
+       0x04, 0x14, 0x10, 0x31,
+       0x03, 0xa9, 0x18, 0x31,
+       0x03, 0xa9, 0x10, 0x30,
+       0x08, 0x6a, 0xcc, 0x00,
+       0xa9, 0x6a, 0xfc, 0x5c,
+       0x01, 0xa9, 0xb2, 0x08,
+       0x00, 0x65, 0x26, 0x42,
+       0xa8, 0x6a, 0x6a, 0x00,
+       0x79, 0x6a, 0x6a, 0x00,
+       0x40, 0x3d, 0x0c, 0x6a,
+       0x04, 0x35, 0x6a, 0x00,
+       0x00, 0x65, 0x54, 0x5c,
+       0x80, 0x6a, 0xd4, 0x01,
+       0x20, 0x36, 0xf6, 0x69,
+       0x20, 0x36, 0x6c, 0x00,
+       0x07, 0xac, 0x10, 0x31,
+       0x88, 0x6a, 0xcc, 0x00,
+       0xac, 0x6a, 0xf4, 0x5c,
+       0x01, 0xb0, 0xb2, 0x08,
+       0x03, 0x8c, 0x10, 0x30,
+       0x00, 0x65, 0xee, 0x5c,
+       0x05, 0xa3, 0x70, 0x30,
+       0x38, 0x6a, 0xcc, 0x00,
+       0xa3, 0x6a, 0xf8, 0x5c,
+       0xff, 0x38, 0x36, 0x6a,
+       0x80, 0x02, 0x04, 0x00,
+       0xe7, 0x35, 0x6a, 0x08,
+       0x03, 0x69, 0x18, 0x31,
+       0x03, 0x69, 0x10, 0x30,
+       0xff, 0x6a, 0x10, 0x00,
+       0xff, 0x6a, 0x12, 0x00,
+       0xff, 0x6a, 0x14, 0x00,
+       0x01, 0x38, 0x40, 0x62,
+       0x02, 0xfc, 0xf8, 0x01,
+       0x80, 0x0b, 0x3e, 0x7a,
+       0x04, 0x35, 0x40, 0x7a,
+       0xbf, 0x35, 0x6a, 0x08,
+       0xff, 0x69, 0xca, 0x08,
+       0xff, 0x35, 0x26, 0x09,
+       0x04, 0x0b, 0x44, 0x6a,
+       0x04, 0x0b, 0x4c, 0x6a,
+       0x10, 0x0c, 0x46, 0x7a,
+       0x00, 0x35, 0x40, 0x5c,
+       0x80, 0x02, 0xb4, 0x6a,
+       0xff, 0x08, 0x9a, 0x6a,
+       0xff, 0x09, 0x9a, 0x6a,
+       0xff, 0x0a, 0x9a, 0x6a,
+       0xff, 0x38, 0x70, 0x18,
+       0xff, 0x38, 0x9a, 0x7a,
+       0x80, 0xea, 0x70, 0x62,
+       0xef, 0x38, 0xc8, 0x18,
+       0x80, 0x6a, 0xc8, 0x00,
+       0x00, 0x65, 0x62, 0x4a,
+       0x33, 0x38, 0xc8, 0x28,
+       0xff, 0x64, 0xd0, 0x09,
+       0x04, 0x39, 0xc0, 0x31,
+       0x09, 0x6a, 0xd6, 0x01,
+       0x80, 0xeb, 0x68, 0x7a,
+       0xf7, 0xeb, 0xd6, 0x09,
+       0x08, 0xeb, 0x6c, 0x6a,
+       0x01, 0x6a, 0xd6, 0x01,
+       0x08, 0xe9, 0x10, 0x31,
+       0x88, 0x6a, 0xcc, 0x00,
+       0x39, 0x6a, 0xfa, 0x5c,
+       0x08, 0x6a, 0x18, 0x01,
+       0xff, 0x6a, 0x1a, 0x09,
+       0xff, 0x6a, 0x1c, 0x09,
+       0x0d, 0x93, 0x26, 0x01,
+       0x00, 0x65, 0x7e, 0x5d,
+       0x88, 0x6a, 0x6e, 0x5d,
+       0x01, 0x8c, 0x86, 0x7a,
+       0x01, 0x59, 0xb2, 0x10,
+       0x03, 0x8c, 0x10, 0x30,
+       0x00, 0x65, 0xee, 0x5c,
+       0xff, 0x6a, 0xc8, 0x08,
+       0x08, 0x39, 0x72, 0x18,
+       0x00, 0x3a, 0x74, 0x20,
+       0x80, 0x0b, 0x26, 0x6a,
+       0x01, 0x0c, 0x92, 0x7a,
+       0x10, 0x0c, 0x26, 0x7a,
+       0xff, 0x35, 0x26, 0x09,
+       0x04, 0x0b, 0x98, 0x6a,
+       0x00, 0x65, 0xbe, 0x5a,
+       0x03, 0x08, 0x52, 0x31,
+       0xff, 0x08, 0x52, 0x09,
+       0xff, 0x09, 0x54, 0x09,
+       0xff, 0x0a, 0x56, 0x09,
+       0xff, 0x38, 0x50, 0x09,
+       0x12, 0x01, 0x02, 0x00,
+       0x04, 0x36, 0xcc, 0x79,
+       0xfb, 0x36, 0x6c, 0x08,
+       0x04, 0x93, 0x2c, 0x79,
+       0x01, 0x0c, 0xae, 0x6a,
+       0x00, 0x65, 0x2c, 0x41,
+       0x00, 0x65, 0xcc, 0x41,
+       0x00, 0x65, 0xbe, 0x5a,
+       0x12, 0x01, 0x02, 0x00,
+       0x7f, 0x02, 0x04, 0x08,
+       0xf1, 0x6a, 0x22, 0x01,
+       0x00, 0x65, 0xcc, 0x41,
+       0x04, 0x93, 0xd0, 0x6a,
+       0xdf, 0x93, 0x26, 0x09,
+       0x20, 0x93, 0xc2, 0x6a,
+       0x02, 0x93, 0x26, 0x01,
+       0x01, 0x94, 0xc4, 0x7a,
+       0x01, 0x94, 0xc4, 0x7a,
+       0x01, 0x94, 0xc4, 0x7a,
+       0x01, 0x94, 0xc4, 0x7a,
+       0x01, 0x94, 0xc4, 0x7a,
+       0x10, 0x94, 0xd0, 0x6a,
+       0xd7, 0x93, 0x26, 0x09,
+       0x08, 0x93, 0xd4, 0x6a,
+       0xff, 0x6a, 0xd4, 0x0c,
+       0x00, 0x65, 0x54, 0x5c,
+       0xff, 0xb8, 0x18, 0x09,
+       0x02, 0x6a, 0x1a, 0x31,
+       0x03, 0x8c, 0x10, 0x30,
+       0xef, 0xb8, 0xd4, 0x18,
+       0x00, 0x65, 0xee, 0x4a,
+       0x01, 0x6a, 0x10, 0x31,
+       0xa4, 0x6a, 0x26, 0x01,
+       0x35, 0x6a, 0x26, 0x01,
+       0x10, 0xc0, 0x32, 0x31,
+       0x00, 0x65, 0xfe, 0x42,
+       0x04, 0xb4, 0x10, 0x31,
+       0x88, 0x6a, 0xcc, 0x00,
+       0xb4, 0x6a, 0xf8, 0x5c,
+       0xff, 0x6a, 0x1a, 0x09,
+       0xff, 0x6a, 0x1c, 0x09,
+       0x00, 0x65, 0xee, 0x5c,
+       0x3d, 0x6a, 0x26, 0x01,
+       0xac, 0x6a, 0x26, 0x01,
+       0x04, 0x0b, 0x02, 0x6b,
+       0x10, 0x0c, 0xfe, 0x7a,
+       0x01, 0x03, 0x02, 0x6b,
+       0xc7, 0x93, 0x26, 0x09,
+       0x38, 0x93, 0x06, 0x6b,
+       0x00, 0x65, 0xcc, 0x41,
+       0x00, 0x65, 0x54, 0x5c,
+       0xff, 0x06, 0x44, 0x09,
+       0x00, 0x65, 0xcc, 0x41,
+       0x10, 0x3d, 0x06, 0x00,
+       0xff, 0x34, 0xca, 0x08,
+       0x80, 0x65, 0x46, 0x63,
+       0x10, 0xa0, 0x68, 0x6b,
+       0xff, 0xa1, 0xdc, 0x08,
+       0xff, 0x6e, 0xc8, 0x08,
+       0xf0, 0x86, 0x20, 0x7b,
+       0x61, 0x6a, 0x22, 0x01,
+       0xff, 0x6a, 0xd4, 0x08,
+       0xff, 0x56, 0xca, 0x08,
+       0x08, 0xa1, 0x28, 0x7b,
+       0xff, 0x57, 0xca, 0x08,
+       0x80, 0xa1, 0x2c, 0x7b,
+       0xff, 0x57, 0xca, 0x08,
+       0x00, 0x65, 0x68, 0x6b,
+       0x07, 0xa1, 0xca, 0x08,
+       0x40, 0xa0, 0xc8, 0x08,
+       0x00, 0x65, 0xca, 0x00,
+       0x80, 0x65, 0xca, 0x00,
+       0x20, 0xa0, 0x4a, 0x7b,
+       0xff, 0x65, 0x0c, 0x08,
+       0x00, 0x65, 0xe6, 0x5c,
+       0xa0, 0x3d, 0x52, 0x63,
+       0x23, 0xa0, 0x0c, 0x08,
+       0x00, 0x65, 0xe6, 0x5c,
+       0xa0, 0x3d, 0x52, 0x63,
+       0x00, 0xb9, 0x4a, 0x43,
+       0xff, 0x65, 0x4a, 0x63,
+       0x00, 0x65, 0x68, 0x43,
+       0x40, 0x6a, 0x18, 0x00,
+       0xff, 0x65, 0x0c, 0x08,
+       0x00, 0x65, 0xe6, 0x5c,
+       0xa0, 0x3d, 0x10, 0x73,
+       0x40, 0x6a, 0x18, 0x00,
+       0xff, 0x34, 0xa8, 0x08,
+       0x08, 0x6a, 0x68, 0x00,
+       0x00, 0x65, 0xcc, 0x41,
+       0x64, 0x6a, 0x16, 0x5c,
+       0x80, 0x64, 0xc6, 0x6b,
+       0x04, 0x64, 0xa8, 0x73,
+       0x02, 0x64, 0xae, 0x73,
+       0x00, 0x6a, 0x74, 0x73,
+       0x03, 0x64, 0xc2, 0x73,
+       0x08, 0x64, 0x70, 0x73,
+       0xa1, 0x6a, 0x22, 0x01,
+       0x00, 0x65, 0xe6, 0x5c,
+       0x08, 0x52, 0xce, 0x71,
+       0x00, 0x65, 0x68, 0x43,
+       0xff, 0x06, 0xd4, 0x08,
+       0x00, 0x65, 0xcc, 0x41,
+       0xff, 0xa8, 0x78, 0x6b,
+       0xff, 0xa2, 0x90, 0x7b,
+       0x01, 0x6a, 0x6a, 0x00,
+       0x00, 0xb9, 0x18, 0x5d,
+       0xff, 0xa2, 0x90, 0x7b,
+       0x71, 0x6a, 0x22, 0x01,
+       0xff, 0x6a, 0xd4, 0x08,
+       0x40, 0x52, 0x90, 0x63,
+       0x0d, 0x6a, 0x6a, 0x00,
+       0x00, 0xb9, 0x18, 0x5d,
+       0xff, 0x3e, 0x74, 0x09,
+       0xff, 0x90, 0x7c, 0x08,
+       0x00, 0x65, 0x50, 0x58,
+       0x00, 0x65, 0xde, 0x41,
+       0x20, 0xa0, 0x94, 0x6b,
+       0xff, 0x37, 0xc8, 0x08,
+       0x00, 0xb9, 0x98, 0x5b,
+       0x00, 0x65, 0xde, 0x41,
+       0x00, 0x65, 0x86, 0x5d,
+       0xff, 0x65, 0xa4, 0x08,
+       0xff, 0xf8, 0xc8, 0x08,
+       0xff, 0x4f, 0xc8, 0x08,
+       0x00, 0x6a, 0xba, 0x5c,
+       0x00, 0x52, 0xd0, 0x5c,
+       0x01, 0x4f, 0x9e, 0x18,
+       0x02, 0x6a, 0x22, 0x05,
+       0x04, 0xa0, 0x40, 0x01,
+       0x00, 0x65, 0xa0, 0x5d,
+       0x00, 0x65, 0xde, 0x41,
+       0x20, 0x36, 0x70, 0x7b,
+       0x05, 0x38, 0x46, 0x31,
+       0x04, 0x14, 0x58, 0x31,
+       0x03, 0xa9, 0x60, 0x31,
+       0xa3, 0x6a, 0xcc, 0x00,
+       0x38, 0x6a, 0xf8, 0x5c,
+       0xac, 0x6a, 0xcc, 0x00,
+       0x14, 0x6a, 0xfa, 0x5c,
+       0xa9, 0x6a, 0xfc, 0x5c,
+       0x00, 0x65, 0x70, 0x43,
+       0xdf, 0x36, 0x6c, 0x08,
+       0x00, 0x65, 0x70, 0x43,
+       0x0f, 0x64, 0xc8, 0x08,
+       0x07, 0x64, 0xc8, 0x08,
+       0x00, 0x37, 0x6e, 0x00,
+       0xff, 0x6a, 0xa6, 0x00,
+       0x00, 0x65, 0x8a, 0x5c,
+       0xff, 0x52, 0xd8, 0x73,
+       0x40, 0x36, 0xe2, 0x7b,
+       0x00, 0x65, 0x78, 0x5c,
+       0x00, 0x65, 0xe4, 0x43,
+       0xff, 0x06, 0xd4, 0x08,
+       0x00, 0x65, 0xe6, 0x5c,
+       0xe0, 0x3d, 0x00, 0x64,
+       0x20, 0x12, 0x00, 0x64,
+       0x52, 0x6a, 0x0c, 0x5c,
+       0x00, 0x65, 0x72, 0x5c,
+       0xff, 0x37, 0xc8, 0x08,
+       0x00, 0xa1, 0xf8, 0x63,
+       0x04, 0xa0, 0xf8, 0x7b,
+       0xfb, 0xa0, 0x40, 0x09,
+       0x80, 0x36, 0x6c, 0x00,
+       0x00, 0x65, 0x74, 0x58,
+       0x10, 0xa0, 0x70, 0x7b,
+       0xef, 0xa0, 0x40, 0x09,
+       0xff, 0x6a, 0x04, 0x5c,
+       0x00, 0x65, 0x70, 0x43,
+       0x04, 0xa0, 0xfe, 0x7b,
+       0x00, 0x65, 0xa0, 0x5d,
+       0x00, 0x65, 0x00, 0x44,
+       0x00, 0x65, 0x86, 0x5d,
+       0x31, 0x6a, 0x22, 0x01,
+       0x00, 0x65, 0x70, 0x43,
+       0x10, 0x3d, 0x06, 0x00,
+       0xff, 0x65, 0x68, 0x0c,
+       0xb1, 0x6a, 0x22, 0x01,
+       0x00, 0x65, 0x0e, 0x44,
+       0xff, 0x06, 0xd4, 0x08,
+       0x01, 0x0c, 0x0e, 0x7c,
+       0x04, 0x0c, 0x08, 0x6c,
+       0xe0, 0x03, 0x7a, 0x08,
+       0xe0, 0x3d, 0x3c, 0x64,
+       0xff, 0x65, 0xcc, 0x08,
+       0xff, 0x12, 0xda, 0x0c,
+       0xff, 0x06, 0xd4, 0x0c,
+       0x01, 0x03, 0x1c, 0x6c,
+       0x40, 0x03, 0xcc, 0x08,
+       0xff, 0x65, 0x06, 0x08,
+       0x40, 0x65, 0xc8, 0x08,
+       0x00, 0x66, 0x2a, 0x74,
+       0x40, 0x65, 0x2a, 0x7c,
+       0x00, 0x65, 0x2a, 0x5c,
+       0xff, 0x6a, 0xd4, 0x08,
+       0xff, 0x6a, 0xd4, 0x08,
+       0xff, 0x6a, 0xd4, 0x08,
+       0xff, 0x6a, 0xd4, 0x0c,
+       0x08, 0x01, 0x02, 0x00,
+       0x02, 0x0b, 0x34, 0x7c,
+       0xff, 0x65, 0x0c, 0x08,
+       0x02, 0x0b, 0x38, 0x7c,
+       0xf7, 0x01, 0x02, 0x0c,
+       0xe1, 0x6a, 0x22, 0x01,
+       0x00, 0x65, 0xcc, 0x41,
+       0xff, 0x65, 0x26, 0x09,
+       0x01, 0x0b, 0x4c, 0x6c,
+       0x10, 0x0c, 0x42, 0x7c,
+       0x04, 0x93, 0x4a, 0x6c,
+       0x01, 0x94, 0x48, 0x7c,
+       0x10, 0x94, 0x4a, 0x6c,
+       0xc7, 0x93, 0x26, 0x09,
+       0xff, 0x99, 0xd4, 0x08,
+       0x38, 0x93, 0x4e, 0x6c,
+       0xff, 0x6a, 0xd4, 0x0c,
+       0x80, 0x36, 0x52, 0x6c,
+       0x21, 0x6a, 0x22, 0x05,
+       0xff, 0x65, 0x20, 0x09,
+       0xff, 0x52, 0x60, 0x64,
+       0xff, 0x37, 0xc8, 0x08,
+       0xa1, 0x6a, 0x6c, 0x44,
+       0xff, 0x52, 0xc8, 0x08,
+       0xb9, 0x6a, 0x6c, 0x44,
+       0xff, 0x90, 0xa6, 0x08,
+       0xff, 0xba, 0x70, 0x74,
+       0xff, 0xba, 0x20, 0x09,
+       0xff, 0x65, 0xca, 0x18,
+       0x00, 0x6c, 0x64, 0x64,
+       0xff, 0x90, 0xca, 0x0c,
+       0xff, 0x6a, 0xca, 0x04,
+       0x40, 0x36, 0x84, 0x7c,
+       0x00, 0x90, 0x58, 0x5c,
+       0xff, 0x65, 0x84, 0x74,
+       0xff, 0x53, 0x82, 0x74,
+       0xff, 0xba, 0xcc, 0x08,
+       0xff, 0x53, 0x20, 0x09,
+       0xff, 0x66, 0x74, 0x09,
+       0xff, 0x65, 0x20, 0x0d,
+       0xff, 0xba, 0x7e, 0x0c,
+       0x00, 0x6a, 0x8e, 0x5d,
+       0x0d, 0x6a, 0x6a, 0x00,
+       0x00, 0x52, 0x18, 0x45,
+       0xff, 0x3f, 0xde, 0x74,
+       0xff, 0x6a, 0xa4, 0x00,
+       0x00, 0x3f, 0x58, 0x5c,
+       0xff, 0x65, 0xde, 0x74,
+       0x40, 0x36, 0x6c, 0x00,
+       0x20, 0xa0, 0x98, 0x6c,
+       0xff, 0xb9, 0xa4, 0x0c,
+       0xff, 0x6a, 0xa4, 0x04,
+       0xff, 0x65, 0xa6, 0x08,
+       0xe0, 0x6a, 0xcc, 0x00,
+       0x45, 0x6a, 0x0c, 0x5d,
+       0x01, 0x6a, 0xd0, 0x01,
+       0x09, 0x6a, 0xd6, 0x01,
+       0x80, 0xeb, 0xa4, 0x7c,
+       0x01, 0x6a, 0xd6, 0x01,
+       0x01, 0xe9, 0xa6, 0x34,
+       0x88, 0x6a, 0xcc, 0x00,
+       0x45, 0x6a, 0x0c, 0x5d,
+       0x01, 0x6a, 0x18, 0x01,
+       0xff, 0x6a, 0x1a, 0x09,
+       0xff, 0x6a, 0x1c, 0x09,
+       0x0d, 0x6a, 0x26, 0x01,
+       0x00, 0x65, 0x7e, 0x5d,
+       0xff, 0x99, 0xa6, 0x0c,
+       0xff, 0x65, 0xa6, 0x08,
+       0xe0, 0x6a, 0xcc, 0x00,
+       0x45, 0x6a, 0x0c, 0x5d,
+       0x01, 0x6a, 0xd0, 0x01,
+       0x01, 0x6a, 0xdc, 0x05,
+       0x88, 0x6a, 0xcc, 0x00,
+       0x45, 0x6a, 0x0c, 0x5d,
+       0x01, 0x6a, 0x18, 0x01,
+       0xff, 0x6a, 0x1a, 0x09,
+       0xff, 0x6a, 0x1c, 0x09,
+       0x01, 0x6a, 0x26, 0x05,
+       0x01, 0x65, 0xd8, 0x31,
+       0x09, 0xee, 0xdc, 0x01,
+       0x80, 0xee, 0xd4, 0x7c,
+       0xff, 0x6a, 0xdc, 0x0d,
+       0xff, 0x65, 0x32, 0x09,
+       0x0a, 0x93, 0x26, 0x01,
+       0x00, 0x65, 0x7e, 0x45,
+       0xff, 0x37, 0xc8, 0x08,
+       0x02, 0x6a, 0x9a, 0x5c,
+       0xff, 0x53, 0xa4, 0x0c,
+       0xb1, 0x6a, 0x22, 0x01,
+       0x01, 0x0c, 0xe6, 0x7c,
+       0x04, 0x0c, 0xe4, 0x6c,
+       0xe0, 0x03, 0x06, 0x08,
+       0xe0, 0x03, 0x7a, 0x0c,
+       0xff, 0x8c, 0x10, 0x08,
+       0xff, 0x8d, 0x12, 0x08,
+       0xff, 0x8e, 0x14, 0x0c,
+       0xff, 0x6c, 0xda, 0x08,
+       0xff, 0x6c, 0xda, 0x08,
+       0xff, 0x6c, 0xda, 0x08,
+       0xff, 0x6c, 0xda, 0x08,
+       0xff, 0x6c, 0xda, 0x08,
+       0xff, 0x6c, 0xda, 0x08,
+       0xff, 0x6c, 0xda, 0x0c,
+       0x3d, 0x64, 0xa6, 0x28,
+       0x55, 0x64, 0xc8, 0x28,
+       0x00, 0x65, 0x0c, 0x45,
+       0x2e, 0x64, 0xa6, 0x28,
+       0x66, 0x64, 0xc8, 0x28,
+       0x00, 0x6c, 0xda, 0x18,
+       0xff, 0x53, 0xc8, 0x08,
+       0x00, 0x6c, 0xda, 0x20,
+       0xff, 0x6a, 0xc8, 0x08,
+       0x00, 0x6c, 0xda, 0x20,
+       0x00, 0x6c, 0xda, 0x24,
+       0xff, 0x65, 0xc8, 0x08,
+       0xe0, 0x6a, 0xcc, 0x00,
+       0x41, 0x6a, 0x08, 0x5d,
+       0xff, 0x90, 0xe2, 0x09,
+       0x04, 0x35, 0x2a, 0x7d,
+       0x30, 0x6a, 0xd0, 0x01,
+       0x1d, 0x6a, 0xdc, 0x01,
+       0xdc, 0xee, 0x26, 0x65,
+       0x00, 0x65, 0x38, 0x45,
+       0x1c, 0x6a, 0xd0, 0x01,
+       0x01, 0x6a, 0xdc, 0x01,
+       0x1c, 0xa0, 0xd8, 0x31,
+       0x09, 0xee, 0xdc, 0x01,
+       0x80, 0xee, 0x32, 0x7d,
+       0x19, 0x6a, 0xdc, 0x01,
+       0xd8, 0xee, 0x36, 0x65,
+       0xff, 0x6a, 0xdc, 0x09,
+       0x18, 0xee, 0x3a, 0x6d,
+       0xff, 0x6a, 0xd4, 0x0c,
+       0x88, 0x6a, 0xcc, 0x00,
+       0x41, 0x6a, 0x08, 0x5d,
+       0x1c, 0x6a, 0x18, 0x01,
+       0xff, 0x6a, 0x1a, 0x09,
+       0xff, 0x6a, 0x1c, 0x09,
+       0xff, 0x35, 0x26, 0x09,
+       0x04, 0x35, 0x62, 0x6d,
+       0xa0, 0x6a, 0xca, 0x00,
+       0x1c, 0x65, 0xc8, 0x18,
+       0xff, 0x6c, 0x32, 0x09,
+       0xff, 0x6c, 0x32, 0x09,
+       0xff, 0x6c, 0x32, 0x09,
+       0xff, 0x6c, 0x32, 0x09,
+       0xff, 0x6c, 0x32, 0x09,
+       0xff, 0x6c, 0x32, 0x09,
+       0xff, 0x6c, 0x32, 0x09,
+       0x00, 0x65, 0x50, 0x65,
+       0x0a, 0x93, 0x26, 0x01,
+       0x00, 0x65, 0x7e, 0x5d,
+       0x04, 0x35, 0x52, 0x7c,
+       0xa0, 0x6a, 0x6e, 0x5d,
+       0x00, 0x65, 0x70, 0x5d,
+       0x00, 0x65, 0x70, 0x5d,
+       0x00, 0x65, 0x70, 0x45,
+       0xff, 0x65, 0xcc, 0x08,
+       0xff, 0x99, 0xda, 0x08,
+       0xff, 0x99, 0xda, 0x08,
+       0xff, 0x99, 0xda, 0x08,
+       0xff, 0x99, 0xda, 0x08,
+       0xff, 0x99, 0xda, 0x08,
+       0xff, 0x99, 0xda, 0x08,
+       0xff, 0x99, 0xda, 0x0c,
+       0x08, 0x94, 0x7e, 0x7d,
+       0xf7, 0x93, 0x26, 0x09,
+       0x08, 0x93, 0x82, 0x6d,
+       0xff, 0x6a, 0xd4, 0x0c,
+       0xff, 0x40, 0x74, 0x09,
+       0xff, 0x6a, 0x72, 0x01,
+       0xff, 0x90, 0x80, 0x0c,
+       0xff, 0x6a, 0x72, 0x05,
+       0xff, 0x40, 0x9c, 0x65,
+       0xff, 0x3f, 0x94, 0x65,
+       0xff, 0x6a, 0xca, 0x04,
+       0xff, 0x3f, 0x20, 0x09,
+       0x01, 0x6a, 0x6a, 0x00,
+       0x00, 0xb9, 0x18, 0x5d,
+       0xff, 0xba, 0x7e, 0x0c,
+       0xff, 0x40, 0x20, 0x09,
+       0xff, 0xba, 0x80, 0x0c,
+       0xff, 0x3f, 0x74, 0x09,
+       0xff, 0x90, 0x7e, 0x0c,
+};
+
+static int ahc_patch16_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch16_func(struct ahc_softc *ahc)
+{
+       return ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895);
+}
+
+static int ahc_patch15_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch15_func(struct ahc_softc *ahc)
+{
+       return ((ahc->features & AHC_WIDE) != 0);
+}
+
+static int ahc_patch14_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch14_func(struct ahc_softc *ahc)
+{
+       return ((ahc->features & AHC_HS_MAILBOX) != 0);
+}
+
+static int ahc_patch13_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch13_func(struct ahc_softc *ahc)
+{
+       return ((ahc->features & AHC_CMD_CHAN) == 0);
+}
+
+static int ahc_patch12_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch12_func(struct ahc_softc *ahc)
+{
+       return ((ahc->features & AHC_ULTRA2) == 0);
+}
+
+static int ahc_patch11_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch11_func(struct ahc_softc *ahc)
+{
+       return ((ahc->features & AHC_MULTI_TID) != 0);
+}
+
+static int ahc_patch10_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch10_func(struct ahc_softc *ahc)
+{
+       return ((ahc->flags & AHC_INITIATORMODE) != 0);
+}
+
+static int ahc_patch9_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch9_func(struct ahc_softc *ahc)
+{
+       return ((ahc->features & AHC_ULTRA) != 0);
+}
+
+static int ahc_patch8_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch8_func(struct ahc_softc *ahc)
+{
+       return ((ahc->features & AHC_ULTRA2) != 0);
+}
+
+static int ahc_patch7_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch7_func(struct ahc_softc *ahc)
+{
+       return ((ahc->flags & AHC_TARGETMODE) != 0);
+}
+
+static int ahc_patch6_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch6_func(struct ahc_softc *ahc)
+{
+       return ((ahc->flags & AHC_PAGESCBS) == 0);
+}
+
+static int ahc_patch5_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch5_func(struct ahc_softc *ahc)
+{
+       return ((ahc->flags & AHC_PAGESCBS) != 0);
+}
+
+static int ahc_patch4_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch4_func(struct ahc_softc *ahc)
+{
+       return ((ahc->features & AHC_QUEUE_REGS) != 0);
+}
+
+static int ahc_patch3_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch3_func(struct ahc_softc *ahc)
+{
+       return ((ahc->features & AHC_TWIN) != 0);
+}
+
+static int ahc_patch2_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch2_func(struct ahc_softc *ahc)
+{
+       return ((ahc->features & AHC_QUEUE_REGS) == 0);
+}
+
+static int ahc_patch1_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch1_func(struct ahc_softc *ahc)
+{
+       return ((ahc->features & AHC_CMD_CHAN) != 0);
+}
+
+static int ahc_patch0_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch0_func(struct ahc_softc *ahc)
+{
+       return (0);
+}
+
+typedef int patch_func_t __P((struct ahc_softc *));
+struct patch {
+       patch_func_t    *patch_func;
+       u_int32_t       begin      :10,
+                       skip_instr :10,
+                       skip_patch :12;
+} patches[] = {
+       { ahc_patch1_func, 4, 2, 1 },
+       { ahc_patch2_func, 8, 1, 1 },
+       { ahc_patch2_func, 9, 1, 1 },
+       { ahc_patch3_func, 12, 4, 1 },
+       { ahc_patch4_func, 17, 3, 2 },
+       { ahc_patch0_func, 20, 4, 1 },
+       { ahc_patch5_func, 24, 1, 1 },
+       { ahc_patch6_func, 27, 1, 1 },
+       { ahc_patch1_func, 30, 1, 2 },
+       { ahc_patch0_func, 31, 3, 1 },
+       { ahc_patch3_func, 40, 4, 1 },
+       { ahc_patch7_func, 45, 5, 3 },
+       { ahc_patch8_func, 46, 1, 2 },
+       { ahc_patch0_func, 47, 1, 1 },
+       { ahc_patch8_func, 50, 3, 2 },
+       { ahc_patch0_func, 53, 3, 1 },
+       { ahc_patch9_func, 58, 2, 1 },
+       { ahc_patch8_func, 60, 1, 2 },
+       { ahc_patch0_func, 61, 1, 1 },
+       { ahc_patch7_func, 64, 64, 24 },
+       { ahc_patch10_func, 64, 1, 1 },
+       { ahc_patch1_func, 69, 3, 2 },
+       { ahc_patch0_func, 72, 3, 1 },
+       { ahc_patch1_func, 76, 1, 2 },
+       { ahc_patch0_func, 77, 1, 1 },
+       { ahc_patch1_func, 78, 3, 6 },
+       { ahc_patch11_func, 78, 1, 2 },
+       { ahc_patch0_func, 79, 2, 3 },
+       { ahc_patch8_func, 79, 1, 2 },
+       { ahc_patch0_func, 80, 1, 1 },
+       { ahc_patch0_func, 81, 3, 5 },
+       { ahc_patch11_func, 81, 1, 2 },
+       { ahc_patch0_func, 82, 2, 3 },
+       { ahc_patch8_func, 82, 1, 2 },
+       { ahc_patch0_func, 83, 1, 1 },
+       { ahc_patch1_func, 88, 1, 2 },
+       { ahc_patch0_func, 89, 1, 1 },
+       { ahc_patch1_func, 98, 1, 2 },
+       { ahc_patch0_func, 99, 1, 1 },
+       { ahc_patch1_func, 102, 1, 2 },
+       { ahc_patch0_func, 103, 1, 1 },
+       { ahc_patch1_func, 119, 1, 2 },
+       { ahc_patch0_func, 120, 1, 1 },
+       { ahc_patch10_func, 128, 7, 2 },
+       { ahc_patch3_func, 129, 2, 1 },
+       { ahc_patch7_func, 140, 85, 8 },
+       { ahc_patch5_func, 155, 1, 1 },
+       { ahc_patch1_func, 177, 1, 2 },
+       { ahc_patch0_func, 178, 1, 1 },
+       { ahc_patch1_func, 187, 1, 2 },
+       { ahc_patch0_func, 188, 1, 1 },
+       { ahc_patch1_func, 209, 6, 2 },
+       { ahc_patch0_func, 215, 8, 1 },
+       { ahc_patch10_func, 225, 20, 1 },
+       { ahc_patch8_func, 246, 1, 2 },
+       { ahc_patch0_func, 247, 2, 1 },
+       { ahc_patch8_func, 251, 2, 2 },
+       { ahc_patch0_func, 253, 3, 3 },
+       { ahc_patch1_func, 253, 1, 2 },
+       { ahc_patch0_func, 254, 2, 1 },
+       { ahc_patch8_func, 258, 1, 2 },
+       { ahc_patch0_func, 259, 1, 1 },
+       { ahc_patch1_func, 263, 1, 1 },
+       { ahc_patch1_func, 266, 1, 2 },
+       { ahc_patch0_func, 267, 2, 1 },
+       { ahc_patch12_func, 270, 2, 3 },
+       { ahc_patch1_func, 270, 1, 2 },
+       { ahc_patch0_func, 271, 1, 1 },
+       { ahc_patch1_func, 272, 1, 2 },
+       { ahc_patch0_func, 273, 2, 1 },
+       { ahc_patch8_func, 278, 1, 2 },
+       { ahc_patch0_func, 279, 4, 3 },
+       { ahc_patch1_func, 279, 1, 2 },
+       { ahc_patch0_func, 280, 3, 1 },
+       { ahc_patch8_func, 284, 1, 2 },
+       { ahc_patch0_func, 285, 3, 2 },
+       { ahc_patch7_func, 285, 2, 1 },
+       { ahc_patch8_func, 288, 5, 2 },
+       { ahc_patch0_func, 293, 1, 1 },
+       { ahc_patch1_func, 300, 13, 2 },
+       { ahc_patch0_func, 313, 8, 1 },
+       { ahc_patch12_func, 323, 2, 3 },
+       { ahc_patch1_func, 323, 1, 2 },
+       { ahc_patch0_func, 324, 1, 1 },
+       { ahc_patch7_func, 328, 1, 1 },
+       { ahc_patch8_func, 331, 2, 1 },
+       { ahc_patch8_func, 333, 1, 1 },
+       { ahc_patch1_func, 334, 1, 2 },
+       { ahc_patch0_func, 335, 3, 1 },
+       { ahc_patch8_func, 339, 1, 1 },
+       { ahc_patch7_func, 340, 5, 1 },
+       { ahc_patch8_func, 346, 2, 1 },
+       { ahc_patch8_func, 351, 13, 1 },
+       { ahc_patch10_func, 364, 96, 13 },
+       { ahc_patch1_func, 365, 11, 5 },
+       { ahc_patch12_func, 367, 1, 1 },
+       { ahc_patch8_func, 371, 1, 2 },
+       { ahc_patch0_func, 372, 1, 1 },
+       { ahc_patch0_func, 376, 4, 1 },
+       { ahc_patch12_func, 380, 2, 3 },
+       { ahc_patch13_func, 380, 1, 1 },
+       { ahc_patch0_func, 382, 1, 1 },
+       { ahc_patch14_func, 398, 3, 1 },
+       { ahc_patch3_func, 402, 2, 2 },
+       { ahc_patch0_func, 404, 2, 2 },
+       { ahc_patch15_func, 404, 2, 1 },
+       { ahc_patch4_func, 462, 1, 2 },
+       { ahc_patch0_func, 463, 1, 1 },
+       { ahc_patch2_func, 466, 1, 1 },
+       { ahc_patch10_func, 468, 58, 6 },
+       { ahc_patch1_func, 472, 3, 2 },
+       { ahc_patch0_func, 475, 5, 1 },
+       { ahc_patch15_func, 483, 1, 2 },
+       { ahc_patch0_func, 484, 1, 1 },
+       { ahc_patch5_func, 489, 1, 1 },
+       { ahc_patch7_func, 526, 16, 1 },
+       { ahc_patch12_func, 551, 1, 1 },
+       { ahc_patch1_func, 590, 7, 2 },
+       { ahc_patch0_func, 597, 8, 1 },
+       { ahc_patch1_func, 606, 4, 2 },
+       { ahc_patch0_func, 610, 6, 1 },
+       { ahc_patch1_func, 616, 4, 2 },
+       { ahc_patch0_func, 620, 3, 1 },
+       { ahc_patch13_func, 631, 10, 1 },
+       { ahc_patch7_func, 641, 3, 1 },
+       { ahc_patch1_func, 653, 18, 4 },
+       { ahc_patch16_func, 662, 4, 2 },
+       { ahc_patch0_func, 666, 2, 1 },
+       { ahc_patch0_func, 671, 32, 1 },
+       { ahc_patch5_func, 707, 3, 2 },
+       { ahc_patch0_func, 710, 1, 1 },
+       { ahc_patch5_func, 711, 9, 1 },
+
+};
diff --git a/sys/dev/microcode/aic7xxx/aicasm.c b/sys/dev/microcode/aic7xxx/aicasm.c
new file mode 100644 (file)
index 0000000..c293601
--- /dev/null
@@ -0,0 +1,721 @@
+/* $OpenBSD: aicasm.c,v 1.1 2000/03/22 02:50:49 smurph Exp $ */
+/*
+ * Aic7xxx SCSI host adapter firmware asssembler
+ *
+ * Copyright (c) 1997, 1998 Justin T. Gibbs.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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.
+ *
+ * $FreeBSD: src/sys/dev/aic7xxx/aicasm.c,v 1.23 1999/08/28 00:41:25 peter Exp $
+ */
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "aicasm.h"
+#include "aicasm_symbol.h"
+#include "sequencer.h"
+
+typedef struct patch {
+       TAILQ_ENTRY(patch) links;
+       int             patch_func;
+       u_int           begin;
+       u_int           skip_instr;
+       u_int           skip_patch;
+} patch_t;
+
+TAILQ_HEAD(patch_list, patch) patches;
+
+static void usage(void);
+static void back_patch(void);
+static void output_code(FILE *ofile);
+static void output_listing(FILE *listfile, char *ifilename);
+static void dump_scope(scope_t *scope);
+static void emit_patch(scope_t *scope, int patch);
+static int check_patch(patch_t **start_patch, int start_instr,
+                      int *skip_addr, int *func_vals);
+
+struct path_list search_path;
+int includes_search_curdir;
+char *appname;
+FILE *ofile;
+char *ofilename;
+char *regfilename;
+FILE *regfile;
+char *listfilename;
+FILE *listfile;
+
+static TAILQ_HEAD(,instruction) seq_program;
+struct scope_list scope_stack;
+symlist_t patch_functions;
+
+#if DEBUG
+extern int yy_flex_debug;
+extern int yydebug;
+#endif
+extern FILE *yyin;
+extern int yyparse __P((void));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       extern char *optarg;
+       extern int optind;
+       int  ch;
+       int  retval;
+       char *inputfilename;
+       scope_t *sentinal;
+
+       TAILQ_INIT(&patches);
+       SLIST_INIT(&search_path);
+       TAILQ_INIT(&seq_program);
+       SLIST_INIT(&scope_stack);
+
+       /* Set Sentinal scope node */
+       sentinal = scope_alloc();
+       sentinal->type = SCOPE_ROOT;
+       
+       includes_search_curdir = 1;
+       appname = *argv;
+       regfile = NULL;
+       listfile = NULL;
+#if DEBUG
+       yy_flex_debug = 0;
+       yydebug = 0;
+#endif
+       while ((ch = getopt(argc, argv, "d:l:n:o:r:I:O:")) != -1) {
+               switch(ch) {
+               case 'd':
+#if DEBUG
+                       if (strcmp(optarg, "s") == 0) {
+                               yy_flex_debug = 1;
+                       } else if (strcmp(optarg, "p") == 0) {
+                               yydebug = 1;
+                       } else {
+                               fprintf(stderr, "%s: -d Requires either an "
+                                       "'s' or 'p' argument\n", appname);
+                               usage();
+                       }
+#else
+                       stop("-d: Assembler not built with debugging "
+                            "information", EX_SOFTWARE);
+#endif
+                       break;
+               case 'l':
+                       /* Create a program listing */
+                       if ((listfile = fopen(optarg, "w")) == NULL) {
+                               perror(optarg);
+                               stop(NULL, EX_CANTCREAT);
+                       }
+                       listfilename = optarg;
+                       break;
+               case 'n':
+                       /* Don't complain about the -nostdinc directrive */
+                       if (strcmp(optarg, "ostdinc")) {
+                               fprintf(stderr, "%s: Unknown option -%c%s\n",
+                                       appname, ch, optarg);
+                               usage();
+                               /* NOTREACHED */
+                       }
+                       break;
+               case 'o':
+                       if ((ofile = fopen(optarg, "w")) == NULL) {
+                               perror(optarg);
+                               stop(NULL, EX_CANTCREAT);
+                       }
+                       ofilename = optarg;
+                       break;
+               case 'r':
+                       if ((regfile = fopen(optarg, "w")) == NULL) {
+                               perror(optarg);
+                               stop(NULL, EX_CANTCREAT);
+                       }
+                       regfilename = optarg;
+                       break;
+               case 'I':
+               {
+                       path_entry_t include_dir;
+
+                       if (strcmp(optarg, "-") == 0) {
+                               if (includes_search_curdir == 0) {
+                                       fprintf(stderr, "%s: Warning - '-I-' "
+                                                       "specified multiple "
+                                                       "times\n", appname);
+                               }
+                               includes_search_curdir = 0;
+                               for (include_dir = search_path.slh_first;
+                                    include_dir != NULL;
+                                    include_dir = include_dir->links.sle_next)
+                                       /*
+                                        * All entries before a '-I-' only
+                                        * apply to includes specified with
+                                        * quotes instead of "<>".
+                                        */
+                                       include_dir->quoted_includes_only = 1;
+                       } else {
+                               include_dir =
+                                   (path_entry_t)malloc(sizeof(*include_dir));
+                               if (include_dir == NULL) {
+                                       perror(optarg);
+                                       stop(NULL, EX_OSERR);
+                               }
+                               include_dir->directory = strdup(optarg);
+                               if (include_dir->directory == NULL) {
+                                       perror(optarg);
+                                       stop(NULL, EX_OSERR);
+                               }
+                               include_dir->quoted_includes_only = 0;
+                               SLIST_INSERT_HEAD(&search_path, include_dir,
+                                                 links);
+                       }
+                       break;
+               }
+               case '?':
+               default:
+                       usage();
+                       /* NOTREACHED */
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 1) {
+               fprintf(stderr, "%s: No input file specifiled\n", appname);
+               usage();
+               /* NOTREACHED */
+       }
+
+       symtable_open();
+       inputfilename = *argv;
+       include_file(*argv, SOURCE_FILE);
+       retval = yyparse();
+       if (retval == 0) {
+               if (SLIST_FIRST(&scope_stack) == NULL
+                || SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) {
+                       stop("Unterminated conditional expression",
+                            EX_DATAERR);
+                       /* NOTREACHED */
+               }
+
+               /* Process outmost scope */
+               process_scope(SLIST_FIRST(&scope_stack));
+               /*
+                * Decend the tree of scopes and insert/emit
+                * patches as appropriate.  We perform a depth first
+                * tranversal, recursively handling each scope.
+                */
+               /* start at the root scope */
+               dump_scope(SLIST_FIRST(&scope_stack));
+
+               /* Patch up forward jump addresses */
+               back_patch();
+
+               if (ofile != NULL)
+                       output_code(ofile);
+               if (regfile != NULL) {
+                       symtable_dump(regfile);
+               }
+               if (listfile != NULL)
+                       output_listing(listfile, inputfilename);
+       }
+
+       stop(NULL, 0);
+       /* NOTREACHED */
+       return (0);
+}
+
+static void
+usage()
+{
+
+       (void)fprintf(stderr,
+"usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file]
+                       [-r register_output_file] [-l program_list_file]
+                       input_file\n",
+                       appname);
+       exit(EX_USAGE);
+}
+
+static void
+back_patch()
+{
+       struct instruction *cur_instr;
+
+       for(cur_instr = seq_program.tqh_first;
+           cur_instr != NULL;
+           cur_instr = cur_instr->links.tqe_next) {
+               if (cur_instr->patch_label != NULL) {
+                       struct ins_format3 *f3_instr;
+                       u_int address;
+
+                       if (cur_instr->patch_label->type != LABEL) {
+                               char buf[255];
+
+                               snprintf(buf, sizeof(buf),
+                                        "Undefined label %s",
+                                        cur_instr->patch_label->name);
+                               stop(buf, EX_DATAERR);
+                               /* NOTREACHED */
+                       }
+                       f3_instr = &cur_instr->format.format3;
+                       address = f3_instr->address;
+                       address += cur_instr->patch_label->info.linfo->address;
+                       f3_instr->address = address;
+               }
+       }
+}
+
+static void
+output_code(ofile)
+       FILE *ofile;
+{
+       struct instruction *cur_instr;
+       patch_t *cur_patch;
+       symbol_node_t *cur_node;
+       int instrcount;
+
+       instrcount = 0;
+       fprintf(ofile,
+"/*
+ * DO NOT EDIT - This file is automatically generated.
+ */\n");
+
+       fprintf(ofile, "static u_int8_t seqprog[] = {\n");
+       for(cur_instr = seq_program.tqh_first;
+           cur_instr != NULL;
+           cur_instr = cur_instr->links.tqe_next) {
+
+               fprintf(ofile, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
+                       cur_instr->format.bytes[0],
+                       cur_instr->format.bytes[1],
+                       cur_instr->format.bytes[2],
+                       cur_instr->format.bytes[3]);
+               instrcount++;
+       }
+       fprintf(ofile, "};\n\n");
+
+       /*
+        *  Output patch information.  Patch functions first.
+        */
+       for(cur_node = SLIST_FIRST(&patch_functions);
+           cur_node != NULL;
+           cur_node = SLIST_NEXT(cur_node,links)) {
+               fprintf(ofile,
+"static int ahc_patch%d_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch%d_func(struct ahc_softc *ahc)
+{
+       return (%s);
+}\n\n",
+                       cur_node->symbol->info.condinfo->func_num,
+                       cur_node->symbol->info.condinfo->func_num,
+                       cur_node->symbol->name);
+       }
+
+       fprintf(ofile,
+"typedef int patch_func_t __P((struct ahc_softc *));
+struct patch {
+       patch_func_t    *patch_func;
+       u_int32_t       begin      :10,
+                       skip_instr :10,
+                       skip_patch :12;
+} patches[] = {\n");
+
+       for(cur_patch = TAILQ_FIRST(&patches);
+           cur_patch != NULL;
+           cur_patch = TAILQ_NEXT(cur_patch,links)) {
+               fprintf(ofile, "\t{ ahc_patch%d_func, %d, %d, %d },\n",
+                       cur_patch->patch_func, cur_patch->begin,
+                       cur_patch->skip_instr, cur_patch->skip_patch);
+       }
+
+       fprintf(ofile, "\n};\n");
+
+       fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
+}
+
+static void
+dump_scope(scope_t *scope)
+{
+       scope_t *cur_scope;
+
+       /*
+        * Emit the first patch for this scope
+        */
+       emit_patch(scope, 0);
+
+       /*
+        * Dump each scope within this one.
+        */
+       cur_scope = TAILQ_FIRST(&scope->inner_scope);
+
+       while (cur_scope != NULL) {
+
+               dump_scope(cur_scope);
+
+               cur_scope = TAILQ_NEXT(cur_scope, scope_links);
+       }
+
+       /*
+        * Emit the second, closing, patch for this scope
+        */
+       emit_patch(scope, 1);
+}
+
+void
+emit_patch(scope_t *scope, int patch)
+{
+       patch_info_t *pinfo;
+       patch_t *new_patch;
+
+       pinfo = &scope->patches[patch];
+
+       if (pinfo->skip_instr == 0)
+               /* No-Op patch */
+               return;
+
+       new_patch = (patch_t *)malloc(sizeof(*new_patch));
+
+       if (new_patch == NULL)
+               stop("Could not malloc patch structure", EX_OSERR);
+
+       memset(new_patch, 0, sizeof(*new_patch));
+
+       if (patch == 0) {
+               new_patch->patch_func = scope->func_num;
+               new_patch->begin = scope->begin_addr;
+       } else {
+               new_patch->patch_func = 0;
+               new_patch->begin = scope->end_addr;
+       }
+       new_patch->skip_instr = pinfo->skip_instr;
+       new_patch->skip_patch = pinfo->skip_patch;
+       TAILQ_INSERT_TAIL(&patches, new_patch, links);
+}
+
+void
+output_listing(FILE *listfile, char *ifilename)
+{
+       char buf[1024];
+       FILE *ifile;
+       struct instruction *cur_instr;
+       patch_t *cur_patch;
+       symbol_node_t *cur_func;
+       int *func_values;
+       int instrcount;
+       int instrptr;
+       int line;
+       int func_count;
+       int skip_addr;
+
+       instrcount = 0;
+       instrptr = 0;
+       line = 1;
+       skip_addr = 0;
+       if ((ifile = fopen(ifilename, "r")) == NULL) {
+               perror(ifilename);
+               stop(NULL, EX_DATAERR);
+       }
+
+       /*
+        * Determine which options to apply to this listing.
+        */
+       for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions);
+           cur_func != NULL;
+           cur_func = SLIST_NEXT(cur_func, links))
+               func_count++;
+
+       if (func_count != 0) {
+               func_values = (int *)malloc(func_count * sizeof(int));
+
+               if (func_values == NULL)
+                       stop("Could not malloc", EX_OSERR);
+               
+               func_values[0] = 0; /* FALSE func */
+               func_count--;
+
+               /*
+                * Ask the user to fill in the return values for
+                * the rest of the functions.
+                */
+               
+               
+               for (cur_func = SLIST_FIRST(&patch_functions);
+                    cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL;
+                    cur_func = SLIST_NEXT(cur_func, links), func_count--) {
+                       int input;
+                       
+                       fprintf(stdout, "\n(%s)\n", cur_func->symbol->name);
+                       fprintf(stdout,
+                               "Enter the return value for "
+                               "this expression[T/F]:");
+
+                       while (1) {
+
+                               input = getchar();
+                               input = toupper(input);
+
+                               if (input == 'T') {
+                                       func_values[func_count] = 1;
+                                       break;
+                               } else if (input == 'F') {
+                                       func_values[func_count] = 0;
+                                       break;
+                               }
+                       }
+                       if (isatty(fileno(stdin)) == 0)
+                               putchar(input);
+               }
+               fprintf(stdout, "\nThanks!\n");
+       }
+
+       /* Now output the listing */
+       cur_patch = TAILQ_FIRST(&patches);
+       for(cur_instr = TAILQ_FIRST(&seq_program);
+           cur_instr != NULL;
+           cur_instr = TAILQ_NEXT(cur_instr, links), instrcount++) {
+
+               if (check_patch(&cur_patch, instrcount,
+                               &skip_addr, func_values) == 0) {
+                       /* Don't count this instruction as it is in a patch
+                        * that was removed.
+                        */
+                        continue;
+               }
+
+               while (line < cur_instr->srcline) {
+                       fgets(buf, sizeof(buf), ifile);
+                               fprintf(listfile, "\t\t%s", buf);
+                               line++;
+               }
+               fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr,
+                       cur_instr->format.bytes[0],
+                       cur_instr->format.bytes[1],
+                       cur_instr->format.bytes[2],
+                       cur_instr->format.bytes[3]);
+               fgets(buf, sizeof(buf), ifile);
+               fprintf(listfile, "\t%s", buf);
+               line++;
+               instrptr++;
+       }
+       /* Dump the remainder of the file */
+       while(fgets(buf, sizeof(buf), ifile) != NULL)
+               fprintf(listfile, "\t\t%s", buf);
+
+       fclose(ifile);
+}
+
+static int
+check_patch(patch_t **start_patch, int start_instr,
+           int *skip_addr, int *func_vals)
+{
+       patch_t *cur_patch;
+
+       cur_patch = *start_patch;
+
+       while (cur_patch != NULL && start_instr == cur_patch->begin) {
+               if (func_vals[cur_patch->patch_func] == 0) {
+                       int skip;
+
+                       /* Start rejecting code */
+                       *skip_addr = start_instr + cur_patch->skip_instr;
+                       for (skip = cur_patch->skip_patch;
+                            skip > 0 && cur_patch != NULL;
+                            skip--)
+                               cur_patch = TAILQ_NEXT(cur_patch, links);
+               } else {
+                       /* Accepted this patch.  Advance to the next
+                        * one and wait for our intruction pointer to
+                        * hit this point.
+                        */
+                       cur_patch = TAILQ_NEXT(cur_patch, links);
+               }
+       }
+
+       *start_patch = cur_patch;
+       if (start_instr < *skip_addr)
+               /* Still skipping */
+               return (0);
+
+       return (1);
+}
+
+/*
+ * Print out error information if appropriate, and clean up before
+ * terminating the program.
+ */
+void
+stop(string, err_code)
+       const char *string;
+       int  err_code;
+{
+       if (string != NULL) {
+               fprintf(stderr, "%s: ", appname);
+               if (yyfilename != NULL) {
+                       fprintf(stderr, "Stopped at file %s, line %d - ",
+                               yyfilename, yylineno);
+               }
+               fprintf(stderr, "%s\n", string);
+       }
+
+       if (ofile != NULL) {
+               fclose(ofile);
+               if (err_code != 0) {
+                       fprintf(stderr, "%s: Removing %s due to error\n",
+                               appname, ofilename);
+                       unlink(ofilename);
+               }
+       }
+
+       if (regfile != NULL) {
+               fclose(regfile);
+               if (err_code != 0) {
+                       fprintf(stderr, "%s: Removing %s due to error\n",
+                               appname, regfilename);
+                       unlink(regfilename);
+               }
+       }
+
+       if (listfile != NULL) {
+               fclose(listfile);
+               if (err_code != 0) {
+                       fprintf(stderr, "%s: Removing %s due to error\n",
+                               appname, listfilename);
+                       unlink(listfilename);
+               }
+       }
+
+       symlist_free(&patch_functions);
+       symtable_close();
+
+       exit(err_code);
+}
+
+struct instruction *
+seq_alloc()
+{
+       struct instruction *new_instr;
+
+       new_instr = (struct instruction *)malloc(sizeof(struct instruction));
+       if (new_instr == NULL)
+               stop("Unable to malloc instruction object", EX_SOFTWARE);
+       memset(new_instr, 0, sizeof(*new_instr));
+       TAILQ_INSERT_TAIL(&seq_program, new_instr, links);
+       new_instr->srcline = yylineno;
+       return new_instr;
+}
+
+scope_t *
+scope_alloc()
+{
+       scope_t *new_scope;
+
+       new_scope = (scope_t *)malloc(sizeof(scope_t));
+       if (new_scope == NULL)
+               stop("Unable to malloc scope object", EX_SOFTWARE);
+       memset(new_scope, 0, sizeof(*new_scope));
+       TAILQ_INIT(&new_scope->inner_scope);
+       
+       if (SLIST_FIRST(&scope_stack) != NULL) {
+               TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope,
+                                 new_scope, scope_links);
+       }
+       /* This patch is now the current scope */
+       SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links);
+       return new_scope;
+}
+
+void
+process_scope(scope_t *scope)
+{
+       /*
+        * We are "leaving" this scope.  We should now have
+        * enough information to process the lists of scopes
+        * we encapsulate.
+        */
+       scope_t *cur_scope;
+       u_int skip_patch_count;
+       u_int skip_instr_count;
+
+       cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq);
+       skip_patch_count = 0;
+       skip_instr_count = 0;
+       while (cur_scope != NULL) {
+               u_int patch0_patch_skip;
+
+               patch0_patch_skip = 0;
+               switch (cur_scope->type) {
+               case SCOPE_IF:
+               case SCOPE_ELSE_IF:
+                       if (skip_instr_count != 0) {
+                               /* Create a tail patch */
+                               patch0_patch_skip++;
+                               cur_scope->patches[1].skip_patch =
+                                   skip_patch_count + 1;
+                               cur_scope->patches[1].skip_instr =
+                                   skip_instr_count;
+                       }
+
+                       /* Count Head patch */
+                       patch0_patch_skip++;
+
+                       /* Count any patches contained in our inner scope */
+                       patch0_patch_skip += cur_scope->inner_scope_patches;
+
+                       cur_scope->patches[0].skip_patch = patch0_patch_skip;
+                       cur_scope->patches[0].skip_instr =
+                           cur_scope->end_addr - cur_scope->begin_addr;
+
+                       skip_instr_count += cur_scope->patches[0].skip_instr;
+
+                       skip_patch_count += patch0_patch_skip;
+                       if (cur_scope->type == SCOPE_IF) {
+                               scope->inner_scope_patches += skip_patch_count;
+                               skip_patch_count = 0;
+                               skip_instr_count = 0;
+                       }
+                       break;
+               case SCOPE_ELSE:
+                       /* Count any patches contained in our innter scope */
+                       skip_patch_count += cur_scope->inner_scope_patches;
+
+                       skip_instr_count += cur_scope->end_addr
+                                         - cur_scope->begin_addr;
+                       break;
+               case SCOPE_ROOT:
+                       stop("Unexpected scope type encountered", EX_SOFTWARE);
+                       /* NOTREACHED */
+               }
+
+               cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
+       }
+}
diff --git a/sys/dev/microcode/aic7xxx/aicasm.h b/sys/dev/microcode/aic7xxx/aicasm.h
new file mode 100644 (file)
index 0000000..92f7e17
--- /dev/null
@@ -0,0 +1,68 @@
+/* $OpenBSD: aicasm.h,v 1.1 2000/03/22 02:50:49 smurph Exp $ */
+/*
+ * Assembler for the sequencer program downloaded to Aic7xxx SCSI host adapters
+ *
+ * Copyright (c) 1997 Justin T. Gibbs.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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.
+ *
+ * $FreeBSD: src/sys/dev/aic7xxx/aicasm.h,v 1.6 1999/12/06 18:23:30 gibbs Exp $
+ */
+
+#include <sys/queue.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+typedef struct path_entry {
+       char    *directory;
+       int     quoted_includes_only;
+       SLIST_ENTRY(path_entry) links;
+} *path_entry_t;
+
+typedef enum {  
+       QUOTED_INCLUDE,
+       BRACKETED_INCLUDE,
+       SOURCE_FILE
+} include_type;
+
+SLIST_HEAD(path_list, path_entry);
+
+extern struct path_list search_path;
+extern struct scope_list scope_stack;
+extern struct symlist patch_functions;
+extern int includes_search_curdir;             /* False if we've seen -I- */
+extern char *appname;
+extern int yylineno;
+extern char *yyfilename;
+
+void stop(const char *errstring, int err_code);
+void include_file(char *file_name, include_type type);
+struct instruction *seq_alloc(void);
+struct scope *scope_alloc(void);
+void process_scope(struct scope *);
diff --git a/sys/dev/microcode/aic7xxx/aicasm_gram.y b/sys/dev/microcode/aic7xxx/aicasm_gram.y
new file mode 100644 (file)
index 0000000..38b0dbc
--- /dev/null
@@ -0,0 +1,1410 @@
+%{
+/*
+ * Parser for the Aic7xxx SCSI Host adapter sequencer assembler.
+ *
+ * Copyright (c) 1997-1998 Justin T. Gibbs.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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.
+ *
+ * $FreeBSD: src/sys/dev/aic7xxx/aicasm_gram.y,v 1.8 1999/12/06 18:23:30 gibbs Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include "aicasm.h"
+#include "aicasm_symbol.h"
+#include "sequencer.h"
+
+int yylineno;
+char *yyfilename;
+static symbol_t *cur_symbol;
+static symtype cur_symtype;
+static symbol_t *accumulator;
+static symbol_ref_t allones;
+static symbol_ref_t allzeros;
+static symbol_ref_t none;
+static symbol_ref_t sindex;
+static int instruction_ptr;
+static int sram_or_scb_offset;
+static int download_constant_count;
+
+static void process_bitmask __P((int mask_type, symbol_t *sym, int mask));
+static void initialize_symbol __P((symbol_t *symbol));
+static void process_register __P((symbol_t **p_symbol));
+static void format_1_instr __P((int opcode, symbol_ref_t *dest,
+                               expression_t *immed, symbol_ref_t *src,
+                               int ret));
+static void format_2_instr __P((int opcode, symbol_ref_t *dest,
+                               expression_t *places, symbol_ref_t *src,
+                               int ret));
+static void format_3_instr __P((int opcode, symbol_ref_t *src,
+                               expression_t *immed, symbol_ref_t *address));
+static void test_readable_symbol __P((symbol_t *symbol));
+static void test_writable_symbol __P((symbol_t *symbol));
+static void type_check __P((symbol_t *symbol, expression_t *expression,
+                           int and_op));
+static void make_expression __P((expression_t *immed, int value));
+static void add_conditional __P((symbol_t *symbol));
+static int  is_download_const __P((expression_t *immed));
+
+#define YYDEBUG 1
+#define SRAM_SYMNAME "SRAM_BASE"
+#define SCB_SYMNAME "SCB_BASE"
+%}
+
+%union {
+       int             value;
+       char            *str;
+       symbol_t        *sym;
+       symbol_ref_t    sym_ref;
+       expression_t    expression;
+}
+
+%token T_REGISTER
+
+%token <value> T_CONST
+
+%token T_DOWNLOAD
+
+%token T_SCB
+
+%token T_SRAM
+
+%token T_ALIAS
+
+%token T_SIZE
+
+%token <value> T_ADDRESS
+
+%token T_ACCESS_MODE
+
+%token <value> T_MODE
+
+%token T_BIT
+
+%token T_MASK
+
+%token <value> T_NUMBER
+
+%token <str> T_PATH
+
+%token <sym> T_CEXPR
+
+%token T_EOF T_INCLUDE 
+
+%token <value> T_SHR T_SHL T_ROR T_ROL
+
+%token <value> T_MVI T_MOV T_CLR T_BMOV
+
+%token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL
+
+%token <value> T_ADD T_ADC
+
+%token <value> T_INC T_DEC
+
+%token <value> T_STC T_CLC
+
+%token <value> T_CMP T_XOR
+
+%token <value> T_TEST T_AND
+
+%token <value> T_OR
+
+%token T_RET
+
+%token T_NOP
+
+%token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX
+
+%token T_A
+
+%token <sym> T_SYMBOL
+
+%token T_NL
+
+%token T_IF T_ELSE T_ELSE_IF T_ENDIF
+
+%type <sym_ref> reg_symbol address destination source opt_source
+
+%type <expression> expression immediate immediate_or_a
+
+%type <value> ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
+
+%type <value> numerical_value
+
+%left '|'
+%left '&'
+%left '+' '-'
+%right '~'
+%nonassoc UMINUS
+%%
+
+program:
+       include
+|      program include
+|      register
+|      program register
+|      constant
+|      program constant
+|      scratch_ram
+|      program scratch_ram
+|      scb
+|      program scb
+|      label
+|      program label
+|      conditional
+|      program conditional
+|      code
+|      program code
+;
+
+include:
+       T_INCLUDE '<' T_PATH '>'
+       { include_file($3, BRACKETED_INCLUDE); }
+|      T_INCLUDE '"' T_PATH '"'
+       { include_file($3, QUOTED_INCLUDE); }
+;
+
+register:
+       T_REGISTER { cur_symtype = REGISTER; } reg_definition
+;
+
+reg_definition:
+       T_SYMBOL '{'
+               {
+                       if ($1->type != UNINITIALIZED) {
+                               stop("Register multiply defined", EX_DATAERR);
+                               /* NOTREACHED */
+                       }
+                       cur_symbol = $1; 
+                       cur_symbol->type = cur_symtype;
+                       initialize_symbol(cur_symbol);
+               }
+               reg_attribute_list
+       '}'
+               {                    
+                       /*
+                        * Default to allowing everything in for registers
+                        * with no bit or mask definitions.
+                        */
+                       if (cur_symbol->info.rinfo->valid_bitmask == 0)
+                               cur_symbol->info.rinfo->valid_bitmask = 0xFF;
+
+                       if (cur_symbol->info.rinfo->size == 0)
+                               cur_symbol->info.rinfo->size = 1;
+
+                       /*
+                        * This might be useful for registers too.
+                        */
+                       if (cur_symbol->type != REGISTER) {
+                               if (cur_symbol->info.rinfo->address == 0)
+                                       cur_symbol->info.rinfo->address =
+                                           sram_or_scb_offset;
+                               sram_or_scb_offset +=
+                                   cur_symbol->info.rinfo->size;
+                       }
+                       cur_symbol = NULL;
+               }
+;
+
+reg_attribute_list:
+       reg_attribute
+|      reg_attribute_list reg_attribute
+;
+
+reg_attribute:         
+       reg_address
+|      size
+|      access_mode
+|      bit_defn
+|      mask_defn
+|      alias
+|      accumulator
+|      allones
+|      allzeros
+|      none
+|      sindex
+;
+
+reg_address:
+       T_ADDRESS T_NUMBER
+       {
+               cur_symbol->info.rinfo->address = $2;
+       }
+;
+
+size:
+       T_SIZE T_NUMBER
+       {
+               cur_symbol->info.rinfo->size = $2;
+       }
+;
+
+access_mode:
+       T_ACCESS_MODE T_MODE
+       {
+               cur_symbol->info.rinfo->mode = $2;
+       }
+;
+
+bit_defn:
+       T_BIT T_SYMBOL T_NUMBER
+       {
+               process_bitmask(BIT, $2, $3);
+       }
+;
+
+mask_defn:
+       T_MASK T_SYMBOL expression
+       {
+               process_bitmask(MASK, $2, $3.value);
+       }
+;
+
+alias:
+       T_ALIAS T_SYMBOL
+       {
+               if ($2->type != UNINITIALIZED) {
+                       stop("Re-definition of register alias",
+                            EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               $2->type = ALIAS;
+               initialize_symbol($2);
+               $2->info.ainfo->parent = cur_symbol;
+       }
+;
+
+accumulator:
+       T_ACCUM
+       {
+               if (accumulator != NULL) {
+                       stop("Only one accumulator definition allowed",
+                            EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               accumulator = cur_symbol;
+       }
+;
+
+allones:
+       T_ALLONES
+       {
+               if (allones.symbol != NULL) {
+                       stop("Only one definition of allones allowed",
+                            EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               allones.symbol = cur_symbol;
+       }
+;
+
+allzeros:
+       T_ALLZEROS
+       {
+               if (allzeros.symbol != NULL) {
+                       stop("Only one definition of allzeros allowed",
+                            EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               allzeros.symbol = cur_symbol;
+       }
+;
+
+none:
+       T_NONE
+       {
+               if (none.symbol != NULL) {
+                       stop("Only one definition of none allowed",
+                            EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               none.symbol = cur_symbol;
+       }
+;
+
+sindex:
+       T_SINDEX
+       {
+               if (sindex.symbol != NULL) {
+                       stop("Only one definition of sindex allowed",
+                            EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               sindex.symbol = cur_symbol;
+       }
+;
+
+expression:
+       expression '|' expression
+       {
+                $$.value = $1.value | $3.value;
+                symlist_merge(&$$.referenced_syms,
+                              &$1.referenced_syms,
+                              &$3.referenced_syms);
+       }
+|      expression '&' expression
+       {
+               $$.value = $1.value & $3.value;
+               symlist_merge(&$$.referenced_syms,
+                              &$1.referenced_syms,
+                              &$3.referenced_syms);
+       }
+|      expression '+' expression
+       {
+               $$.value = $1.value + $3.value;
+               symlist_merge(&$$.referenced_syms,
+                              &$1.referenced_syms,
+                              &$3.referenced_syms);
+       }
+|      expression '-' expression
+       {
+               $$.value = $1.value - $3.value;
+               symlist_merge(&($$.referenced_syms),
+                              &($1.referenced_syms),
+                              &($3.referenced_syms));
+       }
+|      '(' expression ')'
+       {
+               $$ = $2;
+       }
+|      '~' expression
+       {
+               $$ = $2;
+               $$.value = (~$$.value) & 0xFF;
+       }
+|      '-' expression %prec UMINUS
+       {
+               $$ = $2;
+               $$.value = -$$.value;
+       }
+|      T_NUMBER
+       {
+               $$.value = $1;
+               SLIST_INIT(&$$.referenced_syms);
+       }
+|      T_SYMBOL
+       {
+               symbol_t *symbol;
+
+               symbol = $1;
+               switch (symbol->type) {
+               case ALIAS:
+                       symbol = $1->info.ainfo->parent;
+               case REGISTER:
+               case SCBLOC:
+               case SRAMLOC:
+                       $$.value = symbol->info.rinfo->address;
+                       break;
+               case MASK:
+               case BIT:
+                       $$.value = symbol->info.minfo->mask;
+                       break;
+               case DOWNLOAD_CONST:
+               case CONST:
+                       $$.value = symbol->info.cinfo->value;
+                       break;
+               case UNINITIALIZED:
+               default:
+               {
+                       char buf[255];
+
+                       snprintf(buf, sizeof(buf),
+                                "Undefined symbol %s referenced",
+                                symbol->name);
+                       stop(buf, EX_DATAERR);
+                       /* NOTREACHED */
+                       break;
+               }
+               }
+               SLIST_INIT(&$$.referenced_syms);
+               symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD);
+       }
+;
+
+constant:
+       T_CONST T_SYMBOL numerical_value
+       {
+               if ($2->type != UNINITIALIZED) {
+                       stop("Re-definition of symbol as a constant",
+                            EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               $2->type = CONST;
+               initialize_symbol($2);
+               $2->info.cinfo->value = $3;
+               $2->info.cinfo->define = $1;
+       }
+|      T_CONST T_SYMBOL T_DOWNLOAD
+       {
+               if ($1) {
+                       stop("Invalid downloaded constant declaration",
+                            EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               if ($2->type != UNINITIALIZED) {
+                       stop("Re-definition of symbol as a downloaded constant",
+                            EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               $2->type = DOWNLOAD_CONST;
+               initialize_symbol($2);
+               $2->info.cinfo->value = download_constant_count++;
+               $2->info.cinfo->define = FALSE;
+       }
+;
+
+numerical_value:
+       T_NUMBER
+       {
+               $$ = $1;
+       }
+|      '-' T_NUMBER
+       {
+               $$ = -$2;
+       }
+;
+
+scratch_ram:
+       T_SRAM '{'
+               {
+                       cur_symbol = symtable_get(SRAM_SYMNAME);
+                       cur_symtype = SRAMLOC;
+                       if (cur_symbol->type != UNINITIALIZED) {
+                               stop("Only one SRAM definition allowed",
+                                    EX_DATAERR);
+                               /* NOTREACHED */
+                       }
+                       cur_symbol->type = SRAMLOC;
+                       initialize_symbol(cur_symbol);
+               }
+               reg_address
+               {
+                       sram_or_scb_offset = cur_symbol->info.rinfo->address;
+               }
+               scb_or_sram_reg_list
+       '}'
+               {
+                       cur_symbol = NULL;
+               }
+;
+
+scb:
+       T_SCB '{'
+               {
+                       cur_symbol = symtable_get(SCB_SYMNAME);
+                       cur_symtype = SCBLOC;
+                       if (cur_symbol->type != UNINITIALIZED) {
+                               stop("Only one SRAM definition allowed",
+                                    EX_SOFTWARE);
+                               /* NOTREACHED */
+                       }
+                       cur_symbol->type = SCBLOC;
+                       initialize_symbol(cur_symbol);
+               }
+               reg_address
+               {
+                       sram_or_scb_offset = cur_symbol->info.rinfo->address;
+               }
+               scb_or_sram_reg_list
+       '}'
+               {
+                       cur_symbol = NULL;
+               }
+;
+
+scb_or_sram_reg_list:
+       reg_definition
+|      scb_or_sram_reg_list reg_definition
+;
+
+reg_symbol:
+       T_SYMBOL
+       {
+               process_register(&$1);
+               $$.symbol = $1;
+               $$.offset = 0;
+       }
+|      T_SYMBOL '[' T_NUMBER ']'
+       {
+               process_register(&$1);
+               if (($3 + 1) > $1->info.rinfo->size) {
+                       stop("Accessing offset beyond range of register",
+                            EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               $$.symbol = $1;
+               $$.offset = $3;
+       }
+|      T_A
+       {
+               if (accumulator == NULL) {
+                       stop("No accumulator has been defined", EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               $$.symbol = accumulator;
+               $$.offset = 0;
+       }
+;
+
+destination:
+       reg_symbol
+       {
+               test_writable_symbol($1.symbol);
+               $$ = $1;
+       }
+;
+
+immediate:
+       expression
+       { $$ = $1; }
+;
+
+immediate_or_a:
+       expression
+       {
+               $$ = $1;
+       }
+|      T_A
+       {
+               SLIST_INIT(&$$.referenced_syms);
+               $$.value = 0;
+       }
+;
+
+source:
+       reg_symbol
+       {
+               test_readable_symbol($1.symbol);
+               $$ = $1;
+       }
+;
+
+opt_source:
+       {
+               $$.symbol = NULL;
+               $$.offset = 0;
+       }
+|      ',' source
+       { $$ = $2; }
+;
+
+ret:
+       { $$ = 0; }
+|      T_RET
+       { $$ = 1; }
+;
+
+label:
+       T_SYMBOL ':'
+       {
+               if ($1->type != UNINITIALIZED) {
+                       stop("Program label multiply defined", EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               $1->type = LABEL;
+               initialize_symbol($1);
+               $1->info.linfo->address = instruction_ptr;
+       }
+;
+
+address:
+       T_SYMBOL
+       {
+               $$.symbol = $1;
+               $$.offset = 0;
+       }
+|      T_SYMBOL '+' T_NUMBER
+       {
+               $$.symbol = $1;
+               $$.offset = $3;
+       }
+|      T_SYMBOL '-' T_NUMBER
+       {
+               $$.symbol = $1;
+               $$.offset = -$3;
+       }
+|      '.'
+       {
+               $$.symbol = NULL;
+               $$.offset = 0;
+       }
+|      '.' '+' T_NUMBER
+       {
+               $$.symbol = NULL;
+               $$.offset = $3;
+       }
+|      '.' '-' T_NUMBER
+       {
+               $$.symbol = NULL;
+               $$.offset = -$3;
+       }
+;
+
+conditional:
+       T_IF T_CEXPR '{'
+       {
+               scope_t *new_scope;
+
+               add_conditional($2);
+               new_scope = scope_alloc();
+               new_scope->type = SCOPE_IF;
+               new_scope->begin_addr = instruction_ptr;
+               new_scope->func_num = $2->info.condinfo->func_num;
+       }
+|      T_ELSE T_IF T_CEXPR '{'
+       {
+               scope_t *new_scope;
+               scope_t *scope_context;
+               scope_t *last_scope;
+
+               /*
+                * Ensure that the previous scope is either an
+                * if or and else if.
+                */
+               scope_context = SLIST_FIRST(&scope_stack);
+               last_scope = TAILQ_LAST(&scope_context->inner_scope,
+                                       scope_tailq);
+               if (last_scope == NULL
+                || last_scope->type == T_ELSE) {
+
+                       stop("'else if' without leading 'if'", EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               add_conditional($3);
+               new_scope = scope_alloc();
+               new_scope->type = SCOPE_ELSE_IF;
+               new_scope->begin_addr = instruction_ptr;
+               new_scope->func_num = $3->info.condinfo->func_num;
+       }
+|      T_ELSE '{'
+       {
+               scope_t *new_scope;
+               scope_t *scope_context;
+               scope_t *last_scope;
+
+               /*
+                * Ensure that the previous scope is either an
+                * if or and else if.
+                */
+               scope_context = SLIST_FIRST(&scope_stack);
+               last_scope = TAILQ_LAST(&scope_context->inner_scope,
+                                       scope_tailq);
+               if (last_scope == NULL
+                || last_scope->type == SCOPE_ELSE) {
+
+                       stop("'else' without leading 'if'", EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               new_scope = scope_alloc();
+               new_scope->type = SCOPE_ELSE;
+               new_scope->begin_addr = instruction_ptr;
+       }
+;
+
+conditional:
+       '}'
+       {
+               scope_t *scope_context;
+               scope_t *last_scope;
+
+               scope_context = SLIST_FIRST(&scope_stack);
+               if (scope_context->type == SCOPE_ROOT) {
+                       stop("Unexpected '}' encountered", EX_DATAERR);
+                       /* NOTREACHED */
+               }
+
+               scope_context->end_addr = instruction_ptr;
+
+               /* Pop the scope */
+               SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links);
+
+               process_scope(scope_context);
+
+               if (SLIST_FIRST(&scope_stack) == NULL) {
+                       stop("Unexpected '}' encountered", EX_DATAERR);
+                       /* NOTREACHED */
+               }
+       }
+;
+
+f1_opcode:
+       T_AND { $$ = AIC_OP_AND; }
+|      T_XOR { $$ = AIC_OP_XOR; }
+|      T_ADD { $$ = AIC_OP_ADD; }
+|      T_ADC { $$ = AIC_OP_ADC; }
+;
+
+code:
+       f1_opcode destination ',' immediate_or_a opt_source ret ';'
+       {
+               format_1_instr($1, &$2, &$4, &$5, $6);
+       }
+;
+
+code:
+       T_OR reg_symbol ',' immediate_or_a opt_source ret ';'
+       {
+               format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6);
+       }
+;
+
+code:
+       T_INC destination opt_source ret ';'
+       {
+               expression_t immed;
+
+               make_expression(&immed, 1);
+               format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4);
+       }
+;
+
+code:
+       T_DEC destination opt_source ret ';'
+       {
+               expression_t immed;
+
+               make_expression(&immed, -1);
+               format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4);
+       }
+;
+
+code:
+       T_CLC ret ';'
+       {
+               expression_t immed;
+
+               make_expression(&immed, -1);
+               format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2);
+       }
+|      T_CLC T_MVI destination ',' immediate_or_a ret ';'
+       {
+               format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6);
+       }
+;
+
+code:
+       T_STC ret ';'
+       {
+               expression_t immed;
+
+               make_expression(&immed, 1);
+               format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2);
+       }
+|      T_STC destination ret ';'
+       {
+               expression_t immed;
+
+               make_expression(&immed, 1);
+               format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3);
+       }
+;
+
+code:
+       T_BMOV destination ',' source ',' immediate ret ';'
+       {
+               format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7);
+       }
+;
+
+code:
+       T_MOV destination ',' source ret ';'
+       {
+               expression_t immed;
+
+               make_expression(&immed, 0xff);
+               format_1_instr(AIC_OP_AND, &$2, &immed, &$4, $5);
+       }
+;
+
+code:
+       T_MVI destination ',' immediate_or_a ret ';'
+       {
+               format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5);
+       }
+;
+
+code:
+       T_CLR destination ret ';'
+       {
+               expression_t immed;
+
+               make_expression(&immed, 0xff);
+               format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3);
+       }
+;
+
+code:
+       T_NOP ret ';'
+       {
+               expression_t immed;
+
+               make_expression(&immed, 0xff);
+               format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2);
+       }
+;
+
+code:
+       T_RET ';'
+       {
+               expression_t immed;
+
+               make_expression(&immed, 0xff);
+               format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE);
+       }
+;
+
+       /*
+        * This grammer differs from the one in the aic7xxx
+        * reference manual since the grammer listed there is
+        * ambiguous and causes a shift/reduce conflict.
+        * It also seems more logical as the "immediate"
+        * argument is listed as the second arg like the
+        * other formats.
+        */
+
+f2_opcode:
+       T_SHL { $$ = AIC_OP_SHL; }
+|      T_SHR { $$ = AIC_OP_SHR; }
+|      T_ROL { $$ = AIC_OP_ROL; }
+|      T_ROR { $$ = AIC_OP_ROR; }
+;
+
+code:
+       f2_opcode destination ',' expression opt_source ret ';'
+       {
+               format_2_instr($1, &$2, &$4, &$5, $6);
+       }
+;
+
+jmp_jc_jnc_call:
+       T_JMP   { $$ = AIC_OP_JMP; }
+|      T_JC    { $$ = AIC_OP_JC; }
+|      T_JNC   { $$ = AIC_OP_JNC; }
+|      T_CALL  { $$ = AIC_OP_CALL; }
+;
+
+jz_jnz:
+       T_JZ    { $$ = AIC_OP_JZ; }
+|      T_JNZ   { $$ = AIC_OP_JNZ; }
+;
+
+je_jne:
+       T_JE    { $$ = AIC_OP_JE; }
+|      T_JNE   { $$ = AIC_OP_JNE; }
+;
+
+code:
+       jmp_jc_jnc_call address ';'
+       {
+               expression_t immed;
+
+               make_expression(&immed, 0);
+               format_3_instr($1, &sindex, &immed, &$2);
+       }
+;
+
+code:
+       T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';'
+       {
+               format_3_instr($5, &$2, &$4, &$6);
+       }
+;
+
+code:
+       T_TEST source ',' immediate_or_a jz_jnz address ';'
+       {
+               format_3_instr($5, &$2, &$4, &$6);
+       }
+;
+
+code:
+       T_CMP source ',' immediate_or_a je_jne address ';'
+       {
+               format_3_instr($5, &$2, &$4, &$6);
+       }
+;
+
+code:
+       T_MOV source jmp_jc_jnc_call address ';'
+       {
+               expression_t immed;
+
+               make_expression(&immed, 0);
+               format_3_instr($3, &$2, &immed, &$4);
+       }
+;
+
+code:
+       T_MVI immediate jmp_jc_jnc_call address ';'
+       {
+               format_3_instr($3, &allzeros, &$2, &$4);
+       }
+;
+
+%%
+
+static void
+process_bitmask(mask_type, sym, mask)
+       int             mask_type;
+       symbol_t        *sym;
+       int             mask;
+{
+       /*
+        * Add the current register to its
+        * symbol list, if it already exists,
+        * warn if we are setting it to a
+        * different value, or in the bit to
+        * the "allowed bits" of this register.
+        */
+       if (sym->type == UNINITIALIZED) {
+               sym->type = mask_type;
+               initialize_symbol(sym);
+               if (mask_type == BIT) {
+                       if (mask == 0) {
+                               stop("Bitmask with no bits set", EX_DATAERR);
+                               /* NOTREACHED */
+                       }
+                       if ((mask & ~(0x01 << (ffs(mask) - 1))) != 0) {
+                               stop("Bitmask with more than one bit set",
+                                    EX_DATAERR);
+                               /* NOTREACHED */
+                       }
+               }
+               sym->info.minfo->mask = mask;
+       } else if (sym->type != mask_type) {
+               stop("Bit definition mirrors a definition of the same "
+                    " name, but a different type", EX_DATAERR);
+               /* NOTREACHED */
+       } else if (mask != sym->info.minfo->mask) {
+               stop("Bitmask redefined with a conflicting value", EX_DATAERR);
+               /* NOTREACHED */
+       }
+       /* Fail if this symbol is already listed */
+       if (symlist_search(&(sym->info.minfo->symrefs),
+                          cur_symbol->name) != NULL) {
+               stop("Bitmask defined multiple times for register", EX_DATAERR);
+               /* NOTREACHED */
+       }
+       symlist_add(&(sym->info.minfo->symrefs), cur_symbol,
+                   SYMLIST_INSERT_HEAD);
+       cur_symbol->info.rinfo->valid_bitmask |= mask;
+       cur_symbol->info.rinfo->typecheck_masks = TRUE;
+}
+
+static void
+initialize_symbol(symbol)
+       symbol_t *symbol;
+{
+       switch (symbol->type) {
+        case UNINITIALIZED:
+               stop("Call to initialize_symbol with type field unset",
+                    EX_SOFTWARE);
+               /* NOTREACHED */
+               break;
+        case REGISTER:
+        case SRAMLOC:
+        case SCBLOC:
+               symbol->info.rinfo =
+                   (struct reg_info *)malloc(sizeof(struct reg_info));
+               if (symbol->info.rinfo == NULL) {
+                       stop("Can't create register info", EX_SOFTWARE);
+                       /* NOTREACHED */
+               }
+               memset(symbol->info.rinfo, 0,
+                      sizeof(struct reg_info));
+               break;
+        case ALIAS:
+               symbol->info.ainfo =
+                   (struct alias_info *)malloc(sizeof(struct alias_info));
+               if (symbol->info.ainfo == NULL) {
+                       stop("Can't create alias info", EX_SOFTWARE);
+                       /* NOTREACHED */
+               }
+               memset(symbol->info.ainfo, 0,
+                      sizeof(struct alias_info));
+               break;
+        case MASK:
+        case BIT:
+               symbol->info.minfo =
+                   (struct mask_info *)malloc(sizeof(struct mask_info));
+               if (symbol->info.minfo == NULL) {
+                       stop("Can't create bitmask info", EX_SOFTWARE);
+                       /* NOTREACHED */
+               }
+               memset(symbol->info.minfo, 0, sizeof(struct mask_info));
+               SLIST_INIT(&(symbol->info.minfo->symrefs));
+               break;
+        case CONST:
+        case DOWNLOAD_CONST:
+               symbol->info.cinfo =
+                   (struct const_info *)malloc(sizeof(struct const_info));
+               if (symbol->info.cinfo == NULL) {
+                       stop("Can't create alias info", EX_SOFTWARE);
+                       /* NOTREACHED */
+               }
+               memset(symbol->info.cinfo, 0,
+                      sizeof(struct const_info));
+               break;
+       case LABEL:
+               symbol->info.linfo =
+                   (struct label_info *)malloc(sizeof(struct label_info));
+               if (symbol->info.linfo == NULL) {
+                       stop("Can't create label info", EX_SOFTWARE);
+                       /* NOTREACHED */
+               }
+               memset(symbol->info.linfo, 0,
+                      sizeof(struct label_info));
+               break;
+       case CONDITIONAL:
+               symbol->info.condinfo =
+                   (struct cond_info *)malloc(sizeof(struct cond_info));
+               if (symbol->info.condinfo == NULL) {
+                       stop("Can't create conditional info", EX_SOFTWARE);
+                       /* NOTREACHED */
+               }
+               memset(symbol->info.condinfo, 0,
+                      sizeof(struct cond_info));
+               break;
+       default:
+               stop("Call to initialize_symbol with invalid symbol type",
+                    EX_SOFTWARE);
+               /* NOTREACHED */
+               break;
+       }
+}
+
+static void
+process_register(p_symbol)
+       symbol_t **p_symbol;
+{
+       char buf[255];
+       symbol_t *symbol = *p_symbol;
+
+       if (symbol->type == UNINITIALIZED) {
+               snprintf(buf, sizeof(buf), "Undefined register %s",
+                        symbol->name);
+               stop(buf, EX_DATAERR);
+               /* NOTREACHED */
+       } else if (symbol->type == ALIAS) {
+               *p_symbol = symbol->info.ainfo->parent;
+       } else if ((symbol->type != REGISTER)
+               && (symbol->type != SCBLOC)
+               && (symbol->type != SRAMLOC)) {
+               snprintf(buf, sizeof(buf),
+                        "Specified symbol %s is not a register",
+                        symbol->name);
+               stop(buf, EX_DATAERR);
+       }
+}
+
+static void
+format_1_instr(opcode, dest, immed, src, ret)
+       int          opcode;
+       symbol_ref_t *dest;
+       expression_t *immed;
+       symbol_ref_t *src;
+       int          ret;
+{
+       struct instruction *instr;
+       struct ins_format1 *f1_instr;
+
+       if (src->symbol == NULL)
+               src = dest;
+
+       /* Test register permissions */
+       test_writable_symbol(dest->symbol);
+       test_readable_symbol(src->symbol);
+
+       /* Ensure that immediate makes sense for this destination */
+       type_check(dest->symbol, immed, opcode);
+
+       /* Allocate sequencer space for the instruction and fill it out */
+       instr = seq_alloc();
+       f1_instr = &instr->format.format1;
+       f1_instr->ret = ret ? 1 : 0;
+       f1_instr->opcode = opcode;
+       f1_instr->destination = dest->symbol->info.rinfo->address
+                             + dest->offset;
+       f1_instr->source = src->symbol->info.rinfo->address
+                        + src->offset;
+       f1_instr->immediate = immed->value;
+
+       if (is_download_const(immed))
+               f1_instr->parity = 1;
+
+       symlist_free(&immed->referenced_syms);
+       instruction_ptr++;
+}
+
+static void
+format_2_instr(opcode, dest, places, src, ret)
+       int          opcode;
+       symbol_ref_t *dest;
+       expression_t *places;
+       symbol_ref_t *src;
+       int          ret;
+{
+       struct instruction *instr;
+       struct ins_format2 *f2_instr;
+       u_int8_t shift_control;
+
+       if (src->symbol == NULL)
+               src = dest;
+
+       /* Test register permissions */
+       test_writable_symbol(dest->symbol);
+       test_readable_symbol(src->symbol);
+
+       /* Allocate sequencer space for the instruction and fill it out */
+       instr = seq_alloc();
+       f2_instr = &instr->format.format2;
+       f2_instr->ret = ret ? 1 : 0;
+       f2_instr->opcode = AIC_OP_ROL;
+       f2_instr->destination = dest->symbol->info.rinfo->address
+                             + dest->offset;
+       f2_instr->source = src->symbol->info.rinfo->address
+                        + src->offset;
+       if (places->value > 8 || places->value <= 0) {
+               stop("illegal shift value", EX_DATAERR);
+               /* NOTREACHED */
+       }
+       switch (opcode) {
+       case AIC_OP_SHL:
+               if (places->value == 8)
+                       shift_control = 0xf0;
+               else
+                       shift_control = (places->value << 4) | places->value;
+               break;
+       case AIC_OP_SHR:
+               if (places->value == 8) {
+                       shift_control = 0xf8;
+               } else {
+                       shift_control = (places->value << 4)
+                                     | (8 - places->value)
+                                     | 0x08;
+               }
+               break;
+       case AIC_OP_ROL:
+               shift_control = places->value & 0x7;
+               break;
+       case AIC_OP_ROR:
+               shift_control = (8 - places->value) | 0x08;
+               break;
+       default:
+               shift_control = 0; /* Quiet Compiler */
+               stop("Invalid shift operation specified", EX_SOFTWARE);
+               /* NOTREACHED */
+               break;
+       };
+       f2_instr->shift_control = shift_control;
+       symlist_free(&places->referenced_syms);
+       instruction_ptr++;
+}
+
+static void
+format_3_instr(opcode, src, immed, address)
+       int          opcode;
+       symbol_ref_t *src;
+       expression_t *immed;
+       symbol_ref_t *address;
+{
+       struct instruction *instr;
+       struct ins_format3 *f3_instr;
+       int addr;
+
+       /* Test register permissions */
+       test_readable_symbol(src->symbol);
+
+       /* Ensure that immediate makes sense for this source */
+       type_check(src->symbol, immed, opcode);
+
+       /* Allocate sequencer space for the instruction and fill it out */
+       instr = seq_alloc();
+       f3_instr = &instr->format.format3;
+       if (address->symbol == NULL) {
+               /* 'dot' referrence.  Use the current instruction pointer */
+               addr = instruction_ptr + address->offset;
+       } else if (address->symbol->type == UNINITIALIZED) {
+               /* forward reference */
+               addr = address->offset;
+               instr->patch_label = address->symbol;
+       } else
+               addr = address->symbol->info.linfo->address + address->offset;
+       f3_instr->opcode = opcode;
+       f3_instr->address = addr;
+       f3_instr->source = src->symbol->info.rinfo->address
+                        + src->offset;
+       f3_instr->immediate = immed->value;
+
+       if (is_download_const(immed))
+               f3_instr->parity = 1;
+
+       symlist_free(&immed->referenced_syms);
+       instruction_ptr++;
+}
+
+static void
+test_readable_symbol(symbol)
+       symbol_t *symbol;
+{
+       if (symbol->info.rinfo->mode == WO) {
+               stop("Write Only register specified as source",
+                    EX_DATAERR);
+               /* NOTREACHED */
+       }
+}
+
+static void
+test_writable_symbol(symbol)
+       symbol_t *symbol;
+{
+       if (symbol->info.rinfo->mode == RO) {
+               stop("Read Only register specified as destination",
+                    EX_DATAERR);
+               /* NOTREACHED */
+       }
+}
+
+static void
+type_check(symbol, expression, opcode)
+       symbol_t     *symbol;
+       expression_t *expression;
+       int          opcode;
+{
+       symbol_node_t *node;
+       int and_op;
+       char buf[255];
+
+       and_op = FALSE;
+       if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ)
+               and_op = TRUE;
+
+       /*
+        * Make sure that we aren't attempting to write something
+        * that hasn't been defined.  If this is an and operation,
+        * this is a mask, so "undefined" bits are okay.
+        */
+       if (and_op == FALSE
+        && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) {
+               snprintf(buf, sizeof(buf),
+                        "Invalid bit(s) 0x%x in immediate written to %s",
+                        expression->value & ~symbol->info.rinfo->valid_bitmask,
+                        symbol->name);
+               stop(buf, EX_DATAERR);
+               /* NOTREACHED */
+       }
+
+       /*
+        * Now make sure that all of the symbols referenced by the
+        * expression are defined for this register.
+        */
+       if(symbol->info.rinfo->typecheck_masks != FALSE) {
+               for(node = expression->referenced_syms.slh_first;
+                   node != NULL;
+                   node = node->links.sle_next) {
+                       if ((node->symbol->type == MASK
+                         || node->symbol->type == BIT)
+                        && symlist_search(&node->symbol->info.minfo->symrefs,
+                                          symbol->name) == NULL) {
+                               snprintf(buf, sizeof(buf),
+                                        "Invalid bit or mask %s "
+                                        "for register %s",
+                                        node->symbol->name, symbol->name);
+                               stop(buf, EX_DATAERR);
+                               /* NOTREACHED */
+                       }
+               }
+       }
+}
+
+static void
+make_expression(immed, value)
+       expression_t *immed;
+       int          value;
+{
+       SLIST_INIT(&immed->referenced_syms);
+       immed->value = value & 0xff;
+}
+
+static void
+add_conditional(symbol)
+       symbol_t *symbol;
+{
+       static int numfuncs;
+
+       if (numfuncs == 0) {
+               /* add a special conditional, "0" */
+               symbol_t *false_func;
+
+               false_func = symtable_get("0");
+               if (false_func->type != UNINITIALIZED) {
+                       stop("Conditional expression '0' "
+                            "conflicts with a symbol", EX_DATAERR);
+                       /* NOTREACHED */
+               }
+               false_func->type = CONDITIONAL;
+               initialize_symbol(false_func);
+               false_func->info.condinfo->func_num = numfuncs++;
+               symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD);
+       }
+
+       /* This condition has occurred before */
+       if (symbol->type == CONDITIONAL)
+               return;
+
+       if (symbol->type != UNINITIALIZED) {
+               stop("Conditional expression conflicts with a symbol",
+                    EX_DATAERR);
+               /* NOTREACHED */
+       }
+
+       symbol->type = CONDITIONAL;
+       initialize_symbol(symbol);
+       symbol->info.condinfo->func_num = numfuncs++;
+       symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD);
+}
+
+void
+yyerror(string)
+       const char *string;
+{
+       stop(string, EX_DATAERR);
+}
+
+static int
+is_download_const(immed)
+       expression_t *immed;
+{
+       if ((immed->referenced_syms.slh_first != NULL)
+        && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST))
+               return (TRUE);
+
+       return (FALSE);
+}
diff --git a/sys/dev/microcode/aic7xxx/aicasm_scan.l b/sys/dev/microcode/aic7xxx/aicasm_scan.l
new file mode 100644 (file)
index 0000000..20cae61
--- /dev/null
@@ -0,0 +1,283 @@
+%{
+/*
+ * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler.
+ *
+ * Copyright (c) 1997-1998 Justin T. Gibbs.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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.
+ *
+ * $FreeBSD: src/sys/dev/aic7xxx/aicasm_scan.l,v 1.8 1999/12/06 18:23:30 gibbs Exp $
+ */
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <sysexits.h>
+#include <sys/queue.h>
+
+#include "aicasm.h"
+#include "aicasm_symbol.h"
+#include "y.tab.h"
+
+#define MAX_STR_CONST 256
+char string_buf[MAX_STR_CONST];
+char *string_buf_ptr;
+int  parren_count;
+%}
+
+PATH           [-/A-Za-z0-9_.]*[./][-/A-Za-z0-9_.]*
+WORD           [A-Za-z_][-A-Za-z_0-9]*
+SPACE          [ \t]+
+
+%x COMMENT
+%x CEXPR
+%x INCLUDE
+
+%%
+\n                     { ++yylineno; }
+"/*"                   { BEGIN COMMENT;  /* Enter comment eating state */ }
+<COMMENT>"/*"          { fprintf(stderr, "Warning! Comment within comment."); }
+<COMMENT>\n            { ++yylineno; }
+<COMMENT>[^*/\n]*      ;
+<COMMENT>"*"+[^*/\n]*  ;
+<COMMENT>"/"+[^*/\n]*  ;
+<COMMENT>"*"+"/"       { BEGIN INITIAL; }
+if[ \t]*\(             {
+                               string_buf_ptr = string_buf;
+                               parren_count = 1;
+                               BEGIN CEXPR;
+                               return T_IF;
+                       }
+<CEXPR>\(              {       *string_buf_ptr++ = '('; parren_count++; }
+<CEXPR>\)              {
+                               parren_count--;
+                               if (parren_count == 0) {
+                                       /* All done */
+                                       BEGIN INITIAL;
+                                       *string_buf_ptr = '\0';
+                                       yylval.sym = symtable_get(string_buf);
+                                       return T_CEXPR;
+                               } else {
+                                       *string_buf_ptr++ = ')';
+                               }
+                       }
+<CEXPR>\n              { ++yylineno; }
+<CEXPR>[^()\n]+                {
+                               char *yptr = yytext;
+
+                               while (*yptr != '\0')
+                                       *string_buf_ptr++ = *yptr++;
+                       }
+
+{SPACE}                        ;
+
+       /* Register/SCB/SRAM definition keywords */
+register               { return T_REGISTER; }
+const                  { yylval.value = FALSE; return T_CONST; }
+download               { return T_DOWNLOAD; }
+address                        { return T_ADDRESS; }
+access_mode            { return T_ACCESS_MODE; }
+RW|RO|WO               {
+                                if (strcmp(yytext, "RW") == 0)
+                                       yylval.value = RW;
+                                else if (strcmp(yytext, "RO") == 0)
+                                       yylval.value = RO;
+                                else
+                                       yylval.value = WO;
+                                return T_MODE;
+                       }
+bit                    { return T_BIT; }
+mask                   { return T_MASK; }
+alias                  { return T_ALIAS; }
+size                   { return T_SIZE; }
+scb                    { return T_SCB; }
+scratch_ram            { return T_SRAM; }
+accumulator            { return T_ACCUM; }
+allones                        { return T_ALLONES; }
+allzeros               { return T_ALLZEROS; }
+none                   { return T_NONE; }
+sindex                 { return T_SINDEX; }
+A                      { return T_A; }
+
+       /* Opcodes */
+shl                    { return T_SHL; }
+shr                    { return T_SHR; }
+ror                    { return T_ROR; }
+rol                    { return T_ROL; }
+mvi                    { return T_MVI; }
+mov                    { return T_MOV; }
+clr                    { return T_CLR; }
+jmp                    { return T_JMP; }
+jc                     { return T_JC;  }
+jnc                    { return T_JNC; }
+je                     { return T_JE;  }
+jne                    { return T_JNE; }
+jz                     { return T_JZ;  }
+jnz                    { return T_JNZ; }
+call                   { return T_CALL; }
+add                    { return T_ADD; }
+adc                    { return T_ADC; }
+bmov                   { return T_BMOV; }
+inc                    { return T_INC; }
+dec                    { return T_DEC; }
+stc                    { return T_STC; }
+clc                    { return T_CLC; }
+cmp                    { return T_CMP; }
+xor                    { return T_XOR; }
+test                   { return T_TEST;}
+and                    { return T_AND; }
+or                     { return T_OR;  }
+ret                    { return T_RET; }
+nop                    { return T_NOP; }
+else                   { return T_ELSE; }
+
+       /* Allowed Symbols */
+[-+,:()~|&."{};<>[\]!] { return yytext[0]; }
+
+       /* Number processing */
+0[0-7]*                        {
+                               yylval.value = strtol(yytext, NULL, 8);
+                               return T_NUMBER;
+                       }
+
+0[xX][0-9a-fA-F]+      {
+                               yylval.value = strtoul(yytext + 2, NULL, 16);
+                               return T_NUMBER;
+                       }
+
+[1-9][0-9]*            {
+                               yylval.value = strtol(yytext, NULL, 10);
+                               return T_NUMBER;
+                       }
+
+       /* Include Files */
+#include               { return T_INCLUDE; BEGIN INCLUDE;}
+<INCLUDE>[<>\"]                { return yytext[0]; }
+<INCLUDE>{PATH}                { yylval.str = strdup(yytext); return T_PATH; }
+<INCLUDE>;             { BEGIN INITIAL; return yytext[0]; }
+<INCLUDE>.             { stop("Invalid include line", EX_DATAERR); }
+
+       /* For parsing C include files with #define foo */
+#define                        { yylval.value = TRUE; return T_CONST; }
+       /* Throw away macros */
+#define[^\n]*[()]+[^\n]* ;
+{PATH}                 { yylval.str = strdup(yytext); return T_PATH; }
+
+{WORD}                 { yylval.sym = symtable_get(yytext);  return T_SYMBOL; }
+
+.                      { 
+                               char buf[255];
+
+                               snprintf(buf, sizeof(buf), "Invalid character "
+                                        "'%c'", yytext[0]);
+                               stop(buf, EX_DATAERR);
+                       }
+%%
+
+typedef struct include {
+        YY_BUFFER_STATE  buffer;
+        int              lineno;
+        char            *filename;
+       SLIST_ENTRY(include) links;
+}include_t;
+
+SLIST_HEAD(, include) include_stack;
+
+void
+include_file(file_name, type)
+       char    *file_name;
+       include_type type;
+{
+       FILE *newfile;
+       include_t *include;
+
+       newfile = NULL;
+       /* Try the current directory first */
+       if (includes_search_curdir != 0 || type == SOURCE_FILE)
+               newfile = fopen(file_name, "r");
+
+       if (newfile == NULL && type != SOURCE_FILE) {
+                path_entry_t include_dir;
+                for (include_dir = search_path.slh_first;
+                     include_dir != NULL;                
+                     include_dir = include_dir->links.sle_next) {
+                       char fullname[PATH_MAX];
+
+                       if ((include_dir->quoted_includes_only == TRUE)
+                        && (type != QUOTED_INCLUDE))
+                               continue;
+
+                       snprintf(fullname, sizeof(fullname),
+                                "%s/%s", include_dir->directory, file_name);
+
+                       if ((newfile = fopen(fullname, "r")) != NULL)
+                               break;
+                }
+        }
+
+       if (newfile == NULL) {
+               perror(file_name);
+               stop("Unable to open input file", EX_SOFTWARE);
+               /* NOTREACHED */
+       }
+
+       if (type != SOURCE_FILE) {
+               include = (include_t *)malloc(sizeof(include_t));
+               if (include == NULL) {
+                       stop("Unable to allocate include stack entry",
+                            EX_SOFTWARE);
+                       /* NOTREACHED */
+               }
+               include->buffer = YY_CURRENT_BUFFER;
+               include->lineno = yylineno;
+               include->filename = yyfilename;
+               SLIST_INSERT_HEAD(&include_stack, include, links);
+       }
+       yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
+       yylineno = 1;
+       yyfilename = strdup(file_name);
+}
+
+int
+yywrap()
+{
+       include_t *include;
+
+       yy_delete_buffer(YY_CURRENT_BUFFER);
+       (void)fclose(yyin);
+       if (yyfilename != NULL)
+               free(yyfilename);
+       yyfilename = NULL;
+       include = include_stack.slh_first;
+       if (include != NULL) {
+               yy_switch_to_buffer(include->buffer);
+               yylineno = include->lineno;
+               yyfilename = include->filename;
+               SLIST_REMOVE_HEAD(&include_stack, links);
+               free(include);
+               return (0);
+       }
+       return (1);
+}
diff --git a/sys/dev/microcode/aic7xxx/aicasm_symbol.c b/sys/dev/microcode/aic7xxx/aicasm_symbol.c
new file mode 100644 (file)
index 0000000..4f799bc
--- /dev/null
@@ -0,0 +1,473 @@
+/* $OpenBSD: aicasm_symbol.c,v 1.1 2000/03/22 02:50:49 smurph Exp $ */
+/*
+ * Aic7xxx SCSI host adapter firmware asssembler symbol table implementation
+ *
+ * Copyright (c) 1997 Justin T. Gibbs.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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.
+ *
+ * $FreeBSD: src/sys/dev/aic7xxx/aicasm_symbol.c,v 1.8 1999/12/06 18:23:30 gibbs Exp $
+ */
+
+
+#include <sys/types.h>
+
+#include <db.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+
+#include "aicasm_symbol.h"
+#include "aicasm.h"
+
+static DB *symtable;
+
+symbol_t *
+symbol_create(name)
+       char *name;
+{
+       symbol_t *new_symbol;
+
+       new_symbol = (symbol_t *)malloc(sizeof(symbol_t));
+       if (new_symbol == NULL) {
+               perror("Unable to create new symbol");
+               exit(EX_SOFTWARE);
+       }
+       memset(new_symbol, 0, sizeof(*new_symbol));
+       new_symbol->name = strdup(name);
+       new_symbol->type = UNINITIALIZED;
+       return (new_symbol);
+}
+
+void
+symbol_delete(symbol)
+       symbol_t *symbol;
+{
+       if (symtable != NULL) {
+               DBT      key;
+
+               key.data = symbol->name;
+               key.size = strlen(symbol->name);
+               symtable->del(symtable, &key, /*flags*/0);
+       }
+       switch(symbol->type) {
+       case SCBLOC:
+       case SRAMLOC:
+       case REGISTER:
+               if (symbol->info.rinfo != NULL)
+                       free(symbol->info.rinfo);
+               break;
+       case ALIAS:
+               if (symbol->info.ainfo != NULL)
+                       free(symbol->info.ainfo);
+               break;
+       case MASK:
+       case BIT:
+               if (symbol->info.minfo != NULL) {
+                       symlist_free(&symbol->info.minfo->symrefs);
+                       free(symbol->info.minfo);
+               }
+               break;
+       case DOWNLOAD_CONST:
+       case CONST:
+               if (symbol->info.cinfo != NULL)
+                       free(symbol->info.cinfo);
+               break;
+       case LABEL:
+               if (symbol->info.linfo != NULL)
+                       free(symbol->info.linfo);
+               break;
+       case UNINITIALIZED:
+       default:
+               break;
+       }
+       free(symbol->name);
+       free(symbol);
+}
+
+void
+symtable_open()
+{
+       symtable = dbopen(/*filename*/NULL,
+                         O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH,
+                         /*openinfo*/NULL);
+
+       if (symtable == NULL) {
+               perror("Symbol table creation failed");
+               exit(EX_SOFTWARE);
+               /* NOTREACHED */
+       }
+}
+
+void
+symtable_close()
+{
+       if (symtable != NULL) {
+               DBT      key;
+               DBT      data;
+
+               while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {
+                       symbol_t *stored_ptr;
+
+                       memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
+                       symbol_delete(stored_ptr);
+               }
+               symtable->close(symtable);
+       }
+}
+
+/*
+ * The semantics of get is to return an uninitialized symbol entry
+ * if a lookup fails.
+ */
+symbol_t *
+symtable_get(name)
+       char *name;
+{
+       symbol_t *stored_ptr;
+       DBT       key;
+       DBT       data;
+       int       retval;
+
+       key.data = (void *)name;
+       key.size = strlen(name);
+
+       if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) {
+               if (retval == -1) {
+                       perror("Symbol table get operation failed");
+                       exit(EX_SOFTWARE);
+                       /* NOTREACHED */
+               } else if (retval == 1) {
+                       /* Symbol wasn't found, so create a new one */
+                       symbol_t *new_symbol;
+
+                       new_symbol = symbol_create(name);
+                       data.data = &new_symbol;
+                       data.size = sizeof(new_symbol);
+                       if (symtable->put(symtable, &key, &data,
+                                         /*flags*/0) !=0) {
+                               perror("Symtable put failed");
+                               exit(EX_SOFTWARE);
+                       }
+                       return (new_symbol);
+               } else {
+                       perror("Unexpected return value from db get routine");
+                       exit(EX_SOFTWARE);
+                       /* NOTREACHED */
+               }
+       }
+       memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
+       return (stored_ptr);
+}
+
+symbol_node_t *
+symlist_search(symlist, symname)
+       symlist_t *symlist;
+       char      *symname;
+{
+       symbol_node_t *curnode;
+
+       curnode = symlist->slh_first;
+       while(curnode != NULL) {
+               if (strcmp(symname, curnode->symbol->name) == 0)
+                       break;
+               curnode = curnode->links.sle_next;
+       }
+       return (curnode);
+}
+
+void
+symlist_add(symlist, symbol, how)
+       symlist_t *symlist;
+       symbol_t  *symbol;
+       int       how;
+{
+       symbol_node_t *newnode;
+
+       newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t));
+       if (newnode == NULL) {
+               stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE);
+               /* NOTREACHED */
+       }
+       newnode->symbol = symbol;
+       if (how == SYMLIST_SORT) {
+               symbol_node_t *curnode;
+               int mask;
+
+               mask = FALSE;
+               switch(symbol->type) {
+               case REGISTER:
+               case SCBLOC:
+               case SRAMLOC:
+                       break;
+               case BIT:
+               case MASK:
+                       mask = TRUE;
+                       break;
+               default:
+                       stop("symlist_add: Invalid symbol type for sorting",
+                            EX_SOFTWARE);
+                       /* NOTREACHED */
+               }
+
+               curnode = symlist->slh_first;
+               if (curnode == NULL
+                || (mask && (curnode->symbol->info.minfo->mask >
+                             newnode->symbol->info.minfo->mask))
+                || (!mask && (curnode->symbol->info.rinfo->address >
+                              newnode->symbol->info.rinfo->address))) {
+                       SLIST_INSERT_HEAD(symlist, newnode, links);
+                       return;
+               }
+
+               while (1) {
+                       if (curnode->links.sle_next == NULL) {
+                               SLIST_INSERT_AFTER(curnode, newnode,
+                                                  links);
+                               break;
+                       } else {
+                               symbol_t *cursymbol;
+
+                               cursymbol = curnode->links.sle_next->symbol;
+                               if ((mask && (cursymbol->info.minfo->mask >
+                                             symbol->info.minfo->mask))
+                                || (!mask &&(cursymbol->info.rinfo->address >
+                                             symbol->info.rinfo->address))){
+                                       SLIST_INSERT_AFTER(curnode, newnode,
+                                                          links);
+                                       break;
+                               }
+                       }
+                       curnode = curnode->links.sle_next;
+               }
+       } else {
+               SLIST_INSERT_HEAD(symlist, newnode, links);
+       }
+}
+
+void
+symlist_free(symlist)
+       symlist_t *symlist;
+{
+       symbol_node_t *node1, *node2;
+
+       node1 = symlist->slh_first;
+       while (node1 != NULL) {
+               node2 = node1->links.sle_next;
+               free(node1);
+               node1 = node2;
+       }
+       SLIST_INIT(symlist);
+}
+
+void
+symlist_merge(symlist_dest, symlist_src1, symlist_src2)
+       symlist_t *symlist_dest;
+       symlist_t *symlist_src1;
+       symlist_t *symlist_src2;
+{
+       symbol_node_t *node;
+
+       *symlist_dest = *symlist_src1;
+       while((node = symlist_src2->slh_first) != NULL) {
+               SLIST_REMOVE_HEAD(symlist_src2, links);
+               SLIST_INSERT_HEAD(symlist_dest, node, links);
+       }
+
+       /* These are now empty */
+       SLIST_INIT(symlist_src1);
+       SLIST_INIT(symlist_src2);
+}
+
+void
+symtable_dump(ofile)
+       FILE *ofile;
+{
+       /*
+        * Sort the registers by address with a simple insertion sort.
+        * Put bitmasks next to the first register that defines them.
+        * Put constants at the end.
+        */
+       symlist_t registers;
+       symlist_t masks;
+       symlist_t constants;
+       symlist_t download_constants;
+       symlist_t aliases;
+
+       SLIST_INIT(&registers);
+       SLIST_INIT(&masks);
+       SLIST_INIT(&constants);
+       SLIST_INIT(&download_constants);
+       SLIST_INIT(&aliases);
+
+       if (symtable != NULL) {
+               DBT      key;
+               DBT      data;
+               int      flag = R_FIRST;
+
+               while (symtable->seq(symtable, &key, &data, flag) == 0) {
+                       symbol_t *cursym;
+
+                       memcpy(&cursym, data.data, sizeof(cursym));
+                       switch(cursym->type) {
+                       case REGISTER:
+                       case SCBLOC:
+                       case SRAMLOC:
+                               symlist_add(&registers, cursym, SYMLIST_SORT);
+                               break;
+                       case MASK:
+                       case BIT:
+                               symlist_add(&masks, cursym, SYMLIST_SORT);
+                               break;
+                       case CONST:
+                               if (cursym->info.cinfo->define == FALSE) {
+                                       symlist_add(&constants, cursym,
+                                                   SYMLIST_INSERT_HEAD);
+                               }
+                               break;
+                       case DOWNLOAD_CONST:
+                               symlist_add(&download_constants, cursym,
+                                           SYMLIST_INSERT_HEAD);
+                               break;
+                       case ALIAS:
+                               symlist_add(&aliases, cursym,
+                                           SYMLIST_INSERT_HEAD);
+                               break;
+                       default:
+                               break;
+                       }
+                       flag = R_NEXT;
+               }
+
+               /* Put in the masks and bits */
+               while (masks.slh_first != NULL) {
+                       symbol_node_t *curnode;
+                       symbol_node_t *regnode;
+                       char *regname;
+
+                       curnode = masks.slh_first;
+                       SLIST_REMOVE_HEAD(&masks, links);
+
+                       regnode =
+                           curnode->symbol->info.minfo->symrefs.slh_first;
+                       regname = regnode->symbol->name;
+                       regnode = symlist_search(&registers, regname);
+                       SLIST_INSERT_AFTER(regnode, curnode, links);
+               }
+
+               /* Add the aliases */
+               while (aliases.slh_first != NULL) {
+                       symbol_node_t *curnode;
+                       symbol_node_t *regnode;
+                       char *regname;
+
+                       curnode = aliases.slh_first;
+                       SLIST_REMOVE_HEAD(&aliases, links);
+
+                       regname = curnode->symbol->info.ainfo->parent->name;
+                       regnode = symlist_search(&registers, regname);
+                       SLIST_INSERT_AFTER(regnode, curnode, links);
+               }
+
+               /* Output what we have */
+               fprintf(ofile,
+"/*
+ * DO NOT EDIT - This file is automatically generated.
+ */\n");
+               while (registers.slh_first != NULL) {
+                       symbol_node_t *curnode;
+                       u_int8_t value;
+                       char *tab_str;
+                       char *tab_str2;
+
+                       curnode = registers.slh_first;
+                       SLIST_REMOVE_HEAD(&registers, links);
+                       switch(curnode->symbol->type) {
+                       case REGISTER:
+                       case SCBLOC:
+                       case SRAMLOC:
+                               fprintf(ofile, "\n");
+                               value = curnode->symbol->info.rinfo->address;
+                               tab_str = "\t";
+                               tab_str2 = "\t\t";
+                               break;
+                       case ALIAS:
+                       {
+                               symbol_t *parent;
+
+                               parent = curnode->symbol->info.ainfo->parent;
+                               value = parent->info.rinfo->address;
+                               tab_str = "\t";
+                               tab_str2 = "\t\t";
+                               break;
+                       }
+                       case MASK:
+                       case BIT:
+                               value = curnode->symbol->info.minfo->mask;
+                               tab_str = "\t\t";
+                               tab_str2 = "\t";
+                               break;
+                       default:
+                               value = 0; /* Quiet compiler */
+                               tab_str = NULL;
+                               tab_str2 = NULL;
+                               stop("symtable_dump: Invalid symbol type "
+                                    "encountered", EX_SOFTWARE);
+                               break;
+                       }
+                       fprintf(ofile, "#define%s%-16s%s0x%02x\n",
+                               tab_str, curnode->symbol->name, tab_str2,
+                               value);
+                       free(curnode);
+               }
+               fprintf(ofile, "\n\n");
+
+               while (constants.slh_first != NULL) {
+                       symbol_node_t *curnode;
+
+                       curnode = constants.slh_first;
+                       SLIST_REMOVE_HEAD(&constants, links);
+                       fprintf(ofile, "#define\t%-8s\t0x%02x\n",
+                               curnode->symbol->name,
+                               curnode->symbol->info.cinfo->value);
+                       free(curnode);
+               }
+
+               
+               fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
+
+               while (download_constants.slh_first != NULL) {
+                       symbol_node_t *curnode;
+
+                       curnode = download_constants.slh_first;
+                       SLIST_REMOVE_HEAD(&download_constants, links);
+                       fprintf(ofile, "#define\t%-8s\t0x%02x\n",
+                               curnode->symbol->name,
+                               curnode->symbol->info.cinfo->value);
+                       free(curnode);
+               }
+       }
+}
+
diff --git a/sys/dev/microcode/aic7xxx/aicasm_symbol.h b/sys/dev/microcode/aic7xxx/aicasm_symbol.h
new file mode 100644 (file)
index 0000000..201b1c0
--- /dev/null
@@ -0,0 +1,162 @@
+/* $OpenBSD: aicasm_symbol.h,v 1.1 2000/03/22 02:50:50 smurph Exp $ */
+/*
+ * Aic7xxx SCSI host adapter firmware asssembler symbol table definitions
+ *
+ * Copyright (c) 1997 Justin T. Gibbs.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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.
+ *
+ * $FreeBSD: src/sys/dev/aic7xxx/aicasm_symbol.h,v 1.6 1999/12/06 18:23:31 gibbs Exp $
+ */
+
+#include <sys/queue.h>
+
+typedef enum {
+       UNINITIALIZED,
+       REGISTER,
+       ALIAS,
+       SCBLOC,
+       SRAMLOC,
+       MASK,
+       BIT,
+       CONST,
+       DOWNLOAD_CONST,
+       LABEL,
+       CONDITIONAL
+}symtype;
+
+typedef enum {
+       RO = 0x01,
+       WO = 0x02,
+       RW = 0x03
+}amode_t;
+
+struct reg_info {
+       u_int8_t address;
+       int      size;
+       amode_t  mode;
+       u_int8_t valid_bitmask;
+       int      typecheck_masks;
+};
+
+typedef SLIST_HEAD(symlist, symbol_node) symlist_t;
+
+struct mask_info {
+       symlist_t symrefs;
+       u_int8_t mask;
+};
+
+struct const_info {
+       u_int8_t value;
+       int      define;
+};
+
+struct alias_info {
+       struct symbol *parent;
+};
+
+struct label_info {
+       int     address;
+};
+
+struct cond_info {
+       int     func_num;
+};
+
+typedef struct expression_info {
+        symlist_t       referenced_syms;
+        int             value;
+} expression_t;
+
+typedef struct symbol {
+       char    *name;
+       symtype type;
+       union   {
+               struct reg_info *rinfo;
+               struct mask_info *minfo;
+               struct const_info *cinfo;
+               struct alias_info *ainfo;
+               struct label_info *linfo;
+               struct cond_info *condinfo;
+       }info;
+} symbol_t;
+
+typedef struct symbol_ref {
+       symbol_t *symbol;
+       int      offset;
+} symbol_ref_t;
+
+typedef struct symbol_node {
+       SLIST_ENTRY(symbol_node) links;
+       symbol_t *symbol;
+}symbol_node_t;
+
+typedef enum {
+       SCOPE_ROOT,
+       SCOPE_IF,
+       SCOPE_ELSE_IF,
+       SCOPE_ELSE
+} scope_type;
+
+typedef struct patch_info {
+       int skip_patch;
+       int skip_instr;
+} patch_info_t;
+
+typedef struct scope {
+       SLIST_ENTRY(scope) scope_stack_links;
+       TAILQ_ENTRY(scope) scope_links;
+       TAILQ_HEAD(, scope) inner_scope;
+       scope_type type;
+       int inner_scope_patches;
+       int begin_addr;
+        int end_addr;
+       patch_info_t patches[2];
+       int func_num;
+} scope_t;
+
+SLIST_HEAD(scope_list, scope);
+TAILQ_HEAD(scope_tailq, scope);
+
+void   symbol_delete __P((symbol_t *symbol));
+
+void   symtable_open __P((void));
+
+void   symtable_close __P((void));
+
+symbol_t *
+       symtable_get __P((char *name));
+
+symbol_node_t *
+       symlist_search __P((symlist_t *symlist, char *symname));
+
+void
+       symlist_add __P((symlist_t *symlist, symbol_t *symbol, int how));
+#define SYMLIST_INSERT_HEAD    0x00
+#define SYMLIST_SORT           0x01
+
+void   symlist_free __P((symlist_t *symlist));
+
+void   symlist_merge __P((symlist_t *symlist_dest, symlist_t *symlist_src1,
+                          symlist_t *symlist_src2));
+void   symtable_dump __P((FILE *ofile));
diff --git a/sys/dev/microcode/aic7xxx/sequencer.h b/sys/dev/microcode/aic7xxx/sequencer.h
new file mode 100644 (file)
index 0000000..4c57a8d
--- /dev/null
@@ -0,0 +1,96 @@
+/* $OpenBSD: sequencer.h,v 1.1 2000/03/22 02:50:50 smurph Exp $ */
+/*
+ * Instruction formats for the sequencer program downloaded to
+ * Aic7xxx SCSI host adapters
+ *
+ * Copyright (c) 1997, 1998 Justin T. Gibbs.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * the GNU Public License ("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.
+ *
+ * $FreeBSD: src/sys/dev/aic7xxx/sequencer.h,v 1.6 1999/12/06 18:23:31 gibbs Exp $
+ */
+
+struct ins_format1 {
+       u_int32_t       immediate       : 8,
+                       source          : 9,
+                       destination     : 9,
+                       ret             : 1,
+                       opcode          : 4,
+                       parity          : 1;
+};
+
+struct ins_format2 {
+       u_int32_t       shift_control   : 8,
+                       source          : 9,
+                       destination     : 9,
+                       ret             : 1,
+                       opcode          : 4,
+                       parity          : 1;
+};
+
+struct ins_format3 {
+       u_int32_t       immediate       : 8,
+                       source          : 9,
+                       address         : 10,
+                       opcode          : 4,
+                       parity          : 1;
+};
+
+union ins_formats {
+               struct ins_format1 format1;
+               struct ins_format2 format2;
+               struct ins_format3 format3;
+               u_int8_t           bytes[4];
+               u_int32_t          integer;
+};
+struct instruction {
+       union   ins_formats format;
+       u_int   srcline;
+       struct symbol *patch_label;
+       TAILQ_ENTRY(instruction) links;
+};
+
+#define        AIC_OP_OR       0x0
+#define        AIC_OP_AND      0x1
+#define AIC_OP_XOR     0x2
+#define        AIC_OP_ADD      0x3
+#define        AIC_OP_ADC      0x4
+#define        AIC_OP_ROL      0x5
+#define        AIC_OP_BMOV     0x6
+
+#define        AIC_OP_JMP      0x8
+#define AIC_OP_JC      0x9
+#define AIC_OP_JNC     0xa
+#define AIC_OP_CALL    0xb
+#define        AIC_OP_JNE      0xc
+#define        AIC_OP_JNZ      0xd
+#define        AIC_OP_JE       0xe
+#define        AIC_OP_JZ       0xf
+
+/* Pseudo Ops */
+#define        AIC_OP_SHL      0x10
+#define        AIC_OP_SHR      0x20
+#define        AIC_OP_ROR      0x30
index d4affe4..e69de29 100644 (file)
@@ -1,17 +0,0 @@
-#      $OpenBSD: Makefile.inc,v 1.3 1997/11/07 08:07:17 niklas Exp $
-#      $NetBSD: Makefile.inc,v 1.4 1996/05/20 00:48:43 thorpej Exp $
-
-.if target(ncr53cxxx.o)
-PATH: $S/dev/microcode/ncr53cxxx
-
-ncr53cxxx.o: ncr53cxxx_seq.h
-
-ncr53cxxx_seq.h: ncr53cxxx_asm $S/dev/microcode/ncr53cxxx/ncr53cxxx.seq
-       ./ncr53cxxx_asm -o ${.TARGET} $S/dev/microcode/ncr53cxxx/ncr53cxxx.seq
-
-ncr53cxxx_asm: $S/dev/microcode/ncr53cxxx/ncr53cxxx_asm.c
-       ${HOSTCC} -U_KERNEL -o ${.TARGET} $<
-
-clean::
-       rm -f ncr53cxxx_asm
-.endif