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