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