1 /* $NetBSD: if_ep_pcmcia.c,v 1.62 2008/08/27 05:33:47 christos Exp $ */
4 * Copyright (c) 1998, 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.
34 * Copyright (c) 1997 Marc Horowitz. All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by Marc Horowitz.
47 * 4. The name of the author may not be used to endorse or promote products
48 * derived from this software without specific prior written permission.
50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
54 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
59 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 #include <sys/cdefs.h>
63 __KERNEL_RCSID(0, "$NetBSD: if_ep_pcmcia.c,v 1.62 2008/08/27 05:33:47 christos Exp $");
65 #include <sys/param.h>
66 #include <sys/systm.h>
68 #include <sys/socket.h>
69 #include <sys/ioctl.h>
70 #include <sys/errno.h>
71 #include <sys/syslog.h>
72 #include <sys/select.h>
73 #include <sys/device.h>
76 #include <net/if_dl.h>
77 #include <net/if_ether.h>
78 #include <net/if_media.h>
84 #include <dev/mii/miivar.h>
86 #include <dev/ic/elink3var.h>
87 #include <dev/ic/elink3reg.h>
89 #include <dev/pcmcia/pcmciareg.h>
90 #include <dev/pcmcia/pcmciavar.h>
91 #include <dev/pcmcia/pcmciadevs.h>
93 int ep_pcmcia_match(device_t
, cfdata_t
, void *);
94 void ep_pcmcia_attach(device_t
, device_t
, void *);
95 int ep_pcmcia_detach(device_t
, int);
97 int ep_pcmcia_get_enaddr(struct pcmcia_tuple
*, void *);
98 int ep_pcmcia_enable(struct ep_softc
*);
99 void ep_pcmcia_disable(struct ep_softc
*);
101 void ep_pcmcia_disable1(struct ep_softc
*);
103 struct ep_pcmcia_softc
{
104 struct ep_softc sc_ep
; /* real "ep" softc */
106 /* PCMCIA-specific goo */
107 struct pcmcia_io_handle sc_pcioh
; /* PCMCIA i/o space info */
108 int sc_io_window
; /* our i/o window */
109 struct pcmcia_function
*sc_pf
; /* our PCMCIA function */
112 CFATTACH_DECL_NEW(ep_pcmcia
, sizeof(struct ep_pcmcia_softc
),
113 ep_pcmcia_match
, ep_pcmcia_attach
, ep_pcmcia_detach
, ep_activate
);
115 const struct ep_pcmcia_product
{
116 struct pcmcia_product epp_product
;
117 u_short epp_chipset
; /* 3Com chipset used */
118 int epp_flags
; /* initial softc flags */
119 } ep_pcmcia_products
[] = {
120 { { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3C562
,
121 PCMCIA_CIS_INVALID
},
122 ELINK_CHIPSET_3C509
, 0 },
124 { { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3C589
,
125 PCMCIA_CIS_INVALID
},
126 ELINK_CHIPSET_3C509
, 0 },
128 { { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3CXEM556
,
129 PCMCIA_CIS_INVALID
},
130 ELINK_CHIPSET_3C509
, 0 },
132 { { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3CXEM556INT
,
133 PCMCIA_CIS_INVALID
},
134 ELINK_CHIPSET_3C509
, 0 },
136 { { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3C574
,
137 PCMCIA_CIS_INVALID
},
138 ELINK_CHIPSET_ROADRUNNER
, ELINK_FLAGS_MII
},
140 { { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3CCFEM556BI
,
141 PCMCIA_CIS_INVALID
},
142 ELINK_CHIPSET_ROADRUNNER
, ELINK_FLAGS_MII
},
144 { { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3C1
,
145 PCMCIA_CIS_INVALID
},
146 ELINK_CHIPSET_3C509
, 0 },
148 const size_t ep_pcmcia_nproducts
=
149 sizeof(ep_pcmcia_products
) / sizeof(ep_pcmcia_products
[0]);
152 ep_pcmcia_match(device_t parent
, cfdata_t match
, void *aux
)
154 struct pcmcia_attach_args
*pa
= aux
;
156 /* This is to differentiate the serial function of some cards. */
157 if (pa
->pf
->function
!= PCMCIA_FUNCTION_NETWORK
)
160 if (pcmcia_product_lookup(pa
, ep_pcmcia_products
, ep_pcmcia_nproducts
,
161 sizeof(ep_pcmcia_products
[0]), NULL
))
167 ep_pcmcia_enable(struct ep_softc
*sc
)
169 struct ep_pcmcia_softc
*psc
= (struct ep_pcmcia_softc
*) sc
;
170 struct pcmcia_function
*pf
= psc
->sc_pf
;
173 /* establish the interrupt. */
174 sc
->sc_ih
= pcmcia_intr_establish(pf
, IPL_NET
, epintr
, sc
);
178 error
= pcmcia_function_enable(pf
);
180 pcmcia_intr_disestablish(pf
, sc
->sc_ih
);
185 if ((psc
->sc_pf
->sc
->card
.product
== PCMCIA_PRODUCT_3COM_3C562
) ||
186 (psc
->sc_pf
->sc
->card
.product
== PCMCIA_PRODUCT_3COM_3CXEM556
) ||
187 (psc
->sc_pf
->sc
->card
.product
== PCMCIA_PRODUCT_3COM_3CXEM556INT
)) {
190 /* turn off the serial-disable bit */
192 reg
= pcmcia_ccr_read(pf
, PCMCIA_CCR_OPTION
);
195 pcmcia_ccr_write(pf
, PCMCIA_CCR_OPTION
, reg
);
204 ep_pcmcia_disable(struct ep_softc
*sc
)
206 struct ep_pcmcia_softc
*psc
= (struct ep_pcmcia_softc
*) sc
;
208 pcmcia_function_disable(psc
->sc_pf
);
209 pcmcia_intr_disestablish(psc
->sc_pf
, sc
->sc_ih
);
214 ep_pcmcia_attach(device_t parent
, device_t self
, void *aux
)
216 struct ep_pcmcia_softc
*psc
= device_private(self
);
217 struct ep_softc
*sc
= &psc
->sc_ep
;
218 struct pcmcia_attach_args
*pa
= aux
;
219 struct pcmcia_config_entry
*cfe
;
220 const struct ep_pcmcia_product
*epp
;
221 u_int8_t myla
[ETHER_ADDR_LEN
];
222 u_int8_t
*enaddr
= NULL
;
229 SIMPLEQ_FOREACH(cfe
, &pa
->pf
->cfe_head
, cfe_list
) {
230 if (cfe
->num_memspace
!= 0)
232 if (cfe
->num_iospace
!= 1)
235 if (pa
->product
== PCMCIA_PRODUCT_3COM_3C562
) {
237 * the 3c562 can only use 0x??00-0x??7f
238 * according to the Linux driver
242 * 3c562 i/o may decodes address line not only A0-3
243 * but also A7. Anyway, we must sweep at most
244 * [0x0000, 0x0100). The address higher is given by a
245 * pcmcia bridge. But pcmcia bus-space allocation
246 * function implies cards will decode 10-bit address
247 * line. So we must search [0x0000, 0x0400).
249 * XXX: We must not check the bunch of I/O space range
250 * [0x400*n, 0x300 + 0x400*n) because they are
251 * reserved for legacy ISA devices and their alias
252 * images on PC/AT architecture.
254 for (i
= 0x0300; i
< 0x0380; i
+= 0x10) {
255 if (pcmcia_io_alloc(pa
->pf
, i
,
256 cfe
->iospace
[0].length
,
257 cfe
->iospace
[0].length
,
258 &psc
->sc_pcioh
) == 0)
264 if (pcmcia_io_alloc(pa
->pf
, cfe
->iospace
[0].start
,
265 cfe
->iospace
[0].length
, cfe
->iospace
[0].length
,
266 &psc
->sc_pcioh
) == 0)
271 aprint_error_dev(self
, "failed to allocate I/O space\n");
275 sc
->sc_iot
= psc
->sc_pcioh
.iot
;
276 sc
->sc_ioh
= psc
->sc_pcioh
.ioh
;
278 /* Enable the card. */
279 pcmcia_function_init(pa
->pf
, cfe
);
281 if (pcmcia_io_map(pa
->pf
, ((cfe
->flags
& PCMCIA_CFE_IO16
) ?
282 PCMCIA_WIDTH_AUTO
: PCMCIA_WIDTH_IO8
), &psc
->sc_pcioh
,
283 &psc
->sc_io_window
)) {
284 aprint_error_dev(self
, "can't map i/o space\n");
288 error
= ep_pcmcia_enable(sc
);
293 switch (pa
->product
) {
294 case PCMCIA_PRODUCT_3COM_3C562
:
296 * 3c562a-c use this; 3c562d does it in the regular way.
297 * we might want to check the revision and produce a warning
301 case PCMCIA_PRODUCT_3COM_3C574
:
302 case PCMCIA_PRODUCT_3COM_3CCFEM556BI
:
304 * Apparently, some 3c574s do it this way, as well.
306 if (pcmcia_scan_cis(parent
, ep_pcmcia_get_enaddr
, myla
))
311 epp
= pcmcia_product_lookup(pa
, ep_pcmcia_products
, ep_pcmcia_nproducts
,
312 sizeof(ep_pcmcia_products
[0]), NULL
);
314 panic("ep_pcmcia_attach: impossible");
316 sc
->bustype
= ELINK_BUS_PCMCIA
;
317 sc
->ep_flags
= epp
->epp_flags
;
319 sc
->enable
= ep_pcmcia_enable
;
320 sc
->disable
= ep_pcmcia_disable
;
322 if (epconfig(sc
, epp
->epp_chipset
, enaddr
))
323 aprint_error_dev(self
, "couldn't configure controller\n");
326 ep_pcmcia_disable(sc
);
330 pcmcia_io_unmap(psc
->sc_pf
, psc
->sc_io_window
);
332 pcmcia_io_free(psc
->sc_pf
, &psc
->sc_pcioh
);
334 psc
->sc_io_window
= -1;
338 ep_pcmcia_detach(device_t self
, int flags
)
340 struct ep_pcmcia_softc
*psc
= device_private(self
);
343 if (psc
->sc_io_window
== -1)
344 /* Nothing to detach. */
347 rv
= ep_detach(self
, flags
);
351 /* Unmap our i/o window. */
352 pcmcia_io_unmap(psc
->sc_pf
, psc
->sc_io_window
);
354 /* Free our i/o space. */
355 pcmcia_io_free(psc
->sc_pf
, &psc
->sc_pcioh
);
361 ep_pcmcia_get_enaddr(struct pcmcia_tuple
*tuple
, void *arg
)
363 u_int8_t
*myla
= arg
;
366 /* this is 3c562a-c magic */
367 if (tuple
->code
== 0x88) {
368 if (tuple
->length
< ETHER_ADDR_LEN
)
371 for (i
= 0; i
< ETHER_ADDR_LEN
; i
+= 2) {
372 myla
[i
] = pcmcia_tuple_read_1(tuple
, i
+ 1);
373 myla
[i
+ 1] = pcmcia_tuple_read_1(tuple
, i
);