1 /* $NetBSD: lan9118.c,v 1.11 2009/12/06 12:22:17 kiyohara Exp $ */
3 * Copyright (c) 2008 KIYOHARA Takashi
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: lan9118.c,v 1.11 2009/12/06 12:22:17 kiyohara Exp $");
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.
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.
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.
47 * Also support HP Auto-MDIX.
53 #include <sys/param.h>
54 #include <sys/callout.h>
55 #include <sys/device.h>
56 #include <sys/errno.h>
58 #include <sys/ioctl.h>
59 #include <sys/kernel.h>
61 #include <sys/systm.h>
64 #include <net/if_ether.h>
65 #include <net/if_media.h>
67 #include <dev/mii/mii.h>
68 #include <dev/mii/miivar.h>
77 #include <dev/ic/lan9118reg.h>
78 #include <dev/ic/lan9118var.h>
82 #define DPRINTF(x) if (smsh_debug) printf x
83 #define DPRINTFN(n,x) if (smsh_debug >= (n)) printf x
84 int smsh_debug
= SMSH_DEBUG
;
91 static void lan9118_start(struct ifnet
*);
92 static int lan9118_ioctl(struct ifnet
*, u_long
, void *);
93 static int lan9118_init(struct ifnet
*);
94 static void lan9118_stop(struct ifnet
*, int);
95 static void lan9118_watchdog(struct ifnet
*);
97 static int lan9118_ifm_change(struct ifnet
*);
98 static void lan9118_ifm_status(struct ifnet
*, struct ifmediareq
*);
100 static int lan9118_miibus_readreg(device_t
, int, int);
101 static void lan9118_miibus_writereg(device_t
, int, int, int);
102 static void lan9118_miibus_statchg(device_t
);
104 static uint16_t lan9118_mii_readreg(struct lan9118_softc
*, int, int);
105 static void lan9118_mii_writereg(struct lan9118_softc
*, int, int, uint16_t);
106 static uint32_t lan9118_mac_readreg(struct lan9118_softc
*, int);
107 static void lan9118_mac_writereg(struct lan9118_softc
*, int, uint32_t);
109 static void lan9118_set_filter(struct lan9118_softc
*);
110 static void lan9118_rxintr(struct lan9118_softc
*);
111 static void lan9118_txintr(struct lan9118_softc
*);
113 static void lan9118_tick(void *);
115 /* This values refer from Linux's smc911x.c */
116 static uint32_t afc_cfg
[] = {
119 /* 2 */ 0x008c4600 | LAN9118_AFC_CFG_BACK_DUR(10) |
120 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
121 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
122 /* 3 */ 0x00824100 | LAN9118_AFC_CFG_BACK_DUR(9) |
123 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
124 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
125 /* 4 */ 0x00783c00 | LAN9118_AFC_CFG_BACK_DUR(9) |
126 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
127 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
128 /* 5 */ 0x006e3700 | LAN9118_AFC_CFG_BACK_DUR(8) |
129 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
130 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
131 /* 6 */ 0x00643200 | LAN9118_AFC_CFG_BACK_DUR(8) |
132 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
133 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
134 /* 7 */ 0x005a2d00 | LAN9118_AFC_CFG_BACK_DUR(7) |
135 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
136 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
137 /* 8 */ 0x00502800 | LAN9118_AFC_CFG_BACK_DUR(7) |
138 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
139 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
140 /* 9 */ 0x00462300 | LAN9118_AFC_CFG_BACK_DUR(6) |
141 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
142 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
143 /* a */ 0x003c1e00 | LAN9118_AFC_CFG_BACK_DUR(6) |
144 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
145 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
146 /* b */ 0x00321900 | LAN9118_AFC_CFG_BACK_DUR(5) |
147 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
148 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
149 /* c */ 0x00241200 | LAN9118_AFC_CFG_BACK_DUR(4) |
150 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
151 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
152 /* d */ 0x00150700 | LAN9118_AFC_CFG_BACK_DUR(3) |
153 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
154 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
155 /* e */ 0x00060300 | LAN9118_AFC_CFG_BACK_DUR(2) |
156 LAN9118_AFC_CFG_FCMULT
| LAN9118_AFC_CFG_FCBRD
|
157 LAN9118_AFC_CFG_FCADD
| LAN9118_AFC_CFG_FCANY
,
163 lan9118_attach(struct lan9118_softc
*sc
)
165 struct ifnet
*ifp
= &sc
->sc_ec
.ec_if
;
169 if (sc
->sc_flags
& LAN9118_FLAGS_SWAP
)
171 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_WORD_SWAP
,
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(": failed to detect chip\n");
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
);
183 #define LAN9xxx_ID(id) \
184 (IS_LAN9118(id) ? (id) : (IS_LAN9218(id) ? ((id) >> 4) + 0x100 : (id) & 0xfff))
186 aprint_normal(": SMSC LAN9%03x Rev %d\n",
187 LAN9xxx_ID(sc
->sc_id
), sc
->sc_rev
);
189 if (sc
->sc_flags
& LAN9118_FLAGS_SWAP
)
190 aprint_normal_dev(sc
->sc_dev
, "byte swap mode\n");
192 timo
= 3 * 1000 * 1000; /* XXXX 3sec */
194 val
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
195 LAN9118_MAC_CSR_CMD
);
196 if (!(val
& LAN9118_MAC_CSR_CMD_BUSY
))
199 } while (timo
-= 100);
201 aprint_error_dev(sc
->sc_dev
, "%s: command busy\n", __func__
);
202 if (!(sc
->sc_flags
& LAN9118_FLAGS_NO_EEPROM
)) {
203 /* Read auto-loaded MAC address */
204 val
= lan9118_mac_readreg(sc
, LAN9118_ADDRL
);
205 sc
->sc_enaddr
[3] = (val
>> 24) & 0xff;
206 sc
->sc_enaddr
[2] = (val
>> 16) & 0xff;
207 sc
->sc_enaddr
[1] = (val
>> 8) & 0xff;
208 sc
->sc_enaddr
[0] = val
& 0xff;
209 val
= lan9118_mac_readreg(sc
, LAN9118_ADDRH
);
210 sc
->sc_enaddr
[5] = (val
>> 8) & 0xff;
211 sc
->sc_enaddr
[4] = val
& 0xff;
213 aprint_normal_dev(sc
->sc_dev
, "MAC address %s\n",
214 ether_sprintf(sc
->sc_enaddr
));
216 KASSERT(LAN9118_TX_FIF_SZ
>= 2 && LAN9118_TX_FIF_SZ
< 15);
217 sc
->sc_afc_cfg
= afc_cfg
[LAN9118_TX_FIF_SZ
];
219 /* Initialize the ifnet structure. */
220 strlcpy(ifp
->if_xname
, device_xname(sc
->sc_dev
), IFNAMSIZ
);
222 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
;
223 ifp
->if_start
= lan9118_start
;
224 ifp
->if_ioctl
= lan9118_ioctl
;
225 ifp
->if_init
= lan9118_init
;
226 ifp
->if_stop
= lan9118_stop
;
227 ifp
->if_watchdog
= lan9118_watchdog
;
228 IFQ_SET_READY(&ifp
->if_snd
);
230 #if 0 /* Not support 802.1Q VLAN-sized frames yet. */
231 sc
->sc_ec
.ec_capabilities
|= ETHERCAP_VLAN_MTU
;
234 ifmedia_init(&sc
->sc_mii
.mii_media
, 0,
235 lan9118_ifm_change
, lan9118_ifm_status
);
236 sc
->sc_mii
.mii_ifp
= ifp
;
237 sc
->sc_mii
.mii_readreg
= lan9118_miibus_readreg
;
238 sc
->sc_mii
.mii_writereg
= lan9118_miibus_writereg
;
239 sc
->sc_mii
.mii_statchg
= lan9118_miibus_statchg
;
242 * Number of instance of Internal PHY is always 0. External PHY
245 mii_attach(sc
->sc_dev
, &sc
->sc_mii
, 0xffffffff, 1, MII_OFFSET_ANY
, 0);
247 if (sc
->sc_id
== LAN9118_ID_9115
|| sc
->sc_id
== LAN9118_ID_9117
||
248 sc
->sc_id
== LAN9218_ID_9215
|| sc
->sc_id
== LAN9218_ID_9217
) {
249 if (bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_HW_CFG
) &
250 LAN9118_HW_CFG_EXT_PHY_DET
) {
252 * We always have a internal PHY at phy1.
253 * In addition, external PHY is attached.
255 DPRINTFN(1, ("%s: detect External PHY\n", __func__
));
257 /* Switch MII and SMI */
258 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
,
261 LAN9118_HW_CFG_PHY_CLK_SEL_CD
);
262 delay(1); /* Wait 5 cycle */
263 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
,
266 LAN9118_HW_CFG_PHY_CLK_SEL_EMII
|
267 LAN9118_HW_CFG_SMI_SEL
|
268 LAN9118_HW_CFG_EXT_PHY_EN
);
269 delay(1); /* Once wait more 5 cycle */
271 /* Call mii_attach, avoid at phy1. */
272 mii_attach(sc
->sc_dev
, &sc
->sc_mii
, 0xffffffff,
273 0, MII_OFFSET_ANY
, 0);
274 for (i
= 2; i
< MII_NPHY
; i
++)
275 mii_attach(sc
->sc_dev
, &sc
->sc_mii
, 0xffffffff,
276 i
, MII_OFFSET_ANY
, 0);
280 ifmedia_set(&sc
->sc_mii
.mii_media
, IFM_ETHER
| IFM_AUTO
);
282 /* Attach the interface. */
284 ether_ifattach(ifp
, sc
->sc_enaddr
);
286 callout_init(&sc
->sc_tick
, 0);
289 rnd_attach_source(&sc
->rnd_source
, device_xname(sc
->sc_dev
),
296 lan9118_intr(void *arg
)
298 struct lan9118_softc
*sc
= (struct lan9118_softc
*)arg
;
299 struct ifnet
*ifp
= &sc
->sc_ec
.ec_if
;
300 uint32_t int_sts
, int_en
, datum
= 0;
305 bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_INT_STS
);
306 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_INT_STS
,
309 bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_INT_EN
);
311 DPRINTFN(3, ("%s: int_sts=0x%x, int_en=0x%x\n",
312 __func__
, int_sts
, int_en
));
314 if (!(int_sts
& int_en
))
318 #if 0 /* not yet... */
319 if (int_sts
& LAN9118_INT_PHY_INT
) { /* PHY */
322 if (int_sts
& LAN9118_INT_PME_INT
) { /*Power Management Event*/
326 if (int_sts
& LAN9118_INT_RXE
) {
328 aprint_error_ifnet(ifp
, "Receive Error\n");
330 if (int_sts
& LAN9118_INT_TSFL
) /* TX Status FIFO Level */
332 if (int_sts
& LAN9118_INT_RXDF_INT
) {
334 aprint_error_ifnet(ifp
, "RX Dropped Frame Interrupt\n");
336 if (int_sts
& LAN9118_INT_RSFF
) {
338 aprint_error_ifnet(ifp
, "RX Status FIFO Full\n");
340 if (int_sts
& LAN9118_INT_RSFL
) /* RX Status FIFO Level */
344 if (!IFQ_IS_EMPTY(&ifp
->if_snd
))
348 if (RND_ENABLED(&sc
->rnd_source
))
349 rnd_add_uint32(&sc
->rnd_source
, datum
);
357 lan9118_start(struct ifnet
*ifp
)
359 struct lan9118_softc
*sc
= ifp
->if_softc
;
361 unsigned tdfree
, totlen
, dso
;
366 DPRINTFN(3, ("%s\n", __func__
));
368 if ((ifp
->if_flags
& (IFF_RUNNING
| IFF_OACTIVE
)) != IFF_RUNNING
)
373 IFQ_POLL(&ifp
->if_snd
, m0
);
377 tdfree
= LAN9118_TX_FIFO_INF_TDFREE(bus_space_read_4(sc
->sc_iot
,
378 sc
->sc_ioh
, LAN9118_TX_FIFO_INF
));
381 * 2036 is the possible maximum FIFO consumption
382 * for the most fragmented frame.
384 ifp
->if_flags
|= IFF_OACTIVE
;
388 IFQ_DEQUEUE(&ifp
->if_snd
, m0
);
391 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
395 * Check mbuf chain -- "middle" buffers must be >= 4 bytes
396 * and maximum # of buffers is 86.
401 if (m
->m_len
< 4 || ++n
> 86) {
402 /* Copy mbuf chain. */
403 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
405 goto discard
; /* discard packet */
406 MCLGET(m
, M_DONTWAIT
);
407 if ((m
->m_flags
& M_EXT
) == 0) {
409 goto discard
; /* discard packet */
411 m_copydata(m0
, 0, m0
->m_pkthdr
.len
,
413 m
->m_pkthdr
.len
= m
->m_len
= m0
->m_pkthdr
.len
;
422 totlen
= m
->m_pkthdr
.len
;
423 p
= mtod(m
, uint8_t *);
424 dso
= (unsigned)p
& 0x3;
426 LAN9118_TXC_A_BEA_4B
|
427 LAN9118_TXC_A_DSO(dso
) |
429 LAN9118_TXC_A_BS(m
->m_len
);
430 txb
= LAN9118_TXC_B_PL(totlen
);
431 while (m
->m_next
!= NULL
) {
432 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
,
433 LAN9118_TXDFIFOP
, txa
);
434 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
,
435 LAN9118_TXDFIFOP
, txb
);
436 bus_space_write_multi_4(sc
->sc_iot
, sc
->sc_ioh
,
437 LAN9118_TXDFIFOP
, (uint32_t *)(p
- dso
),
438 (m
->m_len
+ dso
+ 3) >> 2);
441 p
= mtod(m
, uint8_t *);
442 dso
= (unsigned)p
& 0x3;
444 LAN9118_TXC_A_BEA_4B
|
445 LAN9118_TXC_A_DSO(dso
) |
446 LAN9118_TXC_A_BS(m
->m_len
);
448 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_TXDFIFOP
,
449 txa
| LAN9118_TXC_A_LS
);
450 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_TXDFIFOP
,
452 bus_space_write_multi_4(sc
->sc_iot
, sc
->sc_ioh
,
453 LAN9118_TXDFIFOP
, (uint32_t *)(p
- dso
),
454 (m
->m_len
+ dso
+ 3) >> 2);
459 * Pass the packet to any BPF listeners.
462 bpf_mtap(ifp
->if_bpf
, m0
);
463 #endif /* NBPFILTER > 0 */
472 lan9118_ioctl(struct ifnet
*ifp
, u_long command
, void *data
)
474 struct lan9118_softc
*sc
= ifp
->if_softc
;
475 struct ifreq
*ifr
= data
;
476 struct mii_data
*mii
= &sc
->sc_mii
;
483 DPRINTFN(2, ("%s: IFFLAGS\n", __func__
));
484 if ((error
= ifioctl_common(ifp
, command
, data
)) != 0)
486 switch (ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) {
488 lan9118_stop(ifp
, 0);
493 case IFF_UP
|IFF_RUNNING
:
494 lan9118_set_filter(sc
);
504 DPRINTFN(2, ("%s: MEDIA\n", __func__
));
505 error
= ifmedia_ioctl(ifp
, ifr
, &mii
->mii_media
, command
);
509 DPRINTFN(2, ("%s: ETHER\n", __func__
));
510 error
= ether_ioctl(ifp
, command
, data
);
511 if (error
== ENETRESET
) {
512 if (ifp
->if_flags
& IFF_RUNNING
) {
513 lan9118_set_filter(sc
);
514 DPRINTFN(2, ("%s set_filter called\n",
528 lan9118_init(struct ifnet
*ifp
)
530 struct lan9118_softc
*sc
= ifp
->if_softc
;
531 struct ifmedia
*ifm
= &sc
->sc_mii
.mii_media
;
532 uint32_t reg
, hw_cfg
, mac_cr
;
535 DPRINTFN(2, ("%s\n", __func__
));
539 /* wait for PMT_CTRL[READY] */
540 timo
= mstohz(5000); /* XXXX 5sec */
541 while (!(bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_PMT_CTRL
) &
542 LAN9118_PMT_CTRL_READY
)) {
543 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_BYTE_TEST
,
545 tsleep(&sc
, PRIBIO
, "lan9118_pmt_ready", 1);
553 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_HW_CFG
,
554 LAN9118_HW_CFG_SRST
);
556 reg
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_HW_CFG
);
557 if (reg
& LAN9118_HW_CFG_SRST_TO
) {
558 aprint_error_dev(sc
->sc_dev
,
559 "soft reset timeouted out\n");
563 } while (reg
& LAN9118_HW_CFG_SRST
);
565 /* Set MAC and PHY CSRs */
567 if (sc
->sc_flags
& LAN9118_FLAGS_SWAP
)
569 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_WORD_SWAP
,
572 while (bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_E2P_CMD
) &
573 LAN9118_E2P_CMD_EPCB
);
574 if (!(bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_E2P_CMD
) &
575 LAN9118_E2P_CMD_MACAL
)) {
576 lan9118_mac_writereg(sc
, LAN9118_ADDRL
,
578 sc
->sc_enaddr
[1] << 8 |
579 sc
->sc_enaddr
[2] << 16 |
580 sc
->sc_enaddr
[3] << 24);
581 lan9118_mac_writereg(sc
, LAN9118_ADDRH
,
582 sc
->sc_enaddr
[4] | sc
->sc_enaddr
[5] << 8);
585 if (ifm
->ifm_media
& IFM_FLOW
) {
586 lan9118_mac_writereg(sc
, LAN9118_FLOW
,
587 LAN9118_FLOW_FCPT(1) | LAN9118_FLOW_FCEN
);
588 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_AFC_CFG
,
592 lan9118_ifm_change(ifp
);
593 hw_cfg
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_HW_CFG
);
594 hw_cfg
&= ~LAN9118_HW_CFG_TX_FIF_MASK
;
595 hw_cfg
|= LAN9118_HW_CFG_TX_FIF_SZ(LAN9118_TX_FIF_SZ
);
596 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_HW_CFG
, hw_cfg
);
598 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_GPIO_CFG
,
599 LAN9118_GPIO_CFG_LEDX_EN(2) |
600 LAN9118_GPIO_CFG_LEDX_EN(1) |
601 LAN9118_GPIO_CFG_LEDX_EN(0) |
602 LAN9118_GPIO_CFG_GPIOBUFN(2) |
603 LAN9118_GPIO_CFG_GPIOBUFN(1) |
604 LAN9118_GPIO_CFG_GPIOBUFN(0));
606 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_IRQ_CFG
,
607 LAN9118_IRQ_CFG_IRQ_EN
);
608 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_INT_STS
,
609 bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_INT_STS
));
610 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_FIFO_INT
,
611 LAN9118_FIFO_INT_TXSL(0) | LAN9118_FIFO_INT_RXSL(0));
612 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_INT_EN
,
613 #if 0 /* not yet... */
614 LAN9118_INT_PHY_INT
| /* PHY */
615 LAN9118_INT_PME_INT
| /* Power Management Event */
617 LAN9118_INT_RXE
| /* Receive Error */
618 LAN9118_INT_TSFL
| /* TX Status FIFO Level */
619 LAN9118_INT_RXDF_INT
| /* RX Dropped Frame Interrupt */
620 LAN9118_INT_RSFF
| /* RX Status FIFO Full */
621 LAN9118_INT_RSFL
); /* RX Status FIFO Level */
623 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_RX_CFG
,
624 LAN9118_RX_CFG_RXDOFF(2));
625 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_TX_CFG
,
626 LAN9118_TX_CFG_TX_ON
);
627 mac_cr
= lan9118_mac_readreg(sc
, LAN9118_MAC_CR
);
628 lan9118_mac_writereg(sc
, LAN9118_MAC_CR
,
629 mac_cr
| LAN9118_MAC_CR_TXEN
| LAN9118_MAC_CR_RXEN
);
631 lan9118_set_filter(sc
);
633 ifp
->if_flags
|= IFF_RUNNING
;
634 ifp
->if_flags
&= ~IFF_OACTIVE
;
636 callout_reset(&sc
->sc_tick
, hz
, lan9118_tick
, sc
);
644 lan9118_stop(struct ifnet
*ifp
, int disable
)
646 struct lan9118_softc
*sc
= ifp
->if_softc
;
649 DPRINTFN(2, ("%s\n", __func__
));
652 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_INT_EN
, 0);
654 /* Stopping transmitter */
655 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_TX_CFG
,
656 LAN9118_TX_CFG_STOP_TX
);
657 while (bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_TX_CFG
) &
658 (LAN9118_TX_CFG_TX_ON
| LAN9118_TX_CFG_STOP_TX
));
660 /* Purge TX Status/Data FIFOs */
661 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_TX_CFG
,
662 LAN9118_TX_CFG_TXS_DUMP
| LAN9118_TX_CFG_TXD_DUMP
);
664 /* Stopping receiver, also clear TXEN */
665 cr
= lan9118_mac_readreg(sc
, LAN9118_MAC_CR
);
666 cr
&= ~(LAN9118_MAC_CR_TXEN
| LAN9118_MAC_CR_RXEN
);
667 lan9118_mac_writereg(sc
, LAN9118_MAC_CR
, cr
);
668 while (!(bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_INT_STS
) &
669 LAN9118_INT_RXSTOP_INT
));
671 /* Clear RX Status/Data FIFOs */
672 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_RX_CFG
,
673 LAN9118_RX_CFG_RX_DUMP
);
675 callout_stop(&sc
->sc_tick
);
679 lan9118_watchdog(struct ifnet
*ifp
)
681 struct lan9118_softc
*sc
= ifp
->if_softc
;
684 * Reclaim first as there is a possibility of losing Tx completion
689 aprint_error_ifnet(ifp
, "watchdog timeout\n");
697 lan9118_ifm_change(struct ifnet
*ifp
)
699 struct lan9118_softc
*sc
= ifp
->if_softc
;
700 struct mii_data
*mii
= &sc
->sc_mii
;
701 struct ifmedia
*ifm
= &mii
->mii_media
;
702 struct ifmedia_entry
*ife
= ifm
->ifm_cur
;
705 DPRINTFN(3, ("%s: ifm inst %d\n", __func__
, IFM_INST(ife
->ifm_media
)));
707 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_HW_CFG
,
708 LAN9118_HW_CFG_MBO
| LAN9118_HW_CFG_PHY_CLK_SEL_CD
);
709 delay(1); /* Wait 5 cycle */
711 if (IFM_INST(ife
->ifm_media
) != 0) {
712 /* Use External PHY */
714 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_HW_CFG
,
716 LAN9118_HW_CFG_PHY_CLK_SEL_EMII
|
717 LAN9118_HW_CFG_SMI_SEL
|
718 LAN9118_HW_CFG_EXT_PHY_EN
);
720 return mii_mediachg(&sc
->sc_mii
);
723 /* Setup Internal PHY */
725 mii
->mii_media_status
= IFM_AVALID
;
726 mii
->mii_media_active
= IFM_ETHER
;
728 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_HW_CFG
,
730 LAN9118_HW_CFG_PHY_CLK_SEL_IPHY
);
734 pmt_ctrl
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_PMT_CTRL
);
735 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_PMT_CTRL
,
736 pmt_ctrl
| LAN9118_PMT_CTRL_PHY_RST
);
737 while (bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_PMT_CTRL
) &
738 LAN9118_PMT_CTRL_PHY_RST
);
740 mii_mediachg(&sc
->sc_mii
);
745 lan9118_ifm_status(struct ifnet
*ifp
, struct ifmediareq
*ifmr
)
747 struct lan9118_softc
*sc
= ifp
->if_softc
;
748 struct mii_data
*mii
= &sc
->sc_mii
;
750 DPRINTFN(3, ("%s\n", __func__
));
753 ifmr
->ifm_active
= mii
->mii_media_active
;
754 ifmr
->ifm_status
= mii
->mii_media_status
;
759 lan9118_miibus_readreg(device_t dev
, int phy
, int reg
)
762 return lan9118_mii_readreg(device_private(dev
), phy
, reg
);
765 lan9118_miibus_writereg(device_t dev
, int phy
, int reg
, int val
)
768 lan9118_mii_writereg(device_private(dev
), phy
, reg
, val
);
772 lan9118_miibus_statchg(device_t dev
)
774 struct lan9118_softc
*sc
= device_private(dev
);
777 cr
= lan9118_mac_readreg(sc
, LAN9118_MAC_CR
);
778 if (IFM_OPTIONS(sc
->sc_mii
.mii_media_active
) & IFM_FDX
) {
779 cr
&= ~LAN9118_MAC_CR_RCVOWN
;
780 cr
|= LAN9118_MAC_CR_FDPX
;
782 cr
|= LAN9118_MAC_CR_RCVOWN
;
783 cr
&= ~LAN9118_MAC_CR_FDPX
;
785 lan9118_mac_writereg(sc
, LAN9118_MAC_CR
, cr
);
790 lan9118_mii_readreg(struct lan9118_softc
*sc
, int phy
, int reg
)
794 while (lan9118_mac_readreg(sc
, LAN9118_MII_ACC
) &
795 LAN9118_MII_ACC_MIIBZY
);
796 acc
= LAN9118_MII_ACC_PHYA(phy
) | LAN9118_MII_ACC_MIIRINDA(reg
);
797 lan9118_mac_writereg(sc
, LAN9118_MII_ACC
, acc
);
798 while (lan9118_mac_readreg(sc
, LAN9118_MII_ACC
) &
799 LAN9118_MII_ACC_MIIBZY
);
800 return lan9118_mac_readreg(sc
, LAN9118_MII_DATA
);
804 lan9118_mii_writereg(struct lan9118_softc
*sc
, int phy
, int reg
, uint16_t val
)
808 while (lan9118_mac_readreg(sc
, LAN9118_MII_ACC
) &
809 LAN9118_MII_ACC_MIIBZY
);
810 acc
= LAN9118_MII_ACC_PHYA(phy
) | LAN9118_MII_ACC_MIIRINDA(reg
) |
811 LAN9118_MII_ACC_MIIWNR
;
812 lan9118_mac_writereg(sc
, LAN9118_MII_DATA
, val
);
813 lan9118_mac_writereg(sc
, LAN9118_MII_ACC
, acc
);
814 while (lan9118_mac_readreg(sc
, LAN9118_MII_ACC
) &
815 LAN9118_MII_ACC_MIIBZY
);
819 lan9118_mac_readreg(struct lan9118_softc
*sc
, int reg
)
822 int timo
= 3 * 1000 * 1000; /* XXXX: 3sec */
824 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_MAC_CSR_CMD
,
825 LAN9118_MAC_CSR_CMD_BUSY
| LAN9118_MAC_CSR_CMD_R
| reg
);
827 cmd
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
828 LAN9118_MAC_CSR_CMD
);
829 if (!(cmd
& LAN9118_MAC_CSR_CMD_BUSY
))
832 } while (timo
-= 100);
834 aprint_error_dev(sc
->sc_dev
, "%s: command busy\n", __func__
);
835 return bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_MAC_CSR_DATA
);
839 lan9118_mac_writereg(struct lan9118_softc
*sc
, int reg
, uint32_t val
)
842 int timo
= 3 * 1000 * 1000; /* XXXX: 3sec */
844 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_MAC_CSR_DATA
, val
);
845 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_MAC_CSR_CMD
,
846 LAN9118_MAC_CSR_CMD_BUSY
| LAN9118_MAC_CSR_CMD_W
| reg
);
848 cmd
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
849 LAN9118_MAC_CSR_CMD
);
850 if (!(cmd
& LAN9118_MAC_CSR_CMD_BUSY
))
853 } while (timo
-= 100);
855 aprint_error_dev(sc
->sc_dev
, "%s: command busy\n", __func__
);
860 lan9118_set_filter(struct lan9118_softc
*sc
)
862 struct ether_multistep step
;
863 struct ether_multi
*enm
;
864 struct ifnet
*ifp
= &sc
->sc_ec
.ec_if
;
865 uint32_t mac_cr
, h
, hashes
[2] = { 0, 0 };
867 mac_cr
= lan9118_mac_readreg(sc
, LAN9118_MAC_CR
);
868 if (ifp
->if_flags
& IFF_PROMISC
) {
869 lan9118_mac_writereg(sc
, LAN9118_MAC_CR
,
870 mac_cr
| LAN9118_MAC_CR_PRMS
);
874 mac_cr
&= ~(LAN9118_MAC_CR_PRMS
| LAN9118_MAC_CR_MCPAS
|
875 LAN9118_MAC_CR_BCAST
| LAN9118_MAC_CR_HPFILT
);
876 if (!(ifp
->if_flags
& IFF_BROADCAST
))
877 mac_cr
|= LAN9118_MAC_CR_BCAST
;
879 if (ifp
->if_flags
& IFF_ALLMULTI
)
880 mac_cr
|= LAN9118_MAC_CR_MCPAS
;
882 ETHER_FIRST_MULTI(step
, &sc
->sc_ec
, enm
);
883 while (enm
!= NULL
) {
884 if (memcmp(enm
->enm_addrlo
, enm
->enm_addrhi
,
885 ETHER_ADDR_LEN
) != 0) {
887 * We must listen to a range of multicast
888 * addresses. For now, just accept all
889 * multicasts, rather than trying to set
890 * only those filter bits needed to match
891 * the range. (At this time, the only use
892 * of address ranges is for IP multicast
893 * routing, for which the range is big enough
894 * to require all bits set.)
896 ifp
->if_flags
|= IFF_ALLMULTI
;
897 mac_cr
|= LAN9118_MAC_CR_MCPAS
;
900 h
= ether_crc32_le(enm
->enm_addrlo
,
901 ETHER_ADDR_LEN
) >> 26;
902 hashes
[h
>> 5] |= 1 << (h
& 0x1f);
904 mac_cr
|= LAN9118_MAC_CR_HPFILT
;
905 ETHER_NEXT_MULTI(step
, enm
);
907 if (mac_cr
& LAN9118_MAC_CR_HPFILT
) {
908 lan9118_mac_writereg(sc
, LAN9118_HASHH
, hashes
[1]);
909 lan9118_mac_writereg(sc
, LAN9118_HASHL
, hashes
[0]);
912 lan9118_mac_writereg(sc
, LAN9118_MAC_CR
, mac_cr
);
917 lan9118_rxintr(struct lan9118_softc
*sc
)
919 struct ifnet
*ifp
= &sc
->sc_ec
.ec_if
;
921 uint32_t rx_fifo_inf
, rx_status
;
923 const int pad
= ETHER_HDR_LEN
% sizeof(uint32_t);
925 DPRINTFN(3, ("%s\n", __func__
));
928 rx_fifo_inf
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
929 LAN9118_RX_FIFO_INF
);
930 if (LAN9118_RX_FIFO_INF_RXSUSED(rx_fifo_inf
) == 0)
933 rx_status
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
935 pktlen
= LAN9118_RXS_PKTLEN(rx_status
);
936 DPRINTFN(3, ("%s: rx_status=0x%x(pktlen %d)\n",
937 __func__
, rx_status
, pktlen
));
938 if (rx_status
& (LAN9118_RXS_ES
| LAN9118_RXS_LENERR
|
939 LAN9118_RXS_RWTO
| LAN9118_RXS_MIIERR
| LAN9118_RXS_DBIT
)) {
940 if (rx_status
& LAN9118_RXS_LENERR
)
941 aprint_error_dev(sc
->sc_dev
, "Length Error\n");
942 if (rx_status
& LAN9118_RXS_RUNTF
)
943 aprint_error_dev(sc
->sc_dev
, "Runt Frame\n");
944 if (rx_status
& LAN9118_RXS_FTL
)
945 aprint_error_dev(sc
->sc_dev
,
947 if (rx_status
& LAN9118_RXS_RWTO
)
948 aprint_error_dev(sc
->sc_dev
,
949 "Receive Watchdog time-out\n");
950 if (rx_status
& LAN9118_RXS_MIIERR
)
951 aprint_error_dev(sc
->sc_dev
, "MII Error\n");
952 if (rx_status
& LAN9118_RXS_DBIT
)
953 aprint_error_dev(sc
->sc_dev
, "Drabbling Bit\n");
954 if (rx_status
& LAN9118_RXS_COLS
)
955 aprint_error_dev(sc
->sc_dev
,
957 if (rx_status
& LAN9118_RXS_CRCERR
)
958 aprint_error_dev(sc
->sc_dev
, "CRC Error\n");
963 * Receive Data FIFO Fast Forward
964 * When performing a fast-forward, there must be at
965 * least 4 DWORDs of data in the RX data FIFO for the
966 * packet being discarded.
968 if (pktlen
>= 4 * sizeof(uint32_t)) {
971 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
,
973 LAN9118_RX_DP_CTL_RX_FFWD
);
974 /* DP_FFWD bit is self clearing */
976 rx_dp_ctl
= bus_space_read_4(sc
->sc_iot
,
977 sc
->sc_ioh
, LAN9118_RX_DP_CTL
);
978 } while (rx_dp_ctl
& LAN9118_RX_DP_CTL_RX_FFWD
);
980 /* For less than 4 DWORDs do not use RX_FFWD. */
983 bus_space_read_multi_4(sc
->sc_iot
, sc
->sc_ioh
,
984 LAN9118_RXDFIFOP
, garbage
,
985 roundup(pktlen
, 4) >> 2);
990 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
993 if (pktlen
> (MHLEN
- pad
)) {
994 MCLGET(m
, M_DONTWAIT
);
995 if ((m
->m_flags
& M_EXT
) == 0) {
1001 /* STRICT_ALIGNMENT */
1002 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_RX_CFG
,
1003 LAN9118_RX_CFG_RXEA_4B
| LAN9118_RX_CFG_RXDOFF(pad
));
1004 bus_space_read_multi_4(sc
->sc_iot
, sc
->sc_ioh
, LAN9118_RXDFIFOP
,
1005 mtod(m
, uint32_t *),
1006 roundup(pad
+ pktlen
, sizeof(uint32_t)) >> 2);
1010 m
->m_pkthdr
.rcvif
= ifp
;
1011 m
->m_pkthdr
.len
= m
->m_len
= (pktlen
- ETHER_CRC_LEN
);
1015 * Pass this up to any BPF listeners, but only
1016 * pass if up the stack if it's for us.
1019 bpf_mtap(ifp
->if_bpf
, m
);
1020 #endif /* NBPFILTER > 0 */
1023 (*ifp
->if_input
)(ifp
, m
);
1028 lan9118_txintr(struct lan9118_softc
*sc
)
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
;
1035 DPRINTFN(3, ("%s\n", __func__
));
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)
1043 tx_status
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
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 ifp
->if_collisions
+= 16;
1058 aprint_error_dev(sc
->sc_dev
,
1059 "Excessive Collision\n");
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");
1075 tdfree
= LAN9118_TX_FIFO_INF_TDFREE(tx_fifo_inf
);
1076 if (tdfree
== LAN9118_TX_DATA_FIFO_SIZE
)
1081 * 2036 is the possible maximum FIFO consumption
1082 * for the most fragmented frame.
1084 ifp
->if_flags
&= ~IFF_OACTIVE
;
1088 lan9118_tick(void *v
)
1090 struct lan9118_softc
*sc
= v
;
1094 mii_tick(&sc
->sc_mii
);
1095 callout_schedule(&sc
->sc_tick
, hz
);