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

Annotation of sys/dev/pcmcia/if_ep_pcmcia.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: if_ep_pcmcia.c,v 1.36 2007/05/08 20:25:17 deraadt Exp $       */
                      2: /*     $NetBSD: if_ep_pcmcia.c,v 1.16 1998/08/17 23:20:40 thorpej Exp $  */
                      3:
                      4: /*-
                      5:  * Copyright (c) 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: /*
                     42:  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
                     43:  *
                     44:  * Redistribution and use in source and binary forms, with or without
                     45:  * modification, are permitted provided that the following conditions
                     46:  * are met:
                     47:  * 1. Redistributions of source code must retain the above copyright
                     48:  *    notice, this list of conditions and the following disclaimer.
                     49:  * 2. Redistributions in binary form must reproduce the above copyright
                     50:  *    notice, this list of conditions and the following disclaimer in the
                     51:  *    documentation and/or other materials provided with the distribution.
                     52:  * 3. All advertising materials mentioning features or use of this software
                     53:  *    must display the following acknowledgement:
                     54:  *     This product includes software developed by Marc Horowitz.
                     55:  * 4. The name of the author may not be used to endorse or promote products
                     56:  *    derived from this software without specific prior written permission.
                     57:  *
                     58:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     59:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     60:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     61:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     62:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     63:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     64:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     65:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     66:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     67:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     68:  */
                     69:
                     70: #include "bpfilter.h"
                     71:
                     72: #include <sys/param.h>
                     73: #include <sys/systm.h>
                     74: #include <sys/mbuf.h>
                     75: #include <sys/socket.h>
                     76: #include <sys/ioctl.h>
                     77: #include <sys/errno.h>
                     78: #include <sys/syslog.h>
                     79: #include <sys/selinfo.h>
                     80: #include <sys/timeout.h>
                     81: #include <sys/device.h>
                     82:
                     83: #include <net/if.h>
                     84: #include <net/if_dl.h>
                     85: #include <net/if_types.h>
                     86: #include <net/netisr.h>
                     87: #include <net/if_media.h>
                     88:
                     89: #ifdef INET
                     90: #include <netinet/in.h>
                     91: #include <netinet/in_systm.h>
                     92: #include <netinet/in_var.h>
                     93: #include <netinet/ip.h>
                     94: #include <netinet/if_ether.h>
                     95: #endif
                     96:
                     97: #if NBPFILTER > 0
                     98: #include <net/bpf.h>
                     99: #endif
                    100:
                    101: #include <machine/cpu.h>
                    102: #include <machine/bus.h>
                    103:
                    104: #include <dev/mii/mii.h>
                    105: #include <dev/mii/miivar.h>
                    106:
                    107: #include <dev/ic/elink3var.h>
                    108: #include <dev/ic/elink3reg.h>
                    109:
                    110: #include <dev/pcmcia/pcmciareg.h>
                    111: #include <dev/pcmcia/pcmciavar.h>
                    112: #include <dev/pcmcia/pcmciadevs.h>
                    113:
                    114: int    ep_pcmcia_match(struct device *, void *, void *);
                    115: void   ep_pcmcia_attach(struct device *, struct device *, void *);
                    116: int    ep_pcmcia_detach(struct device *, int);
                    117: int    ep_pcmcia_activate(struct device *, enum devact);
                    118:
                    119: int    ep_pcmcia_get_enaddr(struct pcmcia_tuple *, void *);
                    120: #ifdef notyet
                    121: int    ep_pcmcia_enable(struct ep_softc *);
                    122: void   ep_pcmcia_disable(struct ep_softc *);
                    123: void   ep_pcmcia_disable1(struct ep_softc *);
                    124: #endif
                    125:
                    126: int    ep_pcmcia_enable1(struct ep_softc *);
                    127:
                    128: struct ep_pcmcia_softc {
                    129:        struct ep_softc sc_ep;                  /* real "ep" softc */
                    130:
                    131:        /* PCMCIA-specific goo */
                    132:        struct pcmcia_io_handle sc_pcioh;       /* PCMCIA i/o space info */
                    133:        int sc_io_window;                       /* our i/o window */
                    134:        struct pcmcia_function *sc_pf;          /* our PCMCIA function */
                    135: };
                    136:
                    137: struct cfattach ep_pcmcia_ca = {
                    138:        sizeof(struct ep_pcmcia_softc), ep_pcmcia_match, ep_pcmcia_attach,
                    139:        ep_pcmcia_detach, ep_pcmcia_activate
                    140: };
                    141:
                    142: struct ep_pcmcia_product {
                    143:        u_int16_t       epp_product;    /* PCMCIA product ID */
                    144:        u_short         epp_chipset;    /* 3Com chipset used */
                    145:        int             epp_flags;      /* initial softc flags */
                    146:        int             epp_expfunc;    /* expected function */
                    147: } ep_pcmcia_prod[] = {
                    148:        { PCMCIA_PRODUCT_3COM_3C562,    EP_CHIPSET_3C509,
                    149:          0,                            0 },
                    150:
                    151:        { PCMCIA_PRODUCT_3COM_3C589,    EP_CHIPSET_3C509,
                    152:          0,                            0 },
                    153:
                    154:        { PCMCIA_PRODUCT_3COM_3CXEM556, EP_CHIPSET_3C509,
                    155:          0,                            0 },
                    156:
                    157:        { PCMCIA_PRODUCT_3COM_3CXEM556B,EP_CHIPSET_3C509,
                    158:          0,                            0 },
                    159:
                    160:        { PCMCIA_PRODUCT_3COM_3C1,      EP_CHIPSET_3C509,
                    161:          0,                            0 },
                    162:
                    163:        { PCMCIA_PRODUCT_3COM_3CCFEM556BI, EP_CHIPSET_ROADRUNNER,
                    164:          EP_FLAGS_MII,                 0 },
                    165:
                    166:        { PCMCIA_PRODUCT_3COM_3C574,    EP_CHIPSET_ROADRUNNER,
                    167:          EP_FLAGS_MII,                 0 }
                    168: };
                    169:
                    170: struct ep_pcmcia_product *ep_pcmcia_lookup(struct pcmcia_attach_args *);
                    171:
                    172: struct ep_pcmcia_product *
                    173: ep_pcmcia_lookup(pa)
                    174:        struct pcmcia_attach_args *pa;
                    175: {
                    176:        int i;
                    177:
                    178:        for (i = 0; i < sizeof(ep_pcmcia_prod)/sizeof(ep_pcmcia_prod[0]); i++)
                    179:                if (pa->product == ep_pcmcia_prod[i].epp_product &&
                    180:                    pa->pf->number == ep_pcmcia_prod[i].epp_expfunc)
                    181:                        return &ep_pcmcia_prod[i];
                    182:
                    183:        return (NULL);
                    184: }
                    185:
                    186: int
                    187: ep_pcmcia_match(parent, match, aux)
                    188:        struct device *parent;
                    189:        void *match, *aux;
                    190: {
                    191:        struct pcmcia_attach_args *pa = aux;
                    192:
                    193:        if (pa->manufacturer != PCMCIA_VENDOR_3COM)
                    194:                return (0);
                    195:
                    196:        if (ep_pcmcia_lookup(pa) != NULL)
                    197:                return (1);
                    198:
                    199:        return (0);
                    200: }
                    201:
                    202: #ifdef notdef
                    203: int
                    204: ep_pcmcia_enable(sc)
                    205:        struct ep_softc *sc;
                    206: {
                    207:        struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
                    208:        struct pcmcia_function *pf = psc->sc_pf;
                    209:
                    210:        /* establish the interrupt. */
                    211:        sc->sc_ih = pcmcia_intr_establish(pf, IPL_NET, epintr,
                    212:            sc, sc->sc_dev.dv_xname);
                    213:        if (sc->sc_ih == NULL) {
                    214:                printf("%s: couldn't establish interrupt\n",
                    215:                    sc->sc_dev.dv_xname);
                    216:                return (1);
                    217:        }
                    218:
                    219:        return (ep_pcmcia_enable1(sc));
                    220: }
                    221: #endif
                    222:
                    223: int
                    224: ep_pcmcia_enable1(sc)
                    225:        struct ep_softc *sc;
                    226: {
                    227:        struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
                    228:        struct pcmcia_function *pf = psc->sc_pf;
                    229:        int ret;
                    230:
                    231:        if ((ret = pcmcia_function_enable(pf)))
                    232:                return (ret);
                    233:
                    234:        if ((psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3C562) ||
                    235:            (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556) ||
                    236:            (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556B)) {
                    237:                int reg;
                    238:
                    239:                /* turn off the serial-disable bit */
                    240:
                    241:                reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
                    242:                if (reg & 0x08) {
                    243:                        reg &= ~0x08;
                    244:                        pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
                    245:                }
                    246:
                    247:        }
                    248:
                    249:        return (ret);
                    250: }
                    251:
                    252: #ifdef notyet
                    253: void
                    254: ep_pcmcia_disable(sc)
                    255:        struct ep_softc *sc;
                    256: {
                    257:        struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
                    258:
                    259:        pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih);
                    260:        ep_pcmcia_disable1(sc);
                    261: }
                    262:
                    263: void
                    264: ep_pcmcia_disable1(sc)
                    265:        struct ep_softc *sc;
                    266: {
                    267:        struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
                    268:
                    269:        pcmcia_function_disable(psc->sc_pf);
                    270: }
                    271: #endif
                    272:
                    273: void
                    274: ep_pcmcia_attach(parent, self, aux)
                    275:        struct device  *parent, *self;
                    276:        void           *aux;
                    277: {
                    278:        struct ep_pcmcia_softc *psc = (void *) self;
                    279:        struct ep_softc *sc = &psc->sc_ep;
                    280:        struct pcmcia_attach_args *pa = aux;
                    281:        struct pcmcia_config_entry *cfe;
                    282:        struct ep_pcmcia_product *epp;
                    283:        u_int8_t myla[ETHER_ADDR_LEN];
                    284:        u_int8_t *enaddr = NULL;
                    285:        const char *intrstr;
                    286:        int i;
                    287:
                    288:        psc->sc_pf = pa->pf;
                    289:        cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head);
                    290:
                    291:        /* Enable the card. */
                    292:        pcmcia_function_init(pa->pf, cfe);
                    293:        if (ep_pcmcia_enable1(sc))
                    294:                printf(": function enable failed\n");
                    295:
                    296: #ifdef notyet
                    297:        sc->enabled = 1;
                    298: #endif
                    299:
                    300:        if (cfe->num_memspace != 0)
                    301:                printf(": unexpected number of memory spaces %d should be 0\n",
                    302:                    cfe->num_memspace);
                    303:
                    304:        if (cfe->num_iospace != 1)
                    305:                printf(": unexpected number of I/O spaces %d should be 1\n",
                    306:                    cfe->num_iospace);
                    307:
                    308:        if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
                    309:                bus_addr_t maxaddr = (pa->pf->sc->iobase + pa->pf->sc->iosize);
                    310:
                    311:                for (i = pa->pf->sc->iobase; i < maxaddr; i += 0x10) {
                    312:                        /*
                    313:                         * the 3c562 can only use 0x??00-0x??7f
                    314:                         * according to the Linux driver
                    315:                         */
                    316:                        if (i & 0x80)
                    317:                                continue;
                    318:                        if (pcmcia_io_alloc(pa->pf, i, cfe->iospace[0].length,
                    319:                            cfe->iospace[0].length, &psc->sc_pcioh) == 0)
                    320:                                break;
                    321:                }
                    322:                if (i >= maxaddr) {
                    323:                        printf(": can't allocate i/o space\n");
                    324:                        return;
                    325:                }
                    326:        } else {
                    327:                if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
                    328:                    cfe->iospace[0].length, &psc->sc_pcioh))
                    329:                        printf(": can't allocate i/o space\n");
                    330:        }
                    331:
                    332:        sc->sc_iot = psc->sc_pcioh.iot;
                    333:        sc->sc_ioh = psc->sc_pcioh.ioh;
                    334:
                    335:        if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
                    336:            PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, cfe->iospace[0].length,
                    337:            &psc->sc_pcioh, &psc->sc_io_window)) {
                    338:                printf(": can't map i/o space\n");
                    339:                return;
                    340:        }
                    341:
                    342:        printf(" port 0x%lx/%d", psc->sc_pcioh.addr, psc->sc_pcioh.size);
                    343:
                    344:        switch (pa->product) {
                    345:        case PCMCIA_PRODUCT_3COM_3C562:
                    346:                /*
                    347:                 * 3c562a-c use this; 3c562d does it in the regular way.
                    348:                 * we might want to check the revision and produce a warning
                    349:                 * in the future.
                    350:                 */
                    351:                /* FALLTHROUGH */
                    352:        case PCMCIA_PRODUCT_3COM_3C574:
                    353:        case PCMCIA_PRODUCT_3COM_3CCFEM556BI:
                    354:                /*
                    355:                 * Apparently, some 3c574s do it this way, as well.
                    356:                 */
                    357:                if (pcmcia_scan_cis(parent, ep_pcmcia_get_enaddr, myla))
                    358:                        enaddr = myla;
                    359:                break;
                    360:        }
                    361:
                    362:        sc->bustype = EP_BUS_PCMCIA;
                    363:
                    364:        epp = ep_pcmcia_lookup(pa);
                    365:        if (epp == NULL)
                    366:                panic("ep_pcmcia_attach: impossible");
                    367:
                    368:        sc->ep_flags = epp->epp_flags;
                    369:
                    370: #ifdef notyet
                    371:        sc->enable = ep_pcmcia_enable;
                    372:        sc->disable = ep_pcmcia_disable;
                    373: #endif
                    374:
                    375:        /* establish the interrupt. */
                    376:        sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, epintr, sc,
                    377:            sc->sc_dev.dv_xname);
                    378:        intrstr = pcmcia_intr_string(psc->sc_pf, sc->sc_ih);
                    379:        if (*intrstr)
                    380:                printf(", %s", intrstr);
                    381:
                    382:        printf(":");
                    383:
                    384:        epconfig(sc, epp->epp_chipset, enaddr);
                    385:
                    386: #ifdef notyet
                    387:        sc->enabled = 0;
                    388:
                    389:        ep_pcmcia_disable1(sc);
                    390: #endif
                    391: }
                    392:
                    393: int
                    394: ep_pcmcia_detach(dev, flags)
                    395:        struct device *dev;
                    396:        int flags;
                    397: {
                    398:        int rv;
                    399:        struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *)dev;
                    400:
                    401:        if ((rv = ep_detach(dev)) != 0)
                    402:                return (rv);
                    403:
                    404:        pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
                    405:        pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
                    406:
                    407:        return (0);
                    408: }
                    409:
                    410: int
                    411: ep_pcmcia_activate(dev, act)
                    412:        struct device *dev;
                    413:        enum devact act;
                    414: {
                    415:        struct ep_pcmcia_softc *sc = (struct ep_pcmcia_softc *)dev;
                    416:        struct ep_softc *esc = &sc->sc_ep;
                    417:        struct ifnet *ifp = &esc->sc_arpcom.ac_if;
                    418:        int s;
                    419:
                    420:        s = splnet();
                    421:        switch (act) {
                    422:        case DVACT_ACTIVATE:
                    423:                pcmcia_function_enable(sc->sc_pf);
                    424:                sc->sc_ep.sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET,
                    425:                    epintr, sc, esc->sc_dev.dv_xname);
                    426:                epinit(esc);
                    427:                break;
                    428:
                    429:        case DVACT_DEACTIVATE:
                    430:                ifp->if_timer = 0;
                    431:                if (ifp->if_flags & IFF_RUNNING)
                    432:                        epstop(esc);
                    433:                pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ep.sc_ih);
                    434:                pcmcia_function_disable(sc->sc_pf);
                    435:                break;
                    436:        }
                    437:        splx(s);
                    438:        return (0);
                    439: }
                    440:
                    441: int
                    442: ep_pcmcia_get_enaddr(tuple, arg)
                    443:        struct pcmcia_tuple *tuple;
                    444:        void *arg;
                    445: {
                    446:        u_int8_t *myla = arg;
                    447:        int i;
                    448:
                    449:        /* this is 3c562a-c magic */
                    450:        if (tuple->code == 0x88) {
                    451:                if (tuple->length < ETHER_ADDR_LEN)
                    452:                        return (0);
                    453:
                    454:                for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
                    455:                        myla[i] = pcmcia_tuple_read_1(tuple, i + 1);
                    456:                        myla[i + 1] = pcmcia_tuple_read_1(tuple, i);
                    457:                }
                    458:
                    459:                return (1);
                    460:        }
                    461:        return (0);
                    462: }

CVSweb