[BACK]Return to if_atw_cardbus.c CVS log [TXT][DIR] Up to [local] / sys / dev / cardbus

Annotation of sys/dev/cardbus/if_atw_cardbus.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_atw_cardbus.c,v 1.14 2006/10/12 16:35:52 grange Exp $      */
        !             2: /*     $NetBSD: if_atw_cardbus.c,v 1.9 2004/07/23 07:07:55 dyoung Exp $        */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1999, 2000, 2003 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.  This code was adapted for the ADMtek ADM8211
        !            11:  * by David Young.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer.
        !            18:  * 2. Redistributions in binary form must reproduce the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer in the
        !            20:  *    documentation and/or other materials provided with the distribution.
        !            21:  * 3. All advertising materials mentioning features or use of this software
        !            22:  *    must display the following acknowledgement:
        !            23:  *     This product includes software developed by the NetBSD
        !            24:  *     Foundation, Inc. and its contributors.
        !            25:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            26:  *    contributors may be used to endorse or promote products derived
        !            27:  *    from this software without specific prior written permission.
        !            28:  *
        !            29:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            30:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            31:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            32:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            33:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            34:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            35:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            36:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            37:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            38:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            39:  * POSSIBILITY OF SUCH DAMAGE.
        !            40:  */
        !            41:
        !            42: /*
        !            43:  * CardBus bus front-end for the ADMtek ADM8211 802.11 MAC/BBP driver.
        !            44:  */
        !            45:
        !            46: #include "bpfilter.h"
        !            47:
        !            48: #include <sys/param.h>
        !            49: #include <sys/systm.h>
        !            50: #include <sys/mbuf.h>
        !            51: #include <sys/malloc.h>
        !            52: #include <sys/kernel.h>
        !            53: #include <sys/socket.h>
        !            54: #include <sys/ioctl.h>
        !            55: #include <sys/errno.h>
        !            56: #include <sys/device.h>
        !            57:
        !            58: #include <machine/endian.h>
        !            59:
        !            60: #include <net/if.h>
        !            61: #include <net/if_dl.h>
        !            62: #include <net/if_media.h>
        !            63:
        !            64: #ifdef INET
        !            65: #include <netinet/in.h>
        !            66: #include <netinet/if_ether.h>
        !            67: #endif
        !            68:
        !            69: #include <net80211/ieee80211_radiotap.h>
        !            70: #include <net80211/ieee80211_var.h>
        !            71:
        !            72: #if NBPFILTER > 0
        !            73: #include <net/bpf.h>
        !            74: #endif
        !            75:
        !            76: #include <machine/bus.h>
        !            77: #include <machine/intr.h>
        !            78:
        !            79: #include <dev/ic/atwreg.h>
        !            80: #include <dev/ic/rf3000reg.h>
        !            81: #include <dev/ic/si4136reg.h>
        !            82: #include <dev/ic/atwvar.h>
        !            83:
        !            84: #include <dev/pci/pcivar.h>
        !            85: #include <dev/pci/pcireg.h>
        !            86: #include <dev/pci/pcidevs.h>
        !            87:
        !            88: #include <dev/cardbus/cardbusvar.h>
        !            89:
        !            90: /*
        !            91:  * PCI configuration space registers used by the ADM8211.
        !            92:  */
        !            93: #define        ATW_PCI_IOBA            0x10    /* i/o mapped base */
        !            94: #define        ATW_PCI_MMBA            0x14    /* memory mapped base */
        !            95:
        !            96: struct atw_cardbus_softc {
        !            97:        struct atw_softc sc_atw;        /* real ADM8211 softc */
        !            98:
        !            99:        /* CardBus-specific goo. */
        !           100:        void    *sc_ih;                 /* interrupt handle */
        !           101:        cardbus_devfunc_t sc_ct;        /* our CardBus devfuncs */
        !           102:        cardbustag_t sc_tag;            /* our CardBus tag */
        !           103:        int     sc_csr;                 /* CSR bits */
        !           104:        bus_size_t sc_mapsize;          /* the size of mapped bus space
        !           105:                                           region */
        !           106:
        !           107:        int     sc_cben;                /* CardBus enables */
        !           108:        int     sc_bar_reg;             /* which BAR to use */
        !           109:        pcireg_t sc_bar_val;            /* value of the BAR */
        !           110:
        !           111:        int     sc_intrline;            /* interrupt line */
        !           112: };
        !           113:
        !           114: int    atw_cardbus_match(struct device *, void *, void *);
        !           115: void   atw_cardbus_attach(struct device *, struct device *, void *);
        !           116: int    atw_cardbus_detach(struct device *, int);
        !           117:
        !           118: struct cfattach atw_cardbus_ca = {
        !           119:        sizeof(struct atw_cardbus_softc), atw_cardbus_match, atw_cardbus_attach,
        !           120:            atw_cardbus_detach
        !           121: };
        !           122:
        !           123: void   atw_cardbus_setup(struct atw_cardbus_softc *);
        !           124:
        !           125: int    atw_cardbus_enable(struct atw_softc *);
        !           126: void   atw_cardbus_disable(struct atw_softc *);
        !           127: void   atw_cardbus_power(struct atw_softc *, int);
        !           128:
        !           129: const struct cardbus_matchid atw_cardbus_devices[] = {
        !           130:        { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_ADM8211 },
        !           131:        { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRSHPW796 },
        !           132: };
        !           133:
        !           134: int
        !           135: atw_cardbus_match(struct device *parent, void *match, void *aux)
        !           136: {
        !           137:        return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
        !           138:            atw_cardbus_devices,
        !           139:            sizeof(atw_cardbus_devices)/sizeof(atw_cardbus_devices[0])));
        !           140: }
        !           141:
        !           142: void
        !           143: atw_cardbus_attach(struct device *parent, struct device *self, void *aux)
        !           144: {
        !           145:        struct atw_cardbus_softc *csc = (void *)self;
        !           146:        struct atw_softc *sc = &csc->sc_atw;
        !           147:        struct cardbus_attach_args *ca = aux;
        !           148:        cardbus_devfunc_t ct = ca->ca_ct;
        !           149:        bus_addr_t adr;
        !           150:
        !           151:        sc->sc_dmat = ca->ca_dmat;
        !           152:        csc->sc_ct = ct;
        !           153:        csc->sc_tag = ca->ca_tag;
        !           154:
        !           155:        /*
        !           156:         * Power management hooks.
        !           157:         */
        !           158:        sc->sc_enable = atw_cardbus_enable;
        !           159:        sc->sc_disable = atw_cardbus_disable;
        !           160:        sc->sc_power = atw_cardbus_power;
        !           161:
        !           162:        /* Get revision info. */
        !           163:        sc->sc_rev = PCI_REVISION(ca->ca_class);
        !           164:
        !           165: #if 0
        !           166:        printf(": signature %08x\n%s",
        !           167:            cardbus_conf_read(ct->ct_cc, ct->ct_cf, csc->sc_tag, 0x80),
        !           168:            sc->sc_dev.dv_xname);
        !           169: #endif
        !           170:
        !           171:        /*
        !           172:         * Map the device.
        !           173:         */
        !           174:        csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
        !           175:        if (Cardbus_mapreg_map(ct, ATW_PCI_MMBA,
        !           176:            CARDBUS_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, &adr,
        !           177:            &csc->sc_mapsize) == 0) {
        !           178: #if 0
        !           179:                printf(": atw_cardbus_attach mapped %d bytes mem space\n%s",
        !           180:                    csc->sc_mapsize, sc->sc_dev.dv_xname);
        !           181: #endif
        !           182:                csc->sc_cben = CARDBUS_MEM_ENABLE;
        !           183:                csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
        !           184:                csc->sc_bar_reg = ATW_PCI_MMBA;
        !           185:                csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
        !           186:        } else if (Cardbus_mapreg_map(ct, ATW_PCI_IOBA,
        !           187:            CARDBUS_MAPREG_TYPE_IO, 0, &sc->sc_st, &sc->sc_sh, &adr,
        !           188:            &csc->sc_mapsize) == 0) {
        !           189: #if 0
        !           190:                printf(": atw_cardbus_attach mapped %d bytes I/O space\n%s",
        !           191:                    csc->sc_mapsize, sc->sc_dev.dv_xname);
        !           192: #endif
        !           193:                csc->sc_cben = CARDBUS_IO_ENABLE;
        !           194:                csc->sc_csr |= CARDBUS_COMMAND_IO_ENABLE;
        !           195:                csc->sc_bar_reg = ATW_PCI_IOBA;
        !           196:                csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO;
        !           197:        } else {
        !           198:                printf(": unable to map device registers\n");
        !           199:                return;
        !           200:        }
        !           201:
        !           202:        /*
        !           203:         * Bring the chip out of powersave mode and initialize the
        !           204:         * configuration registers.
        !           205:         */
        !           206:        atw_cardbus_setup(csc);
        !           207:
        !           208:        /* Remember which interrupt line. */
        !           209:        csc->sc_intrline = ca->ca_intrline;
        !           210:
        !           211:        printf(": revision %d.%d: irq %d\n",
        !           212:            (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf, csc->sc_intrline);
        !           213: #if 0
        !           214:        /*
        !           215:         * The CardBus cards will make it to store-and-forward mode as
        !           216:         * soon as you put them under any kind of load, so just start
        !           217:         * out there.
        !           218:         */
        !           219:        sc->sc_txthresh = 3; /* TBD name constant */
        !           220: #endif
        !           221:
        !           222:        /*
        !           223:         * Finish off the attach.
        !           224:         */
        !           225:        atw_attach(sc);
        !           226:
        !           227:        ATW_WRITE(sc, ATW_FER, ATW_FER_INTR);
        !           228:
        !           229:        /*
        !           230:         * Power down the socket.
        !           231:         */
        !           232:        Cardbus_function_disable(csc->sc_ct);
        !           233: }
        !           234:
        !           235: int
        !           236: atw_cardbus_detach(struct device *self, int flags)
        !           237: {
        !           238:        struct atw_cardbus_softc *csc = (void *)self;
        !           239:        struct atw_softc *sc = &csc->sc_atw;
        !           240:        struct cardbus_devfunc *ct = csc->sc_ct;
        !           241:        int rv;
        !           242:
        !           243: #if defined(DIAGNOSTIC)
        !           244:        if (ct == NULL)
        !           245:                panic("%s: data structure lacks", sc->sc_dev.dv_xname);
        !           246: #endif
        !           247:
        !           248:        rv = atw_detach(sc);
        !           249:        if (rv)
        !           250:                return (rv);
        !           251:
        !           252:        /*
        !           253:         * Unhook the interrupt handler.
        !           254:         */
        !           255:        if (csc->sc_ih != NULL)
        !           256:                cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
        !           257:
        !           258:        /*
        !           259:         * Release bus space and close window.
        !           260:         */
        !           261:        if (csc->sc_bar_reg != 0)
        !           262:                Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
        !           263:                    sc->sc_st, sc->sc_sh, csc->sc_mapsize);
        !           264:
        !           265:        return (0);
        !           266: }
        !           267:
        !           268: int
        !           269: atw_cardbus_enable(struct atw_softc *sc)
        !           270: {
        !           271:        struct atw_cardbus_softc *csc = (void *) sc;
        !           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:
        !           276:        /*
        !           277:         * Power on the socket.
        !           278:         */
        !           279:        Cardbus_function_enable(ct);
        !           280:
        !           281:        /*
        !           282:         * Set up the PCI configuration registers.
        !           283:         */
        !           284:        atw_cardbus_setup(csc);
        !           285:
        !           286:        /*
        !           287:         * Map and establish the interrupt.
        !           288:         */
        !           289:        csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
        !           290:            atw_intr, sc, sc->sc_dev.dv_xname);
        !           291:        if (csc->sc_ih == NULL) {
        !           292:                printf("%s: unable to establish interrupt at %d\n",
        !           293:                    sc->sc_dev.dv_xname, csc->sc_intrline);
        !           294:                Cardbus_function_disable(csc->sc_ct);
        !           295:                return (1);
        !           296:        }
        !           297:
        !           298:        return (0);
        !           299: }
        !           300:
        !           301: void
        !           302: atw_cardbus_disable(struct atw_softc *sc)
        !           303: {
        !           304:        struct atw_cardbus_softc *csc = (void *) sc;
        !           305:        cardbus_devfunc_t ct = csc->sc_ct;
        !           306:        cardbus_chipset_tag_t cc = ct->ct_cc;
        !           307:        cardbus_function_tag_t cf = ct->ct_cf;
        !           308:
        !           309:        /* Unhook the interrupt handler. */
        !           310:        cardbus_intr_disestablish(cc, cf, csc->sc_ih);
        !           311:        csc->sc_ih = NULL;
        !           312:
        !           313:        /* Power down the socket. */
        !           314:        Cardbus_function_disable(ct);
        !           315: }
        !           316:
        !           317: void
        !           318: atw_cardbus_power(struct atw_softc *sc, int why)
        !           319: {
        !           320:        if (why == PWR_RESUME)
        !           321:                atw_enable(sc);
        !           322: }
        !           323:
        !           324: void
        !           325: atw_cardbus_setup(struct atw_cardbus_softc *csc)
        !           326: {
        !           327: #ifdef notyet
        !           328:        struct atw_softc *sc = &csc->sc_atw;
        !           329: #endif
        !           330:        cardbus_devfunc_t ct = csc->sc_ct;
        !           331:        cardbus_chipset_tag_t cc = ct->ct_cc;
        !           332:        cardbus_function_tag_t cf = ct->ct_cf;
        !           333:        pcireg_t reg;
        !           334:
        !           335: #ifdef notyet
        !           336:        (void)cardbus_setpowerstate(sc->sc_dev.dv_xname, ct, csc->sc_tag,
        !           337:            PCI_PWR_D0);
        !           338: #endif
        !           339:
        !           340:        /* Program the BAR. */
        !           341:        cardbus_conf_write(cc, cf, csc->sc_tag, csc->sc_bar_reg,
        !           342:            csc->sc_bar_val);
        !           343:
        !           344:        /* Make sure the right access type is on the CardBus bridge. */
        !           345:        (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
        !           346:        (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
        !           347:
        !           348:        /* Enable the appropriate bits in the PCI CSR. */
        !           349:        reg = cardbus_conf_read(cc, cf, csc->sc_tag,
        !           350:            CARDBUS_COMMAND_STATUS_REG);
        !           351:        reg &= ~(CARDBUS_COMMAND_IO_ENABLE|CARDBUS_COMMAND_MEM_ENABLE);
        !           352:        reg |= csc->sc_csr;
        !           353:        cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_COMMAND_STATUS_REG,
        !           354:            reg);
        !           355:
        !           356:        /*
        !           357:         * Make sure the latency timer is set to some reasonable
        !           358:         * value.
        !           359:         */
        !           360:        reg = cardbus_conf_read(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG);
        !           361:        if (CARDBUS_LATTIMER(reg) < 0x20) {
        !           362:                reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
        !           363:                reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
        !           364:                cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG, reg);
        !           365:        }
        !           366: }

CVSweb