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

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

1.1     ! nbrk        1: /*     $OpenBSD: if_xl_cardbus.c,v 1.19 2007/05/05 13:24:03 deraadt Exp $ */
        !             2: /*     $NetBSD: if_xl_cardbus.c,v 1.13 2000/03/07 00:32:52 mycroft Exp $       */
        !             3:
        !             4: /*
        !             5:  * CardBus specific routines for 3Com 3C575-family CardBus ethernet adapter
        !             6:  *
        !             7:  * Copyright (c) 1998 and 1999
        !             8:  *       HAYAKAWA Koichi.  All rights reserved.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *      This product includes software developed by the author.
        !            21:  * 4. Neither the name of the author nor the names of any co-contributors
        !            22:  *    may be used to endorse or promote products derived from this software
        !            23:  *    without specific prior written permission.
        !            24:  *
        !            25:  * THIS SOFTWARE IS PROVIDED BY HAYAKAWA KOICHI ``AS IS'' AND
        !            26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            28:  * ARE DISCLAIMED.  IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE
        !            29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            35:  * SUCH DAMAGE.
        !            36:  *
        !            37:  *
        !            38:  */
        !            39:
        !            40: #include "bpfilter.h"
        !            41:
        !            42: #include <sys/param.h>
        !            43: #include <sys/systm.h>
        !            44: #include <sys/mbuf.h>
        !            45: #include <sys/socket.h>
        !            46: #include <sys/ioctl.h>
        !            47: #include <sys/errno.h>
        !            48: #include <sys/malloc.h>
        !            49: #include <sys/kernel.h>
        !            50: #include <sys/proc.h>
        !            51: #include <sys/device.h>
        !            52:
        !            53: #include <net/if.h>
        !            54: #include <net/if_dl.h>
        !            55: #include <net/if_types.h>
        !            56: #include <net/if_media.h>
        !            57:
        !            58: #ifdef INET
        !            59: #include <netinet/in.h>
        !            60: #include <netinet/in_systm.h>
        !            61: #include <netinet/in_var.h>
        !            62: #include <netinet/ip.h>
        !            63: #include <netinet/if_ether.h>
        !            64: #endif
        !            65:
        !            66: #include <machine/cpu.h>
        !            67: #include <machine/bus.h>
        !            68:
        !            69: #include <dev/cardbus/cardbusvar.h>
        !            70: #include <dev/pci/pcidevs.h>
        !            71:
        !            72: #include <dev/mii/mii.h>
        !            73: #include <dev/mii/miivar.h>
        !            74:
        !            75: #include <dev/ic/xlreg.h>
        !            76:
        !            77: #if defined XL_DEBUG
        !            78: #define DPRINTF(a) printf a
        !            79: #else
        !            80: #define DPRINTF(a)
        !            81: #endif
        !            82:
        !            83: #define CARDBUS_3C575BTX_FUNCSTAT_PCIREG  CARDBUS_BASE2_REG  /* means 0x18 */
        !            84:
        !            85: int xl_cardbus_match(struct device *, void *, void *);
        !            86: void xl_cardbus_attach(struct device *, struct device *,void *);
        !            87: int xl_cardbus_detach(struct device *, int);
        !            88: void xl_cardbus_intr_ack(struct xl_softc *);
        !            89:
        !            90: #define XL_CARDBUS_BOOMERANG   0x0001
        !            91: #define XL_CARDBUS_CYCLONE     0x0002
        !            92:
        !            93: #define XL_CARDBUS_INTR                0x0004
        !            94: #define XL_CARDBUS_INTR_ACK    0x8000
        !            95:
        !            96: struct xl_cardbus_softc {
        !            97:        struct xl_softc sc_softc;
        !            98:
        !            99:        cardbus_devfunc_t sc_ct;
        !           100:        int sc_intrline;
        !           101:        u_int8_t sc_cardbus_flags;
        !           102:        u_int8_t sc_cardtype;
        !           103:
        !           104:        /* CardBus function status space.  575B requests it. */
        !           105:        bus_space_tag_t sc_funct;
        !           106:        bus_space_handle_t sc_funch;
        !           107:        bus_size_t sc_funcsize;
        !           108:
        !           109:        bus_size_t sc_mapsize;          /* size of mapped bus space region */
        !           110: };
        !           111:
        !           112: struct cfattach xl_cardbus_ca = {
        !           113:        sizeof(struct xl_cardbus_softc), xl_cardbus_match,
        !           114:            xl_cardbus_attach, xl_cardbus_detach
        !           115: };
        !           116:
        !           117: const struct xl_cardbus_product {
        !           118:        u_int32_t       ecp_prodid;     /* CardBus product ID */
        !           119:        int             ecp_flags;      /* initial softc flags */
        !           120:        pcireg_t        ecp_csr;        /* PCI CSR flags */
        !           121:        int             ecp_cardtype;   /* card type */
        !           122:        const char      *ecp_name;      /* device name */
        !           123: } xl_cardbus_products[] = {
        !           124:        { PCI_PRODUCT_3COM_3C575,
        !           125:          XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM,
        !           126:          CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE,
        !           127:          XL_CARDBUS_BOOMERANG,
        !           128:          "3c575-TX Ethernet" },
        !           129:
        !           130:        { PCI_PRODUCT_3COM_3CCFE575BT,
        !           131:          XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
        !           132:              XL_FLAG_INVERT_LED_PWR,
        !           133:          CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
        !           134:              CARDBUS_COMMAND_MASTER_ENABLE,
        !           135:          XL_CARDBUS_CYCLONE,
        !           136:          "3c575B-TX Ethernet" },
        !           137:
        !           138:        { PCI_PRODUCT_3COM_3CCFE575CT,
        !           139:          XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
        !           140:              XL_FLAG_INVERT_MII_PWR,
        !           141:          CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
        !           142:              CARDBUS_COMMAND_MASTER_ENABLE,
        !           143:          XL_CARDBUS_CYCLONE,
        !           144:          "3c575C-TX Ethernet" },
        !           145:
        !           146:        { PCI_PRODUCT_3COM_3CCFEM656,
        !           147:          XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
        !           148:              XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR,
        !           149:          CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
        !           150:              CARDBUS_COMMAND_MASTER_ENABLE,
        !           151:          XL_CARDBUS_CYCLONE,
        !           152:          "3c656-TX Ethernet" },
        !           153:
        !           154:        { PCI_PRODUCT_3COM_3CCFEM656B,
        !           155:          XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
        !           156:              XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR,
        !           157:          CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
        !           158:              CARDBUS_COMMAND_MASTER_ENABLE,
        !           159:          XL_CARDBUS_CYCLONE,
        !           160:          "3c656B-TX Ethernet" },
        !           161:
        !           162:        { PCI_PRODUCT_3COM_3CCFEM656C,
        !           163:          XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
        !           164:              XL_FLAG_INVERT_MII_PWR,
        !           165:          CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
        !           166:              CARDBUS_COMMAND_MASTER_ENABLE,
        !           167:          XL_CARDBUS_CYCLONE,
        !           168:          "3c656C-TX Ethernet" },
        !           169:
        !           170:        { 0,
        !           171:          0,
        !           172:          0,
        !           173:          0,
        !           174:          NULL },
        !           175: };
        !           176:
        !           177: const struct xl_cardbus_product *xl_cardbus_lookup(const struct cardbus_attach_args *);
        !           178:
        !           179: const struct xl_cardbus_product *
        !           180: xl_cardbus_lookup(const struct cardbus_attach_args *ca)
        !           181: {
        !           182:        const struct xl_cardbus_product *ecp;
        !           183:
        !           184:        if (CARDBUS_VENDOR(ca->ca_id) != PCI_VENDOR_3COM)
        !           185:                return (NULL);
        !           186:
        !           187:        for (ecp = xl_cardbus_products; ecp->ecp_name != NULL; ecp++)
        !           188:                if (CARDBUS_PRODUCT(ca->ca_id) == ecp->ecp_prodid)
        !           189:                        return (ecp);
        !           190:        return (NULL);
        !           191: }
        !           192:
        !           193: int
        !           194: xl_cardbus_match(struct device *parent, void *match, void *aux)
        !           195: {
        !           196:        struct cardbus_attach_args *ca = aux;
        !           197:
        !           198:        if (xl_cardbus_lookup(ca) != NULL)
        !           199:                return (1);
        !           200:
        !           201:        return (0);
        !           202: }
        !           203:
        !           204: void
        !           205: xl_cardbus_attach(struct device *parent, struct device *self, void *aux)
        !           206: {
        !           207:        struct xl_cardbus_softc *csc = (void *)self;
        !           208:        struct xl_softc *sc = &csc->sc_softc;
        !           209:        struct cardbus_attach_args *ca = aux;
        !           210:        cardbus_devfunc_t ct = ca->ca_ct;
        !           211:        cardbus_chipset_tag_t cc = ct->ct_cc;
        !           212:        cardbus_function_tag_t cf = ct->ct_cf;
        !           213:        cardbusreg_t iob, command, bhlc;
        !           214:        const struct xl_cardbus_product *ecp;
        !           215:        bus_space_handle_t ioh;
        !           216:        bus_addr_t adr;
        !           217:
        !           218:        if (Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO, 0,
        !           219:            &sc->xl_btag, &ioh, &adr, &csc->sc_mapsize)) {
        !           220:                printf(": can't map i/o space\n");
        !           221:                return;
        !           222:        }
        !           223:
        !           224:        ecp = xl_cardbus_lookup(ca);
        !           225:        if (ecp == NULL) {
        !           226:                printf("\n");
        !           227:                panic("xl_cardbus_attach: impossible");
        !           228:        }
        !           229:
        !           230:        printf(": 3Com %s", ecp->ecp_name);
        !           231:
        !           232:        sc->xl_flags = ecp->ecp_flags;
        !           233:        sc->sc_dmat = ca->ca_dmat;
        !           234:
        !           235:        iob = adr;
        !           236:        sc->xl_bhandle = ioh;
        !           237:
        !           238:        (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE);
        !           239:
        !           240:        command = cardbus_conf_read(cc, cf, ca->ca_tag,
        !           241:            CARDBUS_COMMAND_STATUS_REG);
        !           242:        command |= ecp->ecp_csr;
        !           243:        csc->sc_cardtype = ecp->ecp_cardtype;
        !           244:
        !           245:        if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) {
        !           246:                /* map CardBus function status window */
        !           247:                if (Cardbus_mapreg_map(ct, CARDBUS_BASE2_REG,
        !           248:                    CARDBUS_MAPREG_TYPE_MEM, 0, &csc->sc_funct,
        !           249:                    &csc->sc_funch, 0, &csc->sc_funcsize)) {
        !           250:                        printf("%s: unable to map function status window\n",
        !           251:                            self->dv_xname);
        !           252:                        return;
        !           253:                }
        !           254:
        !           255:                /*
        !           256:                 * Make sure CardBus bridge can access memory space.  Usually
        !           257:                 * memory access is enabled by BIOS, but some BIOSes do not
        !           258:                 * enable it.
        !           259:                 */
        !           260:                (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
        !           261:        }
        !           262:
        !           263:        (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
        !           264:        cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG,
        !           265:            command);
        !           266:
        !           267:        /*
        !           268:         * set latency timer
        !           269:         */
        !           270:        bhlc = cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG);
        !           271:        if (CARDBUS_LATTIMER(bhlc) < 0x20) {
        !           272:                /* at least the value of latency timer should 0x20. */
        !           273:                DPRINTF(("if_xl_cardbus: lattimer 0x%x -> 0x20\n",
        !           274:                    CARDBUS_LATTIMER(bhlc)));
        !           275:                bhlc &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
        !           276:                bhlc |= (0x20 << CARDBUS_LATTIMER_SHIFT);
        !           277:                cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG, bhlc);
        !           278:        }
        !           279:
        !           280:        csc->sc_ct = ca->ca_ct;
        !           281:        csc->sc_intrline = ca->ca_intrline;
        !           282:
        !           283:        /* Map and establish the interrupt. */
        !           284:
        !           285:        sc->xl_intrhand = cardbus_intr_establish(cc, cf, ca->ca_intrline,
        !           286:            IPL_NET, xl_intr, csc, self->dv_xname);
        !           287:
        !           288:        if (sc->xl_intrhand == NULL) {
        !           289:                printf(": couldn't establish interrupt");
        !           290:                printf(" at %d", ca->ca_intrline);
        !           291:                printf("\n");
        !           292:                return;
        !           293:        }
        !           294:        printf(": irq %d", ca->ca_intrline);
        !           295:
        !           296:        sc->intr_ack = xl_cardbus_intr_ack;
        !           297:
        !           298:        xl_attach(sc);
        !           299:
        !           300:        if (csc->sc_cardtype == XL_CARDBUS_CYCLONE)
        !           301:                bus_space_write_4(csc->sc_funct, csc->sc_funch,
        !           302:                    XL_CARDBUS_INTR, XL_CARDBUS_INTR_ACK);
        !           303:
        !           304: }
        !           305:
        !           306: int
        !           307: xl_detach(struct xl_softc *sc)
        !           308: {
        !           309:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           310:        extern void xl_freetxrx(struct xl_softc *);
        !           311:
        !           312:        /* Unhook our tick handler. */
        !           313:        timeout_del(&sc->xl_stsup_tmo);
        !           314:
        !           315:        xl_freetxrx(sc);
        !           316:
        !           317:        /* Detach all PHYs */
        !           318:        if (sc->xl_hasmii)
        !           319:                mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
        !           320:
        !           321:        /* Delete all remaining media. */
        !           322:        ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
        !           323:
        !           324:        ether_ifdetach(ifp);
        !           325:        if_detach(ifp);
        !           326:
        !           327:        if (sc->sc_sdhook != NULL)
        !           328:                shutdownhook_disestablish(sc->sc_sdhook);
        !           329:        if (sc->sc_pwrhook != NULL)
        !           330:                powerhook_disestablish(sc->sc_pwrhook);
        !           331:
        !           332:        return (0);
        !           333: }
        !           334:
        !           335: int
        !           336: xl_cardbus_detach(struct device *self, int arg)
        !           337: {
        !           338:        struct xl_cardbus_softc *csc = (void *)self;
        !           339:        struct xl_softc *sc = &csc->sc_softc;
        !           340:        struct cardbus_devfunc *ct = csc->sc_ct;
        !           341:        int rv = 0;
        !           342:
        !           343: #if defined(DIAGNOSTIC)
        !           344:        if (ct == NULL) {
        !           345:                panic("%s: data structure lacks", sc->sc_dev.dv_xname);
        !           346:        }
        !           347: #endif
        !           348:
        !           349:        rv = xl_detach(sc);
        !           350:        if (rv == 0) {
        !           351:                /*
        !           352:                 * Unhook the interrupt handler.
        !           353:                 */
        !           354:                cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf,
        !           355:                    sc->xl_intrhand);
        !           356:
        !           357:                if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) {
        !           358:                        Cardbus_mapreg_unmap(ct, CARDBUS_BASE2_REG,
        !           359:                            csc->sc_funct, csc->sc_funch, csc->sc_funcsize);
        !           360:                }
        !           361:
        !           362:                Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->xl_btag,
        !           363:                    sc->xl_bhandle, csc->sc_mapsize);
        !           364:        }
        !           365:        return (rv);
        !           366: }
        !           367:
        !           368: void
        !           369: xl_cardbus_intr_ack(struct xl_softc *sc)
        !           370: {
        !           371:        struct xl_cardbus_softc *csc = (struct xl_cardbus_softc *)sc;
        !           372:
        !           373:        bus_space_write_4(csc->sc_funct, csc->sc_funch, XL_CARDBUS_INTR,
        !           374:            XL_CARDBUS_INTR_ACK);
        !           375: }

CVSweb