aic7xxx.seq revision 1.5 1 /* $NetBSD: aic7xxx.seq,v 1.5 1996/08/10 08:36:58 mycroft Exp $ */
2
3 /*+M***********************************************************************
4 *Adaptec 274x/284x/294x device driver for Linux and FreeBSD.
5 *
6 *Copyright (c) 1994 John Aycock
7 * The University of Calgary Department of Computer Science.
8 * All rights reserved.
9 *
10 *FreeBSD, Twin, Wide, 2 command per target support, tagged queuing,
11 *SCB paging and other optimizations:
12 *Copyright (c) 1994, 1995, 1996 Justin Gibbs. All rights reserved.
13 *
14 *Redistribution and use in source and binary forms, with or without
15 *modification, are permitted provided that the following conditions
16 *are met:
17 *1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions, and the following disclaimer.
19 *2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by the University of Calgary
25 * Department of Computer Science and its contributors.
26 *4. Neither the name of the University nor the names of its contributors
27 * may be used to endorse or promote products derived from this software
28 * without specific prior written permission.
29 *
30 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
31 *ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 *ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
34 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 *DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 *OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 *HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 *OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 *SUCH DAMAGE.
41 *
42 * from Id: aic7xxx.seq,v 1.42 1996/06/09 17:29:11 gibbs Exp
43 *
44 *-M************************************************************************/
45
46 VERSION AIC7XXX_SEQ_VER "$NetBSD: aic7xxx.seq,v 1.5 1996/08/10 08:36:58 mycroft Exp $"
47
48 #if defined(__NetBSD__)
49 #include "../../ic/aic7xxxreg.h"
50 #elif defined(__FreeBSD__)
51 #include "../../dev/aic7xxx/aic7xxx_reg.h"
52 #endif
53
54 /*
55 * We can't just use ACCUM in the sequencer code because it
56 * must be treated specially by the assembler, and it currently
57 * looks for the symbol 'A'. This is the only register defined in
58 * the assembler's symbol space.
59 */
60 A = ACCUM
61
62 /* After starting the selection hardware, we check for reconnecting targets
63 * as well as for our selection to complete just in case the reselection wins
64 * bus arbitration. The problem with this is that we must keep track of the
65 * SCB that we've already pulled from the QINFIFO and started the selection
66 * on just in case the reselection wins so that we can retry the selection at
67 * a later time. This problem cannot be resolved by holding a single entry
68 * in scratch ram since a reconnecting target can request sense and this will
69 * create yet another SCB waiting for selection. The solution used here is to
70 * use byte 27 of the SCB as a psuedo-next pointer and to thread a list
71 * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB offsets,
72 * SCB_LIST_NULL is 0xff which is out of range. The kernel driver must
73 * add an entry to this list everytime a request sense occurs. The sequencer
74 * will automatically consume the entries.
75 */
76
77 /*
78 * We assume that the kernel driver may reset us at any time, even in the
79 * middle of a DMA, so clear DFCNTRL too.
80 */
81 reset:
82 clr DFCNTRL
83 clr SCSISIGO /* De-assert BSY */
84 /*
85 * We jump to start after every bus free.
86 */
87 start:
88 and FLAGS,0x0f /* clear target specific flags */
89 mvi SCSISEQ,ENRSELI /* Always allow reselection */
90 clr SCSIRATE /*
91 * We don't know the target we will
92 * connect to, so default to narrow
93 * transfers to avoid parity problems.
94 */
95 poll_for_work:
96 /*
97 * Are we a twin channel device?
98 * For fairness, we check the other bus first,
99 * since we just finished a transaction on the
100 * current channel.
101 */
102 test FLAGS,TWIN_BUS jz start2
103 xor SBLKCTL,SELBUSB /* Toggle to the other bus */
104 test SSTAT0,SELDI jnz reselect
105 xor SBLKCTL,SELBUSB /* Toggle to the original bus */
106 start2:
107 test SSTAT0,SELDI jnz reselect
108 cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting
109 mov A, QCNTMASK
110 test QINCNT,A jz poll_for_work
111
112 /*
113 * We have at least one queued SCB now and we don't have any
114 * SCBs in the list of SCBs awaiting selection. Set the SCB
115 * pointer from the FIFO so we see the right bank of SCB
116 * registers.
117 */
118 mov SCBPTR,QINFIFO
119
120 /*
121 * See if there is not already an active SCB for this target. This code
122 * locks out on a per target basis instead of target/lun. Although this
123 * is not ideal for devices that have multiple luns active at the same
124 * time, it is faster than looping through all SCB's looking for active
125 * commands. It may be benificial to make findscb a more general procedure
126 * to see if the added cost of the search is negligible. This code also
127 * assumes that the kernel driver will clear the active flags on board
128 * initialization, board reset, and a target SELTO. Tagged commands
129 * don't set the active bits since you can queue more than one command
130 * at a time. We do, however, look to see if there are any non-tagged
131 * I/Os in progress, and requeue the command if there are. Tagged and
132 * non-tagged commands cannot be mixed to a single target.
133 */
134
135 test_busy:
136 mov FUNCTION1,SCB_TCL
137 mov A,FUNCTION1
138 test SCB_TCL,0x88 jz test_a /* Id < 8 && A channel */
139
140 test ACTIVE_B,A jnz requeue
141 test SCB_CONTROL,TAG_ENB jnz start_scb
142 /* Mark the current target as busy */
143 or ACTIVE_B,A
144 jmp start_scb
145
146 /* Place the currently active SCB back on the queue for later processing */
147 requeue:
148 mov QINFIFO, SCBPTR
149 jmp poll_for_work
150
151 /*
152 * Pull the first entry off of the waiting for selection list
153 * We don't have to "test_busy" because only transactions that
154 * have passed that test can be in the waiting_scb list.
155 */
156 start_waiting:
157 mov SCBPTR,WAITING_SCBH
158 jmp start_scb2
159
160 test_a:
161 test ACTIVE_A,A jnz requeue
162 test SCB_CONTROL,TAG_ENB jnz start_scb
163 /* Mark the current target as busy */
164 or ACTIVE_A,A
165
166 start_scb:
167 mov SCB_NEXT,WAITING_SCBH
168 mov WAITING_SCBH, SCBPTR
169 start_scb2:
170 and SINDEX,0xf7,SBLKCTL /* Clear the channel select bit */
171 and A,0x08,SCB_TCL /* Get new channel bit */
172 or SINDEX,A
173 mov SBLKCTL,SINDEX /* select channel */
174 mov SCB_TCL call initialize_scsiid
175
176 /*
177 * Enable selection phase as an initiator, and do automatic ATN
178 * after the selection. We do this now so that we can overlap the
179 * rest of our work to set up this target with the arbitration and
180 * selection bus phases.
181 */
182 start_selection:
183 mvi SCSISEQ,0x58 /* ENSELO|ENAUTOATNO|ENRSELI */
184
185 /*
186 * As soon as we get a successful selection, the target should go
187 * into the message out phase since we have ATN asserted. Prepare
188 * the message to send.
189 *
190 * Messages are stored in scratch RAM starting with a length byte
191 * followed by the message itself.
192 */
193 test SCB_CMDLEN,0xff jnz mk_identify /* 0 Length Command? */
194
195 /*
196 * The kernel has sent us an SCB with no command attached. This implies
197 * that the kernel wants to send a message of some sort to this target,
198 * so we interrupt the driver, allow it to fill the message buffer, and
199 * then go back into the arbitration loop
200 */
201 mvi INTSTAT,AWAITING_MSG
202 jmp wait_for_selection
203
204 mk_identify:
205 and A,DISCENB,SCB_CONTROL /* mask off disconnect privledge */
206
207 and MSG0,0x7,SCB_TCL /* lun */
208 or MSG0,A /* or in disconnect privledge */
209 or MSG0,MSG_IDENTIFY
210 mvi MSG_LEN, 1
211
212 test SCB_CONTROL,0xb0 jz !message /* WDTR, SDTR or TAG?? */
213 /*
214 * Send a tag message if TAG_ENB is set in the SCB control block.
215 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
216 */
217
218 mk_tag:
219 mvi DINDEX, MSG1
220 test SCB_CONTROL,TAG_ENB jz mk_tag_done
221 and DINDIR,0x23,SCB_CONTROL
222 mov DINDIR,SCB_TAG
223
224 add MSG_LEN,COMP_MSG0,DINDEX /* update message length */
225
226 mk_tag_done:
227
228 test SCB_CONTROL,0x90 jz !message /* NEEDWDTR|NEEDSDTR */
229 mov DINDEX call mk_dtr /* build DTR message if needed */
230
231 !message:
232 wait_for_selection:
233 test SSTAT0,SELDO jnz select
234 test SSTAT0,SELDI jz wait_for_selection
235
236 /*
237 * Reselection has been initiated by a target. Make a note that we've been
238 * reselected, but haven't seen an IDENTIFY message from the target
239 * yet.
240 */
241 reselect:
242 clr MSG_LEN /* Don't have anything in the mesg buffer */
243 mov SELID call initialize_scsiid
244 or FLAGS,RESELECTED
245 jmp select2
246
247 /*
248 * After the selection, remove this SCB from the "waiting for selection"
249 * list. This is achieved by simply moving our "next" pointer into
250 * WAITING_SCBH. Our next pointer will be set to null the next time this
251 * SCB is used, so don't bother with it now.
252 */
253 select:
254 mov WAITING_SCBH,SCB_NEXT
255 or FLAGS,SELECTED
256 select2:
257 /*
258 * Set CLRCHN here before the target has entered a data transfer mode -
259 * with synchronous SCSI, if you do it later, you blow away some
260 * data in the SCSI FIFO that the target has already sent to you.
261 */
262 or SXFRCTL0,CLRCHN
263 /*
264 * Initialize SCSIRATE with the appropriate value for this target.
265 */
266 call ndx_dtr
267 mov SCSIRATE,SINDIR
268
269 /*
270 * Initialize Ultra mode setting.
271 */
272 mov FUNCTION1,SCSIID
273 mov A,FUNCTION1
274 and SINDEX,0xdf,SXFRCTL0 /* default to Ultra disabled */
275 test SCSIID, 0x80 jnz ultra_b /* Target ID > 7 */
276 test SBLKCTL, SELBUSB jnz ultra_b /* Second channel device */
277 test ULTRA_ENB,A jz set_sxfrctl0
278 or SINDEX, ULTRAEN jmp set_sxfrctl0
279 ultra_b:
280 test ULTRA_ENB_B,A jz set_sxfrctl0
281 or SINDEX, ULTRAEN
282
283 set_sxfrctl0:
284 mov SXFRCTL0,SINDEX
285
286 mvi SCSISEQ,ENAUTOATNP /*
287 * ATN on parity errors
288 * for "in" phases
289 */
290 mvi CLRSINT1,CLRBUSFREE
291 mvi CLRSINT0,0x60 /* CLRSELDI|CLRSELDO */
292 /*
293 * Main loop for information transfer phases. If BSY is false, then
294 * we have a bus free condition, expected or not. Otherwise, wait
295 * for the target to assert REQ before checking MSG, C/D and I/O
296 * for the bus phase.
297 *
298 */
299 ITloop:
300 test SSTAT1,BUSFREE jnz p_busfree
301 test SSTAT1,REQINIT jz ITloop
302
303 and A,PHASE_MASK,SCSISIGI
304 mov LASTPHASE,A
305 mov SCSISIGO,A
306
307 cmp ALLZEROS,A je p_dataout
308 cmp A,P_DATAIN je p_datain
309 cmp A,P_COMMAND je p_command
310 cmp A,P_MESGOUT je p_mesgout
311 cmp A,P_STATUS je p_status
312 cmp A,P_MESGIN je p_mesgin
313
314 mvi INTSTAT,BAD_PHASE /* unknown phase - signal driver */
315 jmp ITloop /* Try reading the bus again. */
316
317 p_dataout:
318 mvi DMAPARAMS,0x7d /*
319 * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
320 * DIRECTION|FIFORESET
321 */
322 jmp data_phase_init
323
324 /*
325 * If we re-enter the data phase after going through another phase, the
326 * STCNT may have been cleared, so restore it from the residual field.
327 */
328 data_phase_reinit:
329 mov STCNT0,SCB_RESID_DCNT0
330 mov STCNT1,SCB_RESID_DCNT1
331 mov STCNT2,SCB_RESID_DCNT2
332 jmp data_phase_loop
333
334 p_datain:
335 mvi DMAPARAMS,0x79 /*
336 * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
337 * !DIRECTION|FIFORESET
338 */
339 data_phase_init:
340 call assert
341
342 test FLAGS, DPHASE jnz data_phase_reinit
343 call sg_scb2ram
344 or FLAGS, DPHASE /* We have seen a data phase */
345
346 data_phase_loop:
347 /* Guard against overruns */
348 test SG_COUNT, 0xff jnz data_phase_inbounds
349 /*
350 * Turn on 'Bit Bucket' mode, set the transfer count to
351 * 16meg and let the target run until it changes phase.
352 * When the transfer completes, notify the host that we
353 * had an overrun.
354 */
355 or SXFRCTL1,BITBUCKET
356 mvi STCNT0,0xff
357 mvi STCNT1,0xff
358 mvi STCNT2,0xff
359
360 data_phase_inbounds:
361 /* If we are the last SG block, don't set wideodd. */
362 cmp SG_COUNT,0x01 jne data_phase_wideodd
363 and DMAPARAMS, 0xbf /* Turn off WIDEODD */
364 data_phase_wideodd:
365 mov DMAPARAMS call dma
366
367 /* Go tell the host about any overruns */
368 test SXFRCTL1,BITBUCKET jnz data_phase_overrun
369
370 /* Exit if we had an underrun */
371 test SSTAT0,SDONE jz data_phase_finish /* underrun STCNT != 0 */
372
373 /*
374 * Advance the scatter-gather pointers if needed
375 */
376 sg_advance:
377 dec SG_COUNT /* one less segment to go */
378
379 test SG_COUNT, 0xff jz data_phase_finish /* Are we done? */
380
381 clr A /* add sizeof(struct scatter) */
382 add SG_NEXT0,SG_SIZEOF,SG_NEXT0
383 adc SG_NEXT1,A,SG_NEXT1
384
385 /*
386 * Load a struct scatter and set up the data address and length.
387 * If the working value of the SG count is nonzero, then
388 * we need to load a new set of values.
389 *
390 * This, like all DMA's, assumes little-endian host data storage.
391 */
392 sg_load:
393 clr HCNT2
394 clr HCNT1
395 mvi HCNT0,SG_SIZEOF
396
397 mov HADDR0,SG_NEXT0
398 mov HADDR1,SG_NEXT1
399 mov HADDR2,SG_NEXT2
400 mov HADDR3,SG_NEXT3
401
402 or DFCNTRL,0xd /* HDMAEN|DIRECTION|FIFORESET */
403
404 /*
405 * Wait for DMA from host memory to data FIFO to complete, then disable
406 * DMA and wait for it to acknowledge that it's off.
407 */
408 dma_finish:
409 test DFSTATUS,HDONE jz dma_finish
410 /* Turn off DMA preserving WIDEODD */
411 and DFCNTRL,WIDEODD
412 dma_finish2:
413 test DFCNTRL,HDMAENACK jnz dma_finish2
414
415 /*
416 * Copy data from FIFO into SCB data pointer and data count. This assumes
417 * that the struct scatterlist has this structure (this and sizeof(struct
418 * scatterlist) == 12 are asserted in aic7xxx.c for the Linux driver):
419 *
420 * struct scatterlist {
421 * char *address; four bytes, little-endian order
422 * ... four bytes, ignored
423 * unsigned short length; two bytes, little-endian order
424 * }
425 *
426 *
427 * In FreeBSD, the scatter list entry is only 8 bytes.
428 *
429 * struct ahc_dma_seg {
430 * physaddr addr; four bytes, little-endian order
431 * long len; four bytes, little endian order
432 * };
433 */
434
435 mov HADDR0,DFDAT
436 mov HADDR1,DFDAT
437 mov HADDR2,DFDAT
438 mov HADDR3,DFDAT
439 /*
440 * For Linux, we must throw away four bytes since there is a 32bit gap
441 * in the middle of a struct scatterlist.
442 */
443 #ifdef __linux__
444 mov NONE,DFDAT
445 mov NONE,DFDAT
446 mov NONE,DFDAT
447 mov NONE,DFDAT
448 #endif
449 mov HCNT0,DFDAT
450 mov HCNT1,DFDAT
451 mov HCNT2,DFDAT
452
453 /* Load STCNT as well. It is a mirror of HCNT */
454 mov STCNT0,HCNT0
455 mov STCNT1,HCNT1
456 mov STCNT2,HCNT2
457 test SSTAT1,PHASEMIS jz data_phase_loop
458
459 data_phase_finish:
460 /*
461 * After a DMA finishes, save the SG and STCNT residuals back into the SCB
462 * We use STCNT instead of HCNT, since it's a reflection of how many bytes
463 * were transferred on the SCSI (as opposed to the host) bus.
464 */
465 mov SCB_RESID_DCNT0,STCNT0
466 mov SCB_RESID_DCNT1,STCNT1
467 mov SCB_RESID_DCNT2,STCNT2
468 mov SCB_RESID_SGCNT, SG_COUNT
469 jmp ITloop
470
471 data_phase_overrun:
472 /*
473 * Turn off BITBUCKET mode and notify the host
474 */
475 and SXFRCTL1,0x7f /* ~BITBUCKET */
476 mvi INTSTAT,DATA_OVERRUN
477 jmp ITloop
478
479 /*
480 * Command phase. Set up the DMA registers and let 'er rip.
481 */
482 p_command:
483 call assert
484
485 /*
486 * Load HADDR and HCNT.
487 */
488 mov HADDR0, SCB_CMDPTR0
489 mov HADDR1, SCB_CMDPTR1
490 mov HADDR2, SCB_CMDPTR2
491 mov HADDR3, SCB_CMDPTR3
492 mov HCNT0, SCB_CMDLEN
493 clr HCNT1
494 clr HCNT2
495
496 mov STCNT0, HCNT0
497 mov STCNT1, HCNT1
498 mov STCNT2, HCNT2
499
500 mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN|
501 # DIRECTION|FIFORESET
502 jmp ITloop
503
504 /*
505 * Status phase. Wait for the data byte to appear, then read it
506 * and store it into the SCB.
507 */
508 p_status:
509 mvi SCB_TARGET_STATUS call inb_first
510 jmp mesgin_done
511
512 /*
513 * Message out phase. If there is not an active message, but the target
514 * took us into this phase anyway, build a no-op message and send it.
515 */
516 p_mesgout:
517 test MSG_LEN, 0xff jnz p_mesgout_start
518 mvi MSG_NOP call mk_mesg /* build NOP message */
519
520 p_mesgout_start:
521 /*
522 * Set up automatic PIO transfer from MSG0. Bit 3 in
523 * SXFRCTL0 (SPIOEN) is already on.
524 */
525 mvi SINDEX,MSG0
526 mov DINDEX,MSG_LEN
527
528 /*
529 * When target asks for a byte, drop ATN if it's the last one in
530 * the message. Otherwise, keep going until the message is exhausted.
531 *
532 * Keep an eye out for a phase change, in case the target issues
533 * a MESSAGE REJECT.
534 */
535 p_mesgout_loop:
536 test SSTAT1,PHASEMIS jnz p_mesgout_phasemis
537 test SSTAT0,SPIORDY jz p_mesgout_loop
538 test SSTAT1,PHASEMIS jnz p_mesgout_phasemis
539 cmp DINDEX,1 jne p_mesgout_outb /* last byte? */
540 mvi CLRSINT1,CLRATNO /* drop ATN */
541 p_mesgout_outb:
542 dec DINDEX
543 or CLRSINT0, CLRSPIORDY
544 mov SCSIDATL,SINDIR
545
546 p_mesgout4:
547 test DINDEX,0xff jnz p_mesgout_loop
548
549 /*
550 * If the next bus phase after ATN drops is a message out, it means
551 * that the target is requesting that the last message(s) be resent.
552 */
553 p_mesgout_snoop:
554 test SSTAT1,BUSFREE jnz p_mesgout_done
555 test SSTAT1,REQINIT jz p_mesgout_snoop
556
557 test SSTAT1,PHASEMIS jnz p_mesgout_done
558
559 or SCSISIGO,ATNO /* turn on ATNO */
560
561 jmp ITloop
562
563 p_mesgout_phasemis:
564 mvi CLRSINT1,CLRATNO /* Be sure to turn ATNO off */
565 p_mesgout_done:
566 clr MSG_LEN /* no active msg */
567 jmp ITloop
568
569 /*
570 * Message in phase. Bytes are read using Automatic PIO mode.
571 */
572 p_mesgin:
573 mvi A call inb_first /* read the 1st message byte */
574 mov REJBYTE,A /* save it for the driver */
575
576 test A,MSG_IDENTIFY jnz mesgin_identify
577 cmp A,MSG_DISCONNECT je mesgin_disconnect
578 cmp A,MSG_SDPTRS je mesgin_sdptrs
579 cmp ALLZEROS,A je mesgin_complete
580 cmp A,MSG_RDPTRS je mesgin_rdptrs
581 cmp A,MSG_EXTENDED je mesgin_extended
582 cmp A,MSG_REJECT je mesgin_reject
583
584 rej_mesgin:
585 /*
586 * We have no idea what this message in is, and there's no way
587 * to pass it up to the kernel, so we issue a message reject and
588 * hope for the best. Since we're now using manual PIO mode to
589 * read in the message, there should no longer be a race condition
590 * present when we assert ATN. In any case, rejection should be a
591 * rare occurrence - signal the driver when it happens.
592 */
593 or SCSISIGO,ATNO /* turn on ATNO */
594 mvi INTSTAT,SEND_REJECT /* let driver know */
595
596 mvi MSG_REJECT call mk_mesg
597
598 mesgin_done:
599 call inb_last /*ack & turn auto PIO back on*/
600 jmp ITloop
601
602
603 mesgin_complete:
604 /*
605 * We got a "command complete" message, so put the SCB_TAG into QUEUEOUT,
606 * and trigger a completion interrupt. Check status for non zero return
607 * and interrupt driver if needed. This allows the driver to interpret
608 * errors only when they occur instead of always uploading the scb. If
609 * the status is SCSI_CHECK, the driver will download a new scb requesting
610 * sense to replace the old one, modify the "waiting for selection" SCB list
611 * and set RETURN_1 to SEND_SENSE. If RETURN_1 is set to SEND_SENSE the
612 * sequencer imediately jumps to main loop where it will run down the waiting
613 * SCB list and process the sense request. If the kernel driver does not
614 * wish to request sense, it need only clear RETURN_1, and the command is
615 * allowed to complete. We don't bother to post to the QOUTFIFO in the
616 * error case since it would require extra work in the kernel driver to
617 * ensure that the entry was removed before the command complete code tried
618 * processing it.
619 *
620 * First check for residuals
621 */
622 test SCB_RESID_SGCNT,0xff jz check_status
623 /*
624 * If we have a residual count, interrupt and tell the host. Other
625 * alternatives are to pause the sequencer on all command completes (yuck),
626 * dma the resid directly to the host (slick, we may have space to do it now)
627 * or have the sequencer pause itself when it encounters a non-zero resid
628 * (unecessary pause just to flag the command -yuck-, but takes one instruction
629 * and since it shouldn't happen that often is good enough for our purposes).
630 */
631 resid:
632 mvi INTSTAT,RESIDUAL
633
634 check_status:
635 test SCB_TARGET_STATUS,0xff jz status_ok /* Good Status? */
636 mvi INTSTAT,BAD_STATUS /* let driver know */
637 cmp RETURN_1, SEND_SENSE jne status_ok
638 jmp mesgin_done
639
640 status_ok:
641 /* First, mark this target as free. */
642 test SCB_CONTROL,TAG_ENB jnz test_immediate /*
643 * Tagged commands
644 * don't busy the
645 * target.
646 */
647 mov FUNCTION1,SCB_TCL
648 mov A,FUNCTION1
649 test SCB_TCL,0x88 jz clear_a
650 xor ACTIVE_B,A
651 jmp test_immediate
652
653 clear_a:
654 xor ACTIVE_A,A
655
656 test_immediate:
657 test SCB_CMDLEN,0xff jnz complete /* Immediate message complete */
658 /*
659 * Pause the sequencer until the driver gets around to handling the command
660 * complete. This is so that any action that might require carefull timing
661 * with the completion of this command can occur.
662 */
663 mvi INTSTAT,IMMEDDONE
664 jmp start
665 complete:
666 mov QOUTFIFO,SCB_TAG
667 mvi INTSTAT,CMDCMPLT
668 jmp mesgin_done
669
670
671 /*
672 * Is it an extended message? We only support the synchronous and wide data
673 * transfer request messages, which will probably be in response to
674 * WDTR or SDTR message outs from us. If it's not SDTR or WDTR, reject it -
675 * apparently this can be done after any message in byte, according
676 * to the SCSI-2 spec.
677 */
678 mesgin_extended:
679 mvi ARG_1 call inb_next /* extended message length */
680 mvi REJBYTE_EXT call inb_next /* extended message code */
681
682 cmp REJBYTE_EXT,MSG_SDTR je p_mesginSDTR
683 cmp REJBYTE_EXT,MSG_WDTR je p_mesginWDTR
684 jmp rej_mesgin
685
686 p_mesginWDTR:
687 cmp ARG_1,2 jne rej_mesgin /* extended mesg length=2 */
688 mvi ARG_1 call inb_next /* Width of bus */
689 mvi INTSTAT,WDTR_MSG /* let driver know */
690 test RETURN_1,0xff jz mesgin_done /* Do we need to send WDTR? */
691 cmp RETURN_1,SEND_REJ je rej_mesgin /*
692 * Bus width was too large
693 * Reject it.
694 */
695
696 /* We didn't initiate the wide negotiation, so we must respond to the request */
697 and RETURN_1,0x7f /* Clear the SEND_WDTR Flag */
698 mvi DINDEX,MSG0
699 mvi MSG0 call mk_wdtr /* build WDTR message */
700 or SCSISIGO,ATNO /* turn on ATNO */
701 jmp mesgin_done
702
703 p_mesginSDTR:
704 cmp ARG_1,3 jne rej_mesgin /* extended mesg length=3 */
705 mvi ARG_1 call inb_next /* xfer period */
706 mvi A call inb_next /* REQ/ACK offset */
707 mvi INTSTAT,SDTR_MSG /* call driver to convert */
708
709 test RETURN_1,0xff jz mesgin_done /* Do we need to mk_sdtr/rej */
710 cmp RETURN_1,SEND_REJ je rej_mesgin /*
711 * Requested SDTR too small
712 * Reject it.
713 */
714 clr ARG_1 /* Use the scratch ram rate */
715 mvi DINDEX, MSG0
716 mvi MSG0 call mk_sdtr
717 or SCSISIGO,ATNO /* turn on ATNO */
718 jmp mesgin_done
719
720 /*
721 * Is it a disconnect message? Set a flag in the SCB to remind us
722 * and await the bus going free.
723 */
724 mesgin_disconnect:
725 or SCB_CONTROL,DISCONNECTED
726 test FLAGS, PAGESCBS jz mesgin_done
727 /*
728 * Link this SCB into the DISCONNECTED list. This list holds the
729 * candidates for paging out an SCB if one is needed for a new command.
730 * Modifying the disconnected list is a critical(pause dissabled) section.
731 */
732 mvi SCB_PREV, SCB_LIST_NULL
733 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */
734 mov SCB_NEXT, DISCONNECTED_SCBH
735 mov DISCONNECTED_SCBH, SCBPTR
736 cmp SCB_NEXT,SCB_LIST_NULL je linkdone
737 mov SCBPTR,SCB_NEXT
738 mov SCB_PREV,DISCONNECTED_SCBH
739 mov SCBPTR,DISCONNECTED_SCBH
740 linkdone:
741 mvi SEQCTL,0x10 /* !PAUSEDIS|FASTMODE */
742 jmp mesgin_done
743
744 /*
745 * Save data pointers message? Copy working values into the SCB,
746 * usually in preparation for a disconnect.
747 */
748 mesgin_sdptrs:
749 call sg_ram2scb
750 jmp mesgin_done
751
752 /*
753 * Restore pointers message? Data pointers are recopied from the
754 * SCB anytime we enter a data phase for the first time, so all
755 * we need to do is clear the DPHASE flag and let the data phase
756 * code do the rest.
757 */
758 mesgin_rdptrs:
759 and FLAGS,0xef /*
760 * !DPHASE we'll reload them
761 * the next time through
762 */
763 jmp mesgin_done
764
765 /*
766 * Identify message? For a reconnecting target, this tells us the lun
767 * that the reconnection is for - find the correct SCB and switch to it,
768 * clearing the "disconnected" bit so we don't "find" it by accident later.
769 */
770 mesgin_identify:
771 test A,0x78 jnz rej_mesgin /*!DiscPriv|!LUNTAR|!Reserved*/
772
773 and A,0x07 /* lun in lower three bits */
774 or SAVED_TCL,A,SELID
775 and SAVED_TCL,0xf7
776 and A,SELBUSB,SBLKCTL /* B Channel?? */
777 or SAVED_TCL,A
778 call inb_last /* ACK */
779
780 /*
781 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
782 * If we get one, we use the tag returned to switch to find the proper
783 * SCB. With SCB paging, this requires using findSCB for both tagged
784 * and non-tagged transactions since the SCB may exist in any slot.
785 * If we're not using SCB paging, we can use the tag as the direct
786 * index to the SCB.
787 */
788 mvi ARG_1,SCB_LIST_NULL /* Default to no-tag */
789 snoop_tag_loop:
790 test SSTAT1,BUSFREE jnz use_findSCB
791 test SSTAT1,REQINIT jz snoop_tag_loop
792 test SSTAT1,PHASEMIS jnz use_findSCB
793 mvi A call inb_first
794 cmp A,MSG_SIMPLE_TAG jne use_findSCB
795 get_tag:
796 mvi ARG_1 call inb_next /* tag value */
797 /*
798 * See if the tag is in range. The tag is < SCBCOUNT if we add
799 * the complement of SCBCOUNT to the incomming tag and there is
800 * no carry.
801 */
802 mov A,COMP_SCBCOUNT
803 add SINDEX,A,ARG_1
804 jc abort_tag
805
806 /*
807 * Ensure that the SCB the tag points to is for an SCB transaction
808 * to the reconnecting target.
809 */
810 test FLAGS, PAGESCBS jz index_by_tag
811 call inb_last /* Ack Tag */
812 use_findSCB:
813 mov ALLZEROS call findSCB /* Have to search */
814 setup_SCB:
815 and SCB_CONTROL,0xfb /* clear disconnect bit in SCB */
816 or FLAGS,IDENTIFY_SEEN /* make note of IDENTIFY */
817 jmp ITloop
818 index_by_tag:
819 mov SCBPTR,ARG_1
820 mov A,SAVED_TCL
821 cmp SCB_TCL,A jne abort_tag
822 test SCB_CONTROL,TAG_ENB jz abort_tag
823 call inb_last /* Ack Successful tag */
824 jmp setup_SCB
825
826 abort_tag:
827 or SCSISIGO,ATNO /* turn on ATNO */
828 mvi INTSTAT,ABORT_TAG /* let driver know */
829 mvi MSG_ABORT_TAG call mk_mesg /* ABORT TAG message */
830 jmp mesgin_done
831
832 /*
833 * Message reject? Let the kernel driver handle this. If we have an
834 * outstanding WDTR or SDTR negotiation, assume that it's a response from
835 * the target selecting 8bit or asynchronous transfer, otherwise just ignore
836 * it since we have no clue what it pertains to.
837 */
838 mesgin_reject:
839 mvi INTSTAT, REJECT_MSG
840 jmp mesgin_done
841
842 /*
843 * [ ADD MORE MESSAGE HANDLING HERE ]
844 */
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,CLRATNO
853 clr LASTPHASE
854
855 /*
856 * if this is an immediate command, perform a psuedo command complete to
857 * notify the driver.
858 */
859 test SCB_CMDLEN,0xff jz status_ok
860 jmp start
861
862 /*
863 * Locking the driver out, build a one-byte message passed in SINDEX
864 * if there is no active message already. SINDEX is returned intact.
865 */
866 mk_mesg:
867 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */
868 test MSG_LEN,0xff jz mk_mesg1 /* Should always succeed */
869
870 /*
871 * Hmmm. For some reason the mesg buffer is in use.
872 * Tell the driver. It should look at SINDEX to find
873 * out what we wanted to use the buffer for and resolve
874 * the conflict.
875 */
876 mvi SEQCTL,0x10 /* !PAUSEDIS|FASTMODE */
877 mvi INTSTAT,MSG_BUFFER_BUSY
878
879 mk_mesg1:
880 mvi MSG_LEN,1 /* length = 1 */
881 mov MSG0,SINDEX /* 1-byte message */
882 mvi SEQCTL,0x10 ret /* !PAUSEDIS|FASTMODE */
883
884 /*
885 * Functions to read data in Automatic PIO mode.
886 *
887 * According to Adaptec's documentation, an ACK is not sent on input from
888 * the target until SCSIDATL is read from. So we wait until SCSIDATL is
889 * latched (the usual way), then read the data byte directly off the bus
890 * using SCSIBUSL. When we have pulled the ATN line, or we just want to
891 * acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI
892 * spec guarantees that the target will hold the data byte on the bus until
893 * we send our ACK.
894 *
895 * The assumption here is that these are called in a particular sequence,
896 * and that REQ is already set when inb_first is called. inb_{first,next}
897 * use the same calling convention as inb.
898 */
899
900 inb_next:
901 or CLRSINT0, CLRSPIORDY
902 mov NONE,SCSIDATL /*dummy read from latch to ACK*/
903 inb_next_wait:
904 test SSTAT1,PHASEMIS jnz mesgin_phasemis
905 test SSTAT0,SPIORDY jz inb_next_wait /* wait for next byte */
906 inb_first:
907 mov DINDEX,SINDEX
908 test SSTAT1,PHASEMIS jnz mesgin_phasemis
909 mov DINDIR,SCSIBUSL ret /*read byte directly from bus*/
910 inb_last:
911 mov NONE,SCSIDATL ret /*dummy read from latch to ACK*/
912
913 mesgin_phasemis:
914 /*
915 * We expected to receive another byte, but the target changed phase
916 */
917 mvi INTSTAT, MSGIN_PHASEMIS
918 jmp ITloop
919
920 /*
921 * DMA data transfer. HADDR and HCNT must be loaded first, and
922 * SINDEX should contain the value to load DFCNTRL with - 0x3d for
923 * host->scsi, or 0x39 for scsi->host. The SCSI channel is cleared
924 * during initialization.
925 */
926 dma:
927 mov DFCNTRL,SINDEX
928 dma1:
929 test SSTAT0,DMADONE jnz dma3
930 test SSTAT1,PHASEMIS jz dma1 /* ie. underrun */
931
932 /*
933 * We will be "done" DMAing when the transfer count goes to zero, or
934 * the target changes the phase (in light of this, it makes sense that
935 * the DMA circuitry doesn't ACK when PHASEMIS is active). If we are
936 * doing a SCSI->Host transfer, the data FIFO should be flushed auto-
937 * magically on STCNT=0 or a phase change, so just wait for FIFO empty
938 * status.
939 */
940 dma3:
941 test SINDEX,DIRECTION jnz dma5
942 dma4:
943 test DFSTATUS,FIFOEMP jz dma4
944
945 /*
946 * Now shut the DMA enables off and make sure that the DMA enables are
947 * actually off first lest we get an ILLSADDR.
948 */
949 dma5:
950 /* disable DMA, but maintain WIDEODD */
951 and DFCNTRL,WIDEODD
952 dma6:
953 test DFCNTRL,0x38 jnz dma6 /* SCSIENACK|SDMAENACK|HDMAENACK */
954
955 ret
956
957 /*
958 * Common SCSI initialization for selection and reselection. Expects
959 * the target SCSI ID to be in the upper four bits of SINDEX, and A's
960 * contents are stomped on return.
961 */
962 initialize_scsiid:
963 and SINDEX,0xf0 /* Get target ID */
964 and A,0x0f,SCSIID
965 or SINDEX,A
966 mov SCSIID,SINDEX ret
967
968 /*
969 * Assert that if we've been reselected, then we've seen an IDENTIFY
970 * message.
971 */
972 assert:
973 test FLAGS,RESELECTED jz return /* reselected? */
974 test FLAGS,IDENTIFY_SEEN jnz return /* seen IDENTIFY? */
975
976 mvi INTSTAT,NO_IDENT ret /* no - cause a kernel panic */
977
978 /*
979 * Locate the SCB matching the target ID/channel/lun in SAVED_TCL, and the tag
980 * value in ARG_1. If ARG_1 == SCB_LIST_NULL, we're looking for a non-tagged
981 * SCB. Have the kernel print a warning message if it can't be found, and
982 * generate an ABORT/ABORT_TAG message to the target. SINDEX should be
983 * cleared on call.
984 */
985 findSCB:
986 mov A,SAVED_TCL
987 mov SCBPTR,SINDEX /* switch to next SCB */
988 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */
989 cmp SCB_TCL,A jne findSCB1 /* target ID/channel/lun match? */
990 test SCB_CONTROL,DISCONNECTED jz findSCB1 /*should be disconnected*/
991 test SCB_CONTROL,TAG_ENB jnz findTaggedSCB
992 cmp ARG_1,SCB_LIST_NULL je foundSCB
993 jmp findSCB1
994 findTaggedSCB:
995 mov A, ARG_1 /* Tag passed in ARG_1 */
996 cmp SCB_TAG,A jne findSCB1 /* Found it? */
997 foundSCB:
998 test FLAGS,PAGESCBS jz foundSCB_ret
999 /* Remove this SCB from the disconnection list */
1000 cmp SCB_NEXT,SCB_LIST_NULL je unlink_prev
1001 mov SAVED_LINKPTR, SCB_PREV
1002 mov SCBPTR, SCB_NEXT
1003 mov SCB_PREV, SAVED_LINKPTR
1004 mov SCBPTR, SINDEX
1005 unlink_prev:
1006 cmp SCB_PREV,SCB_LIST_NULL je rHead/* At the head of the list */
1007 mov SAVED_LINKPTR, SCB_NEXT
1008 mov SCBPTR, SCB_PREV
1009 mov SCB_NEXT, SAVED_LINKPTR
1010 mov SCBPTR, SINDEX
1011 mvi SEQCTL,0x10 ret /* !PAUSEDIS|FASTMODE */
1012 rHead:
1013 mov DISCONNECTED_SCBH,SCB_NEXT
1014 foundSCB_ret:
1015 mvi SEQCTL,0x10 ret /* !PAUSEDIS|FASTMODE */
1016
1017 findSCB1:
1018 mvi SEQCTL,0x10 /* !PAUSEDIS|FASTMODE */
1019 inc SINDEX
1020 mov A,SCBCOUNT
1021 cmp SINDEX,A jne findSCB
1022
1023 mvi INTSTAT,NO_MATCH /* not found - signal kernel */
1024 cmp RETURN_1,SCB_PAGEDIN je return
1025 or SCSISIGO,ATNO /* assert ATNO */
1026 cmp ARG_1,SCB_LIST_NULL jne find_abort_tag
1027 mvi MSG_ABORT call mk_mesg
1028 jmp ITloop
1029 find_abort_tag:
1030 mvi MSG_ABORT_TAG call mk_mesg
1031 jmp ITloop
1032
1033 /*
1034 * Make a working copy of the scatter-gather parameters from the SCB.
1035 */
1036 sg_scb2ram:
1037 mov HADDR0, SCB_DATAPTR0
1038 mov HADDR1, SCB_DATAPTR1
1039 mov HADDR2, SCB_DATAPTR2
1040 mov HADDR3, SCB_DATAPTR3
1041 mov HCNT0, SCB_DATACNT0
1042 mov HCNT1, SCB_DATACNT1
1043 mov HCNT2, SCB_DATACNT2
1044
1045 mov STCNT0, HCNT0
1046 mov STCNT1, HCNT1
1047 mov STCNT2, HCNT2
1048
1049 mov SG_COUNT,SCB_SGCOUNT
1050
1051 mov SG_NEXT0, SCB_SGPTR0
1052 mov SG_NEXT1, SCB_SGPTR1
1053 mov SG_NEXT2, SCB_SGPTR2
1054 mov SG_NEXT3, SCB_SGPTR3 ret
1055
1056 /*
1057 * Copying RAM values back to SCB, for Save Data Pointers message, but
1058 * only if we've actually been into a data phase to change them. This
1059 * protects against bogus data in scratch ram and the residual counts
1060 * since they are only initialized when we go into data_in or data_out.
1061 */
1062 sg_ram2scb:
1063 test FLAGS, DPHASE jz return
1064 mov SCB_SGCOUNT,SG_COUNT
1065
1066 mov SCB_SGPTR0,SG_NEXT0
1067 mov SCB_SGPTR1,SG_NEXT1
1068 mov SCB_SGPTR2,SG_NEXT2
1069 mov SCB_SGPTR3,SG_NEXT3
1070
1071 mov SCB_DATAPTR0,SHADDR0
1072 mov SCB_DATAPTR1,SHADDR1
1073 mov SCB_DATAPTR2,SHADDR2
1074 mov SCB_DATAPTR3,SHADDR3
1075
1076 /*
1077 * Use the residual number since STCNT is corrupted by any message transfer
1078 */
1079 mov SCB_DATACNT0,SCB_RESID_DCNT0
1080 mov SCB_DATACNT1,SCB_RESID_DCNT1
1081 mov SCB_DATACNT2,SCB_RESID_DCNT2 ret
1082
1083 /*
1084 * Add the array base TARG_SCRATCH to the target offset (the target address
1085 * is in SCSIID), and return the result in SINDEX. The accumulator
1086 * contains the 3->8 decoding of the target ID on return.
1087 */
1088 ndx_dtr:
1089 shr A,SCSIID,4
1090 test SBLKCTL,SELBUSB jz ndx_dtr_2
1091 or A,0x08 /* Channel B entries add 8 */
1092 ndx_dtr_2:
1093 add SINDEX,TARG_SCRATCH,A ret
1094
1095 /*
1096 * If we need to negotiate transfer parameters, build the WDTR or SDTR message
1097 * starting at the address passed in SINDEX. DINDEX is modified on return.
1098 * The SCSI-II spec requires that Wide negotiation occur first and you can
1099 * only negotiat one or the other at a time otherwise in the event of a message
1100 * reject, you wouldn't be able to tell which message was the culpret.
1101 */
1102 mk_dtr:
1103 test SCB_CONTROL,NEEDWDTR jnz mk_wdtr_16bit
1104 mvi ARG_1, MAXOFFSET /* Force an offset of 15 or 8 if WIDE */
1105
1106 mk_sdtr:
1107 mvi DINDIR,1 /* extended message */
1108 mvi DINDIR,3 /* extended message length = 3 */
1109 mvi DINDIR,1 /* SDTR code */
1110 call sdtr_to_rate
1111 mov DINDIR,RETURN_1 /* REQ/ACK transfer period */
1112 cmp ARG_1, MAXOFFSET je mk_sdtr_max_offset
1113 and DINDIR,0x0f,SINDIR /* Sync Offset */
1114
1115 mk_sdtr_done:
1116 add MSG_LEN,COMP_MSG0,DINDEX ret /* update message length */
1117
1118 mk_sdtr_max_offset:
1119 /*
1120 * We're initiating sync negotiation, so request the max offset we can (15 or 8)
1121 */
1122 /* Talking to a WIDE device? */
1123 test SCSIRATE, WIDEXFER jnz wmax_offset
1124 mvi DINDIR, MAX_OFFSET_8BIT
1125 jmp mk_sdtr_done
1126
1127 wmax_offset:
1128 mvi DINDIR, MAX_OFFSET_16BIT
1129 jmp mk_sdtr_done
1130
1131 mk_wdtr_16bit:
1132 mvi ARG_1,BUS_16_BIT
1133 mk_wdtr:
1134 mvi DINDIR,1 /* extended message */
1135 mvi DINDIR,2 /* extended message length = 2 */
1136 mvi DINDIR,3 /* WDTR code */
1137 mov DINDIR,ARG_1 /* bus width */
1138
1139 add MSG_LEN,COMP_MSG0,DINDEX ret /* update message length */
1140
1141 sdtr_to_rate:
1142 call ndx_dtr /* index scratch space for target */
1143 shr A,SINDIR,0x4
1144 dec SINDEX /* Preserve SINDEX */
1145 and A,0x7
1146 clr RETURN_1
1147 sdtr_to_rate_loop:
1148 test A,0x0f jz sdtr_to_rate_done
1149 add RETURN_1,0x19
1150 dec A
1151 jmp sdtr_to_rate_loop
1152 sdtr_to_rate_done:
1153 shr RETURN_1,0x2
1154 add RETURN_1,0x19
1155 test SXFRCTL0,ULTRAEN jz return
1156 shr RETURN_1,0x1
1157 return:
1158 ret
1159