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

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

1.1     ! nbrk        1: /*     $OpenBSD: if_rl_cardbus.c,v 1.16 2007/05/08 18:49:32 deraadt Exp $ */
        !             2: /*     $NetBSD: if_rl_cardbus.c,v 1.3.8.3 2001/11/14 19:14:02 nathanw Exp $    */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 2000 Masanori Kanaoka
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. The name of the author may not be used to endorse or promote products
        !            17:  *    derived from this software without specific prior written permission.
        !            18:  *
        !            19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            20:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            21:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            22:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            23:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            24:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            25:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            26:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            27:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
        !            28:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            29:  */
        !            30:
        !            31: /*
        !            32:  * if_rl_cardbus.c:
        !            33:  *     Cardbus specific routines for RealTek 8139 ethernet adapter.
        !            34:  *     Tested for
        !            35:  *             - elecom-Laneed LD-10/100CBA (Accton MPX5030)
        !            36:  *             - MELCO         LPC3-TX-CB   (RealTek 8139)
        !            37:  */
        !            38:
        !            39: #include "bpfilter.h"
        !            40:
        !            41: #include <sys/param.h>
        !            42: #include <sys/systm.h>
        !            43: #include <sys/mbuf.h>
        !            44: #include <sys/socket.h>
        !            45: #include <sys/ioctl.h>
        !            46: #include <sys/errno.h>
        !            47: #include <sys/malloc.h>
        !            48: #include <sys/kernel.h>
        !            49: #include <sys/timeout.h>
        !            50: #include <sys/device.h>
        !            51:
        !            52: #include <net/if.h>
        !            53: #include <net/if_dl.h>
        !            54: #include <net/if_types.h>
        !            55: #include <net/if_media.h>
        !            56:
        !            57: #include <machine/endian.h>
        !            58:
        !            59: #if NBPFILTER > 0
        !            60: #include <net/bpf.h>
        !            61: #endif
        !            62:
        !            63: #ifdef INET
        !            64: #include <netinet/in.h>
        !            65: #include <netinet/in_systm.h>
        !            66: #include <netinet/in_var.h>
        !            67: #include <netinet/ip.h>
        !            68: #include <netinet/if_ether.h>
        !            69: #endif
        !            70:
        !            71: #include <machine/bus.h>
        !            72: #include <machine/intr.h>
        !            73:
        !            74: #include <dev/mii/miivar.h>
        !            75:
        !            76: #include <dev/pci/pcivar.h>
        !            77: #include <dev/pci/pcireg.h>
        !            78: #include <dev/pci/pcidevs.h>
        !            79:
        !            80: #include <dev/cardbus/cardbusvar.h>
        !            81:
        !            82: /*
        !            83:  * Default to using PIO access for this driver. On SMP systems,
        !            84:  * there appear to be problems with memory mapped mode: it looks like
        !            85:  * doing too many memory mapped access back to back in rapid succession
        !            86:  * can hang the bus. I'm inclined to blame this on crummy design/construction
        !            87:  * on the part of RealTek. Memory mapped mode does appear to work on
        !            88:  * uniprocessor systems though.
        !            89:  */
        !            90: #define RL_USEIOSPACE
        !            91:
        !            92: #include <dev/ic/rtl81x9reg.h>
        !            93:
        !            94: /*
        !            95:  * Various supported device vendors/types and their names.
        !            96:  */
        !            97: const struct cardbus_matchid rl_cardbus_devices[] = {
        !            98:        { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_5030 },
        !            99:        { PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2000VX },
        !           100:        { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8138 },
        !           101:        { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8139 },
        !           102:        { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_CB_TXD },
        !           103:        { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_2CB_TXD },
        !           104:        { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DFE690TXD },
        !           105:        { PCI_VENDOR_PLANEX, PCI_PRODUCT_PLANEX_FNW_3603_TX },
        !           106:        { PCI_VENDOR_PLANEX, PCI_PRODUCT_PLANEX_FNW_3800_TX },
        !           107: };
        !           108:
        !           109: struct rl_cardbus_softc {
        !           110:        struct rl_softc sc_rl;  /* real rtk softc */
        !           111:
        !           112:        /* CardBus-specific goo. */
        !           113:        void *sc_ih;
        !           114:        cardbus_devfunc_t sc_ct;
        !           115:        cardbustag_t sc_tag;
        !           116:        int sc_csr;
        !           117:        int sc_cben;
        !           118:        int sc_bar_reg;
        !           119:        pcireg_t sc_bar_val;
        !           120:        bus_size_t sc_mapsize;
        !           121:        int sc_intrline;
        !           122: };
        !           123:
        !           124: static int rl_cardbus_match(struct device *, void *, void *);
        !           125: static void rl_cardbus_attach(struct device *, struct device *, void *);
        !           126: static int rl_cardbus_detach(struct device *, int);
        !           127: void rl_cardbus_setup(struct rl_cardbus_softc *);
        !           128:
        !           129: struct cfattach rl_cardbus_ca = {
        !           130:        sizeof(struct rl_cardbus_softc), rl_cardbus_match, rl_cardbus_attach,
        !           131:            rl_cardbus_detach
        !           132: };
        !           133:
        !           134: int
        !           135: rl_cardbus_match(parent, match, aux)
        !           136:        struct device *parent;
        !           137:        void *match;
        !           138:        void *aux;
        !           139: {
        !           140:        return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
        !           141:            rl_cardbus_devices,
        !           142:            sizeof(rl_cardbus_devices)/sizeof(rl_cardbus_devices[0])));
        !           143: }
        !           144:
        !           145:
        !           146: void
        !           147: rl_cardbus_attach(parent, self, aux)
        !           148:        struct device *parent, *self;
        !           149:        void *aux;
        !           150: {
        !           151:        struct rl_cardbus_softc *csc = (struct rl_cardbus_softc *)self;
        !           152:        struct rl_softc *sc = &csc->sc_rl;
        !           153:        struct cardbus_attach_args *ca = aux;
        !           154:        struct cardbus_softc *psc =
        !           155:            (struct cardbus_softc *)sc->sc_dev.dv_parent;
        !           156:        cardbus_chipset_tag_t cc = psc->sc_cc;
        !           157:        cardbus_function_tag_t cf = psc->sc_cf;
        !           158:        cardbus_devfunc_t ct = ca->ca_ct;
        !           159:        bus_addr_t adr;
        !           160:
        !           161:        sc->sc_dmat = ca->ca_dmat;
        !           162:        csc->sc_ct = ct;
        !           163:        csc->sc_tag = ca->ca_tag;
        !           164:        csc->sc_intrline = ca->ca_intrline;
        !           165:
        !           166:        /*
        !           167:         * Map control/status registers.
        !           168:         */
        !           169:        csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
        !           170: #ifdef RL_USEIOSPACE
        !           171:        if (Cardbus_mapreg_map(ct, RL_PCI_LOIO, CARDBUS_MAPREG_TYPE_IO, 0,
        !           172:            &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
        !           173:                csc->sc_cben = CARDBUS_IO_ENABLE;
        !           174:                csc->sc_csr |= CARDBUS_COMMAND_IO_ENABLE;
        !           175:                csc->sc_bar_reg = RL_PCI_LOIO;
        !           176:                csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO;
        !           177:        }
        !           178: #else
        !           179:        if (Cardbus_mapreg_map(ct, RL_PCI_LOMEM, CARDBUS_MAPREG_TYPE_MEM, 0,
        !           180:            &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
        !           181:                csc->sc_cben = CARDBUS_MEM_ENABLE;
        !           182:                csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
        !           183:                csc->sc_bar_reg = RL_PCI_LOMEM;
        !           184:                csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
        !           185:        }
        !           186: #endif
        !           187:        else {
        !           188:                printf("%s: unable to map deviceregisters\n",
        !           189:                         sc->sc_dev.dv_xname);
        !           190:                return;
        !           191:        }
        !           192:
        !           193:        Cardbus_function_enable(ct);
        !           194:
        !           195:        rl_cardbus_setup(csc);
        !           196:
        !           197:        /*
        !           198:         * Map and establish the interrupt.
        !           199:         */
        !           200:        csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
        !           201:            rl_intr, sc, sc->sc_dev.dv_xname);
        !           202:        if (csc->sc_ih == NULL) {
        !           203:                printf(": couldn't establish interrupt\n");
        !           204:                Cardbus_function_disable(csc->sc_ct);
        !           205:                return;
        !           206:        }
        !           207:        printf(": irq %d", csc->sc_intrline);
        !           208:
        !           209:        /* XXX - hardcode this, for now */
        !           210:        sc->rl_type = RL_8139;
        !           211:
        !           212:        rl_attach(sc);
        !           213: }
        !           214:
        !           215: extern int rl_detach(struct rl_softc *);
        !           216:
        !           217: int
        !           218: rl_detach(sc)
        !           219:        struct rl_softc *sc;
        !           220: {
        !           221:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           222:
        !           223:        /* Unhook our tick handler. */
        !           224:        timeout_del(&sc->sc_tick_tmo);
        !           225:
        !           226:        /* Detach any PHYs we might have. */
        !           227:        if (LIST_FIRST(&sc->sc_mii.mii_phys) != NULL)
        !           228:                mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
        !           229:
        !           230:        /* Delete any remaining media. */
        !           231:        ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
        !           232:
        !           233:        ether_ifdetach(ifp);
        !           234:        if_detach(ifp);
        !           235:
        !           236:        if (sc->sc_sdhook != NULL)
        !           237:                shutdownhook_disestablish(sc->sc_sdhook);
        !           238:        if (sc->sc_pwrhook != NULL)
        !           239:                powerhook_disestablish(sc->sc_pwrhook);
        !           240:
        !           241:        return (0);
        !           242: }
        !           243:
        !           244: int
        !           245: rl_cardbus_detach(self, flags)
        !           246:        struct device *self;
        !           247:        int flags;
        !           248: {
        !           249:        struct rl_cardbus_softc *csc = (void *) self;
        !           250:        struct rl_softc *sc = &csc->sc_rl;
        !           251:        struct cardbus_devfunc *ct = csc->sc_ct;
        !           252:        int     rv;
        !           253:
        !           254: #ifdef DIAGNOSTIC
        !           255:        if (ct == NULL)
        !           256:                panic("%s: data structure lacks", sc->sc_dev.dv_xname);
        !           257: #endif
        !           258:        rv = rl_detach(sc);
        !           259:        if (rv)
        !           260:                return (rv);
        !           261:        /*
        !           262:         * Unhook the interrupt handler.
        !           263:         */
        !           264:        if (csc->sc_ih != NULL)
        !           265:                cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
        !           266:
        !           267:        /*
        !           268:         * Release bus space and close window.
        !           269:         */
        !           270:        if (csc->sc_bar_reg != 0)
        !           271:                Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
        !           272:                        sc->rl_btag, sc->rl_bhandle, csc->sc_mapsize);
        !           273:
        !           274:        return (0);
        !           275: }
        !           276:
        !           277: void
        !           278: rl_cardbus_setup(csc)
        !           279:        struct rl_cardbus_softc *csc;
        !           280: {
        !           281:        struct rl_softc *sc = &csc->sc_rl;
        !           282:        cardbus_devfunc_t ct = csc->sc_ct;
        !           283:        cardbus_chipset_tag_t cc = ct->ct_cc;
        !           284:        cardbus_function_tag_t cf = ct->ct_cf;
        !           285:        pcireg_t        reg, command;
        !           286:        int             pmreg;
        !           287:
        !           288:        /*
        !           289:         * Handle power management nonsense.
        !           290:         */
        !           291:        if (cardbus_get_capability(cc, cf, csc->sc_tag,
        !           292:            PCI_CAP_PWRMGMT, &pmreg, 0)) {
        !           293:                command = cardbus_conf_read(cc, cf, csc->sc_tag, pmreg + 4);
        !           294:                if (command & RL_PSTATE_MASK) {
        !           295:                        pcireg_t                iobase, membase, irq;
        !           296:
        !           297:                        /* Save important PCI config data. */
        !           298:                        iobase = cardbus_conf_read(cc, cf, csc->sc_tag,
        !           299:                            RL_PCI_LOIO);
        !           300:                        membase = cardbus_conf_read(cc, cf,csc->sc_tag,
        !           301:                            RL_PCI_LOMEM);
        !           302:                        irq = cardbus_conf_read(cc, cf,csc->sc_tag,
        !           303:                            PCI_PRODUCT_DELTA_8139);
        !           304:
        !           305:                        /* Reset the power state. */
        !           306:                        printf("%s: chip is in D%d power mode "
        !           307:                            "-- setting to D0\n", sc->sc_dev.dv_xname,
        !           308:                            command & RL_PSTATE_MASK);
        !           309:                        command &= 0xFFFFFFFC;
        !           310:                        cardbus_conf_write(cc, cf, csc->sc_tag,
        !           311:                            pmreg + 4, command);
        !           312:
        !           313:                        /* Restore PCI config data. */
        !           314:                        cardbus_conf_write(cc, cf, csc->sc_tag,
        !           315:                            RL_PCI_LOIO, iobase);
        !           316:                        cardbus_conf_write(cc, cf, csc->sc_tag,
        !           317:                            RL_PCI_LOMEM, membase);
        !           318:                        cardbus_conf_write(cc, cf, csc->sc_tag,
        !           319:                            PCI_PRODUCT_DELTA_8139, irq);
        !           320:                }
        !           321:        }
        !           322:
        !           323:        /* Make sure the right access type is on the CardBus bridge. */
        !           324:        (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
        !           325:        (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
        !           326:
        !           327:        /* Program the BAR */
        !           328:        cardbus_conf_write(cc, cf, csc->sc_tag,
        !           329:                csc->sc_bar_reg, csc->sc_bar_val);
        !           330:
        !           331:        /* Enable the appropriate bits in the CARDBUS CSR. */
        !           332:        reg = cardbus_conf_read(cc, cf, csc->sc_tag,
        !           333:            CARDBUS_COMMAND_STATUS_REG);
        !           334:        reg &= ~(CARDBUS_COMMAND_IO_ENABLE|CARDBUS_COMMAND_MEM_ENABLE);
        !           335:        reg |= csc->sc_csr;
        !           336:        cardbus_conf_write(cc, cf, csc->sc_tag,
        !           337:            CARDBUS_COMMAND_STATUS_REG, reg);
        !           338:
        !           339:        /*
        !           340:         * Make sure the latency timer is set to some reasonable
        !           341:         * value.
        !           342:         */
        !           343:        reg = cardbus_conf_read(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG);
        !           344:        if (CARDBUS_LATTIMER(reg) < 0x20) {
        !           345:                reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
        !           346:                reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
        !           347:                cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG, reg);
        !           348:        }
        !           349: }
        !           350:

CVSweb