The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/netif/sln/if_sln.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
    3  * 
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 
    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
   13  *    distribution.
   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.
   17  * 
   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
   29  * SUCH DAMAGE.
   30  * 
   31  * $FreeBSD-4.7: /usr/src/sys/pci/silan.c,v 1.0 2003/01/10 gaoyonghong $
   32  */
   33 
   34 #include <sys/param.h>
   35 #include <sys/bus.h>
   36 #include <sys/endian.h>
   37 #include <sys/kernel.h>
   38 #include <sys/interrupt.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/resource.h>
   42 #include <sys/rman.h>
   43 #include <sys/socket.h>
   44 #include <sys/sockio.h>
   45 #include <sys/systm.h>
   46 
   47 #include "pcidevs.h"
   48 #include <bus/pci/pcireg.h>
   49 #include <bus/pci/pcivar.h>
   50 
   51 #include <machine/clock.h>
   52 
   53 #include <net/bpf.h>
   54 #include <net/ethernet.h>
   55 #include <net/ifq_var.h>
   56 #include <net/if.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>
   61 
   62 #include <vm/pmap.h>
   63 #include <vm/vm.h>
   64 
   65 #include "if_slnreg.h"
   66 #include "if_slnvar.h"
   67 
   68 /* Default to using PIO access for netcard driver */
   69 #define SL_USEIOSPACE
   70 
   71 #ifdef SLN_DEBUG
   72 #define PDEBUG(fmt, args...)    kprintf("%s: " fmt "\n" , __func__ , ## args)
   73 #else
   74 #define PDEBUG(fmt, args...)
   75 #endif
   76 
   77 static const struct sln_dev {
   78         uint16_t vid;
   79         uint16_t did;
   80         const char *desc;
   81 } sln_devs[] = {
   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" },
   86         {0, 0, NULL}
   87 };
   88 
   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);
   95 
   96 static void     sln_reset(struct sln_softc *);
   97 static void     sln_init(void *);
   98 
   99 static void     sln_tx(struct ifnet *, struct ifaltq_subque *);
  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 *);
  107 
  108 static int      sln_media_upd(struct ifnet *);
  109 
  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 *);
  118 
  119 #ifdef SL_USEIOSPACE
  120 #define SL_RID  SL_PCI_IOAD
  121 #define SL_RES  SYS_RES_IOPORT
  122 #else
  123 #define SL_RID  SL_PCI_MEMAD
  124 #define SL_RES  SYS_RES_MEMORY
  125 #endif
  126 
  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),
  134 
  135         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  136         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
  137 
  138         DEVMETHOD_END
  139 };
  140 
  141 static driver_t sln_driver = {
  142         "sln",
  143         sln_methods,
  144         sizeof(struct sln_softc)
  145 };
  146 
  147 static devclass_t sln_devclass;
  148 
  149 DRIVER_MODULE(sln, pci, sln_driver, sln_devclass, NULL, NULL);
  150 
  151 static int
  152 sln_probe(struct device *dev)
  153 {
  154         const struct sln_dev *d;
  155         uint16_t did, vid;
  156 
  157         vid = pci_get_vendor(dev);
  158         did = pci_get_device(dev);
  159 
  160         for (d = sln_devs; d->desc != NULL; d++) {
  161                 if (vid == d->vid && did == d->did) {
  162                         device_set_desc(dev, d->desc);
  163                         return 0;
  164                 }
  165         }
  166         return ENXIO;
  167 }
  168 
  169 /* the chip reset */
  170 static void
  171 sln_reset(struct sln_softc *sc)
  172 {
  173         SLN_WRITE_4(sc, SL_CFG0, SL_SOFT_RESET);
  174         DELAY(200000);
  175         SLN_WRITE_4(sc, SL_CFG0, 0x0);
  176         DELAY(10000);
  177 }
  178 
  179 /* Attach the interface. Allocate softc structures */
  180 static int
  181 sln_attach(device_t dev)
  182 {
  183         struct sln_softc *sc = device_get_softc(dev);
  184         struct ifnet *ifp = &sc->arpcom.ac_if;
  185         unsigned char eaddr[ETHER_ADDR_LEN];
  186         int rid;
  187         int error = 0;
  188 
  189         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
  190 
  191         /* TODO: power state change */
  192 
  193         pci_enable_busmaster(dev);
  194 
  195         rid = SL_RID;
  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");
  199                 error = ENXIO;
  200                 goto fail;
  201         }
  202         sc->sln_bustag = rman_get_bustag(sc->sln_res);
  203         sc->sln_bushandle = rman_get_bushandle(sc->sln_res);
  204 
  205         /* alloc pci irq */
  206         rid = 0;
  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);
  212                 error = ENXIO;
  213                 goto fail;
  214         }
  215 
  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));
  219 
  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);
  227                 error = ENXIO;
  228                 goto fail;
  229         }
  230         callout_init(&sc->sln_state);
  231 
  232         ifp->if_softc = sc;
  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);
  241 
  242         /* initial media */
  243         ifmedia_init(&sc->ifmedia, 0, sln_media_upd, sln_media_stat);
  244 
  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);
  253 
  254         /* Choose a default media. */
  255         ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO);
  256 
  257         ether_ifattach(ifp, eaddr, NULL);
  258 
  259         ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->sln_irq));
  260 
  261         error = bus_setup_intr(dev, sc->sln_irq, INTR_MPSAFE, sln_interrupt, sc,
  262                                &sc->sln_intrhand, ifp->if_serializer);
  263         if (error) {
  264                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sln_irq);
  265                 bus_release_resource(dev, SL_RES, SL_RID, sc->sln_res);
  266                 ether_ifdetach(ifp);
  267                 device_printf(dev, "couldn't set up irq\n");
  268                 goto fail;
  269         }
  270 
  271         return 0;
  272 fail:
  273         return error;
  274 }
  275 
  276 /* Stop the adapter and free any mbufs allocated to the RX and TX buffers */
  277 static void
  278 sln_stop(struct sln_softc *sc)
  279 {
  280         struct ifnet *ifp = &sc->arpcom.ac_if;
  281         int i;
  282 
  283         ASSERT_SERIALIZED(ifp->if_serializer);
  284 
  285         ifp->if_timer = 0;
  286         callout_stop(&sc->sln_state);
  287 
  288         /* disable Tx/Rx */
  289         sc->txcfg &= ~SL_TXCFG_EN;
  290         sc->rxcfg &= ~SL_RXCFG_EN;
  291         SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
  292         SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
  293 
  294         /* Clear interrupt */
  295         SLN_WRITE_4(sc, SL_INT_MASK, 0);
  296         SLN_READ_4(sc, SL_INT_STATUS);
  297 
  298         /* Free the TX list buffers */
  299         for (i = 0; i < SL_TXD_CNT; i++) {
  300                 if (sc->sln_bufdata.sln_tx_buf[i] != NULL) {
  301                         m_freem(sc->sln_bufdata.sln_tx_buf[i]);
  302                         sc->sln_bufdata.sln_tx_buf[i] = NULL;
  303                         SLN_WRITE_4(sc, SL_TSAD0 + i * 4, 0);
  304                 }
  305         }
  306 
  307         ifp->if_flags &= ~IFF_RUNNING;
  308         ifq_clr_oactive(&ifp->if_snd);
  309 }
  310 
  311 static int
  312 sln_detach(device_t dev)
  313 {
  314         struct sln_softc *sc = device_get_softc(dev);
  315         struct ifnet *ifp = &sc->arpcom.ac_if;
  316 
  317         lwkt_serialize_enter(ifp->if_serializer);
  318         sln_stop(sc);
  319         bus_teardown_intr(dev, sc->sln_irq, sc->sln_intrhand);
  320         lwkt_serialize_exit(ifp->if_serializer);
  321 
  322         ether_ifdetach(ifp);
  323 
  324         bus_generic_detach(dev);
  325 
  326         bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sln_irq);
  327         bus_release_resource(dev, SL_RES, SL_RID, sc->sln_res);
  328         
  329         contigfree(sc->sln_bufdata.sln_rx_buf, SL_RX_BUFLEN, M_DEVBUF);
  330 
  331         return 0;
  332 }
  333 
  334 static int
  335 sln_media_upd(struct ifnet *ifp)
  336 {
  337         struct sln_softc *sc = ifp->if_softc;
  338         struct ifmedia *ifm = &sc->ifmedia;
  339 
  340         if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
  341                 return EINVAL;
  342 
  343         if (ifp->if_flags & IFF_UP)
  344                 sln_init(sc);
  345 
  346         return 0;
  347 }
  348 
  349 static void
  350 sln_media_stat(struct ifnet *ifp, struct ifmediareq *ifmr)
  351 {
  352         struct sln_softc *sc = ifp->if_softc;
  353         u_long phys[2];
  354         uint32_t temp;
  355 
  356         ifmr->ifm_status = IFM_AVALID;
  357         ifmr->ifm_active = IFM_ETHER;
  358 
  359         phys[0] = SL_MII_STAT;
  360         sln_mii_cmd(sc, SL_MII0_READ, phys);
  361 
  362         if (phys[1] & SL_MIISTAT_LINK)
  363                 ifmr->ifm_status |= IFM_ACTIVE;
  364 
  365         temp = SLN_READ_4(sc, SL_PHY_CTRL);
  366 
  367         if ((temp & (SL_PHYCTL_DUX | SL_PHYCTL_SPD100 | SL_PHYCTL_SPD10)) == 0x60800000)
  368                 ifmr->ifm_active |= IFM_AUTO;
  369         else if ((temp & (SL_PHYCTL_DUX | SL_PHYCTL_SPD100)) == 0x40800000)
  370                 ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
  371         else if ((temp & SL_PHYCTL_SPD100) == 0x40000000)
  372                 ifmr->ifm_active |= IFM_100_TX | IFM_HDX;
  373         else if ((temp & (SL_PHYCTL_DUX | SL_PHYCTL_SPD10)) == 0x20800000)
  374                 ifmr->ifm_active |= IFM_10_T | IFM_FDX;
  375         else if ((temp & SL_PHYCTL_SPD10) == 0x20000000)
  376                 ifmr->ifm_active |= IFM_10_T | IFM_HDX;
  377 
  378         sln_mii_cmd(sc, SL_MII0_SCAN, phys);
  379 }
  380 
  381 /* command selected in MII command register  */
  382 static void
  383 sln_mii_cmd(struct sln_softc *sc, uint32_t cmd, u_long *phys)
  384 {
  385         uint32_t mii_status;
  386 
  387         SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER);
  388 
  389         do {
  390                 mii_status = 0;
  391                 DELAY(10);
  392                 mii_status = SLN_READ_4(sc, SL_MII_STATUS);
  393         } while (mii_status & SL_MIISTAT_BUSY);
  394 
  395         switch (cmd) {
  396         case SL_MII0_SCAN:
  397                 SLN_WRITE_4(sc, SL_MII_CMD1, 0x1 << 6);
  398                 SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER | SL_MII0_SCAN);
  399                 break;
  400 
  401         case SL_MII0_READ:
  402                 SLN_WRITE_4(sc, SL_MII_CMD1, phys[0] << 6);
  403                 SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER | SL_MII0_READ);
  404                 break;
  405 
  406         default:                /* WRITE */
  407                 SLN_WRITE_4(sc, SL_MII_CMD1, phys[0] << 6 | phys[1] << 11);
  408                 SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER | SL_MII0_WRITE);
  409                 break;
  410         }
  411 
  412         do {
  413                 DELAY(10);
  414                 mii_status = SLN_READ_4(sc, SL_MII_STATUS);
  415         } while (mii_status & SL_MIISTAT_BUSY);
  416 
  417         if (SL_MII0_READ == cmd)
  418                 phys[1] = (mii_status >> 13) & 0xffff;
  419 }
  420 
  421 /* Set media speed and duplex mode */
  422 static void
  423 sln_media_cfg(struct sln_softc *sc)
  424 {
  425         u_long phys[2];
  426         uint32_t mediatype;
  427         uint32_t temp;
  428 
  429         mediatype = (&sc->ifmedia)->ifm_cur->ifm_media;
  430 
  431         temp = SLN_READ_4(sc, SL_PHY_CTRL);
  432         temp &= ~(SL_PHYCTL_DUX | SL_PHYCTL_SPD100 | SL_PHYCTL_SPD10);
  433         temp |= (SL_PHYCTL_ANE | SL_PHYCTL_RESET);
  434 
  435         /************************************************/
  436         /* currently set media word by selected media   */
  437         /*                                              */
  438         /* IFM_ETHER = 0x00000020                       */
  439         /* IFM_AUTO=0, IFM_10_T=3,  IFM_100_TX=6        */
  440         /* IFM_FDX=0x00100000    IFM_HDX=0x00200000     */
  441         /************************************************/
  442         switch (mediatype) {
  443         case 0x00000020:
  444                 PDEBUG(" autoselet supported\n");
  445                 temp |= (SL_PHYCTL_DUX | SL_PHYCTL_SPD100 | SL_PHYCTL_SPD10);
  446                 sc->ifmedia.ifm_media = IFM_ETHER | IFM_AUTO;
  447                 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO);
  448                 break;
  449         case 0x23:
  450         case 0x00200023:
  451                 PDEBUG(" 10Mbps half_duplex supported\n");
  452                 temp |= SL_PHYCTL_SPD10;
  453                 sc->ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_HDX;
  454                 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_HDX);
  455                 break;
  456 
  457         case 0x00100023:
  458                 PDEBUG("10Mbps full_duplex supported\n");
  459                 temp |= (SL_PHYCTL_SPD10 | SL_PHYCTL_DUX);
  460                 sc->ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_FDX;
  461                 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX);
  462                 break;
  463 
  464         case 0x26:
  465         case 0x00200026:
  466                 PDEBUG("100Mbps half_duplex supported\n");
  467                 temp |= SL_PHYCTL_SPD100;
  468                 sc->ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_HDX;
  469                 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_100_TX | IFM_HDX);
  470                 break;
  471 
  472         case 0x00100026:
  473                 PDEBUG("100Mbps full_duplex supported\n");
  474                 temp |= (SL_PHYCTL_SPD100 | SL_PHYCTL_DUX);
  475                 sc->ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_FDX;
  476                 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_100_TX | IFM_FDX);
  477                 break;
  478 
  479         default:
  480                 break;
  481         }
  482 
  483         SLN_WRITE_4(sc, SL_PHY_CTRL, temp);
  484 
  485         DELAY(10000);
  486         temp &= ~SL_PHYCTL_RESET;
  487         SLN_WRITE_4(sc, SL_PHY_CTRL, temp);
  488 
  489         DELAY(1000);
  490         phys[0] = SL_MII_JAB;
  491         phys[1] = SL_PHY_16_JAB_ENB | SL_PHY_16_PORT_ENB;
  492         sln_mii_cmd(sc, SL_MII0_WRITE, phys);
  493 
  494         sc->connect = 0;
  495         sln_mii_cmd(sc, SL_MII0_SCAN, phys);
  496 }
  497 
  498 static void
  499 sln_mac_cfg(struct sln_softc *sc)
  500 {
  501         struct ifnet *ifp = &sc->arpcom.ac_if;
  502         u_long flowcfg = 0;
  503 
  504         /* Set the initial TX/RX/Flow Control configuration */
  505         sc->rxcfg = SL_RXCFG_LOW_THRESHOLD | SL_RXCFG_HIGH_THRESHOLD;
  506         sc->txcfg = TX_CFG_DEFAULT;
  507 
  508         if (sc->txenablepad)
  509                 sc->txcfg |= 0x20000000;
  510 
  511         if (sc->media_speed == IFM_10_T)
  512                 sc->txcfg |= SL_TXCFG_DATARATE;
  513 
  514         if (sc->media_duplex == IFM_FDX) {
  515                 sc->rxcfg |= SL_RXCFG_FULLDX;
  516                 sc->txcfg |= SL_TXCFG_FULLDX;
  517                 flowcfg = SL_FLOWCTL_FULLDX | SL_FLOWCTL_EN;
  518         } else {
  519                 sc->rxcfg &= ~SL_RXCFG_FULLDX;
  520                 sc->txcfg &= ~SL_TXCFG_FULLDX;
  521         }
  522 
  523         /* if promiscuous mode, set the allframes bit. */
  524         if (ifp->if_flags & IFF_PROMISC)
  525                 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);
  526         else
  527                 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 
  529         /* Set capture broadcast bit to capture broadcast frames */
  530         if (ifp->if_flags & IFF_BROADCAST)
  531                 sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_BROAD;
  532         else
  533                 sc->rxcfg &= ~(SL_RXCFG_EN | SL_RXCFG_RCV_BROAD);
  534 
  535         /* Program the multicast filter, if necessary */
  536         sln_set_multi(sc);
  537 
  538         SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
  539         SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
  540         SLN_WRITE_4(sc, SL_FLOW_CTRL, flowcfg);
  541 }
  542 
  543 static u_char shade_map[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
  544                               0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
  545 
  546 /* Calculate CRC32 of a multicast group address */
  547 static uint32_t
  548 sln_ether_crc32(caddr_t addr)
  549 {
  550         uint32_t crc, crcr;
  551         int i, j;
  552         unsigned char data = 0;
  553         /* Compute CRC for the address value. */
  554 
  555         crc = 0xFFFFFFFF;       /* initial value */
  556 
  557         for (i = ETHER_ADDR_LEN; i > 0; i--) {
  558                 data = *addr++;
  559 
  560                 for (j = 0; j < 8; j++) {
  561                         if (((data & 0x1) ^ (crc & 0x1)) != 0) {
  562                                 crc >>= 1;
  563                                 crc ^= 0xEDB88320;
  564                         } else {
  565                                 crc >>= 1;
  566                         }
  567                         data >>= 1;
  568                 }
  569         }
  570 
  571         crcr = shade_map[crc >> 28];
  572         crcr |= (shade_map[(crc >> 24) & 0xf] << 4);
  573         crcr |= (shade_map[(crc >> 20) & 0xf] << 8);
  574         crcr |= (shade_map[(crc >> 16) & 0xf] << 12);
  575         crcr |= (shade_map[(crc >> 12) & 0xf] << 16);
  576         crcr |= (shade_map[(crc >> 8) & 0xf] << 20);
  577         crcr |= (shade_map[(crc >> 4) & 0xf] << 24);
  578         crcr |= (shade_map[crc & 0xf] << 28);
  579 
  580         return crcr;
  581 }
  582 
  583 /* Program the 64-bit multicast hash filter */
  584 static void
  585 sln_set_multi(struct sln_softc *sc)
  586 {
  587         struct ifnet *ifp = &sc->arpcom.ac_if;
  588         uint32_t crc = 0;
  589         uint32_t mc_g[2] = {0, 0};
  590         struct ifmultiaddr *ifma;
  591         int j;
  592 
  593         if (ifp->if_flags & IFF_PROMISC) {
  594                 kprintf("Promisc mode is enabled\n");
  595                 sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_MULTI;
  596                 mc_g[0] = mc_g[1] = 0xFFFFFFFF;
  597         } else if (ifp->if_flags & IFF_ALLMULTI) {
  598                 kprintf("Allmulti mode is enabled\n");
  599                 sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_MULTI;
  600                 mc_g[0] = mc_g[1] = 0xFFFFFFFF;
  601         } else if (ifp->if_flags & IFF_MULTICAST) {
  602                 kprintf("Multicast mode is enabled\n");
  603                 sc->rxcfg |= SL_RXCFG_EN | SL_RXCFG_RCV_MULTI;
  604 
  605                 /* first, zero all the existing hash bits */
  606                 mc_g[0] = mc_g[1] = 0;
  607 
  608                 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
  609                         j = 0;
  610 
  611                         if ((ifma->ifma_addr->sa_family) != AF_LINK)
  612                                 continue;
  613 
  614                         crc = ~sln_ether_crc32(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
  615                         crc >>= 24;
  616 
  617                         if (crc & 0x1)
  618                                 j |= 0x2;
  619                         if (crc & 0x2)
  620                                 j |= 0x1;
  621                         if (crc & 0x10)
  622                                 j |= 0x20;
  623                         if (crc & 0x20)
  624                                 j |= 0x10;
  625                         if (crc & 0x40)
  626                                 j |= 0x8;
  627                         if (crc & 0x80)
  628                                 j |= 0x4;
  629 
  630                         if (j > 31)
  631                                 mc_g[0] |= (0x1 << (j - 32));
  632                         else
  633                                 mc_g[1] |= (0x1 << j);
  634                 }
  635         } else {
  636                 sc->rxcfg &= ~(SL_RXCFG_EN | SL_RXCFG_RCV_MULTI);
  637         }
  638 
  639         SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
  640         SLN_WRITE_4(sc, SL_MULTI_GROUP0, mc_g[0]);
  641         SLN_WRITE_4(sc, SL_MULTI_GROUP1, mc_g[1]);
  642 }
  643 
  644 /* Initialize the TX/Rx descriptors */
  645 static void
  646 sln_init_tx(struct sln_softc *sc)
  647 {
  648         int i;
  649 
  650         sc->sln_bufdata.cur_tx = 0;
  651         sc->sln_bufdata.dirty_tx = 0;
  652 
  653         for (i = 0; i < SL_TXD_CNT; i++) {
  654                 sc->sln_bufdata.sln_tx_buf[i] = NULL;
  655                 SLN_WRITE_4(sc, SL_TSAD0 + (i * 4), 0);
  656         }
  657 }
  658 
  659 /* Software & Hardware Initialize */
  660 static void
  661 sln_init(void *x)
  662 {
  663         struct sln_softc *sc = x;
  664         struct ifnet *ifp = &sc->arpcom.ac_if;
  665 
  666         PDEBUG("sln_init\n");
  667 
  668         ASSERT_SERIALIZED(ifp->if_serializer);
  669 
  670         sln_stop(sc);
  671 
  672         /* soft reset the chip */
  673         sln_reset(sc);
  674 
  675         /* disable interrupt */
  676         SLN_WRITE_4(sc, SL_INT_MASK, 0);
  677 
  678         /* SLN_WRITE_4(sc, SL_MII_CMD0, SL_MII0_DIVEDER); */
  679 
  680         /* clear multicast address */
  681         SLN_WRITE_4(sc, SL_MULTI_GROUP0, 0);
  682         SLN_WRITE_4(sc, SL_MULTI_GROUP1, 0);
  683 
  684         /* Init the RX buffer start address register. */
  685         SLN_WRITE_4(sc, SL_RBSA, vtophys(sc->sln_bufdata.sln_rx_buf));
  686         sc->sln_bufdata.dirty_rx = vtophys(sc->sln_bufdata.sln_rx_buf);
  687 
  688         /* Init TX descriptors. */
  689         sln_init_tx(sc);
  690 
  691         /* configure RX buffer size */
  692         if (sc->tx_early_ctrl && sc->rx_early_ctrl)
  693                 SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_RX | SL_EARLY_TX | SL_RXBUF_64 | SL_RXFIFO_1024BYTES);
  694         else if (sc->tx_early_ctrl)
  695                 SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_TX | SL_RXBUF_64);
  696         else if (sc->rx_early_ctrl)
  697                 SLN_WRITE_4(sc, SL_CFG1, SL_EARLY_RX | SL_RXBUF_64 | SL_RXFIFO_1024BYTES);
  698         else
  699                 SLN_WRITE_4(sc, SL_CFG1, SL_RXBUF_64);
  700 
  701         /* MII media configuration */
  702         sln_media_cfg(sc);
  703 
  704         if (sc->connect) {
  705                 /* Enable transmit and receive */
  706                 sc->rxcfg |= SL_RXCFG_EN;
  707                 sc->txcfg |= SL_TXCFG_EN;
  708         } else {
  709                 sc->rxcfg &= ~SL_RXCFG_EN;
  710                 sc->txcfg &= ~SL_TXCFG_EN;
  711         }
  712 
  713         SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
  714         SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
  715 
  716         /* Enable interrupts */
  717         SLN_WRITE_4(sc, SL_INT_MASK, SL_INRTS);
  718 
  719         sc->suspended = 0;
  720 
  721         ifp->if_flags |= IFF_RUNNING;
  722         ifq_clr_oactive(&ifp->if_snd);
  723 
  724         callout_reset(&sc->sln_state, hz, sln_tick, sc);
  725 }
  726 
  727 /* Transmit Packet */
  728 static void
  729 sln_tx(struct ifnet *ifp, struct ifaltq_subque *ifsq)
  730 {
  731         struct sln_softc *sc = ifp->if_softc;
  732         struct mbuf *m_head = NULL;
  733         struct mbuf *m_new = NULL;
  734         int entry;
  735 
  736         ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
  737         ASSERT_SERIALIZED(ifp->if_serializer);
  738 
  739         if (!sc->connect) {
  740                 ifq_purge(&ifp->if_snd);
  741                 return;
  742         }
  743 
  744         if ((ifp->if_flags & IFF_RUNNING) == 0 || ifq_is_oactive(&ifp->if_snd))
  745                 return;
  746 
  747         while (SL_CUR_TXBUF(sc) == NULL) {      /* SL_CUR_TXBUF(x) = x->sln_bufdata.sln_tx_buf[x->sln_bufdata.cur_tx] */
  748                 entry = sc->sln_bufdata.cur_tx;
  749 
  750                 m_head = ifq_dequeue(&ifp->if_snd);
  751                 if (m_head == NULL)
  752                         break;
  753 
  754                 MGETHDR(m_new, MB_DONTWAIT, MT_DATA);
  755                 if (m_new == NULL) {
  756                         if_printf(ifp, "no memory for tx descriptor");
  757                         m_freem(m_head);
  758                         break;
  759                 }
  760                 if ((m_head->m_pkthdr.len > MHLEN) || (60 > MHLEN)) {
  761                         MCLGET(m_new, MB_DONTWAIT);
  762                         if (!(m_new->m_flags & M_EXT)) {
  763                                 m_freem(m_new);
  764                                 m_freem(m_head);
  765                                 if_printf(ifp, "no memory for tx descriptor");
  766                                 break;
  767                         }
  768                 }
  769                 m_copydata(m_head, 0, m_head->m_pkthdr.len, mtod(m_new, caddr_t));
  770                 m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
  771                 m_freem(m_head);
  772                 m_head = m_new;
  773                 SL_CUR_TXBUF(sc) = m_head;
  774 
  775                 /*
  776                  * if there's a BPF listener, bounce a copy of this frame to
  777                  * him
  778                  */
  779                 BPF_MTAP(ifp, SL_CUR_TXBUF(sc));
  780 
  781                 /* Transmit the frame */
  782                 SLN_WRITE_4(sc, ((entry * 4) + SL_TSAD0),
  783                     vtophys(mtod(SL_CUR_TXBUF(sc), caddr_t)));
  784 
  785                 /* calculate length of the frame */
  786                 if ((SL_CUR_TXBUF(sc)->m_pkthdr.len < 60) && (!sc->txenablepad)) {
  787                         memset(mtod(m_head, char *)+m_head->m_pkthdr.len, 0x20, 60 - m_head->m_pkthdr.len);
  788                         SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 60);
  789                 } else if (SL_CUR_TXBUF(sc)->m_pkthdr.len < 100)
  790                         SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, SL_CUR_TXBUF(sc)->m_pkthdr.len);
  791                 else if (SL_CUR_TXBUF(sc)->m_pkthdr.len < 300)
  792                         SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 0x30000 | SL_CUR_TXBUF(sc)->m_pkthdr.len);
  793                 else
  794                         SLN_WRITE_4(sc, (entry * 4) + SL_TSD0, 0x50000 | SL_CUR_TXBUF(sc)->m_pkthdr.len);
  795                 sc->sln_bufdata.cur_tx = (entry + 1) % SL_TXD_CNT;
  796 
  797                 PDEBUG("Queue tx packet size %d to tx-descriptor %d.\n", m_head->m_pkthdr.len, entry);
  798         }
  799 
  800         /* Tx buffer chain full */
  801         if (SL_CUR_TXBUF(sc) != NULL)
  802                 ifq_set_oactive(&ifp->if_snd);
  803 
  804         /* Set a timeout in case the chip goes out to lunch */
  805         ifp->if_timer = 5;
  806 }
  807 
  808 /* Receive Data handler */
  809 static void
  810 sln_rx(struct sln_softc *sc)
  811 {
  812         struct mbuf *m;
  813         struct ifnet *ifp = &sc->arpcom.ac_if;
  814         uint32_t rxstat = 0;
  815         uint32_t rx_offset;
  816         caddr_t rx_bufpos = NULL;
  817         uint32_t cur_rx = 0;
  818         uint32_t dirty_rx;
  819         long rx_len;
  820         u_long rx_space;
  821         u_long rx_size = 0;
  822         u_long rx_size_align = 0;
  823         u_long pkt_size = 0;
  824 
  825         cur_rx = SLN_READ_4(sc, SL_RBW_PTR);
  826         dirty_rx = sc->sln_bufdata.dirty_rx;
  827 
  828         /*
  829          * cur_rx is only 17 bits in the RxBufWPtr register. if cur_rx can be
  830          * used in physical space, we need to change it to 32 bits physical
  831          * address
  832          */
  833         cur_rx |= vtophys(sc->sln_bufdata.sln_rx_buf) & (~(u_long) (SL_RX_BUFLEN - 1));
  834 
  835         if (cur_rx < vtophys(sc->sln_bufdata.sln_rx_buf))
  836                 cur_rx += SL_RX_BUFLEN;
  837 
  838         if (cur_rx >= dirty_rx)
  839                 rx_len = (long)(cur_rx - dirty_rx);
  840         else
  841                 rx_len = SL_RX_BUFLEN - (long)(dirty_rx - cur_rx);
  842 
  843         if ((rx_len > SL_RX_BUFLEN) || (rx_len < 0)) {
  844                 if_printf(ifp, "rx len is fail\n");
  845                 return;
  846         }
  847         if (rx_len == 0)
  848                 return;
  849 
  850         rx_offset = (dirty_rx - vtophys(sc->sln_bufdata.sln_rx_buf)) & (u_long) (SL_RX_BUFLEN - 1);
  851 
  852         while (rx_len > 0) {
  853 #ifdef SLN_DEBUG
  854                 u_long ipkts;
  855 #endif
  856 
  857                 rx_bufpos = sc->sln_bufdata.sln_rx_buf + rx_offset;
  858                 rxstat = *(uint32_t *) rx_bufpos;
  859                 rx_size = (rxstat >> 20) & 0x0FFF;
  860                 rx_size_align = (rx_size + 3) & ~3;     /* for 4 bytes aligned */
  861                 pkt_size = rx_size - ETHER_CRC_LEN;     /* Omit the four octet
  862                                                          * CRC from the length. */
  863 
  864                 PDEBUG("rx len: %ld  rx frame size:%ld  rx state:0x%x\n", rx_len, rx_size, rxstat);
  865 
  866                 /* errors receive packets caculatation */
  867                 if (rxstat == 0 || rx_size < 16 || !(rxstat & SL_RXSTAT_RXOK)) {
  868                         IFNET_STAT_INC(ifp, ierrors, 1);
  869 
  870                         if (!(rxstat & SL_RXSTAT_RXOK))
  871                                 if_printf(ifp, "receiver ok error\n");
  872 
  873                         if (!(rxstat & SL_RXSTAT_CRCOK))
  874                                 if_printf(ifp, "crc error\n");
  875 
  876                         if (rxstat & SL_RXSTAT_ALIGNERR)
  877                                 if_printf(ifp, "frame alignment error\n");
  878 
  879                         if (rxstat & (SL_RXSTAT_HUGEFRM | SL_RXSTAT_SMALLFRM))
  880                                 if_printf(ifp, "received frame length is error\n");
  881 
  882                         break;
  883                 }
  884                 rx_len -= (long)(rx_size_align + 4);    /* 4 bytes for receive
  885                                                          * frame head */
  886 
  887                 if (rx_len < 0) {
  888                         kprintf("rx packets len is too small\n");
  889                         break;
  890                 }
  891 #ifdef SLN_PDEBUG
  892                 caddr_t p = NULL;
  893 
  894                 if_printf(ifp, "rx frame content\n");
  895                 p = rx_bufpos;
  896                 for (i = 0; i < 30; i++, p++) {
  897                         if (i % 10 == 0)
  898                                 kprintf("\n");
  899                         if_printf(ifp, "%x  ", (u_char)*p);
  900                 }
  901                 if_printf(ifp, "\n");
  902 #endif
  903                 /* No errors; receive the packet. */
  904                 if (rx_bufpos == (sc->sln_bufdata.sln_rx_buf + SL_RX_BUFLEN))
  905                         rx_bufpos = sc->sln_bufdata.sln_rx_buf;
  906 
  907                 rx_bufpos = rx_bufpos + 4;      /* 4 bytes for receive frame
  908                                                  * header */
  909                 rx_space = (u_long)((sc->sln_bufdata.sln_rx_buf + SL_RX_BUFLEN) - rx_bufpos);
  910 
  911                 if (pkt_size > rx_space) {
  912                         m = m_devget(rx_bufpos - 2, pkt_size + 2, 0, ifp, NULL);        /* 2 for etherer head
  913                                                                                          * align */
  914 
  915                         if (m == NULL) {
  916                                 IFNET_STAT_INC(ifp, ierrors, 1);
  917                                 if_printf(ifp,
  918                                     "out of mbufs, tried to copy %ld bytes\n",
  919                                     rx_space);
  920                         } else {
  921                                 m_adj(m, 2);
  922                                 m_copyback(m, rx_space, pkt_size - rx_space, sc->sln_bufdata.sln_rx_buf);
  923                         }
  924                 } else {
  925                         m = m_devget(rx_bufpos - 2, pkt_size + 2, 0, ifp, NULL);
  926 
  927                         if (m == NULL) {
  928                                 u_long ierr;
  929 
  930                                 IFNET_STAT_INC(ifp, ierrors, 1);
  931                                 if_printf(ifp,
  932                                     "out of mbufs, tried to copy %ld bytes\n",
  933                                     pkt_size);
  934 
  935                                 IFNET_STAT_GET(ifp, ierrors, ierr);
  936                                 if_printf(ifp, "ierrors = %lu\n", ierr);
  937                         } else {
  938                                 m_adj(m, 2);
  939                         }
  940                 }
  941 
  942                 IFNET_STAT_INC(ifp, ipackets, 1);
  943 #ifdef SLN_DEBUG
  944                 IFNET_STAT_GET(ifp, ipackets, ipkts);
  945                 PDEBUG("ipackets = %lu\n", ipkts);
  946 #endif
  947 
  948                 ifp->if_input(ifp, m);
  949 
  950                 rx_offset = (rx_offset + rx_size + 4) & (u_long) (SL_RX_BUFLEN - 1);    /* 4 bytes for receive
  951                                                                                          * frame head */
  952         }
  953 
  954         sc->sln_bufdata.dirty_rx = cur_rx;
  955 
  956         SLN_WRITE_4(sc, SL_RBR_PTR, cur_rx);
  957 }
  958 
  959 /* Transmit OK/ERR handler */
  960 static void
  961 sln_tx_intr(struct sln_softc *sc)
  962 {
  963         struct ifnet *ifp = &sc->arpcom.ac_if;
  964         uint32_t txstat;
  965         int entry;
  966 
  967         do {
  968                 entry = sc->sln_bufdata.dirty_tx;
  969                 txstat = SLN_READ_4(sc, SL_TSD0 + entry * 4);
  970 
  971                 if (!(txstat & (SL_TXSD_TOK | SL_TXSD_TUN | SL_TXSD_TABT)))
  972                         break;  /* It still hasn't been sent */
  973 
  974                 if (SL_DIRTY_TXBUF(sc) != NULL) {       /* SL_DIRTY_TXBUF(x) =
  975                                                          * x->sln_bufdata.sln_tx_
  976                                                          * buf[x->sln_bufdata.dir
  977                                                          * ty_tx] */
  978                         m_freem(SL_DIRTY_TXBUF(sc));
  979                         SL_DIRTY_TXBUF(sc) = NULL;
  980                 }
  981                 if (txstat & SL_TXSD_TOK) {
  982 #ifdef SLN_DEBUG
  983                         u_long opkts;
  984 #endif
  985 
  986                         IFNET_STAT_INC(ifp, opackets, 1);
  987                         IFNET_STAT_INC(ifp, obytes, txstat & SL_TXSD_LENMASK);
  988 #ifdef SLN_DEBUG
  989                         IFNET_STAT_GET(ifp, opackets, opkts);
  990                         PDEBUG("opackets = %lu\n", opkts);
  991 #endif
  992                         IFNET_STAT_INC(ifp, collisions,
  993                             (txstat & SL_TXSD_NCC) >> 22);
  994                 } else {
  995                         IFNET_STAT_INC(ifp, oerrors, 1);
  996                         if ((txstat & (SL_TXSD_TABT | SL_TXSD_OWC))) {
  997                                 sc->txcfg = TX_CFG_DEFAULT;
  998 
  999                                 if (sc->txenablepad)
 1000                                         sc->txcfg |= 0x20000000;
 1001 
 1002                                 SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
 1003                         }
 1004                 }
 1005                 PDEBUG("tx done descriprtor %x\n", entry);
 1006                 sc->sln_bufdata.dirty_tx = (entry + 1) % SL_TXD_CNT;
 1007 
 1008                 ifq_clr_oactive(&ifp->if_snd);
 1009         } while (sc->sln_bufdata.dirty_tx != sc->sln_bufdata.cur_tx);
 1010 
 1011         if (sc->sln_bufdata.dirty_tx == sc->sln_bufdata.cur_tx)
 1012                 ifp->if_timer = 0;
 1013         else
 1014                 ifp->if_timer = 5;
 1015 }
 1016 
 1017 static void
 1018 sln_media_intr(struct sln_softc *sc)
 1019 {
 1020         u_long phys[2];
 1021         struct ifnet *ifp = &sc->arpcom.ac_if;
 1022 
 1023         phys[0] = SL_MII_STAT;
 1024         sln_mii_cmd(sc, SL_MII0_READ, phys);
 1025 
 1026         PDEBUG("mii_stat:0x%lx\n", phys[1]);
 1027 
 1028         if (0 == (phys[1] & SL_MIISTAT_LINK)) {
 1029                 kprintf("media is unconnect,linked down,or uncompatible\n");
 1030                 sc->connect = 0;
 1031                 sln_mii_cmd(sc, SL_MII0_SCAN, phys);
 1032                 /* disable tx/rx */
 1033                 sc->txcfg &= ~SL_TXCFG_EN;
 1034                 sc->rxcfg &= ~SL_RXCFG_EN;
 1035                 SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
 1036                 SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
 1037 
 1038                 return;
 1039         }
 1040         /* Link is good. Report modes and set duplex mode. */
 1041         PDEBUG("media is connecting---> ");
 1042         sc->connect = 1;
 1043 
 1044         phys[0] = SL_MII_STAT_OUTPUT;
 1045         sln_mii_cmd(sc, SL_MII0_READ, phys);
 1046         sc->media_duplex = ((phys[1] & 0x0004) == 0) ? IFM_HDX : IFM_FDX;
 1047         sc->media_speed = ((phys[1] & 0x0002) == 0) ? IFM_10_T : IFM_100_TX;
 1048 
 1049         if_printf(ifp, "media option:%dM %s-duplex\n",
 1050             sc->media_speed == 0x6 ? 100 : 10,
 1051             sc->media_duplex == 0x100000 ? "full" : "half");
 1052 
 1053         sln_mii_cmd(sc, SL_MII0_SCAN, phys);
 1054 
 1055         sln_mac_cfg(sc);
 1056 
 1057         /* Enable tx/rx */
 1058         sc->rxcfg |= SL_RXCFG_EN;
 1059         sc->txcfg |= SL_TXCFG_EN;
 1060         SLN_WRITE_4(sc, SL_TX_CONFIG, sc->txcfg);
 1061         SLN_WRITE_4(sc, SL_RX_CONFIG, sc->rxcfg);
 1062 }
 1063 
 1064 /* Interrupt Handler */
 1065 static void
 1066 sln_interrupt(void *arg)
 1067 {
 1068         struct sln_softc *sc = arg;
 1069         struct ifnet *ifp = &sc->arpcom.ac_if;
 1070         uint32_t int_status;
 1071 
 1072         ASSERT_SERIALIZED(ifp->if_serializer);
 1073 
 1074         if (sc->suspended || (ifp->if_flags & IFF_RUNNING) == 0)
 1075                 return;
 1076 
 1077         /* Disable interrupts. */
 1078         SLN_WRITE_4(sc, SL_INT_MASK, 0);
 1079 
 1080         int_status = SLN_READ_4(sc, SL_INT_STATUS);
 1081 
 1082         if ((int_status == 0xffffffff) || (int_status & SL_INRTS) == 0)
 1083                 goto back;
 1084 
 1085         int_status = int_status & SL_INRTS;
 1086         PDEBUG("int_status = 0x%x\n", int_status);
 1087 
 1088         while (0 != int_status) {
 1089                 if (int_status & SL_INT_ROK)
 1090                         sln_rx(sc);
 1091 
 1092                 if (int_status & SL_INT_TOK)
 1093                         sln_tx_intr(sc);
 1094 
 1095                 if (int_status & SL_INT_RBO) {
 1096                         IFNET_STAT_INC(ifp, ierrors, 1);
 1097                         PDEBUG("rx buffer is overflow\n");
 1098                 }
 1099 
 1100                 if (int_status & (SL_INT_LINKFAIL | SL_INT_LINKOK))
 1101                         sln_media_intr(sc);
 1102 
 1103                 int_status = SLN_READ_4(sc, SL_INT_STATUS);
 1104         }
 1105 
 1106         /* Data in Tx buffer waiting for transimission */
 1107         if (!ifq_is_empty(&ifp->if_snd))
 1108                 if_devstart(ifp);
 1109 back:
 1110         /* Re-enable interrupts. */
 1111         SLN_WRITE_4(sc, SL_INT_MASK, SL_INRTS);
 1112 }
 1113 
 1114 static void
 1115 sln_tick(void *x)
 1116 {
 1117         struct sln_softc *sc = x;
 1118 
 1119         callout_reset(&sc->sln_state, hz, sln_tick, sc);
 1120 }
 1121 
 1122 static int
 1123 sln_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
 1124 {
 1125         struct sln_softc *sc = ifp->if_softc;
 1126         struct ifreq *ifr = (struct ifreq *)data;
 1127         int error = 0;
 1128 
 1129         ASSERT_SERIALIZED(ifp->if_serializer);
 1130 
 1131         switch (cmd) {
 1132         case SIOCSIFFLAGS:
 1133                 if (ifp->if_flags & IFF_UP) {
 1134                         if ((ifp->if_flags & IFF_RUNNING) == 0)
 1135                                 sln_init(sc);
 1136                 } else {
 1137                         if (ifp->if_flags & IFF_RUNNING)
 1138                                 sln_stop(sc);
 1139                 }
 1140                 break;
 1141         case SIOCADDMULTI:
 1142         case SIOCDELMULTI:
 1143                 sln_set_multi(sc);
 1144                 break;
 1145         case SIOCGIFMEDIA:
 1146         case SIOCSIFMEDIA:
 1147                 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd);
 1148                 break;
 1149         default:
 1150                 error = ether_ioctl(ifp, cmd, data);
 1151                 break;
 1152         }
 1153         return error;
 1154 }
 1155 
 1156 static void
 1157 sln_watchdog(struct ifnet *ifp)
 1158 {
 1159         struct sln_softc *sc = ifp->if_softc;
 1160 
 1161         ASSERT_SERIALIZED(ifp->if_serializer);
 1162 
 1163         if_printf(ifp, "watchdog timeout!\n");
 1164         IFNET_STAT_INC(ifp, oerrors, 1);
 1165 
 1166         sln_tx_intr(sc);
 1167         sln_rx(sc);
 1168         sln_init(sc);
 1169 
 1170         if (!ifq_is_empty(&ifp->if_snd))
 1171                 if_devstart(ifp);
 1172 }
 1173 
 1174 /* Stop all chip I/O */
 1175 static int
 1176 sln_shutdown(device_t dev)
 1177 {
 1178         struct sln_softc *sc = device_get_softc(dev);
 1179         struct ifnet *ifp = &sc->arpcom.ac_if;
 1180 
 1181         lwkt_serialize_enter(ifp->if_serializer);
 1182         sln_stop(sc);
 1183         lwkt_serialize_exit(ifp->if_serializer);
 1184 
 1185         return 0;
 1186 }
 1187 
 1188 /* device suspend routine */
 1189 static int
 1190 sln_suspend(device_t dev)
 1191 {
 1192         struct sln_softc *sc = device_get_softc(dev);
 1193         struct ifnet *ifp = &sc->arpcom.ac_if;
 1194 
 1195         lwkt_serialize_enter(ifp->if_serializer);
 1196         sln_stop(sc);
 1197         sc->suspended = 1;
 1198         lwkt_serialize_exit(ifp->if_serializer);
 1199 
 1200         return 0;
 1201 }
 1202 
 1203 /* device resume routine */
 1204 static int
 1205 sln_resume(device_t dev)
 1206 {
 1207         struct sln_softc *sc = device_get_softc(dev);
 1208         struct ifnet *ifp = &sc->arpcom.ac_if;
 1209 
 1210         lwkt_serialize_enter(ifp->if_serializer);
 1211         if (ifp->if_flags & IFF_UP)
 1212                 sln_init(sc);
 1213         sc->suspended = 0;
 1214         lwkt_serialize_exit(ifp->if_serializer);
 1215 
 1216         return 0;
 1217 }

Cache object: 2a1f22377bbc39910a3be87690e99af4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.