[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

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