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