summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin T. Gibbs <gibbs@FreeBSD.org>2000-07-27 23:17:52 +0000
committerJustin T. Gibbs <gibbs@FreeBSD.org>2000-07-27 23:17:52 +0000
commit957790c3e62a2c0854c820e5a2fcebe0017b67cf (patch)
tree92cab81e522ca4e86faeabab9a7c048e87536527
parentab2adc20f2913e43a7623bdd7f61ef2a13f94c5e (diff)
Notes
-rw-r--r--sys/dev/aic7xxx/ahc_pci.c18
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h14
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg1
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq52
4 files changed, 70 insertions, 15 deletions
diff --git a/sys/dev/aic7xxx/ahc_pci.c b/sys/dev/aic7xxx/ahc_pci.c
index 4a22f3aec19f..761ea6b599b1 100644
--- a/sys/dev/aic7xxx/ahc_pci.c
+++ b/sys/dev/aic7xxx/ahc_pci.c
@@ -777,8 +777,23 @@ ahc_pci_attach(device_t dev)
* some MBs so don't use it.
*/
dscommand0 &= ~DPARCKEN;
+ /*
+ * We default to using 32byte SCBs
+ * and using cacheline streaming.
+ * If external SCB ram is detected,
+ * we'll switch to using 64 byte SCBs.
+ */
dscommand0 |= CACHETHEN|USCBSIZE32;
}
+ /*
+ * Handle chips that must have cache line
+ * streaming (dis/en)abled.
+ */
+ if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0)
+ dscommand0 |= CACHETHEN;
+
+ if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0)
+ dscommand0 &= ~CACHETHEN;
ahc_outb(ahc, DSCOMMAND0, dscommand0);
@@ -1856,7 +1871,7 @@ ahc_aic7890_setup(device_t dev, struct ahc_probe_config *probe_config)
probe_config->features = AHC_AIC7890_FE;
probe_config->flags |= AHC_NEWEEPROM_FMT;
if (pci_get_revid(dev) == 0)
- probe_config->bugs |= AHC_AUTOFLUSH_BUG;
+ probe_config->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG;
return (0);
}
@@ -1897,6 +1912,7 @@ ahc_aic7896_setup(device_t dev, struct ahc_probe_config *probe_config)
probe_config->chip = AHC_AIC7896;
probe_config->features = AHC_AIC7896_FE;
probe_config->flags |= AHC_NEWEEPROM_FMT;
+ probe_config->bugs |= AHC_CACHETHEN_DIS_BUG;
return (0);
}
diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h
index 6845299b5bfa..c146a5b3a7e8 100644
--- a/sys/dev/aic7xxx/aic7xxx.h
+++ b/sys/dev/aic7xxx/aic7xxx.h
@@ -182,7 +182,17 @@ typedef enum {
* feature does not work. A manual flush of
* the DMA FIFO is required.
*/
- AHC_AUTOFLUSH_BUG = 0x02
+ AHC_AUTOFLUSH_BUG = 0x02,
+ /*
+ * On the aic7890/91 Rev 0 chips, cacheline
+ * streaming does not work.
+ */
+ AHC_CACHETHEN_BUG = 0x04,
+ /*
+ * On the aic7896/97 chips, cacheline
+ * streaming must be enabled.
+ */
+ AHC_CACHETHEN_DIS_BUG = 0x08
} ahc_bug;
typedef enum {
@@ -598,7 +608,7 @@ struct ahc_softc {
struct scb_data *scb_data;
/*
- * CCBs that have been send to the controller
+ * CCBs that have been sent to the controller
*/
LIST_HEAD(, ccb_hdr) pending_ccbs;
diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg
index d76f44cbdbf4..8e1fd1b9b4cf 100644
--- a/sys/dev/aic7xxx/aic7xxx.reg
+++ b/sys/dev/aic7xxx/aic7xxx.reg
@@ -307,6 +307,7 @@ register SSTAT2 {
address 0x00d
access_mode RO
bit OVERRUN 0x80
+ bit SHVALID 0x40 /* Shaddow Layer non-zero */
bit EXP_ACTIVE 0x10 /* SCSI Expander Active */
mask SFCNT 0x1f
}
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index 00b28b3c79d8..0103104eee06 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -681,7 +681,8 @@ idle_loop:
bmov CCHADDR[1], SCB_RESIDUAL_SGPTR[1], 3;
mvi CCSGCTL, CCSGEN|CCSGRESET ret;
idle_sgfetch_complete:
- mvi CCSGCTL, CCSGRESET;
+ clr CCSGCTL;
+ test CCSGCTL, CCSGEN jnz .;
and CCSGADDR, (CCSGADDR_MAX - 1), SCB_RESIDUAL_SGPTR;
idle_sg_avail:
if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -789,14 +790,12 @@ data_phase_loop:
*/
or SXFRCTL1,BITBUCKET;
and DMAPARAMS, ~(HDMAEN|SDMAEN);
- /* Keep our idle loop from mucking with SG segments */
- or SCB_RESIDUAL_DATACNT[0], SG_LAST_SEG;
if ((ahc->features & AHC_ULTRA2) != 0) {
bmov HCNT, ALLONES, 3;
+ or SXFRCTL0, CLRCHN; /* Ensure FIFO empty */
} else if ((ahc->features & AHC_CMD_CHAN) != 0) {
bmov STCNT, ALLONES, 3;
} else {
- /* XXX Use bcopy? */
mvi STCNT[0], 0xFF;
mvi STCNT[1], 0xFF;
mvi STCNT[2], 0xFF;
@@ -823,6 +822,9 @@ ultra2_dmafinish:
test DFCNTRL, DIRECTION jnz ultra2_dmafifoempty;
and DFCNTRL, ~SCSIEN;
test DFCNTRL, SCSIEN jnz .;
+ if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
+ test DFSTATUS, FIFOEMP jnz ultra2_dmafifoempty;
+ }
ultra2_dmafifoflush:
if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
/*
@@ -854,6 +856,33 @@ ultra2_dmahalt:
test DFCNTRL, HDMAEN jnz .;
test SXFRCTL1,BITBUCKET jnz data_phase_finish;
+
+ /*
+ * If, by chance, we stopped before being able
+ * to fetch additional segments for this transfer,
+ * yet the last S/G was completely exhausted,
+ * call our idle loop until it is able to load
+ * another segment. This will allow us to immediately
+ * pickup on the next segment on the next data phase.
+ *
+ * If we happened to stop on the last segment, then
+ * our residual information is still correct from
+ * the idle loop and there is no need to perform
+ * any fixups. Just jump to data_phase_finish.
+ */
+ultra2_ensure_sg:
+ test SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid;
+ /* Record if we've consumed all S/G entries */
+ test SG_CACHE_SHADOW, LAST_SEG_DONE jz data_phase_finish;
+ or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
+ jmp data_phase_finish;
+
+ultra2_shvalid:
+ test SSTAT2, SHVALID jnz sgptr_fixup;
+ call idle_loop;
+ jmp ultra2_ensure_sg;
+
+sgptr_fixup:
/*
* Fixup the residual next S/G pointer. The S/G preload
* feature of the chip allows us to load two elements
@@ -875,19 +904,17 @@ sgptr_fixup_done:
clr DATA_COUNT_ODD;
test SG_CACHE_SHADOW, ODD_SEG jz . + 2;
or DATA_COUNT_ODD, 0x1;
- clr SCB_RESIDUAL_DATACNT[3];
- test SG_CACHE_SHADOW, LAST_SEG jz data_phase_finish;
- or SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG;
- /* Record if we've consumed all S/G entries */
- test SG_CACHE_SHADOW, LAST_SEG_DONE jz . + 2;
- or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
+ clr SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */
} else {
/* If we are the last SG block, tell the hardware. */
test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;
if ((ahc->flags & AHC_TARGETMODE) != 0) {
- test SSTAT0, TARGET jz . + 2;
- test DMAPARAMS, DIRECTION jz dma_mid_sg;
+ test SSTAT0, TARGET jz dma_last_sg;
+ if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) {
+ test DMAPARAMS, DIRECTION jz dma_mid_sg;
+ }
}
+dma_last_sg:
and DMAPARAMS, ~WIDEODD;
dma_mid_sg:
/* Start DMA data transfer. */
@@ -1071,6 +1098,7 @@ p_command:
if ((ahc->features & AHC_ULTRA2) != 0) {
bmov HCNT[0], SCB_CDB_LEN, 1;
bmov HCNT[1], ALLZEROS, 2;
+ mvi SG_CACHE_PRE, LAST_SEG;
} else if ((ahc->features & AHC_CMD_CHAN) != 0) {
bmov STCNT[0], SCB_CDB_LEN, 1;
bmov STCNT[1], ALLZEROS, 2;