This source file includes following definitions.
- awi_pcmcia_lookup
- awi_pcmcia_enable
- awi_pcmcia_disable
- awi_pcmcia_match
- awi_pcmcia_find
- awi_pcmcia_attach
- awi_pcmcia_detach
- awi_pcmcia_powerhook
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 #include "bpfilter.h"
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/mbuf.h>
53 #include <sys/socket.h>
54 #include <sys/ioctl.h>
55 #include <sys/errno.h>
56 #include <sys/syslog.h>
57 #include <sys/selinfo.h>
58 #include <sys/device.h>
59
60 #include <net/if.h>
61 #include <net/if_dl.h>
62 #include <net/if_media.h>
63
64 #include <netinet/in.h>
65 #include <netinet/if_ether.h>
66
67 #include <net80211/ieee80211.h>
68 #include <net80211/ieee80211_ioctl.h>
69
70 #if NBPFILTER > 0
71 #include <net/bpf.h>
72 #endif
73
74 #include <machine/cpu.h>
75 #include <machine/bus.h>
76 #include <machine/intr.h>
77
78 #include <dev/ic/am79c930reg.h>
79 #include <dev/ic/am79c930var.h>
80 #include <dev/ic/awireg.h>
81 #include <dev/ic/awivar.h>
82
83 #include <dev/pcmcia/pcmciareg.h>
84 #include <dev/pcmcia/pcmciavar.h>
85 #include <dev/pcmcia/pcmciadevs.h>
86
87 struct awi_pcmcia_softc {
88 struct awi_softc sc_awi;
89
90
91 struct pcmcia_io_handle sc_pcioh;
92 struct pcmcia_mem_handle sc_memh;
93 int sc_io_window;
94 int sc_mem_window;
95 struct pcmcia_function *sc_pf;
96 void *sc_powerhook;
97 };
98
99 static int awi_pcmcia_match(struct device *, void *, void *);
100 static void awi_pcmcia_attach(struct device *, struct device *, void *);
101 static int awi_pcmcia_detach(struct device *, int);
102 static int awi_pcmcia_enable(struct awi_softc *);
103 static void awi_pcmcia_disable(struct awi_softc *);
104 static void awi_pcmcia_powerhook(int, void *);
105
106 static int awi_pcmcia_find(struct awi_pcmcia_softc *,
107 struct pcmcia_attach_args *, struct pcmcia_config_entry *);
108
109 struct cfattach awi_pcmcia_ca = {
110 sizeof(struct awi_pcmcia_softc), awi_pcmcia_match, awi_pcmcia_attach,
111 awi_pcmcia_detach, awi_activate
112 };
113
114 static struct awi_pcmcia_product {
115 u_int16_t app_vendor;
116 u_int16_t app_product;
117 const char *app_cisinfo[4];
118 const char *app_name;
119 } awi_pcmcia_products[] = {
120 { PCMCIA_VENDOR_BAY, PCMCIA_PRODUCT_BAY_STACK_650,
121 PCMCIA_CIS_BAY_STACK_650, "BayStack 650" },
122
123 { PCMCIA_VENDOR_BAY, PCMCIA_PRODUCT_BAY_STACK_660,
124 PCMCIA_CIS_BAY_STACK_660, "BayStack 660" },
125
126 { PCMCIA_VENDOR_BAY, PCMCIA_PRODUCT_BAY_SURFER_PRO,
127 PCMCIA_CIS_BAY_SURFER_PRO, "AirSurfer Pro" },
128
129 { PCMCIA_VENDOR_AMD, PCMCIA_PRODUCT_AMD_AM79C930,
130 PCMCIA_CIS_AMD_AM79C930, "AMD AM79C930" },
131
132 { PCMCIA_VENDOR_ICOM, PCMCIA_PRODUCT_ICOM_SL200,
133 PCMCIA_CIS_ICOM_SL200, "Icom SL-200" },
134
135 { PCMCIA_VENDOR_NOKIA, PCMCIA_PRODUCT_NOKIA_C020_WLAN,
136 PCMCIA_CIS_NOKIA_C020_WLAN, "Nokia C020" },
137
138 { PCMCIA_VENDOR_FARALLON, PCMCIA_PRODUCT_FARALLON_SKYLINE,
139 PCMCIA_CIS_FARALLON_SKYLINE, "SkyLINE Wireless" },
140
141 { PCMCIA_VENDOR_ZOOM, PCMCIA_PRODUCT_ZOOM_AIR4000,
142 PCMCIA_CIS_ZOOM_AIR4000, "Zoom Air-4000" },
143
144
145
146
147 { 0, 0,
148 { NULL, NULL, NULL, NULL }, NULL },
149 };
150
151 static struct awi_pcmcia_product *
152 awi_pcmcia_lookup(struct pcmcia_attach_args *);
153
154 static struct awi_pcmcia_product *
155 awi_pcmcia_lookup(pa)
156 struct pcmcia_attach_args *pa;
157 {
158 struct awi_pcmcia_product *app;
159
160 for (app = awi_pcmcia_products; app->app_name != NULL; app++) {
161
162 if (pa->manufacturer != PCMCIA_VENDOR_INVALID &&
163 pa->manufacturer == app->app_vendor &&
164 pa->product != PCMCIA_PRODUCT_INVALID &&
165 pa->product == app->app_product)
166 return (app);
167
168
169 if (pa->card->cis1_info[0] != NULL &&
170 app->app_cisinfo[0] != NULL &&
171 strcmp(pa->card->cis1_info[0], app->app_cisinfo[0]) == 0 &&
172 pa->card->cis1_info[1] != NULL &&
173 app->app_cisinfo[1] != NULL &&
174 strcmp(pa->card->cis1_info[1], app->app_cisinfo[1]) == 0)
175 return (app);
176 }
177
178 return (NULL);
179 }
180
181 static int
182 awi_pcmcia_enable(sc)
183 struct awi_softc *sc;
184 {
185 struct awi_pcmcia_softc *psc = (struct awi_pcmcia_softc *)sc;
186 struct pcmcia_function *pf = psc->sc_pf;
187
188
189 sc->sc_ih = pcmcia_intr_establish(pf, IPL_NET, awi_intr,
190 sc, sc->sc_dev.dv_xname);
191 if (sc->sc_ih == NULL) {
192 printf("%s: couldn't establish interrupt\n",
193 sc->sc_dev.dv_xname);
194 return (1);
195 }
196
197 if (pcmcia_function_enable(pf)) {
198 pcmcia_intr_disestablish(pf, sc->sc_ih);
199 return (1);
200 }
201 DELAY(1000);
202
203 return (0);
204 }
205
206 static void
207 awi_pcmcia_disable(sc)
208 struct awi_softc *sc;
209 {
210 struct awi_pcmcia_softc *psc = (struct awi_pcmcia_softc *)sc;
211 struct pcmcia_function *pf = psc->sc_pf;
212
213 pcmcia_intr_disestablish (pf, sc->sc_ih);
214 pcmcia_function_disable (pf);
215 }
216
217 static int
218 awi_pcmcia_match(parent, match, aux)
219 struct device *parent;
220 void *match;
221 void *aux;
222 {
223 struct pcmcia_attach_args *pa = aux;
224
225 if (awi_pcmcia_lookup(pa) != NULL)
226 return (1);
227
228 return (0);
229 }
230
231 static int
232 awi_pcmcia_find(psc, pa, cfe)
233 struct awi_pcmcia_softc *psc;
234 struct pcmcia_attach_args *pa;
235 struct pcmcia_config_entry *cfe;
236 {
237 struct awi_softc *sc = &psc->sc_awi;
238 int fail = 0;
239 u_int8_t version[AWI_BANNER_LEN];
240
241
242
243
244
245
246 if (pcmcia_io_alloc(psc->sc_pf, cfe->iospace[0].start,
247 cfe->iospace[0].length, AM79C930_IO_ALIGN,
248 &psc->sc_pcioh) != 0)
249 goto fail;
250
251 if (pcmcia_io_map(psc->sc_pf, PCMCIA_WIDTH_AUTO, 0, psc->sc_pcioh.size,
252 &psc->sc_pcioh, &psc->sc_io_window))
253 goto fail_io_free;
254
255
256 pcmcia_function_init(psc->sc_pf, cfe);
257 if (pcmcia_function_enable(psc->sc_pf))
258 goto fail_io_unmap;
259
260 sc->sc_chip.sc_bustype = AM79C930_BUS_PCMCIA;
261 sc->sc_chip.sc_iot = psc->sc_pcioh.iot;
262 sc->sc_chip.sc_ioh = psc->sc_pcioh.ioh;
263 am79c930_chip_init(&sc->sc_chip, 0);
264
265 DELAY(1000);
266
267 awi_read_bytes(sc, AWI_BANNER, version, AWI_BANNER_LEN);
268
269 if (memcmp(version, "PCnetMobile:", 12) == 0)
270 return (0);
271
272 fail++;
273 pcmcia_function_disable(psc->sc_pf);
274
275 fail_io_unmap:
276 fail++;
277 pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
278
279 fail_io_free:
280 fail++;
281 pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
282 fail:
283 fail++;
284 psc->sc_io_window = -1;
285 return (fail);
286 }
287
288 static void
289 awi_pcmcia_attach(parent, self, aux)
290 struct device *parent, *self;
291 void *aux;
292 {
293 struct awi_pcmcia_softc *psc = (void *)self;
294 struct awi_softc *sc = &psc->sc_awi;
295 struct awi_pcmcia_product *app;
296 struct pcmcia_attach_args *pa = aux;
297 struct pcmcia_config_entry *cfe;
298 const char *intrstr;
299 #if 0
300 bus_addr_t memoff;
301 #endif
302
303 app = awi_pcmcia_lookup(pa);
304 if (app == NULL)
305 panic("awi_pcmcia_attach: impossible");
306
307 psc->sc_pf = pa->pf;
308
309 for (cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head); cfe != NULL;
310 cfe = SIMPLEQ_NEXT(cfe, cfe_list)) {
311 if (cfe->iftype != PCMCIA_IFTYPE_IO)
312 continue;
313 if (cfe->num_iospace < 1)
314 continue;
315 if (cfe->iospace[0].length < AM79C930_IO_SIZE)
316 continue;
317
318 if (awi_pcmcia_find(psc, pa, cfe) == 0)
319 break;
320 }
321 if (cfe == NULL) {
322 printf(": no suitable CIS info found\n");
323 goto no_config_entry;
324 }
325
326 sc->sc_enabled = 1;
327 printf(": %s\n", app->app_name);
328
329 psc->sc_mem_window = -1;
330 #if 0
331 if (pcmcia_mem_alloc(psc->sc_pf, AM79C930_MEM_SIZE,
332 &psc->sc_memh) != 0) {
333 printf("%s: unable to allocate memory space; using i/o only\n",
334 sc->sc_dev.dv_xname);
335 } else if (pcmcia_mem_map(psc->sc_pf,
336 PCMCIA_MEM_COMMON, AM79C930_MEM_BASE,
337 AM79C930_MEM_SIZE, &psc->sc_memh, &memoff, &psc->sc_mem_window)) {
338 printf("%s: unable to map memory space; using i/o only\n",
339 sc->sc_dev.dv_xname);
340 pcmcia_mem_free(psc->sc_pf, &psc->sc_memh);
341 } else {
342 sc->sc_chip.sc_memt = psc->sc_memh.memt;
343 sc->sc_chip.sc_memh = psc->sc_memh.memh;
344 am79c930_chip_init(&sc->sc_chip, 1);
345 }
346 #endif
347
348 sc->sc_enable = awi_pcmcia_enable;
349 sc->sc_disable = awi_pcmcia_disable;
350
351
352 sc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET,
353 awi_intr, sc, sc->sc_dev.dv_xname);
354 intrstr = pcmcia_intr_string(psc->sc_pf, sc->sc_ih);
355 if (sc->sc_ih == NULL) {
356 printf(", %s\n", intrstr);
357 goto no_interrupt;
358 }
359 if (*intrstr)
360 printf(", %s", intrstr);
361 sc->sc_ifp = &sc->sc_arpcom.ac_if;
362 sc->sc_cansleep = 1;
363
364 if (awi_attach(sc) != 0) {
365 printf("%s: failed to attach controller\n",
366 sc->sc_dev.dv_xname);
367 goto attach_failed;
368 }
369 psc->sc_powerhook = powerhook_establish(awi_pcmcia_powerhook, psc);
370
371 sc->sc_enabled = 0;
372
373 awi_pcmcia_disable(sc);
374 return;
375
376 attach_failed:
377 pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih);
378
379 no_interrupt:
380
381 if (psc->sc_mem_window != -1) {
382 pcmcia_mem_unmap(psc->sc_pf, psc->sc_mem_window);
383 pcmcia_mem_free(psc->sc_pf, &psc->sc_memh);
384 }
385
386
387 pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
388 pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
389
390
391 pcmcia_function_disable(psc->sc_pf);
392
393 no_config_entry:
394 psc->sc_io_window = -1;
395 }
396
397
398 static int
399 awi_pcmcia_detach(self, flags)
400 struct device *self;
401 int flags;
402 {
403 struct awi_pcmcia_softc *psc = (struct awi_pcmcia_softc *)self;
404 int error;
405
406 if (psc->sc_io_window == -1)
407
408 return (0);
409
410 if (psc->sc_powerhook != NULL)
411 powerhook_disestablish(psc->sc_powerhook);
412
413 error = awi_detach(&psc->sc_awi);
414 if (error != 0)
415 return (error);
416
417
418 if (psc->sc_mem_window != -1) {
419 pcmcia_mem_unmap(psc->sc_pf, psc->sc_mem_window);
420 pcmcia_mem_free(psc->sc_pf, &psc->sc_memh);
421 }
422
423
424 pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
425
426
427 pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
428 return (0);
429 }
430
431 static void
432 awi_pcmcia_powerhook(why, arg)
433 int why;
434 void *arg;
435 {
436 struct awi_pcmcia_softc *psc = arg;
437 struct awi_softc *sc = &psc->sc_awi;
438
439 awi_power(sc, why);
440 }