root/dev/pci/if_rtw_pci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtw_pci_match
  2. rtw_pci_enable
  3. rtw_pci_disable
  4. rtw_pci_attach

    1 /*      $OpenBSD: if_rtw_pci.c,v 1.7 2005/09/08 12:44:55 jsg Exp $      */
    2 /*      $NetBSD: if_rtw_pci.c,v 1.1 2004/09/26 02:33:36 dyoung Exp $    */
    3 
    4 /*-
    5  * Copyright (c) 1998, 1999, 2000, 2002 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
   10  * NASA Ames Research Center; Charles M. Hannum; and David Young.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the NetBSD
   23  *      Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * PCI bus front-end for the Realtek RTL8180L 802.11 MAC/BBP chip.
   43  *
   44  * Derived from the ADMtek ADM8211 PCI bus front-end.
   45  *
   46  * Derived from the ``Tulip'' PCI bus front-end.
   47  */
   48 
   49 #include <sys/cdefs.h>
   50 #include <sys/param.h>
   51 #include <sys/systm.h> 
   52 #include <sys/mbuf.h>   
   53 #include <sys/malloc.h>
   54 #include <sys/kernel.h>
   55 #include <sys/socket.h>
   56 #include <sys/ioctl.h>
   57 #include <sys/errno.h>
   58 #include <sys/device.h>
   59 
   60 #include <machine/endian.h>
   61  
   62 #include <net/if.h>
   63 #include <net/if_dl.h>
   64 #include <net/if_media.h>
   65 #ifdef INET
   66 #include <netinet/in.h>
   67 #include <netinet/if_ether.h>
   68 #endif
   69 
   70 #include <net80211/ieee80211_radiotap.h>
   71 #include <net80211/ieee80211_var.h>
   72 
   73 #include <machine/bus.h>
   74 #include <machine/intr.h>
   75 
   76 #include <dev/ic/rtwreg.h>
   77 #include <dev/ic/sa2400reg.h>
   78 #include <dev/ic/rtwvar.h>
   79 
   80 #include <dev/pci/pcivar.h>
   81 #include <dev/pci/pcireg.h>
   82 #include <dev/pci/pcidevs.h>
   83 
   84 int rtw_pci_enable(struct rtw_softc *);
   85 void rtw_pci_disable(struct rtw_softc *);
   86 
   87 /*
   88  * PCI configuration space registers used by the RTL8180L.
   89  */
   90 #define RTW_PCI_IOBA            0x10    /* i/o mapped base */
   91 #define RTW_PCI_MMBA            0x14    /* memory mapped base */
   92 
   93 struct rtw_pci_softc {
   94         struct rtw_softc        psc_rtw;        /* real RTL8180L softc */
   95 
   96         pci_intr_handle_t       psc_ih;         /* interrupt handle */
   97         void                    *psc_intrcookie;
   98 
   99         pci_chipset_tag_t       psc_pc;         /* our PCI chipset */
  100         pcitag_t                psc_pcitag;     /* our PCI tag */
  101 };
  102 
  103 int     rtw_pci_match(struct device *, void *, void *);
  104 void    rtw_pci_attach(struct device *, struct device *, void *);
  105 
  106 struct cfattach rtw_pci_ca = {
  107         sizeof (struct rtw_pci_softc), rtw_pci_match, rtw_pci_attach
  108 };
  109 
  110 const struct pci_matchid rtw_pci_products[] = {
  111         { PCI_VENDOR_REALTEK,   PCI_PRODUCT_REALTEK_RT8185 },
  112         { PCI_VENDOR_REALTEK,   PCI_PRODUCT_REALTEK_RT8180 },
  113         { PCI_VENDOR_BELKIN2,   PCI_PRODUCT_BELKIN2_F5D6001 },
  114         { PCI_VENDOR_DLINK,     PCI_PRODUCT_DLINK_DWL610 },
  115 };
  116 
  117 int
  118 rtw_pci_match(struct device *parent, void *match, void *aux)
  119 {
  120         return (pci_matchbyid((struct pci_attach_args *)aux, rtw_pci_products,
  121             sizeof(rtw_pci_products)/sizeof(rtw_pci_products[0])));
  122 }
  123 
  124 int
  125 rtw_pci_enable(struct rtw_softc *sc)
  126 {
  127         struct rtw_pci_softc *psc = (void *)sc;
  128 
  129         /* Establish the interrupt. */
  130         psc->psc_intrcookie = pci_intr_establish(psc->psc_pc, psc->psc_ih,
  131             IPL_NET, rtw_intr, sc, sc->sc_dev.dv_xname);
  132         if (psc->psc_intrcookie == NULL) {
  133                 printf("%s: unable to establish interrupt\n",
  134                     sc->sc_dev.dv_xname);
  135                 return (1);
  136         }
  137 
  138         return (0);
  139 }
  140 
  141 void
  142 rtw_pci_disable(struct rtw_softc *sc)
  143 {
  144         struct rtw_pci_softc *psc = (void *)sc;
  145 
  146         /* Unhook the interrupt handler. */
  147         pci_intr_disestablish(psc->psc_pc, psc->psc_intrcookie);
  148         psc->psc_intrcookie = NULL;
  149 }
  150 
  151 void
  152 rtw_pci_attach(struct device *parent, struct device *self, void *aux)
  153 {
  154         struct rtw_pci_softc *psc = (void *) self;
  155         struct rtw_softc *sc = &psc->psc_rtw;
  156         struct rtw_regs *regs = &sc->sc_regs;
  157         struct pci_attach_args *pa = aux;
  158         pci_chipset_tag_t pc = pa->pa_pc;
  159         const char *intrstr = NULL;
  160         bus_space_tag_t iot, memt;
  161         bus_space_handle_t ioh, memh;
  162         int ioh_valid, memh_valid;
  163         pcireg_t reg;
  164         int pmreg;
  165 
  166         psc->psc_pc = pa->pa_pc;
  167         psc->psc_pcitag = pa->pa_tag;
  168 
  169         /*
  170          * No power management hooks.
  171          * XXX Maybe we should add some!
  172          */
  173         sc->sc_flags |= RTW_F_ENABLED;
  174 
  175         /*
  176          * Get revision info, and set some chip-specific variables.
  177          */
  178         sc->sc_rev = PCI_REVISION(pa->pa_class);
  179 
  180         /*
  181          * Check to see if the device is in power-save mode, and
  182          * being it out if necessary.
  183          *
  184          * XXX This code comes almost verbatim from if_tlp_pci.c. I do
  185          * not understand it. Tulip clears the "sleep mode" bit in the
  186          * CFDA register, first.  There is an equivalent (?) register at the
  187          * same place in the ADM8211, but the docs do not assign its bits
  188          * any meanings. -dcy
  189          */
  190         if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) {
  191                 reg = pci_conf_read(pc, pa->pa_tag, pmreg + PCI_PMCSR);
  192                 switch (reg & PCI_PMCSR_STATE_MASK) {
  193                 case PCI_PMCSR_STATE_D1:
  194                 case PCI_PMCSR_STATE_D2:
  195                         printf(": waking up from power state D%d\n",
  196                             reg & PCI_PMCSR_STATE_MASK);
  197                         pci_conf_write(pc, pa->pa_tag, pmreg + PCI_PMCSR,
  198                             (reg & ~PCI_PMCSR_STATE_MASK) |
  199                             PCI_PMCSR_STATE_D0);
  200                         break;
  201                 case PCI_PMCSR_STATE_D3:
  202                         /*
  203                          * The card has lost all configuration data in
  204                          * this state, so punt.
  205                          */
  206                         printf(": unable to wake up from power state D3, "
  207                                "reboot required.\n");
  208                         pci_conf_write(pc, pa->pa_tag, pmreg + PCI_PMCSR,
  209                             (reg & ~PCI_PMCSR_STATE_MASK) |
  210                             PCI_PMCSR_STATE_D0);
  211                         return;
  212                 }
  213         }
  214 
  215         /*
  216          * Map the device.
  217          */
  218         ioh_valid = (pci_mapreg_map(pa, RTW_PCI_IOBA,
  219             PCI_MAPREG_TYPE_IO, 0,
  220             &iot, &ioh, NULL, NULL, 0) == 0);
  221         memh_valid = (pci_mapreg_map(pa, RTW_PCI_MMBA,
  222             PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
  223             &memt, &memh, NULL, NULL, 0) == 0);
  224 
  225         if (memh_valid) {
  226                 regs->r_bt = memt;
  227                 regs->r_bh = memh;
  228         } else if (ioh_valid) {
  229                 regs->r_bt = iot;
  230                 regs->r_bh = ioh;
  231         } else {
  232                 printf(": unable to map device registers\n");
  233                 return;
  234         }
  235 
  236         sc->sc_dmat = pa->pa_dmat;
  237 
  238         /*
  239          * Map and establish our interrupt.
  240          */
  241         if (pci_intr_map(pa, &psc->psc_ih)) {
  242                 printf(": unable to map interrupt\n");
  243                 return;
  244         }
  245         intrstr = pci_intr_string(pc, psc->psc_ih); 
  246         psc->psc_intrcookie = pci_intr_establish(pc, psc->psc_ih, IPL_NET,
  247             rtw_intr, sc, sc->sc_dev.dv_xname);
  248         if (psc->psc_intrcookie == NULL) {
  249                 printf(": unable to establish interrupt");
  250                 if (intrstr != NULL)
  251                         printf(" at %s", intrstr);
  252                 printf("\n");
  253                 return;
  254         }
  255 
  256         printf(": %s\n", intrstr);
  257 
  258         sc->sc_enable = rtw_pci_enable;
  259         sc->sc_disable = rtw_pci_disable;
  260 
  261         /*
  262          * Finish off the attach.
  263          */
  264         rtw_attach(sc);
  265 }

/* [<][>][^][v][top][bottom][index][help] */