Annotation of sys/arch/vax/if/if_de.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_de.c,v 1.19 2006/04/16 00:46:32 pascoe Exp $ */
2: /* $NetBSD: if_de.c,v 1.27 1997/04/19 15:02:29 ragge Exp $ */
3:
4: /*
5: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the University nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: *
32: * @(#)if_de.c 7.12 (Berkeley) 12/16/90
33: */
34:
35: /*
36: * DEC DEUNA interface
37: *
38: * Lou Salkind
39: * New York University
40: *
41: * TODO:
42: * timeout routine (get statistics)
43: */
44:
45: #include <sys/param.h>
46: #include <sys/systm.h>
47: #include <sys/mbuf.h>
48: #include <sys/buf.h>
49: #include <sys/protosw.h>
50: #include <sys/socket.h>
51: #include <sys/ioctl.h>
52: #include <sys/errno.h>
53: #include <sys/syslog.h>
54: #include <sys/device.h>
55:
56: #include <machine/pte.h>
57: #include <machine/sid.h>
58:
59: #include <net/if.h>
60: #include <net/if_dl.h>
61:
62: #ifdef INET
63: #include <netinet/in.h>
64: #include <netinet/in_systm.h>
65: #include <netinet/in_var.h>
66: #include <netinet/ip.h>
67: #include <netinet/if_ether.h>
68: #endif
69:
70: #include <machine/cpu.h>
71: #include <machine/mtpr.h>
72:
73: #include <vax/if/if_dereg.h>
74: #include <vax/if/if_uba.h>
75: #include <vax/uba/ubareg.h>
76: #include <vax/uba/ubavar.h>
77:
78: #define NXMT 3 /* number of transmit buffers */
79: #define NRCV 7 /* number of receive buffers (must be > 1) */
80:
81: int dedebug = 0;
82:
83: /*
84: * Ethernet software status per interface.
85: *
86: * Each interface is referenced by a network interface structure,
87: * ds_if, which the routing code uses to locate the interface.
88: * This structure contains the output queue for the interface, its address, ...
89: * We also have, for each interface, a UBA interface structure, which
90: * contains information about the UNIBUS resources held by the interface:
91: * map registers, buffered data paths, etc. Information is cached in this
92: * structure for use by the if_uba.c routines in running the interface
93: * efficiently.
94: */
95: struct de_softc {
96: struct device ds_dev; /* Configuration common part */
97: struct arpcom ds_ac; /* Ethernet common part */
98: struct dedevice *ds_vaddr; /* Virtual address of this interface */
99: #define ds_if ds_ac.ac_if /* network-visible interface */
100: int ds_flags;
101: #define DSF_RUNNING 2 /* board is enabled */
102: #define DSF_SETADDR 4 /* physical address is changed */
103: int ds_ubaddr; /* map info for incore structs */
104: struct ifubinfo ds_deuba; /* unibus resource structure */
105: struct ifrw ds_ifr[NRCV]; /* unibus receive maps */
106: struct ifxmt ds_ifw[NXMT]; /* unibus xmt maps */
107: /* the following structures are always mapped in */
108: struct de_pcbb ds_pcbb; /* port control block */
109: struct de_ring ds_xrent[NXMT]; /* transmit ring entries */
110: struct de_ring ds_rrent[NRCV]; /* receive ring entries */
111: struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */
112: /* end mapped area */
113: #define INCORE_BASE(p) ((char *)&(p)->ds_pcbb)
114: #define RVAL_OFF(s,n) ((char *)&(s)->n - INCORE_BASE(s))
115: #define LVAL_OFF(s,n) ((char *)(s)->n - INCORE_BASE(s))
116: #define PCBB_OFFSET(s) RVAL_OFF(s,ds_pcbb)
117: #define XRENT_OFFSET(s) LVAL_OFF(s,ds_xrent)
118: #define RRENT_OFFSET(s) LVAL_OFF(s,ds_rrent)
119: #define UDBBUF_OFFSET(s) RVAL_OFF(s,ds_udbbuf)
120: #define INCORE_SIZE(s) RVAL_OFF(s, ds_xindex)
121: int ds_xindex; /* UNA index into transmit chain */
122: int ds_rindex; /* UNA index into receive chain */
123: int ds_xfree; /* index for next transmit buffer */
124: int ds_nxmit; /* # of transmits in progress */
125: };
126:
127: int dematch(struct device *, void *, void *);
128: void deattach(struct device *, struct device *, void *);
129: int dewait(struct de_softc *, char *);
130: void deinit(struct de_softc *);
131: int deioctl(struct ifnet *, u_long, caddr_t);
132: void dereset(int);
133: void destart(struct ifnet *);
134: void deread(struct de_softc *, struct ifrw *, int);
135: void derecv(int);
136: void de_setaddr(u_char *, struct de_softc *);
137: void deintr(int);
138:
139:
140: struct cfdriver de_cd = {
141: NULL, "de", DV_IFNET
142: };
143:
144: struct cfattach de_ca = {
145: sizeof(struct de_softc), dematch, deattach
146: };
147: /*
148: * Interface exists: make available by filling in network interface
149: * record. System will initialize the interface when it is ready
150: * to accept packets. We get the ethernet address here.
151: */
152: void
153: deattach(parent, self, aux)
154: struct device *parent, *self;
155: void *aux;
156: {
157: struct uba_attach_args *ua = aux;
158: struct de_softc *ds = (struct de_softc *)self;
159: struct ifnet *ifp = &ds->ds_if;
160: struct dedevice *addr;
161: char *c;
162: int csr1;
163: u_int8_t myaddr[ETHER_ADDR_LEN];
164:
165: addr = (struct dedevice *)ua->ua_addr;
166: ds->ds_vaddr = addr;
167: bcopy(ds->ds_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
168: ifp->if_softc = ds;
169: ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
170:
171: /*
172: * What kind of a board is this?
173: * The error bits 4-6 in pcsr1 are a device id as long as
174: * the high byte is zero.
175: */
176: csr1 = addr->pcsr1;
177: if (csr1 & 0xff60)
178: c = "broken";
179: else if (csr1 & 0x10)
180: c = "delua";
181: else
182: c = "deuna";
183:
184: printf("\n%s: %s\n", ds->ds_dev.dv_xname, c);
185: /*
186: * Reset the board and temporarily map
187: * the pcbb buffer onto the Unibus.
188: */
189: addr->pcsr0 = 0; /* reset INTE */
190: DELAY(100);
191: addr->pcsr0 = PCSR0_RSET;
192: (void)dewait(ds, "reset");
193:
194: ds->ds_ubaddr = uballoc((void *)ds->ds_dev.dv_parent,
195: (char *)&ds->ds_pcbb, sizeof (struct de_pcbb), 0);
196: addr->pcsr2 = ds->ds_ubaddr & 0xffff;
197: addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3;
198: addr->pclow = CMD_GETPCBB;
199: (void)dewait(ds, "pcbb");
200:
201: ds->ds_pcbb.pcbb0 = FC_RDPHYAD;
202: addr->pclow = CMD_GETCMD;
203: (void)dewait(ds, "read addr ");
204:
205: ubarelse((void *)ds->ds_dev.dv_parent, &ds->ds_ubaddr);
206: bcopy((caddr_t)&ds->ds_pcbb.pcbb2, myaddr, sizeof (myaddr));
207: printf("%s: address %s\n", ds->ds_dev.dv_xname,
208: ether_sprintf(myaddr));
209: ifp->if_ioctl = deioctl;
210: ifp->if_start = destart;
211: ds->ds_deuba.iff_flags = UBA_CANTWAIT;
212: #ifdef notdef
213: /* CAN WE USE BDP's ??? */
214: ds->ds_deuba.iff_flags |= UBA_NEEDBDP;
215: #endif
216: if_attach(ifp);
217: ether_ifattach(ifp);
218: }
219:
220: /*
221: * Reset of interface after UNIBUS reset.
222: */
223: void
224: dereset(unit)
225: int unit;
226: {
227: struct de_softc *sc = de_cd.cd_devs[unit];
228: volatile struct dedevice *addr = sc->ds_vaddr;
229:
230: printf(" de%d", unit);
231: sc->ds_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
232: sc->ds_flags &= ~DSF_RUNNING;
233: addr->pcsr0 = PCSR0_RSET;
234: (void)dewait(sc, "reset");
235: deinit(sc);
236: }
237:
238: /*
239: * Initialization of interface; clear recorded pending
240: * operations, and reinitialize UNIBUS usage.
241: */
242: void
243: deinit(ds)
244: struct de_softc *ds;
245: {
246: volatile struct dedevice *addr;
247: struct ifnet *ifp = &ds->ds_if;
248: struct ifrw *ifrw;
249: struct ifxmt *ifxp;
250: struct de_ring *rp;
251: int s,incaddr;
252:
253: /* not yet, if address still unknown */
254: if (TAILQ_EMPTY(&ifp->if_addrlist))
255: return;
256:
257: if (ds->ds_flags & DSF_RUNNING)
258: return;
259: if ((ifp->if_flags & IFF_RUNNING) == 0) {
260: if (if_ubaminit(&ds->ds_deuba, (void *)ds->ds_dev.dv_parent,
261: sizeof (struct ether_header), (int)vax_btoc(ETHERMTU),
262: ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) {
263: printf("%s: can't initialize\n", ds->ds_dev.dv_xname);
264: ds->ds_if.if_flags &= ~IFF_UP;
265: return;
266: }
267: ds->ds_ubaddr = uballoc((void *)ds->ds_dev.dv_parent,
268: INCORE_BASE(ds), INCORE_SIZE(ds), 0);
269: }
270: addr = ds->ds_vaddr;
271:
272: /* set the pcbb block address */
273: incaddr = ds->ds_ubaddr + PCBB_OFFSET(ds);
274: addr->pcsr2 = incaddr & 0xffff;
275: addr->pcsr3 = (incaddr >> 16) & 0x3;
276: addr->pclow = 0; /* reset INTE */
277: DELAY(500);
278: addr->pclow = CMD_GETPCBB;
279: (void)dewait(ds, "pcbb");
280:
281: /* set the transmit and receive ring header addresses */
282: incaddr = ds->ds_ubaddr + UDBBUF_OFFSET(ds);
283: ds->ds_pcbb.pcbb0 = FC_WTRING;
284: ds->ds_pcbb.pcbb2 = incaddr & 0xffff;
285: ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3;
286:
287: incaddr = ds->ds_ubaddr + XRENT_OFFSET(ds);
288: ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff;
289: ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3;
290: ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short);
291: ds->ds_udbbuf.b_trlen = NXMT;
292: incaddr = ds->ds_ubaddr + RRENT_OFFSET(ds);
293: ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff;
294: ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3;
295: ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short);
296: ds->ds_udbbuf.b_rrlen = NRCV;
297:
298: addr->pclow = CMD_GETCMD;
299: (void)dewait(ds, "wtring");
300:
301: /* initialize the mode - enable hardware padding */
302: ds->ds_pcbb.pcbb0 = FC_WTMODE;
303: /* let hardware do padding - set MTCH bit on broadcast */
304: ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX;
305: addr->pclow = CMD_GETCMD;
306: (void)dewait(ds, "wtmode");
307:
308: /* set up the receive and transmit ring entries */
309: ifxp = &ds->ds_ifw[0];
310: for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) {
311: rp->r_segbl = ifxp->ifw_info & 0xffff;
312: rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3;
313: rp->r_flags = 0;
314: ifxp++;
315: }
316: ifrw = &ds->ds_ifr[0];
317: for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) {
318: rp->r_slen = sizeof (struct de_buf);
319: rp->r_segbl = ifrw->ifrw_info & 0xffff;
320: rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3;
321: rp->r_flags = RFLG_OWN; /* hang receive */
322: ifrw++;
323: }
324:
325: /* start up the board (rah rah) */
326: s = splnet();
327: ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0;
328: ds->ds_if.if_flags |= IFF_RUNNING;
329: addr->pclow = PCSR0_INTE; /* avoid interlock */
330: destart(&ds->ds_if); /* queue output packets */
331: ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */
332: if (ds->ds_flags & DSF_SETADDR)
333: de_setaddr(ds->ds_ac.ac_enaddr, ds);
334: addr->pclow = CMD_START | PCSR0_INTE;
335: splx(s);
336: }
337:
338: /*
339: * Setup output on interface.
340: * Get another datagram to send off of the interface queue,
341: * and map it to the interface before starting the output.
342: * Must be called from ipl >= our interrupt level.
343: */
344: void
345: destart(ifp)
346: struct ifnet *ifp;
347: {
348: int len;
349: register struct de_softc *ds = ifp->if_softc;
350: volatile struct dedevice *addr = ds->ds_vaddr;
351: register struct de_ring *rp;
352: struct mbuf *m;
353: register int nxmit;
354:
355: /*
356: * the following test is necessary, since
357: * the code is not reentrant and we have
358: * multiple transmission buffers.
359: */
360: if (ds->ds_if.if_flags & IFF_OACTIVE)
361: return;
362: for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) {
363: IF_DEQUEUE(&ds->ds_if.if_snd, m);
364: if (m == 0)
365: break;
366: rp = &ds->ds_xrent[ds->ds_xfree];
367: if (rp->r_flags & XFLG_OWN)
368: panic("deuna xmit in progress");
369: len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m);
370: if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) {
371: struct uba_softc *uh = (void *)ds->ds_dev.dv_parent;
372:
373: if (uh->uh_ubapurge)
374: (*uh->uh_ubapurge)
375: (uh, ds->ds_ifw[ds->ds_xfree].ifw_bdp);
376: }
377: rp->r_slen = len;
378: rp->r_tdrerr = 0;
379: rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
380:
381: ds->ds_xfree++;
382: if (ds->ds_xfree == NXMT)
383: ds->ds_xfree = 0;
384: }
385: if (ds->ds_nxmit != nxmit) {
386: ds->ds_nxmit = nxmit;
387: if (ds->ds_flags & DSF_RUNNING)
388: addr->pclow = PCSR0_INTE|CMD_PDMD;
389: }
390: }
391:
392: /*
393: * Command done interrupt.
394: */
395: void
396: deintr(unit)
397: int unit;
398: {
399: volatile struct dedevice *addr;
400: register struct de_softc *ds;
401: register struct de_ring *rp;
402: register struct ifxmt *ifxp;
403: short csr0;
404:
405: ds = de_cd.cd_devs[unit];
406: addr = ds->ds_vaddr;
407:
408:
409: /* save flags right away - clear out interrupt bits */
410: csr0 = addr->pcsr0;
411: addr->pchigh = csr0 >> 8;
412:
413:
414: ds->ds_if.if_flags |= IFF_OACTIVE; /* prevent entering destart */
415: /*
416: * if receive, put receive buffer on mbuf
417: * and hang the request again
418: */
419: derecv(unit);
420:
421: /*
422: * Poll transmit ring and check status.
423: * Be careful about loopback requests.
424: * Then free buffer space and check for
425: * more transmit requests.
426: */
427: for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) {
428: rp = &ds->ds_xrent[ds->ds_xindex];
429: if (rp->r_flags & XFLG_OWN)
430: break;
431: ds->ds_if.if_opackets++;
432: ifxp = &ds->ds_ifw[ds->ds_xindex];
433: /* check for unusual conditions */
434: if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
435: if (rp->r_flags & XFLG_ERRS) {
436: /* output error */
437: ds->ds_if.if_oerrors++;
438: if (dedebug) {
439: printf("de%d: oerror, flags=%b ",
440: unit, rp->r_flags, XFLG_BITS);
441: printf("tdrerr=%b\n",
442: rp->r_tdrerr, XERR_BITS);
443: }
444: } else if (rp->r_flags & XFLG_ONE) {
445: /* one collision */
446: ds->ds_if.if_collisions++;
447: } else if (rp->r_flags & XFLG_MORE) {
448: /* more than one collision */
449: ds->ds_if.if_collisions += 2; /* guess */
450: } else if (rp->r_flags & XFLG_MTCH) {
451: /* received our own packet */
452: ds->ds_if.if_ipackets++;
453: deread(ds, &ifxp->ifrw,
454: rp->r_slen - sizeof (struct ether_header));
455: }
456: }
457: if (ifxp->ifw_xtofree) {
458: m_freem(ifxp->ifw_xtofree);
459: ifxp->ifw_xtofree = 0;
460: }
461: /* check if next transmit buffer also finished */
462: ds->ds_xindex++;
463: if (ds->ds_xindex == NXMT)
464: ds->ds_xindex = 0;
465: }
466: ds->ds_if.if_flags &= ~IFF_OACTIVE;
467: destart(&ds->ds_if);
468:
469: if (csr0 & PCSR0_RCBI) {
470: if (dedebug)
471: log(LOG_WARNING, "de%d: buffer unavailable\n", unit);
472: addr->pclow = PCSR0_INTE|CMD_PDMD;
473: }
474: }
475:
476: /*
477: * Ethernet interface receiver interface.
478: * If input error just drop packet.
479: * Otherwise purge input buffered data path and examine
480: * packet to determine type. If can't determine length
481: * from type, then have to drop packet. Othewise decapsulate
482: * packet based on type and pass to type specific higher-level
483: * input routine.
484: */
485: void
486: derecv(unit)
487: int unit;
488: {
489: register struct de_softc *ds = de_cd.cd_devs[unit];
490: register struct de_ring *rp;
491: int len;
492:
493: rp = &ds->ds_rrent[ds->ds_rindex];
494: while ((rp->r_flags & RFLG_OWN) == 0) {
495: ds->ds_if.if_ipackets++;
496: if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) {
497: struct uba_softc *uh = (void *)ds->ds_dev.dv_parent;
498:
499: if (uh->uh_ubapurge)
500: (*uh->uh_ubapurge)
501: (uh,ds->ds_ifr[ds->ds_rindex].ifrw_bdp);
502: }
503: len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header)
504: - 4; /* don't forget checksum! */
505: /* check for errors */
506: if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) ||
507: (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) ||
508: (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) ||
509: len < ETHERMIN || len > ETHERMTU) {
510: ds->ds_if.if_ierrors++;
511: if (dedebug) {
512: printf("de%d: ierror, flags=%b ",
513: unit, rp->r_flags, RFLG_BITS);
514: printf("lenerr=%b (len=%d)\n",
515: rp->r_lenerr, RERR_BITS, len);
516: }
517: } else
518: deread(ds, &ds->ds_ifr[ds->ds_rindex], len);
519:
520: /* hang the receive buffer again */
521: rp->r_lenerr = 0;
522: rp->r_flags = RFLG_OWN;
523:
524: /* check next receive buffer */
525: ds->ds_rindex++;
526: if (ds->ds_rindex == NRCV)
527: ds->ds_rindex = 0;
528: rp = &ds->ds_rrent[ds->ds_rindex];
529: }
530: }
531:
532: /*
533: * Pass a packet to the higher levels.
534: * We deal with the trailer protocol here.
535: */
536: void
537: deread(ds, ifrw, len)
538: register struct de_softc *ds;
539: struct ifrw *ifrw;
540: int len;
541: {
542: struct ether_header *eh;
543: struct mbuf *m;
544:
545: eh = (struct ether_header *)ifrw->ifrw_addr;
546: if (len == 0)
547: return;
548:
549: /*
550: * Pull packet off interface. Off is nonzero if packet
551: * has trailing header; if_ubaget will then force this header
552: * information to be at the front.
553: */
554: m = if_ubaget(&ds->ds_deuba, ifrw, len, &ds->ds_if);
555: if (m) {
556: /*
557: * XXX not exactly sure what if_ubaget does. Manually
558: * add the ethernet header to the start of the mbuf chain.
559: */
560: M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
561: if (m) {
562: *mtod(m, struct ether_header *) = *eh;
563: ether_input_mbuf(&ds->ds_if, m);
564: }
565: }
566: }
567: /*
568: * Process an ioctl request.
569: */
570: int
571: deioctl(ifp, cmd, data)
572: register struct ifnet *ifp;
573: u_long cmd;
574: caddr_t data;
575: {
576: register struct ifaddr *ifa = (struct ifaddr *)data;
577: register struct de_softc *ds = ifp->if_softc;
578: int s = splnet(), error = 0;
579:
580: switch (cmd) {
581:
582: case SIOCSIFADDR:
583: ifp->if_flags |= IFF_UP;
584: deinit(ds);
585:
586: switch (ifa->ifa_addr->sa_family) {
587: #ifdef INET
588: case AF_INET:
589: arp_ifinit(&ds->ds_ac, ifa);
590: break;
591: #endif
592: }
593: break;
594:
595: case SIOCSIFFLAGS:
596: if ((ifp->if_flags & IFF_UP) == 0 &&
597: ds->ds_flags & DSF_RUNNING) {
598: ds->ds_vaddr->pclow = 0;
599: DELAY(5000);
600: ds->ds_vaddr->pclow = PCSR0_RSET;
601: ds->ds_flags &= ~DSF_RUNNING;
602: ds->ds_if.if_flags &= ~IFF_OACTIVE;
603: } else if (ifp->if_flags & IFF_UP &&
604: (ds->ds_flags & DSF_RUNNING) == 0)
605: deinit(ds);
606: break;
607:
608: default:
609: error = EINVAL;
610: }
611: splx(s);
612: return (error);
613: }
614:
615: /*
616: * set ethernet address for unit
617: */
618: void
619: de_setaddr(physaddr, ds)
620: u_char *physaddr;
621: struct de_softc *ds;
622: {
623: volatile struct dedevice *addr= ds->ds_vaddr;
624:
625: if (! (ds->ds_flags & DSF_RUNNING))
626: return;
627:
628: bcopy((caddr_t) physaddr, (caddr_t) &ds->ds_pcbb.pcbb2, 6);
629: ds->ds_pcbb.pcbb0 = FC_WTPHYAD;
630: addr->pclow = PCSR0_INTE|CMD_GETCMD;
631: if (dewait(ds, "address change") == 0) {
632: ds->ds_flags |= DSF_SETADDR;
633: bcopy((caddr_t) physaddr, ds->ds_ac.ac_enaddr, 6);
634: }
635: }
636:
637: /*
638: * Await completion of the named function
639: * and check for errors.
640: */
641: int
642: dewait(ds, fn)
643: register struct de_softc *ds;
644: char *fn;
645: {
646: volatile struct dedevice *addr = ds->ds_vaddr;
647: register int csr0;
648:
649: while ((addr->pcsr0 & PCSR0_INTR) == 0)
650: ;
651: csr0 = addr->pcsr0;
652: addr->pchigh = csr0 >> 8;
653: if (csr0 & PCSR0_PCEI) {
654: printf("de%d: %s failed, csr0=%b ", ds->ds_dev.dv_unit, fn,
655: csr0, PCSR0_BITS);
656: printf("csr1=%b\n", addr->pcsr1, PCSR1_BITS);
657: }
658: return (csr0 & PCSR0_PCEI);
659: }
660:
661: int
662: dematch(parent, cf, aux)
663: struct device *parent;
664: void *cf, *aux;
665: {
666: struct uba_attach_args *ua = aux;
667: volatile struct dedevice *addr = (struct dedevice *)ua->ua_addr;
668: int i;
669:
670: /*
671: * Make sure self-test is finished before we screw with the board.
672: * Self-test on a DELUA can take 15 seconds (argh).
673: */
674: for (i = 0;
675: i < 160 &&
676: (addr->pcsr0 & PCSR0_FATI) == 0 &&
677: (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET;
678: ++i)
679: DELAY(50000);
680: if (((addr->pcsr0 & PCSR0_FATI) != 0) ||
681: (((addr->pcsr1 & PCSR1_STMASK) != STAT_READY) &&
682: ((addr->pcsr1 & PCSR1_STMASK) != STAT_RUN)))
683: return(0);
684:
685: addr->pcsr0 = 0;
686: DELAY(5000);
687: addr->pcsr0 = PCSR0_RSET;
688: while ((addr->pcsr0 & PCSR0_INTR) == 0)
689: ;
690: /* make board interrupt by executing a GETPCBB command */
691: addr->pcsr0 = PCSR0_INTE;
692: addr->pcsr2 = 0;
693: addr->pcsr3 = 0;
694: addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB;
695: DELAY(50000);
696:
697: ua->ua_ivec = deintr;
698: ua->ua_reset = dereset; /* Wish to be called after ubareset */
699:
700: return 1;
701: }
CVSweb