Handle "scsi bus mode change" interrupts on 895 and higther.

Thanks to Hal Murray for reporting the problem and testing the fix.
This commit is contained in:
bouyer 2000-06-12 20:13:41 +00:00
parent 5f61ae5a02
commit 221a99f782
4 changed files with 85 additions and 7 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: siop.c,v 1.19 2000/06/07 14:40:20 tsutsui Exp $ */
/* $NetBSD: siop.c,v 1.20 2000/06/12 20:13:41 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@ -388,8 +388,6 @@ siop_intr(v)
}
}
if (cbdp == NULL) {
printf("%s: current DSA invalid\n",
sc->sc_dev.dv_xname);
siop_cmd = NULL;
}
if (istat & ISTAT_DIP) {
@ -433,6 +431,9 @@ siop_intr(v)
printf("last msg_in=0x%x status=0x%x\n",
siop_cmd->siop_table->msg_in[0],
le32toh(siop_cmd->siop_table->status));
else
printf("%s: current DSA invalid\n",
sc->sc_dev.dv_xname);
need_reset = 1;
}
}
@ -564,6 +565,26 @@ siop_intr(v)
"command\n", sc->sc_dev.dv_xname);
goto reset;
}
if (sist1 & SIST1_SBMC) {
/* SCSI bus mode change */
if (siop_modechange(sc) == 0 || need_reset == 1)
goto reset;
if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
/*
* we have a script interrupt, it will
* restart the script.
*/
goto scintr;
}
/*
* else we have to restart it ourselve, at the
* interrupted instruction.
*/
bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
bus_space_read_4(sc->sc_rt, sc->sc_rh,
SIOP_DSP) - 8);
return 1;
}
/* Else it's an unhandled exeption (for now). */
printf("%s: unhandled scsi interrupt, sist0=0x%x sist1=0x%x "
"sstat1=0x%x DSA=0x%x DSP=0x%x\n", sc->sc_dev.dv_xname,
@ -592,7 +613,7 @@ reset:
return 1;
}
scintr:
if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
irqcode = bus_space_read_4(sc->sc_rt, sc->sc_rh,
SIOP_DSPS);

View File

@ -1,4 +1,4 @@
/* $NetBSD: siop_common.c,v 1.2 2000/05/15 15:16:59 bouyer Exp $ */
/* $NetBSD: siop_common.c,v 1.3 2000/06/12 20:13:41 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@ -478,3 +478,57 @@ siop_clearfifo(sc)
}
}
}
int
siop_modechange(sc)
struct siop_softc *sc;
{
int retry;
int sist0, sist1, stest2, stest4;
for (retry = 0; retry < 5; retry++) {
/*
* datasheet says to wait 100ms and re-read SIST1,
* to check that DIFFSENSE is srable.
* We may delay() 5 times for 100ms at interrupt time;
* hopefully this will not happen often.
*/
delay(100000);
sist0 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST0);
sist1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST1);
if (sist1 & SIEN1_SBMC)
continue; /* we got an irq again */
stest4 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST4) &
STEST4_MODE_MASK;
stest2 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2);
switch(stest4) {
case STEST4_MODE_DIF:
printf("%s: switching to differential mode\n",
sc->sc_dev.dv_xname);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2,
stest2 | STEST2_DIF);
break;
case STEST4_MODE_SE:
printf("%s: switching to single-ended mode\n",
sc->sc_dev.dv_xname);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2,
stest2 & ~STEST2_DIF);
break;
case STEST4_MODE_LVD:
printf("%s: switching to LVD mode\n",
sc->sc_dev.dv_xname);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2,
stest2 & ~STEST2_DIF);
break;
default:
printf("%s: invalid SCSI mode 0x%x\n",
sc->sc_dev.dv_xname, stest4);
return 0;
}
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST0,
stest4 >> 2);
return 1;
}
printf("%s: timeout waiting for DIFFSENSE to stabilise\n",
sc->sc_dev.dv_xname);
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: siopreg.h,v 1.5 2000/05/15 07:48:25 bouyer Exp $ */
/* $NetBSD: siopreg.h,v 1.6 2000/06/12 20:13:41 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@ -276,6 +276,7 @@ static const struct scf_period scf_period[] __attribute__((__unused__)) = {
#define SIEN0_PAR 0x01
#define SIOP_SIEN1 0x41 /* SCSI interrupt enable 1, R/W */
#define SIEN1_SBMC 0x10 /* 895 only */
#define SIEN1_STO 0x04
#define SIEN1_GEN 0x02
#define SIEN1_HTH 0x01
@ -291,6 +292,7 @@ static const struct scf_period scf_period[] __attribute__((__unused__)) = {
#define SIST0_PAR 0x01
#define SIOP_SIST1 0x43 /* SCSI interrut status 1, RO */
#define SIST1_SBMC 0x10 /* 895 only */
#define SIST1_STO 0x04
#define SIST1_GEN 0x02
#define SIST1_HTH 0x01

View File

@ -1,4 +1,4 @@
/* $NetBSD: siopvar_common.h,v 1.2 2000/05/23 17:08:07 bouyer Exp $ */
/* $NetBSD: siopvar_common.h,v 1.3 2000/06/12 20:13:41 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@ -126,6 +126,7 @@ struct siop_target {
#define TARF_WIDE 0x01 /* target is wide */
void siop_common_reset __P((struct siop_softc *));
int siop_modechange __P((struct siop_softc *));
int siop_wdtr_neg __P((struct siop_cmd *siop_cmd));
int siop_sdtr_neg __P((struct siop_cmd *siop_cmd));