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