diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx.seq')
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx.seq | 143 |
1 files changed, 120 insertions, 23 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq index bef1f9d369b6..58bc17591b54 100644 --- a/drivers/scsi/aic7xxx/aic79xx.seq +++ b/drivers/scsi/aic7xxx/aic79xx.seq | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Adaptec U320 device driver firmware for Linux and FreeBSD. | 2 | * Adaptec U320 device driver firmware for Linux and FreeBSD. |
3 | * | 3 | * |
4 | * Copyright (c) 1994-2001 Justin T. Gibbs. | 4 | * Copyright (c) 1994-2001, 2004 Justin T. Gibbs. |
5 | * Copyright (c) 2000-2002 Adaptec Inc. | 5 | * Copyright (c) 2000-2002 Adaptec Inc. |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -40,7 +40,7 @@ | |||
40 | * $FreeBSD$ | 40 | * $FreeBSD$ |
41 | */ | 41 | */ |
42 | 42 | ||
43 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $" | 43 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $" |
44 | PATCH_ARG_LIST = "struct ahd_softc *ahd" | 44 | PATCH_ARG_LIST = "struct ahd_softc *ahd" |
45 | PREFIX = "ahd_" | 45 | PREFIX = "ahd_" |
46 | 46 | ||
@@ -110,10 +110,8 @@ check_waiting_list: | |||
110 | * one last time. | 110 | * one last time. |
111 | */ | 111 | */ |
112 | test SSTAT0, SELDO jnz select_out; | 112 | test SSTAT0, SELDO jnz select_out; |
113 | END_CRITICAL; | ||
114 | call start_selection; | 113 | call start_selection; |
115 | idle_loop_checkbus: | 114 | idle_loop_checkbus: |
116 | BEGIN_CRITICAL; | ||
117 | test SSTAT0, SELDO jnz select_out; | 115 | test SSTAT0, SELDO jnz select_out; |
118 | END_CRITICAL; | 116 | END_CRITICAL; |
119 | test SSTAT0, SELDI jnz select_in; | 117 | test SSTAT0, SELDI jnz select_in; |
@@ -294,7 +292,6 @@ fetch_new_scb_inprog: | |||
294 | test CCSCBCTL, ARRDONE jz return; | 292 | test CCSCBCTL, ARRDONE jz return; |
295 | fetch_new_scb_done: | 293 | fetch_new_scb_done: |
296 | and CCSCBCTL, ~(CCARREN|CCSCBEN); | 294 | and CCSCBCTL, ~(CCARREN|CCSCBEN); |
297 | bmov REG0, SCBPTR, 2; | ||
298 | clr A; | 295 | clr A; |
299 | add CMDS_PENDING, 1; | 296 | add CMDS_PENDING, 1; |
300 | adc CMDS_PENDING[1], A; | 297 | adc CMDS_PENDING[1], A; |
@@ -316,43 +313,117 @@ fetch_new_scb_done: | |||
316 | clr SCB_FIFO_USE_COUNT; | 313 | clr SCB_FIFO_USE_COUNT; |
317 | /* Update the next SCB address to download. */ | 314 | /* Update the next SCB address to download. */ |
318 | bmov NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4; | 315 | bmov NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4; |
316 | /* | ||
317 | * NULL out the SCB links since these fields | ||
318 | * occupy the same location as SCB_NEXT_SCB_BUSADDR. | ||
319 | */ | ||
319 | mvi SCB_NEXT[1], SCB_LIST_NULL; | 320 | mvi SCB_NEXT[1], SCB_LIST_NULL; |
320 | mvi SCB_NEXT2[1], SCB_LIST_NULL; | 321 | mvi SCB_NEXT2[1], SCB_LIST_NULL; |
321 | /* Increment our position in the QINFIFO. */ | 322 | /* Increment our position in the QINFIFO. */ |
322 | mov NONE, SNSCB_QOFF; | 323 | mov NONE, SNSCB_QOFF; |
324 | |||
323 | /* | 325 | /* |
324 | * SCBs that want to send messages are always | 326 | * Save SCBID of this SCB in REG0 since |
325 | * queued independently. This ensures that they | 327 | * SCBPTR will be clobbered during target |
326 | * are at the head of the SCB list to select out | 328 | * list updates. We also record the SCB's |
327 | * to a target and we will see the MK_MESSAGE flag. | 329 | * flags so that we can refer to them even |
330 | * after SCBPTR has been changed. | ||
331 | */ | ||
332 | bmov REG0, SCBPTR, 2; | ||
333 | mov A, SCB_CONTROL; | ||
334 | |||
335 | /* | ||
336 | * Find the tail SCB of the execution queue | ||
337 | * for this target. | ||
328 | */ | 338 | */ |
329 | test SCB_CONTROL, MK_MESSAGE jnz first_new_target_scb; | ||
330 | shr SINDEX, 3, SCB_SCSIID; | 339 | shr SINDEX, 3, SCB_SCSIID; |
331 | and SINDEX, ~0x1; | 340 | and SINDEX, ~0x1; |
332 | mvi SINDEX[1], (WAITING_SCB_TAILS >> 8); | 341 | mvi SINDEX[1], (WAITING_SCB_TAILS >> 8); |
333 | bmov DINDEX, SINDEX, 2; | 342 | bmov DINDEX, SINDEX, 2; |
334 | bmov SCBPTR, SINDIR, 2; | 343 | bmov SCBPTR, SINDIR, 2; |
344 | |||
345 | /* | ||
346 | * Update the tail to point to the new SCB. | ||
347 | */ | ||
335 | bmov DINDIR, REG0, 2; | 348 | bmov DINDIR, REG0, 2; |
349 | |||
350 | /* | ||
351 | * If the queue was empty, queue this SCB as | ||
352 | * the first for this target. | ||
353 | */ | ||
336 | cmp SCBPTR[1], SCB_LIST_NULL je first_new_target_scb; | 354 | cmp SCBPTR[1], SCB_LIST_NULL je first_new_target_scb; |
355 | |||
356 | /* | ||
357 | * SCBs that want to send messages must always be | ||
358 | * at the head of their per-target queue so that | ||
359 | * ATN can be asserted even if the current | ||
360 | * negotiation agreement is packetized. If the | ||
361 | * target queue is empty, the SCB can be queued | ||
362 | * immediately. If the queue is not empty, we must | ||
363 | * wait for it to empty before entering this SCB | ||
364 | * into the waiting for selection queue. Otherwise | ||
365 | * our batching and round-robin selection scheme | ||
366 | * could allow commands to be queued out of order. | ||
367 | * To simplify the implementation, we stop pulling | ||
368 | * new commands from the host until the MK_MESSAGE | ||
369 | * SCB can be queued to the waiting for selection | ||
370 | * list. | ||
371 | */ | ||
372 | test A, MK_MESSAGE jz batch_scb; | ||
373 | |||
374 | /* | ||
375 | * If the last SCB is also a MK_MESSAGE SCB, then | ||
376 | * order is preserved even if we batch. | ||
377 | */ | ||
378 | test SCB_CONTROL, MK_MESSAGE jz batch_scb; | ||
379 | |||
380 | /* | ||
381 | * Defer this SCB and stop fetching new SCBs until | ||
382 | * it can be queued. Since the SCB_SCSIID of the | ||
383 | * tail SCB must be the same as that of the newly | ||
384 | * queued SCB, there is no need to restore the SCBID | ||
385 | * here. | ||
386 | */ | ||
387 | or SEQ_FLAGS2, PENDING_MK_MESSAGE; | ||
388 | bmov MK_MESSAGE_SCB, REG0, 2; | ||
389 | mov MK_MESSAGE_SCSIID, SCB_SCSIID ret; | ||
390 | |||
391 | batch_scb: | ||
392 | /* | ||
393 | * Otherwise just update the previous tail SCB to | ||
394 | * point to the new tail. | ||
395 | */ | ||
337 | bmov SCB_NEXT, REG0, 2 ret; | 396 | bmov SCB_NEXT, REG0, 2 ret; |
397 | |||
338 | first_new_target_scb: | 398 | first_new_target_scb: |
399 | /* | ||
400 | * Append SCB to the tail of the waiting for | ||
401 | * selection list. | ||
402 | */ | ||
339 | cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je first_new_scb; | 403 | cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je first_new_scb; |
340 | bmov SCBPTR, WAITING_TID_TAIL, 2; | 404 | bmov SCBPTR, WAITING_TID_TAIL, 2; |
341 | bmov SCB_NEXT2, REG0, 2; | 405 | bmov SCB_NEXT2, REG0, 2; |
342 | bmov WAITING_TID_TAIL, REG0, 2 ret; | 406 | bmov WAITING_TID_TAIL, REG0, 2 ret; |
343 | first_new_scb: | 407 | first_new_scb: |
408 | /* | ||
409 | * Whole list is empty, so the head of | ||
410 | * the list must be initialized too. | ||
411 | */ | ||
344 | bmov WAITING_TID_HEAD, REG0, 2; | 412 | bmov WAITING_TID_HEAD, REG0, 2; |
345 | bmov WAITING_TID_TAIL, REG0, 2 ret; | 413 | bmov WAITING_TID_TAIL, REG0, 2 ret; |
346 | END_CRITICAL; | 414 | END_CRITICAL; |
347 | 415 | ||
348 | scbdma_idle: | 416 | scbdma_idle: |
349 | /* | 417 | /* |
350 | * Give precedence to downloading new SCBs to execute | 418 | * Don't bother downloading new SCBs to execute |
351 | * unless select-outs are currently frozen. | 419 | * if select-outs are currently frozen or we have |
420 | * a MK_MESSAGE SCB waiting to enter the queue. | ||
352 | */ | 421 | */ |
353 | test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz . + 2; | 422 | test SEQ_FLAGS2, SELECTOUT_QFROZEN|PENDING_MK_MESSAGE |
423 | jnz scbdma_no_new_scbs; | ||
354 | BEGIN_CRITICAL; | 424 | BEGIN_CRITICAL; |
355 | test QOFF_CTLSTA, NEW_SCB_AVAIL jnz fetch_new_scb; | 425 | test QOFF_CTLSTA, NEW_SCB_AVAIL jnz fetch_new_scb; |
426 | scbdma_no_new_scbs: | ||
356 | cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne dma_complete_scb; | 427 | cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne dma_complete_scb; |
357 | cmp COMPLETE_SCB_HEAD[1], SCB_LIST_NULL je return; | 428 | cmp COMPLETE_SCB_HEAD[1], SCB_LIST_NULL je return; |
358 | /* FALLTHROUGH */ | 429 | /* FALLTHROUGH */ |
@@ -671,27 +742,41 @@ curscb_ww_done: | |||
671 | } | 742 | } |
672 | 743 | ||
673 | /* | 744 | /* |
674 | * Requeue any SCBs not sent, to the tail of the waiting Q. | 745 | * The whole list made it. Clear our tail pointer to indicate |
746 | * that the per-target selection queue is now empty. | ||
675 | */ | 747 | */ |
676 | cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_list_done; | 748 | cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_clear_tail; |
677 | 749 | ||
678 | /* | 750 | /* |
751 | * Requeue any SCBs not sent, to the tail of the waiting Q. | ||
679 | * We know that neither the per-TID list nor the list of | 752 | * We know that neither the per-TID list nor the list of |
680 | * TIDs is empty. Use this knowledge to our advantage. | 753 | * TIDs is empty. Use this knowledge to our advantage and |
754 | * queue the remainder to the tail of the global execution | ||
755 | * queue. | ||
681 | */ | 756 | */ |
682 | bmov REG0, SCB_NEXT, 2; | 757 | bmov REG0, SCB_NEXT, 2; |
758 | select_out_queue_remainder: | ||
683 | bmov SCBPTR, WAITING_TID_TAIL, 2; | 759 | bmov SCBPTR, WAITING_TID_TAIL, 2; |
684 | bmov SCB_NEXT2, REG0, 2; | 760 | bmov SCB_NEXT2, REG0, 2; |
685 | bmov WAITING_TID_TAIL, REG0, 2; | 761 | bmov WAITING_TID_TAIL, REG0, 2; |
686 | jmp select_out_inc_tid_q; | 762 | jmp select_out_inc_tid_q; |
687 | 763 | ||
688 | select_out_list_done: | 764 | select_out_clear_tail: |
765 | /* | ||
766 | * Queue any pending MK_MESSAGE SCB for this target now | ||
767 | * that the queue is empty. | ||
768 | */ | ||
769 | test SEQ_FLAGS2, PENDING_MK_MESSAGE jz select_out_no_mk_message_scb; | ||
770 | mov A, MK_MESSAGE_SCSIID; | ||
771 | cmp SCB_SCSIID, A jne select_out_no_mk_message_scb; | ||
772 | and SEQ_FLAGS2, ~PENDING_MK_MESSAGE; | ||
773 | bmov REG0, MK_MESSAGE_SCB, 2; | ||
774 | jmp select_out_queue_remainder; | ||
775 | |||
776 | select_out_no_mk_message_scb: | ||
689 | /* | 777 | /* |
690 | * The whole list made it. Just clear our TID's tail pointer | 778 | * Clear this target's execution tail and increment the queue. |
691 | * unless we were queued independently due to our need to | ||
692 | * send a message. | ||
693 | */ | 779 | */ |
694 | test SCB_CONTROL, MK_MESSAGE jnz select_out_inc_tid_q; | ||
695 | shr DINDEX, 3, SCB_SCSIID; | 780 | shr DINDEX, 3, SCB_SCSIID; |
696 | or DINDEX, 1; /* Want only the second byte */ | 781 | or DINDEX, 1; /* Want only the second byte */ |
697 | mvi DINDEX[1], ((WAITING_SCB_TAILS) >> 8); | 782 | mvi DINDEX[1], ((WAITING_SCB_TAILS) >> 8); |
@@ -703,8 +788,8 @@ select_out_inc_tid_q: | |||
703 | mvi WAITING_TID_TAIL[1], SCB_LIST_NULL; | 788 | mvi WAITING_TID_TAIL[1], SCB_LIST_NULL; |
704 | bmov SCBPTR, CURRSCB, 2; | 789 | bmov SCBPTR, CURRSCB, 2; |
705 | mvi CLRSINT0, CLRSELDO; | 790 | mvi CLRSINT0, CLRSELDO; |
706 | test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_phase; | 791 | test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_mode_cleared; |
707 | test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_phase; | 792 | test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_mode_cleared; |
708 | 793 | ||
709 | /* | 794 | /* |
710 | * If this is a packetized connection, return to our | 795 | * If this is a packetized connection, return to our |
@@ -2127,6 +2212,18 @@ SET_DST_MODE M_DFF0; | |||
2127 | mvi DFFSXFRCTL, CLRCHN; | 2212 | mvi DFFSXFRCTL, CLRCHN; |
2128 | unexpected_nonpkt_mode_cleared: | 2213 | unexpected_nonpkt_mode_cleared: |
2129 | mvi CLRSINT2, CLRNONPACKREQ; | 2214 | mvi CLRSINT2, CLRNONPACKREQ; |
2215 | if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { | ||
2216 | /* | ||
2217 | * Test to ensure that the bus has not | ||
2218 | * already gone free prior to clearing | ||
2219 | * any stale busfree status. This avoids | ||
2220 | * a window whereby a busfree just after | ||
2221 | * a selection could be missed. | ||
2222 | */ | ||
2223 | test SCSISIGI, BSYI jz . + 2; | ||
2224 | mvi CLRSINT1,CLRBUSFREE; | ||
2225 | or SIMODE1, ENBUSFREE; | ||
2226 | } | ||
2130 | test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase; | 2227 | test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase; |
2131 | SET_SEQINTCODE(ENTERING_NONPACK) | 2228 | SET_SEQINTCODE(ENTERING_NONPACK) |
2132 | jmp ITloop; | 2229 | jmp ITloop; |