Module Name: src Committed By: christos Date: Sun Apr 8 20:49:29 UTC 2012
Modified Files: src/sys/arch/i386/conf: GENERIC src/sys/dev/cardbus: files.cardbus Added Files: src/sys/dev/cardbus: if_bwi_cardbus.c Log Message: PR/46310: Ryo ONODERA: Add support for cardbus bwi(4) To generate a diff of this commit: cvs rdiff -u -r1.1069 -r1.1070 src/sys/arch/i386/conf/GENERIC cvs rdiff -u -r1.36 -r1.37 src/sys/dev/cardbus/files.cardbus cvs rdiff -u -r0 -r1.1 src/sys/dev/cardbus/if_bwi_cardbus.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/i386/conf/GENERIC diff -u src/sys/arch/i386/conf/GENERIC:1.1069 src/sys/arch/i386/conf/GENERIC:1.1070 --- src/sys/arch/i386/conf/GENERIC:1.1069 Sat Apr 7 01:40:41 2012 +++ src/sys/arch/i386/conf/GENERIC Sun Apr 8 16:49:29 2012 @@ -1,4 +1,4 @@ -# $NetBSD: GENERIC,v 1.1069 2012/04/07 05:40:41 christos Exp $ +# $NetBSD: GENERIC,v 1.1070 2012/04/08 20:49:29 christos Exp $ # # GENERIC machine description file # @@ -22,7 +22,7 @@ include "arch/i386/conf/std.i386" options INCLUDE_CONFIG_FILE # embed config file in kernel binary -#ident "GENERIC-$Revision: 1.1069 $" +#ident "GENERIC-$Revision: 1.1070 $" maxusers 64 # estimated number of users @@ -1061,6 +1061,7 @@ we1 at isa? port 0x300 iomem 0xcc000 irq # CardBus network cards ath* at cardbus? function ? # Atheros 5210/5211/5212 802.11 atw* at cardbus? function ? # ADMtek ADM8211 (802.11) +bwi* at cardbus? function ? # Broadcom BCM43xx wireless ex* at cardbus? function ? # 3Com 3c575TX fxp* at cardbus? function ? # Intel i8255x ral* at cardbus? function ? # Ralink Technology RT25x0 802.11a/b/g Index: src/sys/dev/cardbus/files.cardbus diff -u src/sys/dev/cardbus/files.cardbus:1.36 src/sys/dev/cardbus/files.cardbus:1.37 --- src/sys/dev/cardbus/files.cardbus:1.36 Fri Mar 26 23:04:51 2010 +++ src/sys/dev/cardbus/files.cardbus Sun Apr 8 16:49:29 2012 @@ -1,4 +1,4 @@ -# $NetBSD: files.cardbus,v 1.36 2010/03/27 03:04:51 nonaka Exp $ +# $NetBSD: files.cardbus,v 1.37 2012/04/08 20:49:29 christos Exp $ # # files.cardbus # @@ -59,6 +59,12 @@ attach tlp at cardbus with tlp_cardbus file dev/cardbus/if_tlp_cardbus.c tlp_cardbus # +# Broadcom BCM43xx wireless +# +attach bwi at cardbus with bwi_cardbus +file dev/cardbus/if_bwi_cardbus.c bwi_cardbus + +# # OHCI USB controller # attach ohci at cardbus with ohci_cardbus Added files: Index: src/sys/dev/cardbus/if_bwi_cardbus.c diff -u /dev/null src/sys/dev/cardbus/if_bwi_cardbus.c:1.1 --- /dev/null Sun Apr 8 16:49:29 2012 +++ src/sys/dev/cardbus/if_bwi_cardbus.c Sun Apr 8 16:49:29 2012 @@ -0,0 +1,287 @@ +/* $NetBSD: if_bwi_cardbus.c,v 1.1 2012/04/08 20:49:29 christos Exp $ */ +/* $OpenBSD: if_bwi_cardbus.c,v 1.13 2010/08/06 05:26:24 mglocker Exp $ */ + +/* + * Copyright (c) 2007 Marcus Glocker <mgloc...@openbsd.org> + * Copyright (c) 2006 Claudio Jeker <clau...@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Cardbus front-end for the Broadcom AirForce + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0,"$NetBSD: if_bwi_cardbus.c,v 1.1 2012/04/08 20:49:29 christos Exp $"); + +#include "opt_inet.h" + +#include <sys/param.h> +#include <sys/callout.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/sockio.h> +#include <sys/systm.h> +#include <sys/errno.h> + +#include <machine/endian.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_ether.h> +#include <net/if_media.h> + +#include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_amrr.h> +#include <net80211/ieee80211_radiotap.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include <dev/cardbus/cardbusvar.h> + +#include <dev/ic/bwireg.h> +#include <dev/ic/bwivar.h> +#include <dev/pci/pcidevs.h> + +struct bwi_cardbus_softc { + struct bwi_softc csc_bwi; + + /* cardbus specific goo */ + cardbus_devfunc_t csc_ct; + pcitag_t csc_tag; + void *csc_ih; + + bus_size_t csc_mapsize; + pcireg_t csc_bar_val; + int csc_intrline; + pci_chipset_tag_t csc_pc; +}; + +int bwi_cardbus_match(device_t, cfdata_t, void*); +void bwi_cardbus_attach(device_t, device_t, void *); +int bwi_cardbus_detach(device_t, int); +void bwi_cardbus_setup(struct bwi_cardbus_softc *); +int bwi_cardbus_enable(struct bwi_softc *); +void bwi_cardbus_disable(struct bwi_softc *); +void bwi_cardbus_conf_write(void *, uint32_t, uint32_t); +uint32_t bwi_cardbus_conf_read(void *, uint32_t); + +CFATTACH_DECL_NEW(bwi_cardbus, sizeof (struct bwi_cardbus_softc), + bwi_cardbus_match, bwi_cardbus_attach, bwi_cardbus_detach, NULL); + +int +bwi_cardbus_match(device_t parent, cfdata_t match, void *aux) +{ + struct cardbus_attach_args *ca = aux; + + if (PCI_VENDOR(ca->ca_id) == PCI_VENDOR_BROADCOM) { + switch (PCI_PRODUCT(ca->ca_id)) { + case PCI_PRODUCT_BROADCOM_BCM4303: + case PCI_PRODUCT_BROADCOM_BCM4306: + case PCI_PRODUCT_BROADCOM_BCM4306_2: + case PCI_PRODUCT_BROADCOM_BCM4307: + case PCI_PRODUCT_BROADCOM_BCM4309: + case PCI_PRODUCT_BROADCOM_BCM4311: + case PCI_PRODUCT_BROADCOM_BCM4312: + case PCI_PRODUCT_BROADCOM_BCM4318: + case PCI_PRODUCT_BROADCOM_BCM4319: + case PCI_PRODUCT_BROADCOM_BCM4322: + case PCI_PRODUCT_BROADCOM_BCM43XG: + case PCI_PRODUCT_BROADCOM_BCM4328: + return (1); + default: + return (0); + } + } + + return (0); +} + +void +bwi_cardbus_attach(device_t parent, device_t self, void *aux) +{ + struct bwi_cardbus_softc *csc = device_private(self); + struct cardbus_attach_args *ca = aux; + struct bwi_softc *sc = &csc->csc_bwi; + cardbus_devfunc_t ct = ca->ca_ct; + pcireg_t reg; + bus_addr_t base; + int error; + + sc->sc_dev = self; + sc->sc_dmat = ca->ca_dmat; + csc->csc_ct = ct; + csc->csc_tag = ca->ca_tag; + + /* power management hooks */ + sc->sc_enable = bwi_cardbus_enable; + sc->sc_disable = bwi_cardbus_disable; + //sc->sc_power = bwi_cardbus_power; + + /* map control/status registers */ + error = Cardbus_mapreg_map(ct, BWI_PCIR_BAR, + PCI_MAPREG_TYPE_MEM, 0, &sc->sc_mem_bt, + &sc->sc_mem_bh, &base, &csc->csc_mapsize); + if (error != 0) { + printf(": can't map mem space\n"); + return; + } + csc->csc_bar_val = base | PCI_MAPREG_TYPE_MEM; + + /* set up the PCI configuration registers */ + bwi_cardbus_setup(csc); + + printf(": irq %d", csc->csc_intrline); + + /* we need to access Cardbus config space from the driver */ + sc->sc_conf_read = bwi_cardbus_conf_read; + sc->sc_conf_write = bwi_cardbus_conf_write; + + reg = (sc->sc_conf_read)(sc, PCI_SUBSYS_ID_REG); + + sc->sc_pci_revid = PCI_REVISION(ca->ca_class); + sc->sc_pci_did = PCI_PRODUCT(ca->ca_id); + sc->sc_pci_subvid = PCI_VENDOR(reg); + sc->sc_pci_subdid = PCI_PRODUCT(reg); + + error = bwi_attach(sc); + if (error != 0) + bwi_cardbus_detach(sc->sc_dev, 0); + + Cardbus_function_disable(ct); +} + +int +bwi_cardbus_detach(device_t self, int flags) +{ + struct bwi_cardbus_softc *csc = device_private(self); + struct bwi_softc *sc = &csc->csc_bwi; + cardbus_devfunc_t ct = csc->csc_ct; + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + +#ifdef DIAGNOSTIC + if (ct == NULL) + panic("%s: data structure lacks", device_xname(self)); + +#endif + + bwi_detach(sc); + + /* unhook the interrupt handler */ + if (csc->csc_ih != NULL) { + cardbus_intr_disestablish(cc, cf, csc->csc_ih); + csc->csc_ih = NULL; + } + + /* release bus space and close window */ + Cardbus_mapreg_unmap(ct, BWI_PCIR_BAR, sc->sc_mem_bt, + sc->sc_mem_bh, csc->csc_mapsize); + + return (0); +} + +void +bwi_cardbus_setup(struct bwi_cardbus_softc *csc) +{ + cardbus_devfunc_t ct = csc->csc_ct; + cardbus_chipset_tag_t cc = ct->ct_cc; + pci_chipset_tag_t pc = csc->csc_pc; + cardbus_function_tag_t cf = ct->ct_cf; + pcireg_t reg; + + /* program the BAR */ + cardbus_conf_write(cc, cf, csc->csc_tag, BWI_PCIR_BAR, + csc->csc_bar_val); + + /* make sure the right access type is on the cardbus bridge */ + (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE); + (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); + + /* enable the appropriate bits in the PCI CSR */ + reg = pci_conf_read(pc, csc->csc_tag, + PCI_COMMAND_STATUS_REG); + reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE; + Cardbus_conf_write(ct, csc->csc_tag, PCI_COMMAND_STATUS_REG, + reg); +} + +int +bwi_cardbus_enable(struct bwi_softc *sc) +{ + struct bwi_cardbus_softc *csc = (struct bwi_cardbus_softc *)sc; + cardbus_devfunc_t ct = csc->csc_ct; + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + + /* power on the socket */ + Cardbus_function_enable(ct); + + /* setup the PCI configuration registers */ + bwi_cardbus_setup(csc); + + /* map and establish the interrupt handler */ + csc->csc_ih = cardbus_intr_establish(cc, cf, IPL_NET, + bwi_intr, sc); + if (csc->csc_ih == NULL) { + aprint_error_dev(sc->sc_dev, + "unable to establish interrupt\n"); + Cardbus_function_disable(ct); + return false; + } + + return (0); +} + +void +bwi_cardbus_disable(struct bwi_softc *sc) +{ + struct bwi_cardbus_softc *csc = (struct bwi_cardbus_softc *)sc; + cardbus_devfunc_t ct = csc->csc_ct; + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + + /* unhook the interrupt handler */ + cardbus_intr_disestablish(cc, cf, csc->csc_ih); + csc->csc_ih = NULL; + + /* power down the socket */ + Cardbus_function_disable(ct); +} + +void +bwi_cardbus_conf_write(void *self, uint32_t reg, uint32_t val) +{ + struct bwi_cardbus_softc *csc = (struct bwi_cardbus_softc *)self; + cardbus_devfunc_t ct = csc->csc_ct; + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + + cardbus_conf_write(cc, cf, csc->csc_tag, reg, val); +} + +uint32_t +bwi_cardbus_conf_read(void *self, uint32_t reg) +{ + struct bwi_cardbus_softc *csc = (struct bwi_cardbus_softc *)self; + cardbus_devfunc_t ct = csc->csc_ct; + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + + return (cardbus_conf_read(cc, cf, csc->csc_tag, reg)); +}