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