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

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

1.1     ! nbrk        1: /*     $OpenBSD: if_re_cardbus.c,v 1.11 2006/11/28 20:04:02 brad Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2005 Peter Valchev <pvalchev@openbsd.org>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: /*
        !            20:  * Cardbus front-end for the Realtek 8169
        !            21:  */
        !            22:
        !            23: #include <sys/param.h>
        !            24: #include <sys/endian.h>
        !            25: #include <sys/systm.h>
        !            26: #include <sys/sockio.h>
        !            27: #include <sys/mbuf.h>
        !            28: #include <sys/malloc.h>
        !            29: #include <sys/kernel.h>
        !            30: #include <sys/device.h>
        !            31: #include <sys/timeout.h>
        !            32: #include <sys/socket.h>
        !            33:
        !            34: #include <net/if.h>
        !            35: #include <net/if_dl.h>
        !            36: #include <net/if_media.h>
        !            37:
        !            38: #ifdef INET
        !            39: #include <netinet/in.h>
        !            40: #include <netinet/in_systm.h>
        !            41: #include <netinet/in_var.h>
        !            42: #include <netinet/ip.h>
        !            43: #include <netinet/if_ether.h>
        !            44: #endif
        !            45:
        !            46: #include <dev/mii/mii.h>
        !            47: #include <dev/mii/miivar.h>
        !            48:
        !            49: #include <dev/pci/pcidevs.h>
        !            50:
        !            51: #include <dev/cardbus/cardbusvar.h>
        !            52:
        !            53: #include <dev/ic/rtl81x9reg.h>
        !            54: #include <dev/ic/revar.h>
        !            55:
        !            56: struct re_cardbus_softc {
        !            57:        /* General */
        !            58:        struct rl_softc sc_rl;
        !            59:
        !            60:        /* Cardbus-specific data */
        !            61:        void *sc_ih;
        !            62:        cardbus_devfunc_t ct;
        !            63:        cardbustag_t sc_tag;
        !            64:        int sc_csr;
        !            65:        int sc_cben;
        !            66:        int sc_bar_reg;
        !            67:        pcireg_t sc_bar_val;
        !            68:        int sc_intrline;
        !            69:
        !            70:        bus_size_t sc_mapsize;
        !            71: };
        !            72:
        !            73: int    re_cardbus_probe(struct device *, void *, void *);
        !            74: void   re_cardbus_attach(struct device *, struct device *, void *);
        !            75: int    re_cardbus_detach(struct device *, int);
        !            76: void   re_cardbus_setup(struct rl_softc *);
        !            77:
        !            78: void   re_cardbus_shutdown(void *);
        !            79: void   re_cardbus_powerhook(int, void *);
        !            80:
        !            81: /*
        !            82:  * Cardbus autoconfig definitions
        !            83:  */
        !            84: struct cfattach re_cardbus_ca = {
        !            85:        sizeof(struct re_cardbus_softc),
        !            86:        re_cardbus_probe,
        !            87:        re_cardbus_attach,
        !            88:        re_cardbus_detach
        !            89: };
        !            90:
        !            91: const struct cardbus_matchid re_cardbus_devices[] = {
        !            92:        { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169 },
        !            93: };
        !            94:
        !            95: /*
        !            96:  * Probe for a RealTek 8169/8110 chip. Check the PCI vendor and device
        !            97:  * IDs against our list and return a device name if we find a match.
        !            98:  */
        !            99: int
        !           100: re_cardbus_probe(struct device *parent, void *match, void *aux)
        !           101: {
        !           102:        return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
        !           103:            re_cardbus_devices,
        !           104:            sizeof(re_cardbus_devices)/sizeof(re_cardbus_devices[0])));
        !           105: }
        !           106:
        !           107: /*
        !           108:  * Attach the interface. Allocate softc structures, do ifmedia
        !           109:  * setup and ethernet/BPF attach.
        !           110:  */
        !           111: void
        !           112: re_cardbus_attach(struct device *parent, struct device *self, void *aux)
        !           113: {
        !           114:        struct re_cardbus_softc *csc = (struct re_cardbus_softc *)self;
        !           115:        struct rl_softc         *sc = &csc->sc_rl;
        !           116:        struct cardbus_attach_args *ca = aux;
        !           117:        struct cardbus_softc *psc =
        !           118:            (struct cardbus_softc *)sc->sc_dev.dv_parent;
        !           119:        cardbus_chipset_tag_t cc = psc->sc_cc;
        !           120:        cardbus_function_tag_t cf = psc->sc_cf;
        !           121:        cardbus_devfunc_t ct = ca->ca_ct;
        !           122:        bus_addr_t adr;
        !           123:        char intrstr[16];
        !           124:
        !           125:        sc->sc_dmat = ca->ca_dmat;
        !           126:        csc->ct = ct;
        !           127:        csc->sc_tag = ca->ca_tag;
        !           128:        csc->sc_intrline = ca->ca_intrline;
        !           129:
        !           130:        /*
        !           131:         * Map control/status registers.
        !           132:         */
        !           133:        if (Cardbus_mapreg_map(ct, RL_PCI_LOMEM, CARDBUS_MAPREG_TYPE_MEM, 0,
        !           134:            &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
        !           135:                csc->sc_cben = CARDBUS_MEM_ENABLE;
        !           136:                csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
        !           137:                csc->sc_bar_reg = RL_PCI_LOMEM;
        !           138:                csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
        !           139:        } else {
        !           140:                printf(": can't map mem space\n");
        !           141:                return;
        !           142:        }
        !           143:
        !           144:        /* Enable power */
        !           145:        Cardbus_function_enable(ct);
        !           146:
        !           147:        /* Get chip out of powersave mode (if applicable), initialize
        !           148:         * config registers */
        !           149:        re_cardbus_setup(sc);
        !           150:
        !           151:        /* Allocate interrupt */
        !           152:        csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline,
        !           153:            IPL_NET, re_intr, sc, sc->sc_dev.dv_xname);
        !           154:        if (csc->sc_ih == NULL) {
        !           155:                printf(": couldn't establish interrupt at %s",
        !           156:                    ca->ca_intrline);
        !           157:                Cardbus_function_disable(csc->ct);
        !           158:                return;
        !           159:        }
        !           160:        snprintf(intrstr, sizeof(intrstr), "irq %d", ca->ca_intrline);
        !           161:
        !           162:        sc->sc_flags |= RL_ENABLED;
        !           163:        sc->rl_type = RL_8169;
        !           164:
        !           165:        sc->sc_sdhook = shutdownhook_establish(re_cardbus_shutdown, sc);
        !           166:        sc->sc_pwrhook = powerhook_establish(re_cardbus_powerhook, sc);
        !           167:
        !           168:        /* Call bus-independent (common) attach routine */
        !           169:        re_attach(sc, intrstr);
        !           170: }
        !           171:
        !           172: /*
        !           173:  * Get chip out of power-saving mode, init registers
        !           174:  */
        !           175: void
        !           176: re_cardbus_setup(struct rl_softc *sc)
        !           177: {
        !           178:        struct re_cardbus_softc *csc = (struct re_cardbus_softc *)sc;
        !           179:        cardbus_devfunc_t ct = csc->ct;
        !           180:        cardbus_chipset_tag_t cc = ct->ct_cc;
        !           181:        cardbus_function_tag_t cf = ct->ct_cf;
        !           182:        pcireg_t reg, command;
        !           183:        int pmreg;
        !           184:
        !           185:        /* Handle power management nonsense */
        !           186:        if (cardbus_get_capability(cc, cf, csc->sc_tag,
        !           187:            PCI_CAP_PWRMGMT, &pmreg, 0)) {
        !           188:                command = cardbus_conf_read(cc, cf, csc->sc_tag,
        !           189:                    pmreg + PCI_PMCSR);
        !           190:
        !           191:                if (command & RL_PSTATE_MASK) {
        !           192:                        pcireg_t iobase, membase, irq;
        !           193:
        !           194:                        /* Save important PCI config data */
        !           195:                        iobase = cardbus_conf_read(cc, cf, csc->sc_tag, RL_PCI_LOIO);
        !           196:                        membase = cardbus_conf_read(cc, cf, csc->sc_tag, RL_PCI_LOMEM);
        !           197:                        irq = cardbus_conf_read(cc, cf, csc->sc_tag, RL_PCI_INTLINE);
        !           198:
        !           199:                        /* Reset the power state */
        !           200:                        printf("%s: chip is in D%d power mode "
        !           201:                            "-- setting to D0\n", sc->sc_dev.dv_xname,
        !           202:                            command & RL_PSTATE_MASK);
        !           203:                        command &= RL_PSTATE_MASK;
        !           204:                        cardbus_conf_write(cc, cf, csc->sc_tag, pmreg + PCI_PMCSR,
        !           205:                            command);
        !           206:
        !           207:                        /* Restore PCI config data */
        !           208:                        cardbus_conf_write(cc, cf, csc->sc_tag, RL_PCI_LOIO, iobase);
        !           209:                        cardbus_conf_write(cc, cf, csc->sc_tag, RL_PCI_LOMEM, membase);
        !           210:                        cardbus_conf_write(cc, cf, csc->sc_tag, RL_PCI_INTLINE, irq);
        !           211:                }
        !           212:        }
        !           213:
        !           214:        /* Make sure the right access type is on the Cardbus bridge */
        !           215:        (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
        !           216:        (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
        !           217:
        !           218:        /* Program the BAR */
        !           219:        cardbus_conf_write(cc, cf, csc->sc_tag, csc->sc_bar_reg, csc->sc_bar_val);
        !           220:
        !           221:        /* Enable proper bits in CARDBUS CSR */
        !           222:        reg = cardbus_conf_read(cc, cf, csc->sc_tag, CARDBUS_COMMAND_STATUS_REG);
        !           223:        reg &= ~(CARDBUS_COMMAND_IO_ENABLE|CARDBUS_COMMAND_MEM_ENABLE);
        !           224:        reg |= csc->sc_csr;
        !           225:        cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_COMMAND_STATUS_REG, reg);
        !           226:
        !           227:        /* Make sure the latency timer is set to some reasonable value */
        !           228:        reg = cardbus_conf_read(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG);
        !           229:        if (CARDBUS_LATTIMER(reg) < 0x20) {
        !           230:                reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
        !           231:                reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
        !           232:                cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG, reg);
        !           233:        }
        !           234: }
        !           235:
        !           236: /*
        !           237:  * Cardbus detach function: deallocate all resources
        !           238:  */
        !           239: int
        !           240: re_cardbus_detach(struct device *self, int flags)
        !           241: {
        !           242:        struct re_cardbus_softc *csc = (void *)self;
        !           243:        struct rl_softc *sc = &csc->sc_rl;
        !           244:        struct cardbus_devfunc *ct = csc->ct;
        !           245:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           246:
        !           247:        /* Remove timeout handler */
        !           248:        timeout_del(&sc->timer_handle);
        !           249:
        !           250:        /* Detach PHY */
        !           251:        if (LIST_FIRST(&sc->sc_mii.mii_phys) != NULL)
        !           252:                mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
        !           253:
        !           254:        /* Delete media stuff */
        !           255:        ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
        !           256:        ether_ifdetach(ifp);
        !           257:        if_detach(ifp);
        !           258:
        !           259:        /* No more hooks */
        !           260:        if (sc->sc_sdhook != NULL)
        !           261:                shutdownhook_disestablish(sc->sc_sdhook);
        !           262:        if (sc->sc_pwrhook != NULL)
        !           263:                powerhook_disestablish(sc->sc_pwrhook);
        !           264:
        !           265:        /* Disable interrupts */
        !           266:        if (csc->sc_ih != NULL)
        !           267:                cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
        !           268:
        !           269:        /* Free cardbus resources */
        !           270:        Cardbus_mapreg_unmap(ct, csc->sc_bar_reg, sc->rl_btag, sc->rl_bhandle,
        !           271:            csc->sc_mapsize);
        !           272:
        !           273:        return (0);
        !           274: }
        !           275:
        !           276: void
        !           277: re_cardbus_shutdown(void *arg)
        !           278: {
        !           279:        struct rl_softc *sc = arg;
        !           280:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           281:
        !           282:        re_stop(ifp, 1);
        !           283: }
        !           284:
        !           285: void
        !           286: re_cardbus_powerhook(int why, void *arg)
        !           287: {
        !           288:        struct rl_softc *sc = arg;
        !           289:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           290:
        !           291:        if (why == PWR_RESUME)
        !           292:                re_init(ifp);
        !           293: }

CVSweb