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/cardbus/if_rtk_cardbus.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 /*      $NetBSD: if_rtk_cardbus.c,v 1.19 2004/03/11 12:19:14 kanaoka Exp $      */
    2 
    3 /*
    4  * Copyright (c) 2000 Masanori Kanaoka
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * if_rtk_cardbus.c:
   32  *      Cardbus specific routines for Realtek 8139 ethernet adapter.
   33  *      Tested for 
   34  *              - elecom-Laneed LD-10/100CBA (Accton MPX5030)
   35  *              - MELCO         LPC3-TX-CB   (Realtek 8139)
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: if_rtk_cardbus.c,v 1.19 2004/03/11 12:19:14 kanaoka Exp $");
   40 
   41 #include "opt_inet.h"
   42 #include "opt_ns.h"
   43 #include "bpfilter.h"
   44 #include "rnd.h"
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/callout.h>
   49 #include <sys/device.h>
   50 #include <sys/sockio.h>
   51 #include <sys/mbuf.h>
   52 #include <sys/malloc.h>
   53 #include <sys/kernel.h>
   54 #include <sys/socket.h>
   55 
   56 #include <net/if.h>
   57 #include <net/if_arp.h>
   58 #include <net/if_ether.h>
   59 #include <net/if_dl.h>
   60 #include <net/if_media.h>
   61 #ifdef INET
   62 #include <netinet/in.h>
   63 #include <netinet/if_inarp.h>
   64 #endif
   65 #ifdef NS
   66 #include <netns/ns.h>
   67 #include <netns/ns_if.h>
   68 #endif
   69 
   70 #if NBPFILTER > 0
   71 #include <net/bpf.h>
   72 #endif
   73 #if NRND > 0
   74 #include <sys/rnd.h>
   75 #endif
   76 
   77 #include <machine/bus.h>
   78 
   79 #include <dev/pci/pcireg.h>
   80 #include <dev/pci/pcivar.h>
   81 #include <dev/pci/pcidevs.h>
   82 
   83 #include <dev/cardbus/cardbusvar.h>
   84 #include <dev/cardbus/cardbusdevs.h>
   85 
   86 #include <dev/mii/mii.h>
   87 #include <dev/mii/miivar.h>
   88 
   89 /*
   90  * Default to using PIO access for this driver. On SMP systems,
   91  * there appear to be problems with memory mapped mode: it looks like
   92  * doing too many memory mapped access back to back in rapid succession
   93  * can hang the bus. I'm inclined to blame this on crummy design/construction
   94  * on the part of Realtek. Memory mapped mode does appear to work on
   95  * uniprocessor systems though.
   96  */
   97 #define RTK_USEIOSPACE 
   98 
   99 #include <dev/ic/rtl81x9reg.h>
  100 #include <dev/ic/rtl81x9var.h>
  101 
  102 /*
  103  * Various supported device vendors/types and their names.
  104  */
  105 static const struct rtk_type rtk_cardbus_devs[] = {
  106         { CARDBUS_VENDOR_ACCTON, CARDBUS_PRODUCT_ACCTON_MPX5030,
  107                 RTK_8139, "Accton MPX 5030/5038 10/100BaseTX" },
  108         { CARDBUS_VENDOR_DLINK, CARDBUS_PRODUCT_DLINK_DFE_690TXD,
  109                 RTK_8139, "D-Link DFE-690TXD 10/100BaseTX" },
  110         { CARDBUS_VENDOR_REALTEK, CARDBUS_PRODUCT_REALTEK_RT8138,
  111                 RTK_8139, "Realtek 8138 10/100BaseTX" },
  112         { CARDBUS_VENDOR_REALTEK, CARDBUS_PRODUCT_REALTEK_RT8139,
  113                 RTK_8139, "Realtek 8139 10/100BaseTX" },
  114         { CARDBUS_VENDOR_COREGA, CARDBUS_PRODUCT_COREGA_CB_TXD,
  115                 RTK_8139, "Corega FEther CB-TXD 10/100BaseTX" },
  116         { CARDBUS_VENDOR_COREGA, CARDBUS_PRODUCT_COREGA_2CB_TXD,
  117                 RTK_8139, "Corega FEther II CB-TXD 10/100BaseTX" },
  118         { CARDBUS_VENDOR_PLANEX, CARDBUS_PRODUCT_PLANEX_FNW_3603_TX,
  119                 RTK_8139, "Planex FNW-3603 10/100BaseTX" },
  120         { CARDBUS_VENDOR_PLANEX, CARDBUS_PRODUCT_PLANEX_FNW_3800_TX,
  121                 RTK_8139, "Planex 10/100BaseTX FNW-3800-TX" },
  122         { CARDBUS_VENDOR_ABOCOM, CARDBUS_PRODUCT_ABOCOM_FE2000VX,
  123                 RTK_8139, "AboCom FE2000VX 10/100BaseTX" },
  124 
  125         { 0, 0, 0, NULL }
  126 };
  127 
  128 static int rtk_cardbus_match    __P((struct device *, struct cfdata *, void *));
  129 static void rtk_cardbus_attach  __P((struct device *, struct device *, void *));
  130 static int rtk_cardbus_detach   __P((struct device *, int));
  131 
  132 struct rtk_cardbus_softc {
  133         struct rtk_softc sc_rtk;        /* real rtk softc */ 
  134 
  135         /* CardBus-specific goo. */
  136         void *sc_ih;
  137         cardbus_devfunc_t sc_ct;
  138         cardbustag_t sc_tag;
  139         int sc_csr;
  140         int sc_cben;
  141         int sc_bar_reg;
  142         pcireg_t sc_bar_val;
  143         bus_size_t sc_mapsize;
  144         int sc_intrline;
  145 };
  146 
  147 CFATTACH_DECL(rtk_cardbus, sizeof(struct rtk_cardbus_softc),
  148     rtk_cardbus_match, rtk_cardbus_attach, rtk_cardbus_detach, rtk_activate);
  149 
  150 const struct rtk_type *rtk_cardbus_lookup
  151         __P((const struct cardbus_attach_args *));
  152 
  153 void rtk_cardbus_setup          __P((struct rtk_cardbus_softc *));
  154 
  155 int rtk_cardbus_enable          __P((struct rtk_softc *));
  156 void rtk_cardbus_disable        __P((struct rtk_softc *));
  157 void rtk_cardbus_power          __P((struct rtk_softc *, int));
  158 const struct rtk_type *
  159 rtk_cardbus_lookup(ca)
  160         const struct cardbus_attach_args *ca;
  161 {
  162         const struct rtk_type *t;
  163 
  164         for (t = rtk_cardbus_devs; t->rtk_name != NULL; t++){   
  165                 if (CARDBUS_VENDOR(ca->ca_id) == t->rtk_vid &&
  166                     CARDBUS_PRODUCT(ca->ca_id) == t->rtk_did) {
  167                         return (t);
  168                 }
  169         }
  170         return (NULL);
  171 }
  172 
  173 int
  174 rtk_cardbus_match(parent, match, aux)
  175         struct device *parent;
  176         struct cfdata *match;
  177         void *aux;
  178 {
  179         struct cardbus_attach_args *ca = aux;
  180 
  181         if (rtk_cardbus_lookup(ca) != NULL)
  182                 return (1);
  183 
  184         return (0);
  185 }
  186 
  187 
  188 void
  189 rtk_cardbus_attach(parent, self, aux)
  190         struct device *parent, *self;
  191         void *aux;
  192 {
  193         struct rtk_cardbus_softc *csc = (struct rtk_cardbus_softc *)self;
  194         struct rtk_softc *sc = &csc->sc_rtk;
  195         struct cardbus_attach_args *ca = aux;
  196         cardbus_devfunc_t ct = ca->ca_ct;
  197         const struct rtk_type *t;
  198         bus_addr_t adr;
  199 
  200         sc->sc_dmat = ca->ca_dmat;
  201         csc->sc_ct = ct;
  202         csc->sc_tag = ca->ca_tag;
  203         csc->sc_intrline = ca->ca_intrline;
  204 
  205         t = rtk_cardbus_lookup(ca); 
  206         if (t == NULL) { 
  207                 printf("\n"); 
  208                 panic("rtk_cardbus_attach: impossible");
  209          } 
  210         printf(": %s\n", t->rtk_name); 
  211         
  212         /*
  213          * Power management hooks.
  214          */
  215         sc->sc_enable = rtk_cardbus_enable;
  216         sc->sc_disable = rtk_cardbus_disable;
  217         sc->sc_power = rtk_cardbus_power;
  218 
  219         /*
  220          * Map control/status registers.
  221          */
  222         csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
  223 #ifdef RTK_USEIOSPACE
  224         if (Cardbus_mapreg_map(ct, RTK_PCI_LOIO, CARDBUS_MAPREG_TYPE_IO, 0,
  225             &sc->rtk_btag, &sc->rtk_bhandle, &adr, &csc->sc_mapsize) == 0) {
  226 #if rbus
  227 #else
  228                 (*ct->ct_cf->cardbus_io_open)(cc, 0, adr, adr+csc->sc_mapsize);
  229 #endif
  230                 csc->sc_cben = CARDBUS_IO_ENABLE;
  231                 csc->sc_csr |= CARDBUS_COMMAND_IO_ENABLE;
  232                 csc->sc_bar_reg = RTK_PCI_LOIO;
  233                 csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO;
  234         }
  235 #else
  236         if (Cardbus_mapreg_map(ct, RTK_PCI_LOMEM, CARDBUS_MAPREG_TYPE_MEM, 0,
  237             &sc->rtk_btag, &sc->rtk_bhandle, &adr, &csc->sc_mapsize) == 0) {
  238 #if rbus
  239 #else
  240                 (*ct->ct_cf->cardbus_mem_open)(cc, 0, adr, adr+csc->sc_mapsize);
  241 #endif
  242                 csc->sc_cben = CARDBUS_MEM_ENABLE;
  243                 csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
  244                 csc->sc_bar_reg = RTK_PCI_LOMEM;
  245                 csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
  246         }
  247 #endif
  248         else {
  249                 printf("%s: unable to map deviceregisters\n",
  250                          sc->sc_dev.dv_xname);
  251                 return;
  252         }
  253         /*
  254          * Handle power management nonsense and initialize the
  255          * configuration registers.
  256          */
  257         rtk_cardbus_setup(csc);
  258         sc->rtk_type = t->rtk_basetype;
  259 
  260         rtk_attach(sc);
  261 
  262         /*
  263          * Power down the socket.
  264          */
  265         Cardbus_function_disable(csc->sc_ct);
  266 }
  267 
  268 int 
  269 rtk_cardbus_detach(self, flags)
  270         struct device *self;
  271         int flags;
  272 {
  273         struct rtk_cardbus_softc *csc = (void *) self;
  274         struct rtk_softc *sc = &csc->sc_rtk;
  275         struct cardbus_devfunc *ct = csc->sc_ct;
  276         int     rv;
  277 
  278 #ifdef DIAGNOSTIC
  279         if (ct == NULL)
  280                 panic("%s: data structure lacks", sc->sc_dev.dv_xname);
  281 #endif
  282         rv = rtk_detach(sc);
  283         if (rv)
  284                 return (rv);
  285         /*
  286          * Unhook the interrupt handler.
  287          */
  288         if (csc->sc_ih != NULL)
  289                 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
  290         
  291         /*
  292          * Release bus space and close window.
  293          */
  294         if (csc->sc_bar_reg != 0)
  295                 Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
  296                         sc->rtk_btag, sc->rtk_bhandle, csc->sc_mapsize);
  297 
  298         return (0);
  299 }
  300 
  301 void 
  302 rtk_cardbus_setup(csc)
  303         struct rtk_cardbus_softc *csc;
  304 {
  305         struct rtk_softc *sc = &csc->sc_rtk;
  306         cardbus_devfunc_t ct = csc->sc_ct;
  307         cardbus_chipset_tag_t cc = ct->ct_cc;
  308         cardbus_function_tag_t cf = ct->ct_cf;
  309         pcireg_t        reg,command;
  310         int             pmreg;
  311 
  312         /*
  313          * Handle power management nonsense.
  314          */
  315         if (cardbus_get_capability(cc, cf, csc->sc_tag,
  316             PCI_CAP_PWRMGMT, &pmreg, 0)) {
  317                 command = cardbus_conf_read(cc, cf, csc->sc_tag, pmreg + 4);
  318                 if (command & RTK_PSTATE_MASK) {
  319                         pcireg_t                iobase, membase, irq;
  320 
  321                         /* Save important PCI config data. */
  322                         iobase = cardbus_conf_read(cc, cf, csc->sc_tag,
  323                             RTK_PCI_LOIO);
  324                         membase = cardbus_conf_read(cc, cf,csc->sc_tag,
  325                             RTK_PCI_LOMEM);
  326                         irq = cardbus_conf_read(cc, cf,csc->sc_tag,
  327                             CARDBUS_INTERRUPT_REG);
  328 
  329                         /* Reset the power state. */
  330                         printf("%s: chip is in D%d power mode "
  331                             "-- setting to D0\n", sc->sc_dev.dv_xname,
  332                             command & RTK_PSTATE_MASK);
  333                         command &= 0xFFFFFFFC;
  334                         cardbus_conf_write(cc, cf, csc->sc_tag,
  335                             pmreg + 4, command);
  336 
  337                         /* Restore PCI config data. */
  338                         cardbus_conf_write(cc, cf, csc->sc_tag,
  339                             RTK_PCI_LOIO, iobase);
  340                         cardbus_conf_write(cc, cf, csc->sc_tag,
  341                             RTK_PCI_LOMEM, membase);
  342                         cardbus_conf_write(cc, cf, csc->sc_tag,
  343                             CARDBUS_INTERRUPT_REG, irq);
  344                 }
  345         }
  346 
  347         /* Make sure the right access type is on the CardBus bridge. */
  348         (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
  349         (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
  350 
  351         /* Program the BAR */
  352         cardbus_conf_write(cc, cf, csc->sc_tag,
  353                 csc->sc_bar_reg, csc->sc_bar_val);
  354 
  355         /* Enable the appropriate bits in the CARDBUS CSR. */
  356         reg = cardbus_conf_read(cc, cf, csc->sc_tag, 
  357             CARDBUS_COMMAND_STATUS_REG);
  358         reg &= ~(CARDBUS_COMMAND_IO_ENABLE|CARDBUS_COMMAND_MEM_ENABLE);
  359         reg |= csc->sc_csr;
  360         cardbus_conf_write(cc, cf, csc->sc_tag, 
  361             CARDBUS_COMMAND_STATUS_REG, reg);
  362 
  363         /*
  364          * Make sure the latency timer is set to some reasonable
  365          * value.
  366          */
  367         reg = cardbus_conf_read(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG);
  368         if (CARDBUS_LATTIMER(reg) < 0x20) {
  369                 reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
  370                 reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
  371                 cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG, reg);
  372         }
  373 }
  374 
  375 int 
  376 rtk_cardbus_enable(sc)
  377         struct rtk_softc *sc;
  378 {
  379         struct rtk_cardbus_softc *csc = (void *) sc;
  380         cardbus_devfunc_t ct = csc->sc_ct;
  381         cardbus_chipset_tag_t cc = ct->ct_cc;
  382         cardbus_function_tag_t cf = ct->ct_cf;
  383 
  384         /*
  385          * Power on the socket.
  386          */
  387         Cardbus_function_enable(ct);
  388 
  389         /*
  390          * Set up the PCI configuration registers.
  391          */
  392         rtk_cardbus_setup(csc);
  393 
  394         /*
  395          * Map and establish the interrupt.
  396          */
  397         csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline,
  398                 IPL_NET, rtk_intr, sc);
  399         if (csc->sc_ih == NULL) {
  400                 printf("%s: unable to establish interrupt at %d\n",
  401                         sc->sc_dev.dv_xname, csc->sc_intrline);
  402                 Cardbus_function_disable(csc->sc_ct);
  403                 return (1);
  404         }
  405         printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname,
  406                 csc->sc_intrline);
  407         return (0);
  408 }
  409 
  410 void 
  411 rtk_cardbus_disable(sc)
  412         struct rtk_softc *sc;
  413 {
  414         struct rtk_cardbus_softc *csc = (void *) sc;
  415         cardbus_devfunc_t ct = csc->sc_ct;
  416         cardbus_chipset_tag_t cc = ct->ct_cc;
  417         cardbus_function_tag_t cf = ct->ct_cf;
  418 
  419         /* Unhook the interrupt handler. */
  420         cardbus_intr_disestablish(cc, cf, csc->sc_ih);
  421         csc->sc_ih = NULL;
  422 
  423         /* Power down the socket. */
  424         Cardbus_function_disable(ct);
  425 }
  426 
  427 void 
  428 rtk_cardbus_power(sc, why)
  429         struct rtk_softc *sc;
  430         int why;
  431 {
  432         struct rtk_cardbus_softc *csc = (void *) sc;
  433 
  434         if (why == PWR_RESUME) {
  435                 /*
  436                  * Give the PCI configuration registers a kick
  437                  * in the head.
  438                  */
  439 #ifdef DIAGNOSTIC
  440                 if (RTK_IS_ENABLED(sc) == 0)
  441                         panic("rtk_cardbus_power");
  442 #endif
  443                 rtk_cardbus_setup(csc);
  444         }
  445 }

Cache object: 272002d21ae060c9c7e3514c6742e608


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