Reset the device before starting the init sequence.

Add shutdown hook.
This commit is contained in:
ragge 2000-04-16 09:55:39 +00:00
parent 711853729d
commit 9403f3fec8
2 changed files with 85 additions and 34 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ni.c,v 1.1 2000/04/09 16:49:57 ragge Exp $ */ /* $NetBSD: if_ni.c,v 1.2 2000/04/16 09:55:39 ragge Exp $ */
/* /*
* Copyright (c) 2000 Ludd, University of Lule}, Sweden. All rights reserved. * Copyright (c) 2000 Ludd, University of Lule}, Sweden. All rights reserved.
* *
@ -142,9 +142,11 @@ static int niioctl __P((struct ifnet *, u_long, caddr_t));
static int ni_add_rxbuf(struct ni_softc *, struct ni_dg *, int); static int ni_add_rxbuf(struct ni_softc *, struct ni_dg *, int);
static void ni_setup __P((struct ni_softc *)); static void ni_setup __P((struct ni_softc *));
static void nitimeout __P((struct ifnet *)); static void nitimeout __P((struct ifnet *));
static void ni_shutdown(void *);
static void ni_getpgs(struct ni_softc *sc, int size, caddr_t *v, paddr_t *p); static void ni_getpgs(struct ni_softc *sc, int size, caddr_t *v, paddr_t *p);
static int failtest(struct ni_softc *, int, int, int, char *);
volatile int endwait; /* Used during autoconfig */ volatile int endwait, retry; /* Used during autoconfig */
struct cfattach ni_ca = { struct cfattach ni_ca = {
sizeof(struct ni_softc), nimatch, niattach sizeof(struct ni_softc), nimatch, niattach
@ -199,8 +201,26 @@ ni_getpgs(struct ni_softc *sc, int size, caddr_t *v, paddr_t *p)
if (p) if (p)
*p = seg.ds_addr; *p = seg.ds_addr;
bzero(*v, size);
} }
static int
failtest(struct ni_softc *sc, int reg, int mask, int test, char *str)
{
int i = 100;
do {
DELAY(100000);
} while (((NI_RREG(reg) & mask) != test) && --i);
if (i == 0) {
printf("%s: %s\n", sc->sc_dev.dv_xname, str);
return 1;
}
return 0;
}
/* /*
* Interface exists: make available by filling in network interface * Interface exists: make available by filling in network interface
* record. System will initialize the interface when it is ready * record. System will initialize the interface when it is ready
@ -217,7 +237,7 @@ niattach(parent, self, aux)
struct ni_msg *msg; struct ni_msg *msg;
struct ni_ptdb *ptdb; struct ni_ptdb *ptdb;
caddr_t va; caddr_t va;
int i, j, res; int i, j, s, res;
u_short type; u_short type;
type = bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE); type = bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE);
@ -237,7 +257,6 @@ niattach(parent, self, aux)
/* /*
* Zero the newly allocated memory. * Zero the newly allocated memory.
*/ */
bzero(sc->sc_gvppqb, sizeof(struct ni_gvppqb));
nipqb->np_veclvl = (ba->ba_ivec << 2) + 2; nipqb->np_veclvl = (ba->ba_ivec << 2) + 2;
nipqb->np_node = ba->ba_intcpu; nipqb->np_node = ba->ba_intcpu;
@ -269,17 +288,22 @@ niattach(parent, self, aux)
/* /*
* Start init sequence. * Start init sequence.
*/ */
/* Check state */
for (i = 0; i < 100; i++) { /* Reset the node */
if ((NI_RREG(NI_PSR) & PSR_STATE) == PSR_UNDEF) NI_WREG(BIREG_VAXBICSR, NI_RREG(BIREG_VAXBICSR) | BICSR_NRST);
break; DELAY(500000);
DELAY(100000); i = 20;
} while ((NI_RREG(BIREG_VAXBICSR) & BICSR_BROKE) && --i)
if (i == 100) { DELAY(500000);
printf(": not undefined state\n"); if (i == 0) {
printf("%s: BROKE bit set after reset\n", sc->sc_dev.dv_xname);
return; return;
} }
/* Check state */
if (failtest(sc, NI_PSR, PSR_STATE, PSR_UNDEF, "not undefined state"))
return;
/* Clear owner bits */ /* Clear owner bits */
NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN); NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
NI_WREG(NI_PCR, NI_RREG(NI_PCR) & ~PCR_OWN); NI_WREG(NI_PCR, NI_RREG(NI_PCR) & ~PCR_OWN);
@ -290,15 +314,9 @@ niattach(parent, self, aux)
DELAY(100000); DELAY(100000);
/* Check state */ /* Check state */
for (i = 0; i < 100; i++) { if (failtest(sc, NI_PSR, PSR_INITED, PSR_INITED, "failed initialize"))
if ((NI_RREG(NI_PSR) & PSR_INITED))
break;
DELAY(100000);
}
if (i == 100) {
printf(": failed initialize\n");
return; return;
}
NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN); NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
WAITREG(NI_PCR, PCR_OWN); WAITREG(NI_PCR, PCR_OWN);
@ -307,15 +325,9 @@ niattach(parent, self, aux)
WAITREG(NI_PSR, PSR_OWN); WAITREG(NI_PSR, PSR_OWN);
/* Check state */ /* Check state */
for (i = 0; i < 100; i++) { if (failtest(sc, NI_PSR, PSR_STATE, PSR_ENABLED, "failed enable"))
if ((NI_RREG(NI_PSR) & PSR_STATE) == PSR_ENABLED)
break;
DELAY(10000);
}
if (i == 100) {
printf(": failed enable\n");
return; return;
}
NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN); NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
/* /*
@ -327,9 +339,9 @@ niattach(parent, self, aux)
#if NBPG < 4096 #if NBPG < 4096
#error pagesize too small #error pagesize too small
#endif #endif
s = splimp();
/* Set up message free queue */ /* Set up message free queue */
ni_getpgs(sc, NMSGBUF * 512, &va, 0); ni_getpgs(sc, NMSGBUF * 512, &va, 0);
bzero(va, NMSGBUF * 512);
for (i = 0; i < NMSGBUF; i++) { for (i = 0; i < NMSGBUF; i++) {
struct ni_msg *msg; struct ni_msg *msg;
@ -386,6 +398,8 @@ niattach(parent, self, aux)
NI_WREG(NI_PCR, PCR_FREEQNE|PCR_RFREEQ|PCR_OWN); NI_WREG(NI_PCR, PCR_FREEQNE|PCR_RFREEQ|PCR_OWN);
WAITREG(NI_PCR, PCR_OWN); WAITREG(NI_PCR, PCR_OWN);
splx(s);
/* Set initial parameters */ /* Set initial parameters */
msg = REMQHI(&fqb->nf_mforw); msg = REMQHI(&fqb->nf_mforw);
@ -395,14 +409,22 @@ niattach(parent, self, aux)
msg->nm_opcode2 = NI_WPARAM; msg->nm_opcode2 = NI_WPARAM;
((struct ni_param *)&msg->nm_text[0])->np_flags = NP_PAD; ((struct ni_param *)&msg->nm_text[0])->np_flags = NP_PAD;
endwait = 0; endwait = retry = 0;
res = INSQTI(msg, &gvp->nc_forw0); res = INSQTI(msg, &gvp->nc_forw0);
WAITREG(NI_PCR, PCR_OWN); retry: WAITREG(NI_PCR, PCR_OWN);
NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN); NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN);
WAITREG(NI_PCR, PCR_OWN); WAITREG(NI_PCR, PCR_OWN);
while (endwait == 0) i = 1000;
; while (endwait == 0 && --i)
DELAY(10000);
if (endwait == 0) {
if (++retry < 3)
goto retry;
printf("%s: no response to set params\n", sc->sc_dev.dv_xname);
return;
}
/* Clear counters */ /* Clear counters */
msg = REMQHI(&fqb->nf_mforw); msg = REMQHI(&fqb->nf_mforw);
@ -446,6 +468,9 @@ niattach(parent, self, aux)
*/ */
if_attach(ifp); if_attach(ifp);
ether_ifattach(ifp, sc->sc_enaddr); ether_ifattach(ifp, sc->sc_enaddr);
if (shutdownhook_establish(ni_shutdown, sc) == 0)
printf("%s: WARNING: unable to establish shutdown hook\n",
sc->sc_dev.dv_xname);
#if NBPFILTER > 0 #if NBPFILTER > 0
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
@ -570,6 +595,12 @@ niintr(void *arg)
struct mbuf *m; struct mbuf *m;
int idx, res; int idx, res;
if ((NI_RREG(NI_PSR) & PSR_STATE) != PSR_ENABLED)
return;
if ((NI_RREG(NI_PSR) & PSR_ERR))
printf("%s: PSR %x\n", sc->sc_dev.dv_xname, NI_RREG(NI_PSR));
/* Got any response packets? */ /* Got any response packets? */
while ((NI_RREG(NI_PSR) & PSR_RSQ) && (data = REMQHI(&gvp->nc_forwr))) { while ((NI_RREG(NI_PSR) & PSR_RSQ) && (data = REMQHI(&gvp->nc_forwr))) {
@ -860,3 +891,20 @@ nitimeout(ifp)
niinit(sc); niinit(sc);
#endif #endif
} }
/*
* Shutdown hook. Make sure the interface is stopped at reboot.
*/
void
ni_shutdown(arg)
void *arg;
{
struct ni_softc *sc = arg;
WAITREG(NI_PCR, PCR_OWN);
NI_WREG(NI_PCR, PCR_OWN|PCR_SHUTDOWN);
WAITREG(NI_PCR, PCR_OWN);
WAITREG(NI_PSR, PSR_OWN);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_nireg.h,v 1.1 2000/04/09 16:49:58 ragge Exp $ */ /* $NetBSD: if_nireg.h,v 1.2 2000/04/16 09:55:39 ragge Exp $ */
/* /*
* Copyright (c) 1988 Regents of the University of California. * Copyright (c) 1988 Regents of the University of California.
* All rights reserved. * All rights reserved.
@ -85,8 +85,10 @@ struct ni_regs {
#define PCR_CMDQ1 PCR_DFREEQ #define PCR_CMDQ1 PCR_DFREEQ
#define PCR_CMDQ2 PCR_RFREEQ #define PCR_CMDQ2 PCR_RFREEQ
#define PCR_CMDQ3 PCR_IFREEQ #define PCR_CMDQ3 PCR_IFREEQ
#define PCR_RESTART 11
#define PCR_FREEQNE 7 #define PCR_FREEQNE 7
#define PCR_CMDQNE 6 #define PCR_CMDQNE 6
#define PCR_SHUTDOWN 4
#define PCR_ENABLE 2 #define PCR_ENABLE 2
#define PCR_INIT 1 #define PCR_INIT 1
@ -98,6 +100,7 @@ struct ni_regs {
#define PSR_INITED 0x00020000 #define PSR_INITED 0x00020000
#define PSR_UNDEF 0x00010000 #define PSR_UNDEF 0x00010000
#define PSR_RSQ 0x00000080 #define PSR_RSQ 0x00000080
#define PSR_ERR 0x00000040
/* /*
* The DEBNx uses a very wierd (set of) structure(s) to communicate * The DEBNx uses a very wierd (set of) structure(s) to communicate