Annotation of sys/dev/isa/if_ef_isapnp.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_ef_isapnp.c,v 1.21 2006/03/25 22:41:44 djm Exp $ */
2:
3: /*
4: * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26: * POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29: #include "bpfilter.h"
30:
31: #include <sys/param.h>
32: #include <sys/systm.h>
33: #include <sys/mbuf.h>
34: #include <sys/socket.h>
35: #include <sys/ioctl.h>
36: #include <sys/errno.h>
37: #include <sys/syslog.h>
38: #include <sys/selinfo.h>
39: #include <sys/device.h>
40: #include <sys/queue.h>
41: #include <sys/kernel.h>
42: #include <sys/timeout.h>
43:
44: #include <net/if.h>
45: #include <net/if_dl.h>
46: #include <net/if_types.h>
47: #include <net/netisr.h>
48: #include <net/if_media.h>
49:
50: #ifdef INET
51: #include <netinet/in.h>
52: #include <netinet/in_systm.h>
53: #include <netinet/in_var.h>
54: #include <netinet/ip.h>
55: #include <netinet/if_ether.h>
56: #endif
57:
58: #if NBPFILTER > 0
59: #include <net/bpf.h>
60: #endif
61:
62: #include <machine/cpu.h>
63: #include <machine/bus.h>
64: #include <machine/intr.h>
65:
66: #include <dev/mii/mii.h>
67: #include <dev/mii/miivar.h>
68: #include <dev/isa/isavar.h>
69: #include <dev/isa/isadmavar.h>
70: #include <dev/ic/elink3reg.h>
71:
72: #undef EF_DEBUG
73:
74: struct ef_softc {
75: struct device sc_dv;
76: bus_space_tag_t sc_iot;
77: bus_space_handle_t sc_ioh;
78: struct arpcom sc_arpcom;
79: struct mii_data sc_mii;
80: struct timeout sc_tick_tmo;
81: void * sc_ih;
82: int sc_tx_start_thresh;
83: int sc_tx_succ_ok;
84: int sc_busmaster;
85: };
86:
87: #define EF_W0_EEPROM_COMMAND 0x200a
88: #define EF_EEPROM_BUSY (1 << 9)
89: #define EF_EEPROM_READ (1 << 7)
90: #define EF_W0_EEPROM_DATA 0x200c
91:
92: #define EF_W1_TX_PIO_WR_1 0x10
93: #define EF_W1_RX_PIO_RR_1 0x10
94: #define EF_W1_RX_ERRORS 0x14
95: #define EF_W1_RX_STATUS 0x18
96: #define EF_W1_TX_STATUS 0x1b
97: #define EF_W1_FREE_TX 0x1c
98:
99: #define EF_W4_MEDIA 0x0a
100: #define EF_MEDIA_SQE 0x0008 /* sqe error for aui */
101: #define EF_MEDIA_TP 0x00c0 /* link/jabber, 10baseT */
102: #define EF_MEDIA_LNK 0x0080 /* linkbeat, 100baseTX/FX */
103: #define EF_MEDIA_LNKBEAT 0x0800
104:
105: /* Window 4: EP_W4_CTRLR_STATUS: mii manipulation */
106: #define EF_MII_CLK 0x01 /* clock bit */
107: #define EF_MII_DATA 0x02 /* data bit */
108: #define EF_MII_DIR 0x04 /* direction */
109:
110: int ef_isapnp_match(struct device *, void *, void *);
111: void ef_isapnp_attach(struct device *, struct device *, void *);
112:
113: void efstart(struct ifnet *);
114: int efioctl(struct ifnet *, u_long, caddr_t);
115: void efwatchdog(struct ifnet *);
116: void efreset(struct ef_softc *);
117: void efstop(struct ef_softc *);
118: void efsetmulti(struct ef_softc *);
119: int efbusyeeprom(struct ef_softc *);
120: int efintr(void *);
121: void efinit(struct ef_softc *);
122: void efcompletecmd(struct ef_softc *, u_int, u_int);
123: void eftxstat(struct ef_softc *);
124: void efread(struct ef_softc *);
125: struct mbuf *efget(struct ef_softc *, int totlen);
126:
127: void ef_miibus_writereg(struct device *, int, int, int);
128: void ef_miibus_statchg(struct device *);
129: int ef_miibus_readreg(struct device *, int, int);
130: void ef_mii_writeb(struct ef_softc *, int);
131: void ef_mii_sync(struct ef_softc *);
132: int ef_ifmedia_upd(struct ifnet *);
133: void ef_ifmedia_sts(struct ifnet *, struct ifmediareq *);
134: void ef_tick(void *);
135:
136: struct cfdriver ef_cd = {
137: NULL, "ef", DV_IFNET
138: };
139:
140: struct cfattach ef_isapnp_ca = {
141: sizeof(struct ef_softc), ef_isapnp_match, ef_isapnp_attach
142: };
143:
144: int
145: ef_isapnp_match(parent, match, aux)
146: struct device *parent;
147: void *match, *aux;
148: {
149: return (1);
150: }
151:
152: void
153: ef_isapnp_attach(parent, self, aux)
154: struct device *parent, *self;
155: void *aux;
156: {
157: struct ef_softc *sc = (void *)self;
158: struct isa_attach_args *ia = aux;
159: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
160: bus_space_tag_t iot;
161: bus_space_handle_t ioh;
162: int i;
163: u_int16_t x;
164: u_int32_t cfg;
165:
166: sc->sc_iot = iot = ia->ia_iot;
167: sc->sc_ioh = ioh = ia->ipa_io[0].h;
168:
169: efcompletecmd(sc, EP_COMMAND, GLOBAL_RESET);
170: DELAY(1500);
171:
172: for (i = 0; i < 3; i++) {
173: if (efbusyeeprom(sc))
174: return;
175:
176: bus_space_write_2(iot, ioh, EF_W0_EEPROM_COMMAND,
177: EF_EEPROM_READ | i);
178:
179: if (efbusyeeprom(sc))
180: return;
181:
182: x = bus_space_read_2(iot, ioh, EF_W0_EEPROM_DATA);
183:
184: sc->sc_arpcom.ac_enaddr[(i << 1)] = x >> 8;
185: sc->sc_arpcom.ac_enaddr[(i << 1) + 1] = x;
186: }
187:
188: printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
189:
190: GO_WINDOW(3);
191: cfg = bus_space_read_4(iot, ioh, EP_W3_INTERNAL_CONFIG);
192: cfg &= ~(0x00f00000);
193: cfg |= (0x06 << 20);
194: bus_space_write_4(iot, ioh, EP_W3_INTERNAL_CONFIG, cfg);
195:
196: sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
197: IPL_NET, efintr, sc, sc->sc_dv.dv_xname);
198:
199: if (ia->ia_drq != DRQUNK)
200: isadma_cascade(ia->ia_drq);
201:
202: timeout_set(&sc->sc_tick_tmo, ef_tick, sc);
203:
204: bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ);
205: ifp->if_softc = sc;
206: ifp->if_start = efstart;
207: ifp->if_ioctl = efioctl;
208: ifp->if_watchdog = efwatchdog;
209: ifp->if_flags =
210: IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
211: IFQ_SET_READY(&ifp->if_snd);
212:
213: sc->sc_mii.mii_ifp = ifp;
214: sc->sc_mii.mii_readreg = ef_miibus_readreg;
215: sc->sc_mii.mii_writereg = ef_miibus_writereg;
216: sc->sc_mii.mii_statchg = ef_miibus_statchg;
217: ifmedia_init(&sc->sc_mii.mii_media, 0, ef_ifmedia_upd, ef_ifmedia_sts);
218: mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
219: 0);
220: if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
221: ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
222: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
223: } else
224: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
225:
226: if_attach(ifp);
227: ether_ifattach(ifp);
228:
229: sc->sc_tx_start_thresh = 20;
230:
231: efcompletecmd(sc, EP_COMMAND, RX_RESET);
232: efcompletecmd(sc, EP_COMMAND, TX_RESET);
233: }
234:
235: void
236: efstart(ifp)
237: struct ifnet *ifp;
238: {
239: struct ef_softc *sc = ifp->if_softc;
240: bus_space_tag_t iot = sc->sc_iot;
241: bus_space_handle_t ioh = sc->sc_ioh;
242: struct mbuf *m, *m0;
243: int s, len, pad, i;
244: int fillcnt = 0;
245: u_int32_t filler = 0;
246:
247: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
248: return;
249:
250: startagain:
251: IFQ_POLL(&ifp->if_snd, m0);
252: if (m0 == NULL)
253: return;
254:
255: if ((m0->m_flags & M_PKTHDR) == 0)
256: panic("efstart: no header mbuf");
257: len = m0->m_pkthdr.len;
258: pad = (4 - len) & 3;
259:
260: if (len + pad > ETHER_MAX_LEN) {
261: ifp->if_oerrors++;
262: IFQ_DEQUEUE(&ifp->if_snd, m0);
263: m_freem(m0);
264: goto startagain;
265: }
266:
267: if (bus_space_read_2(iot, ioh, EF_W1_FREE_TX) < len + pad + 4) {
268: bus_space_write_2(iot, ioh, EP_COMMAND,
269: SET_TX_AVAIL_THRESH | ((len + pad) >> 2));
270: ifp->if_flags |= IFF_OACTIVE;
271: return;
272: } else {
273: bus_space_write_2(iot, ioh, EP_COMMAND,
274: SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE);
275: }
276:
277: bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH |
278: ((len / 4 + sc->sc_tx_start_thresh)));
279:
280: #if NBPFILTER
281: if (ifp->if_bpf)
282: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
283: #endif
284:
285: IFQ_DEQUEUE(&ifp->if_snd, m0);
286: if (m0 == NULL) /* XXX not needed */
287: return;
288:
289: s = splhigh();
290:
291: bus_space_write_4(iot, ioh, EF_W1_TX_PIO_WR_1, len);
292: for (m = m0; m; ) {
293: if (fillcnt) {
294: while (m->m_len && fillcnt < 4) {
295: fillcnt++;
296: filler >>= 8;
297: filler |= m->m_data[0] << 24;
298: m->m_data++;
299: m->m_len--;
300: }
301: if (fillcnt == 4) {
302: bus_space_write_4(iot, ioh,
303: EF_W1_TX_PIO_WR_1, filler);
304: filler = 0;
305: fillcnt = 0;
306: }
307: }
308:
309: if (m->m_len & ~3)
310: bus_space_write_multi_4(iot, ioh,
311: EF_W1_TX_PIO_WR_1, (u_int32_t *)m->m_data,
312: m->m_len >> 2);
313: for (i = 0; i < (m->m_len & 3); i++) {
314: fillcnt++;
315: filler >>= 8;
316: filler |= m->m_data[(m->m_len & ~3) + i] << 24;
317: }
318: MFREE(m, m0);
319: m = m0;
320: }
321:
322: if (fillcnt) {
323: bus_space_write_4(iot, ioh, EF_W1_TX_PIO_WR_1,
324: filler >> (32 - (8 * fillcnt)));
325: fillcnt = 0;
326: filler = 0;
327: }
328:
329: splx(s);
330:
331: ifp->if_opackets++;
332:
333: goto startagain;
334: }
335:
336: int
337: efioctl(ifp, cmd, data)
338: struct ifnet *ifp;
339: u_long cmd;
340: caddr_t data;
341: {
342: struct ef_softc *sc = ifp->if_softc;
343: struct ifaddr *ifa = (struct ifaddr *)data;
344: struct ifreq *ifr = (struct ifreq *)data;
345: int s, error = 0;
346:
347: s = splnet();
348:
349: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
350: splx(s);
351: return (error);
352: }
353:
354: switch (cmd) {
355: case SIOCSIFADDR:
356: ifp->if_flags |= IFF_UP;
357: switch (ifa->ifa_addr->sa_family) {
358: #ifdef INET
359: case AF_INET:
360: efinit(sc);
361: arp_ifinit(&sc->sc_arpcom, ifa);
362: break;
363: #endif
364: default:
365: efinit(sc);
366: break;
367: }
368: break;
369: case SIOCSIFMEDIA:
370: case SIOCGIFMEDIA:
371: error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
372: break;
373: case SIOCSIFFLAGS:
374: if ((ifp->if_flags & IFF_UP) == 0 &&
375: (ifp->if_flags & IFF_RUNNING) != 0) {
376: efstop(sc);
377: ifp->if_flags &= ~IFF_RUNNING;
378: } else if ((ifp->if_flags & IFF_UP) != 0 &&
379: (ifp->if_flags & IFF_RUNNING) == 0) {
380: efinit(sc);
381: }
382: efsetmulti(sc);
383: break;
384:
385: case SIOCADDMULTI:
386: case SIOCDELMULTI:
387: error = (cmd == SIOCADDMULTI) ?
388: ether_addmulti(ifr, &sc->sc_arpcom) :
389: ether_delmulti(ifr, &sc->sc_arpcom);
390:
391: if (error == ENETRESET) {
392: if (ifp->if_flags & IFF_RUNNING)
393: efreset(sc);
394: error = 0;
395: }
396: efsetmulti(sc);
397: break;
398: default:
399: error = EINVAL;
400: break;
401: }
402:
403: splx(s);
404: return (error);
405: }
406:
407: void
408: efinit(sc)
409: struct ef_softc *sc;
410: {
411: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
412: bus_space_tag_t iot = sc->sc_iot;
413: bus_space_handle_t ioh = sc->sc_ioh;
414: int i, s;
415:
416: s = splnet();
417:
418: efstop(sc);
419:
420: while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
421: ;
422:
423: GO_WINDOW(2);
424: for (i = 0; i < 6; i++)
425: bus_space_write_1(iot, ioh, EP_W2_ADDR_0 + i,
426: sc->sc_arpcom.ac_enaddr[i]);
427: for (i = 0; i < 3; i += 2)
428: bus_space_write_2(iot, ioh, EP_W2_RECVMASK_0 + (i * 2), 0);
429:
430: efcompletecmd(sc, EP_COMMAND, RX_RESET);
431: efcompletecmd(sc, EP_COMMAND, TX_RESET);
432:
433: bus_space_write_2(iot, ioh, EP_COMMAND,
434: SET_TX_AVAIL_THRESH | (ETHER_MAX_DIX_LEN >> 2));
435:
436: efsetmulti(sc);
437:
438: bus_space_write_2(iot, ioh, EP_COMMAND, STATUS_ENABLE | 0);
439:
440: GO_WINDOW(6);
441: for (i = 0; i < 10; i++)
442: (void)bus_space_read_1(iot, ioh, i);
443: (void)bus_space_read_2(iot, ioh, 10);
444: (void)bus_space_read_2(iot, ioh, 12);
445: GO_WINDOW(4);
446: (void)bus_space_read_1(iot, ioh, 12);
447: bus_space_write_2(iot, ioh, EP_W4_NET_DIAG, 0x0040);
448:
449: GO_WINDOW(7);
450:
451: efsetmulti(sc);
452:
453: bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE);
454: bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
455:
456: bus_space_write_2(iot, ioh, EP_COMMAND, STATUS_ENABLE |
457: S_CARD_FAILURE | S_INT_RQD | S_UPD_STATS | S_TX_COMPLETE |
458: S_TX_AVAIL | S_RX_COMPLETE |
459: (sc->sc_busmaster ? S_DMA_DONE : 0));
460: bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR |
461: S_INTR_LATCH | S_TX_AVAIL | S_RX_EARLY | S_INT_RQD);
462: bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK |
463: S_INTR_LATCH | S_TX_AVAIL | S_RX_COMPLETE | S_UPD_STATS |
464: (sc->sc_busmaster ? S_DMA_DONE : 0) | S_UP_COMPLETE |
465: S_DOWN_COMPLETE | S_CARD_FAILURE | S_TX_COMPLETE);
466:
467: mii_mediachg(&sc->sc_mii);
468:
469: ifp->if_flags |= IFF_RUNNING;
470: ifp->if_flags &= ~IFF_OACTIVE;
471:
472: splx(s);
473:
474: timeout_add(&sc->sc_tick_tmo, hz);
475:
476: efstart(ifp);
477: }
478:
479: void
480: efreset(sc)
481: struct ef_softc *sc;
482: {
483: int s;
484:
485: s = splnet();
486: efstop(sc);
487: efinit(sc);
488: splx(s);
489: }
490:
491: void
492: efstop(sc)
493: struct ef_softc *sc;
494: {
495: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
496: bus_space_tag_t iot = sc->sc_iot;
497: bus_space_handle_t ioh = sc->sc_ioh;
498:
499: ifp->if_timer = 0;
500: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
501:
502: timeout_del(&sc->sc_tick_tmo);
503:
504: bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISABLE);
505: efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
506:
507: bus_space_write_2(iot, ioh, EP_COMMAND, TX_DISABLE);
508: bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
509:
510: efcompletecmd(sc, EP_COMMAND, RX_RESET);
511: efcompletecmd(sc, EP_COMMAND, TX_RESET);
512:
513: bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
514: bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK);
515: bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK);
516: bus_space_write_2(iot, ioh, EP_COMMAND, SET_RX_FILTER);
517: }
518:
519: void
520: efcompletecmd(sc, cmd, arg)
521: struct ef_softc *sc;
522: u_int cmd, arg;
523: {
524: bus_space_tag_t iot = sc->sc_iot;
525: bus_space_handle_t ioh = sc->sc_ioh;
526:
527: bus_space_write_2(iot, ioh, cmd, arg);
528: while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
529: ;
530: }
531:
532: int
533: efintr(vsc)
534: void *vsc;
535: {
536: struct ef_softc *sc = vsc;
537: bus_space_tag_t iot = sc->sc_iot;
538: bus_space_handle_t ioh = sc->sc_ioh;
539: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
540: u_int16_t status;
541: int r = 0;
542:
543: status = bus_space_read_2(iot, ioh, EP_STATUS);
544:
545: do {
546: if (status & S_RX_COMPLETE) {
547: r = 1;
548: bus_space_write_2(iot, ioh, EP_STATUS, C_RX_COMPLETE);
549: efread(sc);
550: }
551: if (status & S_TX_AVAIL) {
552: bus_space_write_2(iot, ioh, EP_STATUS, C_TX_AVAIL);
553: r = 1;
554: sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
555: efstart(&sc->sc_arpcom.ac_if);
556: }
557: if (status & S_CARD_FAILURE) {
558: r = 1;
559: efreset(sc);
560: printf("%s: adapter failure (%x)\n",
561: sc->sc_dv.dv_xname, status);
562: bus_space_write_2(iot, ioh, EP_COMMAND,
563: C_CARD_FAILURE);
564: return (1);
565: }
566: if (status & S_TX_COMPLETE) {
567: r = 1;
568: eftxstat(sc);
569: efstart(ifp);
570: }
571: bus_space_write_2(iot, ioh, EP_COMMAND,
572: C_INTR_LATCH | C_INT_RQD);
573: } while ((status = bus_space_read_2(iot, ioh, EP_STATUS)) &
574: (S_INT_RQD | S_RX_COMPLETE));
575:
576: return (r);
577: }
578:
579: void
580: eftxstat(sc)
581: struct ef_softc *sc;
582: {
583: bus_space_tag_t iot = sc->sc_iot;
584: bus_space_handle_t ioh = sc->sc_ioh;
585: int i;
586:
587: while ((i = bus_space_read_1(iot, ioh, EF_W1_TX_STATUS)) &
588: TXS_COMPLETE) {
589: bus_space_write_1(iot, ioh, EF_W1_TX_STATUS, 0);
590:
591: if (i & TXS_JABBER) {
592: sc->sc_arpcom.ac_if.if_oerrors++;
593: #ifdef EF_DEBUG
594: if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
595: printf("%s: jabber (%x)\n",
596: sc->sc_dv.dv_xname, i);
597: #endif
598: efreset(sc);
599: }
600: else if (i & TXS_UNDERRUN) {
601: sc->sc_arpcom.ac_if.if_oerrors++;
602: #ifdef EF_DEBUG
603: if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
604: printf("%s: fifo underrun (%x) @%d\n",
605: sc->sc_dv.dv_xname, i,
606: sc->sc_tx_start_thresh);
607: #endif
608: if (sc->sc_tx_succ_ok < 100)
609: sc->sc_tx_start_thresh = min(ETHER_MAX_LEN,
610: sc->sc_tx_start_thresh + 20);
611: sc->sc_tx_succ_ok = 0;
612: efreset(sc);
613: }
614: else if (i & TXS_MAX_COLLISION) {
615: sc->sc_arpcom.ac_if.if_collisions++;
616: bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
617: sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
618: }
619: else
620: sc->sc_tx_succ_ok = (sc->sc_tx_succ_ok + 1) & 127;
621: }
622: }
623:
624: int
625: efbusyeeprom(sc)
626: struct ef_softc *sc;
627: {
628: int i = 100, j;
629:
630: while (i--) {
631: j = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
632: EF_W0_EEPROM_COMMAND);
633: if (j & EF_EEPROM_BUSY)
634: delay(100);
635: else
636: break;
637: }
638: if (i == 0) {
639: printf("%s: eeprom failed to come ready\n",
640: sc->sc_dv.dv_xname);
641: return (1);
642: }
643:
644: return (0);
645: }
646:
647: void
648: efwatchdog(ifp)
649: struct ifnet *ifp;
650: {
651: struct ef_softc *sc = ifp->if_softc;
652:
653: printf("%s: device timeout\n", sc->sc_dv.dv_xname);
654: sc->sc_arpcom.ac_if.if_oerrors++;
655: efreset(sc);
656: }
657:
658: void
659: efsetmulti(sc)
660: struct ef_softc *sc;
661: {
662: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
663: struct arpcom *ac = &sc->sc_arpcom;
664: bus_space_tag_t iot = sc->sc_iot;
665: bus_space_handle_t ioh = sc->sc_ioh;
666: struct ether_multi *enm;
667: struct ether_multistep step;
668: u_int16_t cmd = SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST;
669: int mcnt = 0;
670:
671: ETHER_FIRST_MULTI(step, ac, enm);
672: while (enm != NULL) {
673: mcnt++;
674: ETHER_NEXT_MULTI(step, enm);
675: }
676: if (mcnt || ifp->if_flags & IFF_ALLMULTI)
677: cmd |= FIL_MULTICAST;
678:
679: if (ifp->if_flags & IFF_PROMISC)
680: cmd |= FIL_PROMISC;
681:
682: bus_space_write_2(iot, ioh, EP_COMMAND, cmd);
683: }
684:
685: void
686: efread(sc)
687: struct ef_softc *sc;
688: {
689: bus_space_tag_t iot = sc->sc_iot;
690: bus_space_handle_t ioh = sc->sc_ioh;
691: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
692: struct mbuf *m;
693: int len;
694:
695: len = bus_space_read_2(iot, ioh, EF_W1_RX_STATUS);
696:
697: #ifdef EF_DEBUG
698: if (ifp->if_flags & IFF_DEBUG) {
699: int err = len & ERR_MASK;
700: char *s = NULL;
701:
702: if (len & ERR_INCOMPLETE)
703: s = "incomplete packet";
704: else if (err == ERR_OVERRUN)
705: s = "packet overrun";
706: else if (err == ERR_RUNT)
707: s = "runt packet";
708: else if (err == ERR_ALIGNMENT)
709: s = "bad alignment";
710: else if (err == ERR_CRC)
711: s = "bad crc";
712: else if (err == ERR_OVERSIZE)
713: s = "oversized packet";
714: else if (err == ERR_DRIBBLE)
715: s = "dribble bits";
716:
717: if (s)
718: printf("%s: %s\n", sc->sc_dv.dv_xname, s);
719: }
720: #endif
721:
722: if (len & ERR_INCOMPLETE)
723: return;
724:
725: if (len & ERR_RX) {
726: ifp->if_ierrors++;
727: efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
728: return;
729: }
730:
731: len &= RX_BYTES_MASK;
732: m = efget(sc, len);
733: if (m == NULL) {
734: ifp->if_ierrors++;
735: efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
736: return;
737: }
738:
739: ifp->if_ipackets++;
740:
741: #if NBPFILTER > 0
742: if (ifp->if_bpf)
743: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
744: #endif
745:
746: ether_input_mbuf(ifp, m);
747: }
748:
749: struct mbuf *
750: efget(sc, totlen)
751: struct ef_softc *sc;
752: int totlen;
753: {
754: bus_space_tag_t iot = sc->sc_iot;
755: bus_space_handle_t ioh = sc->sc_ioh;
756: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
757: struct mbuf *top, **mp, *m;
758: int len, pad, s;
759:
760: MGETHDR(m, M_DONTWAIT, MT_DATA);
761: if (m == NULL)
762: return (NULL);
763: m->m_pkthdr.rcvif = ifp;
764: m->m_pkthdr.len = totlen;
765: pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
766: m->m_data += pad;
767: len = MHLEN -pad;
768: top = 0;
769: mp = ⊤
770:
771: s = splhigh();
772:
773: while (totlen > 0) {
774: if (top) {
775: MGET(m, M_DONTWAIT, MT_DATA);
776: if (m == NULL) {
777: m_freem(top);
778: splx(s);
779: return (NULL);
780: }
781: len = MLEN;
782: }
783: if (top && totlen >= MINCLSIZE) {
784: MCLGET(m, M_DONTWAIT);
785: if (m->m_flags & M_EXT)
786: len = MCLBYTES;
787: }
788: len = min(totlen, len);
789: if (len > 1) {
790: len &= ~1;
791: bus_space_read_raw_multi_2(iot, ioh,
792: EF_W1_RX_PIO_RR_1, mtod(m, u_int8_t *),
793: len);
794: } else
795: *(mtod(m, u_int8_t *)) =
796: bus_space_read_1(iot, ioh, EF_W1_RX_PIO_RR_1);
797:
798: m->m_len = len;
799: totlen -= len;
800: *mp = m;
801: mp = &m->m_next;
802: }
803:
804: efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
805:
806: splx(s);
807:
808: return (top);
809: }
810:
811: #define MII_SET(sc, x) \
812: bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS, \
813: bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS) \
814: | (x))
815:
816: #define MII_CLR(sc, x) \
817: bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS, \
818: bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS) \
819: & (~(x)))
820:
821: void
822: ef_mii_writeb(sc, b)
823: struct ef_softc *sc;
824: int b;
825: {
826: MII_CLR(sc, EF_MII_CLK);
827:
828: if (b)
829: MII_SET(sc, EF_MII_DATA);
830: else
831: MII_CLR(sc, EF_MII_DATA);
832:
833: MII_CLR(sc, EF_MII_CLK);
834: DELAY(1);
835: MII_SET(sc, EF_MII_CLK);
836: DELAY(1);
837: }
838:
839: void
840: ef_mii_sync(sc)
841: struct ef_softc *sc;
842: {
843: int i;
844:
845: for (i = 0; i < 32; i++)
846: ef_mii_writeb(sc, 1);
847: }
848:
849: int
850: ef_miibus_readreg(dev, phy, reg)
851: struct device *dev;
852: int phy, reg;
853: {
854: struct ef_softc *sc = (struct ef_softc *)dev;
855: int i, ack, s, val = 0;
856:
857: s = splnet();
858:
859: GO_WINDOW(4);
860: bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS, 0);
861:
862: /* Turn on xmit */
863: MII_SET(sc, EF_MII_DIR);
864: MII_CLR(sc, EF_MII_CLK);
865:
866: ef_mii_sync(sc);
867:
868: /* Transmit start sequence */
869: ef_mii_writeb(sc, 0);
870: ef_mii_writeb(sc, 1);
871:
872: /* Transmit read sequence */
873: ef_mii_writeb(sc, 1);
874: ef_mii_writeb(sc, 0);
875:
876: /* Transmit phy addr */
877: for (i = 0x10; i; i >>= 1)
878: ef_mii_writeb(sc, (phy & i) ? 1 : 0);
879:
880: /* Transmit reg addr */
881: for (i = 0x10; i; i >>= 1)
882: ef_mii_writeb(sc, (reg & i) ? 1 : 0);
883:
884: /* First cycle of turnaround */
885: MII_CLR(sc, EF_MII_CLK | EF_MII_DATA);
886: DELAY(1);
887: MII_SET(sc, EF_MII_CLK);
888: DELAY(1);
889:
890: /* Turn off xmit */
891: MII_CLR(sc, EF_MII_DIR);
892:
893: /* Second cycle of turnaround */
894: MII_CLR(sc, EF_MII_CLK);
895: DELAY(1);
896: MII_SET(sc, EF_MII_CLK);
897: DELAY(1);
898: ack = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS) &
899: EF_MII_DATA;
900:
901: /* Read 16bit data */
902: for (i = 0x8000; i; i >>= 1) {
903: MII_CLR(sc, EF_MII_CLK);
904: DELAY(1);
905: if (bus_space_read_2(sc->sc_iot, sc->sc_ioh,
906: EP_W4_CTRLR_STATUS) & EF_MII_DATA)
907: val |= i;
908: MII_SET(sc, EF_MII_CLK);
909: DELAY(1);
910: }
911:
912: MII_CLR(sc, EF_MII_CLK);
913: DELAY(1);
914: MII_SET(sc, EF_MII_CLK);
915: DELAY(1);
916:
917: splx(s);
918:
919: return (val);
920: }
921:
922: void
923: ef_miibus_writereg(dev, phy, reg, val)
924: struct device *dev;
925: int phy, reg, val;
926: {
927: struct ef_softc *sc = (struct ef_softc *)dev;
928: int s, i;
929:
930: s = splnet();
931:
932: GO_WINDOW(4);
933: bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS, 0);
934:
935: /* Turn on xmit */
936: MII_SET(sc, EF_MII_DIR);
937:
938: ef_mii_sync(sc);
939:
940: ef_mii_writeb(sc, 0);
941: ef_mii_writeb(sc, 1);
942: ef_mii_writeb(sc, 0);
943: ef_mii_writeb(sc, 1);
944:
945: for (i = 0x10; i; i >>= 1)
946: ef_mii_writeb(sc, (phy & i) ? 1 : 0);
947:
948: for (i = 0x10; i; i >>= 1)
949: ef_mii_writeb(sc, (reg & i) ? 1 : 0);
950:
951: ef_mii_writeb(sc, 1);
952: ef_mii_writeb(sc, 0);
953:
954: for (i = 0x8000; i; i >>= 1)
955: ef_mii_writeb(sc, (val & i) ? 1 : 0);
956:
957: splx(s);
958: }
959:
960: int
961: ef_ifmedia_upd(ifp)
962: struct ifnet *ifp;
963: {
964: struct ef_softc *sc = ifp->if_softc;
965:
966: mii_mediachg(&sc->sc_mii);
967: return (0);
968: }
969:
970: void
971: ef_ifmedia_sts(ifp, ifmr)
972: struct ifnet *ifp;
973: struct ifmediareq *ifmr;
974: {
975: struct ef_softc *sc = ifp->if_softc;
976:
977: mii_pollstat(&sc->sc_mii);
978: ifmr->ifm_status = sc->sc_mii.mii_media_status;
979: ifmr->ifm_active = sc->sc_mii.mii_media_active;
980: }
981:
982: void
983: ef_miibus_statchg(self)
984: struct device *self;
985: {
986: struct ef_softc *sc = (struct ef_softc *)self;
987: int s;
988:
989: s = splnet();
990: GO_WINDOW(3);
991: /* Set duplex bit appropriately */
992: if ((sc->sc_mii.mii_media_active & IFM_GMASK) == IFM_FDX)
993: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
994: EP_W3_MAC_CONTROL, 0x20);
995: else
996: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
997: EP_W3_MAC_CONTROL, 0x00);
998: GO_WINDOW(7);
999: splx(s);
1000: }
1001:
1002: void
1003: ef_tick(v)
1004: void *v;
1005: {
1006: struct ef_softc *sc = v;
1007: int s;
1008:
1009: s = splnet();
1010: mii_tick(&sc->sc_mii);
1011: splx(s);
1012: timeout_add(&sc->sc_tick_tmo, hz);
1013: }
CVSweb