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