X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/bc2cef1effbab2aaf763210a8ffb41be6ecea33c..003ca8a0049bb9f833292e7ef0ed69340e3c671a:/usr/src/sys/tahoe/if/if_enp.c diff --git a/usr/src/sys/tahoe/if/if_enp.c b/usr/src/sys/tahoe/if/if_enp.c index ac042aace2..e818caa746 100644 --- a/usr/src/sys/tahoe/if/if_enp.c +++ b/usr/src/sys/tahoe/if/if_enp.c @@ -1,12 +1,29 @@ -/* if_enp.c 1.2 86/11/29 */ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Computer Consoles Inc. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)if_enp.c 7.4 (Berkeley) %G% + */ #include "enp.h" #if NENP > 0 /* - * Modified 3Com Ethernet Controller interface - * enp modifications added S. F. Holmgren - * - * UNTESTED WITH 4.3 + * CMC ENP-20 Ethernet Controller. */ #include "param.h" #include "systm.h" @@ -44,17 +61,21 @@ #include "../tahoevba/vbavar.h" #include "../tahoeif/if_enpreg.h" -#define ENPVEC 0xc1 #define ENPSTART 0xf02000 /* standard enp start addr */ #define ENPUNIT(dev) (minor(dev)) /* for enp ram devices */ +/* macros for dealing with longs in i/o space */ +#define ENPGETLONG(a) ((((u_short *)(a))[0] << 16)|(((u_short *)(a))[1])) +#define ENPSETLONG(a,v) \ + { register u_short *wp = (u_short *)(a); \ + wp[0] = ((u_short *)&(v))[0]; wp[1] = ((u_short *)&(v))[1];} int enpprobe(), enpattach(), enpintr(); -long enpstd[] = { 0xf41000, 0xf61000, 0 }; +long enpstd[] = { 0xfff41000, 0xfff61000, 0 }; struct vba_device *enpinfo[NENP]; struct vba_driver enpdriver = { enpprobe, 0, enpattach, 0, enpstd, "enp", enpinfo, "enp-20", 0 }; -int enpinit(), enpioctl(), enpreset(), enpoutput(); +int enpinit(), enpioctl(), enpreset(), enpoutput(), enpstart(); struct mbuf *enpget(); /* @@ -67,11 +88,8 @@ struct mbuf *enpget(); struct enp_softc { struct arpcom es_ac; /* common ethernet structures */ #define es_if es_ac.ac_if -#define es_enaddr es_ac.ac_enaddr - short es_flags; /* flags for devices */ +#define es_addr es_ac.ac_enaddr short es_ivec; /* interrupt vector */ - struct pte *es_map; /* map for dual ported memory */ - caddr_t es_ram; /* virtual address of mapped memory */ } enp_softc[NENP]; extern struct ifnet loif; @@ -84,9 +102,10 @@ enpprobe(reg, vi) struct enp_softc *es = &enp_softc[vi->ui_unit]; #ifdef lint + br = 0; cvec = br; br = cvec; enpintr(0); #endif - if (badaddr(addr, 2) || badaddr(&addr->enp_ram[0], 2)) + if (badaddr((caddr_t)addr, 2) || badaddr((caddr_t)&addr->enp_ram[0], 2)) return (0); es->es_ivec = --vi->ui_hd->vh_lastiv; addr->enp_state = S_ENPRESET; /* reset by VERSAbus reset */ @@ -104,28 +123,16 @@ enpattach(ui) { struct enp_softc *es = &enp_softc[ui->ui_unit]; register struct ifnet *ifp = &es->es_if; - register struct enpdevice *addr = (struct enpdevice *)ui->ui_addr; ifp->if_unit = ui->ui_unit; ifp->if_name = "enp"; ifp->if_mtu = ETHERMTU; - /* - * Get station's addresses. - */ - enpcopy(&addr->enp_addr.e_baseaddr, es->es_enaddr, - sizeof (es->es_enaddr)); - printf("enp%d: hardware address %s\n", ui->ui_unit, - ether_sprintf(es->es_enaddr)); - /* - * Allocate and map ram. - */ - vbmemalloc(128, ((caddr_t)addr)+0x1000, &es->es_map, &es->es_ram); - ifp->if_init = enpinit; ifp->if_ioctl = enpioctl; - ifp->if_output = enpoutput; + ifp->if_output = enoutput; + ifp->if_start = enpstart; ifp->if_reset = enpreset; - ifp->if_flags = IFF_BROADCAST; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; if_attach(ifp); } @@ -163,7 +170,6 @@ enpinit(unit) s = splimp(); RESET_ENP(addr); DELAY(200000); - addr->enp_intrvec = es->es_ivec; es->es_if.if_flags |= IFF_RUNNING; splx(s); } @@ -179,28 +185,27 @@ enpintr(unit) register BCB *bcbp; addr = (struct enpdevice *)enpinfo[unit]->ui_addr; +#if ENP == 30 if (!IS_ENP_INTR(addr)) return; ACK_ENP_INTR(addr); - while ((bcbp = (BCB *)ringget(&addr->enp_tohost )) != 0) { - (void) enpread(&enp_softc[unit], bcbp, unit); - ringput(&addr->enp_enpfree, bcbp); +#endif + while ((bcbp = (BCB *)ringget((RING *)&addr->enp_tohost )) != 0) { + enpread(&enp_softc[unit], bcbp); + (void) ringput((RING *)&addr->enp_enpfree, bcbp); } } /* * Read input packet, examine its packet type, and enqueue it. */ -enpread(es, bcbp, unit) +enpread(es, bcbp) struct enp_softc *es; register BCB *bcbp; - int unit; { register struct ether_header *enp; struct mbuf *m; - long int s; - int len, off, resid, enptype; - register struct ifqueue *inq; + int s, len, off, resid; es->es_if.if_ipackets++; /* @@ -211,7 +216,7 @@ enpread(es, bcbp, unit) * Remember that type was trailer by setting off. */ len = bcbp->b_msglen - sizeof (struct ether_header); - enp = (struct ether_header *)bcbp->b_addr; + enp = (struct ether_header *)ENPGETLONG(&bcbp->b_addr); #define enpdataaddr(enp, off, type) \ ((type)(((caddr_t)(((char *)enp)+sizeof (struct ether_header))+(off)))) enp->ether_type = ntohs((u_short)enp->ether_type); @@ -219,237 +224,81 @@ enpread(es, bcbp, unit) enp->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (enp->ether_type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) - goto setup; + return; enp->ether_type = ntohs(*enpdataaddr(enp, off, u_short *)); resid = ntohs(*(enpdataaddr(enp, off+2, u_short *))); if (off + resid > len) - goto setup; + return; len = off + resid; } else off = 0; if (len == 0) - goto setup; + return; /* * Pull packet off interface. Off is nonzero if packet * has trailing header; enpget will then force this header - * information to be at the front, but we still have to drop - * the type and length which are at the front of any trailer data. + * information to be at the front. */ - m = enpget(bcbp->b_addr, len, off, &es->es_if); + m = enpget((u_char *)enp, len, off, &es->es_if); if (m == 0) - goto setup; - if (off) { - struct ifnet *ifp; - - ifp = *(mtod(m, struct ifnet **)); - m->m_off += 2 * sizeof (u_short); - m->m_len -= 2 * sizeof (u_short); - *(mtod(m, struct ifnet **)) = ifp; - } - switch (enp->ether_type) { - -#ifdef INET - case ETHERTYPE_IP: - schednetisr(NETISR_IP); - inq = &ipintrq; - break; -#endif - case ETHERTYPE_ARP: - arpinput(&es->es_ac, m); - goto setup; - -#ifdef NS - case ETHERTYPE_NS: - schednetisr(NETISR_NS); - inq = &nsintrq; - break; -#endif - default: - m_freem(m); - goto setup; - } - if (IF_QFULL(inq)) { - IF_DROP(inq); - m_freem(m); - goto setup; - } - s = splimp(); - IF_ENQUEUE(inq, m); - splx(s); -setup: - return (0); + return; + en_doproto(&es->es_if, enp, m); } -/* - * Ethernet output routine. (called by user) - * Encapsulate a packet of type family for the local net. - * Use trailer local net encapsulation if enough data in first - * packet leaves a multiple of 512 bytes of data in remainder. - * If destination is this address or broadcast, send packet to - * loop device to kludge around the fact that 3com interfaces can't - * talk to themselves. - */ -enpoutput(ifp, m0, dst) +enpstart(ifp) struct ifnet *ifp; - struct mbuf *m0; - struct sockaddr *dst; { - register struct enp_softc *es = &enp_softc[ifp->if_unit]; - register struct mbuf *m = m0; - register struct ether_header *enp; - register int off, i; - struct mbuf *mcopy = (struct mbuf *)0; - int type, s, error, usetrailers; - u_char edst[6]; - struct in_addr idst; - - if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - error = ENETDOWN; - goto bad; - } - switch (dst->sa_family) { -#ifdef INET - case AF_INET: - idst = ((struct sockaddr_in *)dst)->sin_addr; - if (!arpresolve(&es->es_ac, m, &idst, edst, &usetrailers)) - return (0); /* if not yet resolved */ - if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr, - sizeof (edst))) - mcopy = m_copy(m, 0, (int)M_COPYALL); - off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; - if (usetrailers && off > 0 && (off & 0x1ff) == 0 && - m->m_off >= MMINOFF + 2 * sizeof (u_short)) { - type = ETHERTYPE_TRAIL + (off>>9); - m->m_off -= 2 * sizeof (u_short); - m->m_len += 2 * sizeof (u_short); - *mtod(m, u_short *) = ETHERTYPE_IP; - *(mtod(m, u_short *) + 1) = m->m_len; - goto gottrailertype; - } - type = ETHERTYPE_IP; - off = 0; - goto gottype; -#endif -#ifdef NS - case AF_NS: - bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), - (caddr_t)edst, sizeof (edst)); - if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof (edst))) - mcopy = m_copy(m, 0, (int)M_COPYALL); - else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, - sizeof (edst))) - return (looutput(&loif, m, dst)); - type = ETHERTYPE_NS; - off = 0; - goto gottype; -#endif - case AF_UNSPEC: - enp = (struct ether_header *)dst->sa_data; - bcopy((caddr_t)enp->ether_dhost, (caddr_t)edst, sizeof (edst)); - type = enp->ether_type; - goto gottype; - - default: - log(LOG_ERR, "enp%d: can't handle af%d\n", - ifp->if_unit, dst->sa_family); - error = EAFNOSUPPORT; - goto bad; - } - -gottrailertype: - /* - * Packet to be sent as trailer: move first packet - * (control information) to end of chain. - */ - while (m->m_next) - m = m->m_next; - m->m_next = m0; - m = m0->m_next; - m0->m_next = 0; - m0 = m; - -gottype: - /* - * Add local net header. If no space in first mbuf, - * allocate another. - */ - if (m->m_off > MMAXOFF || - MMINOFF + sizeof (struct ether_header) > m->m_off) { - m = m_get(M_DONTWAIT, MT_HEADER); - if (m == 0) { - error = ENOBUFS; - goto bad; - } - m->m_next = m0; - m->m_off = MMINOFF; - m->m_len = sizeof (struct ether_header); - } else { - m->m_off -= sizeof (struct ether_header); - m->m_len += sizeof (struct ether_header); - } - enp = mtod(m, struct ether_header *); - bcopy((caddr_t)edst, (caddr_t)enp->ether_dhost, sizeof (edst)); - bcopy((caddr_t)es->es_enaddr, (caddr_t)enp->ether_shost, - sizeof (es->es_enaddr)); - enp->ether_type = htons((u_short)type); - /* - * Queue message on interface if possible - */ - s = splimp(); - if (enpput(ifp->if_unit, m)) { - error = ENOBUFS; - goto qfull; - } - splx(s); - es->es_if.if_opackets++; - return (mcopy ? looutput(&loif, mcopy, dst) : 0); -qfull: - splx(s); - m0 = m; -bad: - m_freem(m0); - if (mcopy) - m_freem(mcopy); - return (error); + if (enpput(ifp)) + return (ENOBUFS); + else + return (0); } /* * Routine to copy from mbuf chain to transmitter buffer on the VERSAbus. */ -enpput(unit, m) - int unit; - struct mbuf *m; +enpput(ifp) +struct ifnet *ifp; { register BCB *bcbp; register struct enpdevice *addr; register struct mbuf *mp; register u_char *bp; register u_int len; - u_char *mcp; + int unit = ifp->if_unit, ret = 1; + struct mbuf *m; addr = (struct enpdevice *)enpinfo[unit]->ui_addr; - if (ringempty(&addr->enp_hostfree)) - return (1); - bcbp = (BCB *)ringget(&addr->enp_hostfree); +again: + if (ringempty((RING *)&addr->enp_hostfree)) { + /* ifp->if_flags |= IFF_OACTIVE; */ + return (ret); + } + IF_DEQUEUE(&ifp->if_snd, m); + if (m == 0) { + ifp->if_flags &= ~IFF_OACTIVE; + return (0); + } + bcbp = (BCB *)ringget((RING *)&addr->enp_hostfree); bcbp->b_len = 0; - bp = (u_char *)bcbp->b_addr; + bp = (u_char *)ENPGETLONG(&bcbp->b_addr); for (mp = m; mp; mp = mp->m_next) { len = mp->m_len; if (len == 0) continue; - mcp = mtod(mp, u_char *); - enpcopy(mcp, bp, len); + enpcopy(mtod(mp, u_char *), bp, len); bp += len; bcbp->b_len += len; } - bcbp->b_len = max(ETHERMIN, bcbp->b_len); + bcbp->b_len = max(ETHERMIN+sizeof (struct ether_header), bcbp->b_len); bcbp->b_reserved = 0; - if (ringput(&addr->enp_toenp, bcbp) == 1) + if (ringput((RING *)&addr->enp_toenp, bcbp) == 1) INTR_ENP(addr); m_freem(m); - return (0); + ret = 0; + goto again; } /* @@ -459,72 +308,74 @@ enpput(unit, m) * mbufs have even lengths. */ struct mbuf * -enpget(rxbuf, totlen, off0, ifp) +enpget(rxbuf, totlen, off, ifp) u_char *rxbuf; - int totlen, off0; + int totlen, off; struct ifnet *ifp; { - register u_char *cp, *mcp; + register u_char *cp; register struct mbuf *m; struct mbuf *top = 0, **mp = ⊤ - int len, off = off0; + int len; + u_char *packet_end; + + rxbuf += sizeof (struct ether_header); + cp = rxbuf; + packet_end = cp + totlen; + if (off) { + off += 2 * sizeof(u_short); + totlen -= 2 *sizeof(u_short); + cp = rxbuf + off; + } + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == 0) + return (0); + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = totlen; + m->m_len = MHLEN; - cp = rxbuf + sizeof (struct ether_header); while (totlen > 0) { - MGET(m, M_DONTWAIT, MT_DATA); - if (m == 0) - goto bad; - if (off) { - len = totlen - off; - cp = rxbuf + sizeof (struct ether_header) + off; - } else - len = totlen; - if (len >= NBPG) { - struct mbuf *p; - - MCLGET(m); - if (m->m_len == CLBYTES) - m->m_len = len = MIN(len, CLBYTES); + if (top) { + MGET(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + m_freem(top); + return (0); + } + m->m_len = MLEN; + } + len = min(totlen, (packet_end - cp)); + if (len >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + m->m_len = len = min(len, MCLBYTES); else - m->m_len = len = MIN(MLEN, len); + len = m->m_len; } else { - m->m_len = len = MIN(MLEN, len); - m->m_off = MMINOFF; - } - mcp = mtod(m, u_char *); - if (ifp) { /* - * Prepend interface pointer to first mbuf. + * Place initial small packet/header at end of mbuf. */ - *(mtod(m, struct ifnet **)) = ifp; - mcp += sizeof (ifp); - len -= sizeof (ifp); - ifp = (struct ifnet *)0; + if (len < m->m_len) { + if (top == 0 && len + max_linkhdr <= m->m_len) + m->m_data += max_linkhdr; + m->m_len = len; + } else + len = m->m_len; } - enpcopy(cp, mcp, len); - cp += len; + enpcopy(cp, mtod(m, u_char *), (u_int)len); *mp = m; mp = &m->m_next; - if (off == 0) { - totlen -= len; - continue; - } - off += len; - if (off == totlen) { - cp = rxbuf + sizeof (struct ether_header); - off = 0; - totlen = off0; - } + totlen -= len; + cp += len; + if (cp == packet_end) + cp = rxbuf; } return (top); -bad: - m_freem(top); - return (0); } enpcopy(from, to, cnt) - register char *from, *to; - register cnt; + register u_char *from, *to; + register u_int cnt; { register c; register short *f, *t; @@ -541,12 +392,12 @@ enpcopy(from, to, cnt) *t++ = *f++; cnt &= 1; if (cnt) { /* odd len */ - from = (char *)f; - to = (char *)t; + from = (u_char *)f; + to = (u_char *)t; *to = *from; } } - while (cnt-- > 0) /* one of the address(es) must be odd */ + while ((int)cnt-- > 0) /* one of the address(es) must be odd */ *to++ = *from++; } @@ -587,7 +438,7 @@ enpioctl(ifp, cmd, data) enpsetaddr(ifp->if_unit, addr, ina->x_host.c_host); } else - ina->x_host = *(union ns_host *)es->es_enaddr; + ina->x_host = *(union ns_host *)es->es_addr; enpinit(ifp->if_unit); break; } @@ -619,59 +470,75 @@ enpsetaddr(unit, addr, enaddr) struct enpdevice *addr; u_char *enaddr; { - u_char *cp; - int i, code; - - cp = &addr->enp_addr.e_baseaddr.ea_addr[0]; - for (i = 0; i < 6; i++) - *cp++ = ~*enaddr++; - enpcopy(&addr->enp_addr.e_listsize, &code, sizeof (code)); - code |= E_ADDR_SUPP; - enpcopy(&code, &addr->enp_addr.e_listsize, sizeof (code)); + + enpcopy(enaddr, addr->enp_addr.e_baseaddr.ea_addr, + sizeof (struct ether_addr)); enpinit(unit); + enpgetaddr(unit, addr); +} + +enpgetaddr(unit, addr) + int unit; + struct enpdevice *addr; +{ + struct enp_softc *es = &enp_softc[unit]; + + enpcopy(addr->enp_addr.e_baseaddr.ea_addr, es->es_addr, + sizeof (struct ether_addr)); + printf("enp%d: hardware address %s\n", + unit, ether_sprintf(es->es_addr)); } /* * Routines to synchronize enp and host. */ +#ifdef notdef static ringinit(rp, size) register RING *rp; { - register int i; - register short *sp; rp->r_rdidx = rp->r_wrtidx = 0; rp->r_size = size; } static -ringempty(rp) +ringfull(rp) register RING *rp; { + register short idx; - return (rp->r_rdidx == rp->r_wrtidx); + idx = (rp->r_wrtidx + 1) & (rp->r_size-1); + return (idx == rp->r_rdidx); } static -ringfull(rp) +fir(rp) register RING *rp; { - register short idx; - idx = (rp->r_wrtidx + 1) & (rp->r_size-1); - return (idx == rp->r_rdidx); + return (rp->r_rdidx != rp->r_wrtidx ? rp->r_slot[rp->r_rdidx] : 0); +} +#endif + +static +ringempty(rp) + register RING *rp; +{ + + return (rp->r_rdidx == rp->r_wrtidx); } static ringput(rp, v) register RING *rp; + BCB *v; { register int idx; idx = (rp->r_wrtidx + 1) & (rp->r_size-1); if (idx != rp->r_rdidx) { - rp->r_slot[rp->r_wrtidx] = v; + ENPSETLONG(&rp->r_slot[rp->r_wrtidx], v); rp->r_wrtidx = idx; if ((idx -= rp->r_rdidx) < 0) idx += rp->r_size; @@ -687,20 +554,12 @@ ringget(rp) register int i = 0; if (rp->r_rdidx != rp->r_wrtidx) { - i = rp->r_slot[rp->r_rdidx]; + i = ENPGETLONG(&rp->r_slot[rp->r_rdidx]); rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1); } return (i); } -static -fir(rp) - register RING *rp; -{ - - return (rp->r_rdidx != rp->r_wrtidx ? rp->r_slot[rp->r_rdidx] : 0); -} - /* * ENP Ram device. */ @@ -719,6 +578,7 @@ enpr_open(dev) return (0); } +/*ARGSUSED*/ enpr_close(dev) dev_t dev; { @@ -732,18 +592,17 @@ enpr_read(dev, uio) { register struct iovec *iov; struct enpdevice *addr; - int error; if (uio->uio_offset > RAM_SIZE) return (ENODEV); + iov = uio->uio_iov; if (uio->uio_offset + iov->iov_len > RAM_SIZE) iov->iov_len = RAM_SIZE - uio->uio_offset; addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr; - iov = uio->uio_iov; - error = useracc(iov->iov_base, iov->iov_len, 0); - if (error) - return (error); - enpcopy(&addr->enp_ram[uio->uio_offset], iov->iov_base, iov->iov_len); + if (useracc(iov->iov_base, (unsigned)iov->iov_len, 0) == 0) + return (EFAULT); + enpcopy((u_char *)&addr->enp_ram[uio->uio_offset], + (u_char *)iov->iov_base, (u_int)iov->iov_len); uio->uio_resid -= iov->iov_len; iov->iov_len = 0; return (0); @@ -755,7 +614,6 @@ enpr_write(dev, uio) { register struct enpdevice *addr; register struct iovec *iov; - register error; addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr; iov = uio->uio_iov; @@ -763,42 +621,48 @@ enpr_write(dev, uio) return (ENODEV); if (uio->uio_offset + iov->iov_len > RAM_SIZE) iov->iov_len = RAM_SIZE - uio->uio_offset; - error = useracc(iov->iov_base, iov->iov_len, 1); - if (error) - return (error); - enpcopy(iov->iov_base, &addr->enp_ram[uio->uio_offset], iov->iov_len); + if (useracc(iov->iov_base, (unsigned)iov->iov_len, 1) == 0) + return (EFAULT); + enpcopy((u_char *)iov->iov_base, + (u_char *)&addr->enp_ram[uio->uio_offset], (u_int)iov->iov_len); uio->uio_resid -= iov->iov_len; iov->iov_len = 0; return (0); } +/*ARGSUSED*/ enpr_ioctl(dev, cmd, data) dev_t dev; caddr_t data; { - register struct enpdevice *addr; register unit = ENPUNIT(dev); - register struct vba_device *ui; + struct enpdevice *addr; addr = (struct enpdevice *)enpinfo[unit]->ui_addr; switch(cmd) { case ENPIOGO: -/* not needed if prom based version */ - addr->enp_base = (int)addr; + ENPSETLONG(&addr->enp_base, addr); addr->enp_intrvec = enp_softc[unit].es_ivec; ENP_GO(addr, ENPSTART); DELAY(200000); enpinit(unit); - addr->enp_state = S_ENPRUN; /* it is running now */ -/* end of not needed */ + /* + * Fetch Ethernet address after link level + * is booted (firmware copies manufacturer's + * address from on-board ROM). + */ + enpgetaddr(unit, addr); + addr->enp_state = S_ENPRUN; break; case ENPIORESET: RESET_ENP(addr); - addr->enp_state = S_ENPRESET; /* it is reset now */ + addr->enp_state = S_ENPRESET; DELAY(100000); break; + default: + return (EINVAL); } return (0); }