lan9118.c revision 1.6 1 /* $NetBSD: lan9118.c,v 1.6 2009/11/29 05:07:49 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.6 2009/11/29 05:07:49 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 ifmedia *ifm = &sc->sc_mii.mii_media;
697 struct ifmedia_entry *ife = ifm->ifm_cur;
698 uint32_t pmt_ctrl, cr, bmc, bms, ana, anlpa;
699
700 DPRINTFN(3, ("%s: ifm inst %d\n", __func__, IFM_INST(ife->ifm_media)));
701
702 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG,
703 LAN9118_HW_CFG_MBO | LAN9118_HW_CFG_PHY_CLK_SEL_CD);
704 delay(1); /* Wait 5 cycle */
705
706 if (IFM_INST(ife->ifm_media) != 0) {
707 /* Use External PHY */
708
709 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG,
710 LAN9118_HW_CFG_MBO |
711 LAN9118_HW_CFG_PHY_CLK_SEL_EMII |
712 LAN9118_HW_CFG_SMI_SEL |
713 LAN9118_HW_CFG_EXT_PHY_EN);
714 delay(1);
715 return mii_mediachg(&sc->sc_mii);
716 }
717
718 /* Setup Internal PHY */
719
720 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_HW_CFG,
721 LAN9118_HW_CFG_MBO |
722 LAN9118_HW_CFG_PHY_CLK_SEL_IPHY);
723 delay(1);
724
725 /* Reset PHY */
726 pmt_ctrl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_PMT_CTRL);
727 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_PMT_CTRL,
728 pmt_ctrl | LAN9118_PMT_CTRL_PHY_RST);
729 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_PMT_CTRL) &
730 LAN9118_PMT_CTRL_PHY_RST);
731
732 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) {
733 bmc = BMCR_AUTOEN | BMCR_STARTNEG;
734 bms = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, MII_BMSR);
735 ana = ANAR_FC | BMSR_MEDIA_TO_ANAR(bms) | ANAR_CSMA;
736 } else {
737 switch (IFM_SUBTYPE(ifm->ifm_media)) {
738 case IFM_10_T:
739 bmc = BMCR_S10;
740 ana = ANAR_CSMA | ANAR_10;
741 break;
742
743 case IFM_100_TX:
744 bmc = BMCR_S100;
745 if (ifm->ifm_media & IFM_FDX)
746 bmc |= BMCR_FDX;
747 ana = ANAR_CSMA | ANAR_TX;
748 break;
749
750 case IFM_NONE:
751 bmc = BMCR_PDOWN;
752 break;
753
754 default:
755 return EINVAL;
756 }
757 if (ifm->ifm_media & IFM_FDX)
758 bmc |= BMCR_FDX;
759 if (ifm->ifm_media & IFM_FLOW)
760 ana |= ANAR_FC;
761 }
762 lan9118_mii_writereg(sc, LAN9118_IPHY_ADDR, MII_ANAR, ana);
763 lan9118_mii_writereg(sc, LAN9118_IPHY_ADDR, MII_BMCR, bmc);
764
765 bms = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, MII_BMSR);
766 if (bms & BMSR_LINK) {
767 anlpa = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, MII_ANLPAR);
768
769 bmc = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, MII_BMCR);
770 cr = lan9118_mac_readreg(sc, LAN9118_MAC_CR);
771 if (anlpa & (ANLPAR_TX_FD | ANLPAR_10_FD)) {
772 bmc |= BMCR_FDX;
773 cr |= LAN9118_MAC_CR_RCVOWN;
774 } else {
775 bmc &= ~BMCR_FDX;
776 cr &= ~LAN9118_MAC_CR_RCVOWN;
777 }
778 lan9118_mii_writereg(sc, LAN9118_IPHY_ADDR, MII_BMCR, bmc);
779 lan9118_mac_writereg(sc, LAN9118_MAC_CR, cr);
780 }
781 return 0;
782 }
783
784 static void
785 lan9118_ifm_status(struct ifnet *ifp, struct ifmediareq *ifmr)
786 {
787 struct lan9118_softc *sc = ifp->if_softc;
788 struct mii_data *mii = &sc->sc_mii;
789 struct ifmedia *ifm = &mii->mii_media;
790 struct ifmedia_entry *ife = ifm->ifm_cur;
791 uint32_t bms, physcs;
792
793 DPRINTFN(3, ("%s\n", __func__));
794
795 if (IFM_INST(ife->ifm_media) != 0) {
796 mii_pollstat(mii);
797 ifmr->ifm_active = mii->mii_media_active;
798 ifmr->ifm_status = mii->mii_media_status;
799 return;
800 }
801
802 ifmr->ifm_active = IFM_ETHER;
803 ifmr->ifm_status = IFM_AVALID;
804
805 bms = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, MII_BMSR);
806 if (!(bms & BMSR_LINK)) {
807 /* link is down */
808 ifmr->ifm_active |= IFM_NONE;
809 return;
810 }
811 ifmr->ifm_status |= IFM_ACTIVE;
812 physcs = lan9118_mii_readreg(sc, LAN9118_IPHY_ADDR, LAN9118_PHYSCSR);
813 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) {
814 if (!(physcs & LAN9118_PHYSCSR_AUTODONE)) {
815 /* negotiation in progress */
816 ifmr->ifm_active |= IFM_NONE;
817 return;
818 }
819 }
820 if (physcs & LAN9118_PHYSCSR_SI_10)
821 ifmr->ifm_active |= IFM_10_T;
822 if (physcs & LAN9118_PHYSCSR_SI_100)
823 ifmr->ifm_active |= IFM_100_TX;
824 if (physcs & LAN9118_PHYSCSR_SI_FDX)
825 ifmr->ifm_active |= IFM_FDX;
826 }
827
828
829 static int
830 lan9118_miibus_readreg(device_t dev, int phy, int reg)
831 {
832
833 return lan9118_mii_readreg(device_private(dev), phy, reg);
834 }
835 static void
836 lan9118_miibus_writereg(device_t dev, int phy, int reg, int val)
837 {
838
839 lan9118_mii_writereg(device_private(dev), phy, reg, val);
840 }
841
842 static void
843 lan9118_miibus_statchg(device_t dev)
844 {
845
846 /* nothing to do */
847 }
848
849
850 static uint16_t
851 lan9118_mii_readreg(struct lan9118_softc *sc, int phy, int reg)
852 {
853 uint32_t acc;
854
855 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
856 LAN9118_MII_ACC_MIIBZY);
857 acc = LAN9118_MII_ACC_PHYA(phy) | LAN9118_MII_ACC_MIIRINDA(reg);
858 lan9118_mac_writereg(sc, LAN9118_MII_ACC, acc);
859 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
860 LAN9118_MII_ACC_MIIBZY);
861 return lan9118_mac_readreg(sc, LAN9118_MII_DATA);
862 }
863
864 static void
865 lan9118_mii_writereg(struct lan9118_softc *sc, int phy, int reg, uint16_t val)
866 {
867 uint32_t acc;
868
869 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
870 LAN9118_MII_ACC_MIIBZY);
871 acc = LAN9118_MII_ACC_PHYA(phy) | LAN9118_MII_ACC_MIIRINDA(reg) |
872 LAN9118_MII_ACC_MIIWNR;
873 lan9118_mac_writereg(sc, LAN9118_MII_DATA, val);
874 lan9118_mac_writereg(sc, LAN9118_MII_ACC, acc);
875 while (lan9118_mac_readreg(sc, LAN9118_MII_ACC) &
876 LAN9118_MII_ACC_MIIBZY);
877 }
878
879 static uint32_t
880 lan9118_mac_readreg(struct lan9118_softc *sc, int reg)
881 {
882 uint32_t cmd;
883 int timo = 3 * 1000 * 1000; /* XXXX: 3sec */
884
885 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_CMD,
886 LAN9118_MAC_CSR_CMD_BUSY | LAN9118_MAC_CSR_CMD_R | reg);
887 do {
888 cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
889 LAN9118_MAC_CSR_CMD);
890 if (!(cmd & LAN9118_MAC_CSR_CMD_BUSY))
891 break;
892 delay(100);
893 } while (timo -= 100);
894 if (timo <= 0)
895 aprint_error_dev(sc->sc_dev, "%s: command busy\n", __func__);
896 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_DATA);
897 }
898
899 static void
900 lan9118_mac_writereg(struct lan9118_softc *sc, int reg, uint32_t val)
901 {
902 uint32_t cmd;
903 int timo = 3 * 1000 * 1000; /* XXXX: 3sec */
904
905 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_DATA, val);
906 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_MAC_CSR_CMD,
907 LAN9118_MAC_CSR_CMD_BUSY | LAN9118_MAC_CSR_CMD_W | reg);
908 do {
909 cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
910 LAN9118_MAC_CSR_CMD);
911 if (!(cmd & LAN9118_MAC_CSR_CMD_BUSY))
912 break;
913 delay(100);
914 } while (timo -= 100);
915 if (timo <= 0)
916 aprint_error_dev(sc->sc_dev, "%s: command busy\n", __func__);
917 }
918
919
920 static void
921 lan9118_set_filter(struct lan9118_softc *sc)
922 {
923 struct ether_multistep step;
924 struct ether_multi *enm;
925 struct ifnet *ifp = &sc->sc_ec.ec_if;
926 uint32_t mac_cr, h, hashes[2] = { 0, 0 };
927
928 mac_cr = lan9118_mac_readreg(sc, LAN9118_MAC_CR);
929 if (ifp->if_flags & IFF_PROMISC) {
930 lan9118_mac_writereg(sc, LAN9118_MAC_CR,
931 mac_cr | LAN9118_MAC_CR_PRMS);
932 return;
933 }
934
935 mac_cr &= ~(LAN9118_MAC_CR_PRMS | LAN9118_MAC_CR_MCPAS |
936 LAN9118_MAC_CR_BCAST | LAN9118_MAC_CR_HPFILT);
937 if (!(ifp->if_flags & IFF_BROADCAST))
938 mac_cr |= LAN9118_MAC_CR_BCAST;
939
940 if (ifp->if_flags & IFF_ALLMULTI)
941 mac_cr |= LAN9118_MAC_CR_MCPAS;
942 else {
943 ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
944 while (enm != NULL) {
945 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
946 ETHER_ADDR_LEN) != 0) {
947 /*
948 * We must listen to a range of multicast
949 * addresses. For now, just accept all
950 * multicasts, rather than trying to set
951 * only those filter bits needed to match
952 * the range. (At this time, the only use
953 * of address ranges is for IP multicast
954 * routing, for which the range is big enough
955 * to require all bits set.)
956 */
957 ifp->if_flags |= IFF_ALLMULTI;
958 mac_cr |= LAN9118_MAC_CR_MCPAS;
959 break;
960 }
961 h = ether_crc32_le(enm->enm_addrlo,
962 ETHER_ADDR_LEN) >> 26;
963 hashes[h >> 5] |= 1 << (h & 0x1f);
964
965 mac_cr |= LAN9118_MAC_CR_HPFILT;
966 ETHER_NEXT_MULTI(step, enm);
967 }
968 if (mac_cr & LAN9118_MAC_CR_HPFILT) {
969 lan9118_mac_writereg(sc, LAN9118_HASHH, hashes[1]);
970 lan9118_mac_writereg(sc, LAN9118_HASHL, hashes[0]);
971 }
972 }
973 lan9118_mac_writereg(sc, LAN9118_MAC_CR, mac_cr);
974 return;
975 }
976
977 static void
978 lan9118_rxintr(struct lan9118_softc *sc)
979 {
980 struct ifnet *ifp = &sc->sc_ec.ec_if;
981 struct mbuf *m;
982 uint32_t rx_fifo_inf, rx_status;
983 int pktlen;
984 const int pad = ETHER_HDR_LEN % sizeof(uint32_t);
985
986 DPRINTFN(3, ("%s\n", __func__));
987
988 for (;;) {
989 rx_fifo_inf = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
990 LAN9118_RX_FIFO_INF);
991 if (LAN9118_RX_FIFO_INF_RXSUSED(rx_fifo_inf) == 0)
992 break;
993
994 rx_status = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
995 LAN9118_RXSFIFOP);
996 pktlen = LAN9118_RXS_PKTLEN(rx_status);
997 DPRINTFN(3, ("%s: rx_status=0x%x(pktlen %d)\n",
998 __func__, rx_status, pktlen));
999 if (rx_status & (LAN9118_RXS_ES | LAN9118_RXS_LENERR |
1000 LAN9118_RXS_RWTO | LAN9118_RXS_MIIERR | LAN9118_RXS_DBIT)) {
1001 if (rx_status & LAN9118_RXS_LENERR)
1002 aprint_error_dev(sc->sc_dev, "Length Error\n");
1003 if (rx_status & LAN9118_RXS_RUNTF)
1004 aprint_error_dev(sc->sc_dev, "Runt Frame\n");
1005 if (rx_status & LAN9118_RXS_FTL)
1006 aprint_error_dev(sc->sc_dev,
1007 "Frame Too Long\n");
1008 if (rx_status & LAN9118_RXS_RWTO)
1009 aprint_error_dev(sc->sc_dev,
1010 "Receive Watchdog time-out\n");
1011 if (rx_status & LAN9118_RXS_MIIERR)
1012 aprint_error_dev(sc->sc_dev, "MII Error\n");
1013 if (rx_status & LAN9118_RXS_DBIT)
1014 aprint_error_dev(sc->sc_dev, "Drabbling Bit\n");
1015 if (rx_status & LAN9118_RXS_COLS)
1016 aprint_error_dev(sc->sc_dev,
1017 "Collision Seen\n");
1018 if (rx_status & LAN9118_RXS_CRCERR)
1019 aprint_error_dev(sc->sc_dev, "CRC Error\n");
1020
1021 dropit:
1022 ifp->if_ierrors++;
1023 /*
1024 * Receive Data FIFO Fast Forward
1025 * When performing a fast-forward, there must be at
1026 * least 4 DWORDs of data in the RX data FIFO for the
1027 * packet being discarded.
1028 */
1029 if (pktlen >= 4 * sizeof(uint32_t)) {
1030 uint32_t rx_dp_ctl;
1031
1032 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
1033 LAN9118_RX_DP_CTL,
1034 LAN9118_RX_DP_CTL_RX_FFWD);
1035 /* DP_FFWD bit is self clearing */
1036 do {
1037 rx_dp_ctl = bus_space_read_4(sc->sc_iot,
1038 sc->sc_ioh, LAN9118_RX_DP_CTL);
1039 } while (rx_dp_ctl & LAN9118_RX_DP_CTL_RX_FFWD);
1040 } else {
1041 /* For less than 4 DWORDs do not use RX_FFWD. */
1042 uint32_t garbage[4];
1043
1044 bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh,
1045 LAN9118_RXDFIFOP, garbage,
1046 roundup(pktlen, 4) >> 2);
1047 }
1048 continue;
1049 }
1050
1051 MGETHDR(m, M_DONTWAIT, MT_DATA);
1052 if (m == NULL)
1053 goto dropit;
1054 if (pktlen > (MHLEN - pad)) {
1055 MCLGET(m, M_DONTWAIT);
1056 if ((m->m_flags & M_EXT) == 0) {
1057 m_freem(m);
1058 goto dropit;
1059 }
1060 }
1061
1062 /* STRICT_ALIGNMENT */
1063 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LAN9118_RX_CFG,
1064 LAN9118_RX_CFG_RXEA_4B | LAN9118_RX_CFG_RXDOFF(pad));
1065 bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh, LAN9118_RXDFIFOP,
1066 mtod(m, uint32_t *),
1067 roundup(pad + pktlen, sizeof(uint32_t)) >> 2);
1068 m->m_data += pad;
1069
1070 ifp->if_ipackets++;
1071 m->m_pkthdr.rcvif = ifp;
1072 m->m_pkthdr.len = m->m_len = (pktlen - ETHER_CRC_LEN);
1073
1074 #if NBPFILTER > 0
1075 /*
1076 * Pass this up to any BPF listeners, but only
1077 * pass if up the stack if it's for us.
1078 */
1079 if (ifp->if_bpf)
1080 bpf_mtap(ifp->if_bpf, m);
1081 #endif /* NBPFILTER > 0 */
1082
1083 /* Pass it on. */
1084 (*ifp->if_input)(ifp, m);
1085 }
1086 }
1087
1088 static void
1089 lan9118_txintr(struct lan9118_softc *sc)
1090 {
1091 struct ifnet *ifp = &sc->sc_ec.ec_if;
1092 uint32_t tx_fifo_inf, tx_status;
1093 int tdfree;
1094
1095 DPRINTFN(3, ("%s\n", __func__));
1096
1097 for (;;) {
1098 tx_fifo_inf = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
1099 LAN9118_TX_FIFO_INF);
1100 if (LAN9118_TX_FIFO_INF_TXSUSED(tx_fifo_inf) == 0)
1101 break;
1102
1103 tx_status = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
1104 LAN9118_TXSFIFOP);
1105 DPRINTFN(3, ("%s: tx_status=0x%x\n", __func__, tx_status));
1106 if (tx_status & LAN9118_TXS_ES) {
1107 if (tx_status & LAN9118_TXS_LOC)
1108 aprint_error_dev(sc->sc_dev,
1109 "Loss Of Carrier\n");
1110 if (tx_status & LAN9118_TXS_NC)
1111 aprint_error_dev(sc->sc_dev, "No Carrier\n");
1112 if (tx_status & LAN9118_TXS_LCOL)
1113 aprint_error_dev(sc->sc_dev,
1114 "Late Collision\n");
1115 if (tx_status & LAN9118_TXS_ECOL) {
1116 /* Rearch 16 collision */
1117 ifp->if_collisions += 16;
1118 aprint_error_dev(sc->sc_dev,
1119 "Excessive Collision\n");
1120 }
1121 if (LAN9118_TXS_COLCNT(tx_status) != 0)
1122 aprint_error_dev(sc->sc_dev,
1123 "Collision Count: %d\n",
1124 LAN9118_TXS_COLCNT(tx_status));
1125 if (tx_status & LAN9118_TXS_ED)
1126 aprint_error_dev(sc->sc_dev,
1127 "Excessive Deferral\n");
1128 if (tx_status & LAN9118_TXS_DEFERRED)
1129 aprint_error_dev(sc->sc_dev, "Deferred\n");
1130 ifp->if_oerrors++;
1131 } else
1132 ifp->if_opackets++;
1133 }
1134
1135 tdfree = LAN9118_TX_FIFO_INF_TDFREE(tx_fifo_inf);
1136 if (tdfree == LAN9118_TX_DATA_FIFO_SIZE)
1137 /* FIFO empty */
1138 ifp->if_timer = 0;
1139 if (tdfree >= 2036)
1140 /*
1141 * 2036 is the possible maximum FIFO consumption
1142 * for the most fragmented frame.
1143 */
1144 ifp->if_flags &= ~IFF_OACTIVE;
1145 }
1146
1147 void
1148 lan9118_tick(void *v)
1149 {
1150 struct lan9118_softc *sc = v;
1151 int s;
1152
1153 s = splnet();
1154 mii_tick(&sc->sc_mii);
1155 callout_schedule(&sc->sc_tick, hz);
1156 splx(s);
1157 }
1158