LCOV - code coverage report
Current view: top level - dev/cardbus - if_rl_cardbus.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 89 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_rl_cardbus.c,v 1.30 2015/11/24 17:11:39 mpi Exp $ */
       2             : /*      $NetBSD: if_rl_cardbus.c,v 1.3.8.3 2001/11/14 19:14:02 nathanw Exp $    */
       3             : 
       4             : /*
       5             :  * Copyright (c) 2000 Masanori Kanaoka
       6             :  * All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  * 1. Redistributions of source code must retain the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer.
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  * 3. The name of the author may not be used to endorse or promote products
      17             :  *    derived from this software without specific prior written permission.
      18             :  *
      19             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      20             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      21             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      22             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      23             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      24             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      25             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      26             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      27             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      28             :  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29             :  */
      30             : 
      31             : /*
      32             :  * if_rl_cardbus.c:
      33             :  *      Cardbus specific routines for Realtek 8139 ethernet adapter.
      34             :  *      Tested for 
      35             :  *              - elecom-Laneed LD-10/100CBA (Accton MPX5030)
      36             :  *              - MELCO         LPC3-TX-CB   (Realtek 8139)
      37             :  */
      38             : 
      39             : #include "bpfilter.h"
      40             : 
      41             : #include <sys/param.h>
      42             : #include <sys/systm.h>
      43             : #include <sys/mbuf.h>
      44             : #include <sys/socket.h>
      45             : #include <sys/ioctl.h>
      46             : #include <sys/errno.h>
      47             : #include <sys/malloc.h>
      48             : #include <sys/kernel.h>
      49             : #include <sys/timeout.h>
      50             : #include <sys/device.h>
      51             : #include <sys/endian.h>
      52             : 
      53             : #include <net/if.h>
      54             : #include <net/if_media.h>
      55             : 
      56             : #if NBPFILTER > 0
      57             : #include <net/bpf.h>
      58             : #endif
      59             : 
      60             : #include <netinet/in.h>
      61             : #include <netinet/if_ether.h>
      62             : 
      63             : #include <machine/bus.h>
      64             : #include <machine/intr.h>
      65             : 
      66             : #include <dev/mii/miivar.h>
      67             : 
      68             : #include <dev/pci/pcivar.h>
      69             : #include <dev/pci/pcireg.h>
      70             : #include <dev/pci/pcidevs.h>
      71             : 
      72             : #include <dev/cardbus/cardbusvar.h>
      73             : 
      74             : /*
      75             :  * Default to using PIO access for this driver. On SMP systems,
      76             :  * there appear to be problems with memory mapped mode: it looks like
      77             :  * doing too many memory mapped access back to back in rapid succession
      78             :  * can hang the bus. I'm inclined to blame this on crummy design/construction
      79             :  * on the part of Realtek. Memory mapped mode does appear to work on
      80             :  * uniprocessor systems though.
      81             :  */
      82             : #define RL_USEIOSPACE 
      83             : 
      84             : #include <dev/ic/rtl81x9reg.h>
      85             : 
      86             : /*
      87             :  * Various supported device vendors/types and their names.
      88             :  */
      89             : const struct pci_matchid rl_cardbus_devices[] = {
      90             :         { PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2000VX },
      91             :         { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_5030 },
      92             :         { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_2CB_TXD },
      93             :         { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_CB_TXD },
      94             :         { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DFE690TXD },
      95             :         { PCI_VENDOR_PLANEX, PCI_PRODUCT_PLANEX_FNW_3603_TX },
      96             :         { PCI_VENDOR_PLANEX, PCI_PRODUCT_PLANEX_FNW_3800_TX },
      97             :         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8138 },
      98             :         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8139 },
      99             : };
     100             : 
     101             : struct rl_cardbus_softc {
     102             :         struct rl_softc sc_rl;  /* real rtk softc */ 
     103             : 
     104             :         /* CardBus-specific goo. */
     105             :         void *sc_ih;
     106             :         cardbus_devfunc_t sc_ct;
     107             :         pci_chipset_tag_t sc_pc;
     108             :         pcitag_t sc_tag;
     109             :         int sc_csr;
     110             :         int sc_cben;
     111             :         int sc_bar_reg;
     112             :         pcireg_t sc_bar_val;
     113             :         bus_size_t sc_mapsize;
     114             :         int sc_intrline;
     115             : };
     116             : 
     117             : static int rl_cardbus_match(struct device *, void *, void *);
     118             : static void rl_cardbus_attach(struct device *, struct device *, void *);
     119             : static int rl_cardbus_detach(struct device *, int);
     120             : void rl_cardbus_setup(struct rl_cardbus_softc *);
     121             : 
     122             : struct cfattach rl_cardbus_ca = {
     123             :         sizeof(struct rl_cardbus_softc), rl_cardbus_match, rl_cardbus_attach,
     124             :             rl_cardbus_detach
     125             : };
     126             : 
     127             : int
     128           0 : rl_cardbus_match(struct device *parent, void *match, void *aux)
     129             : {
     130           0 :         return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
     131             :             rl_cardbus_devices, nitems(rl_cardbus_devices)));
     132             : }
     133             : 
     134             : 
     135             : void
     136           0 : rl_cardbus_attach(struct device *parent, struct device *self, void *aux)
     137             : {
     138             :         struct rl_cardbus_softc         *csc =
     139           0 :             (struct rl_cardbus_softc *)self;
     140           0 :         struct rl_softc                 *sc = &csc->sc_rl;
     141           0 :         struct cardbus_attach_args      *ca = aux;
     142             :         struct cardbus_softc            *psc =
     143           0 :             (struct cardbus_softc *)sc->sc_dev.dv_parent;
     144           0 :         cardbus_chipset_tag_t           cc = psc->sc_cc;
     145           0 :         cardbus_function_tag_t          cf = psc->sc_cf;                            
     146           0 :         cardbus_devfunc_t               ct = ca->ca_ct;
     147           0 :         bus_addr_t                      adr;
     148             : 
     149           0 :         sc->sc_dmat = ca->ca_dmat;
     150           0 :         csc->sc_ct = ct;
     151           0 :         csc->sc_tag = ca->ca_tag;
     152           0 :         csc->sc_intrline = ca->ca_intrline;
     153           0 :         csc->sc_pc = ca->ca_pc;
     154             : 
     155             :         /*
     156             :          * Map control/status registers.
     157             :          */
     158           0 :         csc->sc_csr = PCI_COMMAND_MASTER_ENABLE;
     159             : #ifdef RL_USEIOSPACE
     160           0 :         if (Cardbus_mapreg_map(ct, RL_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
     161           0 :             &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
     162           0 :                 csc->sc_cben = CARDBUS_IO_ENABLE;
     163           0 :                 csc->sc_csr |= PCI_COMMAND_IO_ENABLE;
     164           0 :                 csc->sc_bar_reg = RL_PCI_LOIO;
     165           0 :                 csc->sc_bar_val = adr | PCI_MAPREG_TYPE_IO;
     166             :         }
     167             : #else
     168             :         if (Cardbus_mapreg_map(ct, RL_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
     169             :             &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
     170             :                 csc->sc_cben = CARDBUS_MEM_ENABLE;
     171             :                 csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
     172             :                 csc->sc_bar_reg = RL_PCI_LOMEM;
     173             :                 csc->sc_bar_val = adr | PCI_MAPREG_TYPE_MEM;
     174             :         }
     175             : #endif
     176             :         else {
     177           0 :                 printf("%s: unable to map deviceregisters\n",
     178           0 :                          sc->sc_dev.dv_xname);
     179           0 :                 return;
     180             :         }
     181             : 
     182           0 :         Cardbus_function_enable(ct);
     183             : 
     184           0 :         rl_cardbus_setup(csc);
     185             : 
     186             :         /*
     187             :          * Map and establish the interrupt.
     188             :          */
     189           0 :         csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
     190           0 :             rl_intr, sc, sc->sc_dev.dv_xname);
     191           0 :         if (csc->sc_ih == NULL) {
     192           0 :                 printf(": couldn't establish interrupt\n");
     193           0 :                 Cardbus_function_disable(csc->sc_ct);
     194           0 :                 return;
     195             :         }
     196           0 :         printf(": irq %d", csc->sc_intrline);
     197             : 
     198           0 :         sc->rl_type = RL_8139;
     199             : 
     200           0 :         rl_attach(sc);
     201           0 : }
     202             : 
     203             : int 
     204           0 : rl_cardbus_detach(struct device *self, int flags)
     205             : {
     206           0 :         struct rl_cardbus_softc *csc = (void *) self;
     207           0 :         struct rl_softc         *sc = &csc->sc_rl;
     208           0 :         struct cardbus_devfunc  *ct = csc->sc_ct;
     209             :         int                     rv;
     210             : 
     211             : #ifdef DIAGNOSTIC
     212           0 :         if (ct == NULL)
     213           0 :                 panic("%s: data structure lacks", sc->sc_dev.dv_xname);
     214             : #endif
     215           0 :         rv = rl_detach(sc);
     216           0 :         if (rv)
     217           0 :                 return (rv);
     218             :         /*
     219             :          * Unhook the interrupt handler.
     220             :          */
     221           0 :         if (csc->sc_ih != NULL)
     222           0 :                 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
     223             :         
     224             :         /*
     225             :          * Release bus space and close window.
     226             :          */
     227           0 :         if (csc->sc_bar_reg != 0)
     228           0 :                 Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
     229             :                         sc->rl_btag, sc->rl_bhandle, csc->sc_mapsize);
     230             : 
     231           0 :         return (0);
     232           0 : }
     233             : 
     234             : void 
     235           0 : rl_cardbus_setup(struct rl_cardbus_softc *csc)
     236             : {
     237           0 :         struct rl_softc         *sc = &csc->sc_rl;
     238           0 :         cardbus_devfunc_t       ct = csc->sc_ct;
     239           0 :         cardbus_chipset_tag_t   cc = ct->ct_cc;
     240           0 :         pci_chipset_tag_t       pc = csc->sc_pc;
     241             :         pcireg_t                reg, command;
     242           0 :         int                     pmreg;
     243             : 
     244             :         /*
     245             :          * Handle power management nonsense.
     246             :          */
     247           0 :         if (pci_get_capability(pc, csc->sc_tag,
     248             :             PCI_CAP_PWRMGMT, &pmreg, 0)) {
     249           0 :                 command = pci_conf_read(pc, csc->sc_tag, pmreg + 4);
     250           0 :                 if (command & RL_PSTATE_MASK) {
     251             :                         pcireg_t                iobase, membase, irq;
     252             : 
     253             :                         /* Save important PCI config data. */
     254           0 :                         iobase = pci_conf_read(pc, csc->sc_tag,
     255             :                             RL_PCI_LOIO);
     256           0 :                         membase = pci_conf_read(pc, csc->sc_tag,
     257             :                             RL_PCI_LOMEM);
     258           0 :                         irq = pci_conf_read(pc, csc->sc_tag,
     259             :                             PCI_PRODUCT_DELTA_8139);
     260             : 
     261             :                         /* Reset the power state. */
     262           0 :                         printf("%s: chip is in D%d power mode "
     263           0 :                             "-- setting to D0\n", sc->sc_dev.dv_xname,
     264             :                             command & RL_PSTATE_MASK);
     265           0 :                         command &= 0xFFFFFFFC;
     266           0 :                         pci_conf_write(pc, csc->sc_tag,
     267           0 :                             pmreg + 4, command);
     268             : 
     269             :                         /* Restore PCI config data. */
     270           0 :                         pci_conf_write(pc, csc->sc_tag,
     271             :                             RL_PCI_LOIO, iobase);
     272           0 :                         pci_conf_write(pc, csc->sc_tag,
     273             :                             RL_PCI_LOMEM, membase);
     274           0 :                         pci_conf_write(pc, csc->sc_tag,
     275             :                             PCI_PRODUCT_DELTA_8139, irq);
     276           0 :                 }
     277             :         }
     278             : 
     279             :         /* Make sure the right access type is on the CardBus bridge. */
     280           0 :         (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
     281           0 :         (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
     282             : 
     283             :         /* Program the BAR */
     284           0 :         pci_conf_write(pc, csc->sc_tag,
     285           0 :                 csc->sc_bar_reg, csc->sc_bar_val);
     286             : 
     287             :         /* Enable the appropriate bits in the CARDBUS CSR. */
     288           0 :         reg = pci_conf_read(pc, csc->sc_tag, 
     289             :             PCI_COMMAND_STATUS_REG);
     290           0 :         reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
     291           0 :         reg |= csc->sc_csr;
     292           0 :         pci_conf_write(pc, csc->sc_tag, 
     293             :             PCI_COMMAND_STATUS_REG, reg);
     294             : 
     295             :         /*
     296             :          * Make sure the latency timer is set to some reasonable
     297             :          * value.
     298             :          */
     299           0 :         reg = pci_conf_read(pc, csc->sc_tag, PCI_BHLC_REG);
     300           0 :         if (PCI_LATTIMER(reg) < 0x20) {
     301           0 :                 reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
     302           0 :                 reg |= (0x20 << PCI_LATTIMER_SHIFT);
     303           0 :                 pci_conf_write(pc, csc->sc_tag, PCI_BHLC_REG, reg);
     304           0 :         }
     305           0 : }
     306             : 

Generated by: LCOV version 1.13