summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>2001-03-19 04:40:35 +0000
committergibbs <gibbs@FreeBSD.org>2001-03-19 04:40:35 +0000
commit90b2a0547e7e74c8e746fac8d0723800b21eccd0 (patch)
treeba3d7b6ac815952243f08e6b5840c5fc4edf906f
parent8a937bbc3a9d1a7f410a8dd8d27f0018404e5158 (diff)
downloadFreeBSD-src-90b2a0547e7e74c8e746fac8d0723800b21eccd0.zip
FreeBSD-src-90b2a0547e7e74c8e746fac8d0723800b21eccd0.tar.gz
This is an MFC candidate.
aic7xxx.c: Correct code that traverses the phase table. A much too quick push to staticize this structure resulted in non-functional lookup code. This corrects the printing of the phase where a timeout occurred. aic7xxx.reg: Use FIFOQWDEMP as the name for bit 5 of DFSTATUS just like the Adaptec data books. aic7xxx.seq: Refine the 2.1 PCI retry bug workaround for certain, non-ULTRA2, controllers. When the DMA of an SCB completes, it can take some time for HDONE to come true after MREQPEN (PCI memory request pending) falls. If HDONE never comes true, we are in the hung state and must manually drain the FIFO. We used to test HDONE for 3 clock cycles to detect this condition. This works on all of the hardware I can personally test. Some controllers were reported to take 4 clock cycles, so the last version of this code waited 4 clock cycles. This still didn't work for everyone. To fix this, I've adjusted the work around so that even if the hardware hasn't hung, but we run the work-around code, the result is a long winded way to complete the transfer, rather than a hang.
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c5
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg2
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq5
3 files changed, 7 insertions, 5 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index f6dc8c7..c0192a5 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -2006,13 +2006,14 @@ struct ahc_phase_table_entry*
ahc_lookup_phase_entry(int phase)
{
struct ahc_phase_table_entry *entry;
- int i;
+ struct ahc_phase_table_entry *last_entry;
/*
* num_phases doesn't include the default entry which
* will be returned if the phase doesn't match.
*/
- for (i = 0, entry = ahc_phase_table; i < num_phases; i++) {
+ last_entry = &ahc_phase_table[num_phases];
+ for (entry = ahc_phase_table; entry < last_entry; entry++) {
if (phase == entry->phase)
break;
}
diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg
index 93e7d8e..ac966f0 100644
--- a/sys/dev/aic7xxx/aic7xxx.reg
+++ b/sys/dev/aic7xxx/aic7xxx.reg
@@ -878,7 +878,7 @@ register DFSTATUS {
access_mode RO
bit PRELOAD_AVAIL 0x80
bit DFCACHETH 0x40
- bit DWORDEMP 0x20
+ bit FIFOQWDEMP 0x20
bit MREQPEND 0x10
bit HDONE 0x08
bit DFTHRESH 0x04
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index 6152c77..d85c89f 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -2070,13 +2070,12 @@ dma_scb_fromhost:
clr A;
/* Wait for some data to arrive. */
dma_scb_hang_fifo:
- test DFSTATUS, FIFOEMP jnz dma_scb_hang_fifo;
+ test DFSTATUS, FIFOQWDEMP jnz dma_scb_hang_fifo;
dma_scb_hang_wait:
test DFSTATUS, MREQPEND jnz dma_scb_hang_wait;
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
- test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
/*
* The PCI module no longer intends to perform
* a PCI transaction and HDONE has not come true.
@@ -2102,6 +2101,7 @@ dma_scb_hang_empty_fifo:
*/
not SINDEX;
add A, 5, SINDEX;
+ cmp A, 4 je dma_finish_nowait;
jmp dma_scb_hang_fifo;
dma_scb_hang_dma_done:
and DFCNTRL, ~HDMAEN;
@@ -2147,6 +2147,7 @@ copy_to_fifo_4:
*/
dma_finish:
test DFSTATUS,HDONE jz dma_finish;
+dma_finish_nowait:
/* Turn off DMA */
and DFCNTRL, ~HDMAEN;
test DFCNTRL, HDMAEN jnz .;
OpenPOWER on IntegriCloud