1 /* $NetBSD: if_awi_pcmcia.c,v 1.43 2009/05/12 14:42:18 cegger Exp $ */
4 * Copyright (c) 1999, 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * PCMCIA attachment for BayStack 650 802.11FH PCMCIA card,
34 * based on the AMD 79c930 802.11 controller chip.
36 * This attachment can probably be trivially adapted for other FH and
37 * DS cards based on the same chipset.
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: if_awi_pcmcia.c,v 1.43 2009/05/12 14:42:18 cegger Exp $");
43 #include <sys/param.h>
44 #include <sys/systm.h>
46 #include <sys/socket.h>
47 #include <sys/ioctl.h>
48 #include <sys/errno.h>
49 #include <sys/syslog.h>
50 #include <sys/select.h>
51 #include <sys/device.h>
54 #include <net/if_dl.h>
55 #include <net/if_ether.h>
56 #include <net/if_media.h>
58 #include <net80211/ieee80211_netbsd.h>
59 #include <net80211/ieee80211_var.h>
65 #include <dev/ic/am79c930reg.h>
66 #include <dev/ic/am79c930var.h>
67 #include <dev/ic/awireg.h>
68 #include <dev/ic/awivar.h>
70 #include <dev/pcmcia/pcmciareg.h>
71 #include <dev/pcmcia/pcmciavar.h>
72 #include <dev/pcmcia/pcmciadevs.h>
74 static int awi_pcmcia_match(device_t
, cfdata_t
, void *);
75 static int awi_pcmcia_validate_config(struct pcmcia_config_entry
*);
76 static void awi_pcmcia_attach(device_t
, device_t
, void *);
77 static int awi_pcmcia_detach(device_t
, int);
78 static int awi_pcmcia_enable(struct awi_softc
*);
79 static void awi_pcmcia_disable(struct awi_softc
*);
81 struct awi_pcmcia_softc
{
82 struct awi_softc sc_awi
; /* real "awi" softc */
84 /* PCMCIA-specific goo */
85 struct pcmcia_function
*sc_pf
; /* our PCMCIA function */
86 void *sc_ih
; /* interrupt handler */
89 #define AWI_PCMCIA_ATTACHED 3
92 CFATTACH_DECL(awi_pcmcia
, sizeof(struct awi_pcmcia_softc
),
93 awi_pcmcia_match
, awi_pcmcia_attach
, awi_pcmcia_detach
, awi_activate
);
95 static const struct pcmcia_product awi_pcmcia_products
[] = {
96 { PCMCIA_VENDOR_BAY
, PCMCIA_PRODUCT_BAY_STACK_650
,
97 PCMCIA_CIS_BAY_STACK_650
},
99 { PCMCIA_VENDOR_BAY
, PCMCIA_PRODUCT_BAY_STACK_660
,
100 PCMCIA_CIS_BAY_STACK_660
},
102 { PCMCIA_VENDOR_BAY
, PCMCIA_PRODUCT_BAY_SURFER_PRO
,
103 PCMCIA_CIS_BAY_SURFER_PRO
},
105 { PCMCIA_VENDOR_AMD
, PCMCIA_PRODUCT_AMD_AM79C930
,
106 PCMCIA_CIS_AMD_AM79C930
},
108 { PCMCIA_VENDOR_ICOM
, PCMCIA_PRODUCT_ICOM_SL200
,
109 PCMCIA_CIS_ICOM_SL200
},
111 { PCMCIA_VENDOR_NOKIA
, PCMCIA_PRODUCT_NOKIA_C020_WLAN
,
112 PCMCIA_CIS_NOKIA_C020_WLAN
},
114 { PCMCIA_VENDOR_FARALLON
, PCMCIA_PRODUCT_FARALLON_SKYLINE
,
115 PCMCIA_CIS_FARALLON_SKYLINE
},
117 static const size_t awi_pcmcia_nproducts
=
118 sizeof(awi_pcmcia_products
) / sizeof(awi_pcmcia_products
[0]);
121 awi_pcmcia_enable(struct awi_softc
*sc
)
123 struct awi_pcmcia_softc
*psc
= (struct awi_pcmcia_softc
*)sc
;
124 struct pcmcia_function
*pf
= psc
->sc_pf
;
127 /* establish the interrupt. */
128 psc
->sc_ih
= pcmcia_intr_establish(pf
, IPL_NET
, awi_intr
, sc
);
132 error
= pcmcia_function_enable(pf
);
134 pcmcia_intr_disestablish(pf
, psc
->sc_ih
);
142 awi_pcmcia_disable(struct awi_softc
*sc
)
144 struct awi_pcmcia_softc
*psc
= (struct awi_pcmcia_softc
*)sc
;
145 struct pcmcia_function
*pf
= psc
->sc_pf
;
147 pcmcia_function_disable(pf
);
148 pcmcia_intr_disestablish(pf
, psc
->sc_ih
);
153 awi_pcmcia_match(device_t parent
, cfdata_t match
,
156 struct pcmcia_attach_args
*pa
= aux
;
158 if (pcmcia_product_lookup(pa
, awi_pcmcia_products
, awi_pcmcia_nproducts
,
159 sizeof(awi_pcmcia_products
[0]), NULL
))
165 awi_pcmcia_validate_config(struct pcmcia_config_entry
*cfe
)
167 if (cfe
->iftype
!= PCMCIA_IFTYPE_IO
||
168 cfe
->num_iospace
< 1 ||
169 cfe
->iospace
[0].length
< AM79C930_IO_SIZE
)
171 if (cfe
->num_memspace
< 1) {
172 cfe
->memspace
[0].length
= AM79C930_MEM_SIZE
;
173 cfe
->memspace
[0].cardaddr
= 0;
174 cfe
->memspace
[0].hostaddr
= 0;
175 } else if (cfe
->memspace
[0].length
< AM79C930_MEM_SIZE
)
181 awi_pcmcia_attach(device_t parent
, device_t self
,
184 struct awi_pcmcia_softc
*psc
= device_private(self
);
185 struct awi_softc
*sc
= &psc
->sc_awi
;
186 struct pcmcia_attach_args
*pa
= aux
;
187 struct pcmcia_config_entry
*cfe
;
192 error
= pcmcia_function_configure(pa
->pf
, awi_pcmcia_validate_config
);
194 aprint_error_dev(self
, "configure failed, error=%d\n",
200 sc
->sc_chip
.sc_bustype
= AM79C930_BUS_PCMCIA
;
201 sc
->sc_chip
.sc_iot
= cfe
->iospace
[0].handle
.iot
;
202 sc
->sc_chip
.sc_ioh
= cfe
->iospace
[0].handle
.ioh
;
203 if (cfe
->num_memspace
> 0) {
204 sc
->sc_chip
.sc_memt
= cfe
->memspace
[0].handle
.memt
;
205 sc
->sc_chip
.sc_memh
= cfe
->memspace
[0].handle
.memh
;
206 am79c930_chip_init(&sc
->sc_chip
, 1);
208 am79c930_chip_init(&sc
->sc_chip
, 0);
210 error
= awi_pcmcia_enable(sc
);
215 awi_read_bytes(sc
, AWI_BANNER
, sc
->sc_banner
, AWI_BANNER_LEN
);
216 if (memcmp(sc
->sc_banner
, "PCnetMobile:", 12))
219 sc
->sc_enable
= awi_pcmcia_enable
;
220 sc
->sc_disable
= awi_pcmcia_disable
;
224 if (awi_attach(sc
) != 0) {
225 aprint_error_dev(self
, "failed to attach controller\n");
230 awi_pcmcia_disable(sc
);
231 psc
->sc_state
= AWI_PCMCIA_ATTACHED
;
236 awi_pcmcia_disable(sc
);
238 pcmcia_function_unconfigure(pa
->pf
);
242 awi_pcmcia_detach(device_t self
, int flags
)
244 struct awi_pcmcia_softc
*psc
= device_private(self
);
247 if (psc
->sc_state
!= AWI_PCMCIA_ATTACHED
)
250 error
= awi_detach(&psc
->sc_awi
);
254 pcmcia_function_unconfigure(psc
->sc_pf
);