1 /* $NetBSD: xirc.c,v 1.30 2009/11/13 01:14:35 dyoung Exp $ */
4 * Copyright (c) 1999, 2000, 2004 The NetBSD Foundation, Inc.
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.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: xirc.c,v 1.30 2009/11/13 01:14:35 dyoung Exp $");
39 #include <sys/param.h>
40 #include <sys/systm.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>
48 #include <sys/device.h>
51 #include <net/if_dl.h>
52 #include <net/if_ether.h>
53 #include <net/if_media.h>
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>
66 #include <net/bpfdesc.h>
72 #include <dev/pcmcia/pcmciareg.h>
73 #include <dev/pcmcia/pcmciavar.h>
74 #include <dev/pcmcia/pcmciadevs.h>
79 #include <dev/ic/comreg.h>
80 #include <dev/ic/comvar.h>
84 #include <dev/mii/mii.h>
85 #include <dev/mii/miivar.h>
87 #include <dev/pcmcia/if_xivar.h>
89 #include <dev/pcmcia/if_xireg.h>
92 device_t sc_dev
; /* generic device glue */
94 struct pcmcia_function
*sc_pf
; /* our PCMCIA function */
95 void *sc_ih
; /* interrupt handle */
98 u_int8_t sc_mako_intmask
;
102 * Data for the Modem portion.
105 struct pcmcia_io_handle sc_modem_pcioh
;
106 int sc_modem_io_window
;
109 * Data for the Ethernet portion.
111 device_t sc_ethernet
;
112 struct pcmcia_io_handle sc_ethernet_pcioh
;
113 int sc_ethernet_io_window
;
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
124 int xirc_match(device_t
, cfdata_t
, void *);
125 void xirc_attach(device_t
, device_t
, void *);
126 int xirc_detach(device_t
, int);
127 void xirc_childdet(device_t
, device_t
);
129 CFATTACH_DECL2_NEW(xirc
, sizeof(struct xirc_softc
),
130 xirc_match
, xirc_attach
, xirc_detach
, NULL
, NULL
, xirc_childdet
);
132 int xirc_print(void *, const char *);
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
*);
142 int xirc_enable(struct xirc_softc
*, int, int);
143 void xirc_disable(struct xirc_softc
*, int, int);
145 int xirc_intr(void *);
148 xirc_match(device_t parent
, cfdata_t match
,
151 struct pcmcia_attach_args
*pa
= aux
;
153 /* XXX Toshiba, Accton */
155 if (pa
->manufacturer
== PCMCIA_VENDOR_COMPAQ2
&&
156 pa
->product
== PCMCIA_PRODUCT_COMPAQ2_CPQ_10_100
)
159 if (pa
->manufacturer
== PCMCIA_VENDOR_INTEL
&&
160 pa
->product
== PCMCIA_PRODUCT_INTEL_EEPRO100
)
163 if (pa
->manufacturer
== PCMCIA_VENDOR_XIRCOM
&&
164 (pa
->product
& (XIMEDIA_ETHER
<< 8)) != 0)
171 xirc_attach(device_t parent
, device_t self
, void *aux
)
173 struct xirc_softc
*sc
= device_private(self
);
174 struct pcmcia_attach_args
*pa
= aux
;
175 struct pcmcia_config_entry
*cfe
;
183 pcmcia_socket_enable(parent
);
184 rv
= pcmcia_scan_cis(parent
, xirc_manfid_ciscallback
, &sc
->sc_id
);
185 pcmcia_socket_disable(parent
);
187 aprint_error_dev(self
, "failed to find ID\n");
191 switch (sc
->sc_id
& 0x100f) {
192 case 0x0001: /* CE */
193 case 0x0002: /* CE2 */
194 sc
->sc_chipset
= XI_CHIPSET_SCIPPER
;
196 case 0x0003: /* CE3 */
197 sc
->sc_chipset
= XI_CHIPSET_MOHAWK
;
203 sc
->sc_chipset
= XI_CHIPSET_SCIPPER
;
206 sc
->sc_chipset
= XI_CHIPSET_MOHAWK
;
210 sc
->sc_chipset
= XI_CHIPSET_DINGO
;
213 aprint_error_dev(self
, "unknown ID %04x\n",
218 aprint_normal_dev(self
, "id=%04x\n", sc
->sc_id
);
220 if (sc
->sc_id
& (XIMEDIA_MODEM
<< 8)) {
221 if (sc
->sc_chipset
>= XI_CHIPSET_DINGO
) {
222 cfe
= xirc_dingo_alloc_modem(sc
);
223 if (cfe
&& sc
->sc_id
& (XIMEDIA_ETHER
<< 8)) {
224 if (!xirc_dingo_alloc_ethernet(sc
)) {
225 pcmcia_io_free(pa
->pf
,
226 &sc
->sc_modem_pcioh
);
231 cfe
= xirc_mako_alloc(sc
);
233 cfe
= xirc_dingo_alloc_ethernet(sc
);
235 aprint_error_dev(self
, "failed to allocate I/O space\n");
239 /* Enable the card. */
240 pcmcia_function_init(pa
->pf
, cfe
);
242 if (sc
->sc_id
& (XIMEDIA_MODEM
<< 8)) {
243 if (pcmcia_io_map(sc
->sc_pf
, PCMCIA_WIDTH_IO8
,
244 &sc
->sc_modem_pcioh
, &sc
->sc_modem_io_window
)) {
245 aprint_error_dev(self
, "unable to map I/O space\n");
248 sc
->sc_flags
|= XIRC_MODEM_MAPPED
;
251 if (sc
->sc_id
& (XIMEDIA_ETHER
<< 8)) {
252 if (pcmcia_io_map(sc
->sc_pf
, PCMCIA_WIDTH_AUTO
,
253 &sc
->sc_ethernet_pcioh
, &sc
->sc_ethernet_io_window
)) {
254 aprint_error_dev(self
, "unable to map I/O space\n");
257 sc
->sc_flags
|= XIRC_ETHERNET_MAPPED
;
260 error
= xirc_enable(sc
, XIRC_MODEM_ENABLED
|XIRC_ETHERNET_ENABLED
,
261 sc
->sc_id
& (XIMEDIA_MODEM
|XIMEDIA_ETHER
));
265 sc
->sc_mako_intmask
= 0xee;
267 if (sc
->sc_id
& (XIMEDIA_MODEM
<< 8))
269 sc
->sc_modem
= config_found(self
, __UNCONST("com"), xirc_print
);
270 if (sc
->sc_id
& (XIMEDIA_ETHER
<< 8))
272 sc
->sc_ethernet
= config_found(self
, __UNCONST("xi"),
275 xirc_disable(sc
, XIRC_MODEM_ENABLED
|XIRC_ETHERNET_ENABLED
,
276 sc
->sc_id
& (XIMEDIA_MODEM
|XIMEDIA_ETHER
));
280 /* I/O spaces will be freed by detach. */
285 xirc_manfid_ciscallback(struct pcmcia_tuple
*tuple
, void *arg
)
289 if (tuple
->code
!= PCMCIA_CISTPL_MANFID
)
292 if (tuple
->length
< 5)
295 *id
= (pcmcia_tuple_read_1(tuple
, 3) << 8) |
296 pcmcia_tuple_read_1(tuple
, 4);
300 struct pcmcia_config_entry
*
301 xirc_mako_alloc(struct xirc_softc
*sc
)
303 struct pcmcia_config_entry
*cfe
;
305 SIMPLEQ_FOREACH(cfe
, &sc
->sc_pf
->cfe_head
, cfe_list
) {
306 if (cfe
->num_iospace
!= 1)
309 if (pcmcia_io_alloc(sc
->sc_pf
, cfe
->iospace
[0].start
,
310 cfe
->iospace
[0].length
, cfe
->iospace
[0].length
,
311 &sc
->sc_modem_pcioh
))
314 cfe
->iospace
[1].start
= cfe
->iospace
[0].start
+8;
315 cfe
->iospace
[1].length
= 18;
316 if (pcmcia_io_alloc(sc
->sc_pf
, cfe
->iospace
[1].start
,
317 cfe
->iospace
[1].length
, 0x20,
318 &sc
->sc_ethernet_pcioh
)) {
319 cfe
->iospace
[1].start
= cfe
->iospace
[0].start
-24;
320 if (pcmcia_io_alloc(sc
->sc_pf
, cfe
->iospace
[1].start
,
321 cfe
->iospace
[1].length
, 0x20,
322 &sc
->sc_ethernet_pcioh
))
327 sc
->sc_flags
|= XIRC_MODEM_ALLOCED
;
328 sc
->sc_flags
|= XIRC_ETHERNET_ALLOCED
;
335 struct pcmcia_config_entry
*
336 xirc_dingo_alloc_modem(struct xirc_softc
*sc
)
338 struct pcmcia_config_entry
*cfe
;
340 SIMPLEQ_FOREACH(cfe
, &sc
->sc_pf
->cfe_head
, cfe_list
) {
341 if (cfe
->num_iospace
!= 1)
344 if (pcmcia_io_alloc(sc
->sc_pf
, cfe
->iospace
[0].start
,
345 cfe
->iospace
[0].length
, cfe
->iospace
[0].length
,
346 &sc
->sc_modem_pcioh
))
350 sc
->sc_flags
|= XIRC_MODEM_ALLOCED
;
357 struct pcmcia_config_entry
*
358 xirc_dingo_alloc_ethernet(struct xirc_softc
*sc
)
360 struct pcmcia_config_entry
*cfe
;
363 for (port
= 0x300; port
< 0x400; port
+= XI_IOSIZE
) {
364 if (pcmcia_io_alloc(sc
->sc_pf
, port
,
365 XI_IOSIZE
, XI_IOSIZE
, &sc
->sc_ethernet_pcioh
))
368 /* Found one for the ethernet! */
369 sc
->sc_flags
|= XIRC_ETHERNET_ALLOCED
;
370 cfe
= SIMPLEQ_FIRST(&sc
->sc_pf
->cfe_head
);
378 xirc_print(void *aux
, const char *pnp
)
380 const char *name
= aux
;
383 aprint_normal("%s at %s(*)", name
, pnp
);
389 xirc_childdet(device_t self
, device_t child
)
391 struct xirc_softc
*sc
= device_private(self
);
393 if (sc
->sc_ethernet
== child
)
394 sc
->sc_ethernet
= NULL
;
396 if (sc
->sc_modem
== child
)
401 xirc_detach(device_t self
, int flags
)
403 struct xirc_softc
*sc
= device_private(self
);
406 if (sc
->sc_ethernet
!= NULL
) {
407 if ((rv
= config_detach(sc
->sc_ethernet
, flags
)) != 0)
411 if (sc
->sc_modem
!= NULL
) {
412 if ((rv
= config_detach(sc
->sc_modem
, flags
)) != 0)
416 /* Unmap our i/o windows. */
417 if (sc
->sc_flags
& XIRC_ETHERNET_MAPPED
)
418 pcmcia_io_unmap(sc
->sc_pf
, sc
->sc_ethernet_io_window
);
419 if (sc
->sc_flags
& XIRC_MODEM_MAPPED
)
420 pcmcia_io_unmap(sc
->sc_pf
, sc
->sc_modem_io_window
);
422 /* Free our i/o spaces. */
423 if (sc
->sc_flags
& XIRC_ETHERNET_ALLOCED
)
424 pcmcia_io_free(sc
->sc_pf
, &sc
->sc_ethernet_pcioh
);
425 if (sc
->sc_flags
& XIRC_MODEM_ALLOCED
)
426 pcmcia_io_free(sc
->sc_pf
, &sc
->sc_modem_pcioh
);
435 struct xirc_softc
*sc
= arg
;
439 if (sc
->sc_modem
!= NULL
&&
440 (sc
->sc_flags
& XIRC_MODEM_ENABLED
) != 0)
441 rval
|= comintr(device_private(sc
->sc_modem
));
445 if (sc
->sc_ethernet
!= NULL
&&
446 (sc
->sc_flags
& XIRC_ETHERNET_ENABLED
) != 0)
447 rval
|= xi_intr(device_private(sc
->sc_ethernet
));
454 xirc_enable(struct xirc_softc
*sc
, int flag
, int media
)
458 if ((sc
->sc_flags
& flag
) == flag
) {
459 printf("%s: already enabled\n", device_xname(sc
->sc_dev
));
463 if ((sc
->sc_flags
& (XIRC_MODEM_ENABLED
|XIRC_ETHERNET_ENABLED
)) != 0) {
464 sc
->sc_flags
|= flag
;
469 * Establish our interrupt handler.
471 * XXX Note, we establish this at IPL_NET. This is suboptimal
472 * XXX the Modem portion, but is necessary to make the Ethernet
473 * XXX portion have the correct interrupt level semantics.
475 * XXX Eventually we should use the `enabled' bits in the
476 * XXX flags word to determine which level we should be at.
478 sc
->sc_ih
= pcmcia_intr_establish(sc
->sc_pf
, IPL_NET
, xirc_intr
, sc
);
482 error
= pcmcia_function_enable(sc
->sc_pf
);
484 pcmcia_intr_disestablish(sc
->sc_pf
, sc
->sc_ih
);
489 sc
->sc_flags
|= flag
;
491 if (sc
->sc_chipset
< XI_CHIPSET_DINGO
&&
492 sc
->sc_id
& (XIMEDIA_MODEM
<< 8)) {
493 sc
->sc_mako_intmask
|= media
;
494 bus_space_write_1(sc
->sc_ethernet_pcioh
.iot
,
495 sc
->sc_ethernet_pcioh
.ioh
, 0x10, sc
->sc_mako_intmask
);
502 xirc_disable(struct xirc_softc
*sc
, int flag
, int media
)
505 if ((sc
->sc_flags
& flag
) == 0) {
506 printf("%s: already disabled\n", device_xname(sc
->sc_dev
));
510 if (sc
->sc_chipset
< XI_CHIPSET_DINGO
&&
511 sc
->sc_id
& (XIMEDIA_MODEM
<< 8)) {
512 sc
->sc_mako_intmask
&= ~media
;
513 bus_space_write_1(sc
->sc_ethernet_pcioh
.iot
,
514 sc
->sc_ethernet_pcioh
.ioh
, 0x10, sc
->sc_mako_intmask
);
517 sc
->sc_flags
&= ~flag
;
518 if ((sc
->sc_flags
& (XIRC_MODEM_ENABLED
|XIRC_ETHERNET_ENABLED
)) != 0)
521 pcmcia_function_disable(sc
->sc_pf
);
522 pcmcia_intr_disestablish(sc
->sc_pf
, sc
->sc_ih
);
526 /****** Here begins the com attachment code. ******/
529 int com_xirc_match(device_t
, cfdata_t
, void *);
530 void com_xirc_attach(device_t
, device_t
, void *);
531 int com_xirc_detach(device_t
, int);
533 /* No xirc-specific goo in the softc; it's all in the parent. */
534 CFATTACH_DECL_NEW(com_xirc
, sizeof(struct com_softc
),
535 com_xirc_match
, com_xirc_attach
, com_detach
, NULL
);
537 int com_xirc_enable(struct com_softc
*);
538 void com_xirc_disable(struct com_softc
*);
541 com_xirc_match(device_t parent
, cfdata_t match
, void *aux
)
543 extern struct cfdriver com_cd
;
544 const char *name
= aux
;
546 if (strcmp(name
, com_cd
.cd_name
) == 0)
553 com_xirc_attach(device_t parent
, device_t self
, void *aux
)
555 struct com_softc
*sc
= device_private(self
);
556 struct xirc_softc
*msc
= device_private(parent
);
562 COM_INIT_REGS(sc
->sc_regs
,
563 msc
->sc_modem_pcioh
.iot
,
564 msc
->sc_modem_pcioh
.ioh
,
569 sc
->sc_frequency
= COM_FREQ
;
571 sc
->enable
= com_xirc_enable
;
572 sc
->disable
= com_xirc_disable
;
574 aprint_normal("%s", device_xname(self
));
582 com_xirc_enable(struct com_softc
*sc
)
584 struct xirc_softc
*msc
=
585 device_private(device_parent(sc
->sc_dev
));
587 return (xirc_enable(msc
, XIRC_MODEM_ENABLED
, XIMEDIA_MODEM
));
591 com_xirc_disable(struct com_softc
*sc
)
593 struct xirc_softc
*msc
=
594 device_private(device_parent(sc
->sc_dev
));
596 xirc_disable(msc
, XIRC_MODEM_ENABLED
, XIMEDIA_MODEM
);
599 #endif /* NCOM_XIRC > 0 */
601 /****** Here begins the xi attachment code. ******/
604 int xi_xirc_match(device_t
, cfdata_t
, void *);
605 void xi_xirc_attach(device_t
, device_t
, void *);
607 /* No xirc-specific goo in the softc; it's all in the parent. */
608 CFATTACH_DECL(xi_xirc
, sizeof(struct xi_softc
),
609 xi_xirc_match
, xi_xirc_attach
, xi_detach
, NULL
);
611 int xi_xirc_enable(struct xi_softc
*);
612 void xi_xirc_disable(struct xi_softc
*);
613 int xi_xirc_lan_nid_ciscallback(struct pcmcia_tuple
*, void *);
616 xi_xirc_match(device_t parent
, cfdata_t match
, void *aux
)
618 extern struct cfdriver xi_cd
;
619 const char *name
= aux
;
621 if (strcmp(name
, xi_cd
.cd_name
) == 0)
628 xi_xirc_attach(device_t parent
, device_t self
, void *aux
)
630 struct xi_softc
*sc
= device_private(self
);
631 struct xirc_softc
*msc
= device_private(parent
);
632 u_int8_t myla
[ETHER_ADDR_LEN
];
638 sc
->sc_bst
= msc
->sc_ethernet_pcioh
.iot
;
639 sc
->sc_bsh
= msc
->sc_ethernet_pcioh
.ioh
;
641 sc
->sc_chipset
= msc
->sc_chipset
;
643 sc
->sc_enable
= xi_xirc_enable
;
644 sc
->sc_disable
= xi_xirc_disable
;
646 if (!pcmcia_scan_cis(device_parent(msc
->sc_dev
),
647 xi_xirc_lan_nid_ciscallback
, myla
)) {
648 aprint_error_dev(self
, "can't find MAC address\n");
652 /* Perform generic initialization. */
657 xi_xirc_enable(struct xi_softc
*sc
)
659 struct xirc_softc
*msc
= device_private(device_parent(sc
->sc_dev
));
661 return (xirc_enable(msc
, XIRC_ETHERNET_ENABLED
, XIMEDIA_ETHER
));
665 xi_xirc_disable(struct xi_softc
*sc
)
667 struct xirc_softc
*msc
= device_private(device_parent(sc
->sc_dev
));
669 xirc_disable(msc
, XIRC_ETHERNET_ENABLED
, XIMEDIA_ETHER
);
673 xi_xirc_lan_nid_ciscallback(struct pcmcia_tuple
*tuple
, void *arg
)
675 u_int8_t
*myla
= arg
;
678 if (tuple
->length
< 2)
681 switch (tuple
->code
) {
682 case PCMCIA_CISTPL_FUNCE
:
683 switch (pcmcia_tuple_read_1(tuple
, 0)) {
684 case PCMCIA_TPLFE_TYPE_LAN_NID
:
685 if (pcmcia_tuple_read_1(tuple
, 1) != ETHER_ADDR_LEN
)
687 for (i
= 0; i
< ETHER_ADDR_LEN
; i
++)
688 myla
[i
] = pcmcia_tuple_read_1(tuple
, i
+ 2);
693 * Not sure about this, I don't have a CE2
694 * that puts the ethernet addr here.
696 if (pcmcia_tuple_read_1(tuple
, 1) != 0x01 ||
697 pcmcia_tuple_read_1(tuple
, 2) != ETHER_ADDR_LEN
)
699 for (i
= 0; i
< ETHER_ADDR_LEN
; i
++)
700 myla
[i
] = pcmcia_tuple_read_1(tuple
, i
+ 3);
705 if (pcmcia_tuple_read_1(tuple
, 0) != 0x04 ||
706 pcmcia_tuple_read_1(tuple
, 1) != ETHER_ADDR_LEN
)
708 for (i
= 0; i
< ETHER_ADDR_LEN
; i
++)
709 myla
[i
] = pcmcia_tuple_read_1(tuple
, i
+ 2);
716 #endif /* NXI_XIRC > 0 */