Home | History | Annotate | Line # | Download | only in pcmcia
xirc.c revision 1.1
      1 /*	$NetBSD: xirc.c,v 1.1 2004/08/08 05:56:08 mycroft Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999, 2000, 2004 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  * NASA Ames Research Center and by Charles M. Hannum.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *	This product includes software developed by the NetBSD
     22  *	Foundation, Inc. and its contributors.
     23  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  *    contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  * POSSIBILITY OF SUCH DAMAGE.
     38  */
     39 
     40 #include <sys/cdefs.h>
     41 __KERNEL_RCSID(0, "$NetBSD: xirc.c,v 1.1 2004/08/08 05:56:08 mycroft Exp $");
     42 
     43 #include "opt_inet.h"
     44 #include "opt_ns.h"
     45 #include "bpfilter.h"
     46 
     47 #include <sys/param.h>
     48 #include <sys/systm.h>
     49 #include <sys/mbuf.h>
     50 #include <sys/socket.h>
     51 #include <sys/ioctl.h>
     52 #include <sys/errno.h>
     53 #include <sys/syslog.h>
     54 #include <sys/select.h>
     55 #include <sys/tty.h>
     56 #include <sys/device.h>
     57 
     58 #include <net/if.h>
     59 #include <net/if_dl.h>
     60 #include <net/if_ether.h>
     61 #include <net/if_media.h>
     62 
     63 #ifdef INET
     64 #include <netinet/in.h>
     65 #include <netinet/in_systm.h>
     66 #include <netinet/in_var.h>
     67 #include <netinet/ip.h>
     68 #include <netinet/if_inarp.h>
     69 #endif
     70 
     71 #ifdef NS
     72 #include <netns/ns.h>
     73 #include <netns/ns_if.h>
     74 #endif
     75 
     76 #if NBPFILTER > 0
     77 #include <net/bpf.h>
     78 #include <net/bpfdesc.h>
     79 #endif
     80 
     81 #include <machine/intr.h>
     82 #include <machine/bus.h>
     83 
     84 #include <dev/pcmcia/pcmciareg.h>
     85 #include <dev/pcmcia/pcmciavar.h>
     86 #include <dev/pcmcia/pcmciadevs.h>
     87 
     88 #include "xirc.h"
     89 
     90 #if NCOM_XIRC > 0
     91 #include <dev/ic/comreg.h>
     92 #include <dev/ic/comvar.h>
     93 #endif
     94 
     95 #if NXI_XIRC > 0
     96 #include <dev/mii/mii.h>
     97 #include <dev/mii/miivar.h>
     98 
     99 #include <dev/pcmcia/if_xivar.h>
    100 #endif
    101 #include <dev/pcmcia/if_xireg.h>
    102 
    103 struct xirc_softc {
    104 	struct device sc_dev;		/* generic device glue */
    105 
    106 	struct pcmcia_function *sc_pf;	/* our PCMCIA function */
    107 	void *sc_ih;			/* interrupt handle */
    108 
    109 	u_int16_t sc_id;
    110 	int sc_chipset;
    111 
    112 	/*
    113 	 * Data for the Modem portion.
    114 	 */
    115 	struct device *sc_modem;
    116 	struct pcmcia_io_handle sc_modem_pcioh;
    117 	int sc_modem_io_window;
    118 
    119 	/*
    120 	 * Data for the Ethernet portion.
    121 	 */
    122 	struct device *sc_ethernet;
    123 	struct pcmcia_io_handle sc_ethernet_pcioh;
    124 	int sc_ethernet_io_window;
    125 
    126 	int sc_flags;
    127 #define	XIRC_MODEM_MAPPED	0x01
    128 #define	XIRC_ETHERNET_MAPPED	0x02
    129 #define	XIRC_MODEM_ENABLED	0x04
    130 #define	XIRC_ETHERNET_ENABLED	0x08
    131 #define	XIRC_MODEM_ALLOCED	0x10
    132 #define	XIRC_ETHERNET_ALLOCED	0x20
    133 };
    134 
    135 int	xirc_match __P((struct device *, struct cfdata *, void *));
    136 void	xirc_attach __P((struct device *, struct device *, void *));
    137 int	xirc_detach __P((struct device *, int));
    138 int	xirc_activate __P((struct device *, enum devact));
    139 
    140 CFATTACH_DECL(xirc, sizeof(struct xirc_softc),
    141     xirc_match, xirc_attach, xirc_detach, xirc_activate);
    142 
    143 int	xirc_print __P((void *, const char *));
    144 
    145 int	xirc_manfid_ciscallback __P((struct pcmcia_tuple *, void *));
    146 struct pcmcia_config_entry *
    147 	xirc_mohawk_alloc __P((struct xirc_softc *));
    148 struct pcmcia_config_entry *
    149 	xirc_dingo_alloc_modem __P((struct xirc_softc *));
    150 struct pcmcia_config_entry *
    151 	xirc_dingo_alloc_ethernet __P((struct xirc_softc *));
    152 
    153 int	xirc_enable __P((struct xirc_softc *, int));
    154 void	xirc_disable __P((struct xirc_softc *, int));
    155 
    156 int	xirc_intr __P((void *));
    157 
    158 int
    159 xirc_match(parent, match, aux)
    160 	struct device *parent;
    161 	struct cfdata *match;
    162 	void *aux;
    163 {
    164 	struct pcmcia_attach_args *pa = aux;
    165 
    166 	/* XXX Toshiba, Accton */
    167 
    168 	if (pa->manufacturer == PCMCIA_VENDOR_COMPAQ2 &&
    169 	    pa->product == PCMCIA_PRODUCT_COMPAQ2_CPQ_10_100)
    170 		return (1);
    171 
    172 	if (pa->manufacturer == PCMCIA_VENDOR_INTEL &&
    173 	    pa->product == PCMCIA_PRODUCT_INTEL_EEPRO100)
    174 		return (1);
    175 
    176 	if (pa->manufacturer == PCMCIA_VENDOR_XIRCOM &&
    177 	    (pa->product & ((XIMEDIA_ETHER | XIMEDIA_MODEM) << 8)) != 0)
    178 		return (2);
    179 
    180 	return (0);
    181 }
    182 
    183 void
    184 xirc_attach(parent, self, aux)
    185 	struct device *parent, *self;
    186 	void *aux;
    187 {
    188 	struct xirc_softc *sc = (void *)self;
    189 	struct pcmcia_attach_args *pa = aux;
    190 	struct pcmcia_config_entry *cfe;
    191 	int rv;
    192 
    193 	aprint_normal("\n");
    194 
    195 	sc->sc_pf = pa->pf;
    196 
    197 	pcmcia_socket_enable(parent);
    198 	rv = pcmcia_scan_cis(parent, xirc_manfid_ciscallback, &sc->sc_id);
    199 	pcmcia_socket_disable(parent);
    200 	if (!rv) {
    201 		aprint_error("%s: failed to find ID\n", self->dv_xname);
    202 		return;
    203 	}
    204 
    205 	switch (sc->sc_id & 0x100f) {
    206 	case 0x0001:	/* CE */
    207 	case 0x0002:	/* CE2 */
    208 		sc->sc_chipset = XI_CHIPSET_SCIPPER;
    209 		break;
    210 	case 0x0003:	/* CE3 */
    211 		sc->sc_chipset = XI_CHIPSET_MOHAWK;
    212 		break;
    213 	case 0x1001:
    214 	case 0x1002:
    215 	case 0x1003:
    216 	case 0x1004:
    217 		sc->sc_chipset = XI_CHIPSET_SCIPPER;
    218 		break;
    219 	case 0x1005:
    220 		sc->sc_chipset = XI_CHIPSET_MOHAWK;
    221 		break;
    222 	case 0x1006:
    223 	case 0x1007:
    224 		sc->sc_chipset = XI_CHIPSET_DINGO;
    225 		break;
    226 	default:
    227 		aprint_error("%s: unknown ID %04x\n", self->dv_xname,
    228 		    sc->sc_id);
    229 		return;
    230 	}
    231 
    232 	aprint_normal("%s: id=%04x\n", self->dv_xname, sc->sc_id);
    233 
    234 	if (sc->sc_id & (XIMEDIA_MODEM << 8)) {
    235 		if (sc->sc_chipset >= XI_CHIPSET_DINGO) {
    236 			cfe = xirc_dingo_alloc_modem(sc);
    237 			if (!cfe) {
    238 				aprint_error("%s: failed to allocate I/O for modem\n",
    239 				    self->dv_xname);
    240 				goto fail;
    241 			}
    242 			if (sc->sc_id & (XIMEDIA_ETHER << 8)) {
    243 				if (!xirc_dingo_alloc_ethernet(sc))
    244 					aprint_error("%s: failed to allocate I/O for ethernet\n",
    245 					    self->dv_xname);
    246 			}
    247 		} else {
    248 			cfe = xirc_mohawk_alloc(sc);
    249 			if (!cfe) {
    250 				aprint_error("%s: failed to allocate I/O\n",
    251 				    self->dv_xname);
    252 				goto fail;
    253 			}
    254 		}
    255 	} else {
    256 		cfe = xirc_dingo_alloc_ethernet(sc);
    257 		if (!cfe)
    258 			aprint_error("%s: failed to allocate I/O for ethernet\n",
    259 			    self->dv_xname);
    260 	}
    261 
    262 	/* Enable the card. */
    263 	pcmcia_function_init(pa->pf, cfe);
    264 	if (pcmcia_function_enable(pa->pf)) {
    265 		aprint_error("%s: function enable failed\n", self->dv_xname);
    266 		goto fail;
    267 	}
    268 
    269 	if (sc->sc_id & (XIMEDIA_MODEM << 8))
    270 		sc->sc_modem = config_found(self, "com", xirc_print);
    271 	if (sc->sc_id & (XIMEDIA_ETHER << 8))
    272 		sc->sc_ethernet = config_found(self, "xi", xirc_print);
    273 
    274 	pcmcia_function_disable(pa->pf);
    275 	return;
    276 
    277 fail:
    278 	/* Free our i/o spaces. */
    279 	if (sc->sc_flags & XIRC_ETHERNET_ALLOCED)
    280 		pcmcia_io_free(sc->sc_pf, &sc->sc_ethernet_pcioh);
    281 	if (sc->sc_flags & XIRC_MODEM_ALLOCED)
    282 		pcmcia_io_free(sc->sc_pf, &sc->sc_modem_pcioh);
    283 	sc->sc_flags = 0;
    284 }
    285 
    286 int
    287 xirc_manfid_ciscallback(tuple, arg)
    288 	struct pcmcia_tuple *tuple;
    289 	void *arg;
    290 {
    291 	u_int16_t *id = arg;
    292 
    293 	if (tuple->code != PCMCIA_CISTPL_MANFID)
    294 		return (0);
    295 
    296 	if (tuple->length < 5)
    297 		return (0);
    298 
    299 	*id = (pcmcia_tuple_read_1(tuple, 3) << 8) |
    300 	      pcmcia_tuple_read_1(tuple, 4);
    301 	return (1);
    302 }
    303 
    304 struct pcmcia_config_entry *
    305 xirc_mohawk_alloc(sc)
    306 	struct xirc_softc *sc;
    307 {
    308 	struct pcmcia_config_entry *cfe;
    309 
    310 	SIMPLEQ_FOREACH(cfe, &sc->sc_pf->cfe_head, cfe_list) {
    311 		if (cfe->num_iospace != 1)
    312 			continue;
    313 
    314 		if (pcmcia_io_alloc(sc->sc_pf, cfe->iospace[0].start,
    315 		    cfe->iospace[0].length, cfe->iospace[0].length,
    316 		    &sc->sc_modem_pcioh))
    317 			continue;
    318 
    319 		if (pcmcia_io_alloc(sc->sc_pf, cfe->iospace[0].start+8,
    320 		    XI_IOSIZE, XI_IOSIZE, &sc->sc_ethernet_pcioh) &&
    321 		    pcmcia_io_alloc(sc->sc_pf, cfe->iospace[0].start-24,
    322 		    XI_IOSIZE, XI_IOSIZE, &sc->sc_ethernet_pcioh)) {
    323 			pcmcia_io_free(sc->sc_pf, &sc->sc_modem_pcioh);
    324 			continue;
    325 		}
    326 
    327 		/* Found one! */
    328 		sc->sc_flags |= XIRC_MODEM_ALLOCED;
    329 		sc->sc_flags |= XIRC_ETHERNET_ALLOCED;
    330 		return (cfe);
    331 	}
    332 
    333 	return (0);
    334 }
    335 
    336 struct pcmcia_config_entry *
    337 xirc_dingo_alloc_modem(sc)
    338 	struct xirc_softc *sc;
    339 {
    340 	struct pcmcia_config_entry *cfe;
    341 
    342 	SIMPLEQ_FOREACH(cfe, &sc->sc_pf->cfe_head, cfe_list) {
    343 		if (cfe->num_iospace != 1)
    344 			continue;
    345 
    346 		if (pcmcia_io_alloc(sc->sc_pf, cfe->iospace[0].start,
    347 		    cfe->iospace[0].length, cfe->iospace[0].length,
    348 		    &sc->sc_modem_pcioh))
    349 			continue;
    350 
    351 		/* Found one! */
    352 		sc->sc_flags |= XIRC_MODEM_ALLOCED;
    353 		return (cfe);
    354 	}
    355 
    356 	return (0);
    357 }
    358 
    359 struct pcmcia_config_entry *
    360 xirc_dingo_alloc_ethernet(sc)
    361 	struct xirc_softc *sc;
    362 {
    363 	struct pcmcia_config_entry *cfe;
    364 	bus_addr_t port;
    365 
    366 	for (port = 0x300; port < 0x400; port += XI_IOSIZE) {
    367 		if (pcmcia_io_alloc(sc->sc_pf, port,
    368 		    XI_IOSIZE, XI_IOSIZE, &sc->sc_ethernet_pcioh))
    369 			continue;
    370 
    371 		/* Found one for the ethernet! */
    372 		sc->sc_flags |= XIRC_ETHERNET_ALLOCED;
    373 		cfe = SIMPLEQ_FIRST(&sc->sc_pf->cfe_head);
    374 		return (cfe);
    375 	}
    376 
    377 	return (0);
    378 }
    379 
    380 int
    381 xirc_print(aux, pnp)
    382 	void *aux;
    383 	const char *pnp;
    384 {
    385 	const char *name = aux;
    386 
    387 	if (pnp)
    388 		aprint_normal("%s at %s(*)",  name, pnp);
    389 
    390 	return (UNCONF);
    391 }
    392 
    393 int
    394 xirc_detach(self, flags)
    395 	struct device *self;
    396 	int flags;
    397 {
    398 	struct xirc_softc *sc = (void *)self;
    399 	int rv;
    400 
    401 	if (sc->sc_ethernet != NULL) {
    402 		rv = config_detach(sc->sc_ethernet, flags);
    403 		if (rv != 0)
    404 			return (rv);
    405 		sc->sc_ethernet = NULL;
    406 	}
    407 
    408 	if (sc->sc_modem != NULL) {
    409 		rv = config_detach(sc->sc_modem, flags);
    410 		if (rv != 0)
    411 			return (rv);
    412 #ifdef not_necessary
    413 		sc->sc_modem = NULL;
    414 #endif
    415 	}
    416 
    417 	/* Unmap our i/o windows. */
    418 	if (sc->sc_flags & XIRC_ETHERNET_MAPPED)
    419 		pcmcia_io_unmap(sc->sc_pf, sc->sc_ethernet_io_window);
    420 	if (sc->sc_flags & XIRC_MODEM_MAPPED)
    421 		pcmcia_io_unmap(sc->sc_pf, sc->sc_modem_io_window);
    422 
    423 	/* Free our i/o spaces. */
    424 	if (sc->sc_flags & XIRC_ETHERNET_ALLOCED)
    425 		pcmcia_io_free(sc->sc_pf, &sc->sc_ethernet_pcioh);
    426 	if (sc->sc_flags & XIRC_MODEM_ALLOCED)
    427 		pcmcia_io_free(sc->sc_pf, &sc->sc_modem_pcioh);
    428 	sc->sc_flags = 0;
    429 
    430 	return (0);
    431 }
    432 
    433 int
    434 xirc_activate(self, act)
    435 	struct device *self;
    436 	enum devact act;
    437 {
    438 	struct xirc_softc *sc = (void *)self;
    439 	int s, rv = 0;
    440 
    441 	s = splhigh();
    442 	switch (act) {
    443 	case DVACT_ACTIVATE:
    444 		rv = EOPNOTSUPP;
    445 		break;
    446 
    447 	case DVACT_DEACTIVATE:
    448 		if (sc->sc_ethernet != NULL) {
    449 			rv = config_deactivate(sc->sc_ethernet);
    450 			if (rv != 0)
    451 				goto out;
    452 		}
    453 
    454 		if (sc->sc_modem != NULL) {
    455 			rv = config_deactivate(sc->sc_modem);
    456 			if (rv != 0)
    457 				goto out;
    458 		}
    459 		break;
    460 	}
    461  out:
    462 	splx(s);
    463 	return (rv);
    464 }
    465 
    466 int
    467 xirc_intr(arg)
    468 	void *arg;
    469 {
    470 	struct xirc_softc *sc = arg;
    471 	int rval = 0;
    472 
    473 #if NCOM_XIRC > 0
    474 	if (sc->sc_modem != NULL &&
    475 	    (sc->sc_flags & XIRC_MODEM_ENABLED) != 0)
    476 		rval |= comintr(sc->sc_modem);
    477 #endif
    478 
    479 #if NXI_XIRC > 0
    480 	if (sc->sc_ethernet != NULL &&
    481 	    (sc->sc_flags & XIRC_ETHERNET_ENABLED) != 0)
    482 		rval |= xi_intr(sc->sc_ethernet);
    483 #endif
    484 
    485 	return (rval);
    486 }
    487 
    488 int
    489 xirc_enable(sc, flag)
    490 	struct xirc_softc *sc;
    491 	int flag;
    492 {
    493 
    494 	if (sc->sc_flags & flag) {
    495 		printf("%s: %s already enabled\n", sc->sc_dev.dv_xname,
    496 		    (flag & XIRC_MODEM_ENABLED) ? "modem" : "ethernet");
    497 		panic("xirc_enable");
    498 	}
    499 
    500 	if ((sc->sc_flags & (XIRC_MODEM_ENABLED|XIRC_ETHERNET_ENABLED)) != 0) {
    501 		sc->sc_flags |= flag;
    502 		return (0);
    503 	}
    504 
    505 	/*
    506 	 * Establish our interrupt handler.
    507 	 *
    508 	 * XXX Note, we establish this at IPL_NET.  This is suboptimal
    509 	 * XXX the Modem portion, but is necessary to make the Ethernet
    510 	 * XXX portion have the correct interrupt level semantics.
    511 	 *
    512 	 * XXX Eventually we should use the `enabled' bits in the
    513 	 * XXX flags word to determine which level we should be at.
    514 	 */
    515 	sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET,
    516 	    xirc_intr, sc);
    517 	if (sc->sc_ih == NULL) {
    518 		printf("%s: unable to establish interrupt\n",
    519 		    sc->sc_dev.dv_xname);
    520 		return (1);
    521 	}
    522 
    523 	if (pcmcia_function_enable(sc->sc_pf)) {
    524 		pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
    525 		return (1);
    526 	}
    527 
    528 	sc->sc_flags |= flag;
    529 	return (0);
    530 }
    531 
    532 void
    533 xirc_disable(sc, flag)
    534 	struct xirc_softc *sc;
    535 	int flag;
    536 {
    537 
    538 	if ((sc->sc_flags & flag) == 0) {
    539 		printf("%s: %s already disabled\n", sc->sc_dev.dv_xname,
    540 		    (flag & XIRC_MODEM_ENABLED) ? "modem" : "ethernet");
    541 		panic("xirc_disable");
    542 	}
    543 
    544 	sc->sc_flags &= ~flag;
    545 	if ((sc->sc_flags & (XIRC_MODEM_ENABLED|XIRC_ETHERNET_ENABLED)) != 0)
    546 		return;
    547 
    548 	pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
    549 	pcmcia_function_disable(sc->sc_pf);
    550 }
    551 
    552 /****** Here begins the com attachment code. ******/
    553 
    554 #if NCOM_XIRC > 0
    555 int	com_xirc_match __P((struct device *, struct cfdata *, void *));
    556 void	com_xirc_attach __P((struct device *, struct device *, void *));
    557 int	com_xirc_detach __P((struct device *, int));
    558 
    559 /* No xirc-specific goo in the softc; it's all in the parent. */
    560 CFATTACH_DECL(com_xirc, sizeof(struct com_softc),
    561     com_xirc_match, com_xirc_attach, com_detach, com_activate);
    562 
    563 int	com_xirc_enable __P((struct com_softc *));
    564 void	com_xirc_disable __P((struct com_softc *));
    565 
    566 int
    567 com_xirc_match(parent, match, aux)
    568 	struct device *parent;
    569 	struct cfdata *match;
    570 	void *aux;
    571 {
    572 	extern struct cfdriver com_cd;
    573 	const char *name = aux;
    574 
    575 	if (strcmp(name, com_cd.cd_name) == 0)
    576 		return (1);
    577 
    578 	return (0);
    579 }
    580 
    581 void
    582 com_xirc_attach(parent, self, aux)
    583 	struct device *parent, *self;
    584 	void *aux;
    585 {
    586 	struct com_softc *sc = (void *)self;
    587 	struct xirc_softc *msc = (void *)parent;
    588 
    589 	aprint_normal("\n");
    590 
    591 	if (pcmcia_io_map(msc->sc_pf, PCMCIA_WIDTH_IO8, 0,
    592 	    msc->sc_modem_pcioh.size, &msc->sc_modem_pcioh,
    593 	    &msc->sc_modem_io_window)) {
    594 		aprint_error("%s: unable to map I/O space\n", self->dv_xname);
    595 		return;
    596 	}
    597 	msc->sc_flags |= XIRC_MODEM_MAPPED;
    598 
    599 	sc->sc_iot = msc->sc_modem_pcioh.iot;
    600 	sc->sc_ioh = msc->sc_modem_pcioh.ioh;
    601 
    602 	sc->enabled = 1;
    603 
    604 	sc->sc_iobase = -1;
    605 	sc->sc_frequency = COM_FREQ;
    606 
    607 	sc->enable = com_xirc_enable;
    608 	sc->disable = com_xirc_disable;
    609 
    610 	aprint_normal("%s", self->dv_xname);
    611 
    612 	com_attach_subr(sc);
    613 
    614 	sc->enabled = 0;
    615 }
    616 
    617 int
    618 com_xirc_enable(sc)
    619 	struct com_softc *sc;
    620 {
    621 
    622 	return (xirc_enable((struct xirc_softc *)sc->sc_dev.dv_parent,
    623 	    XIRC_MODEM_ENABLED));
    624 }
    625 
    626 void
    627 com_xirc_disable(sc)
    628 	struct com_softc *sc;
    629 {
    630 
    631 	xirc_disable((struct xirc_softc *)sc->sc_dev.dv_parent,
    632 	    XIRC_MODEM_ENABLED);
    633 }
    634 
    635 #endif /* NCOM_XIRC > 0 */
    636 
    637 /****** Here begins the xi attachment code. ******/
    638 
    639 #if NXI_XIRC > 0
    640 int	xi_xirc_match __P((struct device *, struct cfdata *, void *));
    641 void	xi_xirc_attach __P((struct device *, struct device *, void *));
    642 
    643 /* No xirc-specific goo in the softc; it's all in the parent. */
    644 CFATTACH_DECL(xi_xirc, sizeof(struct xi_softc),
    645     xi_xirc_match, xi_xirc_attach, xi_detach, xi_activate);
    646 
    647 int	xi_xirc_enable __P((struct xi_softc *));
    648 void	xi_xirc_disable __P((struct xi_softc *));
    649 int	xi_xirc_lan_nid_ciscallback __P((struct pcmcia_tuple *, void *));
    650 
    651 int
    652 xi_xirc_match(parent, match, aux)
    653 	struct device *parent;
    654 	struct cfdata *match;
    655 	void *aux;
    656 {
    657 	extern struct cfdriver xi_cd;
    658 	const char *name = aux;
    659 
    660 	if (strcmp(name, xi_cd.cd_name) == 0)
    661 		return (1);
    662 
    663 	return (0);
    664 }
    665 
    666 void
    667 xi_xirc_attach(parent, self, aux)
    668 	struct device *parent, *self;
    669 	void *aux;
    670 {
    671 	struct xi_softc *sc = (void *)self;
    672 	struct xirc_softc *msc = (void *)parent;
    673 	u_int8_t myla[ETHER_ADDR_LEN];
    674 
    675 	aprint_normal("\n");
    676 
    677 	if (pcmcia_io_map(msc->sc_pf, PCMCIA_WIDTH_AUTO, 0,
    678 	    msc->sc_ethernet_pcioh.size, &msc->sc_ethernet_pcioh,
    679 	    &msc->sc_ethernet_io_window)) {
    680 		aprint_error("%s: unable to map I/O space\n", self->dv_xname);
    681 		return;
    682 	}
    683 	msc->sc_flags |= XIRC_ETHERNET_MAPPED;
    684 
    685 	sc->sc_bst = msc->sc_ethernet_pcioh.iot;
    686 	sc->sc_bsh = msc->sc_ethernet_pcioh.ioh;
    687 
    688 	sc->sc_chipset = msc->sc_chipset;
    689 
    690 	sc->sc_enable = xi_xirc_enable;
    691 	sc->sc_disable = xi_xirc_disable;
    692 
    693 	if (!pcmcia_scan_cis(msc->sc_dev.dv_parent, xi_xirc_lan_nid_ciscallback,
    694 	    myla)) {
    695 		aprint_error("%s: can't find MAC address\n", self->dv_xname);
    696 		return;
    697 	}
    698 
    699 	/* Perform generic initialization. */
    700 	xi_attach(sc, myla);
    701 }
    702 
    703 int
    704 xi_xirc_enable(sc)
    705 	struct xi_softc *sc;
    706 {
    707 
    708 	return (xirc_enable((struct xirc_softc *)sc->sc_dev.dv_parent,
    709 	    XIRC_ETHERNET_ENABLED));
    710 }
    711 
    712 void
    713 xi_xirc_disable(sc)
    714 	struct xi_softc *sc;
    715 {
    716 
    717 	xirc_disable((struct xirc_softc *)sc->sc_dev.dv_parent,
    718 	    XIRC_ETHERNET_ENABLED);
    719 }
    720 
    721 int
    722 xi_xirc_lan_nid_ciscallback(tuple, arg)
    723 	struct pcmcia_tuple *tuple;
    724 	void *arg;
    725 {
    726 	u_int8_t *myla = arg;
    727 	int i;
    728 
    729 	if (tuple->length < 2)
    730 		return (0);
    731 
    732 	switch (tuple->code) {
    733 	case PCMCIA_CISTPL_FUNCE:
    734 		switch (pcmcia_tuple_read_1(tuple, 0)) {
    735 		case PCMCIA_TPLFE_TYPE_LAN_NID:
    736 			if (pcmcia_tuple_read_1(tuple, 1) != ETHER_ADDR_LEN)
    737 				return (0);
    738 			for (i = 0; i < ETHER_ADDR_LEN; i++)
    739 				myla[i] = pcmcia_tuple_read_1(tuple, i + 2);
    740 			return (1);
    741 
    742 		case 0x02:
    743 			/*
    744 			 * Not sure about this, I don't have a CE2
    745 			 * that puts the ethernet addr here.
    746 			 */
    747 		 	if (pcmcia_tuple_read_1(tuple, 1) != 0x01 ||
    748 			    pcmcia_tuple_read_1(tuple, 2) != ETHER_ADDR_LEN)
    749 				return (0);
    750 			for (i = 0; i < ETHER_ADDR_LEN; i++)
    751 				myla[i] = pcmcia_tuple_read_1(tuple, i + 3);
    752 			return (1);
    753 		}
    754 
    755 	case 0x89:
    756 		if (pcmcia_tuple_read_1(tuple, 0) != 0x04 ||
    757 		    pcmcia_tuple_read_1(tuple, 1) != ETHER_ADDR_LEN)
    758 			return (0);
    759 		for (i = 0; i < ETHER_ADDR_LEN; i++)
    760 			myla[i] = pcmcia_tuple_read_1(tuple, i + 2);
    761 		return (1);
    762 	}
    763 
    764 	return (0);
    765 }
    766 
    767 #endif /* NXI_XIRC > 0 */
    768