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