diff options
author | gibbs <gibbs@FreeBSD.org> | 1999-04-19 21:28:15 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 1999-04-19 21:28:15 +0000 |
commit | 888d5241035a7e2b44aad57a1960d1b73b33a27d (patch) | |
tree | 7268247cbdd415369144117c42a7b5dcbe21a2c8 | |
parent | deb3dc05945881a83f9063301d8bfa56720eb332 (diff) | |
download | FreeBSD-src-888d5241035a7e2b44aad57a1960d1b73b33a27d.zip FreeBSD-src-888d5241035a7e2b44aad57a1960d1b73b33a27d.tar.gz |
Preserve termination settings across the card reset in our shutdown hook.
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c index 0c4cfbd..5e0ccab 100644 --- a/sys/dev/aic7xxx/aic7xxx.c +++ b/sys/dev/aic7xxx/aic7xxx.c @@ -36,7 +36,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aic7xxx.c,v 1.20 1999/03/23 07:24:26 gibbs Exp $ + * $Id: aic7xxx.c,v 1.21 1999/04/07 23:02:45 gibbs Exp $ */ /* * A few notes on features of the driver. @@ -2635,8 +2635,6 @@ ahc_handle_message_phase(struct ahc_softc *ahc, struct cam_path *path) int end_session; ahc_fetch_devinfo(ahc, &devinfo); - - end_session = FALSE; bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; @@ -4206,11 +4204,12 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) else maxsync = AHC_SYNCRATE_FAST; - if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0) + if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0) { if (update_type & AHC_TRANS_USER) cts->sync_offset = tinfo->user.offset; else cts->sync_offset = tinfo->goal.offset; + } syncrate = ahc_find_syncrate(ahc, &cts->sync_period, maxsync); @@ -5970,10 +5969,43 @@ ahc_shutdown(int howto, void *arg) { struct ahc_softc *ahc; int i; + u_int sxfrctl1_a, sxfrctl1_b; ahc = (struct ahc_softc *)arg; + pause_sequencer(ahc); + + /* + * Preserve the value of the SXFRCTL1 register for all channels. + * It contains settings that affect termination and we don't want + * to disturb the integrity of the bus during shutdown in case + * we are in a multi-initiator setup. + */ + sxfrctl1_b = 0; + if ((ahc->features & AHC_TWIN) != 0) { + u_int sblkctl; + + sblkctl = ahc_inb(ahc, SBLKCTL); + ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB); + sxfrctl1_b = ahc_inb(ahc, SXFRCTL1); + ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB); + } + + sxfrctl1_a = ahc_inb(ahc, SXFRCTL1); + + /* This will reset most registers to 0, but not all */ ahc_reset(ahc); + + if ((ahc->features & AHC_TWIN) != 0) { + u_int sblkctl; + + sblkctl = ahc_inb(ahc, SBLKCTL); + ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB); + ahc_outb(ahc, SXFRCTL1, sxfrctl1_b); + ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB); + } + ahc_outb(ahc, SXFRCTL1, sxfrctl1_a); + ahc_outb(ahc, SCSISEQ, 0); ahc_outb(ahc, SXFRCTL0, 0); ahc_outb(ahc, DSPCISTATUS, 0); |