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

Annotation of sys/dev/pcmcia/if_sm_pcmcia.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_sm_pcmcia.c,v 1.27 2006/06/17 18:01:52 brad Exp $  */
        !             2: /*     $NetBSD: if_sm_pcmcia.c,v 1.11 1998/08/15 20:47:32 thorpej Exp $  */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1997, 1998 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.
        !            11:  *
        !            12:  * Redistribution and use in source and binary forms, with or without
        !            13:  * modification, are permitted provided that the following conditions
        !            14:  * are met:
        !            15:  * 1. Redistributions of source code must retain the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. All advertising materials mentioning features or use of this software
        !            21:  *    must display the following acknowledgement:
        !            22:  *     This product includes software developed by the NetBSD
        !            23:  *     Foundation, Inc. and its contributors.
        !            24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            25:  *    contributors may be used to endorse or promote products derived
        !            26:  *    from this software without specific prior written permission.
        !            27:  *
        !            28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            38:  * POSSIBILITY OF SUCH DAMAGE.
        !            39:  */
        !            40:
        !            41: #include "bpfilter.h"
        !            42:
        !            43: #include <sys/param.h>
        !            44: #include <sys/systm.h>
        !            45: #include <sys/mbuf.h>
        !            46: #include <sys/socket.h>
        !            47: #include <sys/ioctl.h>
        !            48: #include <sys/errno.h>
        !            49: #include <sys/syslog.h>
        !            50: #include <sys/selinfo.h>
        !            51: #include <sys/timeout.h>
        !            52: #include <sys/device.h>
        !            53:
        !            54: #include <net/if.h>
        !            55: #include <net/if_dl.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: #if NBPFILTER > 0
        !            67: #include <net/bpf.h>
        !            68: #endif
        !            69:
        !            70: #include <machine/intr.h>
        !            71: #include <machine/bus.h>
        !            72:
        !            73: #include <net/if_media.h>
        !            74:
        !            75: #include <dev/mii/mii.h>
        !            76: #include <dev/mii/miivar.h>
        !            77:
        !            78: #include <dev/ic/smc91cxxreg.h>
        !            79: #include <dev/ic/smc91cxxvar.h>
        !            80:
        !            81: #include <dev/pcmcia/pcmciareg.h>
        !            82: #include <dev/pcmcia/pcmciavar.h>
        !            83: #include <dev/pcmcia/pcmciadevs.h>
        !            84:
        !            85: int    sm_pcmcia_match(struct device *, void *, void *);
        !            86: void   sm_pcmcia_attach(struct device *, struct device *, void *);
        !            87: int    sm_pcmcia_detach(struct device *, int);
        !            88: int    sm_pcmcia_activate(struct device *, enum devact);
        !            89:
        !            90: struct sm_pcmcia_softc {
        !            91:        struct  smc91cxx_softc sc_smc;          /* real "smc" softc */
        !            92:
        !            93:        /* PCMCIA-specific goo. */
        !            94:        struct  pcmcia_io_handle sc_pcioh;      /* PCMCIA i/o space info */
        !            95:        int     sc_io_window;                   /* our i/o window */
        !            96:        void    *sc_ih;                         /* interrupt cookie */
        !            97:        struct  pcmcia_function *sc_pf;         /* our PCMCIA function */
        !            98: };
        !            99:
        !           100: struct cfattach sm_pcmcia_ca = {
        !           101:        sizeof(struct sm_pcmcia_softc), sm_pcmcia_match, sm_pcmcia_attach,
        !           102:        sm_pcmcia_detach, sm_pcmcia_activate
        !           103: };
        !           104:
        !           105: int    sm_pcmcia_enable(struct smc91cxx_softc *);
        !           106: void   sm_pcmcia_disable(struct smc91cxx_softc *);
        !           107:
        !           108: int    sm_pcmcia_ascii_enaddr(const char *, u_int8_t *);
        !           109: int    sm_pcmcia_funce_enaddr(struct device *, u_int8_t *);
        !           110:
        !           111: int    sm_pcmcia_lannid_ciscallback(struct pcmcia_tuple *, void *);
        !           112:
        !           113: struct sm_pcmcia_product {
        !           114:        u_int16_t       spp_vendor;     /* vendor ID */
        !           115:        u_int16_t       spp_product;    /* product ID */
        !           116:        int             spp_expfunc;    /* expected function */
        !           117: } sm_pcmcia_prod[] = {
        !           118:        { PCMCIA_VENDOR_MEGAHERTZ2,     PCMCIA_PRODUCT_MEGAHERTZ2_XJACK,
        !           119:          0 },
        !           120:        { PCMCIA_VENDOR_MEGAHERTZ2,     PCMCIA_PRODUCT_MEGAHERTZ2_XJEM1144,
        !           121:          0 },
        !           122:        { PCMCIA_VENDOR_NEWMEDIA,       PCMCIA_PRODUCT_NEWMEDIA_BASICS,
        !           123:          0 },
        !           124:        { PCMCIA_VENDOR_SMC,            PCMCIA_PRODUCT_SMC_8020,
        !           125:          0 },
        !           126:        { PCMCIA_VENDOR_PSION,          PCMCIA_PRODUCT_PSION_GOLDCARD,
        !           127:          0 }
        !           128: };
        !           129:
        !           130: int
        !           131: sm_pcmcia_match(parent, match, aux)
        !           132:        struct device *parent;
        !           133:        void *match, *aux;
        !           134: {
        !           135:        struct pcmcia_attach_args *pa = aux;
        !           136:        int i;
        !           137:
        !           138:        for (i = 0; i < sizeof(sm_pcmcia_prod)/sizeof(sm_pcmcia_prod[0]); i++)
        !           139:                if (pa->manufacturer == sm_pcmcia_prod[i].spp_vendor &&
        !           140:                    pa->product == sm_pcmcia_prod[i].spp_product &&
        !           141:                    pa->pf->number == sm_pcmcia_prod[i].spp_expfunc)
        !           142:                        return (1);
        !           143:        return (0);
        !           144: }
        !           145:
        !           146: void
        !           147: sm_pcmcia_attach(parent, self, aux)
        !           148:        struct device *parent, *self;
        !           149:        void *aux;
        !           150: {
        !           151:        struct sm_pcmcia_softc *psc = (struct sm_pcmcia_softc *)self;
        !           152:        struct smc91cxx_softc *sc = &psc->sc_smc;
        !           153:        struct pcmcia_attach_args *pa = aux;
        !           154:        struct pcmcia_config_entry *cfe;
        !           155:        u_int8_t myla[ETHER_ADDR_LEN], *enaddr = NULL;
        !           156:        const char *intrstr;
        !           157:
        !           158:        psc->sc_pf = pa->pf;
        !           159:        cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head);
        !           160:
        !           161:        /* Enable the card. */
        !           162:        pcmcia_function_init(pa->pf, cfe);
        !           163:        if (pcmcia_function_enable(pa->pf)) {
        !           164:                printf(": function enable failed\n");
        !           165:                return;
        !           166:        }
        !           167:
        !           168:        /* XXX sanity check number of mem and i/o spaces */
        !           169:
        !           170:        /* Allocate and map i/o space for the card. */
        !           171:        if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
        !           172:            cfe->iospace[0].length, &psc->sc_pcioh)) {
        !           173:                printf(": can't allocate i/o space\n");
        !           174:                return;
        !           175:        }
        !           176:
        !           177:        sc->sc_bst = psc->sc_pcioh.iot;
        !           178:        sc->sc_bsh = psc->sc_pcioh.ioh;
        !           179:
        !           180: #ifdef notyet
        !           181:        sc->sc_enable = sm_pcmcia_enable;
        !           182:        sc->sc_disable = sm_pcmcia_disable;
        !           183: #endif
        !           184:        sc->sc_enabled = 1;
        !           185:
        !           186:        if (pcmcia_io_map(pa->pf, (cfe->flags & PCMCIA_CFE_IO16) ?
        !           187:            PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8, 0, cfe->iospace[0].length,
        !           188:            &psc->sc_pcioh, &psc->sc_io_window)) {
        !           189:                printf(": can't map i/o space\n");
        !           190:                return;
        !           191:        }
        !           192:
        !           193:        printf(" port 0x%lx/%lu", psc->sc_pcioh.addr,
        !           194:            (u_long)psc->sc_pcioh.size);
        !           195:
        !           196:        /*
        !           197:         * First try to get the Ethernet address from FUNCE/LANNID tuple.
        !           198:         */
        !           199:        if (sm_pcmcia_funce_enaddr(parent, myla))
        !           200:                enaddr = myla;
        !           201:
        !           202:        /*
        !           203:         * If that failed, try one of the CIS info strings.
        !           204:         */
        !           205:        if (enaddr == NULL) {
        !           206:                char *cisstr = NULL;
        !           207:
        !           208:                switch (pa->manufacturer) {
        !           209:                case PCMCIA_VENDOR_MEGAHERTZ2:
        !           210:                        cisstr = pa->pf->sc->card.cis1_info[3];
        !           211:                        break;
        !           212:                case PCMCIA_VENDOR_SMC:
        !           213:                        cisstr = pa->pf->sc->card.cis1_info[2];
        !           214:                        break;
        !           215:                }
        !           216:                if (cisstr != NULL && sm_pcmcia_ascii_enaddr(cisstr, myla))
        !           217:                        enaddr = myla;
        !           218:        }
        !           219:
        !           220:        if (enaddr == NULL)
        !           221:                printf(", unable to get Ethernet address\n");
        !           222:
        !           223:        psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET,
        !           224:            smc91cxx_intr, sc, sc->sc_dev.dv_xname);
        !           225:        intrstr = pcmcia_intr_string(psc->sc_pf, psc->sc_ih);
        !           226:        if (*intrstr)
        !           227:                printf(", %s", intrstr);
        !           228:
        !           229:        /* Perform generic initialization. */
        !           230:        smc91cxx_attach(sc, enaddr);
        !           231:
        !           232: #ifdef notyet
        !           233:        pcmcia_function_disable(pa->pf);
        !           234: #endif
        !           235: }
        !           236:
        !           237: int
        !           238: sm_pcmcia_detach(dev, flags)
        !           239:        struct device *dev;
        !           240:        int flags;
        !           241: {
        !           242:        struct sm_pcmcia_softc *psc = (struct sm_pcmcia_softc *)dev;
        !           243:        struct ifnet *ifp = &psc->sc_smc.sc_arpcom.ac_if;
        !           244:        int rv = 0;
        !           245:
        !           246:        pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
        !           247:        pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
        !           248:
        !           249:        ether_ifdetach(ifp);
        !           250:        if_detach(ifp);
        !           251:
        !           252:        return (rv);
        !           253: }
        !           254:
        !           255: int
        !           256: sm_pcmcia_activate(dev, act)
        !           257:        struct device *dev;
        !           258:        enum devact act;
        !           259: {
        !           260:        struct sm_pcmcia_softc *sc = (struct sm_pcmcia_softc *)dev;
        !           261:        struct ifnet *ifp = &sc->sc_smc.sc_arpcom.ac_if;
        !           262:        int s;
        !           263:
        !           264:        s = splnet();
        !           265:        switch (act) {
        !           266:        case DVACT_ACTIVATE:
        !           267:                pcmcia_function_enable(sc->sc_pf);
        !           268:                sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET,
        !           269:                    smc91cxx_intr, sc, sc->sc_smc.sc_dev.dv_xname);
        !           270:                smc91cxx_init(&sc->sc_smc);
        !           271:                break;
        !           272:
        !           273:        case DVACT_DEACTIVATE:
        !           274:                ifp->if_timer = 0;
        !           275:                if (ifp->if_flags & IFF_RUNNING)
        !           276:                        smc91cxx_stop(&sc->sc_smc);
        !           277:                pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
        !           278:                pcmcia_function_disable(sc->sc_pf);
        !           279:                break;
        !           280:        }
        !           281:        splx(s);
        !           282:        return (0);
        !           283: }
        !           284:
        !           285: int
        !           286: sm_pcmcia_ascii_enaddr(cisstr, myla)
        !           287:        const char *cisstr;
        !           288:        u_int8_t *myla;
        !           289: {
        !           290:        char enaddr_str[12];
        !           291:        int i, j;
        !           292:
        !           293:        if (strlen(cisstr) != 12) {
        !           294:                /* Bogus address! */
        !           295:                return (0);
        !           296:        }
        !           297:        bcopy(cisstr, enaddr_str, sizeof enaddr_str);
        !           298:        for (i = 0; i < 6; i++) {
        !           299:                for (j = 0; j < 2; j++) {
        !           300:                        /* Convert to upper case. */
        !           301:                        if (enaddr_str[(i * 2) + j] >= 'a' &&
        !           302:                            enaddr_str[(i * 2) + j] <= 'z')
        !           303:                                enaddr_str[(i * 2) + j] -= 'a' - 'A';
        !           304:
        !           305:                        /* Parse the digit. */
        !           306:                        if (enaddr_str[(i * 2) + j] >= '0' &&
        !           307:                            enaddr_str[(i * 2) + j] <= '9')
        !           308:                                myla[i] |= enaddr_str[(i * 2) + j]
        !           309:                                    - '0';
        !           310:                        else if (enaddr_str[(i * 2) + j] >= 'A' &&
        !           311:                                 enaddr_str[(i * 2) + j] <= 'F')
        !           312:                                myla[i] |= enaddr_str[(i * 2) + j]
        !           313:                                    - 'A' + 10;
        !           314:                        else {
        !           315:                                /* Bogus digit!! */
        !           316:                                return (0);
        !           317:                        }
        !           318:
        !           319:                        /* Compensate for ordering of digits. */
        !           320:                        if (j == 0)
        !           321:                                myla[i] <<= 4;
        !           322:                }
        !           323:        }
        !           324:
        !           325:        return (1);
        !           326: }
        !           327:
        !           328: int
        !           329: sm_pcmcia_funce_enaddr(parent, myla)
        !           330:        struct device *parent;
        !           331:        u_int8_t *myla;
        !           332: {
        !           333:
        !           334:        return (pcmcia_scan_cis(parent, sm_pcmcia_lannid_ciscallback, myla));
        !           335: }
        !           336:
        !           337: int
        !           338: sm_pcmcia_lannid_ciscallback(tuple, arg)
        !           339:        struct pcmcia_tuple *tuple;
        !           340:        void *arg;
        !           341: {
        !           342:        u_int8_t *myla = arg;
        !           343:        int i;
        !           344:
        !           345:        if (tuple->code == PCMCIA_CISTPL_FUNCE || tuple->code ==
        !           346:            PCMCIA_CISTPL_SPCL) {
        !           347:                /* subcode, length */
        !           348:                if (tuple->length < 2)
        !           349:                        return (0);
        !           350:
        !           351:                if ((pcmcia_tuple_read_1(tuple, 0) !=
        !           352:                     PCMCIA_TPLFE_TYPE_LAN_NID) ||
        !           353:                    (pcmcia_tuple_read_1(tuple, 1) != ETHER_ADDR_LEN))
        !           354:                        return (0);
        !           355:
        !           356:                for (i = 0; i < ETHER_ADDR_LEN; i++)
        !           357:                        myla[i] = pcmcia_tuple_read_1(tuple, i + 2);
        !           358:                return (1);
        !           359:        }
        !           360:        return (0);
        !           361: }
        !           362:
        !           363: int
        !           364: sm_pcmcia_enable(sc)
        !           365:        struct smc91cxx_softc *sc;
        !           366: {
        !           367:        struct sm_pcmcia_softc *psc = (struct sm_pcmcia_softc *)sc;
        !           368:
        !           369:        /* Establish the interrupt handler. */
        !           370:        psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, smc91cxx_intr,
        !           371:            sc, sc->sc_dev.dv_xname);
        !           372:        if (psc->sc_ih == NULL) {
        !           373:                printf("%s: couldn't establish interrupt handler\n",
        !           374:                    sc->sc_dev.dv_xname);
        !           375:                return (1);
        !           376:        }
        !           377:
        !           378:        return (pcmcia_function_enable(psc->sc_pf));
        !           379: }
        !           380:
        !           381: void
        !           382: sm_pcmcia_disable(sc)
        !           383:        struct smc91cxx_softc *sc;
        !           384: {
        !           385:        struct sm_pcmcia_softc *psc = (struct sm_pcmcia_softc *)sc;
        !           386:
        !           387:        pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
        !           388:        pcmcia_function_disable(psc->sc_pf);
        !           389: }

CVSweb