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/arm/allwinner/if_emac.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) 2013 Ganbold Tsagaankhuu <ganbold@freebsd.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    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 the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD: releng/10.2/sys/arm/allwinner/if_emac.c 266337 2014-05-17 18:53:36Z ian $
   27  */
   28 
   29 /* A10/A20 EMAC driver */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/10.2/sys/arm/allwinner/if_emac.c 266337 2014-05-17 18:53:36Z ian $");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/kernel.h>
   37 #include <sys/module.h>
   38 #include <sys/bus.h>
   39 #include <sys/lock.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/mutex.h>
   42 #include <sys/rman.h>
   43 #include <sys/socket.h>
   44 #include <sys/sockio.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/gpio.h>
   47 
   48 #include <machine/bus.h>
   49 #include <machine/resource.h>
   50 #include <machine/intr.h>
   51 
   52 #include <net/if.h>
   53 #include <net/if_var.h>
   54 #include <net/if_arp.h>
   55 #include <net/if_dl.h>
   56 #include <net/if_media.h>
   57 #include <net/if_types.h>
   58 #include <net/if_mib.h>
   59 #include <net/ethernet.h>
   60 #include <net/if_vlan_var.h>
   61 
   62 #ifdef INET
   63 #include <netinet/in.h>
   64 #include <netinet/in_systm.h>
   65 #include <netinet/in_var.h>
   66 #include <netinet/ip.h>
   67 #endif
   68 
   69 #include <net/bpf.h>
   70 #include <net/bpfdesc.h>
   71 
   72 #include <dev/fdt/fdt_common.h>
   73 #include <dev/ofw/ofw_bus.h>
   74 #include <dev/ofw/ofw_bus_subr.h>
   75 
   76 #include <dev/mii/mii.h>
   77 #include <dev/mii/miivar.h>
   78 
   79 #include <arm/allwinner/if_emacreg.h>
   80 
   81 #include "miibus_if.h"
   82 
   83 #include "gpio_if.h"
   84 
   85 #include "a10_clk.h"
   86 #include "a10_sramc.h"
   87 #include "a10_gpio.h"
   88 
   89 struct emac_softc {
   90         struct ifnet            *emac_ifp;
   91         device_t                emac_dev;
   92         device_t                emac_miibus;
   93         bus_space_handle_t      emac_handle;
   94         bus_space_tag_t         emac_tag;
   95         struct resource         *emac_res;
   96         struct resource         *emac_irq;
   97         void                    *emac_intrhand;
   98         int                     emac_if_flags;
   99         struct mtx              emac_mtx;
  100         struct callout          emac_tick_ch;
  101         int                     emac_watchdog_timer;
  102         int                     emac_rx_process_limit;
  103         int                     emac_link;
  104 };
  105 
  106 static int      emac_probe(device_t);
  107 static int      emac_attach(device_t);
  108 static int      emac_detach(device_t);
  109 static int      emac_shutdown(device_t);
  110 static int      emac_suspend(device_t);
  111 static int      emac_resume(device_t);
  112 
  113 static void     emac_sys_setup(void);
  114 static void     emac_reset(struct emac_softc *);
  115 
  116 static void     emac_init_locked(struct emac_softc *);
  117 static void     emac_start_locked(struct ifnet *);
  118 static void     emac_init(void *);
  119 static void     emac_stop_locked(struct emac_softc *);
  120 static void     emac_intr(void *);
  121 static int      emac_ioctl(struct ifnet *, u_long, caddr_t);
  122 
  123 static void     emac_rxeof(struct emac_softc *, int);
  124 static void     emac_txeof(struct emac_softc *);
  125 
  126 static int      emac_miibus_readreg(device_t, int, int);
  127 static int      emac_miibus_writereg(device_t, int, int, int);
  128 static void     emac_miibus_statchg(device_t);
  129 
  130 static int      emac_ifmedia_upd(struct ifnet *);
  131 static void     emac_ifmedia_sts(struct ifnet *, struct ifmediareq *);
  132 
  133 static int      sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int);
  134 static int      sysctl_hw_emac_proc_limit(SYSCTL_HANDLER_ARGS);
  135 
  136 #define EMAC_READ_REG(sc, reg)          \
  137     bus_space_read_4(sc->emac_tag, sc->emac_handle, reg)
  138 #define EMAC_WRITE_REG(sc, reg, val)    \
  139     bus_space_write_4(sc->emac_tag, sc->emac_handle, reg, val)
  140 
  141 static void
  142 emac_sys_setup(void)
  143 {
  144         int i;
  145 
  146         a10_clk_emac_activate();
  147 
  148         /*
  149          * Configure pin mux settings for MII.
  150          * Pins PA0 from PA17.
  151          */
  152         for (i = 0; i <= 17; i++)
  153                 a10_emac_gpio_config(i);
  154         /* Map sram */
  155         a10_map_to_emac();
  156 }
  157 
  158 static void
  159 emac_get_hwaddr(struct emac_softc *sc, uint8_t *hwaddr)
  160 {
  161         uint32_t val0, val1, rnd;
  162 
  163         /*
  164          * Try to get MAC address from running hardware.
  165          * If there is something non-zero there just use it.
  166          *
  167          * Otherwise set the address to a convenient locally assigned address,
  168          * 'bsd' + random 24 low-order bits. 'b' is 0x62, which has the locally
  169          * assigned bit set, and the broadcast/multicast bit clear.
  170          */
  171         val0 = EMAC_READ_REG(sc, EMAC_MAC_A0);
  172         val1 = EMAC_READ_REG(sc, EMAC_MAC_A1);
  173         if ((val0 | val1) != 0 && (val0 | val1) != 0xffffff) {
  174                 hwaddr[0] = (val1 >> 16) & 0xff;
  175                 hwaddr[1] = (val1 >> 8) & 0xff;
  176                 hwaddr[2] = (val1 >> 0) & 0xff;
  177                 hwaddr[3] = (val0 >> 16) & 0xff;
  178                 hwaddr[4] = (val0 >> 8) & 0xff;
  179                 hwaddr[5] = (val0 >> 0) & 0xff;
  180         } else {
  181                 rnd = arc4random() & 0x00ffffff;
  182                 hwaddr[0] = 'b';
  183                 hwaddr[1] = 's';
  184                 hwaddr[2] = 'd';
  185                 hwaddr[3] = (rnd >> 16) & 0xff;
  186                 hwaddr[4] = (rnd >> 8) & 0xff;
  187                 hwaddr[5] = (rnd >> 0) & 0xff;
  188         }
  189         if (bootverbose)
  190                 printf("MAC address: %s\n", ether_sprintf(hwaddr));
  191 }
  192 
  193 static void
  194 emac_set_rx_mode(struct emac_softc *sc)
  195 {
  196         struct ifnet *ifp;
  197         struct ifmultiaddr *ifma;
  198         uint32_t h, hashes[2];
  199         uint32_t rcr = 0;
  200 
  201         EMAC_ASSERT_LOCKED(sc);
  202 
  203         ifp = sc->emac_ifp;
  204 
  205         rcr = EMAC_READ_REG(sc, EMAC_RX_CTL);
  206 
  207         /* Unicast packet and DA filtering */
  208         rcr |= EMAC_RX_UCAD;
  209         rcr |= EMAC_RX_DAF;
  210 
  211         hashes[0] = 0;
  212         hashes[1] = 0;
  213         if (ifp->if_flags & IFF_ALLMULTI) {
  214                 hashes[0] = 0xffffffff;
  215                 hashes[1] = 0xffffffff;
  216         } else {
  217                 if_maddr_rlock(ifp);
  218                 TAILQ_FOREACH(ifma, &sc->emac_ifp->if_multiaddrs, ifma_link) {
  219                         if (ifma->ifma_addr->sa_family != AF_LINK)
  220                                 continue;
  221                         h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
  222                             ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
  223                         hashes[h >> 5] |= 1 << (h & 0x1f);
  224                 }
  225                 if_maddr_runlock(ifp);
  226         }
  227         rcr |= EMAC_RX_MCO;
  228         rcr |= EMAC_RX_MHF;
  229         EMAC_WRITE_REG(sc, EMAC_RX_HASH0, hashes[0]);
  230         EMAC_WRITE_REG(sc, EMAC_RX_HASH1, hashes[1]);
  231 
  232         if (ifp->if_flags & IFF_BROADCAST) {
  233                 rcr |= EMAC_RX_BCO;
  234                 rcr |= EMAC_RX_MCO;
  235         }
  236 
  237         if (ifp->if_flags & IFF_PROMISC)
  238                 rcr |= EMAC_RX_PA;
  239         else
  240                 rcr |= EMAC_RX_UCAD;
  241 
  242         EMAC_WRITE_REG(sc, EMAC_RX_CTL, rcr);
  243 }
  244 
  245 static void
  246 emac_reset(struct emac_softc *sc)
  247 {
  248 
  249         EMAC_WRITE_REG(sc, EMAC_CTL, 0);
  250         DELAY(200);
  251         EMAC_WRITE_REG(sc, EMAC_CTL, 1);
  252         DELAY(200);
  253 }
  254 
  255 static void
  256 emac_txeof(struct emac_softc *sc)
  257 {
  258         struct ifnet *ifp;
  259 
  260         EMAC_ASSERT_LOCKED(sc);
  261 
  262         ifp = sc->emac_ifp;
  263         ifp->if_opackets++;
  264         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  265 
  266         /* Unarm watchdog timer if no TX */
  267         sc->emac_watchdog_timer = 0;
  268 }
  269 
  270 static void
  271 emac_rxeof(struct emac_softc *sc, int count)
  272 {
  273         struct ifnet *ifp;
  274         struct mbuf *m, *m0;
  275         uint32_t reg_val, rxcount;
  276         int16_t len;
  277         uint16_t status;
  278         int good_packet, i;
  279 
  280         ifp = sc->emac_ifp;
  281         for (; count > 0 &&
  282             (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; count--) {
  283                 /*
  284                  * Race warning: The first packet might arrive with
  285                  * the interrupts disabled, but the second will fix
  286                  */
  287                 rxcount = EMAC_READ_REG(sc, EMAC_RX_FBC);
  288                 if (!rxcount) {
  289                         /* Had one stuck? */
  290                         rxcount = EMAC_READ_REG(sc, EMAC_RX_FBC);
  291                         if (!rxcount)
  292                                 return;
  293                 }
  294                 /* Check packet header */
  295                 reg_val = EMAC_READ_REG(sc, EMAC_RX_IO_DATA);
  296                 if (reg_val != EMAC_PACKET_HEADER) {
  297                         /* Packet header is wrong */
  298                         if (bootverbose)
  299                                 if_printf(ifp, "wrong packet header\n");
  300                         /* Disable RX */
  301                         reg_val = EMAC_READ_REG(sc, EMAC_CTL);
  302                         reg_val &= ~EMAC_CTL_RX_EN;
  303                         EMAC_WRITE_REG(sc, EMAC_CTL, reg_val);
  304 
  305                         /* Flush RX FIFO */
  306                         reg_val = EMAC_READ_REG(sc, EMAC_RX_CTL);
  307                         reg_val |= EMAC_RX_FLUSH_FIFO;
  308                         EMAC_WRITE_REG(sc, EMAC_RX_CTL, reg_val);
  309                         for (i = 100; i > 0; i--) {
  310                                 DELAY(100);
  311                                 if ((EMAC_READ_REG(sc, EMAC_RX_CTL) &
  312                                     EMAC_RX_FLUSH_FIFO) == 0)
  313                                         break;
  314                         }
  315                         if (i == 0) {
  316                                 device_printf(sc->emac_dev,
  317                                     "flush FIFO timeout\n");
  318                                 /* Reinitialize controller */
  319                                 emac_init_locked(sc);
  320                                 return;
  321                         }
  322                         /* Enable RX */
  323                         reg_val = EMAC_READ_REG(sc, EMAC_CTL);
  324                         reg_val |= EMAC_CTL_RX_EN;
  325                         EMAC_WRITE_REG(sc, EMAC_CTL, reg_val);
  326 
  327                         return;
  328                 }
  329 
  330                 good_packet = 1;
  331 
  332                 /* Get packet size and status */
  333                 reg_val = EMAC_READ_REG(sc, EMAC_RX_IO_DATA);
  334                 len = reg_val & 0xffff;
  335                 status = (reg_val >> 16) & 0xffff;
  336 
  337                 if (len < 64) {
  338                         good_packet = 0;
  339                         if (bootverbose)
  340                                 if_printf(ifp,
  341                                     "bad packet: len = %i status = %i\n",
  342                                     len, status);
  343                         ifp->if_ierrors++;
  344                 }
  345 #if 0
  346                 if (status & (EMAC_CRCERR | EMAC_LENERR)) {
  347                         good_packet = 0;
  348                         ifp->if_ierrors++;
  349                         if (status & EMAC_CRCERR)
  350                                 if_printf(ifp, "crc error\n");
  351                         if (status & EMAC_LENERR)
  352                                 if_printf(ifp, "length error\n");
  353                 }
  354 #endif
  355                 if (good_packet) {
  356                         m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
  357                         if (m == NULL)
  358                                 return;
  359                         m->m_len = m->m_pkthdr.len = MCLBYTES;
  360 
  361                         len -= ETHER_CRC_LEN;
  362 
  363                         /* Copy entire frame to mbuf first. */
  364                         bus_space_read_multi_4(sc->emac_tag, sc->emac_handle,
  365                             EMAC_RX_IO_DATA, mtod(m, uint32_t *),
  366                             roundup2(len, 4) / 4);
  367 
  368                         m->m_pkthdr.rcvif = ifp;
  369                         m->m_len = m->m_pkthdr.len = len;
  370 
  371                         /*
  372                          * Emac controller needs strict aligment, so to avoid
  373                          * copying over an entire frame to align, we allocate
  374                          * a new mbuf and copy ethernet header + IP header to
  375                          * the new mbuf. The new mbuf is prepended into the
  376                          * existing mbuf chain.
  377                          */
  378                         if (m->m_len <= (MHLEN - ETHER_HDR_LEN)) {
  379                                 bcopy(m->m_data, m->m_data + ETHER_HDR_LEN,
  380                                     m->m_len);
  381                                 m->m_data += ETHER_HDR_LEN;
  382                         } else if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN) &&
  383                             m->m_len > (MHLEN - ETHER_HDR_LEN)) {
  384                                 MGETHDR(m0, M_NOWAIT, MT_DATA);
  385                                 if (m0 != NULL) {
  386                                         len = ETHER_HDR_LEN +
  387                                             m->m_pkthdr.l2hlen;
  388                                         bcopy(m->m_data, m0->m_data, len);
  389                                         m->m_data += len;
  390                                         m->m_len -= len;
  391                                         m0->m_len = len;
  392                                         M_MOVE_PKTHDR(m0, m);
  393                                         m0->m_next = m;
  394                                         m = m0;
  395                                 } else {
  396                                         ifp->if_ierrors++;
  397                                         m_freem(m);
  398                                         m = NULL;
  399                                         continue;
  400                                 }
  401                         } else if (m->m_len > EMAC_MAC_MAXF) {
  402                                 ifp->if_ierrors++;
  403                                 m_freem(m);
  404                                 m = NULL;
  405                                 continue;
  406                         }
  407                         ifp->if_ipackets++;
  408                         EMAC_UNLOCK(sc);
  409                         (*ifp->if_input)(ifp, m);
  410                         EMAC_LOCK(sc);
  411                 }
  412         }
  413 }
  414 
  415 static void
  416 emac_watchdog(struct emac_softc *sc)
  417 {
  418         struct ifnet *ifp;
  419 
  420         EMAC_ASSERT_LOCKED(sc);
  421 
  422         if (sc->emac_watchdog_timer == 0 || --sc->emac_watchdog_timer)
  423                 return;
  424 
  425         ifp = sc->emac_ifp;
  426 
  427         if (sc->emac_link == 0) {
  428                 if (bootverbose)
  429                         if_printf(sc->emac_ifp, "watchdog timeout "
  430                             "(missed link)\n");
  431         } else
  432                 if_printf(sc->emac_ifp, "watchdog timeout -- resetting\n");
  433         
  434         ifp->if_oerrors++;
  435         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
  436         emac_init_locked(sc);
  437         if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
  438                 emac_start_locked(ifp);
  439 }
  440 
  441 static void
  442 emac_tick(void *arg)
  443 {
  444         struct emac_softc *sc;
  445         struct mii_data *mii;
  446 
  447         sc = (struct emac_softc *)arg;
  448         mii = device_get_softc(sc->emac_miibus);
  449         mii_tick(mii);
  450 
  451         emac_watchdog(sc);
  452         callout_reset(&sc->emac_tick_ch, hz, emac_tick, sc);
  453 }
  454 
  455 static void
  456 emac_init(void *xcs)
  457 {
  458         struct emac_softc *sc;
  459 
  460         sc = (struct emac_softc *)xcs;
  461         EMAC_LOCK(sc);
  462         emac_init_locked(sc);
  463         EMAC_UNLOCK(sc);
  464 }
  465 
  466 static void
  467 emac_init_locked(struct emac_softc *sc)
  468 {
  469         struct ifnet *ifp;
  470         struct mii_data *mii;
  471         uint32_t reg_val;
  472         uint8_t *eaddr;
  473 
  474         EMAC_ASSERT_LOCKED(sc);
  475 
  476         ifp = sc->emac_ifp;
  477         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
  478                 return;
  479 
  480         /* Flush RX FIFO */
  481         reg_val = EMAC_READ_REG(sc, EMAC_RX_CTL);
  482         reg_val |= EMAC_RX_FLUSH_FIFO;
  483         EMAC_WRITE_REG(sc, EMAC_RX_CTL, reg_val);
  484         DELAY(1);
  485 
  486         /* Soft reset MAC */
  487         reg_val = EMAC_READ_REG(sc, EMAC_MAC_CTL0);
  488         reg_val &= (~EMAC_MAC_CTL0_SOFT_RST);
  489         EMAC_WRITE_REG(sc, EMAC_MAC_CTL0, reg_val);
  490 
  491         /* Set MII clock */
  492         reg_val = EMAC_READ_REG(sc, EMAC_MAC_MCFG);
  493         reg_val &= (~(0xf << 2));
  494         reg_val |= (0xd << 2);
  495         EMAC_WRITE_REG(sc, EMAC_MAC_MCFG, reg_val);
  496 
  497         /* Clear RX counter */
  498         EMAC_WRITE_REG(sc, EMAC_RX_FBC, 0);
  499 
  500         /* Disable all interrupt and clear interrupt status */
  501         EMAC_WRITE_REG(sc, EMAC_INT_CTL, 0);
  502         reg_val = EMAC_READ_REG(sc, EMAC_INT_STA);
  503         EMAC_WRITE_REG(sc, EMAC_INT_STA, reg_val);
  504         DELAY(1);
  505 
  506         /* Set up TX */
  507         reg_val = EMAC_READ_REG(sc, EMAC_TX_MODE);
  508         reg_val |= EMAC_TX_AB_M;
  509         reg_val &= EMAC_TX_TM;
  510         EMAC_WRITE_REG(sc, EMAC_TX_MODE, reg_val);
  511 
  512         /* Set up RX */
  513         reg_val = EMAC_READ_REG(sc, EMAC_RX_CTL);
  514         reg_val |= EMAC_RX_SETUP;
  515         reg_val &= EMAC_RX_TM;
  516         EMAC_WRITE_REG(sc, EMAC_RX_CTL, reg_val);
  517 
  518         /* Set up MAC CTL0. */
  519         reg_val = EMAC_READ_REG(sc, EMAC_MAC_CTL0);
  520         reg_val |= EMAC_MAC_CTL0_SETUP;
  521         EMAC_WRITE_REG(sc, EMAC_MAC_CTL0, reg_val);
  522 
  523         /* Set up MAC CTL1. */
  524         reg_val = EMAC_READ_REG(sc, EMAC_MAC_CTL1);
  525         reg_val |= EMAC_MAC_CTL1_SETUP;
  526         EMAC_WRITE_REG(sc, EMAC_MAC_CTL1, reg_val);
  527 
  528         /* Set up IPGT */
  529         EMAC_WRITE_REG(sc, EMAC_MAC_IPGT, EMAC_MAC_IPGT_FD);
  530 
  531         /* Set up IPGR */
  532         EMAC_WRITE_REG(sc, EMAC_MAC_IPGR, EMAC_MAC_NBTB_IPG2 |
  533             (EMAC_MAC_NBTB_IPG1 << 8));
  534 
  535         /* Set up Collison window */
  536         EMAC_WRITE_REG(sc, EMAC_MAC_CLRT, EMAC_MAC_RM | (EMAC_MAC_CW << 8));
  537 
  538         /* Set up Max Frame Length */
  539         EMAC_WRITE_REG(sc, EMAC_MAC_MAXF, EMAC_MAC_MFL);
  540 
  541         /* Setup ethernet address */
  542         eaddr = IF_LLADDR(ifp);
  543         EMAC_WRITE_REG(sc, EMAC_MAC_A1, eaddr[0] << 16 |
  544             eaddr[1] << 8 | eaddr[2]);
  545         EMAC_WRITE_REG(sc, EMAC_MAC_A0, eaddr[3] << 16 |
  546             eaddr[4] << 8 | eaddr[5]);
  547 
  548         /* Setup rx filter */
  549         emac_set_rx_mode(sc);
  550 
  551         /* Enable RX/TX0/RX Hlevel interrupt */
  552         reg_val = EMAC_READ_REG(sc, EMAC_INT_CTL);
  553         reg_val |= EMAC_INT_EN;
  554         EMAC_WRITE_REG(sc, EMAC_INT_CTL, reg_val);
  555 
  556         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  557         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  558 
  559         sc->emac_link = 0;
  560 
  561         /* Switch to the current media. */
  562         mii = device_get_softc(sc->emac_miibus);
  563         mii_mediachg(mii);
  564 
  565         callout_reset(&sc->emac_tick_ch, hz, emac_tick, sc);
  566 }
  567 
  568 
  569 static void
  570 emac_start(struct ifnet *ifp)
  571 {
  572         struct emac_softc *sc;
  573 
  574         sc = ifp->if_softc;
  575         EMAC_LOCK(sc);
  576         emac_start_locked(ifp);
  577         EMAC_UNLOCK(sc);
  578 }
  579 
  580 static void
  581 emac_start_locked(struct ifnet *ifp)
  582 {
  583         struct emac_softc *sc;
  584         struct mbuf *m, *m0;
  585         uint32_t reg_val;
  586 
  587         sc = ifp->if_softc;
  588         if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
  589                 return;
  590         if (sc->emac_link == 0)
  591                 return;
  592         IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
  593         if (m == NULL)
  594                 return;
  595 
  596         /* Select channel */
  597         EMAC_WRITE_REG(sc, EMAC_TX_INS, 0);
  598 
  599         /*
  600          * Emac controller wants 4 byte aligned TX buffers.
  601          * We have to copy pretty much all the time.
  602          */
  603         if (m->m_next != NULL || (mtod(m, uintptr_t) & 3) != 0) {
  604                 m0 = m_defrag(m, M_NOWAIT);
  605                 if (m0 == NULL) {
  606                         m_freem(m);
  607                         m = NULL;
  608                         return;
  609                 }
  610                 m = m0;
  611         }
  612         /* Write data */
  613         bus_space_write_multi_4(sc->emac_tag, sc->emac_handle,
  614             EMAC_TX_IO_DATA, mtod(m, uint32_t *),
  615             roundup2(m->m_len, 4) / 4);
  616 
  617         /* Send the data lengh. */
  618         EMAC_WRITE_REG(sc, EMAC_TX_PL0, m->m_len);
  619 
  620         /* Start translate from fifo to phy. */
  621         reg_val = EMAC_READ_REG(sc, EMAC_TX_CTL0);
  622         reg_val |= 1;
  623         EMAC_WRITE_REG(sc, EMAC_TX_CTL0, reg_val);
  624 
  625         /* Set timeout */
  626         sc->emac_watchdog_timer = 5;
  627 
  628         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  629         BPF_MTAP(ifp, m);
  630         m_freem(m);
  631 }
  632 
  633 static void
  634 emac_stop_locked(struct emac_softc *sc)
  635 {
  636         struct ifnet *ifp;
  637         uint32_t reg_val;
  638 
  639         EMAC_ASSERT_LOCKED(sc);
  640 
  641         ifp = sc->emac_ifp;
  642         ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
  643         sc->emac_link = 0;
  644 
  645         /* Disable all interrupt and clear interrupt status */
  646         EMAC_WRITE_REG(sc, EMAC_INT_CTL, 0);
  647         reg_val = EMAC_READ_REG(sc, EMAC_INT_STA);
  648         EMAC_WRITE_REG(sc, EMAC_INT_STA, reg_val);
  649 
  650         /* Disable RX/TX */
  651         reg_val = EMAC_READ_REG(sc, EMAC_CTL);
  652         reg_val &= ~(EMAC_CTL_RST | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN);
  653         EMAC_WRITE_REG(sc, EMAC_CTL, reg_val);
  654 
  655         callout_stop(&sc->emac_tick_ch);
  656 }
  657 
  658 static void
  659 emac_intr(void *arg)
  660 {
  661         struct emac_softc *sc;
  662         struct ifnet *ifp;
  663         uint32_t reg_val;
  664 
  665         sc = (struct emac_softc *)arg;
  666         EMAC_LOCK(sc);
  667         ifp = sc->emac_ifp;
  668         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
  669                 return;
  670 
  671         /* Disable all interrupts */
  672         EMAC_WRITE_REG(sc, EMAC_INT_CTL, 0);
  673         /* Get EMAC interrupt status */
  674         reg_val = EMAC_READ_REG(sc, EMAC_INT_STA);
  675         /* Clear ISR status */
  676         EMAC_WRITE_REG(sc, EMAC_INT_STA, reg_val);
  677 
  678         /* Received incoming packet */
  679         if (reg_val & EMAC_INT_STA_RX)
  680                 emac_rxeof(sc, sc->emac_rx_process_limit);
  681 
  682         /* Transmit Interrupt check */
  683         if (reg_val & EMAC_INT_STA_TX){
  684                 emac_txeof(sc);
  685                 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
  686                         emac_start_locked(ifp);
  687         }
  688 
  689         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
  690                 /* Re-enable interrupt mask */
  691                 reg_val = EMAC_READ_REG(sc, EMAC_INT_CTL);
  692                 reg_val |= EMAC_INT_EN;
  693                 EMAC_WRITE_REG(sc, EMAC_INT_CTL, reg_val);
  694         }
  695         EMAC_UNLOCK(sc);
  696 }
  697 
  698 static int
  699 emac_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
  700 {
  701         struct emac_softc *sc;
  702         struct mii_data *mii;
  703         struct ifreq *ifr;
  704         int error = 0;
  705 
  706         sc = ifp->if_softc;
  707         ifr = (struct ifreq *)data;
  708 
  709         switch (command) {
  710         case SIOCSIFFLAGS:
  711                 EMAC_LOCK(sc);
  712                 if (ifp->if_flags & IFF_UP) {
  713                         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
  714                                 if ((ifp->if_flags ^ sc->emac_if_flags) &
  715                                     (IFF_PROMISC | IFF_ALLMULTI))
  716                                         emac_set_rx_mode(sc);
  717                         } else
  718                                 emac_init_locked(sc);
  719                 } else {
  720                         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
  721                                 emac_stop_locked(sc);
  722                 }
  723                 sc->emac_if_flags = ifp->if_flags;
  724                 EMAC_UNLOCK(sc);
  725                 break;
  726         case SIOCADDMULTI:
  727         case SIOCDELMULTI:
  728                 EMAC_LOCK(sc);
  729                 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
  730                         emac_set_rx_mode(sc);
  731                 }
  732                 EMAC_UNLOCK(sc);
  733                 break;
  734         case SIOCGIFMEDIA:
  735         case SIOCSIFMEDIA:
  736                 mii = device_get_softc(sc->emac_miibus);
  737                 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
  738                 break;
  739         default:
  740                 error = ether_ioctl(ifp, command, data);
  741                 break;
  742         }
  743         return (error);
  744 }
  745 
  746 static int
  747 emac_probe(device_t dev)
  748 {
  749 
  750         if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-emac"))
  751                 return (ENXIO);
  752 
  753         device_set_desc(dev, "A10/A20 EMAC ethernet controller");
  754         return (BUS_PROBE_DEFAULT);
  755 }
  756 
  757 static int
  758 emac_detach(device_t dev)
  759 {
  760         struct emac_softc *sc;
  761 
  762         sc = device_get_softc(dev);
  763         sc->emac_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
  764         if (device_is_attached(dev)) {
  765                 ether_ifdetach(sc->emac_ifp);
  766                 EMAC_LOCK(sc);
  767                 emac_stop_locked(sc);
  768                 EMAC_UNLOCK(sc);
  769                 callout_drain(&sc->emac_tick_ch);
  770         }
  771 
  772         if (sc->emac_intrhand != NULL)
  773                 bus_teardown_intr(sc->emac_dev, sc->emac_irq,
  774                     sc->emac_intrhand);
  775 
  776         if (sc->emac_miibus != NULL) {
  777                 device_delete_child(sc->emac_dev, sc->emac_miibus);
  778                 bus_generic_detach(sc->emac_dev);
  779         }
  780 
  781         if (sc->emac_res != NULL)
  782                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->emac_res);
  783 
  784         if (sc->emac_irq != NULL)
  785                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->emac_irq);
  786 
  787         if (sc->emac_ifp != NULL)
  788                 if_free(sc->emac_ifp);
  789 
  790         if (mtx_initialized(&sc->emac_mtx))
  791                 mtx_destroy(&sc->emac_mtx);
  792 
  793         return (0);
  794 }
  795 
  796 static int
  797 emac_shutdown(device_t dev)
  798 {
  799 
  800         return (emac_suspend(dev));
  801 }
  802 
  803 static int
  804 emac_suspend(device_t dev)
  805 {
  806         struct emac_softc *sc;
  807         struct ifnet *ifp;
  808 
  809         sc = device_get_softc(dev);
  810 
  811         EMAC_LOCK(sc);
  812         ifp = sc->emac_ifp;
  813         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
  814                 emac_stop_locked(sc);
  815         EMAC_UNLOCK(sc);
  816 
  817         return (0);
  818 }
  819 
  820 static int
  821 emac_resume(device_t dev)
  822 {
  823         struct emac_softc *sc;
  824         struct ifnet *ifp;
  825 
  826         sc = device_get_softc(dev);
  827 
  828         EMAC_LOCK(sc);
  829         ifp = sc->emac_ifp;
  830         if ((ifp->if_flags & IFF_UP) != 0) {
  831                 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
  832                 emac_init_locked(sc);
  833         }
  834         EMAC_UNLOCK(sc);
  835 
  836         return (0);
  837 }
  838 
  839 static int
  840 emac_attach(device_t dev)
  841 {
  842         struct emac_softc *sc;
  843         struct ifnet *ifp;
  844         int error, rid;
  845         uint8_t eaddr[ETHER_ADDR_LEN];
  846 
  847         sc = device_get_softc(dev);
  848         sc->emac_dev = dev;
  849 
  850         error = 0;
  851         mtx_init(&sc->emac_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
  852             MTX_DEF);
  853         callout_init_mtx(&sc->emac_tick_ch, &sc->emac_mtx, 0);
  854 
  855         rid = 0;
  856         sc->emac_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  857             RF_ACTIVE);
  858         if (sc->emac_res == NULL) {
  859                 device_printf(dev, "unable to map memory\n");
  860                 error = ENXIO;
  861                 goto fail;
  862         }
  863 
  864         sc->emac_tag = rman_get_bustag(sc->emac_res);
  865         sc->emac_handle = rman_get_bushandle(sc->emac_res);
  866 
  867         rid = 0;
  868         sc->emac_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  869             RF_SHAREABLE | RF_ACTIVE);
  870         if (sc->emac_irq == NULL) {
  871                 device_printf(dev, "cannot allocate IRQ resources.\n");
  872                 error = ENXIO;
  873                 goto fail;
  874         }
  875         /* Create device sysctl node. */
  876         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  877             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  878             OID_AUTO, "process_limit", CTLTYPE_INT | CTLFLAG_RW,
  879             &sc->emac_rx_process_limit, 0, sysctl_hw_emac_proc_limit, "I",
  880             "max number of Rx events to process");
  881 
  882         sc->emac_rx_process_limit = EMAC_PROC_DEFAULT;
  883         error = resource_int_value(device_get_name(dev), device_get_unit(dev),
  884             "process_limit", &sc->emac_rx_process_limit);
  885         if (error == 0) {
  886                 if (sc->emac_rx_process_limit < EMAC_PROC_MIN ||
  887                     sc->emac_rx_process_limit > EMAC_PROC_MAX) {
  888                         device_printf(dev, "process_limit value out of range; "
  889                             "using default: %d\n", EMAC_PROC_DEFAULT);
  890                         sc->emac_rx_process_limit = EMAC_PROC_DEFAULT;
  891                 }
  892         }
  893         /* Setup EMAC */
  894         emac_sys_setup();
  895         emac_reset(sc);
  896 
  897         ifp = sc->emac_ifp = if_alloc(IFT_ETHER);
  898         if (ifp == NULL) {
  899                 device_printf(dev, "unable to allocate ifp\n");
  900                 error = ENOSPC;
  901                 goto fail;
  902         }
  903         ifp->if_softc = sc;
  904 
  905         /* Setup MII */
  906         error = mii_attach(dev, &sc->emac_miibus, ifp, emac_ifmedia_upd,
  907             emac_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
  908         if (error != 0) {
  909                 device_printf(dev, "PHY probe failed\n");
  910                 goto fail;
  911         }
  912 
  913         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
  914         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  915         ifp->if_start = emac_start;
  916         ifp->if_ioctl = emac_ioctl;
  917         ifp->if_init = emac_init;
  918         IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
  919 
  920         /* Get MAC address */
  921         emac_get_hwaddr(sc, eaddr);
  922         ether_ifattach(ifp, eaddr);
  923 
  924         /* VLAN capability setup. */
  925         ifp->if_capabilities |= IFCAP_VLAN_MTU;
  926         ifp->if_capenable = ifp->if_capabilities;
  927         /* Tell the upper layer we support VLAN over-sized frames. */
  928         ifp->if_hdrlen = sizeof(struct ether_vlan_header);
  929 
  930         error = bus_setup_intr(dev, sc->emac_irq, INTR_TYPE_NET | INTR_MPSAFE,
  931             NULL, emac_intr, sc, &sc->emac_intrhand);
  932         if (error != 0) {
  933                 device_printf(dev, "could not set up interrupt handler.\n");
  934                 ether_ifdetach(ifp);
  935                 goto fail;
  936         }
  937 
  938 fail:
  939         if (error != 0)
  940                 emac_detach(dev);
  941         return (error);
  942 }
  943 
  944 static boolean_t
  945 emac_miibus_iowait(struct emac_softc *sc)
  946 {
  947         uint32_t timeout;
  948 
  949         for (timeout = 100; timeout != 0; --timeout) {
  950                 DELAY(100);
  951                 if ((EMAC_READ_REG(sc, EMAC_MAC_MIND) & 0x1) == 0)
  952                         return (true);
  953         }
  954 
  955         return (false);
  956 }
  957 
  958 /*
  959  * The MII bus interface
  960  */
  961 static int
  962 emac_miibus_readreg(device_t dev, int phy, int reg)
  963 {
  964         struct emac_softc *sc;
  965         int rval;
  966 
  967         sc = device_get_softc(dev);
  968 
  969         /* Issue phy address and reg */
  970         EMAC_WRITE_REG(sc, EMAC_MAC_MADR, (phy << 8) | reg);
  971         /* Pull up the phy io line */
  972         EMAC_WRITE_REG(sc, EMAC_MAC_MCMD, 0x1);
  973         if (!emac_miibus_iowait(sc)) {
  974                 device_printf(dev, "timeout waiting for mii read\n");
  975                 return (0);
  976         }
  977         /* Push down the phy io line */
  978         EMAC_WRITE_REG(sc, EMAC_MAC_MCMD, 0x0);
  979         /* Read data */
  980         rval = EMAC_READ_REG(sc, EMAC_MAC_MRDD);
  981 
  982         return (rval);
  983 }
  984 
  985 static int
  986 emac_miibus_writereg(device_t dev, int phy, int reg, int data)
  987 {
  988         struct emac_softc *sc;
  989 
  990         sc = device_get_softc(dev);
  991 
  992         /* Issue phy address and reg */
  993         EMAC_WRITE_REG(sc, EMAC_MAC_MADR, (phy << 8) | reg);
  994         /* Write data */
  995         EMAC_WRITE_REG(sc, EMAC_MAC_MWTD, data);
  996         /* Pull up the phy io line */
  997         EMAC_WRITE_REG(sc, EMAC_MAC_MCMD, 0x1);
  998         if (!emac_miibus_iowait(sc)) {
  999                 device_printf(dev, "timeout waiting for mii write\n");
 1000                 return (0);
 1001         }
 1002         /* Push down the phy io line */
 1003         EMAC_WRITE_REG(sc, EMAC_MAC_MCMD, 0x0);
 1004 
 1005         return (0);
 1006 }
 1007 
 1008 static void
 1009 emac_miibus_statchg(device_t dev)
 1010 {
 1011         struct emac_softc *sc;
 1012         struct mii_data *mii;
 1013         struct ifnet *ifp;
 1014         uint32_t reg_val;
 1015 
 1016         sc = device_get_softc(dev);
 1017 
 1018         mii = device_get_softc(sc->emac_miibus);
 1019         ifp = sc->emac_ifp;
 1020         if (mii == NULL || ifp == NULL ||
 1021             (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
 1022                 return;
 1023 
 1024         sc->emac_link = 0;
 1025         if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
 1026             (IFM_ACTIVE | IFM_AVALID)) {
 1027                 switch (IFM_SUBTYPE(mii->mii_media_active)) {
 1028                 case IFM_10_T:
 1029                 case IFM_100_TX:
 1030                         sc->emac_link = 1;
 1031                         break;
 1032                 default:
 1033                         break;
 1034                 }
 1035         }
 1036         /* Program MACs with resolved speed/duplex. */
 1037         if (sc->emac_link != 0) {
 1038                 reg_val = EMAC_READ_REG(sc, EMAC_MAC_IPGT);
 1039                 if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
 1040                         reg_val &= ~EMAC_MAC_IPGT_HD;
 1041                         reg_val |= EMAC_MAC_IPGT_FD;
 1042                 } else {
 1043                         reg_val &= ~EMAC_MAC_IPGT_FD;
 1044                         reg_val |= EMAC_MAC_IPGT_HD;
 1045                 }
 1046                 EMAC_WRITE_REG(sc, EMAC_MAC_IPGT, reg_val);
 1047                 /* Enable RX/TX */
 1048                 reg_val = EMAC_READ_REG(sc, EMAC_CTL);
 1049                 reg_val |= EMAC_CTL_RST | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN;
 1050                 EMAC_WRITE_REG(sc, EMAC_CTL, reg_val);
 1051         } else {
 1052                 /* Disable RX/TX */
 1053                 reg_val = EMAC_READ_REG(sc, EMAC_CTL);
 1054                 reg_val &= ~(EMAC_CTL_RST | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN);
 1055                 EMAC_WRITE_REG(sc, EMAC_CTL, reg_val);
 1056         }
 1057 }
 1058 
 1059 static int
 1060 emac_ifmedia_upd(struct ifnet *ifp)
 1061 {
 1062         struct emac_softc *sc;
 1063         struct mii_data *mii;
 1064         struct mii_softc *miisc;
 1065         int error;
 1066 
 1067         sc = ifp->if_softc;
 1068         mii = device_get_softc(sc->emac_miibus);
 1069         EMAC_LOCK(sc);
 1070         LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
 1071                 PHY_RESET(miisc);
 1072         error = mii_mediachg(mii);
 1073         EMAC_UNLOCK(sc);
 1074 
 1075         return (error);
 1076 }
 1077 
 1078 static void
 1079 emac_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
 1080 {
 1081         struct emac_softc *sc;
 1082         struct mii_data *mii;
 1083 
 1084         sc = ifp->if_softc;
 1085         mii = device_get_softc(sc->emac_miibus);
 1086 
 1087         EMAC_LOCK(sc);
 1088         mii_pollstat(mii);
 1089         ifmr->ifm_active = mii->mii_media_active;
 1090         ifmr->ifm_status = mii->mii_media_status;
 1091         EMAC_UNLOCK(sc);
 1092 }
 1093 
 1094 static device_method_t emac_methods[] = {
 1095         /* Device interface */
 1096         DEVMETHOD(device_probe,         emac_probe),
 1097         DEVMETHOD(device_attach,        emac_attach),
 1098         DEVMETHOD(device_detach,        emac_detach),
 1099         DEVMETHOD(device_shutdown,      emac_shutdown),
 1100         DEVMETHOD(device_suspend,       emac_suspend),
 1101         DEVMETHOD(device_resume,        emac_resume),
 1102 
 1103         /* bus interface, for miibus */
 1104         DEVMETHOD(bus_print_child,      bus_generic_print_child),
 1105         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
 1106 
 1107         /* MII interface */
 1108         DEVMETHOD(miibus_readreg,       emac_miibus_readreg),
 1109         DEVMETHOD(miibus_writereg,      emac_miibus_writereg),
 1110         DEVMETHOD(miibus_statchg,       emac_miibus_statchg),
 1111 
 1112         DEVMETHOD_END
 1113 };
 1114 
 1115 static driver_t emac_driver = {
 1116         "emac",
 1117         emac_methods,
 1118         sizeof(struct emac_softc)
 1119 };
 1120 
 1121 static devclass_t emac_devclass;
 1122 
 1123 DRIVER_MODULE(emac, simplebus, emac_driver, emac_devclass, 0, 0);
 1124 DRIVER_MODULE(miibus, emac, miibus_driver, miibus_devclass, 0, 0);
 1125 MODULE_DEPEND(emac, miibus, 1, 1, 1);
 1126 MODULE_DEPEND(emac, ether, 1, 1, 1);
 1127 
 1128 static int
 1129 sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high)
 1130 {
 1131         int error, value;
 1132 
 1133         if (arg1 == NULL)
 1134                 return (EINVAL);
 1135         value = *(int *)arg1;
 1136         error = sysctl_handle_int(oidp, &value, 0, req);
 1137         if (error || req->newptr == NULL)
 1138                 return (error);
 1139         if (value < low || value > high)
 1140                 return (EINVAL);
 1141         *(int *)arg1 = value;
 1142 
 1143         return (0);
 1144 }
 1145 
 1146 static int
 1147 sysctl_hw_emac_proc_limit(SYSCTL_HANDLER_ARGS)
 1148 {
 1149 
 1150         return (sysctl_int_range(oidp, arg1, arg2, req,
 1151             EMAC_PROC_MIN, EMAC_PROC_MAX));
 1152 }

Cache object: 55c272307f23bd7c8d24cf79986c4e39


[ 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.