diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx.seq')
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx.seq | 241 |
1 files changed, 188 insertions, 53 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq index 65339bc1ca99..bef1f9d369b6 100644 --- a/drivers/scsi/aic7xxx/aic79xx.seq +++ b/drivers/scsi/aic7xxx/aic79xx.seq | |||
@@ -40,7 +40,7 @@ | |||
40 | * $FreeBSD$ | 40 | * $FreeBSD$ |
41 | */ | 41 | */ |
42 | 42 | ||
43 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#99 $" | 43 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $" |
44 | PATCH_ARG_LIST = "struct ahd_softc *ahd" | 44 | PATCH_ARG_LIST = "struct ahd_softc *ahd" |
45 | PREFIX = "ahd_" | 45 | PREFIX = "ahd_" |
46 | 46 | ||
@@ -68,13 +68,47 @@ no_error_set: | |||
68 | } | 68 | } |
69 | SET_MODE(M_SCSI, M_SCSI) | 69 | SET_MODE(M_SCSI, M_SCSI) |
70 | test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus; | 70 | test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus; |
71 | test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus; | 71 | test SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list; |
72 | /* | ||
73 | * If the kernel has caught up with us, thaw the queue. | ||
74 | */ | ||
75 | mov A, KERNEL_QFREEZE_COUNT; | ||
76 | cmp QFREEZE_COUNT, A jne check_frozen_completions; | ||
77 | mov A, KERNEL_QFREEZE_COUNT[1]; | ||
78 | cmp QFREEZE_COUNT[1], A jne check_frozen_completions; | ||
79 | and SEQ_FLAGS2, ~SELECTOUT_QFROZEN; | ||
80 | jmp check_waiting_list; | ||
81 | check_frozen_completions: | ||
82 | test SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus; | ||
83 | BEGIN_CRITICAL; | ||
84 | /* | ||
85 | * If we have completions stalled waiting for the qfreeze | ||
86 | * to take effect, move them over to the complete_scb list | ||
87 | * now that no selections are pending. | ||
88 | */ | ||
89 | cmp COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus; | ||
90 | /* | ||
91 | * Find the end of the qfreeze list. The first element has | ||
92 | * to be treated specially. | ||
93 | */ | ||
94 | bmov SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2; | ||
95 | cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists; | ||
96 | /* | ||
97 | * Now the normal loop. | ||
98 | */ | ||
99 | bmov SCBPTR, SCB_NEXT_COMPLETE, 2; | ||
100 | cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1; | ||
101 | join_lists: | ||
102 | bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; | ||
103 | bmov COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2; | ||
104 | mvi COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL; | ||
105 | jmp idle_loop_checkbus; | ||
106 | check_waiting_list: | ||
72 | cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus; | 107 | cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus; |
73 | /* | 108 | /* |
74 | * ENSELO is cleared by a SELDO, so we must test for SELDO | 109 | * ENSELO is cleared by a SELDO, so we must test for SELDO |
75 | * one last time. | 110 | * one last time. |
76 | */ | 111 | */ |
77 | BEGIN_CRITICAL; | ||
78 | test SSTAT0, SELDO jnz select_out; | 112 | test SSTAT0, SELDO jnz select_out; |
79 | END_CRITICAL; | 113 | END_CRITICAL; |
80 | call start_selection; | 114 | call start_selection; |
@@ -90,6 +124,13 @@ idle_loop_check_nonpackreq: | |||
90 | test SSTAT2, NONPACKREQ jz . + 2; | 124 | test SSTAT2, NONPACKREQ jz . + 2; |
91 | call unexpected_nonpkt_phase_find_ctxt; | 125 | call unexpected_nonpkt_phase_find_ctxt; |
92 | if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { | 126 | if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { |
127 | /* | ||
128 | * On Rev A. hardware, the busy LED is only | ||
129 | * turned on automaically during selections | ||
130 | * and re-selections. Make the LED status | ||
131 | * more useful by forcing it to be on so | ||
132 | * long as one of our data FIFOs is active. | ||
133 | */ | ||
93 | and A, FIFO0FREE|FIFO1FREE, DFFSTAT; | 134 | and A, FIFO0FREE|FIFO1FREE, DFFSTAT; |
94 | cmp A, FIFO0FREE|FIFO1FREE jne . + 3; | 135 | cmp A, FIFO0FREE|FIFO1FREE jne . + 3; |
95 | and SBLKCTL, ~DIAGLEDEN|DIAGLEDON; | 136 | and SBLKCTL, ~DIAGLEDEN|DIAGLEDON; |
@@ -101,9 +142,9 @@ idle_loop_check_nonpackreq: | |||
101 | call idle_loop_cchan; | 142 | call idle_loop_cchan; |
102 | jmp idle_loop; | 143 | jmp idle_loop; |
103 | 144 | ||
104 | BEGIN_CRITICAL; | ||
105 | idle_loop_gsfifo: | 145 | idle_loop_gsfifo: |
106 | SET_MODE(M_SCSI, M_SCSI) | 146 | SET_MODE(M_SCSI, M_SCSI) |
147 | BEGIN_CRITICAL; | ||
107 | idle_loop_gsfifo_in_scsi_mode: | 148 | idle_loop_gsfifo_in_scsi_mode: |
108 | test LQISTAT2, LQIGSAVAIL jz return; | 149 | test LQISTAT2, LQIGSAVAIL jz return; |
109 | /* | 150 | /* |
@@ -152,11 +193,15 @@ END_CRITICAL; | |||
152 | 193 | ||
153 | idle_loop_service_fifos: | 194 | idle_loop_service_fifos: |
154 | SET_MODE(M_DFF0, M_DFF0) | 195 | SET_MODE(M_DFF0, M_DFF0) |
196 | BEGIN_CRITICAL; | ||
155 | test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo; | 197 | test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo; |
156 | call longjmp; | 198 | call longjmp; |
199 | END_CRITICAL; | ||
157 | idle_loop_next_fifo: | 200 | idle_loop_next_fifo: |
158 | SET_MODE(M_DFF1, M_DFF1) | 201 | SET_MODE(M_DFF1, M_DFF1) |
202 | BEGIN_CRITICAL; | ||
159 | test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp; | 203 | test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp; |
204 | END_CRITICAL; | ||
160 | return: | 205 | return: |
161 | ret; | 206 | ret; |
162 | 207 | ||
@@ -170,7 +215,6 @@ BEGIN_CRITICAL; | |||
170 | test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle; | 215 | test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle; |
171 | test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog; | 216 | test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog; |
172 | test CCSCBCTL, CCSCBDONE jz return; | 217 | test CCSCBCTL, CCSCBDONE jz return; |
173 | END_CRITICAL; | ||
174 | /* FALLTHROUGH */ | 218 | /* FALLTHROUGH */ |
175 | scbdma_tohost_done: | 219 | scbdma_tohost_done: |
176 | test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; | 220 | test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; |
@@ -180,26 +224,18 @@ scbdma_tohost_done: | |||
180 | * bad SCSI status (currently only for underruns), we | 224 | * bad SCSI status (currently only for underruns), we |
181 | * queue the SCB for normal completion. Otherwise, we | 225 | * queue the SCB for normal completion. Otherwise, we |
182 | * wait until any select-out activity has halted, and | 226 | * wait until any select-out activity has halted, and |
183 | * then notify the host so that the transaction can be | 227 | * then queue the completion. |
184 | * dealt with. | ||
185 | */ | 228 | */ |
186 | test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host; | ||
187 | and CCSCBCTL, ~(CCARREN|CCSCBEN); | 229 | and CCSCBCTL, ~(CCARREN|CCSCBEN); |
188 | bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; | 230 | bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; |
231 | cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2; | ||
232 | mvi COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL; | ||
233 | test SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion; | ||
234 | bmov SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2; | ||
235 | bmov COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret; | ||
236 | scbdma_queue_completion: | ||
189 | bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; | 237 | bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; |
190 | bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; | 238 | bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; |
191 | scbdma_notify_host: | ||
192 | SET_MODE(M_SCSI, M_SCSI) | ||
193 | test SCSISEQ0, ENSELO jnz return; | ||
194 | test SSTAT0, (SELDO|SELINGO) jnz return; | ||
195 | SET_MODE(M_CCHAN, M_CCHAN) | ||
196 | /* | ||
197 | * Remove SCB and notify host. | ||
198 | */ | ||
199 | and CCSCBCTL, ~(CCARREN|CCSCBEN); | ||
200 | bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; | ||
201 | SET_SEQINTCODE(BAD_SCB_STATUS) | ||
202 | ret; | ||
203 | fill_qoutfifo_dmadone: | 239 | fill_qoutfifo_dmadone: |
204 | and CCSCBCTL, ~(CCARREN|CCSCBEN); | 240 | and CCSCBCTL, ~(CCARREN|CCSCBEN); |
205 | call qoutfifo_updated; | 241 | call qoutfifo_updated; |
@@ -208,6 +244,7 @@ fill_qoutfifo_dmadone: | |||
208 | test QOFF_CTLSTA, SDSCB_ROLLOVR jz return; | 244 | test QOFF_CTLSTA, SDSCB_ROLLOVR jz return; |
209 | bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4; | 245 | bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4; |
210 | xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret; | 246 | xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret; |
247 | END_CRITICAL; | ||
211 | 248 | ||
212 | qoutfifo_updated: | 249 | qoutfifo_updated: |
213 | /* | 250 | /* |
@@ -324,14 +361,15 @@ fill_qoutfifo: | |||
324 | * Keep track of the SCBs we are dmaing just | 361 | * Keep track of the SCBs we are dmaing just |
325 | * in case the DMA fails or is aborted. | 362 | * in case the DMA fails or is aborted. |
326 | */ | 363 | */ |
327 | mov A, QOUTFIFO_ENTRY_VALID_TAG; | ||
328 | bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2; | 364 | bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2; |
329 | mvi CCSCBCTL, CCSCBRESET; | 365 | mvi CCSCBCTL, CCSCBRESET; |
330 | bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4; | 366 | bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4; |
367 | mov A, QOUTFIFO_NEXT_ADDR; | ||
331 | bmov SCBPTR, COMPLETE_SCB_HEAD, 2; | 368 | bmov SCBPTR, COMPLETE_SCB_HEAD, 2; |
332 | fill_qoutfifo_loop: | 369 | fill_qoutfifo_loop: |
333 | mov CCSCBRAM, SCBPTR; | 370 | bmov CCSCBRAM, SCBPTR, 2; |
334 | or CCSCBRAM, A, SCBPTR[1]; | 371 | mov CCSCBRAM, SCB_SGPTR[0]; |
372 | mov CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG; | ||
335 | mov NONE, SDSCB_QOFF; | 373 | mov NONE, SDSCB_QOFF; |
336 | inc INT_COALESCING_CMDCOUNT; | 374 | inc INT_COALESCING_CMDCOUNT; |
337 | add CMDS_PENDING, -1; | 375 | add CMDS_PENDING, -1; |
@@ -339,6 +377,18 @@ fill_qoutfifo_loop: | |||
339 | cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done; | 377 | cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done; |
340 | cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done; | 378 | cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done; |
341 | test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done; | 379 | test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done; |
380 | /* | ||
381 | * Don't cross an ADB or Cachline boundary when DMA'ing | ||
382 | * completion entries. In PCI mode, at least in 32/33 | ||
383 | * configurations, the SCB DMA engine may lose its place | ||
384 | * in the data-stream should the target force a retry on | ||
385 | * something other than an 8byte aligned boundary. In | ||
386 | * PCI-X mode, we do this to avoid split transactions since | ||
387 | * many chipsets seem to be unable to format proper split | ||
388 | * completions to continue the data transfer. | ||
389 | */ | ||
390 | add SINDEX, A, CCSCBADDR; | ||
391 | test SINDEX, CACHELINE_MASK jz fill_qoutfifo_done; | ||
342 | bmov SCBPTR, SCB_NEXT_COMPLETE, 2; | 392 | bmov SCBPTR, SCB_NEXT_COMPLETE, 2; |
343 | jmp fill_qoutfifo_loop; | 393 | jmp fill_qoutfifo_loop; |
344 | fill_qoutfifo_done: | 394 | fill_qoutfifo_done: |
@@ -354,7 +404,6 @@ dma_complete_scb: | |||
354 | bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2; | 404 | bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2; |
355 | bmov SCBHADDR, SCB_BUSADDR, 4; | 405 | bmov SCBHADDR, SCB_BUSADDR, 4; |
356 | mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb; | 406 | mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb; |
357 | END_CRITICAL; | ||
358 | 407 | ||
359 | /* | 408 | /* |
360 | * Either post or fetch an SCB from host memory. The caller | 409 | * Either post or fetch an SCB from host memory. The caller |
@@ -371,9 +420,19 @@ dma_scb: | |||
371 | mvi SCBHCNT, SCB_TRANSFER_SIZE; | 420 | mvi SCBHCNT, SCB_TRANSFER_SIZE; |
372 | mov CCSCBCTL, SINDEX ret; | 421 | mov CCSCBCTL, SINDEX ret; |
373 | 422 | ||
374 | BEGIN_CRITICAL; | ||
375 | setjmp: | 423 | setjmp: |
376 | bmov LONGJMP_ADDR, STACK, 2 ret; | 424 | /* |
425 | * At least on the A, a return in the same | ||
426 | * instruction as the bmov results in a return | ||
427 | * to the caller, not to the new address at the | ||
428 | * top of the stack. Since we want the latter | ||
429 | * (we use setjmp to register a handler from an | ||
430 | * interrupt context but not invoke that handler | ||
431 | * until we return to our idle loop), use a | ||
432 | * separate ret instruction. | ||
433 | */ | ||
434 | bmov LONGJMP_ADDR, STACK, 2; | ||
435 | ret; | ||
377 | setjmp_inline: | 436 | setjmp_inline: |
378 | bmov LONGJMP_ADDR, STACK, 2; | 437 | bmov LONGJMP_ADDR, STACK, 2; |
379 | longjmp: | 438 | longjmp: |
@@ -392,11 +451,6 @@ set_mode_work_around: | |||
392 | mvi SEQINTCTL, INTVEC1DSL; | 451 | mvi SEQINTCTL, INTVEC1DSL; |
393 | mov MODE_PTR, SINDEX; | 452 | mov MODE_PTR, SINDEX; |
394 | clr SEQINTCTL ret; | 453 | clr SEQINTCTL ret; |
395 | |||
396 | toggle_dff_mode_work_around: | ||
397 | mvi SEQINTCTL, INTVEC1DSL; | ||
398 | xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); | ||
399 | clr SEQINTCTL ret; | ||
400 | } | 454 | } |
401 | 455 | ||
402 | 456 | ||
@@ -490,6 +544,21 @@ allocate_fifo1: | |||
490 | SET_SRC_MODE M_SCSI; | 544 | SET_SRC_MODE M_SCSI; |
491 | SET_DST_MODE M_SCSI; | 545 | SET_DST_MODE M_SCSI; |
492 | select_in: | 546 | select_in: |
547 | if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { | ||
548 | /* | ||
549 | * On Rev A. hardware, the busy LED is only | ||
550 | * turned on automaically during selections | ||
551 | * and re-selections. Make the LED status | ||
552 | * more useful by forcing it to be on from | ||
553 | * the point of selection until our idle | ||
554 | * loop determines that neither of our FIFOs | ||
555 | * are busy. This handles the non-packetized | ||
556 | * case nicely as we will not return to the | ||
557 | * idle loop until the busfree at the end of | ||
558 | * each transaction. | ||
559 | */ | ||
560 | or SBLKCTL, DIAGLEDEN|DIAGLEDON; | ||
561 | } | ||
493 | if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { | 562 | if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { |
494 | /* | 563 | /* |
495 | * Test to ensure that the bus has not | 564 | * Test to ensure that the bus has not |
@@ -528,6 +597,21 @@ SET_SRC_MODE M_SCSI; | |||
528 | SET_DST_MODE M_SCSI; | 597 | SET_DST_MODE M_SCSI; |
529 | select_out: | 598 | select_out: |
530 | BEGIN_CRITICAL; | 599 | BEGIN_CRITICAL; |
600 | if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { | ||
601 | /* | ||
602 | * On Rev A. hardware, the busy LED is only | ||
603 | * turned on automaically during selections | ||
604 | * and re-selections. Make the LED status | ||
605 | * more useful by forcing it to be on from | ||
606 | * the point of re-selection until our idle | ||
607 | * loop determines that neither of our FIFOs | ||
608 | * are busy. This handles the non-packetized | ||
609 | * case nicely as we will not return to the | ||
610 | * idle loop until the busfree at the end of | ||
611 | * each transaction. | ||
612 | */ | ||
613 | or SBLKCTL, DIAGLEDEN|DIAGLEDON; | ||
614 | } | ||
531 | /* Clear out all SCBs that have been successfully sent. */ | 615 | /* Clear out all SCBs that have been successfully sent. */ |
532 | if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { | 616 | if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { |
533 | /* | 617 | /* |
@@ -1000,15 +1084,9 @@ not_found_ITloop: | |||
1000 | /* | 1084 | /* |
1001 | * We received a "command complete" message. Put the SCB on the complete | 1085 | * We received a "command complete" message. Put the SCB on the complete |
1002 | * queue and trigger a completion interrupt via the idle loop. Before doing | 1086 | * queue and trigger a completion interrupt via the idle loop. Before doing |
1003 | * so, check to see if there | 1087 | * so, check to see if there is a residual or the status byte is something |
1004 | * is a residual or the status byte is something other than STATUS_GOOD (0). | 1088 | * other than STATUS_GOOD (0). In either of these conditions, we upload the |
1005 | * In either of these conditions, we upload the SCB back to the host so it can | 1089 | * SCB back to the host so it can process this information. |
1006 | * process this information. In the case of a non zero status byte, we | ||
1007 | * additionally interrupt the kernel driver synchronously, allowing it to | ||
1008 | * decide if sense should be retrieved. If the kernel driver wishes to request | ||
1009 | * sense, it will fill the kernel SCB with a request sense command, requeue | ||
1010 | * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting | ||
1011 | * RETURN_1 to SEND_SENSE. | ||
1012 | */ | 1090 | */ |
1013 | mesgin_complete: | 1091 | mesgin_complete: |
1014 | 1092 | ||
@@ -1053,6 +1131,7 @@ complete_nomsg: | |||
1053 | call queue_scb_completion; | 1131 | call queue_scb_completion; |
1054 | jmp await_busfree; | 1132 | jmp await_busfree; |
1055 | 1133 | ||
1134 | BEGIN_CRITICAL; | ||
1056 | freeze_queue: | 1135 | freeze_queue: |
1057 | /* Cancel any pending select-out. */ | 1136 | /* Cancel any pending select-out. */ |
1058 | test SSTAT0, SELDO|SELINGO jnz . + 2; | 1137 | test SSTAT0, SELDO|SELINGO jnz . + 2; |
@@ -1063,6 +1142,7 @@ freeze_queue: | |||
1063 | adc QFREEZE_COUNT[1], A; | 1142 | adc QFREEZE_COUNT[1], A; |
1064 | or SEQ_FLAGS2, SELECTOUT_QFROZEN; | 1143 | or SEQ_FLAGS2, SELECTOUT_QFROZEN; |
1065 | mov A, ACCUM_SAVE ret; | 1144 | mov A, ACCUM_SAVE ret; |
1145 | END_CRITICAL; | ||
1066 | 1146 | ||
1067 | /* | 1147 | /* |
1068 | * Complete the current FIFO's SCB if data for this same | 1148 | * Complete the current FIFO's SCB if data for this same |
@@ -1085,8 +1165,10 @@ queue_scb_completion: | |||
1085 | test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ | 1165 | test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ |
1086 | test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; | 1166 | test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; |
1087 | complete: | 1167 | complete: |
1168 | BEGIN_CRITICAL; | ||
1088 | bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; | 1169 | bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; |
1089 | bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; | 1170 | bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; |
1171 | END_CRITICAL; | ||
1090 | bad_status: | 1172 | bad_status: |
1091 | cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; | 1173 | cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; |
1092 | call freeze_queue; | 1174 | call freeze_queue; |
@@ -1097,9 +1179,18 @@ upload_scb: | |||
1097 | * it on the host. | 1179 | * it on the host. |
1098 | */ | 1180 | */ |
1099 | bmov SCB_TAG, SCBPTR, 2; | 1181 | bmov SCB_TAG, SCBPTR, 2; |
1100 | bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2; | 1182 | BEGIN_CRITICAL; |
1183 | or SCB_SGPTR, SG_STATUS_VALID; | ||
1184 | mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL; | ||
1185 | cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail; | ||
1101 | bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; | 1186 | bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; |
1102 | or SCB_SGPTR, SG_STATUS_VALID ret; | 1187 | bmov COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret; |
1188 | add_dma_scb_tail: | ||
1189 | bmov REG0, SCBPTR, 2; | ||
1190 | bmov SCBPTR, COMPLETE_DMA_SCB_TAIL, 2; | ||
1191 | bmov SCB_NEXT_COMPLETE, REG0, 2; | ||
1192 | bmov COMPLETE_DMA_SCB_TAIL, REG0, 2 ret; | ||
1193 | END_CRITICAL; | ||
1103 | 1194 | ||
1104 | /* | 1195 | /* |
1105 | * Is it a disconnect message? Set a flag in the SCB to remind us | 1196 | * Is it a disconnect message? Set a flag in the SCB to remind us |
@@ -1146,8 +1237,18 @@ SET_DST_MODE M_DFF1; | |||
1146 | await_busfree_clrchn: | 1237 | await_busfree_clrchn: |
1147 | mvi DFFSXFRCTL, CLRCHN; | 1238 | mvi DFFSXFRCTL, CLRCHN; |
1148 | await_busfree_not_m_dff: | 1239 | await_busfree_not_m_dff: |
1149 | call clear_target_state; | 1240 | /* clear target specific flags */ |
1241 | mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; | ||
1150 | test SSTAT1,REQINIT|BUSFREE jz .; | 1242 | test SSTAT1,REQINIT|BUSFREE jz .; |
1243 | /* | ||
1244 | * We only set BUSFREE status once either a new | ||
1245 | * phase has been detected or we are really | ||
1246 | * BUSFREE. This allows the driver to know | ||
1247 | * that we are active on the bus even though | ||
1248 | * no identified transaction exists should a | ||
1249 | * timeout occur while awaiting busfree. | ||
1250 | */ | ||
1251 | mvi LASTPHASE, P_BUSFREE; | ||
1151 | test SSTAT1, BUSFREE jnz idle_loop; | 1252 | test SSTAT1, BUSFREE jnz idle_loop; |
1152 | SET_SEQINTCODE(MISSED_BUSFREE) | 1253 | SET_SEQINTCODE(MISSED_BUSFREE) |
1153 | 1254 | ||
@@ -1202,11 +1303,6 @@ msgin_rdptrs_get_fifo: | |||
1202 | call allocate_fifo; | 1303 | call allocate_fifo; |
1203 | jmp mesgin_done; | 1304 | jmp mesgin_done; |
1204 | 1305 | ||
1205 | clear_target_state: | ||
1206 | mvi LASTPHASE, P_BUSFREE; | ||
1207 | /* clear target specific flags */ | ||
1208 | mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret; | ||
1209 | |||
1210 | phase_lock: | 1306 | phase_lock: |
1211 | if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) { | 1307 | if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) { |
1212 | /* | 1308 | /* |
@@ -1298,6 +1394,47 @@ service_fifo: | |||
1298 | test CCSGCTL, CCSGENACK jnz return; | 1394 | test CCSGCTL, CCSGENACK jnz return; |
1299 | 1395 | ||
1300 | /* | 1396 | /* |
1397 | * Should the other FIFO get the S/G cache first? If | ||
1398 | * both FIFOs have been allocated since we last checked | ||
1399 | * any FIFO, it is important that we service a FIFO | ||
1400 | * that is not actively on the bus first. This guarantees | ||
1401 | * that a FIFO will be freed to handle snapshot requests for | ||
1402 | * any FIFO that is still on the bus. Chips with RTI do not | ||
1403 | * perform snapshots, so don't bother with this test there. | ||
1404 | */ | ||
1405 | if ((ahd->features & AHD_RTI) == 0) { | ||
1406 | /* | ||
1407 | * If we're not still receiving SCSI data, | ||
1408 | * it is safe to allocate the S/G cache to | ||
1409 | * this FIFO. | ||
1410 | */ | ||
1411 | test DFCNTRL, SCSIEN jz idle_sgfetch_start; | ||
1412 | |||
1413 | /* | ||
1414 | * Switch to the other FIFO. Non-RTI chips | ||
1415 | * also have the "set mode" bug, so we must | ||
1416 | * disable interrupts during the switch. | ||
1417 | */ | ||
1418 | mvi SEQINTCTL, INTVEC1DSL; | ||
1419 | xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); | ||
1420 | |||
1421 | /* | ||
1422 | * If the other FIFO needs loading, then it | ||
1423 | * must not have claimed the S/G cache yet | ||
1424 | * (SG_CACHE_AVAIL would have been cleared in | ||
1425 | * the orginal FIFO mode and we test this above). | ||
1426 | * Return to the idle loop so we can process the | ||
1427 | * FIFO not currently on the bus first. | ||
1428 | */ | ||
1429 | test SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay; | ||
1430 | clr SEQINTCTL ret; | ||
1431 | idle_sgfetch_okay: | ||
1432 | xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); | ||
1433 | clr SEQINTCTL; | ||
1434 | } | ||
1435 | |||
1436 | idle_sgfetch_start: | ||
1437 | /* | ||
1301 | * We fetch a "cacheline aligned" and sized amount of data | 1438 | * We fetch a "cacheline aligned" and sized amount of data |
1302 | * so we don't end up referencing a non-existant page. | 1439 | * so we don't end up referencing a non-existant page. |
1303 | * Cacheline aligned is in quotes because the kernel will | 1440 | * Cacheline aligned is in quotes because the kernel will |
@@ -1308,7 +1445,7 @@ service_fifo: | |||
1308 | mvi SGHCNT, SG_PREFETCH_CNT; | 1445 | mvi SGHCNT, SG_PREFETCH_CNT; |
1309 | if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) { | 1446 | if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) { |
1310 | /* | 1447 | /* |
1311 | * Need two instruction between "touches" of SGHADDR. | 1448 | * Need two instructions between "touches" of SGHADDR. |
1312 | */ | 1449 | */ |
1313 | nop; | 1450 | nop; |
1314 | } | 1451 | } |
@@ -1658,7 +1795,7 @@ export seq_isr: | |||
1658 | * savepointer in the current FIFO. We do this so that | 1795 | * savepointer in the current FIFO. We do this so that |
1659 | * a pending CTXTDONE or SAVEPTR is visible in the active | 1796 | * a pending CTXTDONE or SAVEPTR is visible in the active |
1660 | * FIFO. This status is the only way we can detect if we | 1797 | * FIFO. This status is the only way we can detect if we |
1661 | * have lost the race (e.g. host paused us) and our attepts | 1798 | * have lost the race (e.g. host paused us) and our attempts |
1662 | * to disable the channel occurred after all REQs were | 1799 | * to disable the channel occurred after all REQs were |
1663 | * already seen and acked (REQINIT never comes true). | 1800 | * already seen and acked (REQINIT never comes true). |
1664 | */ | 1801 | */ |
@@ -1667,7 +1804,7 @@ export seq_isr: | |||
1667 | test DFCNTRL, DIRECTION jz interrupt_return; | 1804 | test DFCNTRL, DIRECTION jz interrupt_return; |
1668 | and DFCNTRL, ~SCSIEN; | 1805 | and DFCNTRL, ~SCSIEN; |
1669 | snapshot_wait_data_valid: | 1806 | snapshot_wait_data_valid: |
1670 | test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid; | 1807 | test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return; |
1671 | test SSTAT1, REQINIT jz snapshot_wait_data_valid; | 1808 | test SSTAT1, REQINIT jz snapshot_wait_data_valid; |
1672 | snapshot_data_valid: | 1809 | snapshot_data_valid: |
1673 | or DFCNTRL, SCSIEN; | 1810 | or DFCNTRL, SCSIEN; |
@@ -1834,7 +1971,6 @@ pkt_saveptrs_check_status: | |||
1834 | dec SCB_FIFO_USE_COUNT; | 1971 | dec SCB_FIFO_USE_COUNT; |
1835 | test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; | 1972 | test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; |
1836 | mvi DFFSXFRCTL, CLRCHN ret; | 1973 | mvi DFFSXFRCTL, CLRCHN ret; |
1837 | END_CRITICAL; | ||
1838 | 1974 | ||
1839 | /* | 1975 | /* |
1840 | * LAST_SEG_DONE status has been seen in the current FIFO. | 1976 | * LAST_SEG_DONE status has been seen in the current FIFO. |
@@ -1843,7 +1979,6 @@ END_CRITICAL; | |||
1843 | * Check for overrun and see if we can complete this command. | 1979 | * Check for overrun and see if we can complete this command. |
1844 | */ | 1980 | */ |
1845 | pkt_last_seg_done: | 1981 | pkt_last_seg_done: |
1846 | BEGIN_CRITICAL; | ||
1847 | /* | 1982 | /* |
1848 | * Mark transfer as completed. | 1983 | * Mark transfer as completed. |
1849 | */ | 1984 | */ |