lan9118.c revision 1.7 1 /* $NetBSD: lan9118.c,v 1.7 2009/11/29 09:34:20 kiyohara Exp $ */
2 /*
3 * Copyright (c) 2008 KIYOHARA Takashi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: lan9118.c,v 1.7 2009/11/29 09:34:20 kiyohara Exp $");
29
30 /*
31 * The LAN9118 Family
32 *
33 * * The LAN9118 is targeted for 32-bit applications requiring high
34 * performance, and provides the highest level of performance possible for
35 * a non-PCI 10/100 Ethernet controller.
36 *
37 * * The LAN9117 is designed to provide the highest level of performance
38 * possible for 16-bit applications. It also has an external MII interface,
39 * which can be used to attach an external PHY.
40 *
41 * * The LAN9116 and LAN9115 are designed for performance-sensitive
42 * applications with less intensive performance requirements. The LAN9116
43 * is for 32-bit host processors, while the LAN9115 is for 16-bit
44 * applications, which may also require an external PHY. Both devices
45 * deliver superior levels of performance.
46 */
47
48 #include "bpfilter.h"
49 #include "rnd.h"
50
51 #include <sys/param.h>
52 #include <sys/callout.h>
53 #include <sys/device.h>
54 #include <sys/errno.h>
55 #include <sys/bus.h>
56 #include <sys/ioctl.h>
57 #include <sys/kernel.h>
58 #include <sys/proc.h>
59 #include <sys/systm.h>
60
61 #include <net/if.h>
62 #include <net/if_ether.h>
63 #include <net/if_media.h>
64
65 #include <dev/mii/mii.h>
66 #include <dev/mii/miivar.h>
67
68 #if NBPFILTER > 0
69 #include <net/bpf.h>
70 #endif
71 #if NRND > 0
72 #include <sys/rnd.h>
73 #endif
74
75 #include <dev/ic/lan9118reg.h>
76 #include <dev/ic/lan9118var.h>
77
78
79 #ifdef SMSH_DEBUG
80 #define DPRINTF(x) if (smsh_debug) printf x
81 #define DPRINTFN(n,x) if (smsh_debug >= (n)) printf x
82 int smsh_debug = SMSH_DEBUG;
83 #else
84 #define DPRINTF(x)
85 #define DPRINTFN(n,x)
86 #endif
87
88
89 static void lan9118_start(struct ifnet *);
90 static int lan9118_ioctl(struct ifnet *, u_long, void *);
91 static int lan9118_init(struct ifnet *);
92 static void lan9118_stop(struct ifnet *, int);
93 static void lan9118_watchdog(struct ifnet *);
94
95 static int lan9118_ifm_change(struct ifnet *);
96 static void lan9118_ifm_status(struct ifnet *, struct ifmediareq *);
97
98 static int lan9118_miibus_readreg(device_t, int, int);
99 static void lan9118_miibus_writereg(device_t, int, int, int);
100 static void lan9118_miibus_statchg(device_t);
101
102 static uint16_t lan9118_mii_readreg(struct lan9118_softc *, int, int);
103 static void lan9118_mii_writereg(struct lan9118_softc *, int, int, uint16_t);
104 static uint32_t lan9118_mac_readreg(struct lan9118_softc *, int);
105 static void lan9118_mac_writereg(struct lan9118_softc *, int, uint32_t);
106
107 static void lan9118_set_filter(struct lan9118_softc *);
108 static void lan9118_rxintr(struct lan9118_softc *);
109 static void lan9118_txintr(struct lan9118_softc *);
110
111 static void lan9118_tick(void *);
112
113 /* This values refer from Linux's smc911x.c */
114 static uint32_t afc_cfg[] = {
115 /* 0 */ 0x00000000,
116 /* 1 */ 0x00000000,
117 /* 2 */ 0x008c4600 | LAN9118_AFC_CFG_BACK_DUR(10) |
118 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
119 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
120 /* 3 */ 0x00824100 | LAN9118_AFC_CFG_BACK_DUR(9) |
121 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
122 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
123 /* 4 */ 0x00783c00 | LAN9118_AFC_CFG_BACK_DUR(9) |
124 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
125 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
126 /* 5 */ 0x006e3700 | LAN9118_AFC_CFG_BACK_DUR(8) |
127 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
128 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
129 /* 6 */ 0x00643200 | LAN9118_AFC_CFG_BACK_DUR(8) |
130 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
131 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
132 /* 7 */ 0x005a2d00 | LAN9118_AFC_CFG_BACK_DUR(7) |
133 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
134 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
135 /* 8 */ 0x00502800 | LAN9118_AFC_CFG_BACK_DUR(7) |
136 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
137 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
138 /* 9 */ 0x00462300 | LAN9118_AFC_CFG_BACK_DUR(6) |
139 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
140 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
141 /* a */ 0x003c1e00 | LAN9118_AFC_CFG_BACK_DUR(6) |
142 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
143 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
144 /* b */ 0x00321900 | LAN9118_AFC_CFG_BACK_DUR(5) |
145 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
146 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
147 /* c */ 0x00241200 | LAN9118_AFC_CFG_BACK_DUR(4) |
148 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
149 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
150 /* d */ 0x00150700 | LAN9118_AFC_CFG_BACK_DUR(3) |
151 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
152 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
153 /* e */ 0x00060300 | LAN9118_AFC_CFG_BACK_DUR(2) |
154 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
155 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
156 /* f */ 0x00000000,
157 };
158
159
160 int
161 lan9118_attach(struct lan9118_softc *sc)
162 {
163 struct ifnet *ifp = &sc->sc_ec.ec_if;
164 uint32_t val;
165 int timo, i;
166
167 if (sc->sc_flags & LAN9118_FLAGS_SWAP) {
168 /* need byte swap */
169 DPRINTFN(1, ("%s: need byte swap\n", __func__));
170 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_WORD_SWAP,
171 0xffffffff);
172 }
173 val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_BYTE_TEST);
174 if (val != LAN9118_BYTE_TEST_VALUE) {
175 aprint_error_dev(sc->sc_dev, "failed to detect chip\n");
176 return EINVAL;
177 }
178
179 val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_ID_REV);
180 sc->sc_id = LAN9118_ID_REV_ID(val);
181 sc->sc_rev = LAN9118_ID_REV_REV(val);
182
183 aprint_normal_dev(sc->sc_dev, "SMSC LAN9%03x Rev %d\n",
184 sc->sc_id, sc->sc_rev);
185
186 timo = 3 * 1000 * 1000; /* XXXX 3sec */
187 do {
188 val = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
189 LAN9118_MAC_CSR_CMD);
190 if (!(val & LAN9118_MAC_CSR_CMD_BUSY))
191 break;
192 delay(100);
193 } while (timo -= 100);
194 if (timo <= 0)
195 aprint_error_dev(sc->sc_dev, "%s: command busy\n", __func__);
196 if (!(sc->sc_flags & LAN9118_FLAGS_NO_EEPROM)) {
197 /* Read auto-loaded MAC address */
198 val = lan9118_mac_readreg(sc, LAN9118_ADDRL);
199 sc->sc_enaddr[3] = (val >> 24) & 0xff;
200 sc->sc_enaddr[2] = (val >> 16) & 0xff;
201 sc->sc_enaddr[1] = (val >> 8) & 0xff;
202 sc->sc_enaddr[0] = val & 0xff;
203 val = lan9118_mac_readreg(sc, LAN9118_ADDRH);
204 sc->sc_enaddr[5] = (val >> 8) & 0xff;
205 sc->sc_enaddr[4] = val & 0xff;
206 }
207 aprint_normal_dev(sc->sc_dev, "MAC address %s\n",
208 ether_sprintf(sc->sc_enaddr));
209
210 KASSERT(LAN9118_TX_FIF_SZ >= 2 && LAN9118_TX_FIF_SZ < 15);
211 sc->sc_afc_cfg = afc_cfg[LAN9118_TX_FIF_SZ];
212
213 /* Initialize the ifnet structure. */
214 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
215 ifp->if_softc = sc;
216 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
217 ifp->if_start = lan9118_start;
218 ifp->if_ioctl = lan9118_ioctl;
219 ifp->if_init = lan9118_init;
220 ifp->if_stop = lan9118_stop;
221 ifp->if_watchdog = lan9118_watchdog;
222 IFQ_SET_READY(&ifp->if_snd);
223
224 #if 0 /* Not support 802.1Q VLAN-sized frames yet. */
225 sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU;
226 #endif
227
228 ifmedia_init(&sc->sc_mii.mii_media, 0,
229 lan9118_ifm_change, lan9118_ifm_status);
230 /*
231 * Number of instance of Internal PHY is always 0. External PHY
232 * number that above.
233 */
234 sc->sc_mii.mii_instance++;
235 if (sc->sc_id == LAN9118_ID_9115 || sc->sc_id == LAN9118_ID_9117) {
236 if (bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG) &
237 LAN9118_HW_CFG_EXT_PHY_DET) {
238 /*
239 * We always have a internal PHY at phy1.
240 * In addition, external PHY is attached.
241 */
242 DPRINTFN(1, ("%s: detect External PHY\n", __func__));
243
244 sc->sc_mii.mii_readreg = lan9118_miibus_readreg;
245 sc->sc_mii.mii_writereg = lan9118_miibus_writereg;
246 sc->sc_mii.mii_statchg = lan9118_miibus_statchg;
247
248 /* Switch MII and SMI */
249 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
250 LAN9118_HW_CFG,
251 LAN9118_HW_CFG_MBO |
252 LAN9118_HW_CFG_PHY_CLK_SEL_CD);
253 delay(1); /* Wait 5 cycle */
254 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
255 LAN9118_HW_CFG,
256 LAN9118_HW_CFG_MBO |
257 LAN9118_HW_CFG_PHY_CLK_SEL_EMII |
258 LAN9118_HW_CFG_SMI_SEL |
259 LAN9118_HW_CFG_EXT_PHY_EN);
260 delay(1); /* Once wait more 5 cycle */
261
262 /* Call mii_attach, avoid at phy1. */
263 mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff,
264 0, MII_OFFSET_ANY, 0);
265 for (i = 2; i < MII_NPHY; i++)
266 mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff,
267 i, MII_OFFSET_ANY, 0);
268 }
269 }
270 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL);
271 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_10_T, 0, NULL);
272 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_10_T | IFM_FDX, 0,
273 NULL);
274 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_100_TX, 0, NULL);
275 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_100_TX | IFM_FDX, 0,
276 NULL);
277 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO, 0, NULL);
278
279 aprint_normal_dev(sc->sc_dev,
280 "10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto\n");
281 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO);
282
283 /* Attach the interface. */
284 if_attach(ifp);
285 ether_ifattach(ifp, sc->sc_enaddr);
286
287 callout_init(&sc->sc_tick, 0);
288
289 #if NRND > 0
290 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
291 RND_TYPE_NET, 0);
292 #endif
293 return 0;
294 }
295
296 int
297 lan9118_intr(void *arg)
298 {
299 struct lan9118_softc *sc = (struct lan9118_softc *)arg;
300 struct ifnet *ifp = &sc->sc_ec.ec_if;
301 uint32_t int_sts, int_en, datum = 0;
302 int handled = 0;
303
304 for (;;) {
305 int_sts =
306 bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_STS);
307 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_STS,
308 int_sts);
309 int_en =
310 bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_EN);
311
312 DPRINTFN(3, ("%s: int_sts=0x%x, int_en=0x%x\n",
313 __func__, int_sts, int_en));
314
315 if (!(int_sts & int_en))
316 break;
317 datum = int_sts;
318
319 #if 0 /* not yet... */
320 if (int_sts & LAN9118_INT_PHY_INT) { /* PHY */
321 /* Shall we need? */
322 }
323 if (int_sts & LAN9118_INT_PME_INT) { /*Power Management Event*/
324 /* not yet... */
325 }
326 #endif
327 if (int_sts & LAN9118_INT_RXE) {
328 ifp->if_ierrors++;
329 aprint_error_ifnet(ifp, "Receive Error\n");
330 }
331 if (int_sts & LAN9118_INT_TSFL) /* TX Status FIFO Level */
332 lan9118_txintr(sc);
333 if (int_sts & LAN9118_INT_RXDF_INT) {
334 ifp->if_ierrors++;
335 aprint_error_ifnet(ifp, "RX Dropped Frame Interrupt\n");
336 }
337 if (int_sts & LAN9118_INT_RSFF) {
338 ifp->if_ierrors++;
339 aprint_error_ifnet(ifp, "RX Status FIFO Full\n");
340 }
341 if (int_sts & LAN9118_INT_RSFL) /* RX Status FIFO Level */
342 lan9118_rxintr(sc);
343 }
344
345 if (!IFQ_IS_EMPTY(&ifp->if_snd))
346 lan9118_start(ifp);
347
348 #if NRND > 0
349 if (RND_ENABLED(&sc->rnd_source))
350 rnd_add_uint32(&sc->rnd_source, datum);
351 #endif
352
353 return handled;
354 }
355
356
357 static void
358 lan9118_start(struct ifnet *ifp)
359 {
360 struct lan9118_softc *sc = ifp->if_softc;
361 struct mbuf *m0, *m;
362 unsigned tdfree, totlen, dso;
363 uint32_t txa, txb;
364 uint8_t *p;
365 int n;
366
367 DPRINTFN(3, ("%s\n", __func__));
368
369 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
370 return;
371
372 totlen = 0;
373 for (;;) {
374 IFQ_POLL(&ifp->if_snd, m0);
375 if (m0 == NULL)
376 break;
377
378 tdfree = LAN9118_TX_FIFO_INF_TDFREE(bus_space_read_4(sc->sc_iot,
379 sc->sc_ioh, LAN9118_TX_FIFO_INF));
380 if (tdfree < 2036) {
381 /*
382 * 2036 is the possible maximum FIFO consumption
383 * for the most fragmented frame.
384 */
385 ifp->if_flags |= IFF_OACTIVE;
386 break;
387 }
388
389 IFQ_DEQUEUE(&ifp->if_snd, m0);
390
391 /*
392 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
393 */
394
395 /*
396 * Check mbuf chain -- "middle" buffers must be >= 4 bytes
397 * and maximum # of buffers is 86.
398 */
399 m = m0;
400 n = 0;
401 while (m) {
402 if (m->m_len < 4 || ++n > 86) {
403 /* Copy mbuf chain. */
404 MGETHDR(m, M_DONTWAIT, MT_DATA);
405 if (m == NULL)
406 goto discard; /* discard packet */
407 MCLGET(m, M_DONTWAIT);
408 if ((m->m_flags & M_EXT) == 0) {
409 m_freem(m);
410 goto discard; /* discard packet */
411 }
412 m_copydata(m0, 0, m0->m_pkthdr.len,
413 mtod(m, void *));
414 m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
415 m_freem(m0);
416 m0 = m;
417 break;
418 }
419 m = m->m_next;
420 }
421
422 m = m0;
423 totlen = m->m_pkthdr.len;
424 p = mtod(m, uint8_t *);
425 dso = (unsigned)p & 0x3;
426 txa =
427 LAN9118_TXC_A_BEA_4B |
428 LAN9118_TXC_A_DSO(dso) |
429 LAN9118_TXC_A_FS |
430 LAN9118_TXC_A_BS(m->m_len);
431 txb = LAN9118_TXC_B_PL(totlen);
432 while (m->m_next != NULL) {
433 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
434 LAN9118_TXDFIFOP, txa);
435 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
436 LAN9118_TXDFIFOP, txb);
437 bus_space_write_multi_4(sc->sc_iot, sc->sc_ioh,
438 LAN9118_TXDFIFOP, (uint32_t *)(p - dso),
439 (m->m_len + dso + 3) >> 2);
440
441 m = m->m_next;
442 p = mtod(m, uint8_t *);
443 dso = (unsigned)p & 0x3;
444 txa =
445 LAN9118_TXC_A_BEA_4B |
446 LAN9118_TXC_A_DSO(dso) |
447 LAN9118_TXC_A_BS(m->m_len);
448 }
449 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_TXDFIFOP,
450 txa | LAN9118_TXC_A_LS);
451 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_TXDFIFOP,
452 txb);
453 bus_space_write_multi_4(sc->sc_iot, sc->sc_ioh,
454 LAN9118_TXDFIFOP, (uint32_t *)(p - dso),
455 (m->m_len + dso + 3) >> 2);
456
457 discard:
458 #if NBPFILTER > 0
459 /*
460 * Pass the packet to any BPF listeners.
461 */
462 if (ifp->if_bpf)
463 bpf_mtap(ifp->if_bpf, m0);
464 #endif /* NBPFILTER > 0 */
465
466 m_freem(m0);
467 }
468 if (totlen > 0)
469 ifp->if_timer = 5;
470 }
471
472 static int
473 lan9118_ioctl(struct ifnet *ifp, u_long command, void *data)
474 {
475 struct lan9118_softc *sc = ifp->if_softc;
476 struct ifreq *ifr = data;
477 struct mii_data *mii = &sc->sc_mii;
478 int s, error = 0;
479
480 s = splnet();
481
482 switch (command) {
483 case SIOCSIFFLAGS:
484 DPRINTFN(2, ("%s: IFFLAGS\n", __func__));
485 if ((error = ifioctl_common(ifp, command, data)) != 0)
486 break;
487 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
488 case IFF_RUNNING:
489 lan9118_stop(ifp, 0);
490 break;
491 case IFF_UP:
492 lan9118_init(ifp);
493 break;
494 default:
495 break;
496 }
497 error = 0;
498 break;
499
500 case SIOCGIFMEDIA:
501 case SIOCSIFMEDIA:
502 DPRINTFN(2, ("%s: MEDIA\n", __func__));
503 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
504 break;
505
506 default:
507 DPRINTFN(2, ("%s: ETHER\n", __func__));
508 error = ether_ioctl(ifp, command, data);
509 if (error == ENETRESET) {
510 if (ifp->if_flags & IFF_RUNNING) {
511 lan9118_set_filter(sc);
512 DPRINTFN(2, ("%s set_filter called\n",
513 __func__));
514 }
515 error = 0;
516 }
517 break;
518 }
519
520 splx(s);
521
522 return error;
523 }
524
525 static int
526 lan9118_init(struct ifnet *ifp)
527 {
528 struct lan9118_softc *sc = ifp->if_softc;
529 struct ifmedia *ifm = &sc->sc_mii.mii_media;
530 uint32_t reg, hw_cfg, mac_cr;
531 int timo, s;
532
533 DPRINTFN(2, ("%s\n", __func__));
534
535 s = splnet();
536
537 /* wait for PMT_CTRL[READY] */
538 timo = mstohz(5000); /* XXXX 5sec */
539 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_PMT_CTRL) &
540 LAN9118_PMT_CTRL_READY)) {
541 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_BYTE_TEST,
542 0xbad0c0de);
543 tsleep(&sc, PRIBIO, "lan9118_pmt_ready", 1);
544 if (--timo <= 0) {
545 splx(s);
546 return EBUSY;
547 }
548 }
549
550 /* Soft Reset */
551 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG,
552 LAN9118_HW_CFG_SRST);
553 do {
554 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG);
555 if (reg & LAN9118_HW_CFG_SRST_TO) {
556 aprint_error_dev(sc->sc_dev,
557 "soft reset timeouted out\n");
558 splx(s);
559 return ETIMEDOUT;
560 }
561 } while (reg & LAN9118_HW_CFG_SRST);
562
563 /* Set MAC and PHY CSRs */
564
565 if (sc->sc_flags & LAN9118_FLAGS_SWAP)
566 /* need byte swap */
567 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_WORD_SWAP,
568 0xffffffff);
569
570 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_E2P_CMD) &
571 LAN9118_E2P_CMD_EPCB);
572 if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_E2P_CMD) &
573 LAN9118_E2P_CMD_MACAL)) {
574 lan9118_mac_writereg(sc, LAN9118_ADDRL,
575 sc->sc_enaddr[0] |
576 sc->sc_enaddr[1] << 8 |
577 sc->sc_enaddr[2] << 16 |
578 sc->sc_enaddr[3] << 24);
579 lan9118_mac_writereg(sc, LAN9118_ADDRH,
580 sc->sc_enaddr[4] | sc->sc_enaddr[5] << 8);
581 }
582
583 if (ifm->ifm_media & IFM_FLOW) {
584 lan9118_mac_writereg(sc, LAN9118_FLOW,
585 LAN9118_FLOW_FCPT(1) | LAN9118_FLOW_FCEN);
586 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_AFC_CFG,
587 sc->sc_afc_cfg);
588 }
589
590 lan9118_ifm_change(ifp);
591 hw_cfg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG);
592 hw_cfg &= ~LAN9118_HW_CFG_TX_FIF_MASK;
593 hw_cfg |= LAN9118_HW_CFG_TX_FIF_SZ(LAN9118_TX_FIF_SZ);
594 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG, hw_cfg);
595
596 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_GPIO_CFG,
597 LAN9118_GPIO_CFG_LEDX_EN(2) |
598 LAN9118_GPIO_CFG_LEDX_EN(1) |
599 LAN9118_GPIO_CFG_LEDX_EN(0) |
600 LAN9118_GPIO_CFG_GPIOBUFN(2) |
601 LAN9118_GPIO_CFG_GPIOBUFN(1) |
602 LAN9118_GPIO_CFG_GPIOBUFN(0));
603
604 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_IRQ_CFG,
605 LAN9118_IRQ_CFG_IRQ_EN);
606 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_STS,
607 bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_STS));
608 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_FIFO_INT,
609 LAN9118_FIFO_INT_TXSL(0) | LAN9118_FIFO_INT_RXSL(0));
610 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_EN,
611 #if 0 /* not yet... */
612 LAN9118_INT_PHY_INT | /* PHY */
613 LAN9118_INT_PME_INT | /* Power Management Event */
614 #endif
615 LAN9118_INT_RXE | /* Receive Error */
616 LAN9118_INT_TSFL | /* TX Status FIFO Level */
617 LAN9118_INT_RXDF_INT| /* RX Dropped Frame Interrupt */
618 LAN9118_INT_RSFF | /* RX Status FIFO Full */
619 LAN9118_INT_RSFL); /* RX Status FIFO Level */
620
621 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_RX_CFG,
622 LAN9118_RX_CFG_RXDOFF(2));
623 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_TX_CFG,
624 LAN9118_TX_CFG_TX_ON);
625 mac_cr = lan9118_mac_readreg(sc, LAN9118_MAC_CR);
626 lan9118_mac_writereg(sc, LAN9118_MAC_CR,
627 mac_cr | LAN9118_MAC_CR_TXEN | LAN9118_MAC_CR_RXEN);
628
629 ifp->if_flags |= IFF_RUNNING;
630 ifp->if_flags &= ~IFF_OACTIVE;
631
632 callout_reset(&sc->sc_tick, hz, lan9118_tick, sc);
633
634 splx(s);
635
636 return 0;
637 }
638
639 static void
640 lan9118_stop(struct ifnet *ifp, int disable)
641 {
642 struct lan9118_softc *sc = ifp->if_softc;
643 uint32_t cr;
644
645 DPRINTFN(2, ("%s\n", __func__));
646
647 /* Disable IRQ */
648 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_EN, 0);
649
650 /* Stopping transmitter */
651 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_TX_CFG,
652 LAN9118_TX_CFG_STOP_TX);
653 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_TX_CFG) &
654 (LAN9118_TX_CFG_TX_ON | LAN9118_TX_CFG_STOP_TX));
655
656 /* Purge TX Status/Data FIFOs */
657 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_TX_CFG,
658 LAN9118_TX_CFG_TXS_DUMP | LAN9118_TX_CFG_TXD_DUMP);
659
660 /* Stopping receiver, also clear TXEN */
661 cr = lan9118_mac_readreg(sc, LAN9118_MAC_CR);
662 cr &= ~(LAN9118_MAC_CR_TXEN | LAN9118_MAC_CR_RXEN);
663 lan9118_mac_writereg(sc, LAN9118_MAC_CR, cr);
664 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_STS) &
665 LAN9118_INT_RXSTOP_INT));
666
667 /* Clear RX Status/Data FIFOs */
668 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_RX_CFG,
669 LAN9118_RX_CFG_RX_DUMP);
670
671 callout_stop(&sc->sc_tick);
672 }
673
674 static void
675 lan9118_watchdog(struct ifnet *ifp)
676 {
677 struct lan9118_softc *sc = ifp->if_softc;
678
679 /*
680 * Reclaim first as there is a possibility of losing Tx completion
681 * interrupts.
682 */
683 lan9118_txintr(sc);
684
685 aprint_error_ifnet(ifp, "watchdog timeout\n");
686 ifp->if_oerrors++;
687
688 lan9118_init(ifp);
689 }
690
691
692 static int
693 lan9118_ifm_change(struct ifnet *ifp)
694 {
695 struct lan9118_softc *sc = ifp->if_softc;
696 struct mii_data *mii = &sc->sc_mii;
697 struct ifmedia *ifm = &mii->mii_media;
698 struct ifmedia_entry *ife = ifm->ifm_cur;
699 uint32_t pmt_ctrl, bmc, bms, ana, anlpa;
700 int i;
701
702 DPRINTFN(3, ("%s: ifm inst %d\n", __func__, IFM_INST(ife->ifm_media)));
703
704 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG,
705 LAN9118_HW_CFG_MBO | LAN9118_HW_CFG_PHY_CLK_SEL_CD);
706 delay(1); /* Wait 5 cycle */
707
708 if (IFM_INST(ife->ifm_media) != 0) {
709 /* Use External PHY */
710
711 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG,
712 LAN9118_HW_CFG_MBO |
713 LAN9118_HW_CFG_PHY_CLK_SEL_EMII |
714 LAN9118_HW_CFG_SMI_SEL |
715 LAN9118_HW_CFG_EXT_PHY_EN);
716 delay(1);
717 return mii_mediachg(&sc->sc_mii);
718 }
719
720 /* Setup Internal PHY */
721
722 mii->mii_media_status = IFM_AVALID;
723 mii->mii_media_active = IFM_ETHER;
724
725 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG,
726 LAN9118_HW_CFG_MBO |
727 LAN9118_HW_CFG_PHY_CLK_SEL_IPHY);
728 delay(1);
729
730 /* Reset PHY */
731 pmt_ctrl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_PMT_CTRL);
732 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_PMT_CTRL,
733 pmt_ctrl | LAN9118_PMT_CTRL_PHY_RST);
734 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_PMT_CTRL) &
735 LAN9118_PMT_CTRL_PHY_RST);
736
737 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) {
738 bmc = BMCR_AUTOEN | BMCR_STARTNEG;
739 bms = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, MII_BMSR);
740 ana = ANAR_FC | BMSR_MEDIA_TO_ANAR(bms) | ANAR_CSMA;
741
742 lan9118_mii_writereg(sc, LAN9118_IPHY_ADDR, MII_ANAR, ana);
743 lan9118_mii_writereg(sc, LAN9118_IPHY_ADDR, MII_BMCR, bmc);
744
745 /* Wait 5sec for it to complete. */
746 for (i = 0; i < 5000; i++) {
747 if (lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, MII_BMSR)
748 & BMSR_ACOMP)
749 break;
750 delay(1000);
751 }
752 if (i == 5000) {
753 aprint_error_ifnet(ifp, "Auto-Negotiate failed\n");
754 return EIO;
755 }
756 } else {
757 switch (IFM_SUBTYPE(ifm->ifm_media)) {
758 case IFM_10_T:
759 bmc = BMCR_S10;
760 ana = ANAR_CSMA | ANAR_10;
761 break;
762
763 case IFM_100_TX:
764 bmc = BMCR_S100;
765 if (ifm->ifm_media & IFM_FDX)
766 bmc |= BMCR_FDX;
767 ana = ANAR_CSMA | ANAR_TX;
768 break;
769
770 case IFM_NONE:
771 bmc = BMCR_PDOWN;
772 break;
773
774 default:
775 return EINVAL;
776 }
777 if (ifm->ifm_media & IFM_FDX)
778 bmc |= BMCR_FDX;
779 if (ifm->ifm_media & IFM_FLOW)
780 ana |= ANAR_FC;
781
782 lan9118_mii_writereg(sc, LAN9118_IPHY_ADDR, MII_ANAR, ana);
783 lan9118_mii_writereg(sc, LAN9118_IPHY_ADDR, MII_BMCR, bmc);
784 }
785
786 bms = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, MII_BMSR);
787 if (bms & BMSR_LINK) {
788 mii->mii_media_status |= IFM_ACTIVE;
789
790 bmc = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, MII_BMCR);
791 if (bmc & BMCR_AUTOEN) {
792 anlpa = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR,
793 MII_ANLPAR);
794 if (anlpa & ANLPAR_TX_FD)
795 mii->mii_media_active |= IFM_100_TX | IFM_FDX;
796 else if (anlpa & ANLPAR_T4)
797 mii->mii_media_active |= IFM_100_T4;
798 else if (anlpa & ANLPAR_TX)
799 mii->mii_media_active |= IFM_100_TX;
800 else if (anlpa & ANLPAR_10_FD)
801 mii->mii_media_active |= IFM_10_T|IFM_FDX;
802 else if (anlpa & ANLPAR_10)
803 mii->mii_media_active |= IFM_10_T;
804 else
805 mii->mii_media_active |= IFM_NONE;
806 } else
807 mii->mii_media_active = ife->ifm_media;
808
809 lan9118_miibus_statchg(sc->sc_dev);
810 }
811 return 0;
812 }
813
814 static void
815 lan9118_ifm_status(struct ifnet *ifp, struct ifmediareq *ifmr)
816 {
817 struct lan9118_softc *sc = ifp->if_softc;
818 struct mii_data *mii = &sc->sc_mii;
819 struct ifmedia *ifm = &mii->mii_media;
820 struct ifmedia_entry *ife = ifm->ifm_cur;
821 uint32_t bms, physcs;
822
823 DPRINTFN(3, ("%s\n", __func__));
824
825 if (IFM_INST(ife->ifm_media) != 0) {
826 mii_pollstat(mii);
827 ifmr->ifm_active = mii->mii_media_active;
828 ifmr->ifm_status = mii->mii_media_status;
829 return;
830 }
831
832 ifmr->ifm_active = IFM_ETHER;
833 ifmr->ifm_status = IFM_AVALID;
834
835 bms = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, MII_BMSR);
836 if (!(bms & BMSR_LINK)) {
837 /* link is down */
838 ifmr->ifm_active |= IFM_NONE;
839 return;
840 }
841 ifmr->ifm_status |= IFM_ACTIVE;
842 physcs = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, LAN9118_PHYSCSR);
843 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) {
844 if (!(physcs & LAN9118_PHYSCSR_AUTODONE)) {
845 /* negotiation in progress */
846 ifmr->ifm_active |= IFM_NONE;
847 return;
848 }
849 }
850 if (physcs & LAN9118_PHYSCSR_SI_10)
851 ifmr->ifm_active |= IFM_10_T;
852 if (physcs & LAN9118_PHYSCSR_SI_100)
853 ifmr->ifm_active |= IFM_100_TX;
854 if (physcs & LAN9118_PHYSCSR_SI_FDX)
855 ifmr->ifm_active |= IFM_FDX;
856 }
857
858
859 static int
860 lan9118_miibus_readreg(device_t dev, int phy, int reg)
861 {
862
863 return lan9118_mii_readreg(device_private(dev), phy, reg);
864 }
865 static void
866 lan9118_miibus_writereg(device_t dev, int phy, int reg, int val)
867 {
868
869 lan9118_mii_writereg(device_private(dev), phy, reg, val);
870 }
871
872 static void
873 lan9118_miibus_statchg(device_t dev)
874 {
875 struct lan9118_softc *sc = device_private(dev);
876 u_int cr;
877
878 cr = lan9118_mac_readreg(sc, LAN9118_MAC_CR);
879 if (IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) {
880 cr &= ~LAN9118_MAC_CR_RCVOWN;
881 cr |= LAN9118_MAC_CR_FDPX;
882 } else {
883 cr |= LAN9118_MAC_CR_RCVOWN;
884 cr &= ~LAN9118_MAC_CR_FDPX;
885 }
886 lan9118_mac_writereg(sc, LAN9118_MAC_CR, cr);
887 }
888
889
890 static uint16_t
891 lan9118_mii_readreg(struct lan9118_softc *sc, int phy, int reg)
892 {
893 uint32_t acc;
894
895 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
896 LAN9118_MII_ACC_MIIBZY);
897 acc = LAN9118_MII_ACC_PHYA(phy) | LAN9118_MII_ACC_MIIRINDA(reg);
898 lan9118_mac_writereg(sc, LAN9118_MII_ACC, acc);
899 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
900 LAN9118_MII_ACC_MIIBZY);
901 return lan9118_mac_readreg(sc, LAN9118_MII_DATA);
902 }
903
904 static void
905 lan9118_mii_writereg(struct lan9118_softc *sc, int phy, int reg, uint16_t val)
906 {
907 uint32_t acc;
908
909 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
910 LAN9118_MII_ACC_MIIBZY);
911 acc = LAN9118_MII_ACC_PHYA(phy) | LAN9118_MII_ACC_MIIRINDA(reg) |
912 LAN9118_MII_ACC_MIIWNR;
913 lan9118_mac_writereg(sc, LAN9118_MII_DATA, val);
914 lan9118_mac_writereg(sc, LAN9118_MII_ACC, acc);
915 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
916 LAN9118_MII_ACC_MIIBZY);
917 }
918
919 static uint32_t
920 lan9118_mac_readreg(struct lan9118_softc *sc, int reg)
921 {
922 uint32_t cmd;
923 int timo = 3 * 1000 * 1000; /* XXXX: 3sec */
924
925 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_CMD,
926 LAN9118_MAC_CSR_CMD_BUSY | LAN9118_MAC_CSR_CMD_R | reg);
927 do {
928 cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
929 LAN9118_MAC_CSR_CMD);
930 if (!(cmd & LAN9118_MAC_CSR_CMD_BUSY))
931 break;
932 delay(100);
933 } while (timo -= 100);
934 if (timo <= 0)
935 aprint_error_dev(sc->sc_dev, "%s: command busy\n", __func__);
936 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_DATA);
937 }
938
939 static void
940 lan9118_mac_writereg(struct lan9118_softc *sc, int reg, uint32_t val)
941 {
942 uint32_t cmd;
943 int timo = 3 * 1000 * 1000; /* XXXX: 3sec */
944
945 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_DATA, val);
946 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_CMD,
947 LAN9118_MAC_CSR_CMD_BUSY | LAN9118_MAC_CSR_CMD_W | reg);
948 do {
949 cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
950 LAN9118_MAC_CSR_CMD);
951 if (!(cmd & LAN9118_MAC_CSR_CMD_BUSY))
952 break;
953 delay(100);
954 } while (timo -= 100);
955 if (timo <= 0)
956 aprint_error_dev(sc->sc_dev, "%s: command busy\n", __func__);
957 }
958
959
960 static void
961 lan9118_set_filter(struct lan9118_softc *sc)
962 {
963 struct ether_multistep step;
964 struct ether_multi *enm;
965 struct ifnet *ifp = &sc->sc_ec.ec_if;
966 uint32_t mac_cr, h, hashes[2] = { 0, 0 };
967
968 mac_cr = lan9118_mac_readreg(sc, LAN9118_MAC_CR);
969 if (ifp->if_flags & IFF_PROMISC) {
970 lan9118_mac_writereg(sc, LAN9118_MAC_CR,
971 mac_cr | LAN9118_MAC_CR_PRMS);
972 return;
973 }
974
975 mac_cr &= ~(LAN9118_MAC_CR_PRMS | LAN9118_MAC_CR_MCPAS |
976 LAN9118_MAC_CR_BCAST | LAN9118_MAC_CR_HPFILT);
977 if (!(ifp->if_flags & IFF_BROADCAST))
978 mac_cr |= LAN9118_MAC_CR_BCAST;
979
980 if (ifp->if_flags & IFF_ALLMULTI)
981 mac_cr |= LAN9118_MAC_CR_MCPAS;
982 else {
983 ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
984 while (enm != NULL) {
985 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
986 ETHER_ADDR_LEN) != 0) {
987 /*
988 * We must listen to a range of multicast
989 * addresses. For now, just accept all
990 * multicasts, rather than trying to set
991 * only those filter bits needed to match
992 * the range. (At this time, the only use
993 * of address ranges is for IP multicast
994 * routing, for which the range is big enough
995 * to require all bits set.)
996 */
997 ifp->if_flags |= IFF_ALLMULTI;
998 mac_cr |= LAN9118_MAC_CR_MCPAS;
999 break;
1000 }
1001 h = ether_crc32_le(enm->enm_addrlo,
1002 ETHER_ADDR_LEN) >> 26;
1003 hashes[h >> 5] |= 1 << (h & 0x1f);
1004
1005 mac_cr |= LAN9118_MAC_CR_HPFILT;
1006 ETHER_NEXT_MULTI(step, enm);
1007 }
1008 if (mac_cr & LAN9118_MAC_CR_HPFILT) {
1009 lan9118_mac_writereg(sc, LAN9118_HASHH, hashes[1]);
1010 lan9118_mac_writereg(sc, LAN9118_HASHL, hashes[0]);
1011 }
1012 }
1013 lan9118_mac_writereg(sc, LAN9118_MAC_CR, mac_cr);
1014 return;
1015 }
1016
1017 static void
1018 lan9118_rxintr(struct lan9118_softc *sc)
1019 {
1020 struct ifnet *ifp = &sc->sc_ec.ec_if;
1021 struct mbuf *m;
1022 uint32_t rx_fifo_inf, rx_status;
1023 int pktlen;
1024 const int pad = ETHER_HDR_LEN % sizeof(uint32_t);
1025
1026 DPRINTFN(3, ("%s\n", __func__));
1027
1028 for (;;) {
1029 rx_fifo_inf = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
1030 LAN9118_RX_FIFO_INF);
1031 if (LAN9118_RX_FIFO_INF_RXSUSED(rx_fifo_inf) == 0)
1032 break;
1033
1034 rx_status = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
1035 LAN9118_RXSFIFOP);
1036 pktlen = LAN9118_RXS_PKTLEN(rx_status);
1037 DPRINTFN(3, ("%s: rx_status=0x%x(pktlen %d)\n",
1038 __func__, rx_status, pktlen));
1039 if (rx_status & (LAN9118_RXS_ES | LAN9118_RXS_LENERR |
1040 LAN9118_RXS_RWTO | LAN9118_RXS_MIIERR | LAN9118_RXS_DBIT)) {
1041 if (rx_status & LAN9118_RXS_LENERR)
1042 aprint_error_dev(sc->sc_dev, "Length Error\n");
1043 if (rx_status & LAN9118_RXS_RUNTF)
1044 aprint_error_dev(sc->sc_dev, "Runt Frame\n");
1045 if (rx_status & LAN9118_RXS_FTL)
1046 aprint_error_dev(sc->sc_dev,
1047 "Frame Too Long\n");
1048 if (rx_status & LAN9118_RXS_RWTO)
1049 aprint_error_dev(sc->sc_dev,
1050 "Receive Watchdog time-out\n");
1051 if (rx_status & LAN9118_RXS_MIIERR)
1052 aprint_error_dev(sc->sc_dev, "MII Error\n");
1053 if (rx_status & LAN9118_RXS_DBIT)
1054 aprint_error_dev(sc->sc_dev, "Drabbling Bit\n");
1055 if (rx_status & LAN9118_RXS_COLS)
1056 aprint_error_dev(sc->sc_dev,
1057 "Collision Seen\n");
1058 if (rx_status & LAN9118_RXS_CRCERR)
1059 aprint_error_dev(sc->sc_dev, "CRC Error\n");
1060
1061 dropit:
1062 ifp->if_ierrors++;
1063 /*
1064 * Receive Data FIFO Fast Forward
1065 * When performing a fast-forward, there must be at
1066 * least 4 DWORDs of data in the RX data FIFO for the
1067 * packet being discarded.
1068 */
1069 if (pktlen >= 4 * sizeof(uint32_t)) {
1070 uint32_t rx_dp_ctl;
1071
1072 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
1073 LAN9118_RX_DP_CTL,
1074 LAN9118_RX_DP_CTL_RX_FFWD);
1075 /* DP_FFWD bit is self clearing */
1076 do {
1077 rx_dp_ctl = bus_space_read_4(sc->sc_iot,
1078 sc->sc_ioh, LAN9118_RX_DP_CTL);
1079 } while (rx_dp_ctl & LAN9118_RX_DP_CTL_RX_FFWD);
1080 } else {
1081 /* For less than 4 DWORDs do not use RX_FFWD. */
1082 uint32_t garbage[4];
1083
1084 bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh,
1085 LAN9118_RXDFIFOP, garbage,
1086 roundup(pktlen, 4) >> 2);
1087 }
1088 continue;
1089 }
1090
1091 MGETHDR(m, M_DONTWAIT, MT_DATA);
1092 if (m == NULL)
1093 goto dropit;
1094 if (pktlen > (MHLEN - pad)) {
1095 MCLGET(m, M_DONTWAIT);
1096 if ((m->m_flags & M_EXT) == 0) {
1097 m_freem(m);
1098 goto dropit;
1099 }
1100 }
1101
1102 /* STRICT_ALIGNMENT */
1103 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_RX_CFG,
1104 LAN9118_RX_CFG_RXEA_4B | LAN9118_RX_CFG_RXDOFF(pad));
1105 bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh, LAN9118_RXDFIFOP,
1106 mtod(m, uint32_t *),
1107 roundup(pad + pktlen, sizeof(uint32_t)) >> 2);
1108 m->m_data += pad;
1109
1110 ifp->if_ipackets++;
1111 m->m_pkthdr.rcvif = ifp;
1112 m->m_pkthdr.len = m->m_len = (pktlen - ETHER_CRC_LEN);
1113
1114 #if NBPFILTER > 0
1115 /*
1116 * Pass this up to any BPF listeners, but only
1117 * pass if up the stack if it's for us.
1118 */
1119 if (ifp->if_bpf)
1120 bpf_mtap(ifp->if_bpf, m);
1121 #endif /* NBPFILTER > 0 */
1122
1123 /* Pass it on. */
1124 (*ifp->if_input)(ifp, m);
1125 }
1126 }
1127
1128 static void
1129 lan9118_txintr(struct lan9118_softc *sc)
1130 {
1131 struct ifnet *ifp = &sc->sc_ec.ec_if;
1132 uint32_t tx_fifo_inf, tx_status;
1133 int fdx = IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX;
1134 int tdfree;
1135
1136 DPRINTFN(3, ("%s\n", __func__));
1137
1138 for (;;) {
1139 tx_fifo_inf = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
1140 LAN9118_TX_FIFO_INF);
1141 if (LAN9118_TX_FIFO_INF_TXSUSED(tx_fifo_inf) == 0)
1142 break;
1143
1144 tx_status = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
1145 LAN9118_TXSFIFOP);
1146 DPRINTFN(3, ("%s: tx_status=0x%x\n", __func__, tx_status));
1147 if (tx_status & LAN9118_TXS_ES) {
1148 if (tx_status & LAN9118_TXS_LOC)
1149 aprint_error_dev(sc->sc_dev,
1150 "Loss Of Carrier\n");
1151 if ((tx_status & LAN9118_TXS_NC) && !fdx)
1152 aprint_error_dev(sc->sc_dev, "No Carrier\n");
1153 if (tx_status & LAN9118_TXS_LCOL)
1154 aprint_error_dev(sc->sc_dev,
1155 "Late Collision\n");
1156 if (tx_status & LAN9118_TXS_ECOL) {
1157 /* Rearch 16 collision */
1158 ifp->if_collisions += 16;
1159 aprint_error_dev(sc->sc_dev,
1160 "Excessive Collision\n");
1161 }
1162 if (LAN9118_TXS_COLCNT(tx_status) != 0)
1163 aprint_error_dev(sc->sc_dev,
1164 "Collision Count: %d\n",
1165 LAN9118_TXS_COLCNT(tx_status));
1166 if (tx_status & LAN9118_TXS_ED)
1167 aprint_error_dev(sc->sc_dev,
1168 "Excessive Deferral\n");
1169 if (tx_status & LAN9118_TXS_DEFERRED)
1170 aprint_error_dev(sc->sc_dev, "Deferred\n");
1171 ifp->if_oerrors++;
1172 } else
1173 ifp->if_opackets++;
1174 }
1175
1176 tdfree = LAN9118_TX_FIFO_INF_TDFREE(tx_fifo_inf);
1177 if (tdfree == LAN9118_TX_DATA_FIFO_SIZE)
1178 /* FIFO empty */
1179 ifp->if_timer = 0;
1180 if (tdfree >= 2036)
1181 /*
1182 * 2036 is the possible maximum FIFO consumption
1183 * for the most fragmented frame.
1184 */
1185 ifp->if_flags &= ~IFF_OACTIVE;
1186 }
1187
1188 void
1189 lan9118_tick(void *v)
1190 {
1191 struct lan9118_softc *sc = v;
1192 int s;
1193
1194 s = splnet();
1195 mii_tick(&sc->sc_mii);
1196 callout_schedule(&sc->sc_tick, hz);
1197 splx(s);
1198 }
1199