Annotation of src/sys/dev/ic/elink3.c, Revision 1.45
1.45 ! thorpej 1: /* $NetBSD: elink3.c,v 1.44 1998/08/17 23:20:39 thorpej Exp $ */
1.41 thorpej 2:
3: /*-
4: * Copyright (c) 1998 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9: * NASA Ames Research Center.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
1.1 thorpej 39:
40: /*
1.19 jonathan 41: * Copyright (c) 1996, 1997 Jonathan Stone <jonathan@NetBSD.org>
1.6 thorpej 42: * Copyright (c) 1994 Herb Peyerl <hpeyerl@beer.org>
1.1 thorpej 43: * All rights reserved.
44: *
45: * Redistribution and use in source and binary forms, with or without
46: * modification, are permitted provided that the following conditions
47: * are met:
48: * 1. Redistributions of source code must retain the above copyright
49: * notice, this list of conditions and the following disclaimer.
50: * 2. Redistributions in binary form must reproduce the above copyright
51: * notice, this list of conditions and the following disclaimer in the
52: * documentation and/or other materials provided with the distribution.
53: * 3. All advertising materials mentioning features or use of this software
54: * must display the following acknowledgement:
55: * This product includes software developed by Herb Peyerl.
56: * 4. The name of Herb Peyerl may not be used to endorse or promote products
57: * derived from this software without specific prior written permission.
58: *
59: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
60: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
61: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
63: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
64: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
65: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
67: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
68: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69: */
70:
1.39 jonathan 71: #include "opt_inet.h"
1.40 jonathan 72: #include "opt_ns.h"
1.1 thorpej 73: #include "bpfilter.h"
1.35 explorer 74: #include "rnd.h"
1.1 thorpej 75:
76: #include <sys/param.h>
1.3 christos 77: #include <sys/systm.h>
1.41 thorpej 78: #include <sys/kernel.h>
1.1 thorpej 79: #include <sys/mbuf.h>
80: #include <sys/socket.h>
81: #include <sys/ioctl.h>
82: #include <sys/errno.h>
83: #include <sys/syslog.h>
84: #include <sys/select.h>
85: #include <sys/device.h>
1.35 explorer 86: #if NRND > 0
87: #include <sys/rnd.h>
88: #endif
1.1 thorpej 89:
90: #include <net/if.h>
91: #include <net/if_dl.h>
1.21 is 92: #include <net/if_ether.h>
1.22 jonathan 93: #include <net/if_media.h>
1.1 thorpej 94:
95: #ifdef INET
96: #include <netinet/in.h>
97: #include <netinet/in_systm.h>
98: #include <netinet/in_var.h>
99: #include <netinet/ip.h>
1.21 is 100: #include <netinet/if_inarp.h>
1.1 thorpej 101: #endif
102:
103: #ifdef NS
104: #include <netns/ns.h>
105: #include <netns/ns_if.h>
106: #endif
107:
108: #if NBPFILTER > 0
109: #include <net/bpf.h>
110: #include <net/bpfdesc.h>
111: #endif
112:
113: #include <machine/cpu.h>
1.2 thorpej 114: #include <machine/bus.h>
1.7 thorpej 115: #include <machine/intr.h>
1.1 thorpej 116:
1.41 thorpej 117: #include <dev/mii/mii.h>
118: #include <dev/mii/miivar.h>
119:
1.1 thorpej 120: #include <dev/ic/elink3var.h>
121: #include <dev/ic/elink3reg.h>
122:
123: #define ETHER_MIN_LEN 64
124: #define ETHER_MAX_LEN 1518
125: #define ETHER_ADDR_LEN 6
126:
1.36 jonathan 127: #ifdef DEBUG
128: int epdebug = 0;
129: #endif
130:
1.23 jonathan 131: /*
1.41 thorpej 132: * Structure to map media-present bits in boards to ifmedia codes and
133: * printable media names. Used for table-driven ifmedia initialization.
1.23 jonathan 134: */
135: struct ep_media {
1.41 thorpej 136: int epm_mpbit; /* media present bit */
137: const char *epm_name; /* name of medium */
1.23 jonathan 138: int epm_ifmedia; /* ifmedia word for medium */
1.41 thorpej 139: int epm_epmedia; /* EPMEDIA_* constant */
1.23 jonathan 140: };
141:
142: /*
1.41 thorpej 143: * Media table for the Demon/Vortex/Boomerang chipsets.
144: *
145: * Note that MII on the Demon and Vortex (3c59x) indicates an external
146: * MII connector (for connecting an external PHY) ... I think. Treat
147: * it as `manual' on these chips.
1.23 jonathan 148: *
1.41 thorpej 149: * Any Boomerang (3c90x) chips with MII really do have an internal
150: * MII and real PHYs attached; no `native' media.
1.23 jonathan 151: */
1.41 thorpej 152: struct ep_media ep_vortex_media[] = {
153: { EP_PCI_10BASE_T, "10baseT", IFM_ETHER|IFM_10_T,
154: EPMEDIA_10BASE_T },
1.45 ! thorpej 155: { EP_PCI_10BASE_T, "10baseT-FDX", IFM_ETHER|IFM_10_T|IFM_FDX,
! 156: EPMEDIA_10BASE_T },
1.41 thorpej 157: { EP_PCI_AUI, "10base5/AUI", IFM_ETHER|IFM_10_5,
158: EPMEDIA_AUI },
159: { EP_PCI_BNC, "10base2/BNC", IFM_ETHER|IFM_10_2,
160: EPMEDIA_10BASE_2 },
161: { EP_PCI_100BASE_TX, "100baseTX", IFM_ETHER|IFM_100_TX,
162: EPMEDIA_100BASE_TX },
1.45 ! thorpej 163: { EP_PCI_100BASE_TX, "100baseTX-FDX",IFM_ETHER|IFM_100_TX|IFM_FDX,
! 164: EPMEDIA_100BASE_TX },
1.41 thorpej 165: { EP_PCI_100BASE_FX, "100baseFX", IFM_ETHER|IFM_100_FX,
166: EPMEDIA_100BASE_FX },
167: { EP_PCI_100BASE_MII, "manual", IFM_ETHER|IFM_MANUAL,
168: EPMEDIA_MII },
169: { EP_PCI_100BASE_T4, "100baseT4", IFM_ETHER|IFM_100_T4,
170: EPMEDIA_100BASE_T4 },
171: { 0, NULL, 0,
172: 0 },
1.23 jonathan 173: };
174:
175: /*
1.41 thorpej 176: * Media table for the older 3Com Etherlink III chipset, used
177: * in the 3c509, 3c579, and 3c589.
1.23 jonathan 178: */
1.41 thorpej 179: struct ep_media ep_509_media[] = {
180: { EP_W0_CC_UTP, "10baseT", IFM_ETHER|IFM_10_T,
181: EPMEDIA_10BASE_T },
182: { EP_W0_CC_AUI, "10base5/AUI", IFM_ETHER|IFM_10_5,
183: EPMEDIA_AUI },
184: { EP_W0_CC_BNC, "10base2/BNC", IFM_ETHER|IFM_10_2,
185: EPMEDIA_10BASE_2 },
186: { 0, NULL, 0,
187: 0 },
1.23 jonathan 188: };
189:
1.15 jonathan 190: void ep_internalconfig __P((struct ep_softc *sc));
1.20 jonathan 191: void ep_vortex_probemedia __P((struct ep_softc *sc));
1.41 thorpej 192: void ep_509_probemedia __P((struct ep_softc *sc));
1.20 jonathan 193:
1.3 christos 194: static void eptxstat __P((struct ep_softc *));
1.1 thorpej 195: static int epstatus __P((struct ep_softc *));
196: void epinit __P((struct ep_softc *));
197: int epioctl __P((struct ifnet *, u_long, caddr_t));
198: void epstart __P((struct ifnet *));
1.5 thorpej 199: void epwatchdog __P((struct ifnet *));
1.1 thorpej 200: void epreset __P((struct ep_softc *));
1.16 jonathan 201: static void epshutdown __P((void *));
1.23 jonathan 202: void epread __P((struct ep_softc *));
1.1 thorpej 203: struct mbuf *epget __P((struct ep_softc *, int));
1.23 jonathan 204: void epmbuffill __P((void *));
205: void epmbufempty __P((struct ep_softc *));
206: void epsetfilter __P((struct ep_softc *));
1.41 thorpej 207: void epsetmedia __P((struct ep_softc *));
1.34 thorpej 208:
209: int epenable __P((struct ep_softc *));
210: void epdisable __P((struct ep_softc *));
1.23 jonathan 211:
212: /* ifmedia callbacks */
213: int ep_media_change __P((struct ifnet *ifp));
214: void ep_media_status __P((struct ifnet *ifp, struct ifmediareq *req));
1.1 thorpej 215:
1.41 thorpej 216: /* MII callbacks */
217: int ep_mii_readreg __P((struct device *, int, int));
218: void ep_mii_writereg __P((struct device *, int, int, int));
219: void ep_statchg __P((struct device *));
220:
221: void ep_tick __P((void *));
222:
223: void ep_mii_setbit __P((struct ep_softc *, u_int16_t));
224: void ep_mii_clrbit __P((struct ep_softc *, u_int16_t));
225: u_int16_t ep_mii_readbit __P((struct ep_softc *, u_int16_t));
226: void ep_mii_sync __P((struct ep_softc *));
227: void ep_mii_sendbits __P((struct ep_softc *, u_int32_t, int));
228:
1.1 thorpej 229: static int epbusyeeprom __P((struct ep_softc *));
1.19 jonathan 230: static inline void ep_complete_cmd __P((struct ep_softc *sc,
231: u_int cmd, u_int arg));
1.42 thorpej 232: static __inline int ep_w1_reg __P((struct ep_softc *, int));
1.19 jonathan 233:
1.42 thorpej 234: /*
235: * Some chips (3c515 [Corkscrew] and 3c574 [RoadRunner]) have
236: * Window 1 registers offset!
237: */
238: static __inline int
239: ep_w1_reg(sc, reg)
240: struct ep_softc *sc;
241: int reg;
242: {
243:
244: switch (sc->ep_chipset) {
245: case EP_CHIPSET_CORKSCREW:
246: return (reg + 0x10);
247:
248: case EP_CHIPSET_ROADRUNNER:
249: switch (reg) {
250: case EP_W1_FREE_TX:
251: case EP_W1_RUNNER_RDCTL:
252: case EP_W1_RUNNER_WRCTL:
253: return (reg);
254: }
255: return (reg + 0x10);
256: }
257:
258: return (reg);
259: }
1.19 jonathan 260:
261: /*
262: * Issue a (reset) command, and be sure it has completed.
263: * Used for commands that reset part or all of the board.
264: * On newer hardware we could poll SC_COMMAND_IN_PROGRESS,
265: * but older hardware doesn't implement it and we must delay.
266: * It's easiest to just delay always.
267: */
268: static inline void
269: ep_complete_cmd(sc, cmd, arg)
270: struct ep_softc *sc;
271: u_int cmd, arg;
272: {
273: register bus_space_tag_t iot = sc->sc_iot;
274: register bus_space_handle_t ioh = sc->sc_ioh;
275:
276: bus_space_write_2(iot, ioh, cmd, arg);
277:
278: #ifdef notyet
279: /* if this adapter family has S_COMMAND_IN_PROGRESS, use it */
280: while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
281: ;
282: else
283: #else
284: DELAY(100000); /* need at least 1 ms, but be generous. */
285: #endif
286: }
287:
1.20 jonathan 288: /*
289: * Back-end attach and configure.
290: */
1.1 thorpej 291: void
1.34 thorpej 292: epconfig(sc, chipset, enaddr)
1.1 thorpej 293: struct ep_softc *sc;
1.20 jonathan 294: u_short chipset;
1.34 thorpej 295: u_int8_t *enaddr;
1.1 thorpej 296: {
1.21 is 297: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.11 thorpej 298: bus_space_tag_t iot = sc->sc_iot;
299: bus_space_handle_t ioh = sc->sc_ioh;
1.7 thorpej 300: u_int16_t i;
1.21 is 301: u_int8_t myla[6];
1.1 thorpej 302:
1.20 jonathan 303: sc->ep_chipset = chipset;
1.32 thorpej 304:
305: /*
306: * We could have been groveling around in other register
307: * windows in the front-end; make sure we're in window 0
308: * to read the EEPROM.
309: */
310: GO_WINDOW(0);
1.1 thorpej 311:
1.34 thorpej 312: if (enaddr == NULL) {
313: /*
314: * Read the station address from the eeprom
315: */
316: for (i = 0; i < 3; i++) {
317: u_int16_t x;
318: if (epbusyeeprom(sc))
319: return; /* XXX why is eeprom busy? */
320: bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND,
321: READ_EEPROM | i);
322: if (epbusyeeprom(sc))
323: return; /* XXX why is eeprom busy? */
324: x = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA);
325: myla[(i << 1)] = x >> 8;
326: myla[(i << 1) + 1] = x;
327: }
328: enaddr = myla;
1.1 thorpej 329: }
330:
1.12 jonathan 331: /*
1.41 thorpej 332: * Vortex-based (3c59x pci,eisa) and Boomerang (3c900) cards
1.23 jonathan 333: * allow FDDI-sized (4500) byte packets. Commands only take an
334: * 11-bit parameter, and 11 bits isn't enough to hold a full-size
335: * packet length.
1.12 jonathan 336: * Commands to these cards implicitly upshift a packet size
337: * or threshold by 2 bits.
338: * To detect cards with large-packet support, we probe by setting
339: * the transmit threshold register, then change windows and
340: * read back the threshold register directly, and see if the
341: * threshold value was shifted or not.
342: */
343: bus_space_write_2(iot, ioh, EP_COMMAND,
1.13 jonathan 344: SET_TX_AVAIL_THRESH | EP_LARGEWIN_PROBE );
1.12 jonathan 345: GO_WINDOW(5);
346: i = bus_space_read_2(iot, ioh, EP_W5_TX_AVAIL_THRESH);
347: GO_WINDOW(1);
348: switch (i) {
1.13 jonathan 349: case EP_LARGEWIN_PROBE:
350: case (EP_LARGEWIN_PROBE & EP_LARGEWIN_MASK):
1.12 jonathan 351: sc->ep_pktlenshift = 0;
352: break;
353:
1.13 jonathan 354: case (EP_LARGEWIN_PROBE << 2):
1.12 jonathan 355: sc->ep_pktlenshift = 2;
356: break;
357:
358: default:
1.34 thorpej 359: printf("%s: wrote 0x%x to TX_AVAIL_THRESH, read back 0x%x. "
1.14 cjs 360: "Interface disabled\n",
1.34 thorpej 361: sc->sc_dev.dv_xname, EP_LARGEWIN_PROBE, (int) i);
1.12 jonathan 362: return;
363: }
1.20 jonathan 364:
1.12 jonathan 365: /*
366: * Ensure Tx-available interrupts are enabled for
367: * start the interface.
1.23 jonathan 368: * XXX should be in epinit()?
1.12 jonathan 369: */
370: bus_space_write_2(iot, ioh, EP_COMMAND,
371: SET_TX_AVAIL_THRESH | (1600 >> sc->ep_pktlenshift));
372:
1.23 jonathan 373: bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
374: ifp->if_softc = sc;
375: ifp->if_start = epstart;
376: ifp->if_ioctl = epioctl;
377: ifp->if_watchdog = epwatchdog;
378: ifp->if_flags =
379: IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
380:
381: if_attach(ifp);
1.34 thorpej 382: ether_ifattach(ifp, enaddr);
1.23 jonathan 383:
384: /*
385: * Finish configuration:
386: * determine chipset if the front-end couldn't do so,
387: * show board details, set media.
388: */
389:
1.41 thorpej 390: /*
391: * Print RAM size. We also print the Ethernet address in here.
392: * It's extracted from the ifp, so we have to make sure it's
393: * been attached first.
394: */
1.23 jonathan 395: ep_internalconfig(sc);
396: GO_WINDOW(0);
397:
1.41 thorpej 398: /*
1.44 thorpej 399: * Display some additional information, if pertinent.
400: */
401: if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER)
402: printf("%s: RoadRunner FIFO buffer enabled\n",
403: sc->sc_dev.dv_xname);
404:
405: /*
1.41 thorpej 406: * Initialize our media structures and MII info. We'll
407: * probe the MII if we discover that we have one.
1.20 jonathan 408: */
1.41 thorpej 409: sc->sc_mii.mii_ifp = ifp;
410: sc->sc_mii.mii_readreg = ep_mii_readreg;
411: sc->sc_mii.mii_writereg = ep_mii_writereg;
412: sc->sc_mii.mii_statchg = ep_statchg;
413: ifmedia_init(&sc->sc_mii.mii_media, 0, ep_media_change,
414: ep_media_status);
1.20 jonathan 415:
416: /*
1.41 thorpej 417: * Now, determine which media we have.
1.20 jonathan 418: */
419: switch (sc->ep_chipset) {
1.41 thorpej 420: case EP_CHIPSET_BOOMERANG:
1.42 thorpej 421: case EP_CHIPSET_ROADRUNNER:
1.41 thorpej 422: /*
423: * If the device has MII, probe it. We won't be using
424: * any `native' media in this case, only PHYs. If
425: * we don't, just treat the Boomerang like the Vortex.
426: */
427: if (sc->ep_flags & EP_FLAGS_MII) {
428: mii_phy_probe(&sc->sc_dev, &sc->sc_mii, 0xffffffff);
429: if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
430: ifmedia_add(&sc->sc_mii.mii_media,
431: IFM_ETHER|IFM_NONE, 0, NULL);
432: ifmedia_set(&sc->sc_mii.mii_media,
433: IFM_ETHER|IFM_NONE);
434: } else {
435: ifmedia_set(&sc->sc_mii.mii_media,
436: IFM_ETHER|IFM_AUTO);
437: }
438: break;
439: }
440: /* FALLTHROUGH */
441:
1.20 jonathan 442: case EP_CHIPSET_VORTEX:
443: ep_vortex_probemedia(sc);
444: break;
445:
446: default:
1.41 thorpej 447: ep_509_probemedia(sc);
1.20 jonathan 448: break;
449: }
1.23 jonathan 450:
1.20 jonathan 451: GO_WINDOW(1); /* Window 1 is operating window */
452:
1.1 thorpej 453: #if NBPFILTER > 0
1.21 is 454: bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB,
1.1 thorpej 455: sizeof(struct ether_header));
456: #endif
457:
1.35 explorer 458: #if NRND > 0
459: rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, RND_TYPE_NET);
460: #endif
461:
1.1 thorpej 462: sc->tx_start_thresh = 20; /* probably a good starting point. */
1.12 jonathan 463:
1.16 jonathan 464: /* Establish callback to reset card when we reboot. */
465: shutdownhook_establish(epshutdown, sc);
466:
1.19 jonathan 467: ep_complete_cmd(sc, EP_COMMAND, RX_RESET);
468: ep_complete_cmd(sc, EP_COMMAND, TX_RESET);
1.1 thorpej 469: }
470:
1.23 jonathan 471:
1.1 thorpej 472: /*
1.15 jonathan 473: * Show interface-model-independent info from window 3
474: * internal-configuration register.
475: */
476: void
477: ep_internalconfig(sc)
478: struct ep_softc *sc;
479: {
480: bus_space_tag_t iot = sc->sc_iot;
481: bus_space_handle_t ioh = sc->sc_ioh;
482:
483: u_int config0;
484: u_int config1;
485:
486: int ram_size, ram_width, ram_speed, rom_size, ram_split;
487: /*
488: * NVRAM buffer Rx:Tx config names for busmastering cards
489: * (Demon, Vortex, and later).
490: */
491: const char *onboard_ram_config[] = {
1.38 augustss 492: "5:3", "3:1", "1:1", "3:5" };
1.15 jonathan 493:
494: GO_WINDOW(3);
495: config0 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG);
1.28 veego 496: config1 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2);
1.15 jonathan 497: GO_WINDOW(0);
498:
499: ram_size = (config0 & CONFIG_RAMSIZE) >> CONFIG_RAMSIZE_SHIFT;
500: ram_width = (config0 & CONFIG_RAMWIDTH) >> CONFIG_RAMWIDTH_SHIFT;
501: ram_speed = (config0 & CONFIG_RAMSPEED) >> CONFIG_RAMSPEED_SHIFT;
502: rom_size = (config0 & CONFIG_ROMSIZE) >> CONFIG_ROMSIZE_SHIFT;
503:
504: ram_split = (config1 & CONFIG_RAMSPLIT) >> CONFIG_RAMSPLIT_SHIFT;
505:
1.41 thorpej 506: printf("%s: address %s, %dKB %s-wide FIFO, %s Rx:Tx split\n",
1.23 jonathan 507: sc->sc_dev.dv_xname,
1.41 thorpej 508: ether_sprintf(LLADDR(sc->sc_ethercom.ec_if.if_sadl)),
1.23 jonathan 509: 8 << ram_size,
510: (ram_width) ? "word" : "byte",
511: onboard_ram_config[ram_split]);
1.15 jonathan 512: }
513:
1.23 jonathan 514:
1.20 jonathan 515: /*
1.23 jonathan 516: * Find supported media on 3c509-generation hardware that doesn't have
1.20 jonathan 517: * a "reset_options" register in window 3.
1.23 jonathan 518: * Use the config_cntrl register in window 0 instead.
519: * Used on original, 10Mbit ISA (3c509), 3c509B, and pre-Demon EISA cards
520: * that implement CONFIG_CTRL. We don't have a good way to set the
521: * default active mediuim; punt to ifconfig instead.
1.20 jonathan 522: */
523: void
1.41 thorpej 524: ep_509_probemedia(sc)
1.20 jonathan 525: struct ep_softc *sc;
526: {
527: bus_space_tag_t iot = sc->sc_iot;
528: bus_space_handle_t ioh = sc->sc_ioh;
1.41 thorpej 529: struct ifmedia *ifm = &sc->sc_mii.mii_media;
1.23 jonathan 530: u_int16_t ep_w0_config, port;
1.41 thorpej 531: struct ep_media *epm;
532: const char *sep = "", *defmedianame = NULL;
533: int defmedia = 0;
1.23 jonathan 534:
1.20 jonathan 535: GO_WINDOW(0);
1.23 jonathan 536: ep_w0_config = bus_space_read_2(iot, ioh, EP_W0_CONFIG_CTRL);
537:
1.41 thorpej 538: printf("%s: ", sc->sc_dev.dv_xname);
1.23 jonathan 539:
1.41 thorpej 540: /* Sanity check that there are any media! */
541: if ((ep_w0_config & EP_W0_CC_MEDIAMASK) == 0) {
542: printf("no media present!\n");
543: ifmedia_add(ifm, IFM_ETHER|IFM_NONE, 0, NULL);
544: ifmedia_set(ifm, IFM_ETHER|IFM_NONE);
545: return;
1.23 jonathan 546: }
547:
1.41 thorpej 548: /*
549: * Get the default media from the EEPROM.
550: */
1.23 jonathan 551: if (epbusyeeprom(sc))
552: return; /* XXX why is eeprom busy? */
553: bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND,
1.28 veego 554: READ_EEPROM | EEPROM_ADDR_CFG);
1.23 jonathan 555: if (epbusyeeprom(sc))
556: return; /* XXX why is eeprom busy? */
1.41 thorpej 557: port = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA) >> 14;
1.23 jonathan 558:
1.41 thorpej 559: #define PRINT(s) printf("%s%s", sep, s); sep = ", "
1.23 jonathan 560:
1.41 thorpej 561: for (epm = ep_509_media; epm->epm_name != NULL; epm++) {
562: if (ep_w0_config & epm->epm_mpbit) {
563: if (epm->epm_epmedia == port || defmedia == 0) {
564: defmedia = epm->epm_ifmedia;
565: defmedianame = epm->epm_name;
566: }
567: ifmedia_add(ifm, epm->epm_ifmedia, epm->epm_epmedia,
568: NULL);
569: PRINT(epm->epm_name);
570: }
571: }
572:
573: #undef PRINT
574:
575: #ifdef DIAGNOSTIC
576: if (defmedia == 0)
577: panic("ep_509_probemedia: impossible");
578: #endif
579:
580: printf(" (default %s)\n", defmedianame);
581: ifmedia_set(ifm, defmedia);
1.20 jonathan 582: }
583:
1.15 jonathan 584: /*
1.23 jonathan 585: * Find media present on large-packet-capable elink3 devices.
586: * Show onboard configuration of large-packet-capable elink3 devices
587: * (Demon, Vortex, Boomerang), which do not implement CONFIG_CTRL in window 0.
588: * Use media and card-version info in window 3 instead.
1.15 jonathan 589: */
590: void
1.20 jonathan 591: ep_vortex_probemedia(sc)
1.15 jonathan 592: struct ep_softc *sc;
593: {
594: bus_space_tag_t iot = sc->sc_iot;
595: bus_space_handle_t ioh = sc->sc_ioh;
1.41 thorpej 596: struct ifmedia *ifm = &sc->sc_mii.mii_media;
597: struct ep_media *epm;
598: u_int config1;
1.15 jonathan 599: int reset_options;
1.28 veego 600: int default_media; /* 3-bit encoding of default (EEPROM) media */
1.41 thorpej 601: int defmedia = 0;
602: const char *sep = "", *defmedianame = NULL;
1.15 jonathan 603:
604: GO_WINDOW(3);
1.28 veego 605: config1 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2);
1.41 thorpej 606: reset_options = (int)bus_space_read_1(iot, ioh, EP_W3_RESET_OPTIONS);
1.15 jonathan 607: GO_WINDOW(0);
608:
1.23 jonathan 609: default_media = (config1 & CONFIG_MEDIAMASK) >> CONFIG_MEDIAMASK_SHIFT;
1.15 jonathan 610:
1.41 thorpej 611: printf("%s: ", sc->sc_dev.dv_xname);
612:
613: /* Sanity check that there are any media! */
614: if ((reset_options & EP_PCI_MEDIAMASK) == 0) {
615: printf("no media present!\n");
616: ifmedia_add(ifm, IFM_ETHER|IFM_NONE, 0, NULL);
617: ifmedia_set(ifm, IFM_ETHER|IFM_NONE);
618: return;
619: }
620:
621: #define PRINT(s) printf("%s%s", sep, s); sep = ", "
1.23 jonathan 622:
1.41 thorpej 623: for (epm = ep_vortex_media; epm->epm_name != NULL; epm++) {
624: if (reset_options & epm->epm_mpbit) {
625: if (epm->epm_epmedia == default_media ||
626: defmedia == 0) {
627: defmedia = epm->epm_ifmedia;
628: defmedianame = epm->epm_name;
629: }
630: ifmedia_add(ifm, epm->epm_ifmedia, epm->epm_epmedia,
631: NULL);
632: PRINT(epm->epm_name);
1.23 jonathan 633: }
634: }
1.15 jonathan 635:
1.41 thorpej 636: #undef PRINT
637:
638: #ifdef DIAGNOSTIC
639: if (defmedia == 0)
640: panic("ep_vortex_probemedia: impossible");
641: #endif
642:
643: printf(" (default %s)\n", defmedianame);
644: ifmedia_set(ifm, defmedia);
645: }
646:
647: /*
648: * One second timer, used to tick the MII.
649: */
650: void
651: ep_tick(arg)
652: void *arg;
653: {
654: struct ep_softc *sc = arg;
655: int s;
1.15 jonathan 656:
1.41 thorpej 657: #ifdef DIAGNOSTIC
658: if ((sc->ep_flags & EP_FLAGS_MII) == 0)
659: panic("ep_tick");
660: #endif
1.31 jonathan 661:
1.41 thorpej 662: s = splnet();
663: mii_tick(&sc->sc_mii);
664: splx(s);
1.15 jonathan 665:
1.41 thorpej 666: timeout(ep_tick, sc, hz);
1.15 jonathan 667: }
668:
669: /*
1.20 jonathan 670: * Bring device up.
671: *
1.1 thorpej 672: * The order in here seems important. Otherwise we may not receive
673: * interrupts. ?!
674: */
675: void
676: epinit(sc)
677: register struct ep_softc *sc;
678: {
1.21 is 679: register struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.11 thorpej 680: bus_space_tag_t iot = sc->sc_iot;
681: bus_space_handle_t ioh = sc->sc_ioh;
1.1 thorpej 682: int i;
683:
1.11 thorpej 684: while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
1.1 thorpej 685: ;
686:
687: if (sc->bustype != EP_BUS_PCI) {
688: GO_WINDOW(0);
1.11 thorpej 689: bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, 0);
690: bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
1.1 thorpej 691: }
692:
693: if (sc->bustype == EP_BUS_PCMCIA) {
1.11 thorpej 694: bus_space_write_2(iot, ioh, EP_W0_RESOURCE_CFG, 0x3f00);
1.1 thorpej 695: }
696:
697: GO_WINDOW(2);
698: for (i = 0; i < 6; i++) /* Reload the ether_addr. */
1.11 thorpej 699: bus_space_write_1(iot, ioh, EP_W2_ADDR_0 + i,
1.21 is 700: LLADDR(ifp->if_sadl)[i]);
1.8 christos 701:
1.12 jonathan 702: /*
703: * Reset the station-address receive filter.
1.41 thorpej 704: * A bug workaround for busmastering (Vortex, Demon) cards.
1.12 jonathan 705: */
706: for (i = 0; i < 6; i++)
707: bus_space_write_1(iot, ioh, EP_W2_RECVMASK_0 + i, 0);
1.1 thorpej 708:
1.19 jonathan 709: ep_complete_cmd(sc, EP_COMMAND, RX_RESET);
710: ep_complete_cmd(sc, EP_COMMAND, TX_RESET);
1.1 thorpej 711:
712: GO_WINDOW(1); /* Window 1 is operating window */
713: for (i = 0; i < 31; i++)
1.42 thorpej 714: bus_space_read_1(iot, ioh, ep_w1_reg(sc, EP_W1_TX_STATUS));
1.31 jonathan 715:
716: /* Set threshhold for for Tx-space avaiable interrupt. */
717: bus_space_write_2(iot, ioh, EP_COMMAND,
718: SET_TX_AVAIL_THRESH | (1600 >> sc->ep_pktlenshift));
1.1 thorpej 719:
1.44 thorpej 720: if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) {
721: /*
722: * Enable options in the PCMCIA LAN COR register, via
723: * RoadRunner Window 1.
724: *
725: * XXX MAGIC CONSTANTS!
726: */
727: u_int16_t cor;
728:
729: bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, (1 << 11));
730:
731: cor = bus_space_read_2(iot, ioh, 0) & ~0x30;
732: if (sc->ep_flags & EP_FLAGS_USESHAREDMEM)
733: cor |= 0x10;
734: if (sc->ep_flags & EP_FLAGS_FORCENOWAIT)
735: cor |= 0x20;
736: bus_space_write_2(iot, ioh, 0, cor);
737:
738: bus_space_write_2(iot, ioh, EP_W1_RUNNER_WRCTL, 0);
739: bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, 0);
740: }
741:
1.18 jonathan 742: /* Enable interrupts. */
1.28 veego 743: bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE |
1.1 thorpej 744: S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
1.11 thorpej 745: bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK | S_CARD_FAILURE |
1.1 thorpej 746: S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
747:
748: /*
749: * Attempt to get rid of any stray interrupts that occured during
750: * configuration. On the i386 this isn't possible because one may
751: * already be queued. However, a single stray interrupt is
752: * unimportant.
753: */
1.11 thorpej 754: bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | 0xff);
1.1 thorpej 755:
756: epsetfilter(sc);
1.41 thorpej 757: epsetmedia(sc);
1.1 thorpej 758:
1.11 thorpej 759: bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE);
760: bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
1.1 thorpej 761:
762: epmbuffill(sc);
763:
764: /* Interface is now `running', with no output active. */
765: ifp->if_flags |= IFF_RUNNING;
766: ifp->if_flags &= ~IFF_OACTIVE;
767:
1.41 thorpej 768: if (sc->ep_flags & EP_FLAGS_MII) {
769: /* Start the one second clock. */
770: timeout(ep_tick, sc, hz);
771: }
772:
1.1 thorpej 773: /* Attempt to start output, if any. */
774: epstart(ifp);
775: }
776:
1.20 jonathan 777:
778: /*
779: * Set multicast receive filter.
780: * elink3 hardware has no selective multicast filter in hardware.
781: * Enable reception of all multicasts and filter in software.
782: */
1.1 thorpej 783: void
784: epsetfilter(sc)
785: register struct ep_softc *sc;
786: {
1.21 is 787: register struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.1 thorpej 788:
789: GO_WINDOW(1); /* Window 1 is operating window */
1.11 thorpej 790: bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_COMMAND, SET_RX_FILTER |
1.1 thorpej 791: FIL_INDIVIDUAL | FIL_BRDCST |
792: ((ifp->if_flags & IFF_MULTICAST) ? FIL_MULTICAST : 0 ) |
793: ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 ));
794: }
795:
1.23 jonathan 796: int
797: ep_media_change(ifp)
798: struct ifnet *ifp;
799: {
800: register struct ep_softc *sc = ifp->if_softc;
801:
1.41 thorpej 802: if (sc->enabled && (ifp->if_flags & IFF_UP) != 0)
803: epreset(sc);
1.34 thorpej 804:
805: return (0);
1.23 jonathan 806: }
807:
1.15 jonathan 808: /*
1.41 thorpej 809: * Set the card to use the specified media.
1.15 jonathan 810: */
1.34 thorpej 811: void
1.41 thorpej 812: epsetmedia(sc)
813: struct ep_softc *sc;
1.1 thorpej 814: {
1.11 thorpej 815: bus_space_tag_t iot = sc->sc_iot;
816: bus_space_handle_t ioh = sc->sc_ioh;
1.23 jonathan 817:
1.41 thorpej 818: /* Turn everything off. First turn off linkbeat and UTP. */
1.1 thorpej 819: GO_WINDOW(4);
1.41 thorpej 820: bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, 0x0);
1.23 jonathan 821:
822: /* Turn off coax */
823: bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
824: delay(1000);
825:
1.29 jonathan 826: /*
1.41 thorpej 827: * If the device has MII, select it, and then tell the
828: * PHY which media to use.
829: */
830: if (sc->ep_flags & EP_FLAGS_MII) {
831: int config0, config1;
832:
833: GO_WINDOW(3);
1.44 thorpej 834:
835: if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) {
836: int resopt;
837:
838: resopt = bus_space_read_2(iot, ioh,
839: EP_W3_RESET_OPTIONS);
840: bus_space_write_2(iot, ioh,
841: EP_W3_RESET_OPTIONS, resopt|EP_RUNNER_ENABLE_MII);
842: }
843:
1.41 thorpej 844: config0 = (u_int)bus_space_read_2(iot, ioh,
845: EP_W3_INTERNAL_CONFIG);
846: config1 = (u_int)bus_space_read_2(iot, ioh,
847: EP_W3_INTERNAL_CONFIG + 2);
848:
849: config1 = config1 & ~CONFIG_MEDIAMASK;
850: config1 |= (EPMEDIA_MII << CONFIG_MEDIAMASK_SHIFT);
851:
852: bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG, config0);
853: bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2, config1);
854: GO_WINDOW(1); /* back to operating window */
855:
856: mii_mediachg(&sc->sc_mii);
857: return;
858: }
859:
860: /*
1.29 jonathan 861: * Now turn on the selected media/transceiver.
862: */
863: GO_WINDOW(4);
1.41 thorpej 864: switch (IFM_SUBTYPE(sc->sc_mii.mii_media.ifm_cur->ifm_media)) {
865: case IFM_10_T:
1.23 jonathan 866: bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE,
1.41 thorpej 867: JABBER_GUARD_ENABLE|LINKBEAT_ENABLE);
1.23 jonathan 868: break;
869:
1.41 thorpej 870: case IFM_10_2:
1.11 thorpej 871: bus_space_write_2(iot, ioh, EP_COMMAND, START_TRANSCEIVER);
1.23 jonathan 872: DELAY(1000); /* 50ms not enmough? */
873: break;
874:
1.41 thorpej 875: case IFM_100_TX:
876: case IFM_100_FX:
877: case IFM_100_T4: /* XXX check documentation */
1.28 veego 878: bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE,
1.41 thorpej 879: LINKBEAT_ENABLE);
1.23 jonathan 880: DELAY(1000); /* not strictly necessary? */
881: break;
882:
1.41 thorpej 883: case IFM_10_5:
1.23 jonathan 884: bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE,
1.41 thorpej 885: SQE_ENABLE);
886: DELAY(1000); /* not strictly necessary? */
887: break;
888:
889: case IFM_MANUAL:
890: /*
891: * Nothing to do here; we are actually enabling the
892: * external PHY on the MII port.
893: */
1.23 jonathan 894: break;
1.41 thorpej 895:
896: case IFM_NONE:
897: printf("%s: interface disabled\n", sc->sc_dev.dv_xname);
898: return;
899:
1.23 jonathan 900: default:
1.41 thorpej 901: panic("epsetmedia: impossible");
1.1 thorpej 902: }
1.23 jonathan 903:
904: /*
1.41 thorpej 905: * Tell the chip which port to use.
1.23 jonathan 906: */
1.41 thorpej 907: switch (sc->ep_chipset) {
908: case EP_CHIPSET_VORTEX:
909: case EP_CHIPSET_BOOMERANG:
910: {
1.45 ! thorpej 911: int mctl, config0, config1;
1.23 jonathan 912:
913: GO_WINDOW(3);
914: config0 = (u_int)bus_space_read_2(iot, ioh,
1.28 veego 915: EP_W3_INTERNAL_CONFIG);
1.23 jonathan 916: config1 = (u_int)bus_space_read_2(iot, ioh,
1.28 veego 917: EP_W3_INTERNAL_CONFIG + 2);
1.23 jonathan 918:
919: config1 = config1 & ~CONFIG_MEDIAMASK;
1.41 thorpej 920: config1 |= (sc->sc_mii.mii_media.ifm_cur->ifm_data <<
921: CONFIG_MEDIAMASK_SHIFT);
922:
1.28 veego 923: bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG, config0);
924: bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2, config1);
1.45 ! thorpej 925:
! 926: mctl = bus_space_read_2(iot, ioh, EP_W3_MAC_CONTROL);
! 927: if (sc->sc_mii.mii_media.ifm_cur->ifm_media & IFM_FDX)
! 928: mctl |= MAC_CONTROL_FDX;
! 929: else
! 930: mctl &= ~MAC_CONTROL_FDX;
! 931: bus_space_write_2(iot, ioh, EP_W3_MAC_CONTROL, mctl);
1.41 thorpej 932: break;
933: }
934: default:
935: {
936: int w0_addr_cfg;
1.28 veego 937:
938: GO_WINDOW(0);
1.29 jonathan 939: w0_addr_cfg = bus_space_read_2(iot, ioh, EP_W0_ADDRESS_CFG);
940: w0_addr_cfg &= 0x3fff;
1.41 thorpej 941: bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG, w0_addr_cfg |
942: (sc->sc_mii.mii_media.ifm_cur->ifm_data << 14));
1.28 veego 943: DELAY(1000);
1.41 thorpej 944: break;
945: }
1.23 jonathan 946: }
947:
948: GO_WINDOW(1); /* Window 1 is operating window */
949: }
950:
951: /*
952: * Get currently-selected media from card.
953: * (if_media callback, may be called before interface is brought up).
954: */
955: void
956: ep_media_status(ifp, req)
957: struct ifnet *ifp;
958: struct ifmediareq *req;
959: {
960: register struct ep_softc *sc = ifp->if_softc;
961: bus_space_tag_t iot = sc->sc_iot;
962: bus_space_handle_t ioh = sc->sc_ioh;
963:
1.34 thorpej 964: if (sc->enabled == 0) {
965: req->ifm_active = IFM_ETHER|IFM_NONE;
966: req->ifm_status = 0;
967: return;
968: }
969:
1.41 thorpej 970: /*
971: * If we have MII, go ask the PHY what's going on.
972: */
973: if (sc->ep_flags & EP_FLAGS_MII) {
974: mii_pollstat(&sc->sc_mii);
975: req->ifm_active = sc->sc_mii.mii_media_active;
976: req->ifm_status = sc->sc_mii.mii_media_status;
977: return;
978: }
979:
980: /*
981: * Ok, at this point we claim that our active media is
982: * the currently selected media. We'll update our status
983: * if our chipset allows us to detect link.
984: */
985: req->ifm_active = sc->sc_mii.mii_media.ifm_cur->ifm_media;
986: req->ifm_status = 0;
987:
1.23 jonathan 988: switch (sc->ep_chipset) {
989: case EP_CHIPSET_VORTEX:
990: case EP_CHIPSET_BOOMERANG:
991: GO_WINDOW(4);
1.41 thorpej 992: req->ifm_status = IFM_AVALID;
993: if (bus_space_read_2(iot, ioh, EP_W4_MEDIA_TYPE) &
994: LINKBEAT_DETECT)
995: req->ifm_status |= IFM_ACTIVE;
996: GO_WINDOW(1); /* back to operating window */
1.23 jonathan 997: break;
1.1 thorpej 998: }
999: }
1000:
1.23 jonathan 1001:
1002:
1.1 thorpej 1003: /*
1004: * Start outputting on the interface.
1005: * Always called as splnet().
1006: */
1007: void
1008: epstart(ifp)
1009: struct ifnet *ifp;
1010: {
1.5 thorpej 1011: register struct ep_softc *sc = ifp->if_softc;
1.11 thorpej 1012: bus_space_tag_t iot = sc->sc_iot;
1013: bus_space_handle_t ioh = sc->sc_ioh;
1.1 thorpej 1014: struct mbuf *m, *m0;
1015: int sh, len, pad;
1.42 thorpej 1016: bus_addr_t txreg;
1.1 thorpej 1017:
1018: /* Don't transmit if interface is busy or not running */
1.28 veego 1019: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
1.1 thorpej 1020: return;
1021:
1022: startagain:
1023: /* Sneak a peek at the next packet */
1024: m0 = ifp->if_snd.ifq_head;
1025: if (m0 == 0)
1026: return;
1027:
1028: /* We need to use m->m_pkthdr.len, so require the header */
1029: if ((m0->m_flags & M_PKTHDR) == 0)
1030: panic("epstart: no header mbuf");
1031: len = m0->m_pkthdr.len;
1032:
1033: pad = (4 - len) & 3;
1034:
1035: /*
1036: * The 3c509 automatically pads short packets to minimum ethernet
1037: * length, but we drop packets that are too large. Perhaps we should
1038: * truncate them instead?
1039: */
1040: if (len + pad > ETHER_MAX_LEN) {
1041: /* packet is obviously too large: toss it */
1042: ++ifp->if_oerrors;
1043: IF_DEQUEUE(&ifp->if_snd, m0);
1044: m_freem(m0);
1045: goto readcheck;
1046: }
1047:
1.42 thorpej 1048: if (bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_FREE_TX)) <
1049: len + pad + 4) {
1.11 thorpej 1050: bus_space_write_2(iot, ioh, EP_COMMAND,
1.12 jonathan 1051: SET_TX_AVAIL_THRESH |
1052: ((len + pad + 4) >> sc->ep_pktlenshift));
1.1 thorpej 1053: /* not enough room in FIFO */
1054: ifp->if_flags |= IFF_OACTIVE;
1055: return;
1056: } else {
1.11 thorpej 1057: bus_space_write_2(iot, ioh, EP_COMMAND,
1.12 jonathan 1058: SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE );
1.1 thorpej 1059: }
1060:
1061: IF_DEQUEUE(&ifp->if_snd, m0);
1062: if (m0 == 0) /* not really needed */
1063: return;
1064:
1.11 thorpej 1065: bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH |
1.12 jonathan 1066: ((len / 4 + sc->tx_start_thresh) /* >> sc->ep_pktlenshift*/) );
1.1 thorpej 1067:
1068: #if NBPFILTER > 0
1069: if (ifp->if_bpf)
1070: bpf_mtap(ifp->if_bpf, m0);
1071: #endif
1072:
1073: /*
1074: * Do the output at splhigh() so that an interrupt from another device
1075: * won't cause a FIFO underrun.
1076: */
1077: sh = splhigh();
1078:
1.42 thorpej 1079: txreg = ep_w1_reg(sc, EP_W1_TX_PIO_WR_1);
1080:
1.44 thorpej 1081: if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER) {
1082: /*
1083: * Prime the FIFO buffer counter (number of 16-bit
1084: * words about to be written to the FIFO).
1085: *
1086: * NOTE: NO OTHER ACCESS CAN BE PERFORMED WHILE THIS
1087: * COUNTER IS NON-ZERO!
1088: */
1089: bus_space_write_2(iot, ioh, EP_W1_RUNNER_WRCTL,
1090: (len + pad) >> 1);
1091: }
1092:
1.42 thorpej 1093: bus_space_write_2(iot, ioh, txreg, len);
1094: bus_space_write_2(iot, ioh, txreg, 0xffff); /* Second is meaningless */
1.1 thorpej 1095: if (EP_IS_BUS_32(sc->bustype)) {
1096: for (m = m0; m; ) {
1.14 cjs 1097: if (m->m_len > 3) {
1098: /* align our reads from core */
1099: if (mtod(m, u_long) & 3) {
1100: u_long count =
1101: 4 - (mtod(m, u_long) & 3);
1102: bus_space_write_multi_1(iot, ioh,
1.42 thorpej 1103: txreg, mtod(m, u_int8_t *), count);
1.14 cjs 1104: m->m_data =
1105: (void *)(mtod(m, u_long) + count);
1106: m->m_len -= count;
1107: }
1.11 thorpej 1108: bus_space_write_multi_4(iot, ioh,
1.42 thorpej 1109: txreg, mtod(m, u_int32_t *), m->m_len >> 2);
1.14 cjs 1110: m->m_data = (void *)(mtod(m, u_long) +
1111: (u_long)(m->m_len & ~3));
1112: m->m_len -= m->m_len & ~3;
1113: }
1114: if (m->m_len) {
1.11 thorpej 1115: bus_space_write_multi_1(iot, ioh,
1.42 thorpej 1116: txreg, mtod(m, u_int8_t *), m->m_len);
1.14 cjs 1117: }
1.1 thorpej 1118: MFREE(m, m0);
1119: m = m0;
1120: }
1121: } else {
1122: for (m = m0; m; ) {
1.14 cjs 1123: if (m->m_len > 1) {
1124: if (mtod(m, u_long) & 1) {
1125: bus_space_write_1(iot, ioh,
1.42 thorpej 1126: txreg, *(mtod(m, u_int8_t *)));
1.14 cjs 1127: m->m_data =
1128: (void *)(mtod(m, u_long) + 1);
1129: m->m_len -= 1;
1130: }
1.11 thorpej 1131: bus_space_write_multi_2(iot, ioh,
1.42 thorpej 1132: txreg, mtod(m, u_int16_t *),
1.14 cjs 1133: m->m_len >> 1);
1134: }
1135: if (m->m_len & 1) {
1.42 thorpej 1136: bus_space_write_1(iot, ioh, txreg,
1.2 thorpej 1137: *(mtod(m, u_int8_t *) + m->m_len - 1));
1.14 cjs 1138: }
1.1 thorpej 1139: MFREE(m, m0);
1140: m = m0;
1141: }
1142: }
1143: while (pad--)
1.42 thorpej 1144: bus_space_write_1(iot, ioh, txreg, 0);
1.1 thorpej 1145:
1146: splx(sh);
1147:
1148: ++ifp->if_opackets;
1149:
1150: readcheck:
1.42 thorpej 1151: if ((bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_RX_STATUS)) &
1152: ERR_INCOMPLETE) == 0) {
1.1 thorpej 1153: /* We received a complete packet. */
1.11 thorpej 1154: u_int16_t status = bus_space_read_2(iot, ioh, EP_STATUS);
1.1 thorpej 1155:
1156: if ((status & S_INTR_LATCH) == 0) {
1157: /*
1158: * No interrupt, read the packet and continue
1159: * Is this supposed to happen? Is my motherboard
1160: * completely busted?
1161: */
1162: epread(sc);
1.28 veego 1163: } else {
1.1 thorpej 1164: /* Got an interrupt, return so that it gets serviced. */
1165: return;
1.28 veego 1166: }
1167: } else {
1.1 thorpej 1168: /* Check if we are stuck and reset [see XXX comment] */
1169: if (epstatus(sc)) {
1170: if (ifp->if_flags & IFF_DEBUG)
1.10 christos 1171: printf("%s: adapter reset\n",
1.9 christos 1172: sc->sc_dev.dv_xname);
1.1 thorpej 1173: epreset(sc);
1174: }
1175: }
1176:
1177: goto startagain;
1178: }
1179:
1180:
1181: /*
1182: * XXX: The 3c509 card can get in a mode where both the fifo status bit
1183: * FIFOS_RX_OVERRUN and the status bit ERR_INCOMPLETE are set
1184: * We detect this situation and we reset the adapter.
1185: * It happens at times when there is a lot of broadcast traffic
1186: * on the cable (once in a blue moon).
1187: */
1188: static int
1189: epstatus(sc)
1190: register struct ep_softc *sc;
1191: {
1.11 thorpej 1192: bus_space_tag_t iot = sc->sc_iot;
1193: bus_space_handle_t ioh = sc->sc_ioh;
1.7 thorpej 1194: u_int16_t fifost;
1.1 thorpej 1195:
1196: /*
1197: * Check the FIFO status and act accordingly
1198: */
1199: GO_WINDOW(4);
1.11 thorpej 1200: fifost = bus_space_read_2(iot, ioh, EP_W4_FIFO_DIAG);
1.1 thorpej 1201: GO_WINDOW(1);
1202:
1203: if (fifost & FIFOS_RX_UNDERRUN) {
1.21 is 1204: if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10 christos 1205: printf("%s: RX underrun\n", sc->sc_dev.dv_xname);
1.1 thorpej 1206: epreset(sc);
1207: return 0;
1208: }
1209:
1210: if (fifost & FIFOS_RX_STATUS_OVERRUN) {
1.21 is 1211: if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10 christos 1212: printf("%s: RX Status overrun\n", sc->sc_dev.dv_xname);
1.1 thorpej 1213: return 1;
1214: }
1215:
1216: if (fifost & FIFOS_RX_OVERRUN) {
1.21 is 1217: if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10 christos 1218: printf("%s: RX overrun\n", sc->sc_dev.dv_xname);
1.1 thorpej 1219: return 1;
1220: }
1221:
1222: if (fifost & FIFOS_TX_OVERRUN) {
1.21 is 1223: if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10 christos 1224: printf("%s: TX overrun\n", sc->sc_dev.dv_xname);
1.1 thorpej 1225: epreset(sc);
1226: return 0;
1227: }
1228:
1229: return 0;
1230: }
1231:
1232:
1233: static void
1234: eptxstat(sc)
1235: register struct ep_softc *sc;
1236: {
1.11 thorpej 1237: bus_space_tag_t iot = sc->sc_iot;
1238: bus_space_handle_t ioh = sc->sc_ioh;
1.1 thorpej 1239: int i;
1240:
1241: /*
1242: * We need to read+write TX_STATUS until we get a 0 status
1243: * in order to turn off the interrupt flag.
1244: */
1.42 thorpej 1245: while ((i = bus_space_read_1(iot, ioh, ep_w1_reg(sc, EP_W1_TX_STATUS)))
1246: & TXS_COMPLETE) {
1247: bus_space_write_1(iot, ioh, ep_w1_reg(sc, EP_W1_TX_STATUS),
1248: 0x0);
1.1 thorpej 1249:
1250: if (i & TXS_JABBER) {
1.21 is 1251: ++sc->sc_ethercom.ec_if.if_oerrors;
1252: if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10 christos 1253: printf("%s: jabber (%x)\n",
1.1 thorpej 1254: sc->sc_dev.dv_xname, i);
1255: epreset(sc);
1256: } else if (i & TXS_UNDERRUN) {
1.21 is 1257: ++sc->sc_ethercom.ec_if.if_oerrors;
1258: if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10 christos 1259: printf("%s: fifo underrun (%x) @%d\n",
1.1 thorpej 1260: sc->sc_dev.dv_xname, i,
1261: sc->tx_start_thresh);
1262: if (sc->tx_succ_ok < 100)
1263: sc->tx_start_thresh = min(ETHER_MAX_LEN,
1264: sc->tx_start_thresh + 20);
1265: sc->tx_succ_ok = 0;
1266: epreset(sc);
1267: } else if (i & TXS_MAX_COLLISION) {
1.21 is 1268: ++sc->sc_ethercom.ec_if.if_collisions;
1.11 thorpej 1269: bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
1.21 is 1270: sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE;
1.1 thorpej 1271: } else
1272: sc->tx_succ_ok = (sc->tx_succ_ok+1) & 127;
1273: }
1274: }
1275:
1276: int
1277: epintr(arg)
1278: void *arg;
1279: {
1280: register struct ep_softc *sc = arg;
1.11 thorpej 1281: bus_space_tag_t iot = sc->sc_iot;
1282: bus_space_handle_t ioh = sc->sc_ioh;
1.21 is 1283: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.7 thorpej 1284: u_int16_t status;
1.1 thorpej 1285: int ret = 0;
1.35 explorer 1286: int addrandom = 0;
1.1 thorpej 1287:
1.34 thorpej 1288: if (sc->enabled == 0)
1289: return (0);
1290:
1.1 thorpej 1291: for (;;) {
1.11 thorpej 1292: bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
1.1 thorpej 1293:
1.11 thorpej 1294: status = bus_space_read_2(iot, ioh, EP_STATUS);
1.1 thorpej 1295:
1296: if ((status & (S_TX_COMPLETE | S_TX_AVAIL |
1.34 thorpej 1297: S_RX_COMPLETE | S_CARD_FAILURE)) == 0) {
1298: if ((status & S_INTR_LATCH) == 0) {
1299: #if 0
1300: printf("%s: intr latch cleared\n",
1301: sc->sc_dev.dv_xname);
1302: #endif
1303: break;
1304: }
1305: }
1.1 thorpej 1306:
1307: ret = 1;
1308:
1309: /*
1310: * Acknowledge any interrupts. It's important that we do this
1311: * first, since there would otherwise be a race condition.
1312: * Due to the i386 interrupt queueing, we may get spurious
1313: * interrupts occasionally.
1314: */
1.34 thorpej 1315: bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR |
1316: (status & (C_INTR_LATCH |
1317: C_CARD_FAILURE |
1318: C_TX_COMPLETE |
1319: C_TX_AVAIL |
1320: C_RX_COMPLETE |
1321: C_RX_EARLY |
1322: C_INT_RQD |
1323: C_UPD_STATS)));
1324:
1325: #if 0
1326: status = bus_space_read_2(iot, ioh, EP_STATUS);
1327:
1328: printf("%s: intr%s%s%s%s\n", sc->sc_dev.dv_xname,
1329: (status & S_RX_COMPLETE)?" RX_COMPLETE":"",
1330: (status & S_TX_COMPLETE)?" TX_COMPLETE":"",
1331: (status & S_TX_AVAIL)?" TX_AVAIL":"",
1332: (status & S_CARD_FAILURE)?" CARD_FAILURE":"");
1333: #endif
1.1 thorpej 1334:
1.35 explorer 1335: if (status & S_RX_COMPLETE) {
1.1 thorpej 1336: epread(sc);
1.35 explorer 1337: addrandom = 1;
1338: }
1.1 thorpej 1339: if (status & S_TX_AVAIL) {
1.21 is 1340: sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE;
1341: epstart(&sc->sc_ethercom.ec_if);
1.35 explorer 1342: addrandom = 1;
1.1 thorpej 1343: }
1344: if (status & S_CARD_FAILURE) {
1.10 christos 1345: printf("%s: adapter failure (%x)\n",
1.9 christos 1346: sc->sc_dev.dv_xname, status);
1.1 thorpej 1347: epreset(sc);
1348: return (1);
1349: }
1350: if (status & S_TX_COMPLETE) {
1351: eptxstat(sc);
1352: epstart(ifp);
1.35 explorer 1353: addrandom = 1;
1.1 thorpej 1354: }
1.35 explorer 1355:
1356: #if NRND > 0
1357: if (status)
1358: rnd_add_uint32(&sc->rnd_source, status);
1359: #endif
1.1 thorpej 1360: }
1361:
1362: /* no more interrupts */
1363: return (ret);
1364: }
1365:
1366: void
1367: epread(sc)
1368: register struct ep_softc *sc;
1369: {
1.11 thorpej 1370: bus_space_tag_t iot = sc->sc_iot;
1371: bus_space_handle_t ioh = sc->sc_ioh;
1.21 is 1372: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.1 thorpej 1373: struct mbuf *m;
1374: struct ether_header *eh;
1375: int len;
1376:
1.42 thorpej 1377: len = bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_RX_STATUS));
1.1 thorpej 1378:
1379: again:
1380: if (ifp->if_flags & IFF_DEBUG) {
1381: int err = len & ERR_MASK;
1382: char *s = NULL;
1383:
1384: if (len & ERR_INCOMPLETE)
1385: s = "incomplete packet";
1386: else if (err == ERR_OVERRUN)
1387: s = "packet overrun";
1388: else if (err == ERR_RUNT)
1389: s = "runt packet";
1390: else if (err == ERR_ALIGNMENT)
1391: s = "bad alignment";
1392: else if (err == ERR_CRC)
1393: s = "bad crc";
1394: else if (err == ERR_OVERSIZE)
1395: s = "oversized packet";
1396: else if (err == ERR_DRIBBLE)
1397: s = "dribble bits";
1398:
1399: if (s)
1.10 christos 1400: printf("%s: %s\n", sc->sc_dev.dv_xname, s);
1.1 thorpej 1401: }
1402:
1403: if (len & ERR_INCOMPLETE)
1404: return;
1405:
1406: if (len & ERR_RX) {
1407: ++ifp->if_ierrors;
1408: goto abort;
1409: }
1410:
1411: len &= RX_BYTES_MASK; /* Lower 11 bits = RX bytes. */
1412:
1413: /* Pull packet off interface. */
1414: m = epget(sc, len);
1415: if (m == 0) {
1416: ifp->if_ierrors++;
1417: goto abort;
1418: }
1419:
1420: ++ifp->if_ipackets;
1421:
1422: /* We assume the header fit entirely in one mbuf. */
1423: eh = mtod(m, struct ether_header *);
1424:
1425: #if NBPFILTER > 0
1426: /*
1427: * Check if there's a BPF listener on this interface.
1428: * If so, hand off the raw packet to BPF.
1429: */
1430: if (ifp->if_bpf) {
1431: bpf_mtap(ifp->if_bpf, m);
1432:
1433: /*
1434: * Note that the interface cannot be in promiscuous mode if
1435: * there are no BPF listeners. And if we are in promiscuous
1436: * mode, we have to check if this packet is really ours.
1437: */
1438: if ((ifp->if_flags & IFF_PROMISC) &&
1439: (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
1.21 is 1440: bcmp(eh->ether_dhost, LLADDR(sc->sc_ethercom.ec_if.if_sadl),
1.1 thorpej 1441: sizeof(eh->ether_dhost)) != 0) {
1442: m_freem(m);
1443: return;
1444: }
1445: }
1446: #endif
1447:
1448: /* We assume the header fit entirely in one mbuf. */
1449: m_adj(m, sizeof(struct ether_header));
1.43 thorpej 1450: ether_input(ifp, eh, m);
1.1 thorpej 1451:
1452: /*
1453: * In periods of high traffic we can actually receive enough
1454: * packets so that the fifo overrun bit will be set at this point,
1455: * even though we just read a packet. In this case we
1456: * are not going to receive any more interrupts. We check for
1457: * this condition and read again until the fifo is not full.
1458: * We could simplify this test by not using epstatus(), but
1459: * rechecking the RX_STATUS register directly. This test could
1460: * result in unnecessary looping in cases where there is a new
1461: * packet but the fifo is not full, but it will not fix the
1462: * stuck behavior.
1463: *
1464: * Even with this improvement, we still get packet overrun errors
1465: * which are hurting performance. Maybe when I get some more time
1466: * I'll modify epread() so that it can handle RX_EARLY interrupts.
1467: */
1468: if (epstatus(sc)) {
1.42 thorpej 1469: len = bus_space_read_2(iot, ioh,
1470: ep_w1_reg(sc, EP_W1_RX_STATUS));
1.1 thorpej 1471: /* Check if we are stuck and reset [see XXX comment] */
1472: if (len & ERR_INCOMPLETE) {
1473: if (ifp->if_flags & IFF_DEBUG)
1.10 christos 1474: printf("%s: adapter reset\n",
1.9 christos 1475: sc->sc_dev.dv_xname);
1.1 thorpej 1476: epreset(sc);
1477: return;
1478: }
1479: goto again;
1480: }
1481:
1482: return;
1483:
1484: abort:
1.11 thorpej 1485: bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
1486: while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
1.1 thorpej 1487: ;
1488: }
1489:
1490: struct mbuf *
1491: epget(sc, totlen)
1492: struct ep_softc *sc;
1493: int totlen;
1494: {
1.11 thorpej 1495: bus_space_tag_t iot = sc->sc_iot;
1496: bus_space_handle_t ioh = sc->sc_ioh;
1.21 is 1497: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.44 thorpej 1498: struct mbuf *top, **mp, *m, *rv = NULL;
1.42 thorpej 1499: bus_addr_t rxreg;
1.14 cjs 1500: int len, remaining;
1.1 thorpej 1501: int sh;
1502:
1503: m = sc->mb[sc->next_mb];
1504: sc->mb[sc->next_mb] = 0;
1505: if (m == 0) {
1506: MGETHDR(m, M_DONTWAIT, MT_DATA);
1507: if (m == 0)
1508: return 0;
1509: } else {
1510: /* If the queue is no longer full, refill. */
1511: if (sc->last_mb == sc->next_mb)
1512: timeout(epmbuffill, sc, 1);
1513: /* Convert one of our saved mbuf's. */
1514: sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
1515: m->m_data = m->m_pktdat;
1516: m->m_flags = M_PKTHDR;
1517: }
1518: m->m_pkthdr.rcvif = ifp;
1519: m->m_pkthdr.len = totlen;
1520: len = MHLEN;
1521: top = 0;
1522: mp = ⊤
1523:
1524: /*
1525: * We read the packet at splhigh() so that an interrupt from another
1526: * device doesn't cause the card's buffer to overflow while we're
1527: * reading it. We may still lose packets at other times.
1528: */
1529: sh = splhigh();
1530:
1.42 thorpej 1531: rxreg = ep_w1_reg(sc, EP_W1_RX_PIO_RD_1);
1532:
1.44 thorpej 1533: if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER) {
1534: /*
1535: * Prime the FIFO buffer counter (number of 16-bit
1536: * words about to be read from the FIFO).
1537: *
1538: * NOTE: NO OTHER ACCESS CAN BE PERFORMED WHILE THIS
1539: * COUNTER IS NON-ZERO!
1540: */
1541: bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, totlen >> 1);
1542: }
1543:
1.1 thorpej 1544: while (totlen > 0) {
1545: if (top) {
1546: m = sc->mb[sc->next_mb];
1547: sc->mb[sc->next_mb] = 0;
1548: if (m == 0) {
1549: MGET(m, M_DONTWAIT, MT_DATA);
1550: if (m == 0) {
1551: m_freem(top);
1.44 thorpej 1552: goto out;
1.1 thorpej 1553: }
1554: } else {
1555: sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
1556: }
1557: len = MLEN;
1558: }
1559: if (totlen >= MINCLSIZE) {
1560: MCLGET(m, M_DONTWAIT);
1.27 mycroft 1561: if ((m->m_flags & M_EXT) == 0) {
1.30 mycroft 1562: m_free(m);
1.26 mycroft 1563: m_freem(top);
1.44 thorpej 1564: goto out;
1.26 mycroft 1565: }
1566: len = MCLBYTES;
1.1 thorpej 1567: }
1.24 cjs 1568: if (top == 0) {
1.25 cjs 1569: /* align the struct ip header */
1570: caddr_t newdata = (caddr_t)
1571: ALIGN(m->m_data + sizeof(struct ether_header))
1572: - sizeof(struct ether_header);
1573: len -= newdata - m->m_data;
1574: m->m_data = newdata;
1.14 cjs 1575: }
1576: remaining = len = min(totlen, len);
1.1 thorpej 1577: if (EP_IS_BUS_32(sc->bustype)) {
1.14 cjs 1578: u_long offset = mtod(m, u_long);
1579: /*
1580: * Read bytes up to the point where we are aligned.
1581: * (We can align to 4 bytes, rather than ALIGNBYTES,
1582: * here because we're later reading 4-byte chunks.)
1583: */
1584: if ((remaining > 3) && (offset & 3)) {
1585: int count = (4 - (offset & 3));
1586: bus_space_read_multi_1(iot, ioh,
1.42 thorpej 1587: rxreg, (u_int8_t *) offset, count);
1.14 cjs 1588: offset += count;
1589: remaining -= count;
1590: }
1591: if (remaining > 3) {
1.11 thorpej 1592: bus_space_read_multi_4(iot, ioh,
1.42 thorpej 1593: rxreg, (u_int32_t *) offset,
1594: remaining >> 2);
1.14 cjs 1595: offset += remaining & ~3;
1596: remaining &= 3;
1597: }
1598: if (remaining) {
1.11 thorpej 1599: bus_space_read_multi_1(iot, ioh,
1.42 thorpej 1600: rxreg, (u_int8_t *) offset, remaining);
1.14 cjs 1601: }
1.1 thorpej 1602: } else {
1.14 cjs 1603: u_long offset = mtod(m, u_long);
1604: if ((remaining > 1) && (offset & 1)) {
1605: bus_space_read_multi_1(iot, ioh,
1.42 thorpej 1606: rxreg, (u_int8_t *) offset, 1);
1.14 cjs 1607: remaining -= 1;
1608: offset += 1;
1609: }
1610: if (remaining > 1) {
1.11 thorpej 1611: bus_space_read_multi_2(iot, ioh,
1.42 thorpej 1612: rxreg, (u_int16_t *) offset,
1613: remaining >> 1);
1.14 cjs 1614: offset += remaining & ~1;
1615: }
1616: if (remaining & 1) {
1617: bus_space_read_multi_1(iot, ioh,
1.42 thorpej 1618: rxreg, (u_int8_t *) offset, remaining & 1);
1.14 cjs 1619: }
1.1 thorpej 1620: }
1621: m->m_len = len;
1622: totlen -= len;
1623: *mp = m;
1624: mp = &m->m_next;
1625: }
1626:
1.44 thorpej 1627: rv = top;
1628:
1.11 thorpej 1629: bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
1630: while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
1.1 thorpej 1631: ;
1632:
1.44 thorpej 1633: out:
1634: if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER)
1635: bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, 0);
1.1 thorpej 1636: splx(sh);
1637:
1.44 thorpej 1638: return rv;
1.1 thorpej 1639: }
1640:
1641: int
1642: epioctl(ifp, cmd, data)
1643: register struct ifnet *ifp;
1644: u_long cmd;
1645: caddr_t data;
1646: {
1.5 thorpej 1647: struct ep_softc *sc = ifp->if_softc;
1.1 thorpej 1648: struct ifaddr *ifa = (struct ifaddr *)data;
1649: struct ifreq *ifr = (struct ifreq *)data;
1650: int s, error = 0;
1651:
1652: s = splnet();
1653:
1654: switch (cmd) {
1655:
1656: case SIOCSIFADDR:
1.34 thorpej 1657: if ((error = epenable(sc)) != 0)
1658: break;
1659: /* epinit is called just below */
1.1 thorpej 1660: ifp->if_flags |= IFF_UP;
1661: switch (ifa->ifa_addr->sa_family) {
1662: #ifdef INET
1663: case AF_INET:
1664: epinit(sc);
1.21 is 1665: arp_ifinit(&sc->sc_ethercom.ec_if, ifa);
1.1 thorpej 1666: break;
1667: #endif
1668: #ifdef NS
1669: case AF_NS:
1670: {
1671: register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1672:
1673: if (ns_nullhost(*ina))
1.21 is 1674: ina->x_host = *(union ns_host *)
1675: LLADDR(ifp->if_sadl);
1.1 thorpej 1676: else
1677: bcopy(ina->x_host.c_host,
1.21 is 1678: LLADDR(ifp->if_sadl),
1679: ifp->if_addrlen);
1.1 thorpej 1680: /* Set new address. */
1681: epinit(sc);
1682: break;
1683: }
1684: #endif
1685: default:
1686: epinit(sc);
1687: break;
1688: }
1689: break;
1690:
1.23 jonathan 1691: case SIOCSIFMEDIA:
1692: case SIOCGIFMEDIA:
1.41 thorpej 1693: error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
1.23 jonathan 1694: break;
1695:
1.1 thorpej 1696: case SIOCSIFFLAGS:
1697: if ((ifp->if_flags & IFF_UP) == 0 &&
1698: (ifp->if_flags & IFF_RUNNING) != 0) {
1699: /*
1700: * If interface is marked down and it is running, then
1701: * stop it.
1702: */
1703: epstop(sc);
1704: ifp->if_flags &= ~IFF_RUNNING;
1.34 thorpej 1705: epdisable(sc);
1.1 thorpej 1706: } else if ((ifp->if_flags & IFF_UP) != 0 &&
1707: (ifp->if_flags & IFF_RUNNING) == 0) {
1708: /*
1709: * If interface is marked up and it is stopped, then
1710: * start it.
1711: */
1.34 thorpej 1712: if ((error = epenable(sc)) != 0)
1713: break;
1.1 thorpej 1714: epinit(sc);
1.34 thorpej 1715: } else if (sc->enabled) {
1.1 thorpej 1716: /*
1717: * deal with flags changes:
1.23 jonathan 1718: * IFF_MULTICAST, IFF_PROMISC.
1.1 thorpej 1719: */
1720: epsetfilter(sc);
1721: }
1722: break;
1723:
1724: case SIOCADDMULTI:
1725: case SIOCDELMULTI:
1.34 thorpej 1726: if (sc->enabled == 0) {
1727: error = EIO;
1728: break;
1729: }
1730:
1.1 thorpej 1731: error = (cmd == SIOCADDMULTI) ?
1.21 is 1732: ether_addmulti(ifr, &sc->sc_ethercom) :
1733: ether_delmulti(ifr, &sc->sc_ethercom);
1.1 thorpej 1734:
1735: if (error == ENETRESET) {
1736: /*
1737: * Multicast list has changed; set the hardware filter
1738: * accordingly.
1739: */
1740: epreset(sc);
1741: error = 0;
1742: }
1743: break;
1744:
1745: default:
1746: error = EINVAL;
1747: break;
1748: }
1749:
1750: splx(s);
1751: return (error);
1752: }
1753:
1754: void
1755: epreset(sc)
1756: struct ep_softc *sc;
1757: {
1758: int s;
1759:
1760: s = splnet();
1761: epstop(sc);
1762: epinit(sc);
1763: splx(s);
1764: }
1765:
1766: void
1.5 thorpej 1767: epwatchdog(ifp)
1768: struct ifnet *ifp;
1.1 thorpej 1769: {
1.5 thorpej 1770: struct ep_softc *sc = ifp->if_softc;
1.1 thorpej 1771:
1772: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1.21 is 1773: ++sc->sc_ethercom.ec_if.if_oerrors;
1.1 thorpej 1774:
1775: epreset(sc);
1776: }
1777:
1778: void
1779: epstop(sc)
1780: register struct ep_softc *sc;
1781: {
1.11 thorpej 1782: bus_space_tag_t iot = sc->sc_iot;
1783: bus_space_handle_t ioh = sc->sc_ioh;
1.1 thorpej 1784:
1.41 thorpej 1785: if (sc->ep_flags & EP_FLAGS_MII) {
1786: /* Stop the one second clock. */
1787: untimeout(ep_tick, sc);
1.44 thorpej 1788: }
1789:
1790: if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) {
1791: /*
1792: * Clear the FIFO buffer count, thus halting
1793: * any currently-running transactions.
1794: */
1795: GO_WINDOW(1); /* sanity */
1796: bus_space_write_2(iot, ioh, EP_W1_RUNNER_WRCTL, 0);
1797: bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, 0);
1.41 thorpej 1798: }
1799:
1.11 thorpej 1800: bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISABLE);
1801: bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
1802: while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
1.1 thorpej 1803: ;
1.11 thorpej 1804: bus_space_write_2(iot, ioh, EP_COMMAND, TX_DISABLE);
1805: bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
1.18 jonathan 1806:
1.19 jonathan 1807: ep_complete_cmd(sc, EP_COMMAND, RX_RESET);
1808: ep_complete_cmd(sc, EP_COMMAND, TX_RESET);
1.18 jonathan 1809:
1.11 thorpej 1810: bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
1811: bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK);
1812: bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK);
1813: bus_space_write_2(iot, ioh, EP_COMMAND, SET_RX_FILTER);
1.1 thorpej 1814:
1815: epmbufempty(sc);
1816: }
1.16 jonathan 1817:
1818:
1819: /*
1820: * Before reboots, reset card completely.
1821: */
1822: static void
1823: epshutdown(arg)
1824: void *arg;
1825: {
1826: register struct ep_softc *sc = arg;
1827:
1.34 thorpej 1828: if (sc->enabled) {
1829: epstop(sc);
1830: ep_complete_cmd(sc, EP_COMMAND, GLOBAL_RESET);
1831: }
1.16 jonathan 1832: }
1.1 thorpej 1833:
1834: /*
1835: * We get eeprom data from the id_port given an offset into the
1836: * eeprom. Basically; after the ID_sequence is sent to all of
1837: * the cards; they enter the ID_CMD state where they will accept
1838: * command requests. 0x80-0xbf loads the eeprom data. We then
1839: * read the port 16 times and with every read; the cards check
1840: * for contention (ie: if one card writes a 0 bit and another
1841: * writes a 1 bit then the host sees a 0. At the end of the cycle;
1842: * each card compares the data on the bus; if there is a difference
1843: * then that card goes into ID_WAIT state again). In the meantime;
1844: * one bit of data is returned in the AX register which is conveniently
1.11 thorpej 1845: * returned to us by bus_space_read_1(). Hence; we read 16 times getting one
1.1 thorpej 1846: * bit of data with each read.
1.2 thorpej 1847: *
1848: * NOTE: the caller must provide an i/o handle for ELINK_ID_PORT!
1.1 thorpej 1849: */
1.2 thorpej 1850: u_int16_t
1.11 thorpej 1851: epreadeeprom(iot, ioh, offset)
1852: bus_space_tag_t iot;
1853: bus_space_handle_t ioh;
1.2 thorpej 1854: int offset;
1.1 thorpej 1855: {
1.2 thorpej 1856: u_int16_t data = 0;
1857: int i;
1.1 thorpej 1858:
1.11 thorpej 1859: bus_space_write_1(iot, ioh, 0, 0x80 + offset);
1.1 thorpej 1860: delay(1000);
1861: for (i = 0; i < 16; i++)
1.11 thorpej 1862: data = (data << 1) | (bus_space_read_2(iot, ioh, 0) & 1);
1.1 thorpej 1863: return (data);
1864: }
1865:
1866: static int
1867: epbusyeeprom(sc)
1868: struct ep_softc *sc;
1869: {
1.11 thorpej 1870: bus_space_tag_t iot = sc->sc_iot;
1871: bus_space_handle_t ioh = sc->sc_ioh;
1.1 thorpej 1872: int i = 100, j;
1873:
1874: if (sc->bustype == EP_BUS_PCMCIA) {
1875: delay(1000);
1876: return 0;
1877: }
1878:
1.33 jonathan 1879: j = 0; /* bad GCC flow analysis */
1.1 thorpej 1880: while (i--) {
1.11 thorpej 1881: j = bus_space_read_2(iot, ioh, EP_W0_EEPROM_COMMAND);
1.1 thorpej 1882: if (j & EEPROM_BUSY)
1883: delay(100);
1884: else
1885: break;
1886: }
1887: if (!i) {
1.10 christos 1888: printf("\n%s: eeprom failed to come ready\n",
1.1 thorpej 1889: sc->sc_dev.dv_xname);
1890: return (1);
1891: }
1892: if (j & EEPROM_TST_MODE) {
1.29 jonathan 1893: /* XXX PnP mode? */
1.28 veego 1894: printf("\n%s: erase pencil mark!\n", sc->sc_dev.dv_xname);
1.1 thorpej 1895: return (1);
1896: }
1897: return (0);
1898: }
1899:
1900: void
1.3 christos 1901: epmbuffill(v)
1902: void *v;
1.1 thorpej 1903: {
1.3 christos 1904: struct ep_softc *sc = v;
1.1 thorpej 1905: int s, i;
1906:
1907: s = splnet();
1908: i = sc->last_mb;
1909: do {
1910: if (sc->mb[i] == NULL)
1911: MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
1912: if (sc->mb[i] == NULL)
1913: break;
1914: i = (i + 1) % MAX_MBS;
1915: } while (i != sc->next_mb);
1916: sc->last_mb = i;
1917: /* If the queue was not filled, try again. */
1918: if (sc->last_mb != sc->next_mb)
1919: timeout(epmbuffill, sc, 1);
1920: splx(s);
1921: }
1922:
1923: void
1924: epmbufempty(sc)
1925: struct ep_softc *sc;
1926: {
1927: int s, i;
1928:
1929: s = splnet();
1930: for (i = 0; i<MAX_MBS; i++) {
1931: if (sc->mb[i]) {
1932: m_freem(sc->mb[i]);
1933: sc->mb[i] = NULL;
1934: }
1935: }
1936: sc->last_mb = sc->next_mb = 0;
1937: untimeout(epmbuffill, sc);
1938: splx(s);
1.34 thorpej 1939: }
1940:
1941: int
1942: epenable(sc)
1943: struct ep_softc *sc;
1944: {
1945:
1946: if (sc->enabled == 0 && sc->enable != NULL) {
1947: if ((*sc->enable)(sc) != 0) {
1948: printf("%s: device enable failed\n",
1949: sc->sc_dev.dv_xname);
1950: return (EIO);
1951: }
1952: }
1953:
1954: sc->enabled = 1;
1955: return (0);
1956: }
1957:
1958: void
1959: epdisable(sc)
1960: struct ep_softc *sc;
1961: {
1962:
1963: if (sc->enabled != 0 && sc->disable != NULL) {
1964: (*sc->disable)(sc);
1965: sc->enabled = 0;
1966: }
1.41 thorpej 1967: }
1968:
1969: void
1970: ep_mii_setbit(sc, bit)
1971: struct ep_softc *sc;
1972: u_int16_t bit;
1973: {
1974: u_int16_t val;
1975:
1976: /* We assume we're already in Window 4 */
1977: val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT);
1978: bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT,
1979: val | bit);
1980: }
1981:
1982: void
1983: ep_mii_clrbit(sc, bit)
1984: struct ep_softc *sc;
1985: u_int16_t bit;
1986: {
1987: u_int16_t val;
1988:
1989: /* We assume we're already in Window 4 */
1990: val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT);
1991: bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT,
1992: val & ~bit);
1993: }
1994:
1995: u_int16_t
1996: ep_mii_readbit(sc, bit)
1997: struct ep_softc *sc;
1998: u_int16_t bit;
1999: {
2000:
2001: /* We assume we're already in Window 4 */
2002: return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT) &
2003: bit);
2004: }
2005:
2006: void
2007: ep_mii_sync(sc)
2008: struct ep_softc *sc;
2009: {
2010: int i;
2011:
2012: /* We assume we're already in Window 4 */
2013: ep_mii_clrbit(sc, PHYSMGMT_DIR);
2014: for (i = 0; i < 32; i++) {
2015: ep_mii_clrbit(sc, PHYSMGMT_CLK);
2016: ep_mii_setbit(sc, PHYSMGMT_CLK);
2017: }
2018: }
2019:
2020: void
2021: ep_mii_sendbits(sc, data, nbits)
2022: struct ep_softc *sc;
2023: u_int32_t data;
2024: int nbits;
2025: {
2026: int i;
2027:
2028: /* We assume we're already in Window 4 */
2029: ep_mii_setbit(sc, PHYSMGMT_DIR);
2030: for (i = 1 << (nbits - 1); i; i = i >> 1) {
2031: ep_mii_clrbit(sc, PHYSMGMT_CLK);
2032: ep_mii_readbit(sc, PHYSMGMT_CLK);
2033: if (data & i)
2034: ep_mii_setbit(sc, PHYSMGMT_DATA);
2035: else
2036: ep_mii_clrbit(sc, PHYSMGMT_DATA);
2037: ep_mii_setbit(sc, PHYSMGMT_CLK);
2038: ep_mii_readbit(sc, PHYSMGMT_CLK);
2039: }
2040: }
2041:
2042: int
2043: ep_mii_readreg(self, phy, reg)
2044: struct device *self;
2045: int phy, reg;
2046: {
2047: struct ep_softc *sc = (struct ep_softc *)self;
2048: int val = 0, i, err;
2049:
2050: /*
2051: * Read the PHY register by manually driving the MII control lines.
2052: */
2053:
2054: GO_WINDOW(4);
2055:
2056: bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT, 0);
2057:
2058: ep_mii_sync(sc);
2059: ep_mii_sendbits(sc, MII_COMMAND_START, 2);
2060: ep_mii_sendbits(sc, MII_COMMAND_READ, 2);
2061: ep_mii_sendbits(sc, phy, 5);
2062: ep_mii_sendbits(sc, reg, 5);
2063:
2064: ep_mii_clrbit(sc, PHYSMGMT_DIR);
2065: ep_mii_clrbit(sc, PHYSMGMT_CLK);
2066: ep_mii_setbit(sc, PHYSMGMT_CLK);
2067: ep_mii_clrbit(sc, PHYSMGMT_CLK);
2068:
2069: err = ep_mii_readbit(sc, PHYSMGMT_DATA);
2070: ep_mii_setbit(sc, PHYSMGMT_CLK);
2071:
2072: /* Even if an error occurs, must still clock out the cycle. */
2073: for (i = 0; i < 16; i++) {
2074: val <<= 1;
2075: ep_mii_clrbit(sc, PHYSMGMT_CLK);
2076: if (err == 0 && ep_mii_readbit(sc, PHYSMGMT_DATA))
2077: val |= 1;
2078: ep_mii_setbit(sc, PHYSMGMT_CLK);
2079: }
2080: ep_mii_clrbit(sc, PHYSMGMT_CLK);
2081: ep_mii_setbit(sc, PHYSMGMT_CLK);
2082:
2083: GO_WINDOW(1); /* back to operating window */
2084:
2085: return (err ? 0 : val);
2086: }
2087:
2088: void
2089: ep_mii_writereg(self, phy, reg, val)
2090: struct device *self;
2091: int phy, reg, val;
2092: {
2093: struct ep_softc *sc = (struct ep_softc *)self;
2094:
2095: /*
2096: * Write the PHY register by manually driving the MII control lines.
2097: */
2098:
2099: GO_WINDOW(4);
2100:
2101: ep_mii_sync(sc);
2102: ep_mii_sendbits(sc, MII_COMMAND_START, 2);
2103: ep_mii_sendbits(sc, MII_COMMAND_WRITE, 2);
2104: ep_mii_sendbits(sc, phy, 5);
2105: ep_mii_sendbits(sc, reg, 5);
2106: ep_mii_sendbits(sc, MII_COMMAND_ACK, 2);
2107: ep_mii_sendbits(sc, val, 16);
2108:
2109: ep_mii_clrbit(sc, PHYSMGMT_CLK);
2110: ep_mii_setbit(sc, PHYSMGMT_CLK);
2111:
2112: GO_WINDOW(1); /* back to operating window */
2113: }
2114:
2115: void
2116: ep_statchg(self)
2117: struct device *self;
2118: {
1.45 ! thorpej 2119: struct ep_softc *sc = (struct ep_softc *)self;
! 2120: bus_space_tag_t iot = sc->sc_iot;
! 2121: bus_space_handle_t ioh = sc->sc_ioh;
! 2122: int mctl;
1.41 thorpej 2123:
2124: /* XXX Update ifp->if_baudrate */
1.45 ! thorpej 2125:
! 2126: GO_WINDOW(3);
! 2127: mctl = bus_space_read_2(iot, ioh, EP_W3_MAC_CONTROL);
! 2128: if (sc->sc_mii.mii_media_active & IFM_FDX)
! 2129: mctl |= MAC_CONTROL_FDX;
! 2130: else
! 2131: mctl &= ~MAC_CONTROL_FDX;
! 2132: bus_space_write_2(iot, ioh, EP_W3_MAC_CONTROL, mctl);
! 2133: GO_WINDOW(1); /* back to operating window */
1.1 thorpej 2134: }
CVSweb <webmaster@jp.NetBSD.org>