Home | History | Annotate | Line # | Download | only in aic7xxx
aic7xxx.seq revision 1.3
      1 /*	$NetBSD: aic7xxx.seq,v 1.3 1996/05/20 00:48:45 thorpej Exp $	*/
      2 
      3 /*+M***********************************************************************
      4  *Adaptec 274x/284x/294x device driver for Linux and FreeBSD.
      5  *
      6  *Copyright (c) 1994 John Aycock
      7  *  The University of Calgary Department of Computer Science.
      8  *  All rights reserved.
      9  *
     10  *FreeBSD, Twin, Wide, 2 command per target support, tagged queuing,
     11  *SCB paging and other optimizations:
     12  *Copyright (c) 1994, 1995, 1996 Justin Gibbs. All rights reserved.
     13  *
     14  *Redistribution and use in source and binary forms, with or without
     15  *modification, are permitted provided that the following conditions
     16  *are met:
     17  *1. Redistributions of source code must retain the above copyright
     18  *   notice, this list of conditions, and the following disclaimer.
     19  *2. Redistributions in binary form must reproduce the above copyright
     20  *   notice, this list of conditions and the following disclaimer in the
     21  *   documentation and/or other materials provided with the distribution.
     22  *3. All advertising materials mentioning features or use of this software
     23  *   must display the following acknowledgement:
     24  *     This product includes software developed by the University of Calgary
     25  *     Department of Computer Science and its contributors.
     26  *4. Neither the name of the University nor the names of its contributors
     27  *   may be used to endorse or promote products derived from this software
     28  *   without specific prior written permission.
     29  *
     30  *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     31  *ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     32  *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     33  *ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     34  *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     35  *DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     36  *OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     37  *HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     38  *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     39  *OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     40  *SUCH DAMAGE.
     41  *
     42  *-M************************************************************************/
     43 
     44 VERSION AIC7XXX_SEQ_VER "$NetBSD: aic7xxx.seq,v 1.3 1996/05/20 00:48:45 thorpej Exp $"
     45 
     46 #if defined(__NetBSD__)
     47 #include "../../../../dev/ic/aic7xxxreg.h"
     48 #elif defined(__FreeBSD__)
     49 #include "../../dev/aic7xxx/aic7xxx_reg.h"
     50 #endif
     51 
     52 /*
     53  * We can't just use ACCUM in the sequencer code because it
     54  * must be treated specially by the assembler, and it currently
     55  * looks for the symbol 'A'.  This is the only register defined in
     56  * the assembler's symbol space.
     57  */
     58 A = ACCUM
     59 
     60 /* After starting the selection hardware, we check for reconnecting targets
     61  * as well as for our selection to complete just in case the reselection wins
     62  * bus arbitration.  The problem with this is that we must keep track of the
     63  * SCB that we've already pulled from the QINFIFO and started the selection
     64  * on just in case the reselection wins so that we can retry the selection at
     65  * a later time.  This problem cannot be resolved by holding a single entry
     66  * in scratch ram since a reconnecting target can request sense and this will
     67  * create yet another SCB waiting for selection.  The solution used here is to
     68  * use byte 27 of the SCB as a psuedo-next pointer and to thread a list
     69  * of SCBs that are awaiting selection.  Since 0-0xfe are valid SCB offsets,
     70  * SCB_LIST_NULL is 0xff which is out of range.  The kernel driver must
     71  * add an entry to this list everytime a request sense occurs.  The sequencer
     72  * will automatically consume the entries.
     73  */
     74 
     75 /*
     76  * We assume that the kernel driver may reset us at any time, even in the
     77  * middle of a DMA, so clear DFCNTRL too.
     78  */
     79 reset:
     80 	clr	DFCNTRL
     81 	clr	SCSISIGO		/* De-assert BSY */
     82 /*
     83  * We jump to start after every bus free.
     84  */
     85 start:
     86 	and	FLAGS,0x0f		/* clear target specific flags */
     87 	mvi	SCSISEQ,ENRSELI		/* Always allow reselection */
     88 poll_for_work:
     89 	/*
     90 	 * Are we a twin channel device?
     91 	 * For fairness, we check the other bus first,
     92 	 * since we just finished a transaction on the
     93 	 * current channel.
     94 	 */
     95 	test	FLAGS,TWIN_BUS	jz start2
     96 	xor	SBLKCTL,SELBUSB			/* Toggle to the other bus */
     97 	test	SSTAT0,SELDI	jnz reselect
     98 	xor	SBLKCTL,SELBUSB			/* Toggle to the original bus */
     99 start2:
    100 	test	SSTAT0,SELDI	jnz reselect
    101 	cmp	WAITING_SCBH,SCB_LIST_NULL jne start_waiting
    102 	mov	A, QCNTMASK
    103 	test	QINCNT,A	jz poll_for_work
    104 
    105 /*
    106  * We have at least one queued SCB now and we don't have any
    107  * SCBs in the list of SCBs awaiting selection.  Set the SCB
    108  * pointer from the FIFO so we see the right bank of SCB
    109  * registers.
    110  */
    111 	mov	SCBPTR,QINFIFO
    112 
    113 /*
    114  * See if there is not already an active SCB for this target.  This code
    115  * locks out on a per target basis instead of target/lun.  Although this
    116  * is not ideal for devices that have multiple luns active at the same
    117  * time, it is faster than looping through all SCB's looking for active
    118  * commands.  It may be benificial to make findscb a more general procedure
    119  * to see if the added cost of the search is negligible.  This code also
    120  * assumes that the kernel driver will clear the active flags on board
    121  * initialization, board reset, and a target SELTO.  Tagged commands
    122  * don't set the active bits since you can queue more than one command
    123  * at a time.  We do, however, look to see if there are any non-tagged
    124  * I/Os in progress, and requeue the command if there are.  Tagged and
    125  * non-tagged commands cannot be mixed to a single target.
    126  */
    127 
    128 test_busy:
    129 	mov	FUNCTION1,SCB_TCL
    130 	mov	A,FUNCTION1
    131 	test	SCB_TCL,0x88	jz test_a	/* Id < 8 && A channel */
    132 
    133 	test	ACTIVE_B,A	jnz requeue
    134 	test	SCB_CONTROL,TAG_ENB	jnz start_scb
    135 	/* Mark the current target as busy */
    136 	or	ACTIVE_B,A
    137 	jmp	start_scb
    138 
    139 /* Place the currently active SCB back on the queue for later processing */
    140 requeue:
    141 	mov	QINFIFO, SCBPTR
    142 	jmp	poll_for_work
    143 
    144 /*
    145  * Pull the first entry off of the waiting for selection list
    146  * We don't have to "test_busy" because only transactions that
    147  * have passed that test can be in the waiting_scb list.
    148  */
    149 start_waiting:
    150 	mov	SCBPTR,WAITING_SCBH
    151 	jmp	start_scb2
    152 
    153 test_a:
    154 	test	ACTIVE_A,A jnz requeue
    155 	test	SCB_CONTROL,TAG_ENB jnz start_scb
    156 	/* Mark the current target as busy */
    157 	or	ACTIVE_A,A
    158 
    159 start_scb:
    160 	mov	SCB_NEXT,WAITING_SCBH
    161 	mov	WAITING_SCBH, SCBPTR
    162 start_scb2:
    163 	and	SINDEX,0xf7,SBLKCTL	/* Clear the channel select bit */
    164 	and	A,0x08,SCB_TCL		/* Get new channel bit */
    165 	or	SINDEX,A
    166 	mov	SBLKCTL,SINDEX		/* select channel */
    167 	mov	SCB_TCL	call initialize_scsiid
    168 
    169 /*
    170  * Enable selection phase as an initiator, and do automatic ATN
    171  * after the selection.  We do this now so that we can overlap the
    172  * rest of our work to set up this target with the arbitration and
    173  * selection bus phases.
    174  */
    175 start_selection:
    176 	mvi	SCSISEQ,0x58		/* ENSELO|ENAUTOATNO|ENRSELI */
    177 
    178 /*
    179  * As soon as we get a successful selection, the target should go
    180  * into the message out phase since we have ATN asserted.  Prepare
    181  * the message to send.
    182  *
    183  * Messages are stored in scratch RAM starting with a length byte
    184  * followed by the message itself.
    185  */
    186 	test	SCB_CMDLEN,0xff jnz mk_identify	/* 0 Length Command? */
    187 
    188 /*
    189  * The kernel has sent us an SCB with no command attached.  This implies
    190  * that the kernel wants to send a message of some sort to this target,
    191  * so we interrupt the driver, allow it to fill the message buffer, and
    192  * then go back into the arbitration loop
    193  */
    194 	mvi     INTSTAT,AWAITING_MSG
    195 	jmp     wait_for_selection
    196 
    197 mk_identify:
    198 	and	A,DISCENB,SCB_CONTROL	/* mask off disconnect privledge */
    199 
    200 	and	MSG0,0x7,SCB_TCL	/* lun */
    201 	or	MSG0,A			/* or in disconnect privledge */
    202 	or	MSG0,MSG_IDENTIFY
    203 	mvi	MSG_LEN, 1
    204 
    205 	test	SCB_CONTROL,0xb0 jz  !message	/* WDTR, SDTR or TAG?? */
    206 /*
    207  * Send a tag message if TAG_ENB is set in the SCB control block.
    208  * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
    209  */
    210 
    211 mk_tag:
    212 	mvi	DINDEX, MSG1
    213 	test	SCB_CONTROL,TAG_ENB jz mk_tag_done
    214 	and	DINDIR,0x23,SCB_CONTROL
    215 	mov	DINDIR,SCB_TAG
    216 
    217 	add	MSG_LEN,COMP_MSG0,DINDEX	/* update message length */
    218 
    219 mk_tag_done:
    220 
    221 	test	SCB_CONTROL,0x90 jz !message	/* NEEDWDTR|NEEDSDTR */
    222 	mov	DINDEX	call mk_dtr	/* build DTR message if needed */
    223 
    224 !message:
    225 wait_for_selection:
    226 	test	SSTAT0,SELDO	jnz select
    227 	test	SSTAT0,SELDI	jz wait_for_selection
    228 
    229 /*
    230  * Reselection has been initiated by a target. Make a note that we've been
    231  * reselected, but haven't seen an IDENTIFY message from the target
    232  * yet.
    233  */
    234 reselect:
    235 	clr	MSG_LEN		/* Don't have anything in the mesg buffer */
    236 	mov	SELID		call initialize_scsiid
    237 	or	FLAGS,RESELECTED
    238 	jmp	select2
    239 
    240 /*
    241  * After the selection, remove this SCB from the "waiting for selection"
    242  * list.  This is achieved by simply moving our "next" pointer into
    243  * WAITING_SCBH.  Our next pointer will be set to null the next time this
    244  * SCB is used, so don't bother with it now.
    245  */
    246 select:
    247 	mov	WAITING_SCBH,SCB_NEXT
    248 	or	FLAGS,SELECTED
    249 select2:
    250 /*
    251  * Set CLRCHN here before the target has entered a data transfer mode -
    252  * with synchronous SCSI, if you do it later, you blow away some
    253  * data in the SCSI FIFO that the target has already sent to you.
    254  */
    255 	or	SXFRCTL0,CLRCHN
    256 /*
    257  * Initialize SCSIRATE with the appropriate value for this target.
    258  */
    259 	call	ndx_dtr
    260 	mov	SCSIRATE,SINDIR
    261 
    262 	mvi	SCSISEQ,ENAUTOATNP		/*
    263 						 * ATN on parity errors
    264 						 * for "in" phases
    265 						 */
    266 	mvi	CLRSINT1,CLRBUSFREE
    267 	mvi	CLRSINT0,0x60			/* CLRSELDI|CLRSELDO */
    268 
    269 /*
    270  * Main loop for information transfer phases.  If BSY is false, then
    271  * we have a bus free condition, expected or not.  Otherwise, wait
    272  * for the target to assert REQ before checking MSG, C/D and I/O
    273  * for the bus phase.
    274  *
    275  */
    276 ITloop:
    277 	test	SSTAT1,BUSFREE	jnz p_busfree
    278 	test	SSTAT1,REQINIT	jz ITloop
    279 
    280 	and	A,PHASE_MASK,SCSISIGI
    281 	mov	LASTPHASE,A
    282 	mov	SCSISIGO,A
    283 
    284 	cmp	ALLZEROS,A	je p_dataout
    285 	cmp	A,P_DATAIN	je p_datain
    286 	cmp	A,P_COMMAND	je p_command
    287 	cmp	A,P_MESGOUT	je p_mesgout
    288 	cmp	A,P_STATUS	je p_status
    289 	cmp	A,P_MESGIN	je p_mesgin
    290 
    291 	mvi	INTSTAT,BAD_PHASE	/* unknown phase - signal driver */
    292 
    293 p_dataout:
    294 	mvi	DMAPARAMS,0x7d			/*
    295 						 * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
    296 						 * DIRECTION|FIFORESET
    297 						 */
    298 	jmp	data_phase_init
    299 
    300 /*
    301  * If we re-enter the data phase after going through another phase, the
    302  * STCNT may have been cleared, so restore it from the residual field.
    303  */
    304 data_phase_reinit:
    305 	mov	STCNT0,SCB_RESID_DCNT0
    306 	mov	STCNT1,SCB_RESID_DCNT1
    307 	mov	STCNT2,SCB_RESID_DCNT2
    308 	jmp	data_phase_loop
    309 
    310 p_datain:
    311 	mvi	DMAPARAMS,0x79		/*
    312 					 * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
    313 					 * !DIRECTION|FIFORESET
    314 					 */
    315 data_phase_init:
    316 	call	assert
    317 
    318 	test	FLAGS, DPHASE	jnz data_phase_reinit
    319 	call	sg_scb2ram
    320 	or	FLAGS, DPHASE		/* We have seen a data phase */
    321 
    322 data_phase_loop:
    323 /* If we are the last SG block, don't set wideodd. */
    324 	cmp	SG_COUNT,0x01 jne data_phase_wideodd
    325 	and	DMAPARAMS, 0xbf		/* Turn off WIDEODD */
    326 data_phase_wideodd:
    327 	mov	DMAPARAMS  call dma
    328 
    329 /* Exit if we had an underrun */
    330 	test	SSTAT0,SDONE	jz data_phase_finish /* underrun STCNT != 0 */
    331 
    332 /*
    333  * Advance the scatter-gather pointers if needed
    334  */
    335 sg_advance:
    336 	dec	SG_COUNT	/* one less segment to go */
    337 
    338 	test	SG_COUNT, 0xff	jz data_phase_finish /* Are we done? */
    339 
    340 	clr	A			/* add sizeof(struct scatter) */
    341 	add	SG_NEXT0,SG_SIZEOF,SG_NEXT0
    342 	adc	SG_NEXT1,A,SG_NEXT1
    343 
    344 /*
    345  * Load a struct scatter and set up the data address and length.
    346  * If the working value of the SG count is nonzero, then
    347  * we need to load a new set of values.
    348  *
    349  * This, like all DMA's, assumes little-endian host data storage.
    350  */
    351 sg_load:
    352 	clr	HCNT2
    353 	clr	HCNT1
    354 	mvi	HCNT0,SG_SIZEOF
    355 
    356 	mov	HADDR0,SG_NEXT0
    357 	mov	HADDR1,SG_NEXT1
    358 	mov	HADDR2,SG_NEXT2
    359 	mov	HADDR3,SG_NEXT3
    360 
    361 	or	DFCNTRL,0xd			/* HDMAEN|DIRECTION|FIFORESET */
    362 
    363 /*
    364  * Wait for DMA from host memory to data FIFO to complete, then disable
    365  * DMA and wait for it to acknowledge that it's off.
    366  */
    367 dma_finish:
    368 	test	DFSTATUS,HDONE	jz dma_finish
    369 	/* Turn off DMA preserving WIDEODD */
    370 	and	DFCNTRL,WIDEODD
    371 dma_finish2:
    372 	test	DFCNTRL,HDMAENACK jnz dma_finish2
    373 
    374 /*
    375  * Copy data from FIFO into SCB data pointer and data count.  This assumes
    376  * that the struct scatterlist has this structure (this and sizeof(struct
    377  * scatterlist) == 12 are asserted in aic7xxx.c for the Linux driver):
    378  *
    379  *	struct scatterlist {
    380  *		char *address;		four bytes, little-endian order
    381  *		...			four bytes, ignored
    382  *		unsigned short length;	two bytes, little-endian order
    383  *	}
    384  *
    385  *
    386  * In FreeBSD, the scatter list entry is only 8 bytes.
    387  *
    388  * struct ahc_dma_seg {
    389  *       physaddr addr;                  four bytes, little-endian order
    390  *       long    len;                    four bytes, little endian order
    391  * };
    392  */
    393 
    394 	mov	HADDR0,DFDAT
    395 	mov	HADDR1,DFDAT
    396 	mov	HADDR2,DFDAT
    397 	mov	HADDR3,DFDAT
    398 /*
    399  * For Linux, we must throw away four bytes since there is a 32bit gap
    400  * in the middle of a struct scatterlist.
    401  */
    402 #ifdef __linux__
    403 	mov	NONE,DFDAT
    404 	mov	NONE,DFDAT
    405 	mov	NONE,DFDAT
    406 	mov	NONE,DFDAT
    407 #endif
    408 	mov	HCNT0,DFDAT
    409 	mov	HCNT1,DFDAT
    410 	mov	HCNT2,DFDAT
    411 
    412 /* Load STCNT as well.  It is a mirror of HCNT */
    413 	mov	STCNT0,HCNT0
    414 	mov	STCNT1,HCNT1
    415 	mov	STCNT2,HCNT2
    416         test    SSTAT1,PHASEMIS  jz data_phase_loop
    417 
    418 data_phase_finish:
    419 /*
    420  * After a DMA finishes, save the SG and STCNT residuals back into the SCB
    421  * We use STCNT instead of HCNT, since it's a reflection of how many bytes
    422  * were transferred on the SCSI (as opposed to the host) bus.
    423  */
    424 	mov	SCB_RESID_DCNT0,STCNT0
    425 	mov	SCB_RESID_DCNT1,STCNT1
    426 	mov	SCB_RESID_DCNT2,STCNT2
    427 	mov	SCB_RESID_SGCNT, SG_COUNT
    428 	jmp	ITloop
    429 
    430 /*
    431  * Command phase.  Set up the DMA registers and let 'er rip.
    432  */
    433 p_command:
    434 	call	assert
    435 
    436 /*
    437  * Load HADDR and HCNT.
    438  */
    439 	mov	HADDR0, SCB_CMDPTR0
    440 	mov	HADDR1, SCB_CMDPTR1
    441 	mov	HADDR2, SCB_CMDPTR2
    442 	mov	HADDR3, SCB_CMDPTR3
    443 	mov	HCNT0, SCB_CMDLEN
    444 	clr	HCNT1
    445 	clr	HCNT2
    446 
    447 	mov	STCNT0, HCNT0
    448 	mov	STCNT1, HCNT1
    449 	mov	STCNT2, HCNT2
    450 
    451 	mvi	0x3d		call dma	# SCSIEN|SDMAEN|HDMAEN|
    452 						#   DIRECTION|FIFORESET
    453 	jmp	ITloop
    454 
    455 /*
    456  * Status phase.  Wait for the data byte to appear, then read it
    457  * and store it into the SCB.
    458  */
    459 p_status:
    460 	mvi	SCB_TARGET_STATUS	call inb_first
    461 	jmp	mesgin_done
    462 
    463 /*
    464  * Message out phase.  If there is not an active message, but the target
    465  * took us into this phase anyway, build a no-op message and send it.
    466  */
    467 p_mesgout:
    468 	test	MSG_LEN, 0xff	jnz  p_mesgout_start
    469 	mvi	MSG_NOP		call mk_mesg	/* build NOP message */
    470 
    471 p_mesgout_start:
    472 /*
    473  * Set up automatic PIO transfer from MSG0.  Bit 3 in
    474  * SXFRCTL0 (SPIOEN) is already on.
    475  */
    476 	mvi	SINDEX,MSG0
    477 	mov	DINDEX,MSG_LEN
    478 
    479 /*
    480  * When target asks for a byte, drop ATN if it's the last one in
    481  * the message.  Otherwise, keep going until the message is exhausted.
    482  *
    483  * Keep an eye out for a phase change, in case the target issues
    484  * a MESSAGE REJECT.
    485  */
    486 p_mesgout_loop:
    487 	test	SSTAT1,PHASEMIS	jnz p_mesgout_phasemis
    488 	test	SSTAT0,SPIORDY	jz p_mesgout_loop
    489 	cmp	DINDEX,1	jne p_mesgout_outb	/* last byte? */
    490 	mvi	CLRSINT1,CLRATNO			/* drop ATN */
    491 p_mesgout_outb:
    492 	dec	DINDEX
    493 	or	CLRSINT0, CLRSPIORDY
    494 	mov	SCSIDATL,SINDIR
    495 
    496 p_mesgout4:
    497 	test	DINDEX,0xff	jnz p_mesgout_loop
    498 
    499 /*
    500  * If the next bus phase after ATN drops is a message out, it means
    501  * that the target is requesting that the last message(s) be resent.
    502  */
    503 p_mesgout_snoop:
    504 	test	SSTAT1,BUSFREE	jnz p_mesgout_done
    505 	test	SSTAT1,REQINIT	jz p_mesgout_snoop
    506 
    507 	test	SSTAT1,PHASEMIS	jnz p_mesgout_done
    508 
    509 	or	SCSISIGO,ATNO			/* turn on ATNO */
    510 
    511 	jmp	ITloop
    512 
    513 p_mesgout_phasemis:
    514 	mvi	CLRSINT1,CLRATNO	/* Be sure to turn ATNO off */
    515 p_mesgout_done:
    516 	clr	MSG_LEN			/* no active msg */
    517 	jmp	ITloop
    518 
    519 /*
    520  * Message in phase.  Bytes are read using Automatic PIO mode.
    521  */
    522 p_mesgin:
    523 	mvi	A		call inb_first	/* read the 1st message byte */
    524 	mov	REJBYTE,A			/* save it for the driver */
    525 
    526 	test	A,MSG_IDENTIFY		jnz mesgin_identify
    527 	cmp	A,MSG_DISCONNECT	je mesgin_disconnect
    528 	cmp	A,MSG_SDPTRS		je mesgin_sdptrs
    529 	cmp	ALLZEROS,A		je mesgin_complete
    530 	cmp	A,MSG_RDPTRS		je mesgin_rdptrs
    531 	cmp	A,MSG_EXTENDED		je mesgin_extended
    532 	cmp	A,MSG_REJECT		je mesgin_reject
    533 
    534 rej_mesgin:
    535 /*
    536  * We have no idea what this message in is, and there's no way
    537  * to pass it up to the kernel, so we issue a message reject and
    538  * hope for the best.  Since we're now using manual PIO mode to
    539  * read in the message, there should no longer be a race condition
    540  * present when we assert ATN.  In any case, rejection should be a
    541  * rare occurrence - signal the driver when it happens.
    542  */
    543 	or	SCSISIGO,ATNO			/* turn on ATNO */
    544 	mvi	INTSTAT,SEND_REJECT		/* let driver know */
    545 
    546 	mvi	MSG_REJECT	call mk_mesg
    547 
    548 mesgin_done:
    549 	call	inb_last			/*ack & turn auto PIO back on*/
    550 	jmp	ITloop
    551 
    552 
    553 mesgin_complete:
    554 /*
    555  * We got a "command complete" message, so put the SCB_TAG into QUEUEOUT,
    556  * and trigger a completion interrupt.  Check status for non zero return
    557  * and interrupt driver if needed.  This allows the driver to interpret
    558  * errors only when they occur instead of always uploading the scb.  If
    559  * the status is SCSI_CHECK, the driver will download a new scb requesting
    560  * sense to replace the old one, modify the "waiting for selection" SCB list
    561  * and set RETURN_1 to SEND_SENSE.  If RETURN_1 is set to SEND_SENSE the
    562  * sequencer imediately jumps to main loop where it will run down the waiting
    563  * SCB list and process the sense request.  If the kernel driver does not
    564  * wish to request sense, it need only clear RETURN_1, and the command is
    565  * allowed to complete.  We don't bother to post to the QOUTFIFO in the
    566  * error case since it would require extra work in the kernel driver to
    567  * ensure that the entry was removed before the command complete code tried
    568  * processing it.
    569  *
    570  * First check for residuals
    571  */
    572 	test	SCB_RESID_SGCNT,0xff	jz check_status
    573 /*
    574  * If we have a residual count, interrupt and tell the host.  Other
    575  * alternatives are to pause the sequencer on all command completes (yuck),
    576  * dma the resid directly to the host (slick, we may have space to do it now)
    577  * or have the sequencer pause itself when it encounters a non-zero resid
    578  * (unecessary pause just to flag the command -yuck-, but takes one instruction
    579  * and since it shouldn't happen that often is good enough for our purposes).
    580  */
    581 resid:
    582 	mvi	INTSTAT,RESIDUAL
    583 
    584 check_status:
    585 	test	SCB_TARGET_STATUS,0xff	jz status_ok	/* Good Status? */
    586 	mvi	INTSTAT,BAD_STATUS			/* let driver know */
    587 	cmp	RETURN_1, SEND_SENSE	jne status_ok
    588 	jmp	mesgin_done
    589 
    590 status_ok:
    591 /* First, mark this target as free. */
    592 	test	SCB_CONTROL,TAG_ENB jnz test_immediate	/*
    593 							 * Tagged commands
    594 							 * don't busy the
    595 							 * target.
    596 							 */
    597 	mov	FUNCTION1,SCB_TCL
    598 	mov	A,FUNCTION1
    599 	test	SCB_TCL,0x88 jz clear_a
    600 	xor	ACTIVE_B,A
    601 	jmp	test_immediate
    602 
    603 clear_a:
    604 	xor	ACTIVE_A,A
    605 
    606 test_immediate:
    607 	test    SCB_CMDLEN,0xff jnz complete  /* Immediate message complete */
    608 /*
    609  * Pause the sequencer until the driver gets around to handling the command
    610  * complete.  This is so that any action that might require carefull timing
    611  * with the completion of this command can occur.
    612  */
    613 	mvi	INTSTAT,IMMEDDONE
    614 	jmp	start
    615 complete:
    616 	mov	QOUTFIFO,SCB_TAG
    617 	mvi	INTSTAT,CMDCMPLT
    618 	jmp	mesgin_done
    619 
    620 
    621 /*
    622  * Is it an extended message?  We only support the synchronous and wide data
    623  * transfer request messages, which will probably be in response to
    624  * WDTR or SDTR message outs from us.  If it's not SDTR or WDTR, reject it -
    625  * apparently this can be done after any message in byte, according
    626  * to the SCSI-2 spec.
    627  */
    628 mesgin_extended:
    629 	mvi	ARG_1		call inb_next	/* extended message length */
    630 	mvi	REJBYTE_EXT	call inb_next	/* extended message code */
    631 
    632 	cmp	REJBYTE_EXT,MSG_SDTR	je p_mesginSDTR
    633 	cmp	REJBYTE_EXT,MSG_WDTR	je p_mesginWDTR
    634 	jmp	rej_mesgin
    635 
    636 p_mesginWDTR:
    637 	cmp	ARG_1,2		jne rej_mesgin	/* extended mesg length=2 */
    638 	mvi	ARG_1		call inb_next	/* Width of bus */
    639 	mvi	INTSTAT,WDTR_MSG		/* let driver know */
    640 	test	RETURN_1,0xff jz mesgin_done	/* Do we need to send WDTR? */
    641 	cmp	RETURN_1,SEND_REJ je rej_mesgin /*
    642 						 * Bus width was too large
    643 						 * Reject it.
    644 						 */
    645 
    646 /* We didn't initiate the wide negotiation, so we must respond to the request */
    647 	and	RETURN_1,0x7f			/* Clear the SEND_WDTR Flag */
    648 	mvi	DINDEX,MSG0
    649 	mvi	MSG0	call mk_wdtr		/* build WDTR message */
    650 	or	SCSISIGO,ATNO			/* turn on ATNO */
    651 	jmp	mesgin_done
    652 
    653 p_mesginSDTR:
    654 	cmp	ARG_1,3		jne rej_mesgin	/* extended mesg length=3 */
    655 	mvi	ARG_1		call inb_next	/* xfer period */
    656 	mvi	A		call inb_next	/* REQ/ACK offset */
    657 	mvi	INTSTAT,SDTR_MSG		/* call driver to convert */
    658 
    659 	test	RETURN_1,0xff	jz mesgin_done  /* Do we need to mk_sdtr/rej */
    660 	cmp	RETURN_1,SEND_REJ je rej_mesgin /*
    661 						 * Requested SDTR too small
    662 						 * Reject it.
    663 						 */
    664 	clr	ARG_1				/* Use the scratch ram rate */
    665 	mvi	DINDEX, MSG0
    666 	mvi     MSG0     call mk_sdtr
    667 	or	SCSISIGO,ATNO			/* turn on ATNO */
    668 	jmp	mesgin_done
    669 
    670 /*
    671  * Is it a disconnect message?  Set a flag in the SCB to remind us
    672  * and await the bus going free.
    673  */
    674 mesgin_disconnect:
    675 	or	SCB_CONTROL,DISCONNECTED
    676 	test	FLAGS, PAGESCBS jz mesgin_done
    677 /*
    678  * Link this SCB into the DISCONNECTED list.  This list holds the
    679  * candidates for paging out an SCB if one is needed for a new command.
    680  * Modifying the disconnected list is a critical(pause dissabled) section.
    681  */
    682 	mvi	SCB_PREV, SCB_LIST_NULL
    683 	mvi	SEQCTL,0x50			/* PAUSEDIS|FASTMODE */
    684 	mov	SCB_NEXT, DISCONNECTED_SCBH
    685 	mov	DISCONNECTED_SCBH, SCBPTR
    686 	cmp	SCB_NEXT,SCB_LIST_NULL je linkdone
    687 	mov	SCBPTR,SCB_NEXT
    688 	mov	SCB_PREV,DISCONNECTED_SCBH
    689 	mov	SCBPTR,DISCONNECTED_SCBH
    690 linkdone:
    691 	mvi	SEQCTL,0x10			/* !PAUSEDIS|FASTMODE */
    692 	jmp	mesgin_done
    693 
    694 /*
    695  * Save data pointers message?  Copy working values into the SCB,
    696  * usually in preparation for a disconnect.
    697  */
    698 mesgin_sdptrs:
    699 	call	sg_ram2scb
    700 	jmp	mesgin_done
    701 
    702 /*
    703  * Restore pointers message?  Data pointers are recopied from the
    704  * SCB anytime we enter a data phase for the first time, so all
    705  * we need to do is clear the DPHASE flag and let the data phase
    706  * code do the rest.
    707  */
    708 mesgin_rdptrs:
    709 	and	FLAGS,0xef			/*
    710 						 * !DPHASE we'll reload them
    711 						 * the next time through
    712 						 */
    713 	jmp	mesgin_done
    714 
    715 /*
    716  * Identify message?  For a reconnecting target, this tells us the lun
    717  * that the reconnection is for - find the correct SCB and switch to it,
    718  * clearing the "disconnected" bit so we don't "find" it by accident later.
    719  */
    720 mesgin_identify:
    721 	test	A,0x78	jnz rej_mesgin	/*!DiscPriv|!LUNTAR|!Reserved*/
    722 
    723 	and	A,0x07			/* lun in lower three bits */
    724 	or      SAVED_TCL,A,SELID
    725 	and     SAVED_TCL,0xf7
    726 	and     A,SELBUSB,SBLKCTL	/* B Channel?? */
    727 	or      SAVED_TCL,A
    728 	call	inb_last		/* ACK */
    729 
    730 /*
    731  * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
    732  * If we get one, we use the tag returned to switch to find the proper
    733  * SCB.  With SCB paging, this requires using findSCB for both tagged
    734  * and non-tagged transactions since the SCB may exist in any slot.
    735  * If we're not using SCB paging, we can use the tag as the direct
    736  * index to the SCB.
    737  */
    738 	mvi	ARG_1,SCB_LIST_NULL	/* Default to no-tag */
    739 snoop_tag_loop:
    740 	test	SSTAT1,BUSFREE	jnz use_findSCB
    741 	test	SSTAT1,REQINIT	jz snoop_tag_loop
    742 	test	SSTAT1,PHASEMIS	jnz use_findSCB
    743 	mvi	A		call inb_first
    744 	cmp	A,MSG_SIMPLE_TAG jne use_findSCB
    745 get_tag:
    746 	mvi	ARG_1	call inb_next	/* tag value */
    747 /*
    748  * See if the tag is in range.  The tag is < SCBCOUNT if we add
    749  * the complement of SCBCOUNT to the incomming tag and there is
    750  * no carry.
    751  */
    752 	mov	A,COMP_SCBCOUNT
    753 	add	SINDEX,A,ARG_1
    754 	jc	abort_tag
    755 
    756 /*
    757  * Ensure that the SCB the tag points to is for an SCB transaction
    758  * to the reconnecting target.
    759  */
    760 	test	FLAGS, PAGESCBS	jz index_by_tag
    761 	call	inb_last			/* Ack Tag */
    762 use_findSCB:
    763 	mov	ALLZEROS	call findSCB	  /* Have to search */
    764 setup_SCB:
    765 	and	SCB_CONTROL,0xfb	  /* clear disconnect bit in SCB */
    766 	or	FLAGS,IDENTIFY_SEEN	  /* make note of IDENTIFY */
    767 	jmp	ITloop
    768 index_by_tag:
    769 	mov	SCBPTR,ARG_1
    770 	mov	A,SAVED_TCL
    771 	cmp	SCB_TCL,A		jne abort_tag
    772 	test	SCB_CONTROL,TAG_ENB	jz  abort_tag
    773 	call	inb_last			/* Ack Successful tag */
    774 	jmp	setup_SCB
    775 
    776 abort_tag:
    777 	or	SCSISIGO,ATNO			/* turn on ATNO */
    778 	mvi	INTSTAT,ABORT_TAG 		/* let driver know */
    779 	mvi	MSG_ABORT_TAG	call mk_mesg	/* ABORT TAG message */
    780 	jmp	mesgin_done
    781 
    782 /*
    783  * Message reject?  Let the kernel driver handle this.  If we have an
    784  * outstanding WDTR or SDTR negotiation, assume that it's a response from
    785  * the target selecting 8bit or asynchronous transfer, otherwise just ignore
    786  * it since we have no clue what it pertains to.
    787  */
    788 mesgin_reject:
    789 	mvi	INTSTAT, REJECT_MSG
    790 	jmp	mesgin_done
    791 
    792 /*
    793  * [ ADD MORE MESSAGE HANDLING HERE ]
    794  */
    795 
    796 /*
    797  * Bus free phase.  It might be useful to interrupt the device
    798  * driver if we aren't expecting this.  For now, make sure that
    799  * ATN isn't being asserted and look for a new command.
    800  */
    801 p_busfree:
    802 	mvi	CLRSINT1,CLRATNO
    803 	clr	LASTPHASE
    804 
    805 /*
    806  * if this is an immediate command, perform a psuedo command complete to
    807  * notify the driver.
    808  */
    809 	test	SCB_CMDLEN,0xff	jz status_ok
    810 	jmp	start
    811 
    812 /*
    813  * Locking the driver out, build a one-byte message passed in SINDEX
    814  * if there is no active message already.  SINDEX is returned intact.
    815  */
    816 mk_mesg:
    817 	mvi	SEQCTL,0x50			/* PAUSEDIS|FASTMODE */
    818 	test	MSG_LEN,0xff	jz mk_mesg1	/* Should always succeed */
    819 
    820 	/*
    821 	 * Hmmm.  For some reason the mesg buffer is in use.
    822 	 * Tell the driver.  It should look at SINDEX to find
    823 	 * out what we wanted to use the buffer for and resolve
    824 	 * the conflict.
    825 	 */
    826 	mvi	SEQCTL,0x10			/* !PAUSEDIS|FASTMODE */
    827 	mvi	INTSTAT,MSG_BUFFER_BUSY
    828 
    829 mk_mesg1:
    830 	mvi	MSG_LEN,1		/* length = 1 */
    831 	mov	MSG0,SINDEX		/* 1-byte message */
    832 	mvi	SEQCTL,0x10	ret	/* !PAUSEDIS|FASTMODE */
    833 
    834 /*
    835  * Functions to read data in Automatic PIO mode.
    836  *
    837  * According to Adaptec's documentation, an ACK is not sent on input from
    838  * the target until SCSIDATL is read from.  So we wait until SCSIDATL is
    839  * latched (the usual way), then read the data byte directly off the bus
    840  * using SCSIBUSL.  When we have pulled the ATN line, or we just want to
    841  * acknowledge the byte, then we do a dummy read from SCISDATL.  The SCSI
    842  * spec guarantees that the target will hold the data byte on the bus until
    843  * we send our ACK.
    844  *
    845  * The assumption here is that these are called in a particular sequence,
    846  * and that REQ is already set when inb_first is called.  inb_{first,next}
    847  * use the same calling convention as inb.
    848  */
    849 
    850 inb_next:
    851 	or	CLRSINT0, CLRSPIORDY
    852 	mov	NONE,SCSIDATL			/*dummy read from latch to ACK*/
    853 inb_next_wait:
    854 	test	SSTAT1,PHASEMIS	jnz mesgin_phasemis
    855 	test	SSTAT0,SPIORDY	jz inb_next_wait /* wait for next byte */
    856 inb_first:
    857 	mov	DINDEX,SINDEX
    858 	mov	DINDIR,SCSIBUSL	ret		/*read byte directly from bus*/
    859 inb_last:
    860 	mov	NONE,SCSIDATL ret		/*dummy read from latch to ACK*/
    861 
    862 mesgin_phasemis:
    863 /*
    864  * We expected to receive another byte, but the target changed phase
    865  */
    866 	mvi	INTSTAT, MSGIN_PHASEMIS
    867 	jmp	ITloop
    868 
    869 /*
    870  * DMA data transfer.  HADDR and HCNT must be loaded first, and
    871  * SINDEX should contain the value to load DFCNTRL with - 0x3d for
    872  * host->scsi, or 0x39 for scsi->host.  The SCSI channel is cleared
    873  * during initialization.
    874  */
    875 dma:
    876 	mov	DFCNTRL,SINDEX
    877 dma1:
    878 	test	SSTAT0,DMADONE	jnz dma3
    879 	test	SSTAT1,PHASEMIS	jz dma1		/* ie. underrun */
    880 
    881 /*
    882  * We will be "done" DMAing when the transfer count goes to zero, or
    883  * the target changes the phase (in light of this, it makes sense that
    884  * the DMA circuitry doesn't ACK when PHASEMIS is active).  If we are
    885  * doing a SCSI->Host transfer, the data FIFO should be flushed auto-
    886  * magically on STCNT=0 or a phase change, so just wait for FIFO empty
    887  * status.
    888  */
    889 dma3:
    890 	test	SINDEX,DIRECTION	jnz dma5
    891 dma4:
    892 	test	DFSTATUS,FIFOEMP	jz dma4
    893 
    894 /*
    895  * Now shut the DMA enables off and make sure that the DMA enables are
    896  * actually off first lest we get an ILLSADDR.
    897  */
    898 dma5:
    899 	/* disable DMA, but maintain WIDEODD */
    900 	and	DFCNTRL,WIDEODD
    901 dma6:
    902 	test	DFCNTRL,0x38	jnz dma6  /* SCSIENACK|SDMAENACK|HDMAENACK */
    903 
    904 	ret
    905 
    906 /*
    907  * Common SCSI initialization for selection and reselection.  Expects
    908  * the target SCSI ID to be in the upper four bits of SINDEX, and A's
    909  * contents are stomped on return.
    910  */
    911 initialize_scsiid:
    912 	and	SINDEX,0xf0		/* Get target ID */
    913 	and	A,0x0f,SCSIID
    914 	or	SINDEX,A
    915 	mov	SCSIID,SINDEX ret
    916 
    917 /*
    918  * Assert that if we've been reselected, then we've seen an IDENTIFY
    919  * message.
    920  */
    921 assert:
    922 	test	FLAGS,RESELECTED	jz return	/* reselected? */
    923 	test	FLAGS,IDENTIFY_SEEN	jnz return	/* seen IDENTIFY? */
    924 
    925 	mvi	INTSTAT,NO_IDENT 	ret	/* no - cause a kernel panic */
    926 
    927 /*
    928  * Locate the SCB matching the target ID/channel/lun in SAVED_TCL, and the tag
    929  * value in ARG_1.  If ARG_1 == SCB_LIST_NULL, we're looking for a non-tagged
    930  * SCB.  Have the kernel print a warning message if it can't be found, and
    931  * generate an ABORT/ABORT_TAG message to the target.  SINDEX should be
    932  * cleared on call.
    933  */
    934 findSCB:
    935 	mov	A,SAVED_TCL
    936 	mov	SCBPTR,SINDEX			/* switch to next SCB */
    937 	mvi	SEQCTL,0x50			/* PAUSEDIS|FASTMODE */
    938 	cmp	SCB_TCL,A	jne findSCB1 /* target ID/channel/lun match? */
    939 	test	SCB_CONTROL,DISCONNECTED jz findSCB1 /*should be disconnected*/
    940 	test	SCB_CONTROL,TAG_ENB jnz findTaggedSCB
    941 	cmp	ARG_1,SCB_LIST_NULL je foundSCB
    942 	jmp	findSCB1
    943 findTaggedSCB:
    944 	mov	A, ARG_1			/* Tag passed in ARG_1 */
    945 	cmp	SCB_TAG,A	jne findSCB1	/* Found it? */
    946 foundSCB:
    947 	test	FLAGS,PAGESCBS	jz foundSCB_ret
    948 /* Remove this SCB from the disconnection list */
    949 	cmp	SCB_NEXT,SCB_LIST_NULL je unlink_prev
    950 	mov	SAVED_LINKPTR, SCB_PREV
    951 	mov	SCBPTR, SCB_NEXT
    952 	mov	SCB_PREV, SAVED_LINKPTR
    953 	mov	SCBPTR, SINDEX
    954 unlink_prev:
    955 	cmp	SCB_PREV,SCB_LIST_NULL	je rHead/* At the head of the list */
    956 	mov	SAVED_LINKPTR, SCB_NEXT
    957 	mov	SCBPTR, SCB_PREV
    958 	mov	SCB_NEXT, SAVED_LINKPTR
    959 	mov	SCBPTR, SINDEX
    960 	mvi	SEQCTL,0x10	ret		/* !PAUSEDIS|FASTMODE */
    961 rHead:
    962 	mov	DISCONNECTED_SCBH,SCB_NEXT
    963 foundSCB_ret:
    964 	mvi	SEQCTL,0x10	ret		/* !PAUSEDIS|FASTMODE */
    965 
    966 findSCB1:
    967 	mvi	SEQCTL,0x10			/* !PAUSEDIS|FASTMODE */
    968 	inc	SINDEX
    969 	mov	A,SCBCOUNT
    970 	cmp	SINDEX,A	jne findSCB
    971 
    972 	mvi	INTSTAT,NO_MATCH		/* not found - signal kernel */
    973 	cmp	RETURN_1,SCB_PAGEDIN je return
    974 	or	SCSISIGO,ATNO			/* assert ATNO */
    975 	cmp	ARG_1,SCB_LIST_NULL jne find_abort_tag
    976 	mvi	MSG_ABORT	call mk_mesg
    977 	jmp	ITloop
    978 find_abort_tag:
    979 	mvi	MSG_ABORT_TAG	call mk_mesg
    980 	jmp	ITloop
    981 
    982 /*
    983  * Make a working copy of the scatter-gather parameters from the SCB.
    984  */
    985 sg_scb2ram:
    986 	mov	HADDR0, SCB_DATAPTR0
    987 	mov	HADDR1, SCB_DATAPTR1
    988 	mov	HADDR2, SCB_DATAPTR2
    989 	mov	HADDR3, SCB_DATAPTR3
    990 	mov	HCNT0, SCB_DATACNT0
    991 	mov	HCNT1, SCB_DATACNT1
    992 	mov	HCNT2, SCB_DATACNT2
    993 
    994 	mov	STCNT0, HCNT0
    995 	mov	STCNT1, HCNT1
    996 	mov	STCNT2, HCNT2
    997 
    998 	mov	SG_COUNT,SCB_SGCOUNT
    999 
   1000 	mov	SG_NEXT0, SCB_SGPTR0
   1001 	mov	SG_NEXT1, SCB_SGPTR1
   1002 	mov	SG_NEXT2, SCB_SGPTR2
   1003 	mov	SG_NEXT3, SCB_SGPTR3 ret
   1004 
   1005 /*
   1006  * Copying RAM values back to SCB, for Save Data Pointers message, but
   1007  * only if we've actually been into a data phase to change them.  This
   1008  * protects against bogus data in scratch ram and the residual counts
   1009  * since they are only initialized when we go into data_in or data_out.
   1010  */
   1011 sg_ram2scb:
   1012 	test	FLAGS, DPHASE	jz return
   1013 	mov	SCB_SGCOUNT,SG_COUNT
   1014 
   1015 	mov	SCB_SGPTR0,SG_NEXT0
   1016 	mov	SCB_SGPTR1,SG_NEXT1
   1017 	mov	SCB_SGPTR2,SG_NEXT2
   1018 	mov	SCB_SGPTR3,SG_NEXT3
   1019 
   1020 	mov	SCB_DATAPTR0,SHADDR0
   1021 	mov	SCB_DATAPTR1,SHADDR1
   1022 	mov	SCB_DATAPTR2,SHADDR2
   1023 	mov	SCB_DATAPTR3,SHADDR3
   1024 
   1025 /*
   1026  * Use the residual number since STCNT is corrupted by any message transfer
   1027  */
   1028 	mov	SCB_DATACNT0,SCB_RESID_DCNT0
   1029 	mov	SCB_DATACNT1,SCB_RESID_DCNT1
   1030 	mov	SCB_DATACNT2,SCB_RESID_DCNT2 ret
   1031 
   1032 /*
   1033  * Add the array base TARG_SCRATCH to the target offset (the target address
   1034  * is in SCSIID), and return the result in SINDEX.  The accumulator
   1035  * contains the 3->8 decoding of the target ID on return.
   1036  */
   1037 ndx_dtr:
   1038 	shr	A,SCSIID,4
   1039 	test	SBLKCTL,SELBUSB	jz ndx_dtr_2
   1040 	or	A,0x08		/* Channel B entries add 8 */
   1041 ndx_dtr_2:
   1042 	add	SINDEX,TARG_SCRATCH,A ret
   1043 
   1044 /*
   1045  * If we need to negotiate transfer parameters, build the WDTR or SDTR message
   1046  * starting at the address passed in SINDEX.  DINDEX is modified on return.
   1047  * The SCSI-II spec requires that Wide negotiation occur first and you can
   1048  * only negotiat one or the other at a time otherwise in the event of a message
   1049  * reject, you wouldn't be able to tell which message was the culpret.
   1050  */
   1051 mk_dtr:
   1052 	test	SCB_CONTROL,NEEDWDTR jnz  mk_wdtr_16bit
   1053 	mvi	ARG_1, MAXOFFSET	/* Force an offset of 15 or 8 if WIDE */
   1054 
   1055 mk_sdtr:
   1056 	mvi	DINDIR,1		/* extended message */
   1057 	mvi	DINDIR,3		/* extended message length = 3 */
   1058 	mvi	DINDIR,1		/* SDTR code */
   1059 	call	sdtr_to_rate
   1060 	mov	DINDIR,RETURN_1		/* REQ/ACK transfer period */
   1061 	cmp	ARG_1, MAXOFFSET je mk_sdtr_max_offset
   1062 	and	DINDIR,0x0f,SINDIR	/* Sync Offset */
   1063 
   1064 mk_sdtr_done:
   1065 	add	MSG_LEN,COMP_MSG0,DINDEX ret	/* update message length */
   1066 
   1067 mk_sdtr_max_offset:
   1068 /*
   1069  * We're initiating sync negotiation, so request the max offset we can (15 or 8)
   1070  */
   1071 	/* Talking to a WIDE device? */
   1072 	test	SCSIRATE, WIDEXFER	jnz wmax_offset
   1073 	mvi	DINDIR, MAX_OFFSET_8BIT
   1074 	jmp	mk_sdtr_done
   1075 
   1076 wmax_offset:
   1077 	mvi	DINDIR, MAX_OFFSET_16BIT
   1078 	jmp	mk_sdtr_done
   1079 
   1080 mk_wdtr_16bit:
   1081 	mvi	ARG_1,BUS_16_BIT
   1082 mk_wdtr:
   1083 	mvi	DINDIR,1		/* extended message */
   1084 	mvi	DINDIR,2		/* extended message length = 2 */
   1085 	mvi	DINDIR,3		/* WDTR code */
   1086 	mov	DINDIR,ARG_1		/* bus width */
   1087 
   1088 	add	MSG_LEN,COMP_MSG0,DINDEX ret	/* update message length */
   1089 
   1090 sdtr_to_rate:
   1091 	call	ndx_dtr			/* index scratch space for target */
   1092 	shr	A,SINDIR,0x4
   1093 	dec	SINDEX			/* Preserve SINDEX */
   1094 	and	A,0x7
   1095 	clr	RETURN_1
   1096 sdtr_to_rate_loop:
   1097 	test	A,0x0f	jz sdtr_to_rate_done
   1098 	add	RETURN_1,0x19
   1099 	dec	A
   1100 	jmp	sdtr_to_rate_loop
   1101 sdtr_to_rate_done:
   1102 	shr	RETURN_1,0x2
   1103 	add	RETURN_1,0x19
   1104 	test	SXFRCTL0,ULTRAEN jz return
   1105 	shr	RETURN_1,0x1
   1106 return:
   1107 	ret
   1108