root/dev/cardbus/if_acx_cardbus.c

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

DEFINITIONS

This source file includes following definitions.
  1. acx_cardbus_match
  2. acx_cardbus_attach
  3. acx_cardbus_detach
  4. acx_cardbus_enable
  5. acx_cardbus_disable
  6. acx_cardbus_power
  7. acx_cardbus_setup

    1 /*      $OpenBSD: if_acx_cardbus.c,v 1.11 2006/11/10 20:20:04 damien Exp $  */
    2 
    3 /*
    4  * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
    5  * Copyright (c) 2005, 2006
    6  *      Damien Bergamini <damien.bergamini@free.fr>
    7  *
    8  * Permission to use, copy, modify, and distribute this software for any
    9  * purpose with or without fee is hereby granted, provided that the above
   10  * copyright notice and this permission notice appear in all copies.
   11  *
   12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   19  */
   20 
   21 /*
   22  * CardBus front-end for the Texas Instruments ACX driver
   23  */
   24 
   25 #include "bpfilter.h"
   26 
   27 #include <sys/param.h>
   28 #include <sys/sockio.h>
   29 #include <sys/mbuf.h>
   30 #include <sys/kernel.h>
   31 #include <sys/socket.h>
   32 #include <sys/systm.h>
   33 #include <sys/malloc.h>
   34 #include <sys/timeout.h>
   35 #include <sys/device.h>
   36 
   37 #include <machine/bus.h>
   38 #include <machine/intr.h>
   39 
   40 #include <net/if.h>
   41 #include <net/if_dl.h>
   42 #include <net/if_media.h>
   43 
   44 #ifdef INET
   45 #include <netinet/in.h>
   46 #include <netinet/if_ether.h>
   47 #endif
   48 
   49 #include <net80211/ieee80211_var.h>
   50 #include <net80211/ieee80211_amrr.h>
   51 #include <net80211/ieee80211_radiotap.h>
   52 
   53 #include <dev/ic/acxvar.h>
   54 #include <dev/ic/acxreg.h>
   55 
   56 #include <dev/pci/pcireg.h>
   57 #include <dev/pci/pcivar.h>
   58 #include <dev/pci/pcidevs.h>
   59 
   60 #include <dev/cardbus/cardbusvar.h>
   61 
   62 struct acx_cardbus_softc {
   63         struct acx_softc        sc_acx;
   64 
   65         /* cardbus specific goo */
   66         cardbus_devfunc_t       sc_ct;
   67         cardbustag_t            sc_tag;
   68         void                    *sc_ih;
   69         bus_size_t              sc_mapsize1;
   70         bus_size_t              sc_mapsize2;
   71         pcireg_t                sc_iobar_val; /* acx100 only */
   72         pcireg_t                sc_bar1_val;
   73         pcireg_t                sc_bar2_val;
   74         int                     sc_intrline;
   75 
   76         /* hack for ACX100A */
   77         bus_space_tag_t         sc_io_bt;
   78         bus_space_handle_t      sc_io_bh;
   79         bus_size_t              sc_iomapsize;
   80 };
   81 
   82 int     acx_cardbus_match(struct device *, void *, void *);
   83 void    acx_cardbus_attach(struct device *, struct device *, void *);
   84 int     acx_cardbus_detach(struct device *, int);
   85 
   86 struct cfattach acx_cardbus_ca = {
   87         sizeof (struct acx_cardbus_softc), acx_cardbus_match,
   88         acx_cardbus_attach, acx_cardbus_detach
   89 };
   90 
   91 static const struct cardbus_matchid acx_cardbus_devices[] = {
   92         { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX100A },
   93         { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX100B },
   94         { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX111 },
   95 };
   96 
   97 int     acx_cardbus_enable(struct acx_softc *);
   98 void    acx_cardbus_disable(struct acx_softc *);
   99 void    acx_cardbus_power(struct acx_softc *, int);
  100 void    acx_cardbus_setup(struct acx_cardbus_softc *);
  101 
  102 int
  103 acx_cardbus_match(struct device *parent, void *match, void *aux)
  104 {
  105         return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
  106             acx_cardbus_devices,
  107             sizeof (acx_cardbus_devices) / sizeof (acx_cardbus_devices[0])));
  108 }
  109 
  110 void
  111 acx_cardbus_attach(struct device *parent, struct device *self, void *aux)
  112 {
  113         struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)self;
  114         struct acx_softc *sc = &csc->sc_acx;
  115         struct cardbus_attach_args *ca = aux;
  116         cardbus_devfunc_t ct = ca->ca_ct;
  117         bus_addr_t base;
  118         int error, b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG;
  119 
  120         sc->sc_dmat = ca->ca_dmat;
  121         csc->sc_ct = ct;
  122         csc->sc_tag = ca->ca_tag;
  123         csc->sc_intrline = ca->ca_intrline;
  124 
  125         /* power management hooks */
  126         sc->sc_enable = acx_cardbus_enable;
  127         sc->sc_disable = acx_cardbus_disable;
  128         sc->sc_power = acx_cardbus_power;
  129 
  130         if (CARDBUS_PRODUCT(ca->ca_id) == PCI_PRODUCT_TI_ACX100A) {
  131                 /* first map I/O space as seen in the dragonfly code */
  132                 error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
  133                     CARDBUS_MAPREG_TYPE_IO, 0, &csc->sc_io_bt, &csc->sc_io_bh,
  134                     &base, &csc->sc_iomapsize);
  135                 if (error != 0) {
  136                         printf(": could not map i/o space\n");
  137                         return;
  138                 }
  139                 csc->sc_iobar_val = base | CARDBUS_MAPREG_TYPE_IO;
  140                 b1 = CARDBUS_BASE1_REG;
  141                 b2 = CARDBUS_BASE2_REG;
  142         }
  143 
  144         /* map control/status registers */
  145         error = Cardbus_mapreg_map(ct, b1, CARDBUS_MAPREG_TYPE_MEM, 0,
  146             &sc->sc_mem1_bt, &sc->sc_mem1_bh, &base, &csc->sc_mapsize1);
  147         if (error != 0) {
  148                 printf(": could not map memory1 space\n");
  149                 return;
  150         }
  151 
  152         csc->sc_bar1_val = base | CARDBUS_MAPREG_TYPE_MEM;
  153 
  154         /* map the other memory region */
  155         error = Cardbus_mapreg_map(ct, b2, CARDBUS_MAPREG_TYPE_MEM, 0,
  156             &sc->sc_mem2_bt, &sc->sc_mem2_bh, &base, &csc->sc_mapsize2);
  157         if (error != 0) {
  158                 printf(": could not map memory2 space\n");
  159                 return;
  160         }
  161 
  162         csc->sc_bar2_val = base | CARDBUS_MAPREG_TYPE_MEM;
  163 
  164         /* set up the PCI configuration registers */
  165         acx_cardbus_setup(csc);
  166 
  167         printf(": irq %d\n", csc->sc_intrline);
  168 
  169         if (CARDBUS_PRODUCT(ca->ca_id) == PCI_PRODUCT_TI_ACX111)
  170                 acx111_set_param(sc);
  171         else
  172                 acx100_set_param(sc);
  173 
  174         acx_attach(sc);
  175 
  176         Cardbus_function_disable(ct);
  177 }
  178 
  179 int
  180 acx_cardbus_detach(struct device *self, int flags)
  181 {
  182         struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)self;
  183         struct acx_softc *sc = &csc->sc_acx;
  184         cardbus_devfunc_t ct = csc->sc_ct;
  185         cardbus_chipset_tag_t cc = ct->ct_cc;
  186         cardbus_function_tag_t cf = ct->ct_cf;
  187         int error, b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG;
  188 
  189         error = acx_detach(sc);
  190         if (error != 0)
  191                 return (error);
  192 
  193         /* unhook the interrupt handler */
  194         if (csc->sc_ih != NULL) {
  195                 cardbus_intr_disestablish(cc, cf, csc->sc_ih);
  196                 csc->sc_ih = NULL;
  197         }
  198 
  199         /* release bus space and close window */
  200         if (csc->sc_iomapsize) {
  201                 b1 = CARDBUS_BASE1_REG;
  202                 b2 = CARDBUS_BASE2_REG;
  203         }
  204         Cardbus_mapreg_unmap(ct, b1, sc->sc_mem1_bt,
  205             sc->sc_mem1_bh, csc->sc_mapsize1);
  206         Cardbus_mapreg_unmap(ct, b2, sc->sc_mem2_bt,
  207             sc->sc_mem2_bh, csc->sc_mapsize2);
  208         if (csc->sc_iomapsize)
  209                 Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, csc->sc_io_bt,
  210                     csc->sc_io_bh, csc->sc_iomapsize);
  211 
  212         return (0);
  213 }
  214 
  215 int
  216 acx_cardbus_enable(struct acx_softc *sc)
  217 {
  218         struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)sc;
  219         cardbus_devfunc_t ct = csc->sc_ct;
  220         cardbus_chipset_tag_t cc = ct->ct_cc;
  221         cardbus_function_tag_t cf = ct->ct_cf;
  222 
  223         /* power on the socket */
  224         Cardbus_function_enable(ct);
  225 
  226         /* setup the PCI configuration registers */
  227         acx_cardbus_setup(csc);
  228 
  229         /* map and establish the interrupt handler */
  230         csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
  231             acx_intr, sc, sc->sc_dev.dv_xname);
  232         if (csc->sc_ih == NULL) {
  233                 printf("%s: could not establish interrupt at %d\n",
  234                     sc->sc_dev.dv_xname, csc->sc_intrline);
  235                 Cardbus_function_disable(ct);
  236                 return (1);
  237         }
  238 
  239         return (0);
  240 }
  241 
  242 void
  243 acx_cardbus_disable(struct acx_softc *sc)
  244 {
  245         struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)sc;
  246         cardbus_devfunc_t ct = csc->sc_ct;
  247         cardbus_chipset_tag_t cc = ct->ct_cc;
  248         cardbus_function_tag_t cf = ct->ct_cf;
  249 
  250         /* unhook the interrupt handler */
  251         cardbus_intr_disestablish(cc, cf, csc->sc_ih);
  252         csc->sc_ih = NULL;
  253 
  254         /* power down the socket */
  255         Cardbus_function_disable(ct);
  256 }
  257 
  258 void
  259 acx_cardbus_power(struct acx_softc *sc, int why)
  260 {
  261         struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)sc;
  262 
  263         if (why == PWR_RESUME) {
  264                 /* kick the PCI configuration registers */
  265                 acx_cardbus_setup(csc);
  266         }
  267 }
  268 
  269 void
  270 acx_cardbus_setup(struct acx_cardbus_softc *csc)
  271 {
  272         cardbus_devfunc_t ct = csc->sc_ct;
  273         cardbus_chipset_tag_t cc = ct->ct_cc;
  274         cardbus_function_tag_t cf = ct->ct_cf;
  275         pcireg_t reg;
  276         int b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG;
  277 
  278         if (csc->sc_iobar_val) {
  279                 cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BASE0_REG,
  280                     csc->sc_bar1_val);
  281                 b1 = CARDBUS_BASE1_REG;
  282                 b2 = CARDBUS_BASE2_REG;
  283                 /* (*cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE); */
  284         }
  285 
  286         /* program the BAR */
  287         cardbus_conf_write(cc, cf, csc->sc_tag, b1, csc->sc_bar1_val);
  288         cardbus_conf_write(cc, cf, csc->sc_tag, b2, csc->sc_bar2_val);
  289 
  290         /* make sure the right access type is on the cardbus bridge */
  291         (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
  292         (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
  293 
  294         /* enable the appropriate bits in the PCI CSR */
  295         reg = cardbus_conf_read(cc, cf, csc->sc_tag,
  296             CARDBUS_COMMAND_STATUS_REG);
  297         reg |= CARDBUS_COMMAND_MASTER_ENABLE | CARDBUS_COMMAND_MEM_ENABLE;
  298 #if 0
  299         if (csc->sc_iobar_val)
  300                 reg |= CARDBUS_COMMAND_IO_ENABLE;
  301 #endif
  302         cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_COMMAND_STATUS_REG,
  303             reg);
  304 }

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