2 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
14 * 3. Neither the name of The DragonFly Project nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific, prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * $FreeBSD-4.7: /usr/src/sys/pci/silan.c,v 1.0 2003/01/10 gaoyonghong $
32 * $DragonFly: src/sys/dev/netif/sln/if_sln.c,v 1.3 2008/06/29 20:45:44 swildner Exp $
36 #include <sys/endian.h>
37 #include <sys/kernel.h>
38 #include <sys/interrupt.h>
39 #include <sys/malloc.h>
41 #include <sys/resource.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/systm.h>
47 #include <bus/pci/pcidevs.h>
48 #include <bus/pci/pcireg.h>
49 #include <bus/pci/pcivar.h>
51 #include <machine/clock.h>
54 #include <net/ethernet.h>
55 #include <net/ifq_var.h>
57 #include <net/if_arp.h>
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 #include <net/if_var.h>
65 #include "if_slnreg.h"
66 #include "if_slnvar.h"
68 /* Default to using PIO access for netcard driver */
72 #define PDEBUG(fmt, args...) kprintf("%s: " fmt "\n" , __func__ , ## args)
74 #define PDEBUG(fmt, args...)
77 static const struct sln_dev
{
82 {PCI_VENDOR_SILAN
, PCI_PRODUCT_SILAN_SC92031
,
83 "Silan SC92031 Fast Ethernet" },
84 {PCI_VENDOR_SILAN
, PCI_PRODUCT_SILAN_8139D
,
85 "Silan Rsltek 8139D Fast Ethernet" },
89 static int sln_probe(device_t
);
90 static int sln_attach(device_t
);
91 static int sln_detach(device_t
);
92 static int sln_shutdown(device_t
);
93 static int sln_suspend(device_t
);
94 static int sln_resume(device_t
);
96 static void sln_reset(struct sln_softc
*);
97 static void sln_init(void *);
99 static void sln_tx(struct ifnet
*);
100 static void sln_rx(struct sln_softc
*);
101 static void sln_tx_intr(struct sln_softc
*);
102 static void sln_media_intr(struct sln_softc
*);
103 static void sln_interrupt(void *);
104 static int sln_ioctl(struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
105 static void sln_stop(struct sln_softc
*);
106 static void sln_watchdog(struct ifnet
*);
108 static int sln_media_upd(struct ifnet
*);
110 static void sln_media_stat(struct ifnet
*, struct ifmediareq
*);
111 static void sln_mii_cmd(struct sln_softc
*, uint32_t, u_long
*);
112 static void sln_media_cfg(struct sln_softc
*);
113 static void sln_mac_cfg(struct sln_softc
*);
114 static uint32_t sln_ether_crc32(caddr_t
);
115 static void sln_set_multi(struct sln_softc
*);
116 static void sln_init_tx(struct sln_softc
*);
117 static void sln_tick(void *);
120 #define SL_RID SL_PCI_IOAD
121 #define SL_RES SYS_RES_IOPORT
123 #define SL_RID SL_PCI_MEMAD
124 #define SL_RES SYS_RES_MEMORY
127 static device_method_t sln_methods
[] = {
128 DEVMETHOD(device_probe
, sln_probe
),
129 DEVMETHOD(device_attach
, sln_attach
),
130 DEVMETHOD(device_detach
, sln_detach
),
131 DEVMETHOD(device_shutdown
, sln_shutdown
),
132 DEVMETHOD(device_suspend
, sln_suspend
),
133 DEVMETHOD(device_resume
, sln_resume
),
135 DEVMETHOD(bus_print_child
, bus_generic_print_child
),
136 DEVMETHOD(bus_driver_added
, bus_generic_driver_added
),
141 static driver_t sln_driver
= {
144 sizeof(struct sln_softc
)
147 static devclass_t sln_devclass
;
149 DRIVER_MODULE(sln
, pci
, sln_driver
, sln_devclass
, 0, 0);
152 sln_probe(struct device
*dev
)
154 const struct sln_dev
*d
;
157 vid
= pci_get_vendor(dev
);
158 did
= pci_get_device(dev
);
160 for (d
= sln_devs
; d
->desc
!= NULL
; d
++) {
161 if (vid
== d
->vid
&& did
== d
->did
) {
162 device_set_desc(dev
, d
->desc
);
171 sln_reset(struct sln_softc
*sc
)
173 SLN_WRITE_4(sc
, SL_CFG0
, SL_SOFT_RESET
);
175 SLN_WRITE_4(sc
, SL_CFG0
, 0x0);
179 /* Attach the interface. Allocate softc structures */
181 sln_attach(device_t dev
)
183 struct sln_softc
*sc
= device_get_softc(dev
);
184 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
185 unsigned char eaddr
[ETHER_ADDR_LEN
];
189 if_initname(ifp
, device_get_name(dev
), device_get_unit(dev
));
191 /* TODO: power state change */
193 pci_enable_busmaster(dev
);
196 sc
->sln_res
= bus_alloc_resource_any(dev
, SL_RES
, &rid
, RF_ACTIVE
);
197 if (sc
->sln_res
== NULL
) {
198 device_printf(dev
, "couldn't map ports/memory\n");
202 sc
->sln_bustag
= rman_get_bustag(sc
->sln_res
);
203 sc
->sln_bushandle
= rman_get_bushandle(sc
->sln_res
);
207 sc
->sln_irq
= bus_alloc_resource_any(dev
, SYS_RES_IRQ
, &rid
,
208 RF_SHAREABLE
| RF_ACTIVE
);
209 if (sc
->sln_irq
== NULL
) {
210 device_printf(dev
, "couldn't map interrupt\n");
211 bus_release_resource(dev
, SL_RES
, SL_RID
, sc
->sln_res
);
216 /* Get MAC address */
217 ((uint32_t *)(&eaddr
))[0] = be32toh(SLN_READ_4(sc
, SL_MAC_ADDR0
));
218 ((uint16_t *)(&eaddr
))[2] = be16toh(SLN_READ_4(sc
, SL_MAC_ADDR1
));
220 /* alloc rx buffer space */
221 sc
->sln_bufdata
.sln_rx_buf
= contigmalloc(SL_RX_BUFLEN
,
222 M_DEVBUF
, M_WAITOK
, 0, 0xffffffff, PAGE_SIZE
, 0);
223 if (sc
->sln_bufdata
.sln_rx_buf
== NULL
) {
224 device_printf(dev
, "no memory for rx buffers!\n");
225 bus_release_resource(dev
, SYS_RES_IRQ
, 0, sc
->sln_irq
);
226 bus_release_resource(dev
, SL_RES
, SL_RID
, sc
->sln_res
);
230 callout_init(&sc
->sln_state
);
233 ifp
->if_mtu
= ETHERMTU
;
234 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
;
235 ifp
->if_init
= sln_init
;
236 ifp
->if_start
= sln_tx
;
237 ifp
->if_ioctl
= sln_ioctl
;
238 ifp
->if_watchdog
= sln_watchdog
;
239 ifq_set_maxlen(&ifp
->if_snd
, IFQ_MAXLEN
);
240 ifq_set_ready(&ifp
->if_snd
);
243 ifmedia_init(&sc
->ifmedia
, 0, sln_media_upd
, sln_media_stat
);
245 /* supported media types */
246 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
| IFM_AUTO
, 0, NULL
);
247 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
| IFM_10_T
, 0, NULL
);
248 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
| IFM_10_T
| IFM_HDX
, 0, NULL
);
249 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
| IFM_10_T
| IFM_FDX
, 0, NULL
);
250 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
| IFM_100_TX
, 0, NULL
);
251 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
| IFM_100_TX
| IFM_HDX
, 0, NULL
);
252 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
| IFM_100_TX
| IFM_FDX
, 0, NULL
);
254 /* Choose a default media. */
255 ifmedia_set(&sc
->ifmedia
, IFM_ETHER
| IFM_AUTO
);
257 ether_ifattach(ifp
, eaddr
, NULL
);
259 error
= bus_setup_intr(dev
, sc
->sln_irq
, INTR_MPSAFE
, sln_interrupt
, sc
,
260 &sc
->sln_intrhand
, ifp
->if_serializer
);
262 bus_release_resource(dev
, SYS_RES_IRQ
, 0, sc
->sln_irq
);
263 bus_release_resource(dev
, SL_RES
, SL_RID
, sc
->sln_res
);
265 device_printf(dev
, "couldn't set up irq\n");
269 ifp
->if_cpuid
= ithread_cpuid(rman_get_start(sc
->sln_irq
));
270 KKASSERT(ifp
->if_cpuid
>= 0 && ifp
->if_cpuid
< ncpus
);
277 /* Stop the adapter and free any mbufs allocated to the RX and TX buffers */
279 sln_stop(struct sln_softc
*sc
)
281 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
282 uint32_t intr_status
;
285 ASSERT_SERIALIZED(ifp
->if_serializer
);
288 callout_stop(&sc
->sln_state
);
291 sc
->txcfg
&= ~SL_TXCFG_EN
;
292 sc
->rxcfg
&= ~SL_RXCFG_EN
;
293 SLN_WRITE_4(sc
, SL_TX_CONFIG
, sc
->txcfg
);
294 SLN_WRITE_4(sc
, SL_RX_CONFIG
, sc
->rxcfg
);
296 /* Clear interrupt */
297 SLN_WRITE_4(sc
, SL_INT_MASK
, 0);
298 intr_status
= SLN_READ_4(sc
, SL_INT_STATUS
);
300 /* Free the TX list buffers */
301 for (i
= 0; i
< SL_TXD_CNT
; i
++) {
302 if (sc
->sln_bufdata
.sln_tx_buf
[i
] != NULL
) {
303 m_freem(sc
->sln_bufdata
.sln_tx_buf
[i
]);
304 sc
->sln_bufdata
.sln_tx_buf
[i
] = NULL
;
305 SLN_WRITE_4(sc
, SL_TSAD0
+ i
* 4, 0);
309 ifp
->if_flags
&= ~(IFF_RUNNING
| IFF_OACTIVE
);
313 sln_detach(device_t dev
)
315 struct sln_softc
*sc
= device_get_softc(dev
);
316 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
318 lwkt_serialize_enter(ifp
->if_serializer
);
320 bus_teardown_intr(dev
, sc
->sln_irq
, sc
->sln_intrhand
);
321 lwkt_serialize_exit(ifp
->if_serializer
);
325 bus_generic_detach(dev
);
327 bus_release_resource(dev
, SYS_RES_IRQ
, 0, sc
->sln_irq
);
328 bus_release_resource(dev
, SL_RES
, SL_RID
, sc
->sln_res
);
330 contigfree(sc
->sln_bufdata
.sln_rx_buf
, SL_RX_BUFLEN
, M_DEVBUF
);
336 sln_media_upd(struct ifnet
*ifp
)
338 struct sln_softc
*sc
= ifp
->if_softc
;
339 struct ifmedia
*ifm
= &sc
->ifmedia
;
341 if (IFM_TYPE(ifm
->ifm_media
) != IFM_ETHER
)
344 if (ifp
->if_flags
& IFF_UP
)
351 sln_media_stat(struct ifnet
*ifp
, struct ifmediareq
*ifmr
)
353 struct sln_softc
*sc
= ifp
->if_softc
;
357 ifmr
->ifm_status
= IFM_AVALID
;
358 ifmr
->ifm_active
= IFM_ETHER
;
360 phys
[0] = SL_MII_STAT
;
361 sln_mii_cmd(sc
, SL_MII0_READ
, phys
);
363 if (phys
[1] & SL_MIISTAT_LINK
)
364 ifmr
->ifm_status
|= IFM_ACTIVE
;
366 temp
= SLN_READ_4(sc
, SL_PHY_CTRL
);
368 if ((temp
& (SL_PHYCTL_DUX
| SL_PHYCTL_SPD100
| SL_PHYCTL_SPD10
)) == 0x60800000)
369 ifmr
->ifm_active
|= IFM_AUTO
;
370 else if ((temp
& (SL_PHYCTL_DUX
| SL_PHYCTL_SPD100
)) == 0x40800000)
371 ifmr
->ifm_active
|= IFM_100_TX
| IFM_FDX
;
372 else if ((temp
& SL_PHYCTL_SPD100
) == 0x40000000)
373 ifmr
->ifm_active
|= IFM_100_TX
| IFM_HDX
;
374 else if ((temp
& (SL_PHYCTL_DUX
| SL_PHYCTL_SPD10
)) == 0x20800000)
375 ifmr
->ifm_active
|= IFM_10_T
| IFM_FDX
;
376 else if ((temp
& SL_PHYCTL_SPD10
) == 0x20000000)
377 ifmr
->ifm_active
|= IFM_10_T
| IFM_HDX
;
379 sln_mii_cmd(sc
, SL_MII0_SCAN
, phys
);
382 /* command selected in MII command register */
384 sln_mii_cmd(struct sln_softc
*sc
, uint32_t cmd
, u_long
*phys
)
388 SLN_WRITE_4(sc
, SL_MII_CMD0
, SL_MII0_DIVEDER
);
393 mii_status
= SLN_READ_4(sc
, SL_MII_STATUS
);
394 } while (mii_status
& SL_MIISTAT_BUSY
);
398 SLN_WRITE_4(sc
, SL_MII_CMD1
, 0x1 << 6);
399 SLN_WRITE_4(sc
, SL_MII_CMD0
, SL_MII0_DIVEDER
| SL_MII0_SCAN
);
403 SLN_WRITE_4(sc
, SL_MII_CMD1
, phys
[0] << 6);
404 SLN_WRITE_4(sc
, SL_MII_CMD0
, SL_MII0_DIVEDER
| SL_MII0_READ
);
408 SLN_WRITE_4(sc
, SL_MII_CMD1
, phys
[0] << 6 | phys
[1] << 11);
409 SLN_WRITE_4(sc
, SL_MII_CMD0
, SL_MII0_DIVEDER
| SL_MII0_WRITE
);
415 mii_status
= SLN_READ_4(sc
, SL_MII_STATUS
);
416 } while (mii_status
& SL_MIISTAT_BUSY
);
418 if (SL_MII0_READ
== cmd
)
419 phys
[1] = (mii_status
>> 13) & 0xffff;
422 /* Set media speed and duplex mode */
424 sln_media_cfg(struct sln_softc
*sc
)
430 mediatype
= (&sc
->ifmedia
)->ifm_cur
->ifm_media
;
432 temp
= SLN_READ_4(sc
, SL_PHY_CTRL
);
433 temp
&= ~(SL_PHYCTL_DUX
| SL_PHYCTL_SPD100
| SL_PHYCTL_SPD10
);
434 temp
|= (SL_PHYCTL_ANE
| SL_PHYCTL_RESET
);
436 /************************************************/
437 /* currently set media word by selected media */
439 /* IFM_ETHER = 0x00000020 */
440 /* IFM_AUTO=0, IFM_10_T=3, IFM_100_TX=6 */
441 /* IFM_FDX=0x00100000 IFM_HDX=0x00200000 */
442 /************************************************/
445 PDEBUG(" autoselet supported\n");
446 temp
|= (SL_PHYCTL_DUX
| SL_PHYCTL_SPD100
| SL_PHYCTL_SPD10
);
447 sc
->ifmedia
.ifm_media
= IFM_ETHER
| IFM_AUTO
;
448 ifmedia_set(&sc
->ifmedia
, IFM_ETHER
| IFM_AUTO
);
452 PDEBUG(" 10Mbps half_duplex supported\n");
453 temp
|= SL_PHYCTL_SPD10
;
454 sc
->ifmedia
.ifm_media
= IFM_ETHER
| IFM_10_T
| IFM_HDX
;
455 ifmedia_set(&sc
->ifmedia
, IFM_ETHER
| IFM_10_T
| IFM_HDX
);
459 PDEBUG("10Mbps full_duplex supported\n");
460 temp
|= (SL_PHYCTL_SPD10
| SL_PHYCTL_DUX
);
461 sc
->ifmedia
.ifm_media
= IFM_ETHER
| IFM_10_T
| IFM_FDX
;
462 ifmedia_set(&sc
->ifmedia
, IFM_ETHER
| IFM_10_T
| IFM_FDX
);
467 PDEBUG("100Mbps half_duplex supported\n");
468 temp
|= SL_PHYCTL_SPD100
;
469 sc
->ifmedia
.ifm_media
= IFM_ETHER
| IFM_100_TX
| IFM_HDX
;
470 ifmedia_set(&sc
->ifmedia
, IFM_ETHER
| IFM_100_TX
| IFM_HDX
);
474 PDEBUG("100Mbps full_duplex supported\n");
475 temp
|= (SL_PHYCTL_SPD100
| SL_PHYCTL_DUX
);
476 sc
->ifmedia
.ifm_media
= IFM_ETHER
| IFM_100_TX
| IFM_FDX
;
477 ifmedia_set(&sc
->ifmedia
, IFM_ETHER
| IFM_100_TX
| IFM_FDX
);
484 SLN_WRITE_4(sc
, SL_PHY_CTRL
, temp
);
487 temp
&= ~SL_PHYCTL_RESET
;
488 SLN_WRITE_4(sc
, SL_PHY_CTRL
, temp
);
491 phys
[0] = SL_MII_JAB
;
492 phys
[1] = SL_PHY_16_JAB_ENB
| SL_PHY_16_PORT_ENB
;
493 sln_mii_cmd(sc
, SL_MII0_WRITE
, phys
);
496 sln_mii_cmd(sc
, SL_MII0_SCAN
, phys
);
500 sln_mac_cfg(struct sln_softc
*sc
)
502 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
505 /* Set the initial TX/RX/Flow Control configuration */
506 sc
->rxcfg
= SL_RXCFG_LOW_THRESHOLD
| SL_RXCFG_HIGH_THRESHOLD
;
507 sc
->txcfg
= TX_CFG_DEFAULT
;
510 sc
->txcfg
|= 0x20000000;
512 if (sc
->media_speed
== IFM_10_T
)
513 sc
->txcfg
|= SL_TXCFG_DATARATE
;
515 if (sc
->media_duplex
== IFM_FDX
) {
516 sc
->rxcfg
|= SL_RXCFG_FULLDX
;
517 sc
->txcfg
|= SL_TXCFG_FULLDX
;
518 flowcfg
= SL_FLOWCTL_FULLDX
| SL_FLOWCTL_EN
;
520 sc
->rxcfg
&= ~SL_RXCFG_FULLDX
;
521 sc
->txcfg
&= ~SL_TXCFG_FULLDX
;
524 /* if promiscuous mode, set the allframes bit. */
525 if (ifp
->if_flags
& IFF_PROMISC
)
526 sc
->rxcfg
|= (SL_RXCFG_EN
| SL_RXCFG_RCV_SMALL
| SL_RXCFG_RCV_HUGE
| SL_RXCFG_RCV_ERR
| SL_RXCFG_RCV_BROAD
| SL_RXCFG_RCV_MULTI
| SL_RXCFG_RCV_ALL
);
528 sc
->rxcfg
&= ~(SL_RXCFG_EN
| SL_RXCFG_RCV_SMALL
| SL_RXCFG_RCV_HUGE
| SL_RXCFG_RCV_ERR
| SL_RXCFG_RCV_BROAD
| SL_RXCFG_RCV_MULTI
| SL_RXCFG_RCV_ALL
);
530 /* Set capture broadcast bit to capture broadcast frames */
531 if (ifp
->if_flags
& IFF_BROADCAST
)
532 sc
->rxcfg
|= SL_RXCFG_EN
| SL_RXCFG_RCV_BROAD
;
534 sc
->rxcfg
&= ~(SL_RXCFG_EN
| SL_RXCFG_RCV_BROAD
);
536 /* Program the multicast filter, if necessary */
539 SLN_WRITE_4(sc
, SL_RX_CONFIG
, sc
->rxcfg
);
540 SLN_WRITE_4(sc
, SL_TX_CONFIG
, sc
->txcfg
);
541 SLN_WRITE_4(sc
, SL_FLOW_CTRL
, flowcfg
);
544 static u_char shade_map
[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
545 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
547 /* Calculate CRC32 of a multicast group address */
549 sln_ether_crc32(caddr_t addr
)
553 unsigned char data
= 0;
554 /* Compute CRC for the address value. */
556 crc
= 0xFFFFFFFF; /* initial value */
558 for (i
= ETHER_ADDR_LEN
; i
> 0; i
--) {
561 for (j
= 0; j
< 8; j
++) {
562 if (((data
& 0x1) ^ (crc
& 0x1)) != 0) {
572 crcr
= shade_map
[crc
>> 28];
573 crcr
|= (shade_map
[(crc
>> 24) & 0xf] << 4);
574 crcr
|= (shade_map
[(crc
>> 20) & 0xf] << 8);
575 crcr
|= (shade_map
[(crc
>> 16) & 0xf] << 12);
576 crcr
|= (shade_map
[(crc
>> 12) & 0xf] << 16);
577 crcr
|= (shade_map
[(crc
>> 8) & 0xf] << 20);
578 crcr
|= (shade_map
[(crc
>> 4) & 0xf] << 24);
579 crcr
|= (shade_map
[crc
& 0xf] << 28);
584 /* Program the 64-bit multicast hash filter */
586 sln_set_multi(struct sln_softc
*sc
)
588 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
590 uint32_t mc_g
[2] = {0, 0};
591 struct ifmultiaddr
*ifma
;
594 if (ifp
->if_flags
& IFF_PROMISC
) {
595 kprintf("Promisc mode is enabled\n");
596 sc
->rxcfg
|= SL_RXCFG_EN
| SL_RXCFG_RCV_MULTI
;
597 mc_g
[0] = mc_g
[1] = 0xFFFFFFFF;
598 } else if (ifp
->if_flags
& IFF_ALLMULTI
) {
599 kprintf("Allmulti mode is enabled\n");
600 sc
->rxcfg
|= SL_RXCFG_EN
| SL_RXCFG_RCV_MULTI
;
601 mc_g
[0] = mc_g
[1] = 0xFFFFFFFF;
602 } else if (ifp
->if_flags
& IFF_MULTICAST
) {
603 kprintf("Multicast mode is enabled\n");
604 sc
->rxcfg
|= SL_RXCFG_EN
| SL_RXCFG_RCV_MULTI
;
606 /* first, zero all the existing hash bits */
607 mc_g
[0] = mc_g
[1] = 0;
609 for (i
= 0, ifma
= (ifp
->if_multiaddrs
.lh_first
);
610 ifma
!= NULL
&& (i
< ifma
->ifma_refcount
);
611 i
++, ifma
= (ifma
->ifma_link
.le_next
)) {
614 if ((ifma
->ifma_addr
->sa_family
) != AF_LINK
)
617 crc
= ~sln_ether_crc32(LLADDR((struct sockaddr_dl
*)ifma
->ifma_addr
));
634 mc_g
[0] |= (0x1 << (j
- 32));
636 mc_g
[1] |= (0x1 << j
);
639 sc
->rxcfg
&= ~(SL_RXCFG_EN
| SL_RXCFG_RCV_MULTI
);
642 SLN_WRITE_4(sc
, SL_RX_CONFIG
, sc
->rxcfg
);
643 SLN_WRITE_4(sc
, SL_MULTI_GROUP0
, mc_g
[0]);
644 SLN_WRITE_4(sc
, SL_MULTI_GROUP1
, mc_g
[1]);
647 /* Initialize the TX/Rx descriptors */
649 sln_init_tx(struct sln_softc
*sc
)
653 sc
->sln_bufdata
.cur_tx
= 0;
654 sc
->sln_bufdata
.dirty_tx
= 0;
656 for (i
= 0; i
< SL_TXD_CNT
; i
++) {
657 sc
->sln_bufdata
.sln_tx_buf
[i
] = NULL
;
658 SLN_WRITE_4(sc
, SL_TSAD0
+ (i
* 4), 0);
662 /* Software & Hardware Initialize */
666 struct sln_softc
*sc
= x
;
667 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
669 PDEBUG("sln_init\n");
671 ASSERT_SERIALIZED(ifp
->if_serializer
);
675 /* soft reset the chip */
678 /* disable interrupt */
679 SLN_WRITE_4(sc
, SL_INT_MASK
, 0);
681 /* SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER); */
683 /* clear multicast address */
684 SLN_WRITE_4(sc
, SL_MULTI_GROUP0
, 0);
685 SLN_WRITE_4(sc
, SL_MULTI_GROUP1
, 0);
687 /* Init the RX buffer start address register. */
688 SLN_WRITE_4(sc
, SL_RBSA
, vtophys(sc
->sln_bufdata
.sln_rx_buf
));
689 sc
->sln_bufdata
.dirty_rx
= vtophys(sc
->sln_bufdata
.sln_rx_buf
);
691 /* Init TX descriptors. */
694 /* configure RX buffer size */
695 if (sc
->tx_early_ctrl
&& sc
->rx_early_ctrl
)
696 SLN_WRITE_4(sc
, SL_CFG1
, SL_EARLY_RX
| SL_EARLY_TX
| SL_RXBUF_64
| SL_RXFIFO_1024BYTES
);
697 else if (sc
->tx_early_ctrl
)
698 SLN_WRITE_4(sc
, SL_CFG1
, SL_EARLY_TX
| SL_RXBUF_64
);
699 else if (sc
->rx_early_ctrl
)
700 SLN_WRITE_4(sc
, SL_CFG1
, SL_EARLY_RX
| SL_RXBUF_64
| SL_RXFIFO_1024BYTES
);
702 SLN_WRITE_4(sc
, SL_CFG1
, SL_RXBUF_64
);
704 /* MII media configuration */
708 /* Enable transmit and receive */
709 sc
->rxcfg
|= SL_RXCFG_EN
;
710 sc
->txcfg
|= SL_TXCFG_EN
;
712 sc
->rxcfg
&= ~SL_RXCFG_EN
;
713 sc
->txcfg
&= ~SL_TXCFG_EN
;
716 SLN_WRITE_4(sc
, SL_TX_CONFIG
, sc
->txcfg
);
717 SLN_WRITE_4(sc
, SL_RX_CONFIG
, sc
->rxcfg
);
719 /* Enable interrupts */
720 SLN_WRITE_4(sc
, SL_INT_MASK
, SL_INRTS
);
724 ifp
->if_flags
|= IFF_RUNNING
;
725 ifp
->if_flags
&= ~IFF_OACTIVE
;
727 callout_reset(&sc
->sln_state
, hz
, sln_tick
, sc
);
730 /* Transmit Packet */
732 sln_tx(struct ifnet
*ifp
)
734 struct sln_softc
*sc
= ifp
->if_softc
;
735 struct mbuf
*m_head
= NULL
;
736 struct mbuf
*m_new
= NULL
;
739 ASSERT_SERIALIZED(ifp
->if_serializer
);
742 ifq_purge(&ifp
->if_snd
);
746 if ((ifp
->if_flags
& (IFF_OACTIVE
| IFF_RUNNING
)) != IFF_RUNNING
)
749 while (SL_CUR_TXBUF(sc
) == NULL
) { /* SL_CUR_TXBUF(x) = x->sln_bufdata.sln_tx_buf[x->sln_bufdata.cur_tx] */
750 entry
= sc
->sln_bufdata
.cur_tx
;
752 m_head
= ifq_dequeue(&ifp
->if_snd
, NULL
);
756 MGETHDR(m_new
, MB_DONTWAIT
, MT_DATA
);
758 if_printf(ifp
, "no memory for tx descriptor");
762 if ((m_head
->m_pkthdr
.len
> MHLEN
) || (60 > MHLEN
)) {
763 MCLGET(m_new
, MB_DONTWAIT
);
764 if (!(m_new
->m_flags
& M_EXT
)) {
767 if_printf(ifp
, "no memory for tx descriptor");
771 m_copydata(m_head
, 0, m_head
->m_pkthdr
.len
, mtod(m_new
, caddr_t
));
772 m_new
->m_pkthdr
.len
= m_new
->m_len
= m_head
->m_pkthdr
.len
;
775 SL_CUR_TXBUF(sc
) = m_head
;
778 * if there's a BPF listener, bounce a copy of this frame to
781 BPF_MTAP(ifp
, SL_CUR_TXBUF(sc
));
783 /* Transmit the frame */
784 SLN_WRITE_4(sc
, ((entry
* 4) + SL_TSAD0
),
785 vtophys(mtod(SL_CUR_TXBUF(sc
), caddr_t
)));
787 /* calculate length of the frame */
788 if ((SL_CUR_TXBUF(sc
)->m_pkthdr
.len
< 60) && (!sc
->txenablepad
)) {
789 memset(mtod(m_head
, char *)+m_head
->m_pkthdr
.len
, 0x20, 60 - m_head
->m_pkthdr
.len
);
790 SLN_WRITE_4(sc
, (entry
* 4) + SL_TSD0
, 60);
791 } else if (SL_CUR_TXBUF(sc
)->m_pkthdr
.len
< 100)
792 SLN_WRITE_4(sc
, (entry
* 4) + SL_TSD0
, SL_CUR_TXBUF(sc
)->m_pkthdr
.len
);
793 else if (SL_CUR_TXBUF(sc
)->m_pkthdr
.len
< 300)
794 SLN_WRITE_4(sc
, (entry
* 4) + SL_TSD0
, 0x30000 | SL_CUR_TXBUF(sc
)->m_pkthdr
.len
);
796 SLN_WRITE_4(sc
, (entry
* 4) + SL_TSD0
, 0x50000 | SL_CUR_TXBUF(sc
)->m_pkthdr
.len
);
797 sc
->sln_bufdata
.cur_tx
= (entry
+ 1) % SL_TXD_CNT
;
799 PDEBUG("Queue tx packet size %d to tx-descriptor %d.\n", m_head
->m_pkthdr
.len
, entry
);
802 /* Tx buffer chain full */
803 if (SL_CUR_TXBUF(sc
) != NULL
)
804 ifp
->if_flags
|= IFF_OACTIVE
;
806 /* Set a timeout in case the chip goes out to lunch */
810 /* Receive Data handler */
812 sln_rx(struct sln_softc
*sc
)
815 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
818 caddr_t rx_bufpos
= NULL
;
824 u_long rx_size_align
= 0;
825 uint32_t rx_bytes
= 0;
828 cur_rx
= SLN_READ_4(sc
, SL_RBW_PTR
);
829 dirty_rx
= sc
->sln_bufdata
.dirty_rx
;
832 * cur_rx is only 17 bits in the RxBufWPtr register. if cur_rx can be
833 * used in physical space, we need to change it to 32 bits physical
836 cur_rx
|= vtophys(sc
->sln_bufdata
.sln_rx_buf
) & (~(u_long
) (SL_RX_BUFLEN
- 1));
838 if (cur_rx
< vtophys(sc
->sln_bufdata
.sln_rx_buf
))
839 cur_rx
+= SL_RX_BUFLEN
;
841 if (cur_rx
>= dirty_rx
)
842 rx_len
= (long)(cur_rx
- dirty_rx
);
844 rx_len
= SL_RX_BUFLEN
- (long)(dirty_rx
- cur_rx
);
846 if ((rx_len
> SL_RX_BUFLEN
) || (rx_len
< 0)) {
847 if_printf(ifp
, "rx len is fail\n");
853 rx_offset
= (dirty_rx
- vtophys(sc
->sln_bufdata
.sln_rx_buf
)) & (u_long
) (SL_RX_BUFLEN
- 1);
856 rx_bufpos
= sc
->sln_bufdata
.sln_rx_buf
+ rx_offset
;
857 rxstat
= *(uint32_t *) rx_bufpos
;
858 rx_size
= (rxstat
>> 20) & 0x0FFF;
859 rx_size_align
= (rx_size
+ 3) & ~3; /* for 4 bytes aligned */
860 pkt_size
= rx_size
- ETHER_CRC_LEN
; /* Omit the four octet
861 * CRC from the length. */
863 PDEBUG("rx len: %ld rx frame size:%ld rx state:0x%x\n", rx_len
, rx_size
, rxstat
);
865 /* errors receive packets caculatation */
866 if (rxstat
== 0 || rx_size
< 16 || !(rxstat
& SL_RXSTAT_RXOK
)) {
869 if (!(rxstat
& SL_RXSTAT_RXOK
))
870 if_printf(ifp
, "receiver ok error\n");
872 if (!(rxstat
& SL_RXSTAT_CRCOK
))
873 if_printf(ifp
, "crc error\n");
875 if (rxstat
& SL_RXSTAT_ALIGNERR
)
876 if_printf(ifp
, "frame alignment error\n");
878 if (rxstat
& (SL_RXSTAT_HUGEFRM
| SL_RXSTAT_SMALLFRM
))
879 if_printf(ifp
, "received frame length is error\n");
883 rx_len
-= (long)(rx_size_align
+ 4); /* 4 bytes for receive
887 kprintf("rx packets len is too small\n");
893 if_printf(ifp
, "rx frame content\n");
895 for (i
= 0; i
< 30; i
++, p
++) {
898 if_printf(ifp
, "%x ", (u_char
)*p
);
900 if_printf(ifp
, "\n");
902 /* No errors; receive the packet. */
903 rx_bytes
= rx_bytes
+ rx_size
+ 4; /* 4 bytes for receive
906 if (rx_bufpos
== (sc
->sln_bufdata
.sln_rx_buf
+ SL_RX_BUFLEN
))
907 rx_bufpos
= sc
->sln_bufdata
.sln_rx_buf
;
909 rx_bufpos
= rx_bufpos
+ 4; /* 4 bytes for receive frame
911 rx_space
= (u_long
)((sc
->sln_bufdata
.sln_rx_buf
+ SL_RX_BUFLEN
) - rx_bufpos
);
913 if (pkt_size
> rx_space
) {
914 m
= m_devget(rx_bufpos
- 2, pkt_size
+ 2, 0, ifp
, NULL
); /* 2 for etherer head
920 "out of mbufs, tried to copy %ld bytes\n",
924 m_copyback(m
, rx_space
, pkt_size
- rx_space
, sc
->sln_bufdata
.sln_rx_buf
);
927 m
= m_devget(rx_bufpos
- 2, pkt_size
+ 2, 0, ifp
, NULL
);
932 "out of mbufs, tried to copy %ld bytes\n",
934 if_printf(ifp
, "ierrors = %ld\n", ifp
->if_ierrors
);
942 PDEBUG("ipackets = %ld\n", ifp
->if_ipackets
);
944 ifp
->if_input(ifp
, m
);
946 rx_offset
= (rx_offset
+ rx_size
+ 4) & (u_long
) (SL_RX_BUFLEN
- 1); /* 4 bytes for receive
950 sc
->sln_bufdata
.dirty_rx
= cur_rx
;
952 SLN_WRITE_4(sc
, SL_RBR_PTR
, cur_rx
);
955 /* Transmit OK/ERR handler */
957 sln_tx_intr(struct sln_softc
*sc
)
959 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
964 entry
= sc
->sln_bufdata
.dirty_tx
;
965 txstat
= SLN_READ_4(sc
, SL_TSD0
+ entry
* 4);
967 if (!(txstat
& (SL_TXSD_TOK
| SL_TXSD_TUN
| SL_TXSD_TABT
)))
968 break; /* It still hasn't been sent */
970 if (SL_DIRTY_TXBUF(sc
) != NULL
) { /* SL_DIRTY_TXBUF(x) =
971 * x->sln_bufdata.sln_tx_
972 * buf[x->sln_bufdata.dir
974 m_freem(SL_DIRTY_TXBUF(sc
));
975 SL_DIRTY_TXBUF(sc
) = NULL
;
977 if (txstat
& SL_TXSD_TOK
) {
979 ifp
->if_obytes
+= txstat
& SL_TXSD_LENMASK
;
980 PDEBUG("opackets = %ld\n", ifp
->if_opackets
);
981 ifp
->if_collisions
+= (txstat
& SL_TXSD_NCC
) >> 22;
984 if ((txstat
& (SL_TXSD_TABT
| SL_TXSD_OWC
))) {
985 sc
->txcfg
= TX_CFG_DEFAULT
;
988 sc
->txcfg
|= 0x20000000;
990 SLN_WRITE_4(sc
, SL_TX_CONFIG
, sc
->txcfg
);
993 PDEBUG("tx done descriprtor %x\n", entry
);
994 sc
->sln_bufdata
.dirty_tx
= (entry
+ 1) % SL_TXD_CNT
;
996 ifp
->if_flags
&= ~IFF_OACTIVE
;
997 } while (sc
->sln_bufdata
.dirty_tx
!= sc
->sln_bufdata
.cur_tx
);
999 if (sc
->sln_bufdata
.dirty_tx
== sc
->sln_bufdata
.cur_tx
)
1006 sln_media_intr(struct sln_softc
*sc
)
1009 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1011 phys
[0] = SL_MII_STAT
;
1012 sln_mii_cmd(sc
, SL_MII0_READ
, phys
);
1014 PDEBUG("mii_stat:0x%lx\n", phys
[1]);
1016 if (0 == (phys
[1] & SL_MIISTAT_LINK
)) {
1017 kprintf("media is unconnect,linked down,or uncompatible\n");
1019 sln_mii_cmd(sc
, SL_MII0_SCAN
, phys
);
1021 sc
->txcfg
&= ~SL_TXCFG_EN
;
1022 sc
->rxcfg
&= ~SL_RXCFG_EN
;
1023 SLN_WRITE_4(sc
, SL_TX_CONFIG
, sc
->txcfg
);
1024 SLN_WRITE_4(sc
, SL_RX_CONFIG
, sc
->rxcfg
);
1028 /* Link is good. Report modes and set duplex mode. */
1029 PDEBUG("media is connecting---> ");
1032 phys
[0] = SL_MII_STAT_OUTPUT
;
1033 sln_mii_cmd(sc
, SL_MII0_READ
, phys
);
1034 sc
->media_duplex
= ((phys
[1] & 0x0004) == 0) ? IFM_HDX
: IFM_FDX
;
1035 sc
->media_speed
= ((phys
[1] & 0x0002) == 0) ? IFM_10_T
: IFM_100_TX
;
1037 if_printf(ifp
, "media option:%dM %s-duplex\n",
1038 sc
->media_speed
== 0x6 ? 100 : 10,
1039 sc
->media_duplex
== 0x100000 ? "full" : "half");
1041 sln_mii_cmd(sc
, SL_MII0_SCAN
, phys
);
1046 sc
->rxcfg
|= SL_RXCFG_EN
;
1047 sc
->txcfg
|= SL_TXCFG_EN
;
1048 SLN_WRITE_4(sc
, SL_TX_CONFIG
, sc
->txcfg
);
1049 SLN_WRITE_4(sc
, SL_RX_CONFIG
, sc
->rxcfg
);
1052 /* Interrupt Handler */
1054 sln_interrupt(void *arg
)
1056 struct sln_softc
*sc
= arg
;
1057 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1058 uint32_t int_status
;
1060 ASSERT_SERIALIZED(ifp
->if_serializer
);
1062 if (sc
->suspended
|| (ifp
->if_flags
& IFF_RUNNING
) == 0)
1065 /* Disable interrupts. */
1066 SLN_WRITE_4(sc
, SL_INT_MASK
, 0);
1068 int_status
= SLN_READ_4(sc
, SL_INT_STATUS
);
1070 if ((int_status
== 0xffffffff) || (int_status
& SL_INRTS
) == 0)
1073 int_status
= int_status
& SL_INRTS
;
1074 PDEBUG("int_status = 0x%x\n", int_status
);
1076 while (0 != int_status
) {
1077 if (int_status
& SL_INT_ROK
)
1080 if (int_status
& SL_INT_TOK
)
1083 if (int_status
& SL_INT_RBO
) {
1085 PDEBUG("rx buffer is overflow\n");
1088 if (int_status
& (SL_INT_LINKFAIL
| SL_INT_LINKOK
))
1091 int_status
= SLN_READ_4(sc
, SL_INT_STATUS
);
1094 /* Data in Tx buffer waiting for transimission */
1095 if (!ifq_is_empty(&ifp
->if_snd
))
1098 /* Re-enable interrupts. */
1099 SLN_WRITE_4(sc
, SL_INT_MASK
, SL_INRTS
);
1105 struct sln_softc
*sc
= x
;
1107 callout_reset(&sc
->sln_state
, hz
, sln_tick
, sc
);
1111 sln_ioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
1113 struct sln_softc
*sc
= ifp
->if_softc
;
1114 struct ifreq
*ifr
= (struct ifreq
*)data
;
1117 ASSERT_SERIALIZED(ifp
->if_serializer
);
1121 if (ifp
->if_flags
& IFF_UP
) {
1122 if ((ifp
->if_flags
& IFF_RUNNING
) == 0)
1125 if (ifp
->if_flags
& IFF_RUNNING
)
1135 error
= ifmedia_ioctl(ifp
, ifr
, &sc
->ifmedia
, cmd
);
1138 error
= ether_ioctl(ifp
, cmd
, data
);
1145 sln_watchdog(struct ifnet
*ifp
)
1147 struct sln_softc
*sc
= ifp
->if_softc
;
1149 ASSERT_SERIALIZED(ifp
->if_serializer
);
1151 if_printf(ifp
, "watchdog timeout!\n");
1158 if (!ifq_is_empty(&ifp
->if_snd
))
1162 /* Stop all chip I/O */
1164 sln_shutdown(device_t dev
)
1166 struct sln_softc
*sc
= device_get_softc(dev
);
1167 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1169 lwkt_serialize_enter(ifp
->if_serializer
);
1171 lwkt_serialize_exit(ifp
->if_serializer
);
1176 /* device suspend routine */
1178 sln_suspend(device_t dev
)
1180 struct sln_softc
*sc
= device_get_softc(dev
);
1181 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1183 lwkt_serialize_enter(ifp
->if_serializer
);
1186 lwkt_serialize_exit(ifp
->if_serializer
);
1191 /* device resume routine */
1193 sln_resume(device_t dev
)
1195 struct sln_softc
*sc
= device_get_softc(dev
);
1196 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1198 lwkt_serialize_enter(ifp
->if_serializer
);
1199 if (ifp
->if_flags
& IFF_UP
)
1202 lwkt_serialize_exit(ifp
->if_serializer
);