Annotation of sys/dev/pcmcia/if_ep_pcmcia.c, Revision 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