1 /* $NetBSD: lan9118.c,v 1.36 2020/01/29 14:53:40 thorpej 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.36 2020/01/29 14:53:40 thorpej Exp $");
29
30 /*
31 * The LAN9118 Family
32 * * The LAN9118 is targeted for 32-bit applications requiring high
33 * performance, and provides the highest level of performance possible for
34 * a non-PCI 10/100 Ethernet controller.
35 *
36 * * The LAN9117 is designed to provide the highest level of performance
37 * possible for 16-bit applications. It also has an external MII interface,
38 * which can be used to attach an external PHY.
39 *
40 * * The LAN9116 and LAN9115 are designed for performance-sensitive
41 * applications with less intensive performance requirements. The LAN9116
42 * is for 32-bit host processors, while the LAN9115 is for 16-bit
43 * applications, which may also require an external PHY. Both devices
44 * deliver superior levels of performance.
45 *
46 * The LAN9218 Family
47 * Also support HP Auto-MDIX.
48 */
49
50 #include <sys/param.h>
51 #include <sys/callout.h>
52 #include <sys/device.h>
53 #include <sys/errno.h>
54 #include <sys/bus.h>
55 #include <sys/ioctl.h>
56 #include <sys/kernel.h>
57 #include <sys/proc.h>
58 #include <sys/systm.h>
59
60 #include <net/if.h>
61 #include <net/if_ether.h>
62 #include <net/if_media.h>
63
64 #include <dev/mii/mii.h>
65 #include <dev/mii/miivar.h>
66
67 #include <net/bpf.h>
68 #include <sys/rndsource.h>
69
70 #include <dev/ic/lan9118reg.h>
71 #include <dev/ic/lan9118var.h>
72
73
74 #ifdef SMSH_DEBUG
75 #define DPRINTF(x) if (smsh_debug) printf x
76 #define DPRINTFN(n, x) if (smsh_debug >= (n)) printf x
77 int smsh_debug = SMSH_DEBUG;
78 #else
79 #define DPRINTF(x)
80 #define DPRINTFN(n, x)
81 #endif
82
83
84 static void lan9118_start(struct ifnet *);
85 static int lan9118_ioctl(struct ifnet *, u_long, void *);
86 static int lan9118_init(struct ifnet *);
87 static void lan9118_stop(struct ifnet *, int);
88 static void lan9118_watchdog(struct ifnet *);
89
90 static int lan9118_ifm_change(struct ifnet *);
91 static void lan9118_ifm_status(struct ifnet *, struct ifmediareq *);
92
93 static int lan9118_miibus_readreg(device_t, int, int, uint16_t *);
94 static int lan9118_miibus_writereg(device_t, int, int, uint16_t);
95 static void lan9118_miibus_statchg(struct ifnet *);
96
97 static int lan9118_mii_readreg(struct lan9118_softc *, int, int, uint16_t *);
98 static int lan9118_mii_writereg(struct lan9118_softc *, int, int, uint16_t);
99 static uint32_t lan9118_mac_readreg(struct lan9118_softc *, int);
100 static void lan9118_mac_writereg(struct lan9118_softc *, int, uint32_t);
101
102 static void lan9118_set_filter(struct lan9118_softc *);
103 static void lan9118_rxintr(struct lan9118_softc *);
104 static void lan9118_txintr(struct lan9118_softc *);
105
106 static void lan9118_tick(void *);
107
108 /* This values refer from Linux's smc911x.c */
109 static uint32_t afc_cfg[] = {
110 /* 0 */ 0x00000000,
111 /* 1 */ 0x00000000,
112 /* 2 */ 0x008c4600 | LAN9118_AFC_CFG_BACK_DUR(10) |
113 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
114 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
115 /* 3 */ 0x00824100 | LAN9118_AFC_CFG_BACK_DUR(9) |
116 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
117 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
118 /* 4 */ 0x00783c00 | LAN9118_AFC_CFG_BACK_DUR(9) |
119 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
120 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
121 /* 5 */ 0x006e3700 | LAN9118_AFC_CFG_BACK_DUR(8) |
122 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
123 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
124 /* 6 */ 0x00643200 | LAN9118_AFC_CFG_BACK_DUR(8) |
125 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
126 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
127 /* 7 */ 0x005a2d00 | LAN9118_AFC_CFG_BACK_DUR(7) |
128 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
129 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
130 /* 8 */ 0x00502800 | LAN9118_AFC_CFG_BACK_DUR(7) |
131 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
132 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
133 /* 9 */ 0x00462300 | LAN9118_AFC_CFG_BACK_DUR(6) |
134 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
135 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
136 /* a */ 0x003c1e00 | LAN9118_AFC_CFG_BACK_DUR(6) |
137 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
138 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
139 /* b */ 0x00321900 | LAN9118_AFC_CFG_BACK_DUR(5) |
140 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
141 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
142 /* c */ 0x00241200 | LAN9118_AFC_CFG_BACK_DUR(4) |
143 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
144 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
145 /* d */ 0x00150700 | LAN9118_AFC_CFG_BACK_DUR(3) |
146 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
147 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
148 /* e */ 0x00060300 | LAN9118_AFC_CFG_BACK_DUR(2) |
149 LAN9118_AFC_CFG_FCMULT | LAN9118_AFC_CFG_FCBRD |
150 LAN9118_AFC_CFG_FCADD | LAN9118_AFC_CFG_FCANY,
151 /* f */ 0x00000000,
152 };
153
154
155 int
lan9118_attach(struct lan9118_softc * sc)156 lan9118_attach(struct lan9118_softc *sc)
157 {
158 struct ifnet *ifp = &sc->sc_ec.ec_if;
159 struct mii_data *mii = &sc->sc_mii;
160 uint32_t val, irq_cfg;
161 int timo, i;
162
163 if (sc->sc_flags & LAN9118_FLAGS_SWAP)
164 /* byte swap mode */
165 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_WORD_SWAP,
166 0xffffffff);
167 val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_BYTE_TEST);
168 if (val != LAN9118_BYTE_TEST_VALUE) {
169 aprint_error(": failed to detect chip\n");
170 return EINVAL;
171 }
172
173 val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_ID_REV);
174 sc->sc_id = LAN9118_ID_REV_ID(val);
175 sc->sc_rev = LAN9118_ID_REV_REV(val);
176
177 #define LAN9xxx_ID(id) \
178 (IS_LAN9118(id) ? (id) : (IS_LAN9218(id) ? ((id) >> 4) + 0x100 : (id) & 0xfff))
179
180 aprint_normal(": SMSC LAN9%03x Rev %d\n",
181 LAN9xxx_ID(sc->sc_id), sc->sc_rev);
182
183 if (sc->sc_flags & LAN9118_FLAGS_SWAP)
184 aprint_normal_dev(sc->sc_dev, "byte swap mode\n");
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 /* Set IRQ config */
211 irq_cfg = 0;
212 if (sc->sc_flags & LAN9118_FLAGS_IRQ_ACTHI)
213 irq_cfg |= LAN9118_IRQ_CFG_IRQ_POL;
214 if (sc->sc_flags & LAN9118_FLAGS_IRQ_PP)
215 irq_cfg |= LAN9118_IRQ_CFG_IRQ_TYPE;
216 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_IRQ_CFG, irq_cfg);
217
218 KASSERT(LAN9118_TX_FIF_SZ >= 2 && LAN9118_TX_FIF_SZ < 15);
219 sc->sc_afc_cfg = afc_cfg[LAN9118_TX_FIF_SZ];
220
221 /* Initialize the ifnet structure. */
222 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
223 ifp->if_softc = sc;
224 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
225 ifp->if_start = lan9118_start;
226 ifp->if_ioctl = lan9118_ioctl;
227 ifp->if_init = lan9118_init;
228 ifp->if_stop = lan9118_stop;
229 ifp->if_watchdog = lan9118_watchdog;
230 IFQ_SET_READY(&ifp->if_snd);
231
232 #if 0 /* Not support 802.1Q VLAN-sized frames yet. */
233 sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU;
234 #endif
235
236 sc->sc_ec.ec_mii = mii;
237 ifmedia_init(&mii->mii_media, 0,
238 lan9118_ifm_change, lan9118_ifm_status);
239 mii->mii_ifp = ifp;
240 mii->mii_readreg = lan9118_miibus_readreg;
241 mii->mii_writereg = lan9118_miibus_writereg;
242 mii->mii_statchg = lan9118_miibus_statchg;
243
244 /*
245 * Number of instance of Internal PHY is always 0. External PHY
246 * number that above.
247 */
248 mii_attach(sc->sc_dev, mii, 0xffffffff, 1, MII_OFFSET_ANY, 0);
249
250 if (sc->sc_id == LAN9118_ID_9115 || sc->sc_id == LAN9118_ID_9117 ||
251 sc->sc_id == LAN9218_ID_9215 || sc->sc_id == LAN9218_ID_9217) {
252 if (bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG) &
253 LAN9118_HW_CFG_EXT_PHY_DET) {
254 /*
255 * We always have a internal PHY at phy1.
256 * In addition, external PHY is attached.
257 */
258 DPRINTFN(1, ("%s: detect External PHY\n", __func__));
259
260 /* Switch MII and SMI */
261 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
262 LAN9118_HW_CFG,
263 LAN9118_HW_CFG_MBO |
264 LAN9118_HW_CFG_PHY_CLK_SEL_CD);
265 delay(1); /* Wait 5 cycle */
266 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
267 LAN9118_HW_CFG,
268 LAN9118_HW_CFG_MBO |
269 LAN9118_HW_CFG_PHY_CLK_SEL_EMII |
270 LAN9118_HW_CFG_SMI_SEL |
271 LAN9118_HW_CFG_EXT_PHY_EN);
272 delay(1); /* Once wait more 5 cycle */
273
274 /* Call mii_attach, avoid at phy1. */
275 mii_attach(sc->sc_dev, mii, 0xffffffff,
276 0, MII_OFFSET_ANY, 0);
277 for (i = 2; i < MII_NPHY; i++)
278 mii_attach(sc->sc_dev, mii, 0xffffffff,
279 i, MII_OFFSET_ANY, 0);
280 }
281 }
282
283 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
284
285 /* Attach the interface. */
286 if_attach(ifp);
287 if_deferred_start_init(ifp, NULL);
288 ether_ifattach(ifp, sc->sc_enaddr);
289
290 callout_init(&sc->sc_tick, 0);
291
292 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
293 RND_TYPE_NET, RND_FLAG_DEFAULT);
294 return 0;
295 }
296
297 int
lan9118_intr(void * arg)298 lan9118_intr(void *arg)
299 {
300 struct lan9118_softc *sc = (struct lan9118_softc *)arg;
301 struct ifnet *ifp = &sc->sc_ec.ec_if;
302 uint32_t int_sts, int_en, datum = 0;
303 int handled = 0;
304
305 for (;;) {
306 int_sts =
307 bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_STS);
308 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_STS,
309 int_sts);
310 int_en =
311 bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_EN) |
312 LAN9118_INT_SW_INT;
313
314 DPRINTFN(3, ("%s: int_sts=0x%x, int_en=0x%x\n",
315 __func__, int_sts, int_en));
316
317 if (!(int_sts & int_en))
318 break;
319 datum = int_sts;
320 handled = 1;
321
322 #if 0 /* not yet... */
323 if (int_sts & LAN9118_INT_PHY_INT) { /* PHY */
324 /* Shall we need? */
325 }
326 if (int_sts & LAN9118_INT_PME_INT) { /*Power Management Event*/
327 /* not yet... */
328 }
329 #endif
330 if (int_sts & LAN9118_INT_RXE) {
331 if_statinc(ifp, if_ierrors);
332 aprint_error_ifnet(ifp, "Receive Error\n");
333 }
334 if (int_sts & (LAN9118_INT_TSFL|LAN9118_INT_SW_INT)) /* TX Status FIFO Level */
335 lan9118_txintr(sc);
336 if (int_sts & LAN9118_INT_RXDF_INT) {
337 if_statinc(ifp, if_ierrors);
338 aprint_error_ifnet(ifp, "RX Dropped Frame Interrupt\n");
339 }
340 if (int_sts & LAN9118_INT_RSFF) {
341 if_statinc(ifp, if_ierrors);
342 aprint_error_ifnet(ifp, "RX Status FIFO Full\n");
343 }
344 if (int_sts & LAN9118_INT_RSFL) /* RX Status FIFO Level */
345 lan9118_rxintr(sc);
346 }
347
348 if (handled)
349 if_schedule_deferred_start(ifp);
350
351 rnd_add_uint32(&sc->rnd_source, datum);
352
353 return handled;
354 }
355
356
357 static void
lan9118_start(struct ifnet * ifp)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, int_en;
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 /*
459 * Pass the packet to any BPF listeners.
460 */
461 bpf_mtap(ifp, m0, BPF_D_OUT);
462
463 m_freem(m0);
464 }
465
466 if (totlen > 0) {
467 ifp->if_timer = 5;
468
469 /*
470 * Trigger a software interrupt to catch any missed completion
471 * interrupts.
472 */
473 int_en = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
474 LAN9118_INT_EN);
475 int_en |= LAN9118_INT_SW_INT;
476 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_EN,
477 int_en);
478 }
479 }
480
481 static int
lan9118_ioctl(struct ifnet * ifp,u_long command,void * data)482 lan9118_ioctl(struct ifnet *ifp, u_long command, void *data)
483 {
484 struct lan9118_softc *sc = ifp->if_softc;
485 int s, error = 0;
486
487 s = splnet();
488
489 switch (command) {
490 case SIOCSIFFLAGS:
491 DPRINTFN(2, ("%s: IFFLAGS\n", __func__));
492 if ((error = ifioctl_common(ifp, command, data)) != 0)
493 break;
494 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
495 case IFF_RUNNING:
496 lan9118_stop(ifp, 0);
497 break;
498 case IFF_UP:
499 lan9118_init(ifp);
500 break;
501 case IFF_UP | IFF_RUNNING:
502 lan9118_set_filter(sc);
503 break;
504 default:
505 break;
506 }
507 error = 0;
508 break;
509
510 default:
511 DPRINTFN(2, ("%s: ETHER\n", __func__));
512 error = ether_ioctl(ifp, command, data);
513 if (error == ENETRESET) {
514 if (ifp->if_flags & IFF_RUNNING) {
515 lan9118_set_filter(sc);
516 DPRINTFN(2, ("%s set_filter called\n",
517 __func__));
518 }
519 error = 0;
520 }
521 break;
522 }
523
524 splx(s);
525
526 return error;
527 }
528
529 static int
lan9118_init(struct ifnet * ifp)530 lan9118_init(struct ifnet *ifp)
531 {
532 struct lan9118_softc *sc = ifp->if_softc;
533 struct ifmedia *ifm = &sc->sc_mii.mii_media;
534 uint32_t reg, hw_cfg, mac_cr, irq_cfg;
535 int timo, s;
536
537 DPRINTFN(2, ("%s\n", __func__));
538
539 s = splnet();
540
541 /* wait for PMT_CTRL[READY] */
542 timo = mstohz(5000); /* XXXX 5sec */
543 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_PMT_CTRL) &
544 LAN9118_PMT_CTRL_READY)) {
545 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_BYTE_TEST,
546 0xbad0c0de);
547 tsleep(&sc, PRIBIO, "lan9118_pmt_ready", 1);
548 if (--timo <= 0) {
549 splx(s);
550 return EBUSY;
551 }
552 }
553
554 /* Soft Reset */
555 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG,
556 LAN9118_HW_CFG_SRST);
557 do {
558 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG);
559 if (reg & LAN9118_HW_CFG_SRST_TO) {
560 aprint_error_dev(sc->sc_dev,
561 "soft reset timeouted out\n");
562 splx(s);
563 return ETIMEDOUT;
564 }
565 } while (reg & LAN9118_HW_CFG_SRST);
566
567 /* Set MAC and PHY CSRs */
568
569 if (sc->sc_flags & LAN9118_FLAGS_SWAP)
570 /* need byte swap */
571 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_WORD_SWAP,
572 0xffffffff);
573
574 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_E2P_CMD) &
575 LAN9118_E2P_CMD_EPCB);
576 if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_E2P_CMD) &
577 LAN9118_E2P_CMD_MACAL)) {
578 lan9118_mac_writereg(sc, LAN9118_ADDRL,
579 sc->sc_enaddr[0] |
580 sc->sc_enaddr[1] << 8 |
581 sc->sc_enaddr[2] << 16 |
582 sc->sc_enaddr[3] << 24);
583 lan9118_mac_writereg(sc, LAN9118_ADDRH,
584 sc->sc_enaddr[4] | sc->sc_enaddr[5] << 8);
585 }
586
587 if (ifm->ifm_media & IFM_FLOW) {
588 lan9118_mac_writereg(sc, LAN9118_FLOW,
589 LAN9118_FLOW_FCPT(1) | LAN9118_FLOW_FCEN);
590 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_AFC_CFG,
591 sc->sc_afc_cfg);
592 }
593
594 lan9118_ifm_change(ifp);
595 hw_cfg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG);
596 hw_cfg &= ~LAN9118_HW_CFG_TX_FIF_MASK;
597 hw_cfg |= LAN9118_HW_CFG_TX_FIF_SZ(LAN9118_TX_FIF_SZ);
598 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG, hw_cfg);
599
600 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_GPIO_CFG,
601 LAN9118_GPIO_CFG_LEDX_EN(2) |
602 LAN9118_GPIO_CFG_LEDX_EN(1) |
603 LAN9118_GPIO_CFG_LEDX_EN(0) |
604 LAN9118_GPIO_CFG_GPIOBUFN(2) |
605 LAN9118_GPIO_CFG_GPIOBUFN(1) |
606 LAN9118_GPIO_CFG_GPIOBUFN(0));
607
608 irq_cfg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_IRQ_CFG);
609 irq_cfg |= LAN9118_IRQ_CFG_IRQ_EN;
610 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_IRQ_CFG, irq_cfg);
611
612 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_STS,
613 bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_STS));
614 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_FIFO_INT,
615 LAN9118_FIFO_INT_TXSL(0) | LAN9118_FIFO_INT_RXSL(0));
616 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_EN,
617 #if 0 /* not yet... */
618 LAN9118_INT_PHY_INT | /* PHY */
619 LAN9118_INT_PME_INT | /* Power Management Event */
620 #endif
621 LAN9118_INT_RXE | /* Receive Error */
622 LAN9118_INT_TSFL | /* TX Status FIFO Level */
623 LAN9118_INT_RXDF_INT| /* RX Dropped Frame Interrupt */
624 LAN9118_INT_RSFF | /* RX Status FIFO Full */
625 LAN9118_INT_RSFL); /* RX Status FIFO Level */
626
627 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_RX_CFG,
628 LAN9118_RX_CFG_RXDOFF(2));
629 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_TX_CFG,
630 LAN9118_TX_CFG_TX_ON);
631 mac_cr = lan9118_mac_readreg(sc, LAN9118_MAC_CR);
632 lan9118_mac_writereg(sc, LAN9118_MAC_CR,
633 mac_cr | LAN9118_MAC_CR_TXEN | LAN9118_MAC_CR_RXEN);
634
635 lan9118_set_filter(sc);
636
637 ifp->if_flags |= IFF_RUNNING;
638 ifp->if_flags &= ~IFF_OACTIVE;
639
640 callout_reset(&sc->sc_tick, hz, lan9118_tick, sc);
641
642 splx(s);
643
644 return 0;
645 }
646
647 static void
lan9118_stop(struct ifnet * ifp,int disable)648 lan9118_stop(struct ifnet *ifp, int disable)
649 {
650 struct lan9118_softc *sc = ifp->if_softc;
651 uint32_t cr;
652
653 DPRINTFN(2, ("%s\n", __func__));
654
655 /* Disable IRQ */
656 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_EN, 0);
657
658 /* Stopping transmitter */
659 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_TX_CFG,
660 LAN9118_TX_CFG_STOP_TX);
661 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_TX_CFG) &
662 (LAN9118_TX_CFG_TX_ON | LAN9118_TX_CFG_STOP_TX));
663
664 /* Purge TX Status/Data FIFOs */
665 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_TX_CFG,
666 LAN9118_TX_CFG_TXS_DUMP | LAN9118_TX_CFG_TXD_DUMP);
667
668 /* Stopping receiver, also clear TXEN */
669 cr = lan9118_mac_readreg(sc, LAN9118_MAC_CR);
670 cr &= ~(LAN9118_MAC_CR_TXEN | LAN9118_MAC_CR_RXEN);
671 lan9118_mac_writereg(sc, LAN9118_MAC_CR, cr);
672 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_INT_STS) &
673 LAN9118_INT_RXSTOP_INT));
674
675 /* Clear RX Status/Data FIFOs */
676 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_RX_CFG,
677 LAN9118_RX_CFG_RX_DUMP);
678
679 callout_stop(&sc->sc_tick);
680 }
681
682 static void
lan9118_watchdog(struct ifnet * ifp)683 lan9118_watchdog(struct ifnet *ifp)
684 {
685 struct lan9118_softc *sc = ifp->if_softc;
686
687 /*
688 * Reclaim first as there is a possibility of losing Tx completion
689 * interrupts.
690 */
691 lan9118_txintr(sc);
692
693 aprint_error_ifnet(ifp, "watchdog timeout\n");
694 if_statinc(ifp, if_oerrors);
695
696 lan9118_init(ifp);
697 }
698
699
700 static int
lan9118_ifm_change(struct ifnet * ifp)701 lan9118_ifm_change(struct ifnet *ifp)
702 {
703 struct lan9118_softc *sc = ifp->if_softc;
704 struct mii_data *mii = &sc->sc_mii;
705 struct ifmedia *ifm = &mii->mii_media;
706 struct ifmedia_entry *ife = ifm->ifm_cur;
707 uint32_t pmt_ctrl;
708
709 DPRINTFN(3, ("%s: ifm inst %d\n", __func__, IFM_INST(ife->ifm_media)));
710
711 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG,
712 LAN9118_HW_CFG_MBO | LAN9118_HW_CFG_PHY_CLK_SEL_CD);
713 delay(1); /* Wait 5 cycle */
714
715 if (IFM_INST(ife->ifm_media) != 0) {
716 /* Use External PHY */
717
718 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG,
719 LAN9118_HW_CFG_MBO |
720 LAN9118_HW_CFG_PHY_CLK_SEL_EMII |
721 LAN9118_HW_CFG_SMI_SEL |
722 LAN9118_HW_CFG_EXT_PHY_EN);
723 delay(1);
724 return mii_mediachg(&sc->sc_mii);
725 }
726
727 /* Setup Internal PHY */
728
729 mii->mii_media_status = IFM_AVALID;
730 mii->mii_media_active = IFM_ETHER;
731
732 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG,
733 LAN9118_HW_CFG_MBO |
734 LAN9118_HW_CFG_PHY_CLK_SEL_IPHY);
735 delay(1);
736
737 /* Reset PHY */
738 pmt_ctrl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_PMT_CTRL);
739 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_PMT_CTRL,
740 pmt_ctrl | LAN9118_PMT_CTRL_PHY_RST);
741 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_PMT_CTRL) &
742 LAN9118_PMT_CTRL_PHY_RST);
743
744 mii_mediachg(&sc->sc_mii);
745 return 0;
746 }
747
748 static void
lan9118_ifm_status(struct ifnet * ifp,struct ifmediareq * ifmr)749 lan9118_ifm_status(struct ifnet *ifp, struct ifmediareq *ifmr)
750 {
751 struct lan9118_softc *sc = ifp->if_softc;
752 struct mii_data *mii = &sc->sc_mii;
753
754 DPRINTFN(3, ("%s\n", __func__));
755
756 mii_pollstat(mii);
757 ifmr->ifm_active = mii->mii_media_active;
758 ifmr->ifm_status = mii->mii_media_status;
759 }
760
761
762 static int
lan9118_miibus_readreg(device_t dev,int phy,int reg,uint16_t * val)763 lan9118_miibus_readreg(device_t dev, int phy, int reg, uint16_t *val)
764 {
765
766 return lan9118_mii_readreg(device_private(dev), phy, reg, val);
767 }
768 static int
lan9118_miibus_writereg(device_t dev,int phy,int reg,uint16_t val)769 lan9118_miibus_writereg(device_t dev, int phy, int reg, uint16_t val)
770 {
771
772 return lan9118_mii_writereg(device_private(dev), phy, reg, val);
773 }
774
775 static void
lan9118_miibus_statchg(struct ifnet * ifp)776 lan9118_miibus_statchg(struct ifnet *ifp)
777 {
778 struct lan9118_softc *sc = ifp->if_softc;
779 u_int cr;
780
781 cr = lan9118_mac_readreg(sc, LAN9118_MAC_CR);
782 if (IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) {
783 cr &= ~LAN9118_MAC_CR_RCVOWN;
784 cr |= LAN9118_MAC_CR_FDPX;
785 } else {
786 cr |= LAN9118_MAC_CR_RCVOWN;
787 cr &= ~LAN9118_MAC_CR_FDPX;
788 }
789 lan9118_mac_writereg(sc, LAN9118_MAC_CR, cr);
790 }
791
792
793 static int
lan9118_mii_readreg(struct lan9118_softc * sc,int phy,int reg,uint16_t * val)794 lan9118_mii_readreg(struct lan9118_softc *sc, int phy, int reg, uint16_t *val)
795 {
796 uint32_t acc;
797
798 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
799 LAN9118_MII_ACC_MIIBZY);
800 acc = LAN9118_MII_ACC_PHYA(phy) | LAN9118_MII_ACC_MIIRINDA(reg);
801 lan9118_mac_writereg(sc, LAN9118_MII_ACC, acc);
802 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
803 LAN9118_MII_ACC_MIIBZY);
804 *val = lan9118_mac_readreg(sc, LAN9118_MII_DATA) & 0xffff;
805 return 0;
806 }
807
808 static int
lan9118_mii_writereg(struct lan9118_softc * sc,int phy,int reg,uint16_t val)809 lan9118_mii_writereg(struct lan9118_softc *sc, int phy, int reg, uint16_t val)
810 {
811 uint32_t acc;
812
813 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
814 LAN9118_MII_ACC_MIIBZY);
815 acc = LAN9118_MII_ACC_PHYA(phy) | LAN9118_MII_ACC_MIIRINDA(reg) |
816 LAN9118_MII_ACC_MIIWNR;
817 lan9118_mac_writereg(sc, LAN9118_MII_DATA, val);
818 lan9118_mac_writereg(sc, LAN9118_MII_ACC, acc);
819 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
820 LAN9118_MII_ACC_MIIBZY);
821
822 return 0;
823 }
824
825 static uint32_t
lan9118_mac_readreg(struct lan9118_softc * sc,int reg)826 lan9118_mac_readreg(struct lan9118_softc *sc, int reg)
827 {
828 uint32_t cmd;
829 int timo = 3 * 1000 * 1000; /* XXXX: 3sec */
830
831 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_CMD,
832 LAN9118_MAC_CSR_CMD_BUSY | LAN9118_MAC_CSR_CMD_R | reg);
833 do {
834 cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
835 LAN9118_MAC_CSR_CMD);
836 if (!(cmd & LAN9118_MAC_CSR_CMD_BUSY))
837 break;
838 delay(100);
839 } while (timo -= 100);
840 if (timo <= 0)
841 aprint_error_dev(sc->sc_dev, "%s: command busy\n", __func__);
842 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_DATA);
843 }
844
845 static void
lan9118_mac_writereg(struct lan9118_softc * sc,int reg,uint32_t val)846 lan9118_mac_writereg(struct lan9118_softc *sc, int reg, uint32_t val)
847 {
848 uint32_t cmd;
849 int timo = 3 * 1000 * 1000; /* XXXX: 3sec */
850
851 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_DATA, val);
852 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_CMD,
853 LAN9118_MAC_CSR_CMD_BUSY | LAN9118_MAC_CSR_CMD_W | reg);
854 do {
855 cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
856 LAN9118_MAC_CSR_CMD);
857 if (!(cmd & LAN9118_MAC_CSR_CMD_BUSY))
858 break;
859 delay(100);
860 } while (timo -= 100);
861 if (timo <= 0)
862 aprint_error_dev(sc->sc_dev, "%s: command busy\n", __func__);
863 }
864
865
866 static void
lan9118_set_filter(struct lan9118_softc * sc)867 lan9118_set_filter(struct lan9118_softc *sc)
868 {
869 struct ethercom *ec = &sc->sc_ec;
870 struct ether_multistep step;
871 struct ether_multi *enm;
872 struct ifnet *ifp = &ec->ec_if;
873 uint32_t mac_cr, h, hashes[2] = { 0, 0 };
874
875 mac_cr = lan9118_mac_readreg(sc, LAN9118_MAC_CR);
876 if (ifp->if_flags & IFF_PROMISC) {
877 lan9118_mac_writereg(sc, LAN9118_MAC_CR,
878 mac_cr | LAN9118_MAC_CR_PRMS);
879 return;
880 }
881
882 mac_cr &= ~(LAN9118_MAC_CR_PRMS | LAN9118_MAC_CR_MCPAS |
883 LAN9118_MAC_CR_BCAST | LAN9118_MAC_CR_HPFILT);
884 if (!(ifp->if_flags & IFF_BROADCAST))
885 mac_cr |= LAN9118_MAC_CR_BCAST;
886
887 if (ifp->if_flags & IFF_ALLMULTI)
888 mac_cr |= LAN9118_MAC_CR_MCPAS;
889 else {
890 ETHER_LOCK(ec);
891 ETHER_FIRST_MULTI(step, ec, enm);
892 while (enm != NULL) {
893 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
894 ETHER_ADDR_LEN) != 0) {
895 /*
896 * We must listen to a range of multicast
897 * addresses. For now, just accept all
898 * multicasts, rather than trying to set
899 * only those filter bits needed to match
900 * the range. (At this time, the only use
901 * of address ranges is for IP multicast
902 * routing, for which the range is big enough
903 * to require all bits set.)
904 */
905 ifp->if_flags |= IFF_ALLMULTI;
906 mac_cr |= LAN9118_MAC_CR_MCPAS;
907 break;
908 }
909 h = ether_crc32_le(enm->enm_addrlo,
910 ETHER_ADDR_LEN) >> 26;
911 hashes[h >> 5] |= 1 << (h & 0x1f);
912
913 mac_cr |= LAN9118_MAC_CR_HPFILT;
914 ETHER_NEXT_MULTI(step, enm);
915 }
916 ETHER_UNLOCK(ec);
917 if (mac_cr & LAN9118_MAC_CR_HPFILT) {
918 lan9118_mac_writereg(sc, LAN9118_HASHH, hashes[1]);
919 lan9118_mac_writereg(sc, LAN9118_HASHL, hashes[0]);
920 }
921 }
922 lan9118_mac_writereg(sc, LAN9118_MAC_CR, mac_cr);
923 return;
924 }
925
926 static void
lan9118_rxintr(struct lan9118_softc * sc)927 lan9118_rxintr(struct lan9118_softc *sc)
928 {
929 struct ifnet *ifp = &sc->sc_ec.ec_if;
930 struct mbuf *m;
931 uint32_t rx_fifo_inf, rx_status;
932 int pktlen;
933 const int pad = ETHER_HDR_LEN % sizeof(uint32_t);
934
935 DPRINTFN(3, ("%s\n", __func__));
936
937 for (;;) {
938 rx_fifo_inf = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
939 LAN9118_RX_FIFO_INF);
940 if (LAN9118_RX_FIFO_INF_RXSUSED(rx_fifo_inf) == 0)
941 break;
942
943 rx_status = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
944 LAN9118_RXSFIFOP);
945 pktlen = LAN9118_RXS_PKTLEN(rx_status);
946 DPRINTFN(3, ("%s: rx_status=0x%x(pktlen %d)\n",
947 __func__, rx_status, pktlen));
948 if (rx_status & (LAN9118_RXS_ES | LAN9118_RXS_LENERR |
949 LAN9118_RXS_RWTO | LAN9118_RXS_MIIERR | LAN9118_RXS_DBIT)) {
950 if (rx_status & LAN9118_RXS_LENERR)
951 aprint_error_dev(sc->sc_dev, "Length Error\n");
952 if (rx_status & LAN9118_RXS_RUNTF)
953 aprint_error_dev(sc->sc_dev, "Runt Frame\n");
954 if (rx_status & LAN9118_RXS_FTL)
955 aprint_error_dev(sc->sc_dev,
956 "Frame Too Long\n");
957 if (rx_status & LAN9118_RXS_RWTO)
958 aprint_error_dev(sc->sc_dev,
959 "Receive Watchdog time-out\n");
960 if (rx_status & LAN9118_RXS_MIIERR)
961 aprint_error_dev(sc->sc_dev, "MII Error\n");
962 if (rx_status & LAN9118_RXS_DBIT)
963 aprint_error_dev(sc->sc_dev, "Drabbling Bit\n");
964 if (rx_status & LAN9118_RXS_COLS)
965 aprint_error_dev(sc->sc_dev,
966 "Collision Seen\n");
967 if (rx_status & LAN9118_RXS_CRCERR)
968 aprint_error_dev(sc->sc_dev, "CRC Error\n");
969
970 dropit:
971 if_statinc(ifp, if_ierrors);
972 /*
973 * Receive Data FIFO Fast Forward
974 * When performing a fast-forward, there must be at
975 * least 4 DWORDs of data in the RX data FIFO for the
976 * packet being discarded.
977 */
978 if (pktlen >= 4 * sizeof(uint32_t)) {
979 uint32_t rx_dp_ctl;
980
981 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
982 LAN9118_RX_DP_CTL,
983 LAN9118_RX_DP_CTL_RX_FFWD);
984 /* DP_FFWD bit is self clearing */
985 do {
986 rx_dp_ctl = bus_space_read_4(sc->sc_iot,
987 sc->sc_ioh, LAN9118_RX_DP_CTL);
988 } while (rx_dp_ctl & LAN9118_RX_DP_CTL_RX_FFWD);
989 } else {
990 /* For less than 4 DWORDs do not use RX_FFWD. */
991 uint32_t garbage[4];
992
993 bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh,
994 LAN9118_RXDFIFOP, garbage,
995 roundup(pktlen, 4) >> 2);
996 }
997 continue;
998 }
999
1000 MGETHDR(m, M_DONTWAIT, MT_DATA);
1001 if (m == NULL)
1002 goto dropit;
1003 if (pktlen > (MHLEN - pad)) {
1004 MCLGET(m, M_DONTWAIT);
1005 if ((m->m_flags & M_EXT) == 0) {
1006 m_freem(m);
1007 goto dropit;
1008 }
1009 }
1010
1011 /* STRICT_ALIGNMENT */
1012 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_RX_CFG,
1013 LAN9118_RX_CFG_RXEA_4B | LAN9118_RX_CFG_RXDOFF(pad));
1014 bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh, LAN9118_RXDFIFOP,
1015 mtod(m, uint32_t *),
1016 roundup(pad + pktlen, sizeof(uint32_t)) >> 2);
1017 m->m_data += pad;
1018
1019 m_set_rcvif(m, ifp);
1020 m->m_pkthdr.len = m->m_len = (pktlen - ETHER_CRC_LEN);
1021
1022 /* Pass it on. */
1023 if_percpuq_enqueue(ifp->if_percpuq, m);
1024 }
1025 }
1026
1027 static void
lan9118_txintr(struct lan9118_softc * sc)1028 lan9118_txintr(struct lan9118_softc *sc)
1029 {
1030 struct ifnet *ifp = &sc->sc_ec.ec_if;
1031 uint32_t tx_fifo_inf, tx_status;
1032 int fdx = IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX;
1033 int tdfree;
1034
1035 DPRINTFN(3, ("%s\n", __func__));
1036
1037 for (;;) {
1038 tx_fifo_inf = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
1039 LAN9118_TX_FIFO_INF);
1040 if (LAN9118_TX_FIFO_INF_TXSUSED(tx_fifo_inf) == 0)
1041 break;
1042
1043 tx_status = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
1044 LAN9118_TXSFIFOP);
1045 DPRINTFN(3, ("%s: tx_status=0x%x\n", __func__, tx_status));
1046 if (tx_status & LAN9118_TXS_ES) {
1047 if (tx_status & LAN9118_TXS_LOC)
1048 aprint_error_dev(sc->sc_dev,
1049 "Loss Of Carrier\n");
1050 if ((tx_status & LAN9118_TXS_NC) && !fdx)
1051 aprint_error_dev(sc->sc_dev, "No Carrier\n");
1052 if (tx_status & LAN9118_TXS_LCOL)
1053 aprint_error_dev(sc->sc_dev,
1054 "Late Collision\n");
1055 if (tx_status & LAN9118_TXS_ECOL) {
1056 /* Rearch 16 collision */
1057 if_statadd(ifp, if_collisions, 16);
1058 aprint_error_dev(sc->sc_dev,
1059 "Excessive Collision\n");
1060 }
1061 if (LAN9118_TXS_COLCNT(tx_status) != 0)
1062 aprint_error_dev(sc->sc_dev,
1063 "Collision Count: %d\n",
1064 LAN9118_TXS_COLCNT(tx_status));
1065 if (tx_status & LAN9118_TXS_ED)
1066 aprint_error_dev(sc->sc_dev,
1067 "Excessive Deferral\n");
1068 if (tx_status & LAN9118_TXS_DEFERRED)
1069 aprint_error_dev(sc->sc_dev, "Deferred\n");
1070 if_statinc(ifp, if_oerrors);
1071 } else
1072 if_statinc(ifp, if_opackets);
1073 }
1074
1075 tdfree = LAN9118_TX_FIFO_INF_TDFREE(tx_fifo_inf);
1076 if (tdfree == LAN9118_TX_DATA_FIFO_SIZE)
1077 /* FIFO empty */
1078 ifp->if_timer = 0;
1079 if (tdfree >= 2036)
1080 /*
1081 * 2036 is the possible maximum FIFO consumption
1082 * for the most fragmented frame.
1083 */
1084 ifp->if_flags &= ~IFF_OACTIVE;
1085 }
1086
1087 void
lan9118_tick(void * v)1088 lan9118_tick(void *v)
1089 {
1090 struct lan9118_softc *sc = v;
1091 int s;
1092
1093 s = splnet();
1094 mii_tick(&sc->sc_mii);
1095 callout_schedule(&sc->sc_tick, hz);
1096 splx(s);
1097 }
1098