[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

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