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