Home | History | Annotate | Line # | Download | only in aic7xxx
aic7xxx.seq revision 1.1
      1  1.1  mycroft ##+M#########################################################################
      2  1.1  mycroft # Adaptec 274x/284x/294x device driver for Linux and FreeBSD.
      3  1.1  mycroft #
      4  1.1  mycroft # Copyright (c) 1994 John Aycock
      5  1.1  mycroft #   The University of Calgary Department of Computer Science.
      6  1.1  mycroft #   All rights reserved.
      7  1.1  mycroft #
      8  1.1  mycroft # Modifications/enhancements:
      9  1.1  mycroft #   Copyright (c) 1994, 1995 Justin Gibbs. All rights reserved.
     10  1.1  mycroft #
     11  1.1  mycroft # Redistribution and use in source and binary forms, with or without
     12  1.1  mycroft # modification, are permitted provided that the following conditions
     13  1.1  mycroft # are met:
     14  1.1  mycroft # 1. Redistributions of source code must retain the above copyright
     15  1.1  mycroft #    notice, this list of conditions, and the following disclaimer.
     16  1.1  mycroft # 2. Redistributions in binary form must reproduce the above copyright
     17  1.1  mycroft #    notice, this list of conditions and the following disclaimer in the
     18  1.1  mycroft #    documentation and/or other materials provided with the distribution.
     19  1.1  mycroft # 3. All advertising materials mentioning features or use of this software
     20  1.1  mycroft #    must display the following acknowledgement:
     21  1.1  mycroft #      This product includes software developed by the University of Calgary
     22  1.1  mycroft #      Department of Computer Science and its contributors.
     23  1.1  mycroft # 4. Neither the name of the University nor the names of its contributors
     24  1.1  mycroft #    may be used to endorse or promote products derived from this software
     25  1.1  mycroft #    without specific prior written permission.
     26  1.1  mycroft #
     27  1.1  mycroft # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     28  1.1  mycroft # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     29  1.1  mycroft # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     30  1.1  mycroft # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     31  1.1  mycroft # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     32  1.1  mycroft # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     33  1.1  mycroft # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     34  1.1  mycroft # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     35  1.1  mycroft # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     36  1.1  mycroft # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     37  1.1  mycroft # SUCH DAMAGE.
     38  1.1  mycroft # 
     39  1.1  mycroft # FreeBSD, Twin, Wide, 2 command per target support, tagged queuing and other 
     40  1.1  mycroft # optimizations provided by Justin T. Gibbs (gibbs (at] FreeBSD.org)
     41  1.1  mycroft #
     42  1.1  mycroft ##-M#########################################################################
     43  1.1  mycroft 
     44  1.1  mycroft VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.1 1995/10/09 09:49:37 mycroft Exp $"
     45  1.1  mycroft 
     46  1.1  mycroft SCBMASK		= 0x1f
     47  1.1  mycroft 
     48  1.1  mycroft SCSISEQ		= 0x00
     49  1.1  mycroft ENRSELI		= 0x10
     50  1.1  mycroft SXFRCTL0	= 0x01
     51  1.1  mycroft SXFRCTL1	= 0x02
     52  1.1  mycroft SCSISIGI	= 0x03
     53  1.1  mycroft SCSISIGO	= 0x03
     54  1.1  mycroft SCSIRATE	= 0x04
     55  1.1  mycroft SCSIID		= 0x05
     56  1.1  mycroft SCSIDATL	= 0x06
     57  1.1  mycroft STCNT		= 0x08
     58  1.1  mycroft STCNT+0		= 0x08
     59  1.1  mycroft STCNT+1		= 0x09
     60  1.1  mycroft STCNT+2		= 0x0a
     61  1.1  mycroft CLRSINT0	= 0x0b
     62  1.1  mycroft SSTAT0		= 0x0b
     63  1.1  mycroft SELDO		= 0x40
     64  1.1  mycroft SELDI		= 0x20
     65  1.1  mycroft CLRSINT1	= 0x0c
     66  1.1  mycroft SSTAT1		= 0x0c
     67  1.1  mycroft SIMODE1		= 0x11
     68  1.1  mycroft SCSIBUSL	= 0x12
     69  1.1  mycroft SHADDR		= 0x14
     70  1.1  mycroft SELID		= 0x19
     71  1.1  mycroft SBLKCTL		= 0x1f
     72  1.1  mycroft SEQCTL		= 0x60
     73  1.1  mycroft A		= 0x64				# == ACCUM
     74  1.1  mycroft SINDEX		= 0x65
     75  1.1  mycroft DINDEX		= 0x66
     76  1.1  mycroft ALLZEROS	= 0x6a
     77  1.1  mycroft NONE		= 0x6a
     78  1.1  mycroft SINDIR		= 0x6c
     79  1.1  mycroft DINDIR		= 0x6d
     80  1.1  mycroft FUNCTION1	= 0x6e
     81  1.1  mycroft HADDR		= 0x88
     82  1.1  mycroft HADDR+1		= 0x89
     83  1.1  mycroft HADDR+2		= 0x8a
     84  1.1  mycroft HADDR+3		= 0x8b
     85  1.1  mycroft HCNT		= 0x8c
     86  1.1  mycroft HCNT+0		= 0x8c
     87  1.1  mycroft HCNT+1		= 0x8d
     88  1.1  mycroft HCNT+2		= 0x8e
     89  1.1  mycroft SCBPTR		= 0x90
     90  1.1  mycroft INTSTAT		= 0x91
     91  1.1  mycroft DFCNTRL		= 0x93
     92  1.1  mycroft DFSTATUS	= 0x94
     93  1.1  mycroft DFDAT		= 0x99
     94  1.1  mycroft QINFIFO		= 0x9b
     95  1.1  mycroft QINCNT		= 0x9c
     96  1.1  mycroft QOUTFIFO	= 0x9d
     97  1.1  mycroft 
     98  1.1  mycroft SCSICONF_A	= 0x5a
     99  1.1  mycroft SCSICONF_B	= 0x5b
    100  1.1  mycroft 
    101  1.1  mycroft #  The two reserved bytes at SCBARRAY+1[23] are expected to be set to
    102  1.1  mycroft #  zero, and the reserved bit in SCBARRAY+0 is used as an internal flag
    103  1.1  mycroft #  to indicate whether or not to reload scatter-gather parameters after
    104  1.1  mycroft #  a disconnect.  We also use bits 6 & 7 to indicate whether or not to
    105  1.1  mycroft #  initiate SDTR or WDTR repectively when starting this command.
    106  1.1  mycroft #
    107  1.1  mycroft SCBARRAY+0	= 0xa0
    108  1.1  mycroft 
    109  1.1  mycroft DISCONNECTED	= 0x04
    110  1.1  mycroft NEEDDMA		= 0x08
    111  1.1  mycroft SG_LOAD		= 0x10
    112  1.1  mycroft TAG_ENB		= 0x20
    113  1.1  mycroft NEEDSDTR	= 0x40
    114  1.1  mycroft NEEDWDTR	= 0x80
    115  1.1  mycroft 
    116  1.1  mycroft SCBARRAY+1	= 0xa1
    117  1.1  mycroft SCBARRAY+2	= 0xa2
    118  1.1  mycroft SCBARRAY+3	= 0xa3
    119  1.1  mycroft SCBARRAY+4	= 0xa4
    120  1.1  mycroft SCBARRAY+5	= 0xa5
    121  1.1  mycroft SCBARRAY+6	= 0xa6
    122  1.1  mycroft SCBARRAY+7	= 0xa7
    123  1.1  mycroft SCBARRAY+8	= 0xa8
    124  1.1  mycroft SCBARRAY+9	= 0xa9
    125  1.1  mycroft SCBARRAY+10	= 0xaa
    126  1.1  mycroft SCBARRAY+11	= 0xab
    127  1.1  mycroft SCBARRAY+12	= 0xac
    128  1.1  mycroft SCBARRAY+13	= 0xad
    129  1.1  mycroft SCBARRAY+14	= 0xae
    130  1.1  mycroft SCBARRAY+15	= 0xaf
    131  1.1  mycroft SCBARRAY+16	= 0xb0
    132  1.1  mycroft SCBARRAY+17	= 0xb1
    133  1.1  mycroft SCBARRAY+18	= 0xb2
    134  1.1  mycroft SCBARRAY+19	= 0xb3
    135  1.1  mycroft SCBARRAY+20	= 0xb4
    136  1.1  mycroft SCBARRAY+21	= 0xb5
    137  1.1  mycroft SCBARRAY+22	= 0xb6
    138  1.1  mycroft SCBARRAY+23	= 0xb7
    139  1.1  mycroft SCBARRAY+24	= 0xb8
    140  1.1  mycroft SCBARRAY+25	= 0xb9
    141  1.1  mycroft SCBARRAY+26	= 0xba
    142  1.1  mycroft SCBARRAY+27	= 0xbb
    143  1.1  mycroft SCBARRAY+28	= 0xbc
    144  1.1  mycroft SCBARRAY+29	= 0xbd
    145  1.1  mycroft SCBARRAY+30	= 0xbe
    146  1.1  mycroft 
    147  1.1  mycroft BAD_PHASE	= 0x01				# unknown scsi bus phase
    148  1.1  mycroft CMDCMPLT	= 0x02				# Command Complete
    149  1.1  mycroft SEND_REJECT	= 0x11				# sending a message reject
    150  1.1  mycroft NO_IDENT	= 0x21				# no IDENTIFY after reconnect
    151  1.1  mycroft NO_MATCH	= 0x31				# no cmd match for reconnect
    152  1.1  mycroft MSG_SDTR	= 0x41				# SDTR message recieved
    153  1.1  mycroft MSG_WDTR	= 0x51				# WDTR message recieved
    154  1.1  mycroft MSG_REJECT	= 0x61				# Reject message recieved
    155  1.1  mycroft BAD_STATUS	= 0x71				# Bad status from target
    156  1.1  mycroft RESIDUAL	= 0x81				# Residual byte count != 0
    157  1.1  mycroft ABORT_TAG	= 0x91				# Sent an ABORT_TAG message
    158  1.1  mycroft 
    159  1.1  mycroft #  The host adapter card (at least the BIOS) uses 20-2f for SCSI
    160  1.1  mycroft #  device information, 32-33 and 5a-5f as well. As it turns out, the
    161  1.1  mycroft #  BIOS trashes 20-2f, writing the synchronous negotiation results
    162  1.1  mycroft #  on top of the BIOS values, so we re-use those for our per-target
    163  1.1  mycroft #  scratchspace (actually a value that can be copied directly into
    164  1.1  mycroft #  SCSIRATE).  The kernel driver will enable synchronous negotiation
    165  1.1  mycroft #  for all targets that have a value other than 0 in the lower four
    166  1.1  mycroft #  bits of the target scratch space.  This should work irregardless of
    167  1.1  mycroft #  whether the bios has been installed. NEEDWDTR and NEEDSDTR are the top
    168  1.1  mycroft #  two bits of the SCB control byte.  The kernel driver will set these
    169  1.1  mycroft #  when a WDTR or SDTR message should be sent to the target the SCB's 
    170  1.1  mycroft #  command references.
    171  1.1  mycroft #
    172  1.1  mycroft #  REJBYTE contains the first byte of a MESSAGE IN message, so the driver 
    173  1.1  mycroft #  can report an intelligible error if a message is rejected.
    174  1.1  mycroft #
    175  1.1  mycroft #  FLAGS's high bit is true if we are currently handling a reselect;
    176  1.1  mycroft #  its next-highest bit is true ONLY IF we've seen an IDENTIFY message
    177  1.1  mycroft #  from the reselecting target.  If we haven't had IDENTIFY, then we have
    178  1.1  mycroft #  no idea what the lun is, and we can't select the right SCB register
    179  1.1  mycroft #  bank, so force a kernel panic if the target attempts a data in/out or
    180  1.1  mycroft #  command phase instead of corrupting something.  FLAGS also contains
    181  1.1  mycroft #  configuration bits so that we can optimize for TWIN and WIDE controllers
    182  1.1  mycroft #  as well as the MAX_SYNC bit which we set when we want to negotiate for
    183  1.1  mycroft #  10MHz irregardless of what the per target scratch space says.
    184  1.1  mycroft #
    185  1.1  mycroft #  Note that SG_NEXT occupies four bytes.
    186  1.1  mycroft #
    187  1.1  mycroft SYNCNEG		= 0x20
    188  1.1  mycroft 
    189  1.1  mycroft REJBYTE		= 0x31
    190  1.1  mycroft DISC_DSB_A	= 0x32
    191  1.1  mycroft DISC_DSB_B	= 0x33
    192  1.1  mycroft 
    193  1.1  mycroft MSG_LEN		= 0x34
    194  1.1  mycroft MSG_START+0	= 0x35
    195  1.1  mycroft MSG_START+1	= 0x36
    196  1.1  mycroft MSG_START+2	= 0x37
    197  1.1  mycroft MSG_START+3	= 0x38
    198  1.1  mycroft MSG_START+4	= 0x39
    199  1.1  mycroft MSG_START+5	= 0x3a
    200  1.1  mycroft -MSG_START+0	= 0xcb				# 2's complement of MSG_START+0
    201  1.1  mycroft 
    202  1.1  mycroft ARG_1		= 0x4a				# sdtr conversion args & return
    203  1.1  mycroft BUS_16_BIT	= 0x01
    204  1.1  mycroft RETURN_1	= 0x4a
    205  1.1  mycroft 
    206  1.1  mycroft SIGSTATE	= 0x4b				# value written to SCSISIGO
    207  1.1  mycroft 
    208  1.1  mycroft # Linux users should use 0xc (12) for SG_SIZEOF
    209  1.1  mycroft SG_SIZEOF	= 0x8 				# sizeof(struct ahc_dma)
    210  1.1  mycroft #SG_SIZEOF	= 0xc 				# sizeof(struct scatterlist)
    211  1.1  mycroft SCB_SIZEOF	= 0x13				# sizeof SCB to DMA (19 bytes)
    212  1.1  mycroft 
    213  1.1  mycroft SG_NOLOAD	= 0x4c				# load SG pointer/length?
    214  1.1  mycroft SG_COUNT	= 0x4d				# working value of SG count
    215  1.1  mycroft SG_NEXT		= 0x4e				# working value of SG pointer
    216  1.1  mycroft SG_NEXT+0	= 0x4e
    217  1.1  mycroft SG_NEXT+1	= 0x4f
    218  1.1  mycroft SG_NEXT+2	= 0x50
    219  1.1  mycroft SG_NEXT+3	= 0x51
    220  1.1  mycroft 
    221  1.1  mycroft SCBCOUNT	= 0x52				# the actual number of SCBs
    222  1.1  mycroft FLAGS		= 0x53				# Device configuration flags
    223  1.1  mycroft TWIN_BUS	= 0x01
    224  1.1  mycroft WIDE_BUS	= 0x02
    225  1.1  mycroft MAX_SYNC	= 0x08
    226  1.1  mycroft ACTIVE_MSG	= 0x20
    227  1.1  mycroft IDENTIFY_SEEN	= 0x40
    228  1.1  mycroft RESELECTED	= 0x80
    229  1.1  mycroft 
    230  1.1  mycroft ACTIVE_A	= 0x54
    231  1.1  mycroft ACTIVE_B	= 0x55
    232  1.1  mycroft SAVED_TCL	= 0x56				# Temporary storage for the 
    233  1.1  mycroft 						# target/channel/lun of a
    234  1.1  mycroft 						# reconnecting target
    235  1.1  mycroft 
    236  1.1  mycroft # After starting the selection hardware, we return to the "poll_for_work"
    237  1.1  mycroft # loop so that we can check for reconnecting targets as well as for our
    238  1.1  mycroft # selection to complete just in case the reselection wins bus arbitration.
    239  1.1  mycroft # The problem with this is that we must keep track of the SCB that we've
    240  1.1  mycroft # already pulled from the QINFIFO and started the selection on just in case
    241  1.1  mycroft # the reselection wins so that we can retry the selection at a later time.
    242  1.1  mycroft # This problem cannot be resolved by holding a single entry in scratch
    243  1.1  mycroft # ram since a reconnecting target can request sense and this will create
    244  1.1  mycroft # yet another SCB waiting for selection.  The solution used here is to 
    245  1.1  mycroft # use byte 31 of the SCB as a psuedo-next pointer and to thread a list
    246  1.1  mycroft # of SCBs that are awaiting selection.  Since 0 is a valid SCB offset, 
    247  1.1  mycroft # SCB_LIST_NULL is 0x10 which is out of range.  The kernel driver must
    248  1.1  mycroft # add an entry to this list everytime a request sense occurs.  The sequencer
    249  1.1  mycroft # will automatically consume the entries.
    250  1.1  mycroft 
    251  1.1  mycroft WAITING_SCBH	= 0x57				# head of list of SCBs awaiting
    252  1.1  mycroft 						# selection
    253  1.1  mycroft WAITING_SCBT	= 0x58				# tail of list of SCBs awaiting
    254  1.1  mycroft 						# selection
    255  1.1  mycroft SCB_LIST_NULL	= 0x10
    256  1.1  mycroft 
    257  1.1  mycroft 
    258  1.1  mycroft #  Poll QINCNT for work - the lower bits contain
    259  1.1  mycroft #  the number of entries in the Queue In FIFO.
    260  1.1  mycroft #
    261  1.1  mycroft start:
    262  1.1  mycroft 	test	WAITING_SCBH,SCB_LIST_NULL jz start_waiting
    263  1.1  mycroft poll_for_work:
    264  1.1  mycroft 	test	FLAGS,TWIN_BUS	jz start2	# Are we a twin channel device?
    265  1.1  mycroft # For fairness, we check the other bus first, since we just finished a 
    266  1.1  mycroft # transaction on the current channel.
    267  1.1  mycroft 	xor	SBLKCTL,0x08			# Toggle to the other bus
    268  1.1  mycroft 	test	SSTAT0,SELDI	jnz reselect
    269  1.1  mycroft 	test	SSTAT0,SELDO	jnz select
    270  1.1  mycroft 	xor	SBLKCTL,0x08			# Toggle to the original bus
    271  1.1  mycroft start2:
    272  1.1  mycroft 	test	SSTAT0,SELDI	jnz reselect
    273  1.1  mycroft 	test	SSTAT0,SELDO	jnz select
    274  1.1  mycroft 	test	WAITING_SCBH,SCB_LIST_NULL jz start_waiting
    275  1.1  mycroft 	test	QINCNT,SCBMASK	jz poll_for_work
    276  1.1  mycroft 
    277  1.1  mycroft # We have at least one queued SCB now and we don't have any 
    278  1.1  mycroft # SCBs in the list of SCBs awaiting selection.  Set the SCB
    279  1.1  mycroft # pointer from the FIFO so we see the right bank of SCB 
    280  1.1  mycroft # registers, then set SCSI options and set the initiator and
    281  1.1  mycroft # target SCSI IDs.
    282  1.1  mycroft #
    283  1.1  mycroft 	mov	SCBPTR,QINFIFO
    284  1.1  mycroft 
    285  1.1  mycroft # If the control byte of this SCB has the NEEDDMA flag set, we have
    286  1.1  mycroft # yet to DMA it from host memory
    287  1.1  mycroft 
    288  1.1  mycroft test    SCBARRAY+0,NEEDDMA      jz test_busy    
    289  1.1  mycroft 	clr	HCNT+2
    290  1.1  mycroft 	clr	HCNT+1
    291  1.1  mycroft 	mvi	HCNT+0,SCB_SIZEOF
    292  1.1  mycroft 
    293  1.1  mycroft 	mvi	DINDEX,HADDR      
    294  1.1  mycroft 	mvi	SCBARRAY+26     call bcopy_4
    295  1.1  mycroft         
    296  1.1  mycroft 	mvi	DFCNTRL,0xd                     # HDMAEN|DIRECTION|FIFORESET
    297  1.1  mycroft 
    298  1.1  mycroft #  Wait for DMA from host memory to data FIFO to complete, then disable
    299  1.1  mycroft #  DMA and wait for it to acknowledge that it's off.
    300  1.1  mycroft #
    301  1.1  mycroft 	call	dma_finish
    302  1.1  mycroft 
    303  1.1  mycroft # Copy the SCB from the FIFO to  the SCBARRAY
    304  1.1  mycroft 
    305  1.1  mycroft 	mvi	DINDEX, SCBARRAY+0
    306  1.1  mycroft 	call	bcopy_3_dfdat 
    307  1.1  mycroft 	call	bcopy_4_dfdat
    308  1.1  mycroft 	call	bcopy_4_dfdat
    309  1.1  mycroft 	call	bcopy_4_dfdat   
    310  1.1  mycroft 	call	bcopy_4_dfdat
    311  1.1  mycroft 
    312  1.1  mycroft # See if there is not already an active SCB for this target.  This code
    313  1.1  mycroft # locks out on a per target basis instead of target/lun.  Although this
    314  1.1  mycroft # is not ideal for devices that have multiple luns active at the same
    315  1.1  mycroft # time, it is faster than looping through all SCB's looking for active
    316  1.1  mycroft # commands.  It may be benificial to make findscb a more general procedure
    317  1.1  mycroft # to see if the added cost of the search is negligible.  This code also 
    318  1.1  mycroft # assumes that the kernel driver will clear the active flags on board 
    319  1.1  mycroft # initialization, board reset, and a target's SELTO.
    320  1.1  mycroft 
    321  1.1  mycroft test_busy:
    322  1.1  mycroft 	test	SCBARRAY+0,0x20	jnz start_scb
    323  1.1  mycroft 	and	FUNCTION1,0x70,SCBARRAY+1
    324  1.1  mycroft 	mov	A,FUNCTION1
    325  1.1  mycroft 	test	SCBARRAY+1,0x88	jz test_a	# Id < 8 && A channel
    326  1.1  mycroft 
    327  1.1  mycroft 	test	ACTIVE_B,A	jnz requeue
    328  1.1  mycroft 	or	ACTIVE_B,A	# Mark the current target as busy
    329  1.1  mycroft 	jmp	start_scb
    330  1.1  mycroft 
    331  1.1  mycroft # Place the currently active back on the queue for later processing
    332  1.1  mycroft requeue:
    333  1.1  mycroft 	mov	QINFIFO, SCBPTR
    334  1.1  mycroft 	jmp	poll_for_work
    335  1.1  mycroft 
    336  1.1  mycroft # Pull the first entry off of the waiting for selection list
    337  1.1  mycroft start_waiting:
    338  1.1  mycroft 	mov	SCBPTR,WAITING_SCBH
    339  1.1  mycroft 	jmp	start_scb
    340  1.1  mycroft 
    341  1.1  mycroft test_a:
    342  1.1  mycroft 	test	ACTIVE_A,A	jnz requeue
    343  1.1  mycroft 	or	ACTIVE_A,A	# Mark the current target as busy
    344  1.1  mycroft 
    345  1.1  mycroft start_scb:
    346  1.1  mycroft 	and	SINDEX,0xf7,SBLKCTL  #Clear the channel select bit
    347  1.1  mycroft 	and	A,0x08,SCBARRAY+1    #Get new channel bit
    348  1.1  mycroft 	or	SINDEX,A	     
    349  1.1  mycroft 	mov	SBLKCTL,SINDEX	# select channel
    350  1.1  mycroft 	mov	SCBARRAY+1	call initialize_scsiid
    351  1.1  mycroft 
    352  1.1  mycroft # Enable selection phase as an initiator, and do automatic ATN
    353  1.1  mycroft # after the selection.  We do this now so that we can overlap the
    354  1.1  mycroft # rest of our work to set up this target with the arbitration and
    355  1.1  mycroft # selection bus phases.
    356  1.1  mycroft #
    357  1.1  mycroft start_selection:
    358  1.1  mycroft 	or	SCSISEQ,0x48			# ENSELO|ENAUTOATNO
    359  1.1  mycroft 	mov	WAITING_SCBH, SCBPTR
    360  1.1  mycroft 	clr	SG_NOLOAD
    361  1.1  mycroft 	and	FLAGS,0x3f	# !RESELECTING
    362  1.1  mycroft 
    363  1.1  mycroft #  As soon as we get a successful selection, the target should go
    364  1.1  mycroft #  into the message out phase since we have ATN asserted.  Prepare
    365  1.1  mycroft #  the message to send, locking out the device driver.  If the device
    366  1.1  mycroft #  driver hasn't beaten us with an ABORT or RESET message, then tack
    367  1.1  mycroft #  on an SDTR negotiation if required.
    368  1.1  mycroft #
    369  1.1  mycroft #  Messages are stored in scratch RAM starting with a flag byte (high bit
    370  1.1  mycroft #  set means active message), one length byte, and then the message itself.
    371  1.1  mycroft #
    372  1.1  mycroft 	mov	SCBARRAY+1	call disconnect	# disconnect ok?
    373  1.1  mycroft 
    374  1.1  mycroft 	and	SINDEX,0x7,SCBARRAY+1		# lun
    375  1.1  mycroft 	or	SINDEX,A			# return value from disconnect
    376  1.1  mycroft 	or	SINDEX,0x80	call mk_mesg	# IDENTIFY message
    377  1.1  mycroft 
    378  1.1  mycroft 	mov	A,SINDEX
    379  1.1  mycroft 	test	SCBARRAY+0,0xe0	jz  !message	# WDTR, SDTR or TAG??
    380  1.1  mycroft 	cmp	MSG_START+0,A	jne !message	# did driver beat us?
    381  1.1  mycroft 
    382  1.1  mycroft # Tag Message if Tag enabled in SCB control block.  Use SCBPTR as the tag
    383  1.1  mycroft # value
    384  1.1  mycroft 
    385  1.1  mycroft mk_tag:
    386  1.1  mycroft 	mvi	DINDEX, MSG_START+1
    387  1.1  mycroft 	test	SCBARRAY+0,TAG_ENB jz mk_tag_done
    388  1.1  mycroft 	and	A,0x23,SCBARRAY+0
    389  1.1  mycroft 	mov	DINDIR,A
    390  1.1  mycroft 	mov	DINDIR,SCBPTR
    391  1.1  mycroft 
    392  1.1  mycroft 	add	MSG_LEN,-MSG_START+0,DINDEX	# update message length
    393  1.1  mycroft 
    394  1.1  mycroft mk_tag_done:
    395  1.1  mycroft 
    396  1.1  mycroft 	mov	DINDEX	call mk_dtr	# build DTR message if needed
    397  1.1  mycroft 
    398  1.1  mycroft !message:
    399  1.1  mycroft 	jmp	poll_for_work
    400  1.1  mycroft 
    401  1.1  mycroft #  Reselection has been initiated by a target. Make a note that we've been
    402  1.1  mycroft #  reselected, but haven't seen an IDENTIFY message from the target
    403  1.1  mycroft #  yet.
    404  1.1  mycroft #
    405  1.1  mycroft reselect:
    406  1.1  mycroft 	mov	SELID		call initialize_scsiid
    407  1.1  mycroft 	and	FLAGS,0x3f			# reselected, no IDENTIFY	
    408  1.1  mycroft 	or	FLAGS,RESELECTED jmp select2
    409  1.1  mycroft 
    410  1.1  mycroft # After the selection, remove this SCB from the "waiting for selection"
    411  1.1  mycroft # list.  This is achieved by simply moving our "next" pointer into
    412  1.1  mycroft # WAITING_SCBH and setting our next pointer to null so that the next
    413  1.1  mycroft # time this SCB is used, we don't get confused.
    414  1.1  mycroft #
    415  1.1  mycroft select:
    416  1.1  mycroft 	or	SCBARRAY+0,NEEDDMA
    417  1.1  mycroft 	mov	WAITING_SCBH,SCBARRAY+30
    418  1.1  mycroft 	mvi	SCBARRAY+30,SCB_LIST_NULL
    419  1.1  mycroft select2:
    420  1.1  mycroft 	call	initialize_for_target
    421  1.1  mycroft 	mvi	SCSISEQ,ENRSELI
    422  1.1  mycroft 	mvi	CLRSINT0,0x60			# CLRSELDI|CLRSELDO
    423  1.1  mycroft 	mvi	CLRSINT1,0x8			# CLRBUSFREE
    424  1.1  mycroft 
    425  1.1  mycroft #  Main loop for information transfer phases.  If BSY is false, then
    426  1.1  mycroft #  we have a bus free condition, expected or not.  Otherwise, wait
    427  1.1  mycroft #  for the target to assert REQ before checking MSG, C/D and I/O
    428  1.1  mycroft #  for the bus phase.
    429  1.1  mycroft #
    430  1.1  mycroft #  We can't simply look at the values of SCSISIGI here (if we want
    431  1.1  mycroft #  to do synchronous data transfer), because the target won't assert
    432  1.1  mycroft #  REQ if it's already sent us some data that we haven't acknowledged
    433  1.1  mycroft #  yet.
    434  1.1  mycroft #
    435  1.1  mycroft ITloop:
    436  1.1  mycroft 	test	SSTAT1,0x8	jnz p_busfree	# BUSFREE
    437  1.1  mycroft 	test	SSTAT1,0x1	jz ITloop	# REQINIT
    438  1.1  mycroft 
    439  1.1  mycroft 	and	A,0xe0,SCSISIGI			# CDI|IOI|MSGI
    440  1.1  mycroft 
    441  1.1  mycroft 	cmp	ALLZEROS,A	je p_dataout
    442  1.1  mycroft 	cmp	A,0x40		je p_datain
    443  1.1  mycroft 	cmp	A,0x80		je p_command
    444  1.1  mycroft 	cmp	A,0xc0		je p_status
    445  1.1  mycroft 	cmp	A,0xa0		je p_mesgout
    446  1.1  mycroft 	cmp	A,0xe0		je p_mesgin
    447  1.1  mycroft 
    448  1.1  mycroft 	mvi	INTSTAT,BAD_PHASE		# unknown - signal driver
    449  1.1  mycroft 
    450  1.1  mycroft p_dataout:
    451  1.1  mycroft 	mvi	0		call scsisig	# !CDO|!IOO|!MSGO
    452  1.1  mycroft 	call	assert
    453  1.1  mycroft 	call	sg_load
    454  1.1  mycroft 
    455  1.1  mycroft 	mvi	DINDEX,HADDR
    456  1.1  mycroft 	mvi	SCBARRAY+19	call bcopy_4
    457  1.1  mycroft 
    458  1.1  mycroft #	mvi	DINDEX,HCNT	# implicit since HCNT is next to HADDR
    459  1.1  mycroft 	mvi	SCBARRAY+23	call bcopy_3
    460  1.1  mycroft 
    461  1.1  mycroft 	mvi	DINDEX,STCNT
    462  1.1  mycroft 	mvi	SCBARRAY+23	call bcopy_3
    463  1.1  mycroft 
    464  1.1  mycroft # If we are the last SG block, don't set wideodd.
    465  1.1  mycroft 	test    SCBARRAY+18,0xff jnz p_dataout_wideodd
    466  1.1  mycroft 	mvi	0x3d		call dma	# SCSIEN|SDMAEN|HDMAEN|
    467  1.1  mycroft 						#   DIRECTION|FIFORESET
    468  1.1  mycroft 	jmp	p_dataout_rest
    469  1.1  mycroft 
    470  1.1  mycroft p_dataout_wideodd:
    471  1.1  mycroft 	mvi	0xbd		call dma	# WIDEODD|SCSIEN|SDMAEN|HDMAEN|
    472  1.1  mycroft 						#   DIRECTION|FIFORESET
    473  1.1  mycroft 
    474  1.1  mycroft p_dataout_rest:
    475  1.1  mycroft #  After a DMA finishes, save the final transfer pointer and count
    476  1.1  mycroft #  back into the SCB, in case a device disconnects in the middle of
    477  1.1  mycroft #  a transfer.  Use SHADDR and STCNT instead of HADDR and HCNT, since
    478  1.1  mycroft #  it's a reflection of how many bytes were transferred on the SCSI
    479  1.1  mycroft #  (as opposed to the host) bus.
    480  1.1  mycroft #
    481  1.1  mycroft 	mvi	DINDEX,SCBARRAY+23
    482  1.1  mycroft 	mvi	STCNT		call bcopy_3
    483  1.1  mycroft 
    484  1.1  mycroft 	mvi	DINDEX,SCBARRAY+19
    485  1.1  mycroft 	mvi	SHADDR		call bcopy_4
    486  1.1  mycroft 
    487  1.1  mycroft 	call	sg_advance
    488  1.1  mycroft 	mov	SCBARRAY+18,SG_COUNT		# residual S/G count
    489  1.1  mycroft 
    490  1.1  mycroft 	jmp	ITloop
    491  1.1  mycroft 
    492  1.1  mycroft p_datain:
    493  1.1  mycroft 	mvi	0x40		call scsisig	# !CDO|IOO|!MSGO
    494  1.1  mycroft 	call	assert
    495  1.1  mycroft 	call	sg_load
    496  1.1  mycroft 
    497  1.1  mycroft 	mvi	DINDEX,HADDR
    498  1.1  mycroft 	mvi	SCBARRAY+19	call bcopy_4
    499  1.1  mycroft 
    500  1.1  mycroft #	mvi	DINDEX,HCNT	# implicit since HCNT is next to HADDR
    501  1.1  mycroft 	mvi	SCBARRAY+23	call bcopy_3
    502  1.1  mycroft 
    503  1.1  mycroft 	mvi	DINDEX,STCNT
    504  1.1  mycroft 	mvi	SCBARRAY+23	call bcopy_3
    505  1.1  mycroft 
    506  1.1  mycroft # If we are the last SG block, don't set wideodd.
    507  1.1  mycroft 	test	SCBARRAY+18,0xff jnz p_datain_wideodd
    508  1.1  mycroft 	mvi	0x39		call dma	# SCSIEN|SDMAEN|HDMAEN|
    509  1.1  mycroft 						#   !DIRECTION|FIFORESET
    510  1.1  mycroft 	jmp	p_datain_rest
    511  1.1  mycroft p_datain_wideodd:
    512  1.1  mycroft 	mvi	0xb9		call dma	# WIDEODD|SCSIEN|SDMAEN|HDMAEN|
    513  1.1  mycroft 						#   !DIRECTION|FIFORESET
    514  1.1  mycroft p_datain_rest:
    515  1.1  mycroft 	mvi	DINDEX,SCBARRAY+23
    516  1.1  mycroft 	mvi	STCNT		call bcopy_3
    517  1.1  mycroft 
    518  1.1  mycroft 	mvi	DINDEX,SCBARRAY+19
    519  1.1  mycroft 	mvi	SHADDR		call bcopy_4
    520  1.1  mycroft 
    521  1.1  mycroft 	call	sg_advance
    522  1.1  mycroft 	mov	SCBARRAY+18,SG_COUNT		# residual S/G count
    523  1.1  mycroft 
    524  1.1  mycroft 	jmp	ITloop
    525  1.1  mycroft 
    526  1.1  mycroft #  Command phase.  Set up the DMA registers and let 'er rip - the
    527  1.1  mycroft #  two bytes after the SCB SCSI_cmd_length are zeroed by the driver,
    528  1.1  mycroft #  so we can copy those three bytes directly into HCNT.
    529  1.1  mycroft #
    530  1.1  mycroft p_command:
    531  1.1  mycroft 	mvi	0x80		call scsisig	# CDO|!IOO|!MSGO
    532  1.1  mycroft 	call	assert
    533  1.1  mycroft 
    534  1.1  mycroft 	mvi	DINDEX,HADDR
    535  1.1  mycroft 	mvi	SCBARRAY+7	call bcopy_4
    536  1.1  mycroft 
    537  1.1  mycroft #	mvi	DINDEX,HCNT	# implicit since HCNT is next to HADDR
    538  1.1  mycroft 	mvi	SCBARRAY+11	call bcopy_3
    539  1.1  mycroft 
    540  1.1  mycroft 	mvi	DINDEX,STCNT
    541  1.1  mycroft 	mvi	SCBARRAY+11	call bcopy_3
    542  1.1  mycroft 
    543  1.1  mycroft 	mvi	0x3d		call dma	# SCSIEN|SDMAEN|HDMAEN|
    544  1.1  mycroft 						#   DIRECTION|FIFORESET
    545  1.1  mycroft 	jmp	ITloop
    546  1.1  mycroft 
    547  1.1  mycroft #  Status phase.  Wait for the data byte to appear, then read it
    548  1.1  mycroft #  and store it into the SCB.
    549  1.1  mycroft #
    550  1.1  mycroft p_status:
    551  1.1  mycroft 	mvi	0xc0		call scsisig	# CDO|IOO|!MSGO
    552  1.1  mycroft 
    553  1.1  mycroft 	mvi	SCBARRAY+14	call inb_first
    554  1.1  mycroft 	jmp	p_mesgin_done
    555  1.1  mycroft 
    556  1.1  mycroft #  Message out phase.  If there is no active message, but the target
    557  1.1  mycroft #  took us into this phase anyway, build a no-op message and send it.
    558  1.1  mycroft #
    559  1.1  mycroft p_mesgout:
    560  1.1  mycroft 	mvi	0xa0		call scsisig	# CDO|!IOO|MSGO
    561  1.1  mycroft 	mvi	0x8		call mk_mesg	# build NOP message
    562  1.1  mycroft 
    563  1.1  mycroft 	clr     STCNT+2
    564  1.1  mycroft 	clr     STCNT+1
    565  1.1  mycroft 
    566  1.1  mycroft #  Set up automatic PIO transfer from MSG_START.  Bit 3 in
    567  1.1  mycroft #  SXFRCTL0 (SPIOEN) is already on.
    568  1.1  mycroft #
    569  1.1  mycroft 	mvi	SINDEX,MSG_START+0
    570  1.1  mycroft 	mov	DINDEX,MSG_LEN
    571  1.1  mycroft 
    572  1.1  mycroft #  When target asks for a byte, drop ATN if it's the last one in
    573  1.1  mycroft #  the message.  Otherwise, keep going until the message is exhausted.
    574  1.1  mycroft #  (We can't use outb for this since it wants the input in SINDEX.)
    575  1.1  mycroft #
    576  1.1  mycroft #  Keep an eye out for a phase change, in case the target issues
    577  1.1  mycroft #  a MESSAGE REJECT.
    578  1.1  mycroft #
    579  1.1  mycroft p_mesgout2:
    580  1.1  mycroft 	test	SSTAT0,0x2	jz p_mesgout2	# SPIORDY
    581  1.1  mycroft 	test	SSTAT1,0x10	jnz p_mesgout6	# PHASEMIS
    582  1.1  mycroft 
    583  1.1  mycroft 	cmp	DINDEX,1	jne p_mesgout3	# last byte?
    584  1.1  mycroft 	mvi	CLRSINT1,0x40			# CLRATNO - drop ATN
    585  1.1  mycroft 
    586  1.1  mycroft #  Write a byte to the SCSI bus.  The AIC-7770 refuses to automatically
    587  1.1  mycroft #  send ACKs in automatic PIO or DMA mode unless you make sure that the
    588  1.1  mycroft #  "expected" bus phase in SCSISIGO matches the actual bus phase.  This
    589  1.1  mycroft #  behaviour is completely undocumented and caused me several days of
    590  1.1  mycroft #  grief.
    591  1.1  mycroft #
    592  1.1  mycroft #  After plugging in different drives to test with and using a longer
    593  1.1  mycroft #  SCSI cable, I found that I/O in Automatic PIO mode ceased to function,
    594  1.1  mycroft #  especially when transferring >1 byte.  It seems to be much more stable
    595  1.1  mycroft #  if STCNT is set to one before the transfer, and SDONE (in SSTAT0) is
    596  1.1  mycroft #  polled for transfer completion - for both output _and_ input.  The
    597  1.1  mycroft #  only theory I have is that SPIORDY doesn't drop right away when SCSIDATL
    598  1.1  mycroft #  is accessed (like the documentation says it does), and that on a longer
    599  1.1  mycroft #  cable run, the sequencer code was fast enough to loop back and see
    600  1.1  mycroft #  an SPIORDY that hadn't dropped yet.
    601  1.1  mycroft #
    602  1.1  mycroft p_mesgout3:
    603  1.1  mycroft 	mvi	STCNT+0, 0x01	
    604  1.1  mycroft 	mov	SCSIDATL,SINDIR
    605  1.1  mycroft 
    606  1.1  mycroft p_mesgout4:
    607  1.1  mycroft 	test	SSTAT0,0x4	jz p_mesgout4	# SDONE
    608  1.1  mycroft 	dec	DINDEX
    609  1.1  mycroft 	test	DINDEX,0xff	jnz p_mesgout2
    610  1.1  mycroft 
    611  1.1  mycroft #  If the next bus phase after ATN drops is a message out, it means
    612  1.1  mycroft #  that the target is requesting that the last message(s) be resent.
    613  1.1  mycroft #
    614  1.1  mycroft p_mesgout5:
    615  1.1  mycroft 	test	SSTAT1,0x8	jnz p_mesgout6	# BUSFREE
    616  1.1  mycroft 	test	SSTAT1,0x1	jz p_mesgout5	# REQINIT
    617  1.1  mycroft 
    618  1.1  mycroft 	and	A,0xe0,SCSISIGI			# CDI|IOI|MSGI
    619  1.1  mycroft 	cmp	A,0xa0		jne p_mesgout6
    620  1.1  mycroft 	mvi	0x10		call scsisig	# ATNO - re-assert ATN
    621  1.1  mycroft 
    622  1.1  mycroft 	jmp	ITloop
    623  1.1  mycroft 
    624  1.1  mycroft p_mesgout6:
    625  1.1  mycroft 	mvi	CLRSINT1,0x40			# CLRATNO - in case of PHASEMIS
    626  1.1  mycroft 	and	FLAGS,0xdf			# no active msg
    627  1.1  mycroft 	jmp	ITloop
    628  1.1  mycroft 
    629  1.1  mycroft #  Message in phase.  Bytes are read using Automatic PIO mode, but not
    630  1.1  mycroft #  using inb.  This alleviates a race condition, namely that if ATN had
    631  1.1  mycroft #  to be asserted under Automatic PIO mode, it had to beat the SCSI
    632  1.1  mycroft #  circuitry sending an ACK to the target.  This showed up under heavy
    633  1.1  mycroft #  loads and really confused things, since ABORT commands wouldn't be
    634  1.1  mycroft #  seen by the drive after an IDENTIFY message in until it had changed
    635  1.1  mycroft #  to a data I/O phase.
    636  1.1  mycroft #
    637  1.1  mycroft p_mesgin:
    638  1.1  mycroft 	mvi	0xe0		call scsisig	# CDO|IOO|MSGO
    639  1.1  mycroft 	mvi	A		call inb_first	# read the 1st message byte
    640  1.1  mycroft 	mvi	REJBYTE,A			# save it for the driver
    641  1.1  mycroft 
    642  1.1  mycroft 	cmp	ALLZEROS,A	jne p_mesgin1
    643  1.1  mycroft 
    644  1.1  mycroft #  We got a "command complete" message, so put the SCB pointer
    645  1.1  mycroft #  into the Queue Out, and trigger a completion interrupt.
    646  1.1  mycroft #  Check status for non zero return and interrupt driver if needed
    647  1.1  mycroft #  This allows the driver to interpret errors only when they occur
    648  1.1  mycroft #  instead of always uploading the scb.  If the status is SCSI_CHECK,
    649  1.1  mycroft #  the driver will download a new scb requesting sense to replace
    650  1.1  mycroft #  the old one, modify the "waiting for selection" SCB list and set 
    651  1.1  mycroft #  RETURN_1 to 0x80.  If RETURN_1 is set to 0x80 the sequencer imediately
    652  1.1  mycroft #  jumps to main loop where it will run down the waiting SCB list.
    653  1.1  mycroft #  If the kernel driver does not wish to request sense, it need
    654  1.1  mycroft #  only clear RETURN_1, and the command is allowed to complete.  We don't 
    655  1.1  mycroft #  bother to post to the QOUTFIFO in the error case since it would require 
    656  1.1  mycroft #  extra work in the kernel driver to ensure that the entry was removed 
    657  1.1  mycroft #  before the command complete code tried processing it.
    658  1.1  mycroft 
    659  1.1  mycroft # First check for residuals
    660  1.1  mycroft 	test	SCBARRAY+15,0xff	jnz resid
    661  1.1  mycroft 	test	SCBARRAY+16,0xff	jnz resid
    662  1.1  mycroft 	test	SCBARRAY+17,0xff	jnz resid
    663  1.1  mycroft 
    664  1.1  mycroft check_status:
    665  1.1  mycroft 	test	SCBARRAY+14,0xff	jz status_ok	# 0 Status?
    666  1.1  mycroft 	mvi	INTSTAT,BAD_STATUS			# let driver know
    667  1.1  mycroft 	test	RETURN_1, 0x80	jz status_ok
    668  1.1  mycroft 	jmp	p_mesgin_done
    669  1.1  mycroft 
    670  1.1  mycroft status_ok:
    671  1.1  mycroft #  First, mark this target as free.
    672  1.1  mycroft 	test	SCBARRAY+0,0x20	jnz complete		# Tagged command
    673  1.1  mycroft 	and	FUNCTION1,0x70,SCBARRAY+1
    674  1.1  mycroft 	mov	A,FUNCTION1
    675  1.1  mycroft 	test	SCBARRAY+1,0x88 jz clear_a
    676  1.1  mycroft 	xor	ACTIVE_B,A
    677  1.1  mycroft 	jmp	complete
    678  1.1  mycroft 
    679  1.1  mycroft clear_a:
    680  1.1  mycroft 	xor	ACTIVE_A,A
    681  1.1  mycroft 
    682  1.1  mycroft complete:
    683  1.1  mycroft 	mov	QOUTFIFO,SCBPTR
    684  1.1  mycroft 	mvi	INTSTAT,CMDCMPLT
    685  1.1  mycroft 	jmp	p_mesgin_done
    686  1.1  mycroft 
    687  1.1  mycroft # If we have a residual count, interrupt and tell the host.  Other
    688  1.1  mycroft # alternatives are to pause the sequencer on all command completes (yuck),
    689  1.1  mycroft # dma the resid directly to the host (slick, but a ton of instructions), or
    690  1.1  mycroft # have the sequencer pause itself when it encounters a non-zero resid 
    691  1.1  mycroft # (unecessary pause just to flag the command -- yuck, but takes few instructions
    692  1.1  mycroft # and since it shouldn't happen that often is good enough for our purposes).  
    693  1.1  mycroft 
    694  1.1  mycroft resid:
    695  1.1  mycroft 	mvi	INTSTAT,RESIDUAL
    696  1.1  mycroft 	jmp	check_status
    697  1.1  mycroft 
    698  1.1  mycroft #  Is it an extended message?  We only support the synchronous and wide data
    699  1.1  mycroft #  transfer request messages, which will probably be in response to
    700  1.1  mycroft #  WDTR or SDTR message outs from us.  If it's not SDTR or WDTR, reject it -
    701  1.1  mycroft #  apparently this can be done after any message in byte, according
    702  1.1  mycroft #  to the SCSI-2 spec.
    703  1.1  mycroft #
    704  1.1  mycroft p_mesgin1:
    705  1.1  mycroft 	cmp	A,1		jne p_mesgin2	# extended message code?
    706  1.1  mycroft 	
    707  1.1  mycroft 	mvi	ARG_1		call inb_next	# extended message length
    708  1.1  mycroft 	mvi	A		call inb_next	# extended message code
    709  1.1  mycroft 
    710  1.1  mycroft 	cmp	A,1		je p_mesginSDTR	# Syncronous negotiation message
    711  1.1  mycroft 	cmp	A,3		je p_mesginWDTR # Wide negotiation message
    712  1.1  mycroft 	jmp	p_mesginN
    713  1.1  mycroft 
    714  1.1  mycroft p_mesginWDTR:
    715  1.1  mycroft 	cmp	ARG_1,2		jne p_mesginN	# extended mesg length = 2
    716  1.1  mycroft 	mvi	A		call inb_next	# Width of bus
    717  1.1  mycroft 	mvi	INTSTAT,MSG_WDTR		# let driver know
    718  1.1  mycroft 	test	RETURN_1,0x80	jz p_mesgin_done# Do we need to send WDTR?
    719  1.1  mycroft 
    720  1.1  mycroft # We didn't initiate the wide negotiation, so we must respond to the request
    721  1.1  mycroft 	and	RETURN_1,0x7f			# Clear the SEND_WDTR Flag
    722  1.1  mycroft 	or	FLAGS,ACTIVE_MSG
    723  1.1  mycroft 	mvi	DINDEX,MSG_START+0
    724  1.1  mycroft 	mvi	MSG_START+0	call mk_wdtr	# build WDTR message	
    725  1.1  mycroft 	or	SINDEX,0x10,SIGSTATE		# turn on ATNO
    726  1.1  mycroft 	call	scsisig
    727  1.1  mycroft 	jmp	p_mesgin_done
    728  1.1  mycroft 
    729  1.1  mycroft p_mesginSDTR:
    730  1.1  mycroft 	cmp	ARG_1,3		jne p_mesginN	# extended mesg length = 3
    731  1.1  mycroft 	mvi	ARG_1		call inb_next	# xfer period
    732  1.1  mycroft 	mvi	A		call inb_next	# REQ/ACK offset
    733  1.1  mycroft 	mvi	INTSTAT,MSG_SDTR		# call driver to convert
    734  1.1  mycroft 
    735  1.1  mycroft 	test	RETURN_1,0xc0	jz p_mesgin_done# Do we need to mk_sdtr or rej?
    736  1.1  mycroft 	test	RETURN_1,0x40	jnz p_mesginN	# Requested SDTR too small - rej
    737  1.1  mycroft 	or	FLAGS,ACTIVE_MSG
    738  1.1  mycroft 	mvi	DINDEX, MSG_START+0
    739  1.1  mycroft 	mvi     MSG_START+0     call mk_sdtr
    740  1.1  mycroft 	or	SINDEX,0x10,SIGSTATE		# turn on ATNO
    741  1.1  mycroft 	call	scsisig
    742  1.1  mycroft 	jmp	p_mesgin_done
    743  1.1  mycroft 
    744  1.1  mycroft #  Is it a disconnect message?  Set a flag in the SCB to remind us
    745  1.1  mycroft #  and await the bus going free.
    746  1.1  mycroft #
    747  1.1  mycroft p_mesgin2:
    748  1.1  mycroft 	cmp	A,4		jne p_mesgin3	# disconnect code?
    749  1.1  mycroft 
    750  1.1  mycroft 	or	SCBARRAY+0,0x4			# set "disconnected" bit
    751  1.1  mycroft 	jmp	p_mesgin_done
    752  1.1  mycroft 
    753  1.1  mycroft #  Save data pointers message?  Copy working values into the SCB,
    754  1.1  mycroft #  usually in preparation for a disconnect.
    755  1.1  mycroft #
    756  1.1  mycroft p_mesgin3:
    757  1.1  mycroft 	cmp	A,2		jne p_mesgin4	# save data pointers code?
    758  1.1  mycroft 
    759  1.1  mycroft 	call	sg_ram2scb
    760  1.1  mycroft 	jmp	p_mesgin_done
    761  1.1  mycroft 
    762  1.1  mycroft #  Restore pointers message?  Data pointers are recopied from the
    763  1.1  mycroft #  SCB anyway at the start of any DMA operation, so the only thing
    764  1.1  mycroft #  to copy is the scatter-gather values.
    765  1.1  mycroft #
    766  1.1  mycroft p_mesgin4:
    767  1.1  mycroft 	cmp	A,3		jne p_mesgin5	# restore pointers code?
    768  1.1  mycroft 
    769  1.1  mycroft 	call	sg_scb2ram
    770  1.1  mycroft 	jmp	p_mesgin_done
    771  1.1  mycroft 
    772  1.1  mycroft #  Identify message?  For a reconnecting target, this tells us the lun
    773  1.1  mycroft #  that the reconnection is for - find the correct SCB and switch to it,
    774  1.1  mycroft #  clearing the "disconnected" bit so we don't "find" it by accident later.
    775  1.1  mycroft #
    776  1.1  mycroft p_mesgin5:
    777  1.1  mycroft 	test	A,0x80		jz p_mesgin6	# identify message?
    778  1.1  mycroft 
    779  1.1  mycroft 	test	A,0x78		jnz p_mesginN	# !DiscPriv|!LUNTAR|!Reserved
    780  1.1  mycroft 
    781  1.1  mycroft 	and	A,0x07				# lun in lower three bits
    782  1.1  mycroft 	or      SAVED_TCL,A,SELID          
    783  1.1  mycroft 	and     SAVED_TCL,0xf7
    784  1.1  mycroft 	and     A,0x08,SBLKCTL			# B Channel??
    785  1.1  mycroft 	or      SAVED_TCL,A
    786  1.1  mycroft 	call	inb_last			# ACK
    787  1.1  mycroft 	mov	ALLZEROS	call findSCB    
    788  1.1  mycroft setup_SCB:
    789  1.1  mycroft 	and	SCBARRAY+0,0xfb			# clear disconnect bit in SCB
    790  1.1  mycroft 	or	FLAGS,IDENTIFY_SEEN		# make note of IDENTIFY
    791  1.1  mycroft 
    792  1.1  mycroft 	call	sg_scb2ram			# implied restore pointers
    793  1.1  mycroft 						#   required on reselect
    794  1.1  mycroft 	jmp	ITloop
    795  1.1  mycroft get_tag:
    796  1.1  mycroft 	mvi	A		call inb_first
    797  1.1  mycroft 	cmp	A,0x20  	jne return	# Simple Tag message?
    798  1.1  mycroft 	mvi	A		call inb_next
    799  1.1  mycroft 	call			inb_last
    800  1.1  mycroft 	test	A,0xf0		jnz abort_tag	# Tag in range?
    801  1.1  mycroft 	mov	SCBPTR,A
    802  1.1  mycroft 	mov	A,SAVED_TCL
    803  1.1  mycroft 	cmp	SCBARRAY+1,A		jne abort_tag
    804  1.1  mycroft 	test	SCBARRAY+0,TAG_ENB	jz  abort_tag
    805  1.1  mycroft 	ret
    806  1.1  mycroft abort_tag:
    807  1.1  mycroft 	or	SINDEX,0x10,SIGSTATE		# turn on ATNO
    808  1.1  mycroft 	call	scsisig
    809  1.1  mycroft 	mvi	INTSTAT,ABORT_TAG 		# let driver know
    810  1.1  mycroft 	mvi	0xd		call mk_mesg	# ABORT TAG message
    811  1.1  mycroft 	ret
    812  1.1  mycroft 
    813  1.1  mycroft #  Message reject?  Let the kernel driver handle this.  If we have an 
    814  1.1  mycroft #  outstanding WDTR or SDTR negotiation, assume that it's a response from 
    815  1.1  mycroft #  the target selecting 8bit or asynchronous transfer, otherwise just ignore 
    816  1.1  mycroft #  it since we have no clue what it pertains to.
    817  1.1  mycroft #
    818  1.1  mycroft p_mesgin6:
    819  1.1  mycroft 	cmp	A,7		jne p_mesgin7	# message reject code?
    820  1.1  mycroft 
    821  1.1  mycroft 	mvi	INTSTAT, MSG_REJECT
    822  1.1  mycroft 	jmp	p_mesgin_done
    823  1.1  mycroft 
    824  1.1  mycroft #  [ ADD MORE MESSAGE HANDLING HERE ]
    825  1.1  mycroft #
    826  1.1  mycroft p_mesgin7:
    827  1.1  mycroft 
    828  1.1  mycroft #  We have no idea what this message in is, and there's no way
    829  1.1  mycroft #  to pass it up to the kernel, so we issue a message reject and
    830  1.1  mycroft #  hope for the best.  Since we're now using manual PIO mode to
    831  1.1  mycroft #  read in the message, there should no longer be a race condition
    832  1.1  mycroft #  present when we assert ATN.  In any case, rejection should be a
    833  1.1  mycroft #  rare occurrence - signal the driver when it happens.
    834  1.1  mycroft #
    835  1.1  mycroft p_mesginN:
    836  1.1  mycroft 	or	SINDEX,0x10,SIGSTATE		# turn on ATNO
    837  1.1  mycroft 	call	scsisig
    838  1.1  mycroft 	mvi	INTSTAT,SEND_REJECT		# let driver know
    839  1.1  mycroft 
    840  1.1  mycroft 	mvi	0x7		call mk_mesg	# MESSAGE REJECT message
    841  1.1  mycroft 
    842  1.1  mycroft p_mesgin_done:
    843  1.1  mycroft 	call	inb_last			# ack & turn auto PIO back on
    844  1.1  mycroft 	jmp	ITloop
    845  1.1  mycroft 
    846  1.1  mycroft 
    847  1.1  mycroft #  Bus free phase.  It might be useful to interrupt the device
    848  1.1  mycroft #  driver if we aren't expecting this.  For now, make sure that
    849  1.1  mycroft #  ATN isn't being asserted and look for a new command.
    850  1.1  mycroft #
    851  1.1  mycroft p_busfree:
    852  1.1  mycroft 	mvi	CLRSINT1,0x40			# CLRATNO
    853  1.1  mycroft 	clr	SIGSTATE
    854  1.1  mycroft 	jmp	start
    855  1.1  mycroft 
    856  1.1  mycroft #  Instead of a generic bcopy routine that requires an argument, we unroll
    857  1.1  mycroft #  the two cases that are actually used, and call them explicitly.  This
    858  1.1  mycroft #  not only reduces the overhead of doing a bcopy by 2/3rds, but ends up
    859  1.1  mycroft #  saving space in the program since you don't have to put the argument 
    860  1.1  mycroft #  into the accumulator before the call.  Both functions expect DINDEX to
    861  1.1  mycroft #  contain the destination address and SINDEX to contain the source 
    862  1.1  mycroft #  address.
    863  1.1  mycroft bcopy_3:
    864  1.1  mycroft 	mov	DINDIR,SINDIR
    865  1.1  mycroft 	mov	DINDIR,SINDIR
    866  1.1  mycroft 	mov	DINDIR,SINDIR	ret
    867  1.1  mycroft 
    868  1.1  mycroft bcopy_4:
    869  1.1  mycroft 	mov	DINDIR,SINDIR
    870  1.1  mycroft 	mov	DINDIR,SINDIR
    871  1.1  mycroft 	mov	DINDIR,SINDIR
    872  1.1  mycroft 	mov	DINDIR,SINDIR	ret
    873  1.1  mycroft 	
    874  1.1  mycroft bcopy_3_dfdat:
    875  1.1  mycroft 	mov	DINDIR,DFDAT
    876  1.1  mycroft 	mov	DINDIR,DFDAT
    877  1.1  mycroft 	mov	DINDIR,DFDAT	ret
    878  1.1  mycroft 
    879  1.1  mycroft bcopy_4_dfdat:
    880  1.1  mycroft 	mov	DINDIR,DFDAT
    881  1.1  mycroft 	mov	DINDIR,DFDAT
    882  1.1  mycroft 	mov	DINDIR,DFDAT
    883  1.1  mycroft 	mov	DINDIR,DFDAT	ret
    884  1.1  mycroft 
    885  1.1  mycroft #  Locking the driver out, build a one-byte message passed in SINDEX
    886  1.1  mycroft #  if there is no active message already.  SINDEX is returned intact.
    887  1.1  mycroft #
    888  1.1  mycroft mk_mesg:
    889  1.1  mycroft 	mvi	SEQCTL,0x50			# PAUSEDIS|FASTMODE
    890  1.1  mycroft 	test	FLAGS,ACTIVE_MSG jnz mk_mesg1	# active message?
    891  1.1  mycroft 
    892  1.1  mycroft 	or	FLAGS,ACTIVE_MSG		# if not, there is now
    893  1.1  mycroft 	mvi	MSG_LEN,1			# length = 1
    894  1.1  mycroft 	mov	MSG_START+0,SINDEX		# 1-byte message
    895  1.1  mycroft 
    896  1.1  mycroft mk_mesg1:
    897  1.1  mycroft 	mvi	SEQCTL,0x10	ret		# !PAUSEDIS|FASTMODE
    898  1.1  mycroft 
    899  1.1  mycroft #  Carefully read data in Automatic PIO mode.  I first tried this using
    900  1.1  mycroft #  Manual PIO mode, but it gave me continual underrun errors, probably
    901  1.1  mycroft #  indicating that I did something wrong, but I feel more secure leaving
    902  1.1  mycroft #  Automatic PIO on all the time.
    903  1.1  mycroft #
    904  1.1  mycroft #  According to Adaptec's documentation, an ACK is not sent on input from
    905  1.1  mycroft #  the target until SCSIDATL is read from.  So we wait until SCSIDATL is
    906  1.1  mycroft #  latched (the usual way), then read the data byte directly off the bus
    907  1.1  mycroft #  using SCSIBUSL.  When we have pulled the ATN line, or we just want to
    908  1.1  mycroft #  acknowledge the byte, then we do a dummy read from SCISDATL.  The SCSI
    909  1.1  mycroft #  spec guarantees that the target will hold the data byte on the bus until
    910  1.1  mycroft #  we send our ACK.
    911  1.1  mycroft #
    912  1.1  mycroft #  The assumption here is that these are called in a particular sequence,
    913  1.1  mycroft #  and that REQ is already set when inb_first is called.  inb_{first,next}
    914  1.1  mycroft #  use the same calling convention as inb.
    915  1.1  mycroft #
    916  1.1  mycroft inb_first:
    917  1.1  mycroft 	clr	STCNT+2
    918  1.1  mycroft 	clr	STCNT+1
    919  1.1  mycroft 	mov	DINDEX,SINDEX
    920  1.1  mycroft 	mov	DINDIR,SCSIBUSL	ret		# read byte directly from bus
    921  1.1  mycroft 
    922  1.1  mycroft inb_next:
    923  1.1  mycroft 	mov	DINDEX,SINDEX			# save SINDEX
    924  1.1  mycroft 
    925  1.1  mycroft         mvi     STCNT+0,1			# xfer one byte
    926  1.1  mycroft 	mov	NONE,SCSIDATL			# dummy read from latch to ACK
    927  1.1  mycroft inb_next1:
    928  1.1  mycroft 	test	SSTAT0,0x4	jz inb_next1	# SDONE
    929  1.1  mycroft inb_next2:
    930  1.1  mycroft 	test	SSTAT0,0x2	jz inb_next2	# SPIORDY - wait for next byte
    931  1.1  mycroft 	mov	DINDIR,SCSIBUSL	ret		# read byte directly from bus
    932  1.1  mycroft 
    933  1.1  mycroft inb_last:
    934  1.1  mycroft 	mvi	STCNT+0,1			# ACK with dummy read
    935  1.1  mycroft 	mov	NONE,SCSIDATL
    936  1.1  mycroft inb_last1:
    937  1.1  mycroft 	test	SSTAT0,0x4	jz inb_last1	# wait for completion
    938  1.1  mycroft 	ret
    939  1.1  mycroft 
    940  1.1  mycroft #  DMA data transfer.  HADDR and HCNT must be loaded first, and
    941  1.1  mycroft #  SINDEX should contain the value to load DFCNTRL with - 0x3d for
    942  1.1  mycroft #  host->scsi, or 0x39 for scsi->host.  The SCSI channel is cleared
    943  1.1  mycroft #  during initialization.
    944  1.1  mycroft #
    945  1.1  mycroft dma:
    946  1.1  mycroft 	mov	DFCNTRL,SINDEX
    947  1.1  mycroft dma1:
    948  1.1  mycroft dma2:
    949  1.1  mycroft 	test	SSTAT0,0x1	jnz dma3	# DMADONE
    950  1.1  mycroft 	test	SSTAT1,0x10	jz dma1		# PHASEMIS, ie. underrun
    951  1.1  mycroft 
    952  1.1  mycroft #  We will be "done" DMAing when the transfer count goes to zero, or
    953  1.1  mycroft #  the target changes the phase (in light of this, it makes sense that
    954  1.1  mycroft #  the DMA circuitry doesn't ACK when PHASEMIS is active).  If we are
    955  1.1  mycroft #  doing a SCSI->Host transfer, the data FIFO should be flushed auto-
    956  1.1  mycroft #  magically on STCNT=0 or a phase change, so just wait for FIFO empty
    957  1.1  mycroft #  status.
    958  1.1  mycroft #
    959  1.1  mycroft dma3:
    960  1.1  mycroft 	test	SINDEX,0x4	jnz dma5	# DIRECTION
    961  1.1  mycroft dma4:
    962  1.1  mycroft 	test	DFSTATUS,0x1	jz dma4		# !FIFOEMP
    963  1.1  mycroft 
    964  1.1  mycroft #  Now shut the DMA enables off, and copy STCNT (ie. the underrun
    965  1.1  mycroft #  amount, if any) to the SCB registers; SG_COUNT will get copied to
    966  1.1  mycroft #  the SCB's residual S/G count field after sg_advance is called.  Make
    967  1.1  mycroft #  sure that the DMA enables are actually off first lest we get an ILLSADDR.
    968  1.1  mycroft #
    969  1.1  mycroft dma5:
    970  1.1  mycroft 	clr	DFCNTRL				# disable DMA
    971  1.1  mycroft dma6:
    972  1.1  mycroft 	test	DFCNTRL,0x38	jnz dma6	# SCSIENACK|SDMAENACK|HDMAENACK
    973  1.1  mycroft 
    974  1.1  mycroft 	mvi	DINDEX,SCBARRAY+15
    975  1.1  mycroft 	mvi	STCNT		call bcopy_3
    976  1.1  mycroft 
    977  1.1  mycroft 	ret
    978  1.1  mycroft 
    979  1.1  mycroft dma_finish:
    980  1.1  mycroft 	test	DFSTATUS,0x8	jz dma_finish	# HDONE
    981  1.1  mycroft 
    982  1.1  mycroft 	clr	DFCNTRL				# disable DMA
    983  1.1  mycroft dma_finish2:
    984  1.1  mycroft 	test	DFCNTRL,0x8	jnz dma_finish2	# HDMAENACK
    985  1.1  mycroft 	ret
    986  1.1  mycroft 
    987  1.1  mycroft #  Common SCSI initialization for selection and reselection.  Expects
    988  1.1  mycroft #  the target SCSI ID to be in the upper four bits of SINDEX, and A's
    989  1.1  mycroft #  contents are stomped on return.
    990  1.1  mycroft #
    991  1.1  mycroft initialize_scsiid:
    992  1.1  mycroft 	and	SINDEX,0xf0		# Get target ID
    993  1.1  mycroft 	and	A,0x0f,SCSIID
    994  1.1  mycroft 	or	SINDEX,A
    995  1.1  mycroft 	mov	SCSIID,SINDEX ret
    996  1.1  mycroft 
    997  1.1  mycroft initialize_for_target:
    998  1.1  mycroft #  Turn on Automatic PIO mode now, before we expect to see a REQ
    999  1.1  mycroft #  from the target.  It shouldn't hurt anything to leave it on.  Set
   1000  1.1  mycroft #  CLRCHN here before the target has entered a data transfer mode -
   1001  1.1  mycroft #  with synchronous SCSI, if you do it later, you blow away some
   1002  1.1  mycroft #  data in the SCSI FIFO that the target has already sent to you.
   1003  1.1  mycroft #
   1004  1.1  mycroft 	clr	SIGSTATE 
   1005  1.1  mycroft 
   1006  1.1  mycroft 	mvi	SXFRCTL0,0x8a			# DFON|SPIOEN|CLRCHN
   1007  1.1  mycroft 
   1008  1.1  mycroft #  Initialize scatter-gather pointers by setting up the working copy
   1009  1.1  mycroft #  in scratch RAM.
   1010  1.1  mycroft #
   1011  1.1  mycroft 	call	sg_scb2ram
   1012  1.1  mycroft 
   1013  1.1  mycroft #  Initialize SCSIRATE with the appropriate value for this target.
   1014  1.1  mycroft #
   1015  1.1  mycroft 	call	ndx_dtr
   1016  1.1  mycroft 	mov	SCSIRATE,SINDIR	ret
   1017  1.1  mycroft 
   1018  1.1  mycroft #  Assert that if we've been reselected, then we've seen an IDENTIFY
   1019  1.1  mycroft #  message.
   1020  1.1  mycroft #
   1021  1.1  mycroft assert:
   1022  1.1  mycroft 	test	FLAGS,RESELECTED	jz return	# reselected?
   1023  1.1  mycroft 	test	FLAGS,IDENTIFY_SEEN	jnz return	# seen IDENTIFY?
   1024  1.1  mycroft 
   1025  1.1  mycroft 	mvi	INTSTAT,NO_IDENT 	ret	# no - cause a kernel panic
   1026  1.1  mycroft 
   1027  1.1  mycroft #  Find out if disconnection is ok from the information the BIOS has left
   1028  1.1  mycroft #  us.  The tcl from SCBARRAY+1 should be in SINDEX; A will
   1029  1.1  mycroft #  contain either 0x40 (disconnection ok) or 0x00 (disconnection not ok)
   1030  1.1  mycroft #  on exit.
   1031  1.1  mycroft #
   1032  1.1  mycroft #  To allow for wide or twin busses, we check the upper bit of the target ID
   1033  1.1  mycroft #  and the channel ID and look at the appropriate disconnect register. 
   1034  1.1  mycroft #
   1035  1.1  mycroft disconnect:
   1036  1.1  mycroft 	and	FUNCTION1,0x70,SINDEX		# strip off extra just in case
   1037  1.1  mycroft 	mov	A,FUNCTION1
   1038  1.1  mycroft 	test	SINDEX, 0x88	jz disconnect_a
   1039  1.1  mycroft 
   1040  1.1  mycroft 	test	DISC_DSB_B,A	jz disconnect1	# bit nonzero if DISabled
   1041  1.1  mycroft 	clr	A		ret
   1042  1.1  mycroft 
   1043  1.1  mycroft disconnect_a:
   1044  1.1  mycroft 	test	DISC_DSB_A,A	jz disconnect1	# bit nonzero if DISabled
   1045  1.1  mycroft 	clr	A		ret
   1046  1.1  mycroft 
   1047  1.1  mycroft disconnect1:
   1048  1.1  mycroft 	mvi	A,0x40		ret
   1049  1.1  mycroft 
   1050  1.1  mycroft #  Locate the SCB matching the target ID/channel/lun in SAVED_TCL and switch 
   1051  1.1  mycroft #  the SCB to it.  Have the kernel print a warning message if it can't be 
   1052  1.1  mycroft #  found, and generate an ABORT message to the target.  SINDEX should be
   1053  1.1  mycroft #  cleared on call.
   1054  1.1  mycroft #
   1055  1.1  mycroft findSCB:
   1056  1.1  mycroft 	mov	A,SAVED_TCL
   1057  1.1  mycroft 	mov	SCBPTR,SINDEX			# switch to new SCB
   1058  1.1  mycroft 	cmp	SCBARRAY+1,A	jne findSCB1	# target ID/channel/lun match?
   1059  1.1  mycroft 	test	SCBARRAY+0,0x4	jz findSCB1	# should be disconnected
   1060  1.1  mycroft 	test	SCBARRAY+0,TAG_ENB jnz get_tag
   1061  1.1  mycroft 	ret
   1062  1.1  mycroft 
   1063  1.1  mycroft findSCB1:
   1064  1.1  mycroft 	inc	SINDEX
   1065  1.1  mycroft 	mov	A,SCBCOUNT
   1066  1.1  mycroft 	cmp	SINDEX,A	jne findSCB
   1067  1.1  mycroft 
   1068  1.1  mycroft 	mvi	INTSTAT,NO_MATCH		# not found - signal kernel
   1069  1.1  mycroft 	mvi	0x6		call mk_mesg	# ABORT message
   1070  1.1  mycroft 
   1071  1.1  mycroft 	or	SINDEX,0x10,SIGSTATE		# assert ATNO
   1072  1.1  mycroft 	call	scsisig
   1073  1.1  mycroft 	ret
   1074  1.1  mycroft 
   1075  1.1  mycroft #  Make a working copy of the scatter-gather parameters in the SCB.
   1076  1.1  mycroft #
   1077  1.1  mycroft sg_scb2ram:
   1078  1.1  mycroft 	mov	SG_COUNT,SCBARRAY+2
   1079  1.1  mycroft 
   1080  1.1  mycroft 	mvi	DINDEX,SG_NEXT
   1081  1.1  mycroft 	mvi	SCBARRAY+3	call bcopy_4
   1082  1.1  mycroft 
   1083  1.1  mycroft 	mvi	SG_NOLOAD,0x80
   1084  1.1  mycroft 	test	SCBARRAY+0,0x10	jnz return	# don't reload s/g?
   1085  1.1  mycroft 	clr	SG_NOLOAD	 ret
   1086  1.1  mycroft 
   1087  1.1  mycroft #  Copying RAM values back to SCB, for Save Data Pointers message.
   1088  1.1  mycroft #
   1089  1.1  mycroft sg_ram2scb:
   1090  1.1  mycroft 	mov	SCBARRAY+2,SG_COUNT
   1091  1.1  mycroft 
   1092  1.1  mycroft 	mvi	DINDEX,SCBARRAY+3
   1093  1.1  mycroft 	mvi	SG_NEXT		call bcopy_4
   1094  1.1  mycroft 
   1095  1.1  mycroft 	and	SCBARRAY+0,0xef,SCBARRAY+0
   1096  1.1  mycroft 	test	SG_NOLOAD,0x80	jz return	# reload s/g?
   1097  1.1  mycroft 	or	SCBARRAY+0,SG_LOAD	 ret
   1098  1.1  mycroft 
   1099  1.1  mycroft #  Load a struct scatter if needed and set up the data address and
   1100  1.1  mycroft #  length.  If the working value of the SG count is nonzero, then
   1101  1.1  mycroft #  we need to load a new set of values.
   1102  1.1  mycroft #
   1103  1.1  mycroft #  This, like the above DMA, assumes a little-endian host data storage.
   1104  1.1  mycroft #
   1105  1.1  mycroft sg_load:
   1106  1.1  mycroft 	test	SG_COUNT,0xff	jz return	# SG being used?
   1107  1.1  mycroft 	test	SG_NOLOAD,0x80	jnz return	# don't reload s/g?
   1108  1.1  mycroft 
   1109  1.1  mycroft 	clr	HCNT+2
   1110  1.1  mycroft 	clr	HCNT+1
   1111  1.1  mycroft 	mvi	HCNT+0,SG_SIZEOF
   1112  1.1  mycroft 
   1113  1.1  mycroft 	mvi	DINDEX,HADDR
   1114  1.1  mycroft 	mvi	SG_NEXT		call bcopy_4
   1115  1.1  mycroft 
   1116  1.1  mycroft 	mvi	DFCNTRL,0xd			# HDMAEN|DIRECTION|FIFORESET
   1117  1.1  mycroft 
   1118  1.1  mycroft #  Wait for DMA from host memory to data FIFO to complete, then disable
   1119  1.1  mycroft #  DMA and wait for it to acknowledge that it's off.
   1120  1.1  mycroft #
   1121  1.1  mycroft 
   1122  1.1  mycroft 	call	dma_finish
   1123  1.1  mycroft 
   1124  1.1  mycroft #  Copy data from FIFO into SCB data pointer and data count.  This assumes
   1125  1.1  mycroft #  that the struct scatterlist has this structure (this and sizeof(struct
   1126  1.1  mycroft #  scatterlist) == 12 are asserted in aic7xxx.c):
   1127  1.1  mycroft #
   1128  1.1  mycroft #	struct scatterlist {
   1129  1.1  mycroft #		char *address;		/* four bytes, little-endian order */
   1130  1.1  mycroft #		...			/* four bytes, ignored */
   1131  1.1  mycroft #		unsigned short length;	/* two bytes, little-endian order */
   1132  1.1  mycroft #	}
   1133  1.1  mycroft #
   1134  1.1  mycroft 
   1135  1.1  mycroft # Not in FreeBSD.  the scatter list entry is only 8 bytes.
   1136  1.1  mycroft # 
   1137  1.1  mycroft # struct ahc_dma_seg {
   1138  1.1  mycroft #       physaddr addr;                  /* four bytes, little-endian order */
   1139  1.1  mycroft #       long    len;                    /* four bytes, little endian order */   
   1140  1.1  mycroft # };
   1141  1.1  mycroft #
   1142  1.1  mycroft 
   1143  1.1  mycroft 	mvi	DINDEX, SCBARRAY+19
   1144  1.1  mycroft 	call	bcopy_4_dfdat
   1145  1.1  mycroft 
   1146  1.1  mycroft # For Linux, we must throw away four bytes since there is a 32bit gap
   1147  1.1  mycroft # in the middle of a struct scatterlist
   1148  1.1  mycroft #	mov	NONE,DFDAT
   1149  1.1  mycroft #	mov	NONE,DFDAT
   1150  1.1  mycroft #	mov	NONE,DFDAT
   1151  1.1  mycroft #	mov	NONE,DFDAT
   1152  1.1  mycroft 
   1153  1.1  mycroft 	call	bcopy_3_dfdat		#Only support 24 bit length.
   1154  1.1  mycroft 	ret
   1155  1.1  mycroft 
   1156  1.1  mycroft #  Advance the scatter-gather pointers only IF NEEDED.  If SG is enabled,
   1157  1.1  mycroft #  and the SCSI transfer count is zero (note that this should be called
   1158  1.1  mycroft #  right after a DMA finishes), then move the working copies of the SG
   1159  1.1  mycroft #  pointer/length along.  If the SCSI transfer count is not zero, then
   1160  1.1  mycroft #  presumably the target is disconnecting - do not reload the SG values
   1161  1.1  mycroft #  next time.
   1162  1.1  mycroft #
   1163  1.1  mycroft sg_advance:
   1164  1.1  mycroft 	test	SG_COUNT,0xff	jz return	# s/g enabled?
   1165  1.1  mycroft 
   1166  1.1  mycroft 	test	STCNT+0,0xff	jnz sg_advance1	# SCSI transfer count nonzero?
   1167  1.1  mycroft 	test	STCNT+1,0xff	jnz sg_advance1
   1168  1.1  mycroft 	test	STCNT+2,0xff	jnz sg_advance1
   1169  1.1  mycroft 
   1170  1.1  mycroft 	clr	SG_NOLOAD			# reload s/g next time
   1171  1.1  mycroft 	dec	SG_COUNT			# one less segment to go
   1172  1.1  mycroft 
   1173  1.1  mycroft 	clr	A				# add sizeof(struct scatter)
   1174  1.1  mycroft 	add	SG_NEXT+0,SG_SIZEOF,SG_NEXT+0
   1175  1.1  mycroft 	adc	SG_NEXT+1,A,SG_NEXT+1
   1176  1.1  mycroft 	adc	SG_NEXT+2,A,SG_NEXT+2
   1177  1.1  mycroft 	adc	SG_NEXT+3,A,SG_NEXT+3	ret
   1178  1.1  mycroft 
   1179  1.1  mycroft sg_advance1:
   1180  1.1  mycroft 	mvi	SG_NOLOAD,0x80	ret		# don't reload s/g next time
   1181  1.1  mycroft 
   1182  1.1  mycroft #  Add the array base SYNCNEG to the target offset (the target address
   1183  1.1  mycroft #  is in SCSIID), and return the result in SINDEX.  The accumulator
   1184  1.1  mycroft #  contains the 3->8 decoding of the target ID on return.
   1185  1.1  mycroft #
   1186  1.1  mycroft ndx_dtr:
   1187  1.1  mycroft 	shr	A,SCSIID,4
   1188  1.1  mycroft 	test	SBLKCTL,0x08	jz ndx_dtr_2
   1189  1.1  mycroft 	or	A,0x08		# Channel B entries add 8
   1190  1.1  mycroft ndx_dtr_2:
   1191  1.1  mycroft 	add	SINDEX,SYNCNEG,A
   1192  1.1  mycroft 
   1193  1.1  mycroft 	and	FUNCTION1,0x70,SCSIID		# 3-bit target address decode
   1194  1.1  mycroft 	mov	A,FUNCTION1	ret
   1195  1.1  mycroft 
   1196  1.1  mycroft #  If we need to negotiate transfer parameters, build the WDTR or SDTR message
   1197  1.1  mycroft #  starting at the address passed in SINDEX.  DINDEX is modified on return.
   1198  1.1  mycroft #  The SCSI-II spec requires that Wide negotiation occur first and you can
   1199  1.1  mycroft #  only negotiat one or the other at a time otherwise in the event of a message
   1200  1.1  mycroft #  reject, you wouldn't be able to tell which message was the culpret.
   1201  1.1  mycroft #
   1202  1.1  mycroft mk_dtr:
   1203  1.1  mycroft 	test	SCBARRAY+0,0xc0 jz return	# NEEDWDTR|NEEDSDTR
   1204  1.1  mycroft 	test	SCBARRAY+0,NEEDWDTR jnz  mk_wdtr_16bit
   1205  1.1  mycroft 	or	FLAGS, MAX_SYNC		 # Force an offset of 15
   1206  1.1  mycroft 
   1207  1.1  mycroft mk_sdtr:
   1208  1.1  mycroft 	mvi	DINDIR,1			# extended message
   1209  1.1  mycroft 	mvi	DINDIR,3			# extended message length = 3
   1210  1.1  mycroft 	mvi	DINDIR,1			# SDTR code
   1211  1.1  mycroft 	call	sdtr_to_rate
   1212  1.1  mycroft 	mov	DINDIR,RETURN_1			# REQ/ACK transfer period
   1213  1.1  mycroft 	test	FLAGS, MAX_SYNC	jnz mk_sdtr_max_sync
   1214  1.1  mycroft 	and	DINDIR,0xf,SINDIR		# Sync Offset
   1215  1.1  mycroft 
   1216  1.1  mycroft mk_sdtr_done:
   1217  1.1  mycroft 	add	MSG_LEN,-MSG_START+0,DINDEX ret	# update message length
   1218  1.1  mycroft 
   1219  1.1  mycroft mk_sdtr_max_sync:
   1220  1.1  mycroft # We're initiating sync negotiation, so request the max offset we can (15)
   1221  1.1  mycroft 	mvi	DINDIR, 0x0f
   1222  1.1  mycroft 	xor	FLAGS, MAX_SYNC
   1223  1.1  mycroft 	jmp	mk_sdtr_done
   1224  1.1  mycroft 
   1225  1.1  mycroft mk_wdtr_16bit:
   1226  1.1  mycroft 	mvi	ARG_1,BUS_16_BIT
   1227  1.1  mycroft mk_wdtr:
   1228  1.1  mycroft 	mvi	DINDIR,1			# extended message
   1229  1.1  mycroft 	mvi	DINDIR,2			# extended message length = 2
   1230  1.1  mycroft 	mvi	DINDIR,3			# WDTR code
   1231  1.1  mycroft 	mov	DINDIR,ARG_1			# bus width
   1232  1.1  mycroft 
   1233  1.1  mycroft 	add	MSG_LEN,-MSG_START+0,DINDEX ret	# update message length
   1234  1.1  mycroft 	
   1235  1.1  mycroft #  Set SCSI bus control signal state.  This also saves the last-written
   1236  1.1  mycroft #  value into a location where the higher-level driver can read it - if
   1237  1.1  mycroft #  it has to send an ABORT or RESET message, then it needs to know this
   1238  1.1  mycroft #  so it can assert ATN without upsetting SCSISIGO.  The new value is
   1239  1.1  mycroft #  expected in SINDEX.  Change the actual state last to avoid contention
   1240  1.1  mycroft #  from the driver.
   1241  1.1  mycroft #
   1242  1.1  mycroft scsisig:
   1243  1.1  mycroft 	mov	SIGSTATE,SINDEX
   1244  1.1  mycroft 	mov	SCSISIGO,SINDEX	ret
   1245  1.1  mycroft 
   1246  1.1  mycroft sdtr_to_rate:
   1247  1.1  mycroft 	call	ndx_dtr				# index scratch space for target
   1248  1.1  mycroft 	shr	A,SINDIR,0x4
   1249  1.1  mycroft 	dec	SINDEX				#Preserve SINDEX
   1250  1.1  mycroft 	and	A,0x7
   1251  1.1  mycroft 	clr	RETURN_1
   1252  1.1  mycroft sdtr_to_rate_loop:
   1253  1.1  mycroft 	test	A,0x0f	jz sdtr_to_rate_done
   1254  1.1  mycroft 	add	RETURN_1,0x18
   1255  1.1  mycroft 	dec	A	
   1256  1.1  mycroft 	jmp	sdtr_to_rate_loop
   1257  1.1  mycroft sdtr_to_rate_done:
   1258  1.1  mycroft 	shr	RETURN_1,0x2
   1259  1.1  mycroft 	add	RETURN_1,0x18	ret
   1260  1.1  mycroft 
   1261  1.1  mycroft return:
   1262  1.1  mycroft 	ret
   1263