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