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