LCOV - code coverage report
Current view: top level - dev/pci - if_re_pci.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 95 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if_re_pci.c,v 1.52 2018/04/11 08:02:18 patrick 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             :  * PCI 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/pcireg.h>
      43             : #include <dev/pci/pcivar.h>
      44             : #include <dev/pci/pcidevs.h>
      45             : 
      46             : #include <dev/ic/rtl81x9reg.h>
      47             : #include <dev/ic/revar.h>
      48             : 
      49             : struct re_pci_softc {
      50             :         /* General */
      51             :         struct rl_softc sc_rl;
      52             : 
      53             :         /* PCI-specific data */
      54             :         void *sc_ih;
      55             :         pci_chipset_tag_t sc_pc;
      56             :         pcitag_t sc_pcitag;
      57             : 
      58             :         bus_size_t sc_iosize;
      59             : };
      60             : 
      61             : const struct pci_matchid re_pci_devices[] = {
      62             :         { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_CGLAPCIGT },
      63             :         { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE528T },
      64             :         { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE530T_C1 },
      65             :         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8101E },
      66             :         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8168 },
      67             :         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169 },
      68             :         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169SC },
      69             :         { PCI_VENDOR_TTTECH, PCI_PRODUCT_TTTECH_MC322 },
      70             :         { PCI_VENDOR_USR2, PCI_PRODUCT_USR2_USR997902 }
      71             : };
      72             : 
      73             : #define RE_LINKSYS_EG1032_SUBID 0x00241737
      74             : 
      75             : int     re_pci_probe(struct device *, void *, void *);
      76             : void    re_pci_attach(struct device *, struct device *, void *);
      77             : int     re_pci_detach(struct device *, int);
      78             : int     re_pci_activate(struct device *, int);
      79             : 
      80             : /*
      81             :  * PCI autoconfig definitions
      82             :  */
      83             : struct cfattach re_pci_ca = {
      84             :         sizeof(struct re_pci_softc),
      85             :         re_pci_probe,
      86             :         re_pci_attach,
      87             :         re_pci_detach,
      88             :         re_pci_activate
      89             : };
      90             : 
      91             : /*
      92             :  * Probe for a Realtek 8169/8110 chip. Check the PCI vendor and device
      93             :  * IDs against our list and return a device name if we find a match.
      94             :  */
      95             : int
      96           0 : re_pci_probe(struct device *parent, void *match, void *aux)
      97             : {
      98           0 :         struct pci_attach_args *pa = aux;
      99           0 :         pci_chipset_tag_t pc = pa->pa_pc;
     100             :         pcireg_t subid;
     101             : 
     102           0 :         subid = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
     103             : 
     104             :         /* C+ mode 8139's */
     105           0 :         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_REALTEK &&
     106           0 :             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RT8139 &&
     107           0 :             PCI_REVISION(pa->pa_class) == 0x20)
     108           0 :                 return (1);
     109             : 
     110           0 :         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_LINKSYS &&
     111           0 :             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LINKSYS_EG1032 &&
     112           0 :             subid == RE_LINKSYS_EG1032_SUBID)
     113           0 :                 return (1);
     114             : 
     115           0 :         return (pci_matchbyid((struct pci_attach_args *)aux, re_pci_devices,
     116             :             nitems(re_pci_devices)));
     117           0 : }
     118             : 
     119             : /*
     120             :  * PCI-specific attach routine
     121             :  */
     122             : void
     123           0 : re_pci_attach(struct device *parent, struct device *self, void *aux)
     124             : {
     125           0 :         struct re_pci_softc     *psc = (struct re_pci_softc *)self;
     126           0 :         struct rl_softc         *sc = &psc->sc_rl;
     127           0 :         struct pci_attach_args  *pa = aux;
     128           0 :         pci_chipset_tag_t       pc = pa->pa_pc;
     129           0 :         pci_intr_handle_t       ih;
     130             :         const char              *intrstr = NULL;
     131             :         pcireg_t                reg;
     132           0 :         int                     offset;
     133             : 
     134           0 :         pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
     135             : 
     136             : #ifndef SMALL_KERNEL
     137             :         /* Enable power management for wake on lan. */
     138           0 :         pci_conf_write(pc, pa->pa_tag, RL_PCI_PMCSR, RL_PME_EN);
     139             : #endif
     140             : 
     141             :         /*
     142             :          * Map control/status registers.
     143             :          */
     144           0 :         if (pci_mapreg_map(pa, RL_PCI_LOMEM64, PCI_MAPREG_TYPE_MEM |
     145           0 :             PCI_MAPREG_MEM_TYPE_64BIT, 0, &sc->rl_btag, &sc->rl_bhandle,
     146           0 :             NULL, &psc->sc_iosize, 0)) {
     147           0 :                 if (pci_mapreg_map(pa, RL_PCI_LOMEM, PCI_MAPREG_TYPE_MEM |
     148             :                     PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->rl_btag, &sc->rl_bhandle,
     149             :                     NULL, &psc->sc_iosize, 0)) {
     150           0 :                         if (pci_mapreg_map(pa, RL_PCI_LOIO, PCI_MAPREG_TYPE_IO,
     151             :                             0, &sc->rl_btag, &sc->rl_bhandle, NULL,
     152             :                             &psc->sc_iosize, 0)) {
     153           0 :                                 printf(": can't map mem or i/o space\n");
     154           0 :                                 return;
     155             :                         }
     156             :                 }
     157             :         }
     158             : 
     159             :         /* Allocate interrupt */
     160           0 :         if (pci_intr_map_msi(pa, &ih) == 0)
     161           0 :                 sc->rl_flags |= RL_FLAG_MSI;
     162           0 :         else if (pci_intr_map(pa, &ih) != 0) {
     163           0 :                 printf(": couldn't map interrupt\n");
     164           0 :                 return;
     165             :         }
     166           0 :         intrstr = pci_intr_string(pc, ih);
     167           0 :         psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET | IPL_MPSAFE, re_intr,
     168           0 :             sc, sc->sc_dev.dv_xname);
     169           0 :         if (psc->sc_ih == NULL) {
     170           0 :                 printf(": couldn't establish interrupt");
     171           0 :                 if (intrstr != NULL)
     172           0 :                         printf(" at %s", intrstr);
     173           0 :                 return;
     174             :         }
     175             : 
     176           0 :         sc->sc_dmat = pa->pa_dmat;
     177           0 :         psc->sc_pc = pc;
     178             : 
     179             :         /*
     180             :          * PCI Express check.
     181             :          */
     182           0 :         if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PCIEXPRESS,
     183             :             &offset, NULL)) {
     184             :                 /* Disable PCIe ASPM and ECPM. */
     185           0 :                 reg = pci_conf_read(pc, pa->pa_tag, offset + PCI_PCIE_LCSR);
     186           0 :                 reg &= ~(PCI_PCIE_LCSR_ASPM_L0S | PCI_PCIE_LCSR_ASPM_L1 |
     187             :                     PCI_PCIE_LCSR_ECPM);
     188           0 :                 pci_conf_write(pc, pa->pa_tag, offset + PCI_PCIE_LCSR, reg);
     189           0 :                 sc->rl_flags |= RL_FLAG_PCIE;
     190           0 :         }
     191             : 
     192           0 :         if (!(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_REALTEK &&
     193           0 :             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RT8139)) {
     194             :                 u_int8_t        cfg;
     195             : 
     196           0 :                 CSR_WRITE_1(sc, RL_EECMD, RL_EE_MODE);
     197           0 :                 cfg = CSR_READ_1(sc, RL_CFG2);
     198           0 :                 if (sc->rl_flags & RL_FLAG_MSI) {
     199           0 :                         cfg |= RL_CFG2_MSI;
     200           0 :                         CSR_WRITE_1(sc, RL_CFG2, cfg);
     201           0 :                 } else {
     202           0 :                         if ((cfg & RL_CFG2_MSI) != 0) {
     203           0 :                                 cfg &= ~RL_CFG2_MSI;
     204           0 :                                 CSR_WRITE_1(sc, RL_CFG2, cfg);
     205           0 :                         }
     206             :                 }
     207           0 :                 CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
     208           0 :         }
     209             : 
     210           0 :         sc->sc_product = PCI_PRODUCT(pa->pa_id);
     211             : 
     212             :         /* Call bus-independent attach routine */
     213           0 :         if (re_attach(sc, intrstr)) {
     214           0 :                 pci_intr_disestablish(pc, psc->sc_ih);
     215           0 :                 bus_space_unmap(sc->rl_btag, sc->rl_bhandle, psc->sc_iosize);
     216           0 :         }
     217           0 : }
     218             : 
     219             : int
     220           0 : re_pci_detach(struct device *self, int flags)
     221             : {
     222           0 :         struct re_pci_softc     *psc = (struct re_pci_softc *)self;
     223           0 :         struct rl_softc         *sc = &psc->sc_rl;
     224           0 :         struct ifnet            *ifp = &sc->sc_arpcom.ac_if;
     225             : 
     226             :         /* Remove timeout handler */
     227           0 :         timeout_del(&sc->timer_handle);
     228             : 
     229             :         /* Detach PHY */
     230           0 :         if (LIST_FIRST(&sc->sc_mii.mii_phys) != NULL)
     231           0 :                 mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
     232             : 
     233             :         /* Delete media stuff */
     234           0 :         ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
     235           0 :         ether_ifdetach(ifp);
     236           0 :         if_detach(ifp);
     237             : 
     238             :         /* Disable interrupts */
     239           0 :         if (psc->sc_ih != NULL)
     240           0 :                 pci_intr_disestablish(psc->sc_pc, psc->sc_ih);
     241             : 
     242             :         /* Free pci resources */
     243           0 :         bus_space_unmap(sc->rl_btag, sc->rl_bhandle, psc->sc_iosize);
     244             : 
     245           0 :         return (0);
     246             : }
     247             : 
     248             : int
     249           0 : re_pci_activate(struct device *self, int act)
     250             : {
     251           0 :         struct re_pci_softc     *psc = (struct re_pci_softc *)self;
     252           0 :         struct rl_softc         *sc = &psc->sc_rl;
     253           0 :         struct ifnet            *ifp = &sc->sc_arpcom.ac_if;
     254             : 
     255           0 :         switch (act) {
     256             :         case DVACT_SUSPEND:
     257           0 :                 if (ifp->if_flags & IFF_RUNNING)
     258           0 :                         re_stop(ifp);
     259             :                 break;
     260             :         case DVACT_RESUME:
     261           0 :                 if (ifp->if_flags & IFF_UP)
     262           0 :                         re_init(ifp);
     263             :                 break;
     264             :         }
     265             : 
     266           0 :         return (0);
     267             : }

Generated by: LCOV version 1.13