Reset the device before starting the init sequence.
Add shutdown hook.
This commit is contained in:
parent
711853729d
commit
9403f3fec8
@ -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.
|
||||
*
|
||||
@ -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 void ni_setup __P((struct ni_softc *));
|
||||
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 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 = {
|
||||
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)
|
||||
*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
|
||||
* record. System will initialize the interface when it is ready
|
||||
@ -217,7 +237,7 @@ niattach(parent, self, aux)
|
||||
struct ni_msg *msg;
|
||||
struct ni_ptdb *ptdb;
|
||||
caddr_t va;
|
||||
int i, j, res;
|
||||
int i, j, s, res;
|
||||
u_short type;
|
||||
|
||||
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.
|
||||
*/
|
||||
bzero(sc->sc_gvppqb, sizeof(struct ni_gvppqb));
|
||||
|
||||
nipqb->np_veclvl = (ba->ba_ivec << 2) + 2;
|
||||
nipqb->np_node = ba->ba_intcpu;
|
||||
@ -269,17 +288,22 @@ niattach(parent, self, aux)
|
||||
/*
|
||||
* Start init sequence.
|
||||
*/
|
||||
/* Check state */
|
||||
for (i = 0; i < 100; i++) {
|
||||
if ((NI_RREG(NI_PSR) & PSR_STATE) == PSR_UNDEF)
|
||||
break;
|
||||
DELAY(100000);
|
||||
}
|
||||
if (i == 100) {
|
||||
printf(": not undefined state\n");
|
||||
|
||||
/* Reset the node */
|
||||
NI_WREG(BIREG_VAXBICSR, NI_RREG(BIREG_VAXBICSR) | BICSR_NRST);
|
||||
DELAY(500000);
|
||||
i = 20;
|
||||
while ((NI_RREG(BIREG_VAXBICSR) & BICSR_BROKE) && --i)
|
||||
DELAY(500000);
|
||||
if (i == 0) {
|
||||
printf("%s: BROKE bit set after reset\n", sc->sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check state */
|
||||
if (failtest(sc, NI_PSR, PSR_STATE, PSR_UNDEF, "not undefined state"))
|
||||
return;
|
||||
|
||||
/* Clear owner bits */
|
||||
NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
|
||||
NI_WREG(NI_PCR, NI_RREG(NI_PCR) & ~PCR_OWN);
|
||||
@ -290,15 +314,9 @@ niattach(parent, self, aux)
|
||||
DELAY(100000);
|
||||
|
||||
/* Check state */
|
||||
for (i = 0; i < 100; i++) {
|
||||
if ((NI_RREG(NI_PSR) & PSR_INITED))
|
||||
break;
|
||||
DELAY(100000);
|
||||
}
|
||||
if (i == 100) {
|
||||
printf(": failed initialize\n");
|
||||
if (failtest(sc, NI_PSR, PSR_INITED, PSR_INITED, "failed initialize"))
|
||||
return;
|
||||
}
|
||||
|
||||
NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
|
||||
|
||||
WAITREG(NI_PCR, PCR_OWN);
|
||||
@ -307,15 +325,9 @@ niattach(parent, self, aux)
|
||||
WAITREG(NI_PSR, PSR_OWN);
|
||||
|
||||
/* Check state */
|
||||
for (i = 0; i < 100; i++) {
|
||||
if ((NI_RREG(NI_PSR) & PSR_STATE) == PSR_ENABLED)
|
||||
break;
|
||||
DELAY(10000);
|
||||
}
|
||||
if (i == 100) {
|
||||
printf(": failed enable\n");
|
||||
if (failtest(sc, NI_PSR, PSR_STATE, PSR_ENABLED, "failed enable"))
|
||||
return;
|
||||
}
|
||||
|
||||
NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
|
||||
|
||||
/*
|
||||
@ -327,9 +339,9 @@ niattach(parent, self, aux)
|
||||
#if NBPG < 4096
|
||||
#error pagesize too small
|
||||
#endif
|
||||
s = splimp();
|
||||
/* Set up message free queue */
|
||||
ni_getpgs(sc, NMSGBUF * 512, &va, 0);
|
||||
bzero(va, NMSGBUF * 512);
|
||||
for (i = 0; i < NMSGBUF; i++) {
|
||||
struct ni_msg *msg;
|
||||
|
||||
@ -386,6 +398,8 @@ niattach(parent, self, aux)
|
||||
NI_WREG(NI_PCR, PCR_FREEQNE|PCR_RFREEQ|PCR_OWN);
|
||||
WAITREG(NI_PCR, PCR_OWN);
|
||||
|
||||
splx(s);
|
||||
|
||||
/* Set initial parameters */
|
||||
msg = REMQHI(&fqb->nf_mforw);
|
||||
|
||||
@ -395,14 +409,22 @@ niattach(parent, self, aux)
|
||||
msg->nm_opcode2 = NI_WPARAM;
|
||||
((struct ni_param *)&msg->nm_text[0])->np_flags = NP_PAD;
|
||||
|
||||
endwait = 0;
|
||||
endwait = retry = 0;
|
||||
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);
|
||||
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 */
|
||||
msg = REMQHI(&fqb->nf_mforw);
|
||||
@ -446,6 +468,9 @@ niattach(parent, self, aux)
|
||||
*/
|
||||
if_attach(ifp);
|
||||
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
|
||||
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
|
||||
@ -570,6 +595,12 @@ niintr(void *arg)
|
||||
struct mbuf *m;
|
||||
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? */
|
||||
while ((NI_RREG(NI_PSR) & PSR_RSQ) && (data = REMQHI(&gvp->nc_forwr))) {
|
||||
|
||||
@ -860,3 +891,20 @@ nitimeout(ifp)
|
||||
niinit(sc);
|
||||
#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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
* All rights reserved.
|
||||
@ -85,8 +85,10 @@ struct ni_regs {
|
||||
#define PCR_CMDQ1 PCR_DFREEQ
|
||||
#define PCR_CMDQ2 PCR_RFREEQ
|
||||
#define PCR_CMDQ3 PCR_IFREEQ
|
||||
#define PCR_RESTART 11
|
||||
#define PCR_FREEQNE 7
|
||||
#define PCR_CMDQNE 6
|
||||
#define PCR_SHUTDOWN 4
|
||||
#define PCR_ENABLE 2
|
||||
#define PCR_INIT 1
|
||||
|
||||
@ -98,6 +100,7 @@ struct ni_regs {
|
||||
#define PSR_INITED 0x00020000
|
||||
#define PSR_UNDEF 0x00010000
|
||||
#define PSR_RSQ 0x00000080
|
||||
#define PSR_ERR 0x00000040
|
||||
|
||||
/*
|
||||
* The DEBNx uses a very wierd (set of) structure(s) to communicate
|
||||
|
Loading…
Reference in New Issue
Block a user