root/dev/cardbus/if_ral_cardbus.c

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

DEFINITIONS

This source file includes following definitions.
  1. ral_cardbus_match
  2. ral_cardbus_attach
  3. ral_cardbus_detach
  4. ral_cardbus_enable
  5. ral_cardbus_disable
  6. ral_cardbus_power
  7. ral_cardbus_setup

    1 /*      $OpenBSD: if_ral_cardbus.c,v 1.9 2006/10/22 12:14:44 damien Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 2005, 2006
    5  *      Damien Bergamini <damien.bergamini@free.fr>
    6  *
    7  * Permission to use, copy, modify, and distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  */
   19 
   20 /*
   21  * CardBus front-end for the Ralink RT2560/RT2561/RT2561S/RT2661 driver.
   22  */
   23 
   24 #include "bpfilter.h"
   25 
   26 #include <sys/param.h>
   27 #include <sys/sockio.h>
   28 #include <sys/mbuf.h>
   29 #include <sys/kernel.h>
   30 #include <sys/socket.h>
   31 #include <sys/systm.h>
   32 #include <sys/malloc.h>
   33 #include <sys/timeout.h>
   34 #include <sys/device.h>
   35 
   36 #include <machine/bus.h>
   37 #include <machine/intr.h>
   38 
   39 #include <net/if.h>
   40 #include <net/if_dl.h>
   41 #include <net/if_media.h>
   42 
   43 #include <netinet/in.h>
   44 #include <netinet/if_ether.h>
   45 
   46 #include <net80211/ieee80211_var.h>
   47 #include <net80211/ieee80211_amrr.h>
   48 #include <net80211/ieee80211_radiotap.h>
   49 
   50 #include <dev/ic/rt2560var.h>
   51 #include <dev/ic/rt2661var.h>
   52 
   53 #include <dev/pci/pcireg.h>
   54 #include <dev/pci/pcivar.h>
   55 #include <dev/pci/pcidevs.h>
   56 
   57 #include <dev/cardbus/cardbusvar.h>
   58 
   59 static struct ral_opns {
   60         int     (*attach)(void *, int);
   61         int     (*detach)(void *);
   62         int     (*intr)(void *);
   63 
   64 }  ral_rt2560_opns = {
   65         rt2560_attach,
   66         rt2560_detach,
   67         rt2560_intr
   68 
   69 }, ral_rt2661_opns = {
   70         rt2661_attach,
   71         rt2661_detach,
   72         rt2661_intr
   73 };
   74 
   75 struct ral_cardbus_softc {
   76         union {
   77                 struct rt2560_softc     sc_rt2560;
   78                 struct rt2661_softc     sc_rt2661;
   79         } u;
   80 #define sc_sc   u.sc_rt2560
   81 
   82         /* cardbus specific goo */
   83         struct ral_opns         *sc_opns;
   84         cardbus_devfunc_t       sc_ct;
   85         cardbustag_t            sc_tag;
   86         void                    *sc_ih;
   87         bus_size_t              sc_mapsize;
   88         pcireg_t                sc_bar_val;
   89         int                     sc_intrline;
   90 };
   91 
   92 int     ral_cardbus_match(struct device *, void *, void *);
   93 void    ral_cardbus_attach(struct device *, struct device *, void *);
   94 int     ral_cardbus_detach(struct device *, int);
   95 
   96 struct cfattach ral_cardbus_ca = {
   97         sizeof (struct ral_cardbus_softc), ral_cardbus_match,
   98         ral_cardbus_attach, ral_cardbus_detach
   99 };
  100 
  101 static const struct cardbus_matchid ral_cardbus_devices[] = {
  102         { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2560  },
  103         { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2561  },
  104         { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2561S },
  105         { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2661  }
  106 };
  107 
  108 int     ral_cardbus_enable(struct rt2560_softc *);
  109 void    ral_cardbus_disable(struct rt2560_softc *);
  110 void    ral_cardbus_power(struct rt2560_softc *, int);
  111 void    ral_cardbus_setup(struct ral_cardbus_softc *);
  112 
  113 int
  114 ral_cardbus_match(struct device *parent, void *match, void *aux)
  115 {
  116         return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
  117             ral_cardbus_devices,
  118             sizeof (ral_cardbus_devices) / sizeof (ral_cardbus_devices[0])));
  119 }
  120 
  121 void
  122 ral_cardbus_attach(struct device *parent, struct device *self, void *aux)
  123 {
  124         struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)self;
  125         struct rt2560_softc *sc = &csc->sc_sc;
  126         struct cardbus_attach_args *ca = aux;
  127         cardbus_devfunc_t ct = ca->ca_ct;
  128         bus_addr_t base;
  129         int error;
  130 
  131         csc->sc_opns =
  132             (CARDBUS_PRODUCT(ca->ca_id) == PCI_PRODUCT_RALINK_RT2560) ?
  133             &ral_rt2560_opns : &ral_rt2661_opns;
  134 
  135         sc->sc_dmat = ca->ca_dmat;
  136         csc->sc_ct = ct;
  137         csc->sc_tag = ca->ca_tag;
  138         csc->sc_intrline = ca->ca_intrline;
  139 
  140         /* power management hooks */
  141         sc->sc_enable = ral_cardbus_enable;
  142         sc->sc_disable = ral_cardbus_disable;
  143         sc->sc_power = ral_cardbus_power;
  144 
  145         /* map control/status registers */
  146         error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
  147             CARDBUS_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, &base,
  148             &csc->sc_mapsize);
  149         if (error != 0) {
  150                 printf(": could not map memory space\n");
  151                 return;
  152         }
  153 
  154         csc->sc_bar_val = base | CARDBUS_MAPREG_TYPE_MEM;
  155 
  156         /* set up the PCI configuration registers */
  157         ral_cardbus_setup(csc);
  158 
  159         printf(": irq %d", csc->sc_intrline);
  160 
  161         (*csc->sc_opns->attach)(sc, CARDBUS_PRODUCT(ca->ca_id));
  162 
  163         Cardbus_function_disable(ct);
  164 }
  165 
  166 int
  167 ral_cardbus_detach(struct device *self, int flags)
  168 {
  169         struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)self;
  170         struct rt2560_softc *sc = &csc->sc_sc;
  171         cardbus_devfunc_t ct = csc->sc_ct;
  172         cardbus_chipset_tag_t cc = ct->ct_cc;
  173         cardbus_function_tag_t cf = ct->ct_cf;
  174         int error;
  175 
  176         error = (*csc->sc_opns->detach)(sc);
  177         if (error != 0)
  178                 return error;
  179 
  180         /* unhook the interrupt handler */
  181         if (csc->sc_ih != NULL) {
  182                 cardbus_intr_disestablish(cc, cf, csc->sc_ih);
  183                 csc->sc_ih = NULL;
  184         }
  185 
  186         /* release bus space and close window */
  187         Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_st, sc->sc_sh,
  188             csc->sc_mapsize);
  189 
  190         return 0;
  191 }
  192 
  193 int
  194 ral_cardbus_enable(struct rt2560_softc *sc)
  195 {
  196         struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)sc;
  197         cardbus_devfunc_t ct = csc->sc_ct;
  198         cardbus_chipset_tag_t cc = ct->ct_cc;
  199         cardbus_function_tag_t cf = ct->ct_cf;
  200 
  201         /* power on the socket */
  202         Cardbus_function_enable(ct);
  203 
  204         /* setup the PCI configuration registers */
  205         ral_cardbus_setup(csc);
  206 
  207         /* map and establish the interrupt handler */
  208         csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
  209             csc->sc_opns->intr, sc, sc->sc_dev.dv_xname);
  210         if (csc->sc_ih == NULL) {
  211                 printf("%s: could not establish interrupt at %d\n",
  212                     sc->sc_dev.dv_xname, csc->sc_intrline);
  213                 Cardbus_function_disable(ct);
  214                 return 1;
  215         }
  216 
  217         return 0;
  218 }
  219 
  220 void
  221 ral_cardbus_disable(struct rt2560_softc *sc)
  222 {
  223         struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)sc;
  224         cardbus_devfunc_t ct = csc->sc_ct;
  225         cardbus_chipset_tag_t cc = ct->ct_cc;
  226         cardbus_function_tag_t cf = ct->ct_cf;
  227 
  228         /* unhook the interrupt handler */
  229         cardbus_intr_disestablish(cc, cf, csc->sc_ih);
  230         csc->sc_ih = NULL;
  231 
  232         /* power down the socket */
  233         Cardbus_function_disable(ct);
  234 }
  235 
  236 void
  237 ral_cardbus_power(struct rt2560_softc *sc, int why)
  238 {
  239         struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)sc;
  240 
  241         if (why == PWR_RESUME) {
  242                 /* kick the PCI configuration registers */
  243                 ral_cardbus_setup(csc);
  244         }
  245 }
  246 
  247 void
  248 ral_cardbus_setup(struct ral_cardbus_softc *csc)
  249 {
  250         cardbus_devfunc_t ct = csc->sc_ct;
  251         cardbus_chipset_tag_t cc = ct->ct_cc;
  252         cardbus_function_tag_t cf = ct->ct_cf;
  253         pcireg_t reg;
  254 
  255         /* program the BAR */
  256         cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BASE0_REG,
  257             csc->sc_bar_val);
  258 
  259         /* make sure the right access type is on the cardbus bridge */
  260         (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
  261         (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
  262 
  263         /* enable the appropriate bits in the PCI CSR */
  264         reg = cardbus_conf_read(cc, cf, csc->sc_tag,
  265             CARDBUS_COMMAND_STATUS_REG);
  266         reg |= CARDBUS_COMMAND_MASTER_ENABLE | CARDBUS_COMMAND_MEM_ENABLE;
  267         cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_COMMAND_STATUS_REG,
  268             reg);
  269 }

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