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_re_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 /*      $OpenBSD: if_re_cardbus.c,v 1.30 2022/04/06 18:59:28 naddy Exp $        */
    2 
    3 /*
    4  * Copyright (c) 2005 Peter Valchev <pvalchev@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 /*
   20  * Cardbus front-end for the Realtek 8169
   21  */
   22 
   23 #include <sys/param.h>
   24 #include <sys/endian.h>
   25 #include <sys/systm.h>
   26 #include <sys/sockio.h>
   27 #include <sys/mbuf.h>
   28 #include <sys/malloc.h>
   29 #include <sys/kernel.h>
   30 #include <sys/device.h>
   31 #include <sys/timeout.h>
   32 #include <sys/socket.h>
   33 
   34 #include <net/if.h>
   35 #include <net/if_media.h>
   36 
   37 #include <netinet/in.h>
   38 #include <netinet/if_ether.h>
   39 
   40 #include <dev/mii/miivar.h>
   41 
   42 #include <dev/pci/pcidevs.h>
   43 
   44 #include <dev/cardbus/cardbusvar.h>
   45 
   46 #include <dev/ic/rtl81x9reg.h>
   47 #include <dev/ic/revar.h>
   48 
   49 struct re_cardbus_softc {
   50         /* General */
   51         struct rl_softc sc_rl;
   52 
   53         /* Cardbus-specific data */
   54         cardbus_devfunc_t ct;
   55         pcitag_t sc_tag;
   56         pci_chipset_tag_t sc_pc;
   57         int sc_csr;
   58         int sc_cben;
   59         int sc_bar_reg;
   60         pcireg_t sc_bar_val;
   61         int sc_intrline;
   62 
   63         bus_size_t sc_mapsize;
   64 };
   65 
   66 int     re_cardbus_probe(struct device *, void *, void *);
   67 void    re_cardbus_attach(struct device *, struct device *, void *);
   68 int     re_cardbus_detach(struct device *, int);
   69 void    re_cardbus_setup(struct rl_softc *);
   70 
   71 /*
   72  * Cardbus autoconfig definitions
   73  */
   74 const struct cfattach re_cardbus_ca = {
   75         sizeof(struct re_cardbus_softc),
   76         re_cardbus_probe,
   77         re_cardbus_attach,
   78         re_cardbus_detach
   79 };
   80 
   81 const struct pci_matchid re_cardbus_devices[] = {
   82         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169 },
   83 };
   84 
   85 /*
   86  * Probe for a Realtek 8169/8110 chip. Check the PCI vendor and device
   87  * IDs against our list and return a device name if we find a match.
   88  */
   89 int
   90 re_cardbus_probe(struct device *parent, void *match, void *aux)
   91 {
   92         return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
   93             re_cardbus_devices, nitems(re_cardbus_devices)));
   94 }
   95 
   96 /*
   97  * Attach the interface. Allocate softc structures, do ifmedia
   98  * setup and ethernet/BPF attach.
   99  */
  100 void
  101 re_cardbus_attach(struct device *parent, struct device *self, void *aux)
  102 {
  103         struct re_cardbus_softc *csc = (struct re_cardbus_softc *)self;
  104         struct rl_softc         *sc = &csc->sc_rl;
  105         struct cardbus_attach_args *ca = aux;
  106         struct cardbus_softc *psc =
  107             (struct cardbus_softc *)sc->sc_dev.dv_parent;
  108         cardbus_chipset_tag_t cc = psc->sc_cc;
  109         cardbus_function_tag_t cf = psc->sc_cf;
  110         cardbus_devfunc_t ct = ca->ca_ct;
  111         bus_addr_t adr;
  112         char intrstr[16];
  113 
  114         sc->sc_dmat = ca->ca_dmat;
  115         csc->ct = ct;
  116         csc->sc_tag = ca->ca_tag;
  117         csc->sc_pc = ca->ca_pc;
  118         csc->sc_intrline = ca->ca_intrline;
  119 
  120         /*
  121          * Map control/status registers.
  122          */
  123         if (Cardbus_mapreg_map(ct, RL_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
  124             &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
  125                 csc->sc_cben = CARDBUS_MEM_ENABLE;
  126                 csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
  127                 csc->sc_bar_reg = RL_PCI_LOMEM;
  128                 csc->sc_bar_val = adr | PCI_MAPREG_TYPE_MEM;
  129         } else {
  130                 printf(": can't map mem space\n");
  131                 return;
  132         }
  133 
  134         /* Enable power */
  135         Cardbus_function_enable(ct);
  136 
  137         /* Get chip out of powersave mode (if applicable), initialize
  138          * config registers */
  139         re_cardbus_setup(sc);
  140 
  141         /* Allocate interrupt */
  142         sc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline,
  143             IPL_NET, re_intr, sc, sc->sc_dev.dv_xname);
  144         if (sc->sc_ih == NULL) {
  145                 printf(": couldn't establish interrupt at %d",
  146                     ca->ca_intrline);
  147                 Cardbus_function_disable(csc->ct);
  148                 return;
  149         }
  150         snprintf(intrstr, sizeof(intrstr), "irq %d", ca->ca_intrline);
  151 
  152         sc->sc_product = PCI_PRODUCT(ca->ca_id);
  153 
  154         /* Call bus-independent (common) attach routine */
  155         if (re_attach(sc, intrstr)) {
  156                 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, sc->sc_ih);
  157                 Cardbus_mapreg_unmap(ct, csc->sc_bar_reg, sc->rl_btag,
  158                     sc->rl_bhandle, csc->sc_mapsize);
  159         }
  160 }
  161 
  162 /*
  163  * Get chip out of power-saving mode, init registers
  164  */
  165 void
  166 re_cardbus_setup(struct rl_softc *sc)
  167 {
  168         struct re_cardbus_softc *csc = (struct re_cardbus_softc *)sc;
  169         cardbus_devfunc_t ct = csc->ct;
  170         cardbus_chipset_tag_t cc = ct->ct_cc;
  171         pci_chipset_tag_t pc = csc->sc_pc;
  172         pcireg_t reg, command;
  173         int pmreg;
  174 
  175         /* Handle power management nonsense */
  176         if (pci_get_capability(pc, csc->sc_tag,
  177             PCI_CAP_PWRMGMT, &pmreg, 0)) {
  178                 command = pci_conf_read(pc, csc->sc_tag,
  179                     pmreg + PCI_PMCSR);
  180 
  181                 if (command & RL_PSTATE_MASK) {
  182                         pcireg_t iobase, membase, irq;
  183 
  184                         /* Save important PCI config data */
  185                         iobase = pci_conf_read(pc, csc->sc_tag, RL_PCI_LOIO);
  186                         membase = pci_conf_read(pc, csc->sc_tag, RL_PCI_LOMEM);
  187                         irq = pci_conf_read(pc, csc->sc_tag, RL_PCI_INTLINE);
  188 
  189                         /* Reset the power state */
  190                         printf("%s: chip is in D%d power mode "
  191                             "-- setting to D0\n", sc->sc_dev.dv_xname,
  192                             command & RL_PSTATE_MASK);
  193                         command &= RL_PSTATE_MASK;
  194                         pci_conf_write(pc, csc->sc_tag, pmreg + PCI_PMCSR,
  195                             command);
  196 
  197                         /* Restore PCI config data */
  198                         pci_conf_write(pc, csc->sc_tag, RL_PCI_LOIO, iobase);
  199                         pci_conf_write(pc, csc->sc_tag, RL_PCI_LOMEM, membase);
  200                         pci_conf_write(pc, csc->sc_tag, RL_PCI_INTLINE, irq);
  201                 }
  202         }
  203 
  204         /* Make sure the right access type is on the Cardbus bridge */
  205         (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
  206         (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
  207 
  208         /* Program the BAR */
  209         pci_conf_write(pc, csc->sc_tag, csc->sc_bar_reg, csc->sc_bar_val);
  210 
  211         /* Enable proper bits in CARDBUS CSR */
  212         reg = pci_conf_read(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG);
  213         reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
  214         reg |= csc->sc_csr;
  215         pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG, reg);
  216 
  217         /* Make sure the latency timer is set to some reasonable value */
  218         reg = pci_conf_read(pc, csc->sc_tag, PCI_BHLC_REG);
  219         if (PCI_LATTIMER(reg) < 0x20) {
  220                 reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
  221                 reg |= (0x20 << PCI_LATTIMER_SHIFT);
  222                 pci_conf_write(pc, csc->sc_tag, PCI_BHLC_REG, reg);
  223         }
  224 }
  225 
  226 /*
  227  * Cardbus detach function: deallocate all resources
  228  */
  229 int
  230 re_cardbus_detach(struct device *self, int flags)
  231 {
  232         struct re_cardbus_softc *csc = (void *)self;
  233         struct rl_softc *sc = &csc->sc_rl;
  234         struct cardbus_devfunc *ct = csc->ct;
  235         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  236 
  237         /* Remove timeout handler */
  238         timeout_del(&sc->timer_handle);
  239 
  240         /* Detach PHY */
  241         if (LIST_FIRST(&sc->sc_mii.mii_phys) != NULL)
  242                 mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
  243 
  244         /* Delete media stuff */
  245         ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
  246         ether_ifdetach(ifp);
  247         if_detach(ifp);
  248 
  249         /* Disable interrupts */
  250         if (sc->sc_ih != NULL)
  251                 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, sc->sc_ih);
  252 
  253         /* Free cardbus resources */
  254         Cardbus_mapreg_unmap(ct, csc->sc_bar_reg, sc->rl_btag, sc->rl_bhandle,
  255             csc->sc_mapsize);
  256 
  257         return (0);
  258 }

Cache object: 1fa6d490edf8868323019f8877fba54b


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