diff options
| author | Justin T. Gibbs <gibbs@FreeBSD.org> | 2000-07-27 23:17:52 +0000 |
|---|---|---|
| committer | Justin T. Gibbs <gibbs@FreeBSD.org> | 2000-07-27 23:17:52 +0000 |
| commit | 957790c3e62a2c0854c820e5a2fcebe0017b67cf (patch) | |
| tree | 92cab81e522ca4e86faeabab9a7c048e87536527 | |
| parent | ab2adc20f2913e43a7623bdd7f61ef2a13f94c5e (diff) | |
Notes
| -rw-r--r-- | sys/dev/aic7xxx/ahc_pci.c | 18 | ||||
| -rw-r--r-- | sys/dev/aic7xxx/aic7xxx.h | 14 | ||||
| -rw-r--r-- | sys/dev/aic7xxx/aic7xxx.reg | 1 | ||||
| -rw-r--r-- | sys/dev/aic7xxx/aic7xxx.seq | 52 |
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; |
