This source file includes following definitions.
- malo_pcmcia_match
- malo_pcmcia_attach
- malo_pcmcia_detach
- malo_pcmcia_activate
- cmalo_attach
- cmalo_ioctl
- cmalo_fw_load_helper
- cmalo_fw_load_main
- cmalo_init
- cmalo_stop
- cmalo_media_change
- cmalo_newstate
- cmalo_detach
- cmalo_intr
- cmalo_intr_mask
- cmalo_rx
- cmalo_start
- cmalo_watchdog
- cmalo_tx
- cmalo_tx_done
- cmalo_event
- cmalo_select_network
- cmalo_reflect_network
- cmalo_wep
- cmalo_hexdump
- cmalo_cmd_get_hwspec
- cmalo_cmd_rsp_hwspec
- cmalo_cmd_set_reset
- cmalo_cmd_set_scan
- cmalo_cmd_rsp_scan
- cmalo_parse_elements
- cmalo_cmd_set_auth
- cmalo_cmd_set_wep
- cmalo_cmd_set_snmp
- cmalo_cmd_set_radio
- cmalo_cmd_set_channel
- cmalo_cmd_set_txpower
- cmalo_cmd_set_antenna
- cmalo_cmd_set_macctrl
- cmalo_cmd_set_assoc
- cmalo_cmd_rsp_assoc
- cmalo_cmd_set_80211d
- cmalo_cmd_set_bgscan_config
- cmalo_cmd_set_bgscan_query
- cmalo_cmd_set_rate
- cmalo_cmd_request
- cmalo_cmd_response
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include "bpfilter.h"
20
21 #include <sys/param.h>
22 #include <sys/proc.h>
23 #include <sys/systm.h>
24 #include <sys/kernel.h>
25 #include <sys/device.h>
26 #include <sys/timeout.h>
27 #include <sys/socket.h>
28 #include <sys/tree.h>
29 #include <sys/malloc.h>
30 #include <sys/sockio.h>
31 #include <sys/mbuf.h>
32
33 #if NBPFILTER > 0
34 #include <net/bpf.h>
35 #endif
36
37 #include <net/if.h>
38 #include <net/if_media.h>
39 #include <net/if_llc.h>
40
41 #include <netinet/in.h>
42 #include <netinet/in_systm.h>
43 #include <netinet/if_ether.h>
44
45 #include <net80211/ieee80211_var.h>
46 #include <net80211/ieee80211_radiotap.h>
47
48 #include <machine/bus.h>
49 #include <machine/intr.h>
50
51 #include <dev/pcmcia/pcmciareg.h>
52 #include <dev/pcmcia/pcmciavar.h>
53 #include <dev/pcmcia/pcmciadevs.h>
54
55 #include <dev/pcmcia/if_malovar.h>
56 #include <dev/pcmcia/if_maloreg.h>
57
58
59
60
61
62 #ifdef CMALO_DEBUG
63 int cmalo_d = 1;
64 #define DPRINTF(l, x...) do { if ((l) <= cmalo_d) printf(x); } while (0)
65 #else
66 #define DPRINTF(l, x...)
67 #endif
68
69 int malo_pcmcia_match(struct device *, void *, void *);
70 void malo_pcmcia_attach(struct device *, struct device *, void *);
71 int malo_pcmcia_detach(struct device *, int);
72 int malo_pcmcia_activate(struct device *, enum devact);
73
74 void cmalo_attach(void *);
75 int cmalo_ioctl(struct ifnet *, u_long, caddr_t);
76 int cmalo_fw_load_helper(struct malo_softc *);
77 int cmalo_fw_load_main(struct malo_softc *);
78 int cmalo_init(struct ifnet *);
79 void cmalo_stop(struct malo_softc *);
80 int cmalo_media_change(struct ifnet *);
81 int cmalo_newstate(struct ieee80211com *, enum ieee80211_state, int);
82 void cmalo_detach(void *);
83 int cmalo_intr(void *);
84 void cmalo_intr_mask(struct malo_softc *, int);
85 void cmalo_rx(struct malo_softc *);
86 void cmalo_start(struct ifnet *);
87 void cmalo_watchdog(struct ifnet *);
88 int cmalo_tx(struct malo_softc *, struct mbuf *);
89 void cmalo_tx_done(struct malo_softc *);
90 void cmalo_event(struct malo_softc *);
91 void cmalo_select_network(struct malo_softc *);
92 void cmalo_reflect_network(struct malo_softc *);
93 int cmalo_wep(struct malo_softc *);
94
95 void cmalo_hexdump(void *, int);
96 int cmalo_cmd_get_hwspec(struct malo_softc *);
97 int cmalo_cmd_rsp_hwspec(struct malo_softc *);
98 int cmalo_cmd_set_reset(struct malo_softc *);
99 int cmalo_cmd_set_scan(struct malo_softc *);
100 int cmalo_cmd_rsp_scan(struct malo_softc *);
101 int cmalo_parse_elements(struct malo_softc *, void *, int, int);
102 int cmalo_cmd_set_auth(struct malo_softc *);
103 int cmalo_cmd_set_wep(struct malo_softc *, uint16_t,
104 struct ieee80211_key *);
105 int cmalo_cmd_set_snmp(struct malo_softc *, uint16_t);
106 int cmalo_cmd_set_radio(struct malo_softc *, uint16_t);
107 int cmalo_cmd_set_channel(struct malo_softc *, uint16_t);
108 int cmalo_cmd_set_txpower(struct malo_softc *, int16_t);
109 int cmalo_cmd_set_antenna(struct malo_softc *, uint16_t);
110 int cmalo_cmd_set_macctrl(struct malo_softc *);
111 int cmalo_cmd_set_assoc(struct malo_softc *);
112 int cmalo_cmd_rsp_assoc(struct malo_softc *);
113 int cmalo_cmd_set_80211d(struct malo_softc *);
114 int cmalo_cmd_set_bgscan_config(struct malo_softc *);
115 int cmalo_cmd_set_bgscan_query(struct malo_softc *);
116 int cmalo_cmd_set_rate(struct malo_softc *);
117 int cmalo_cmd_request(struct malo_softc *, uint16_t, int);
118 int cmalo_cmd_response(struct malo_softc *);
119
120
121
122
123 struct malo_pcmcia_softc {
124 struct malo_softc sc_malo;
125
126 struct pcmcia_function *sc_pf;
127 struct pcmcia_io_handle sc_pcioh;
128 int sc_io_window;
129 void *sc_ih;
130 };
131
132 struct cfattach malo_pcmcia_ca = {
133 sizeof(struct malo_pcmcia_softc),
134 malo_pcmcia_match,
135 malo_pcmcia_attach,
136 malo_pcmcia_detach,
137 malo_pcmcia_activate
138 };
139
140 int
141 malo_pcmcia_match(struct device *parent, void *match, void *aux)
142 {
143 struct pcmcia_attach_args *pa = aux;
144
145 if (pa->manufacturer == PCMCIA_VENDOR_AMBICOM &&
146 pa->product == PCMCIA_PRODUCT_AMBICOM_WL54CF)
147 return (1);
148
149 return (0);
150 }
151
152 void
153 malo_pcmcia_attach(struct device *parent, struct device *self, void *aux)
154 {
155 struct malo_pcmcia_softc *psc = (struct malo_pcmcia_softc *)self;
156 struct malo_softc *sc = &psc->sc_malo;
157 struct pcmcia_attach_args *pa = aux;
158 struct pcmcia_config_entry *cfe;
159 const char *intrstr = NULL;
160
161 psc->sc_pf = pa->pf;
162 cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head);
163
164
165 pcmcia_function_init(psc->sc_pf, cfe);
166 if (pcmcia_function_enable(psc->sc_pf)) {
167 printf(": can't enable function!\n");
168 return;
169 }
170
171
172 if (pcmcia_io_alloc(psc->sc_pf, 0,
173 cfe->iospace[0].length, cfe->iospace[0].length, &psc->sc_pcioh)) {
174 printf(": can't allocate i/o space!\n");
175 pcmcia_function_disable(psc->sc_pf);
176 return;
177 }
178
179
180 if (pcmcia_io_map(psc->sc_pf, PCMCIA_WIDTH_IO16, 0,
181 cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) {
182 printf(": can't map i/o space!\n");
183 pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
184 pcmcia_function_disable(psc->sc_pf);
185 return;
186 }
187 sc->sc_iot = psc->sc_pcioh.iot;
188 sc->sc_ioh = psc->sc_pcioh.ioh;
189
190 printf(" port 0x%x/%d", psc->sc_pcioh.addr, psc->sc_pcioh.size);
191
192
193 psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, cmalo_intr, sc,
194 sc->sc_dev.dv_xname);
195 if (psc->sc_ih == NULL) {
196 printf(": can't establish interrupt!\n");
197 return;
198 }
199 intrstr = pcmcia_intr_string(psc->sc_pf, psc->sc_ih);
200 if (intrstr != NULL) {
201 if (*intrstr != NULL)
202 printf(", %s", intrstr);
203 }
204 printf("\n");
205
206
207 if (rootvp == NULL)
208 mountroothook_establish(cmalo_attach, sc);
209 else
210 cmalo_attach(sc);
211 }
212
213 int
214 malo_pcmcia_detach(struct device *dev, int flags)
215 {
216 struct malo_pcmcia_softc *psc = (struct malo_pcmcia_softc *)dev;
217 struct malo_softc *sc = &psc->sc_malo;
218
219 cmalo_detach(sc);
220
221 pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
222 pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
223
224 return (0);
225 }
226
227 int
228 malo_pcmcia_activate(struct device *dev, enum devact act)
229 {
230 struct malo_pcmcia_softc *psc = (struct malo_pcmcia_softc *)dev;
231 struct malo_softc *sc = &psc->sc_malo;
232 struct ieee80211com *ic = &sc->sc_ic;
233 struct ifnet *ifp = &ic->ic_if;
234 int s;
235
236 s = splnet();
237 switch (act) {
238 case DVACT_ACTIVATE:
239 pcmcia_function_enable(psc->sc_pf);
240 psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET,
241 cmalo_intr, sc, sc->sc_dev.dv_xname);
242 cmalo_init(ifp);
243 break;
244 case DVACT_DEACTIVATE:
245 ifp->if_timer = 0;
246 if (ifp->if_flags & IFF_RUNNING)
247 cmalo_stop(sc);
248 if (psc->sc_ih != NULL)
249 pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
250 pcmcia_function_disable(psc->sc_pf);
251 break;
252 }
253 splx(s);
254
255 return (0);
256 }
257
258
259
260
261 void
262 cmalo_attach(void *arg)
263 {
264 struct malo_softc *sc = arg;
265 struct ieee80211com *ic = &sc->sc_ic;
266 struct ifnet *ifp = &sc->sc_ic.ic_if;
267 int i;
268
269
270 cmalo_intr_mask(sc, 0);
271
272
273 if (cmalo_fw_load_helper(sc) != 0)
274 return;
275 if (cmalo_fw_load_main(sc) != 0)
276 return;
277 sc->sc_flags |= MALO_FW_LOADED;
278
279
280 sc->sc_cmd = malloc(MALO_CMD_BUFFER_SIZE, M_DEVBUF, M_NOWAIT);
281
282
283 sc->sc_data = malloc(MCLBYTES, M_DEVBUF, M_NOWAIT);
284
285
286 cmalo_intr_mask(sc, 1);
287
288
289 sc->sc_cmd_ctxsave = 1;
290
291
292 cmalo_cmd_get_hwspec(sc);
293
294
295 ifp->if_softc = sc;
296 ifp->if_ioctl = cmalo_ioctl;
297 ifp->if_init = cmalo_init;
298 ifp->if_start = cmalo_start;
299 ifp->if_watchdog = cmalo_watchdog;
300 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
301 strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
302 IFQ_SET_READY(&ifp->if_snd);
303
304 ic->ic_opmode = IEEE80211_M_STA;
305 ic->ic_state = IEEE80211_S_INIT;
306 ic->ic_caps = IEEE80211_C_MONITOR | IEEE80211_C_WEP;
307
308 ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
309 ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
310
311 for (i = 0; i <= 14; i++) {
312 ic->ic_channels[i].ic_freq =
313 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
314 ic->ic_channels[i].ic_flags =
315 IEEE80211_CHAN_B |
316 IEEE80211_CHAN_G;
317 }
318
319
320 if_attach(ifp);
321 ieee80211_ifattach(ifp);
322
323 sc->sc_newstate = ic->ic_newstate;
324 ic->ic_newstate = cmalo_newstate;
325 ieee80211_media_init(ifp, cmalo_media_change, ieee80211_media_status);
326
327
328 printf("%s: address %s\n",
329 sc->sc_dev.dv_xname, ether_sprintf(ic->ic_myaddr));
330
331
332 sc->sc_flags |= MALO_DEVICE_ATTACHED;
333 }
334
335 int
336 cmalo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
337 {
338 struct malo_softc *sc = ifp->if_softc;
339 struct ieee80211com *ic = &sc->sc_ic;
340 struct ieee80211_nodereq_all *na;
341 struct ieee80211_nodereq *nr;
342 struct ifaddr *ifa;
343 struct ifreq *ifr;
344 int i, j, s, error = 0;
345
346 s = splnet();
347
348 switch (cmd) {
349 case SIOCSIFADDR:
350 ifa = (struct ifaddr *)data;
351 ifp->if_flags |= IFF_UP;
352 #ifdef INET
353 if (ifa->ifa_addr->sa_family == AF_INET)
354 arp_ifinit(&ic->ic_ac, ifa);
355 #endif
356
357 case SIOCSIFFLAGS:
358 if (ifp->if_flags & IFF_UP) {
359 if ((ifp->if_flags & IFF_RUNNING) == 0)
360 cmalo_init(ifp);
361 } else {
362 if (ifp->if_flags & IFF_RUNNING)
363 cmalo_stop(sc);
364 }
365 break;
366 case SIOCADDMULTI:
367 case SIOCDELMULTI:
368 ifr = (struct ifreq *)data;
369 error = (cmd == SIOCADDMULTI) ?
370 ether_addmulti(ifr, &ic->ic_ac) :
371 ether_delmulti(ifr, &ic->ic_ac);
372 if (error == ENETRESET)
373 error = 0;
374 break;
375 case SIOCS80211SCAN:
376 cmalo_cmd_set_scan(sc);
377 break;
378 case SIOCG80211ALLNODES:
379 nr = NULL;
380 na = (struct ieee80211_nodereq_all *)data;
381
382 if ((nr = malloc(sizeof(*nr), M_DEVBUF, M_WAITOK)) == NULL)
383 break;
384
385 for (na->na_nodes = i = j = 0; i < sc->sc_net_num &&
386 (na->na_size >= j + sizeof(struct ieee80211_nodereq));
387 i++) {
388 bzero(nr, sizeof(*nr));
389
390 IEEE80211_ADDR_COPY(nr->nr_macaddr,
391 sc->sc_net[i].bssid);
392 IEEE80211_ADDR_COPY(nr->nr_bssid,
393 sc->sc_net[i].bssid);
394 nr->nr_channel = sc->sc_net[i].channel;
395 nr->nr_chan_flags = IEEE80211_CHAN_B;
396 nr->nr_rssi = sc->sc_net[i].rssi;
397 nr->nr_max_rssi = 0;
398 nr->nr_nwid_len = strlen(sc->sc_net[i].ssid);
399 bcopy(sc->sc_net[i].ssid, nr->nr_nwid,
400 nr->nr_nwid_len);
401 nr->nr_intval = sc->sc_net[i].beaconintvl;
402 nr->nr_capinfo = sc->sc_net[i].capinfo;
403 nr->nr_flags |= IEEE80211_NODEREQ_AP;
404
405 if (copyout(nr, (caddr_t)na->na_node + j,
406 sizeof(struct ieee80211_nodereq)))
407 break;
408
409 j += sizeof(struct ieee80211_nodereq);
410 na->na_nodes++;
411 }
412
413 if (nr)
414 free(nr, M_DEVBUF);
415 break;
416 default:
417 error = ieee80211_ioctl(ifp, cmd, data);
418 break;
419 }
420
421 if (error == ENETRESET) {
422 if (ifp->if_flags & (IFF_UP | IFF_RUNNING))
423 cmalo_init(ifp);
424 error = 0;
425 }
426
427 splx(s);
428
429 return (error);
430 }
431
432 int
433 cmalo_fw_load_helper(struct malo_softc *sc)
434 {
435 const char *name = "malo8385-h";
436 size_t usize;
437 uint8_t val8, *ucode;
438 uint16_t bsize, *uc;
439 int error, offset, i;
440
441
442 val8 = MALO_READ_1(sc, MALO_REG_SCRATCH);
443 if (val8 == MALO_VAL_SCRATCH_FW_LOADED)
444
445 return (0);
446 if (val8 != MALO_VAL_SCRATCH_READY) {
447
448 printf("%s: device not ready for FW download!\n",
449 sc->sc_dev.dv_xname);
450 return (EIO);
451 }
452
453
454 if ((error = loadfirmware(name, &ucode, &usize)) != 0) {
455 printf("%s: can't read microcode %s (error %d)!\n",
456 sc->sc_dev.dv_xname, name, error);
457 return (EIO);
458 }
459
460
461 for (offset = 0; offset < usize; offset += bsize) {
462 if (usize - offset >= MALO_FW_HELPER_BSIZE)
463 bsize = MALO_FW_HELPER_BSIZE;
464 else
465 bsize = usize - offset;
466
467
468 DPRINTF(3, "%s: download helper FW block (%d bytes, %d off)\n",
469 sc->sc_dev.dv_xname, bsize, offset);
470 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, bsize);
471 uc = (uint16_t *)(ucode + offset);
472 for (i = 0; i < bsize / 2; i++)
473 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i]));
474 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER);
475 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE,
476 MALO_VAL_CMD_DL_OVER);
477
478
479 for (i = 0; i < 50; i++) {
480 if (MALO_READ_1(sc, MALO_REG_CARD_STATUS) ==
481 MALO_VAL_CMD_DL_OVER)
482 break;
483 delay(1000);
484 }
485 if (i == 50) {
486 printf("%s: timeout while helper FW block download!\n",
487 sc->sc_dev.dv_xname);
488 free(ucode, M_DEVBUF);
489 return (EIO);
490 }
491 }
492 free(ucode, M_DEVBUF);
493
494
495 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, 0);
496 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER);
497 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_CMD_DL_OVER);
498 DPRINTF(1, "%s: helper FW downloaded\n", sc->sc_dev.dv_xname);
499
500 return (0);
501 }
502
503 int
504 cmalo_fw_load_main(struct malo_softc *sc)
505 {
506 const char *name = "malo8385-m";
507 size_t usize;
508 uint8_t *ucode;
509 uint16_t val16, bsize, *uc;
510 int error, offset, i, retry;
511
512
513 if ((error = loadfirmware(name, &ucode, &usize)) != 0) {
514 printf("%s: can't read microcode %s (error %d)!\n",
515 sc->sc_dev.dv_xname, name, error);
516 return (EIO);
517 }
518
519
520 for (i = 0; i < 10; i++) {
521 if (MALO_READ_1(sc, MALO_REG_RBAL) == MALO_FW_HELPER_LOADED)
522 break;
523 delay(1000);
524 }
525 if (i == 10) {
526 printf("%s: helper FW not loaded!\n", sc->sc_dev.dv_xname);
527 free(ucode, M_DEVBUF);
528 return (EIO);
529 }
530 DPRINTF(1, "%s: helper FW loaded successfully\n", sc->sc_dev.dv_xname);
531
532
533 for (offset = 0; offset < usize; offset += bsize) {
534 val16 = MALO_READ_2(sc, MALO_REG_RBAL);
535
536
537
538
539
540 if (val16 & 0x0001) {
541 if (retry > MALO_FW_MAIN_MAXRETRY) {
542 printf("%s: main FW download failed!\n",
543 sc->sc_dev.dv_xname);
544 free(ucode, M_DEVBUF);
545 return (EIO);
546 }
547 retry++;
548 offset -= bsize;
549 } else {
550 retry = 0;
551 bsize = val16;
552 }
553
554
555 DPRINTF(3, "%s: download main FW block (%d bytes, %d off)\n",
556 sc->sc_dev.dv_xname, bsize, offset);
557 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, bsize);
558 uc = (uint16_t *)(ucode + offset);
559 for (i = 0; i < bsize / 2; i++)
560 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i]));
561 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER);
562 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE,
563 MALO_VAL_CMD_DL_OVER);
564
565
566 for (i = 0; i < 5000; i++) {
567 if (MALO_READ_1(sc, MALO_REG_CARD_STATUS) ==
568 MALO_VAL_CMD_DL_OVER)
569 break;
570 }
571 if (i == 5000) {
572 printf("%s: timeout while main FW block download!\n",
573 sc->sc_dev.dv_xname);
574 free(ucode, M_DEVBUF);
575 return (EIO);
576 }
577 }
578 free(ucode, M_DEVBUF);
579
580 DPRINTF(1, "%s: main FW downloaded\n", sc->sc_dev.dv_xname);
581
582
583 for (i = 0; i < 50; i++) {
584 if (MALO_READ_1(sc, MALO_REG_SCRATCH) ==
585 MALO_VAL_SCRATCH_FW_LOADED)
586 break;
587 delay(1000);
588 }
589 if (i == 50) {
590 printf("%s: main FW not loaded!\n", sc->sc_dev.dv_xname);
591 return (EIO);
592 }
593
594 DPRINTF(1, "%s: main FW loaded successfully\n", sc->sc_dev.dv_xname);
595
596 return (0);
597 }
598
599 int
600 cmalo_init(struct ifnet *ifp)
601 {
602 struct malo_softc *sc = ifp->if_softc;
603 struct ieee80211com *ic = &sc->sc_ic;
604
605
606 if (!(sc->sc_flags & MALO_FW_LOADED)) {
607
608 cmalo_intr_mask(sc, 0);
609
610
611 if (cmalo_fw_load_helper(sc) != 0)
612 return (EIO);
613 if (cmalo_fw_load_main(sc) != 0)
614 return (EIO);
615 sc->sc_flags |= MALO_FW_LOADED;
616
617
618 cmalo_intr_mask(sc, 1);
619 }
620
621
622 sc->sc_flags &= ~MALO_ASSOC_FAILED;
623
624
625 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
626 sc->sc_curchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
627 DPRINTF(1, "%s: current channel is %d\n",
628 sc->sc_dev.dv_xname, sc->sc_curchan);
629
630
631 if (cmalo_cmd_set_macctrl(sc) != 0)
632 return (EIO);
633 if (cmalo_cmd_set_txpower(sc, 15) != 0)
634 return (EIO);
635 if (cmalo_cmd_set_antenna(sc, 1) != 0)
636 return (EIO);
637 if (cmalo_cmd_set_antenna(sc, 2) != 0)
638 return (EIO);
639 if (cmalo_cmd_set_radio(sc, 1) != 0)
640 return (EIO);
641 if (cmalo_cmd_set_channel(sc, sc->sc_curchan) != 0)
642 return (EIO);
643 if (cmalo_cmd_set_rate(sc) != 0)
644 return (EIO);
645 if (cmalo_cmd_set_snmp(sc, MALO_OID_RTSTRESH) != 0)
646 return (EIO);
647 if (cmalo_cmd_set_snmp(sc, MALO_OID_SHORTRETRY) != 0)
648 return (EIO);
649 if (cmalo_cmd_set_snmp(sc, MALO_OID_FRAGTRESH) != 0)
650 return (EIO);
651 if (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) {
652 if (cmalo_wep(sc) != 0)
653 return (EIO);
654 }
655
656
657 ifp->if_flags |= IFF_RUNNING;
658 ifp->if_flags &= ~IFF_OACTIVE;
659
660
661 if (ic->ic_opmode != IEEE80211_M_MONITOR)
662 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
663 if (sc->sc_flags & MALO_ASSOC_FAILED)
664 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
665 else
666 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
667
668
669 sc->sc_cmd_ctxsave = 0;
670
671 return (0);
672 }
673
674 void
675 cmalo_stop(struct malo_softc *sc)
676 {
677 struct ieee80211com *ic = &sc->sc_ic;
678 struct ifnet *ifp = &ic->ic_if;
679
680
681 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
682
683
684 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
685
686
687 cmalo_cmd_set_reset(sc);
688 sc->sc_flags &= ~MALO_FW_LOADED;
689
690 DPRINTF(1, "%s: device down\n", sc->sc_dev.dv_xname);
691 }
692
693 int
694 cmalo_media_change(struct ifnet *ifp)
695 {
696 int error;
697
698 if ((error = ieee80211_media_change(ifp) != ENETRESET))
699 return (error);
700
701 if (ifp->if_flags & (IFF_UP | IFF_RUNNING))
702 cmalo_init(ifp);
703
704 return (0);
705 }
706
707 int
708 cmalo_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
709 {
710 struct malo_softc *sc = ic->ic_if.if_softc;
711 enum ieee80211_state ostate;
712
713 ostate = ic->ic_state;
714
715 if (ostate == nstate)
716 goto out;
717
718 switch (nstate) {
719 case IEEE80211_S_INIT:
720 DPRINTF(1, "%s: newstate is IEEE80211_S_INIT\n",
721 sc->sc_dev.dv_xname);
722 break;
723 case IEEE80211_S_SCAN:
724 DPRINTF(1, "%s: newstate is IEEE80211_S_SCAN\n",
725 sc->sc_dev.dv_xname);
726 cmalo_cmd_set_scan(sc);
727 if (!sc->sc_net_num) {
728
729 DPRINTF(1, "%s: no networks found!\n",
730 sc->sc_dev.dv_xname);
731 break;
732 }
733 cmalo_select_network(sc);
734 cmalo_cmd_set_auth(sc);
735 cmalo_cmd_set_assoc(sc);
736 break;
737 case IEEE80211_S_AUTH:
738 DPRINTF(1, "%s: newstate is IEEE80211_S_AUTH\n",
739 sc->sc_dev.dv_xname);
740 break;
741 case IEEE80211_S_ASSOC:
742 DPRINTF(1, "%s: newstate is IEEE80211_S_ASSOC\n",
743 sc->sc_dev.dv_xname);
744 break;
745 case IEEE80211_S_RUN:
746 DPRINTF(1, "%s: newstate is IEEE80211_S_RUN\n",
747 sc->sc_dev.dv_xname);
748 cmalo_reflect_network(sc);
749 break;
750 default:
751 break;
752 }
753
754 out:
755 return (sc->sc_newstate(ic, nstate, arg));
756 }
757
758 void
759 cmalo_detach(void *arg)
760 {
761 struct malo_softc *sc = arg;
762 struct ieee80211com *ic = &sc->sc_ic;
763 struct ifnet *ifp = &ic->ic_if;
764
765 if (!(sc->sc_flags & MALO_DEVICE_ATTACHED))
766
767 return;
768
769
770 if (sc->sc_cmd != NULL)
771 free(sc->sc_cmd, M_DEVBUF);
772
773
774 if (sc->sc_data != NULL)
775 free(sc->sc_data, M_DEVBUF);
776
777
778 ieee80211_ifdetach(ifp);
779 if_detach(ifp);
780 }
781
782 int
783 cmalo_intr(void *arg)
784 {
785 struct malo_softc *sc = arg;
786 uint16_t intr = 0;
787
788
789 intr = MALO_READ_2(sc, MALO_REG_HOST_INTR_CAUSE);
790 if (intr == 0) {
791
792 return (0);
793 }
794 if (intr == 0xffff) {
795
796 return (0);
797 }
798
799
800 cmalo_intr_mask(sc, 0);
801
802
803 MALO_WRITE_2(sc, MALO_REG_HOST_INTR_CAUSE,
804 intr & MALO_VAL_HOST_INTR_MASK_ON);
805
806
807 cmalo_intr_mask(sc, 1);
808
809 DPRINTF(2, "%s: interrupt handler called (intr = 0x%04x)\n",
810 sc->sc_dev.dv_xname, intr);
811
812 if (intr & MALO_VAL_HOST_INTR_TX)
813
814 cmalo_tx_done(sc);
815 if (intr & MALO_VAL_HOST_INTR_RX)
816
817 cmalo_rx(sc);
818 if (intr & MALO_VAL_HOST_INTR_CMD) {
819
820 wakeup(sc);
821 if (!sc->sc_cmd_ctxsave)
822 cmalo_cmd_response(sc);
823 }
824 if (intr & MALO_VAL_HOST_INTR_EVENT)
825
826 cmalo_event(sc);
827
828 return (1);
829 }
830
831 void
832 cmalo_intr_mask(struct malo_softc *sc, int enable)
833 {
834 uint16_t val16;
835
836 val16 = MALO_READ_2(sc, MALO_REG_HOST_INTR_MASK);
837
838 DPRINTF(3, "%s: intr mask changed from 0x%04x ",
839 sc->sc_dev.dv_xname, val16);
840
841 if (enable)
842 MALO_WRITE_2(sc, MALO_REG_HOST_INTR_MASK,
843 val16 & ~MALO_VAL_HOST_INTR_MASK_ON);
844 else
845 MALO_WRITE_2(sc, MALO_REG_HOST_INTR_MASK,
846 val16 | MALO_VAL_HOST_INTR_MASK_ON);
847
848 val16 = MALO_READ_2(sc, MALO_REG_HOST_INTR_MASK);
849
850 DPRINTF(3, "to 0x%04x\n", val16);
851 }
852
853 void
854 cmalo_rx(struct malo_softc *sc)
855 {
856 struct ieee80211com *ic = &sc->sc_ic;
857 struct ifnet *ifp = &ic->ic_if;
858 struct malo_rx_desc *rxdesc;
859 struct mbuf *m;
860 uint8_t *data;
861 uint16_t psize;
862 int i;
863
864 splassert(IPL_NET);
865
866
867 psize = MALO_READ_2(sc, MALO_REG_DATA_READ_LEN);
868 if (psize & 0x0001) {
869 MALO_READ_MULTI_2(sc, MALO_REG_DATA_READ, sc->sc_data,
870 psize - 1);
871 data = (uint8_t *)sc->sc_data;
872 data[psize - 1] = MALO_READ_1(sc, MALO_REG_DATA_READ);
873 } else
874 MALO_READ_MULTI_2(sc, MALO_REG_DATA_READ, sc->sc_data, psize);
875 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_RX_DL_OVER);
876 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_RX_DL_OVER);
877
878
879 rxdesc = (struct malo_rx_desc *)sc->sc_data;
880 rxdesc->status = letoh16(rxdesc->status);
881 rxdesc->pkglen = letoh16(rxdesc->pkglen);
882 rxdesc->pkgoffset = letoh32(rxdesc->pkgoffset);
883
884 DPRINTF(2, "RX status=%d, pkglen=%d, pkgoffset=%d\n",
885 rxdesc->status, rxdesc->pkglen, rxdesc->pkgoffset);
886
887 if (rxdesc->status != MALO_RX_STATUS_OK)
888
889 return;
890
891
892 data = sc->sc_data + rxdesc->pkgoffset;
893 i = (ETHER_ADDR_LEN * 2) + sizeof(struct llc);
894 bcopy(data + i, data + (ETHER_ADDR_LEN * 2), rxdesc->pkglen - i);
895 rxdesc->pkglen -= sizeof(struct llc);
896
897
898 m = m_devget(sc->sc_data + rxdesc->pkgoffset - ETHER_ALIGN,
899 rxdesc->pkglen + ETHER_ALIGN, 0, ifp, NULL);
900 m_adj(m, ETHER_ALIGN);
901
902 #if NBPFILTER > 0
903 if (ifp->if_bpf)
904 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
905 #endif
906
907
908 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
909 ether_input_mbuf(ifp, m);
910 ifp->if_ipackets++;
911 }
912 }
913
914 void
915 cmalo_start(struct ifnet *ifp)
916 {
917 struct malo_softc *sc = ifp->if_softc;
918 struct mbuf *m;
919
920
921 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
922 return;
923
924 IFQ_POLL(&ifp->if_snd, m);
925 if (m == NULL)
926 return;
927
928 IFQ_DEQUEUE(&ifp->if_snd, m);
929
930 #if NBPFILTER > 0
931 if (ifp->if_bpf)
932 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
933 #endif
934
935 if (cmalo_tx(sc, m) != 0)
936 ifp->if_oerrors++;
937 }
938
939 void
940 cmalo_watchdog(struct ifnet *ifp)
941 {
942 DPRINTF(2, "watchdog timeout\n");
943
944
945 ifp->if_flags &= ~IFF_OACTIVE;
946 }
947
948 int
949 cmalo_tx(struct malo_softc *sc, struct mbuf *m)
950 {
951 struct ifnet *ifp = &sc->sc_ic.ic_if;
952 struct malo_tx_desc *txdesc = sc->sc_data;
953 uint8_t *data;
954 uint16_t psize;
955
956 splassert(IPL_NET);
957
958 bzero(sc->sc_data, sizeof(*txdesc));
959 psize = sizeof(*txdesc) + m->m_pkthdr.len;
960 data = mtod(m, uint8_t *);
961
962
963 txdesc->pkgoffset = htole32(sizeof(*txdesc));
964 txdesc->pkglen = htole16(m->m_pkthdr.len);
965 bcopy(data, txdesc->dstaddrhigh, ETHER_ADDR_LEN);
966
967
968 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_data + sizeof(*txdesc));
969 m_freem(m);
970
971
972 MALO_WRITE_2(sc, MALO_REG_DATA_WRITE_LEN, psize);
973 if (psize & 0x0001) {
974 MALO_WRITE_MULTI_2(sc, MALO_REG_DATA_WRITE, sc->sc_data,
975 psize - 1);
976 data = (uint8_t *)sc->sc_data;
977 MALO_WRITE_1(sc, MALO_REG_DATA_WRITE, data[psize - 1]);
978 } else
979 MALO_WRITE_MULTI_2(sc, MALO_REG_DATA_WRITE, sc->sc_data, psize);
980 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_TX_DL_OVER);
981 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_TX_DL_OVER);
982
983 ifp->if_flags |= IFF_OACTIVE;
984 ifp->if_timer = 5;
985
986 DPRINTF(2, "%s: TX status=%d, pkglen=%d, pkgoffset=%d\n",
987 sc->sc_dev.dv_xname, txdesc->status, letoh16(txdesc->pkglen),
988 sizeof(*txdesc));
989
990 return (0);
991 }
992
993 void
994 cmalo_tx_done(struct malo_softc *sc)
995 {
996 struct ifnet *ifp = &sc->sc_ic.ic_if;
997
998 splassert(IPL_NET);
999
1000 DPRINTF(2, "%s: TX done\n", sc->sc_dev.dv_xname);
1001
1002 ifp->if_opackets++;
1003 ifp->if_flags &= ~IFF_OACTIVE;
1004 ifp->if_timer = 0;
1005 cmalo_start(ifp);
1006 }
1007
1008 void
1009 cmalo_event(struct malo_softc *sc)
1010 {
1011 uint16_t event;
1012
1013
1014 event = MALO_READ_2(sc, MALO_REG_CARD_STATUS);
1015 event &= MALO_VAL_CARD_STATUS_MASK;
1016 event = event >> 8;
1017
1018 switch (event) {
1019 case MALO_EVENT_DEAUTH:
1020 DPRINTF(1, "%s: got deauthentication event (0x%04x)\n",
1021 sc->sc_dev.dv_xname, event);
1022
1023 cmalo_cmd_set_assoc(sc);
1024 break;
1025 case MALO_EVENT_DISASSOC:
1026 DPRINTF(1, "%s: got disassociation event (0x%04x)\n",
1027 sc->sc_dev.dv_xname, event);
1028
1029 cmalo_cmd_set_assoc(sc);
1030 break;
1031 default:
1032 DPRINTF(1, "%s: got unknown event (0x%04x)\n",
1033 sc->sc_dev.dv_xname, event);
1034 break;
1035 }
1036
1037
1038 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_HOST_INTR_EVENT);
1039 }
1040
1041 void
1042 cmalo_select_network(struct malo_softc *sc)
1043 {
1044 struct ieee80211com *ic = &sc->sc_ic;
1045 int i, best_rssi;
1046
1047
1048 sc->sc_net_cur = 0;
1049
1050
1051 if (ic->ic_des_esslen) {
1052 for (i = 0; i < sc->sc_net_num; i++) {
1053 if (!strcmp(ic->ic_des_essid, sc->sc_net[i].ssid)) {
1054 sc->sc_net_cur = i;
1055 DPRINTF(1, "%s: desired network found (%s)\n",
1056 sc->sc_dev.dv_xname, ic->ic_des_essid);
1057 return;
1058 }
1059 }
1060 DPRINTF(1, "%s: desired network not found in scan results "
1061 "(%s)!\n",
1062 sc->sc_dev.dv_xname, ic->ic_des_essid);
1063 }
1064
1065
1066 best_rssi = sc->sc_net[0].rssi;
1067 for (i = 0; i < sc->sc_net_num; i++) {
1068 if (best_rssi < sc->sc_net[i].rssi) {
1069 best_rssi = sc->sc_net[i].rssi;
1070 sc->sc_net_cur = i;
1071 }
1072 }
1073 DPRINTF(1, "%s: best network found (%s)\n",
1074 sc->sc_dev.dv_xname, sc->sc_net[sc->sc_net_cur].ssid);
1075 }
1076
1077 void
1078 cmalo_reflect_network(struct malo_softc *sc)
1079 {
1080 struct ieee80211com *ic = &sc->sc_ic;
1081 uint8_t chan;
1082
1083
1084
1085
1086 IEEE80211_ADDR_COPY(ic->ic_bss->ni_bssid,
1087 sc->sc_net[sc->sc_net_cur].bssid);
1088
1089
1090 ic->ic_bss->ni_esslen = strlen(sc->sc_net[sc->sc_net_cur].ssid);
1091 bcopy(sc->sc_net[sc->sc_net_cur].ssid, ic->ic_bss->ni_essid,
1092 ic->ic_bss->ni_esslen);
1093
1094
1095 chan = sc->sc_net[sc->sc_net_cur].channel;
1096 ic->ic_bss->ni_chan = &ic->ic_channels[chan];
1097 }
1098
1099 int
1100 cmalo_wep(struct malo_softc *sc)
1101 {
1102 struct ieee80211com *ic = &sc->sc_ic;
1103 int i;
1104
1105 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1106 struct ieee80211_key *key = &ic->ic_nw_keys[i];
1107
1108 if (!key->k_len)
1109 continue;
1110
1111 DPRINTF(1, "%s: setting wep key for index %d\n",
1112 sc->sc_dev.dv_xname, i);
1113
1114 cmalo_cmd_set_wep(sc, i, key);
1115 }
1116
1117 return (0);
1118 }
1119
1120 void
1121 cmalo_hexdump(void *buf, int len)
1122 {
1123 #ifdef CMALO_DEBUG
1124 int i;
1125
1126 if (cmalo_d >= 2) {
1127 for (i = 0; i < len; i++) {
1128 if (i % 16 == 0)
1129 printf("%s%5i:", i ? "\n" : "", i);
1130 if (i % 4 == 0)
1131 printf(" ");
1132 printf("%02x", (int)*((u_char *)buf + i));
1133 }
1134 printf("\n");
1135 }
1136 #endif
1137 }
1138
1139 int
1140 cmalo_cmd_get_hwspec(struct malo_softc *sc)
1141 {
1142 struct malo_cmd_header *hdr = sc->sc_cmd;
1143 struct malo_cmd_body_spec *body;
1144 uint16_t psize;
1145
1146 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1147 psize = sizeof(*hdr) + sizeof(*body);
1148
1149 hdr->cmd = htole16(MALO_CMD_HWSPEC);
1150 hdr->size = htole16(sizeof(*body));
1151 hdr->seqnum = htole16(1);
1152 hdr->result = 0;
1153 body = (struct malo_cmd_body_spec *)(hdr + 1);
1154
1155
1156 memset(body->macaddr, 0xff, ETHER_ADDR_LEN);
1157
1158
1159 if (cmalo_cmd_request(sc, psize, 0) != 0)
1160 return (EIO);
1161
1162
1163 cmalo_cmd_response(sc);
1164
1165 return (0);
1166 }
1167
1168 int
1169 cmalo_cmd_rsp_hwspec(struct malo_softc *sc)
1170 {
1171 struct ieee80211com *ic = &sc->sc_ic;
1172 struct malo_cmd_header *hdr = sc->sc_cmd;
1173 struct malo_cmd_body_spec *body;
1174 int i;
1175
1176 body = (struct malo_cmd_body_spec *)(hdr + 1);
1177
1178
1179 for (i = 0; i < ETHER_ADDR_LEN; i++)
1180 ic->ic_myaddr[i] = body->macaddr[i];
1181
1182 return (0);
1183 }
1184
1185 int
1186 cmalo_cmd_set_reset(struct malo_softc *sc)
1187 {
1188 struct malo_cmd_header *hdr = sc->sc_cmd;
1189 uint16_t psize;
1190
1191 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1192 psize = sizeof(*hdr);
1193
1194 hdr->cmd = htole16(MALO_CMD_RESET);
1195 hdr->size = 0;
1196 hdr->seqnum = htole16(1);
1197 hdr->result = 0;
1198
1199
1200 if (cmalo_cmd_request(sc, psize, 1) != 0)
1201 return (EIO);
1202
1203 return (0);
1204 }
1205
1206 int
1207 cmalo_cmd_set_scan(struct malo_softc *sc)
1208 {
1209 struct ieee80211com *ic = &sc->sc_ic;
1210 struct malo_cmd_header *hdr = sc->sc_cmd;
1211 struct malo_cmd_body_scan *body;
1212 struct malo_cmd_tlv_ssid *body_ssid;
1213 struct malo_cmd_tlv_chanlist *body_chanlist;
1214 struct malo_cmd_tlv_rates *body_rates;
1215
1216 uint16_t psize;
1217 int i;
1218
1219 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1220 psize = sizeof(*hdr) + sizeof(*body);
1221
1222 hdr->cmd = htole16(MALO_CMD_SCAN);
1223 hdr->seqnum = htole16(1);
1224 hdr->result = 0;
1225 body = (struct malo_cmd_body_scan *)(hdr + 1);
1226
1227 body->bsstype = 0x03;
1228 memset(body->bssid, 0xff, ETHER_ADDR_LEN);
1229
1230 body_ssid = sc->sc_cmd + psize;
1231 body_ssid->type = htole16(MALO_TLV_TYPE_SSID);
1232 body_ssid->size = htole16(0);
1233 psize += (sizeof(*body_ssid) - 1);
1234
1235 body_chanlist = sc->sc_cmd + psize;
1236 body_chanlist->type = htole16(MALO_TLV_TYPE_CHANLIST);
1237 body_chanlist->size = htole16(sizeof(body_chanlist->data));
1238 for (i = 0; i < CHANNELS; i++) {
1239 body_chanlist->data[i].radiotype = 0x00;
1240 body_chanlist->data[i].channumber = (i + 1);
1241 body_chanlist->data[i].scantype = 0x00;
1242 body_chanlist->data[i].minscantime = htole16(0);
1243 body_chanlist->data[i].maxscantime = htole16(100);
1244 }
1245 psize += sizeof(*body_chanlist);
1246
1247 body_rates = sc->sc_cmd + psize;
1248 body_rates->type = htole16(MALO_TLV_TYPE_RATES);
1249 body_rates->size =
1250 htole16(ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates);
1251 bcopy(ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates, body_rates->data,
1252 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates);
1253 psize += (sizeof(*body_rates) - 1) + letoh16(body_rates->size);
1254 #if 0
1255 body_numprobes = sc->sc_cmd + psize;
1256 body_numprobes->type = htole16(MALO_TLV_TYPE_NUMPROBES);
1257 body_numprobes->size = htole16(2);
1258 body_numprobes->numprobes = htole16(1);
1259 psize += sizeof(*body_numprobes);
1260 #endif
1261 hdr->size = htole16(psize - sizeof(*hdr));
1262
1263
1264 if (cmalo_cmd_request(sc, psize, 0) != 0)
1265 return (EIO);
1266
1267
1268 cmalo_cmd_response(sc);
1269
1270 return (0);
1271 }
1272
1273 int
1274 cmalo_cmd_rsp_scan(struct malo_softc *sc)
1275 {
1276 struct malo_cmd_header *hdr = sc->sc_cmd;
1277 struct malo_cmd_body_rsp_scan *body;
1278 struct malo_cmd_body_rsp_scan_set *set;
1279 uint16_t psize;
1280 int i;
1281
1282 bzero(sc->sc_net, sizeof(sc->sc_net));
1283 psize = sizeof(*hdr) + sizeof(*body);
1284
1285 body = (struct malo_cmd_body_rsp_scan *)(hdr + 1);
1286
1287 body->bufsize = letoh16(body->bufsize);
1288
1289 DPRINTF(1, "bufsize=%d, APs=%d\n", body->bufsize, body->numofset);
1290 sc->sc_net_num = body->numofset;
1291
1292
1293 for (i = 0; i < body->numofset; i++) {
1294 set = (struct malo_cmd_body_rsp_scan_set *)(sc->sc_cmd + psize);
1295
1296 set->size = letoh16(set->size);
1297 set->beaconintvl = letoh16(set->beaconintvl);
1298 set->capinfo = letoh16(set->capinfo);
1299
1300 DPRINTF(1, "size=%d, bssid=%s, rssi=%d, beaconintvl=%d, "
1301 "capinfo=0x%04x\n",
1302 set->size, ether_sprintf(set->bssid), set->rssi,
1303 set->beaconintvl, set->capinfo);
1304
1305
1306 bcopy(set->bssid, sc->sc_net[i].bssid, sizeof(set->bssid));
1307 bcopy(set->timestamp, sc->sc_net[i].timestamp,
1308 sizeof(set->timestamp));
1309 sc->sc_net[i].rssi = set->rssi;
1310 sc->sc_net[i].beaconintvl = set->beaconintvl;
1311 sc->sc_net[i].capinfo = set->capinfo;
1312 cmalo_parse_elements(sc, (set + 1),
1313 set->size - (sizeof(*set) - sizeof(set->size)), i);
1314
1315 psize += (set->size + sizeof(set->size));
1316 }
1317
1318 return (0);
1319 }
1320
1321 int
1322 cmalo_parse_elements(struct malo_softc *sc, void *buf, int size, int pos)
1323 {
1324 uint8_t eid, len;
1325 int i;
1326
1327 DPRINTF(2, "element_size=%d, element_pos=%d\n", size, pos);
1328
1329 for (i = 0; i < size; ) {
1330 eid = *(uint8_t *)(buf + i);
1331 i++;
1332 len = *(uint8_t *)(buf + i);
1333 i++;
1334 DPRINTF(2, "eid=%d, len=%d, ", eid, len);
1335
1336 switch (eid) {
1337 case IEEE80211_ELEMID_SSID:
1338 bcopy(buf + i, sc->sc_net[pos].ssid, len);
1339 DPRINTF(2, "ssid=%s\n", sc->sc_net[pos].ssid);
1340 break;
1341 case IEEE80211_ELEMID_RATES:
1342 bcopy(buf + i, sc->sc_net[pos].rates, len);
1343 DPRINTF(2, "rates\n");
1344 break;
1345 case IEEE80211_ELEMID_DSPARMS:
1346 sc->sc_net[pos].channel = *(uint8_t *)(buf + i);
1347 DPRINTF(2, "chnl=%d\n", sc->sc_net[pos].channel);
1348 break;
1349 default:
1350 DPRINTF(2, "unknown\n");
1351 break;
1352 }
1353
1354 i += len;
1355 }
1356
1357 return (0);
1358 }
1359
1360 int
1361 cmalo_cmd_set_auth(struct malo_softc *sc)
1362 {
1363 struct malo_cmd_header *hdr = sc->sc_cmd;
1364 struct malo_cmd_body_auth *body;
1365 uint16_t psize;
1366
1367 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1368 psize = sizeof(*hdr) + sizeof(*body);
1369
1370 hdr->cmd = htole16(MALO_CMD_AUTH);
1371 hdr->size = htole16(sizeof(*body));
1372 hdr->seqnum = htole16(1);
1373 hdr->result = 0;
1374 body = (struct malo_cmd_body_auth *)(hdr + 1);
1375
1376 bcopy(sc->sc_net[sc->sc_net_cur].bssid, body->peermac, ETHER_ADDR_LEN);
1377 body->authtype = 0;
1378
1379
1380 if (cmalo_cmd_request(sc, psize, 0) != 0)
1381 return (EIO);
1382
1383
1384 cmalo_cmd_response(sc);
1385
1386 return (0);
1387 }
1388
1389 int
1390 cmalo_cmd_set_wep(struct malo_softc *sc, uint16_t index,
1391 struct ieee80211_key *key)
1392 {
1393 struct malo_cmd_header *hdr = sc->sc_cmd;
1394 struct malo_cmd_body_wep *body;
1395 uint16_t psize;
1396
1397 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1398 psize = sizeof(*hdr) + sizeof(*body);
1399
1400 hdr->cmd = htole16(MALO_CMD_WEP);
1401 hdr->size = htole16(sizeof(*body));
1402 hdr->seqnum = htole16(1);
1403 hdr->result = 0;
1404 body = (struct malo_cmd_body_wep *)(hdr + 1);
1405
1406 body->action = htole16(MALO_WEP_ACTION_TYPE_ADD);
1407 body->key_index = htole16(index);
1408
1409 if (body->key_index == 0) {
1410 if (key->k_len > 5)
1411 body->key_type_1 = MALO_WEP_KEY_TYPE_104BIT;
1412 else
1413 body->key_type_1 = MALO_WEP_KEY_TYPE_40BIT;
1414 bcopy(key->k_key, body->key_value_1, key->k_len);
1415 }
1416 if (body->key_index == 1) {
1417 if (key->k_len > 5)
1418 body->key_type_2 = MALO_WEP_KEY_TYPE_104BIT;
1419 else
1420 body->key_type_2 = MALO_WEP_KEY_TYPE_40BIT;
1421 bcopy(key->k_key, body->key_value_2, key->k_len);
1422 }
1423 if (body->key_index == 2) {
1424 if (key->k_len > 5)
1425 body->key_type_3 = MALO_WEP_KEY_TYPE_104BIT;
1426 else
1427 body->key_type_3 = MALO_WEP_KEY_TYPE_40BIT;
1428 bcopy(key->k_key, body->key_value_3, key->k_len);
1429 }
1430 if (body->key_index == 3) {
1431 if (key->k_len > 5)
1432 body->key_type_4 = MALO_WEP_KEY_TYPE_104BIT;
1433 else
1434 body->key_type_4 = MALO_WEP_KEY_TYPE_40BIT;
1435 bcopy(key->k_key, body->key_value_4, key->k_len);
1436 }
1437
1438
1439 if (cmalo_cmd_request(sc, psize, 0) != 0)
1440 return (EIO);
1441
1442
1443 cmalo_cmd_response(sc);
1444
1445 return (0);
1446 }
1447
1448 int
1449 cmalo_cmd_set_snmp(struct malo_softc *sc, uint16_t oid)
1450 {
1451 struct malo_cmd_header *hdr = sc->sc_cmd;
1452 struct malo_cmd_body_snmp *body;
1453 uint16_t psize;
1454
1455 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1456 psize = sizeof(*hdr) + sizeof(*body);
1457
1458 hdr->cmd = htole16(MALO_CMD_SNMP);
1459 hdr->size = htole16(sizeof(*body));
1460 hdr->seqnum = htole16(1);
1461 hdr->result = 0;
1462 body = (struct malo_cmd_body_snmp *)(hdr + 1);
1463
1464 body->action = htole16(1);
1465
1466 switch (oid) {
1467 case MALO_OID_RTSTRESH:
1468 body->oid = htole16(MALO_OID_RTSTRESH);
1469 body->size = htole16(2);
1470 *(uint16_t *)body->data = htole16(2347);
1471 break;
1472 case MALO_OID_SHORTRETRY:
1473 body->oid = htole16(MALO_OID_SHORTRETRY);
1474 body->size = htole16(2);
1475 *(uint16_t *)body->data = htole16(4);
1476 break;
1477 case MALO_OID_FRAGTRESH:
1478 body->oid = htole16(MALO_OID_FRAGTRESH);
1479 body->size = htole16(2);
1480 *(uint16_t *)body->data = htole16(2346);
1481 break;
1482 case MALO_OID_80211D:
1483 body->oid = htole16(MALO_OID_80211D);
1484 body->size = htole16(2);
1485 *(uint16_t *)body->data = htole16(1);
1486 break;
1487 default:
1488 break;
1489 }
1490
1491
1492 if (cmalo_cmd_request(sc, psize, 0) != 0)
1493 return (EIO);
1494
1495
1496 cmalo_cmd_response(sc);
1497
1498 return (0);
1499 }
1500
1501 int
1502 cmalo_cmd_set_radio(struct malo_softc *sc, uint16_t control)
1503 {
1504 struct malo_cmd_header *hdr = sc->sc_cmd;
1505 struct malo_cmd_body_radio *body;
1506 uint16_t psize;
1507
1508 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1509 psize = sizeof(*hdr) + sizeof(*body);
1510
1511 hdr->cmd = htole16(MALO_CMD_RADIO);
1512 hdr->size = htole16(sizeof(*body));
1513 hdr->seqnum = htole16(1);
1514 hdr->result = 0;
1515 body = (struct malo_cmd_body_radio *)(hdr + 1);
1516
1517 body->action = htole16(1);
1518
1519 if (control) {
1520 body->control = htole16(MALO_CMD_RADIO_ON);
1521 body->control |= htole16(MALO_CMD_RADIO_AUTO_P);
1522 }
1523
1524
1525 if (cmalo_cmd_request(sc, psize, 0) != 0)
1526 return (EIO);
1527
1528
1529 cmalo_cmd_response(sc);
1530
1531 return (0);
1532 }
1533
1534 int
1535 cmalo_cmd_set_channel(struct malo_softc *sc, uint16_t channel)
1536 {
1537 struct malo_cmd_header *hdr = sc->sc_cmd;
1538 struct malo_cmd_body_channel *body;
1539 uint16_t psize;
1540
1541 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1542 psize = sizeof(*hdr) + sizeof(*body);
1543
1544 hdr->cmd = htole16(MALO_CMD_CHANNEL);
1545 hdr->size = htole16(sizeof(*body));
1546 hdr->seqnum = htole16(1);
1547 hdr->result = 0;
1548 body = (struct malo_cmd_body_channel *)(hdr + 1);
1549
1550 body->action = htole16(1);
1551 body->channel = htole16(channel);
1552
1553
1554 if (cmalo_cmd_request(sc, psize, 0) != 0)
1555 return (EIO);
1556
1557
1558 cmalo_cmd_response(sc);
1559
1560 return (0);
1561 }
1562
1563
1564 int
1565 cmalo_cmd_set_txpower(struct malo_softc *sc, int16_t txpower)
1566 {
1567 struct malo_cmd_header *hdr = sc->sc_cmd;
1568 struct malo_cmd_body_txpower *body;
1569 uint16_t psize;
1570
1571 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1572 psize = sizeof(*hdr) + sizeof(*body);
1573
1574 hdr->cmd = htole16(MALO_CMD_TXPOWER);
1575 hdr->size = htole16(sizeof(*body));
1576 hdr->seqnum = htole16(1);
1577 hdr->result = 0;
1578 body = (struct malo_cmd_body_txpower *)(hdr + 1);
1579
1580 body->action = htole16(1);
1581 body->txpower = htole16(txpower);
1582
1583
1584 if (cmalo_cmd_request(sc, psize, 0) != 0)
1585 return (EIO);
1586
1587
1588 cmalo_cmd_response(sc);
1589
1590 return (0);
1591 }
1592
1593 int
1594 cmalo_cmd_set_antenna(struct malo_softc *sc, uint16_t action)
1595 {
1596 struct malo_cmd_header *hdr = sc->sc_cmd;
1597 struct malo_cmd_body_antenna *body;
1598 uint16_t psize;
1599
1600 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1601 psize = sizeof(*hdr) + sizeof(*body);
1602
1603 hdr->cmd = htole16(MALO_CMD_ANTENNA);
1604 hdr->size = htole16(sizeof(*body));
1605 hdr->seqnum = htole16(1);
1606 hdr->result = 0;
1607 body = (struct malo_cmd_body_antenna *)(hdr + 1);
1608
1609
1610 body->action = htole16(action);
1611
1612 if (action == 1)
1613
1614 body->antenna_mode = htole16(0xffff);
1615 if (action == 2)
1616
1617 body->antenna_mode = htole16(2);
1618
1619
1620 if (cmalo_cmd_request(sc, psize, 0) != 0)
1621 return (EIO);
1622
1623
1624 cmalo_cmd_response(sc);
1625
1626 return (0);
1627 }
1628
1629 int
1630 cmalo_cmd_set_macctrl(struct malo_softc *sc)
1631 {
1632 struct ieee80211com *ic = &sc->sc_ic;
1633 struct malo_cmd_header *hdr = sc->sc_cmd;
1634 struct malo_cmd_body_macctrl *body;
1635 uint16_t psize;
1636
1637 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1638 psize = sizeof(*hdr) + sizeof(*body);
1639
1640 hdr->cmd = htole16(MALO_CMD_MACCTRL);
1641 hdr->size = htole16(sizeof(*body));
1642 hdr->seqnum = htole16(1);
1643 hdr->result = 0;
1644 body = (struct malo_cmd_body_macctrl *)(hdr + 1);
1645
1646 body->action = htole16(MALO_CMD_MACCTRL_RX_ON);
1647 body->action |= htole16(MALO_CMD_MACCTRL_TX_ON);
1648 if (ic->ic_opmode == IEEE80211_M_MONITOR)
1649 body->action |= htole16(MALO_CMD_MACCTRL_PROMISC_ON);
1650
1651
1652 if (cmalo_cmd_request(sc, psize, 0) != 0)
1653 return (EIO);
1654
1655
1656 cmalo_cmd_response(sc);
1657
1658 return (0);
1659 }
1660
1661 int
1662 cmalo_cmd_set_assoc(struct malo_softc *sc)
1663 {
1664 struct malo_cmd_header *hdr = sc->sc_cmd;
1665 struct malo_cmd_body_assoc *body;
1666 struct malo_cmd_tlv_ssid *body_ssid;
1667 struct malo_cmd_tlv_phy *body_phy;
1668 struct malo_cmd_tlv_cf *body_cf;
1669 struct malo_cmd_tlv_rates *body_rates;
1670 struct malo_cmd_tlv_passeid *body_passeid;
1671 uint16_t psize;
1672
1673 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1674 psize = sizeof(*hdr) + sizeof(*body);
1675
1676 hdr->cmd = htole16(MALO_CMD_ASSOC);
1677 hdr->seqnum = htole16(1);
1678 hdr->result = 0;
1679 body = (struct malo_cmd_body_assoc *)(hdr + 1);
1680
1681 bcopy(sc->sc_net[sc->sc_net_cur].bssid, body->peermac, ETHER_ADDR_LEN);
1682 body->capinfo = htole16(sc->sc_net[sc->sc_net_cur].capinfo);
1683 body->listenintrv = htole16(10);
1684
1685 body_ssid = sc->sc_cmd + psize;
1686 body_ssid->type = htole16(MALO_TLV_TYPE_SSID);
1687 body_ssid->size = htole16(strlen(sc->sc_net[sc->sc_net_cur].ssid));
1688 bcopy(sc->sc_net[sc->sc_net_cur].ssid, body_ssid->data,
1689 letoh16(body_ssid->size));
1690 psize += (sizeof(*body_ssid) - 1) + letoh16(body_ssid->size);
1691
1692 body_phy = sc->sc_cmd + psize;
1693 body_phy->type = htole16(MALO_TLV_TYPE_PHY);
1694 body_phy->size = htole16(1);
1695 bcopy(&sc->sc_net[sc->sc_net_cur].channel, body_phy->data, 1);
1696 psize += sizeof(*body_phy);
1697
1698 body_cf = sc->sc_cmd + psize;
1699 body_cf->type = htole16(MALO_TLV_TYPE_CF);
1700 body_cf->size = htole16(0);
1701 psize += (sizeof(*body_cf) - 1);
1702
1703 body_rates = sc->sc_cmd + psize;
1704 body_rates->type = htole16(MALO_TLV_TYPE_RATES);
1705 body_rates->size = htole16(strlen(sc->sc_net[sc->sc_net_cur].rates));
1706 bcopy(sc->sc_net[sc->sc_net_cur].rates, body_rates->data,
1707 letoh16(body_rates->size));
1708 psize += (sizeof(*body_rates) - 1) + letoh16(body_rates->size);
1709
1710
1711 body_passeid = sc->sc_cmd + psize;
1712 body_passeid->type = htole16(MALO_TLV_TYPE_PASSEID);
1713 body_passeid->size = body_rates->size;
1714 bcopy(body_rates->data, body_passeid->data, letoh16(body_rates->size));
1715 psize += (sizeof(*body_passeid) - 1) + letoh16(body_passeid->size);
1716
1717 hdr->size = htole16(psize - sizeof(*hdr));
1718
1719
1720 if (!sc->sc_cmd_ctxsave) {
1721 if (cmalo_cmd_request(sc, psize, 1) != 0)
1722 return (EIO);
1723 return (0);
1724 }
1725 if (cmalo_cmd_request(sc, psize, 0) != 0)
1726 return (EIO);
1727
1728
1729 cmalo_cmd_response(sc);
1730
1731 return (0);
1732 }
1733
1734 int
1735 cmalo_cmd_rsp_assoc(struct malo_softc *sc)
1736 {
1737 struct malo_cmd_header *hdr = sc->sc_cmd;
1738 struct malo_cmd_body_rsp_assoc *body;
1739
1740 body = (struct malo_cmd_body_rsp_assoc *)(hdr + 1);
1741
1742 if (body->status) {
1743 DPRINTF(1, "%s: association failed (status %d)!\n",
1744 sc->sc_dev.dv_xname, body->status);
1745 sc->sc_flags |= MALO_ASSOC_FAILED;
1746 } else
1747 DPRINTF(1, "%s: association successful\n",
1748 sc->sc_dev.dv_xname, body->status);
1749
1750 return (0);
1751 }
1752
1753 int
1754 cmalo_cmd_set_80211d(struct malo_softc *sc)
1755 {
1756 struct malo_cmd_header *hdr = sc->sc_cmd;
1757 struct malo_cmd_body_80211d *body;
1758 struct malo_cmd_tlv_80211d *body_80211d;
1759 uint16_t psize;
1760 int i;
1761
1762 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1763 psize = sizeof(*hdr) + sizeof(*body);
1764
1765 hdr->cmd = htole16(MALO_CMD_80211D);
1766 hdr->seqnum = htole16(1);
1767 hdr->result = 0;
1768 body = (struct malo_cmd_body_80211d *)(hdr + 1);
1769
1770 body->action = htole16(1);
1771
1772 body_80211d = sc->sc_cmd + psize;
1773 body_80211d->type = htole16(MALO_TLV_TYPE_80211D);
1774 body_80211d->size = htole16(sizeof(body_80211d->data) +
1775 sizeof(body_80211d->countrycode));
1776 bcopy("EU ", body_80211d->countrycode,
1777 sizeof(body_80211d->countrycode));
1778 for (i = 0; i < CHANNELS; i++) {
1779 body_80211d->data[i].firstchannel = 1;
1780 body_80211d->data[i].numchannels = 12;
1781 body_80211d->data[i].maxtxpower = 10;
1782 }
1783 psize += sizeof(*body_80211d);
1784
1785 hdr->size = htole16(psize - sizeof(*hdr));
1786
1787
1788 if (cmalo_cmd_request(sc, psize, 0) != 0)
1789 return (EIO);
1790
1791
1792 cmalo_cmd_response(sc);
1793
1794 return (0);
1795 }
1796
1797 int
1798 cmalo_cmd_set_bgscan_config(struct malo_softc *sc)
1799 {
1800 struct malo_cmd_header *hdr = sc->sc_cmd;
1801 struct malo_cmd_body_bgscan_config *body;
1802 uint16_t psize;
1803
1804 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1805 psize = sizeof(*hdr) + sizeof(*body);
1806
1807 hdr->cmd = htole16(MALO_CMD_BGSCAN_CONFIG);
1808 hdr->size = htole16(sizeof(*body));
1809 hdr->seqnum = htole16(1);
1810 hdr->result = 0;
1811 body = (struct malo_cmd_body_bgscan_config *)(hdr + 1);
1812
1813 body->action = htole16(1);
1814 body->enable = 1;
1815 body->bsstype = 0x03;
1816 body->chperscan = 12;
1817 body->scanintvl = htole32(100);
1818 body->maxscanres = htole16(12);
1819
1820
1821 if (cmalo_cmd_request(sc, psize, 0) != 0)
1822 return (EIO);
1823
1824
1825 cmalo_cmd_response(sc);
1826
1827 return (0);
1828 }
1829
1830 int
1831 cmalo_cmd_set_bgscan_query(struct malo_softc *sc)
1832 {
1833 struct malo_cmd_header *hdr = sc->sc_cmd;
1834 struct malo_cmd_body_bgscan_query *body;
1835 uint16_t psize;
1836
1837 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1838 psize = sizeof(*hdr) + sizeof(*body);
1839
1840 hdr->cmd = htole16(MALO_CMD_BGSCAN_QUERY);
1841 hdr->size = htole16(sizeof(*body));
1842 hdr->seqnum = htole16(1);
1843 hdr->result = 0;
1844 body = (struct malo_cmd_body_bgscan_query *)(hdr + 1);
1845
1846 body->flush = 0;
1847
1848
1849 if (cmalo_cmd_request(sc, psize, 0) != 0)
1850 return (EIO);
1851
1852
1853 cmalo_cmd_response(sc);
1854
1855 return (0);
1856 }
1857
1858 int
1859 cmalo_cmd_set_rate(struct malo_softc *sc)
1860 {
1861 struct malo_cmd_header *hdr = sc->sc_cmd;
1862 struct malo_cmd_body_rate *body;
1863 uint16_t psize;
1864
1865 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1866 psize = sizeof(*hdr) + sizeof(*body);
1867
1868 hdr->cmd = htole16(MALO_CMD_RATE);
1869 hdr->size = htole16(sizeof(*body));
1870 hdr->seqnum = htole16(1);
1871 hdr->result = 0;
1872 body = (struct malo_cmd_body_rate *)(hdr + 1);
1873
1874 body->action = htole16(1);
1875 body->hwauto = htole16(1);
1876 body->ratebitmap = htole16(0x1fff);
1877
1878
1879 if (cmalo_cmd_request(sc, psize, 0) != 0)
1880 return (EIO);
1881
1882
1883 cmalo_cmd_response(sc);
1884
1885 return (0);
1886 }
1887
1888 int
1889 cmalo_cmd_request(struct malo_softc *sc, uint16_t psize, int no_response)
1890 {
1891 uint8_t *cmd;
1892
1893 cmalo_hexdump(sc->sc_cmd, psize);
1894
1895
1896 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, psize);
1897 if (psize & 0x0001) {
1898 MALO_WRITE_MULTI_2(sc, MALO_REG_CMD_WRITE, sc->sc_cmd,
1899 psize - 1);
1900 cmd = (uint8_t *)sc->sc_cmd;
1901 MALO_WRITE_1(sc, MALO_REG_CMD_WRITE, cmd[psize - 1]);
1902 } else
1903 MALO_WRITE_MULTI_2(sc, MALO_REG_CMD_WRITE, sc->sc_cmd, psize);
1904 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER);
1905 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_CMD_DL_OVER);
1906
1907 if (no_response)
1908
1909 return (0);
1910
1911
1912 if (tsleep(sc, 0, "malocmd", 500)) {
1913 printf("%s: timeout while waiting for cmd response!\n",
1914 sc->sc_dev.dv_xname);
1915 return (EIO);
1916 }
1917
1918 return (0);
1919 }
1920
1921 int
1922 cmalo_cmd_response(struct malo_softc *sc)
1923 {
1924 struct malo_cmd_header *hdr = sc->sc_cmd;
1925 uint16_t psize;
1926 uint8_t *cmd;
1927 int s;
1928
1929 s = splnet();
1930
1931 bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
1932
1933
1934 psize = MALO_READ_2(sc, MALO_REG_CMD_READ_LEN);
1935 if (psize & 0x0001) {
1936 MALO_READ_MULTI_2(sc, MALO_REG_CMD_READ, sc->sc_cmd,
1937 psize - 1);
1938 cmd = (uint8_t *)sc->sc_cmd;
1939 cmd[psize - 1] = MALO_READ_1(sc, MALO_REG_CMD_READ);
1940 } else
1941 MALO_READ_MULTI_2(sc, MALO_REG_CMD_READ, sc->sc_cmd, psize);
1942
1943 cmalo_hexdump(sc->sc_cmd, psize);
1944
1945
1946
1947
1948
1949
1950
1951 hdr->cmd = letoh16(hdr->cmd);
1952 hdr->size = letoh16(hdr->size);
1953 hdr->seqnum = letoh16(hdr->seqnum);
1954 hdr->result = letoh16(hdr->result);
1955
1956
1957 if (!(hdr->cmd & MALO_CMD_RESP)) {
1958 printf("%s: got invalid command response (0x%04x)!\n",
1959 sc->sc_dev.dv_xname, hdr->cmd);
1960 splx(s);
1961 return (EIO);
1962 }
1963 hdr->cmd &= ~MALO_CMD_RESP;
1964
1965
1966 if (hdr->cmd == 0x0012)
1967 hdr->cmd = MALO_CMD_ASSOC;
1968
1969
1970 switch (hdr->cmd) {
1971 case MALO_CMD_HWSPEC:
1972 DPRINTF(1, "%s: got hwspec cmd response\n",
1973 sc->sc_dev.dv_xname);
1974 cmalo_cmd_rsp_hwspec(sc);
1975 break;
1976 case MALO_CMD_RESET:
1977
1978 break;
1979 case MALO_CMD_SCAN:
1980 DPRINTF(1, "%s: got scan cmd response\n",
1981 sc->sc_dev.dv_xname);
1982 cmalo_cmd_rsp_scan(sc);
1983 break;
1984 case MALO_CMD_AUTH:
1985
1986 DPRINTF(1, "%s: got auth cmd response\n",
1987 sc->sc_dev.dv_xname);
1988 break;
1989 case MALO_CMD_WEP:
1990
1991 DPRINTF(1, "%s: got wep cmd response\n",
1992 sc->sc_dev.dv_xname);
1993 break;
1994 case MALO_CMD_SNMP:
1995
1996 DPRINTF(1, "%s: got snmp cmd response\n",
1997 sc->sc_dev.dv_xname);
1998 break;
1999 case MALO_CMD_RADIO:
2000
2001 DPRINTF(1, "%s: got radio cmd response\n",
2002 sc->sc_dev.dv_xname);
2003 break;
2004 case MALO_CMD_CHANNEL:
2005
2006 DPRINTF(1, "%s: got channel cmd response\n",
2007 sc->sc_dev.dv_xname);
2008 break;
2009 case MALO_CMD_TXPOWER:
2010
2011 DPRINTF(1, "%s: got txpower cmd response\n",
2012 sc->sc_dev.dv_xname);
2013 break;
2014 case MALO_CMD_ANTENNA:
2015
2016 DPRINTF(1, "%s: got antenna cmd response\n",
2017 sc->sc_dev.dv_xname);
2018 break;
2019 case MALO_CMD_MACCTRL:
2020
2021 DPRINTF(1, "%s: got macctrl cmd response\n",
2022 sc->sc_dev.dv_xname);
2023 break;
2024 case MALO_CMD_ASSOC:
2025
2026 DPRINTF(1, "%s: got assoc cmd response\n",
2027 sc->sc_dev.dv_xname);
2028 cmalo_cmd_rsp_assoc(sc);
2029 break;
2030 case MALO_CMD_80211D:
2031
2032 DPRINTF(1, "%s: got 80211d cmd response\n",
2033 sc->sc_dev.dv_xname);
2034 break;
2035 case MALO_CMD_BGSCAN_CONFIG:
2036
2037 DPRINTF(1, "%s: got bgscan config cmd response\n",
2038 sc->sc_dev.dv_xname);
2039 break;
2040 case MALO_CMD_BGSCAN_QUERY:
2041
2042 DPRINTF(1, "%s: got bgscan query cmd response\n",
2043 sc->sc_dev.dv_xname);
2044 break;
2045 case MALO_CMD_RATE:
2046
2047 DPRINTF(1, "%s: got rate cmd response\n",
2048 sc->sc_dev.dv_xname);
2049 break;
2050 default:
2051 printf("%s: got unknown cmd response (0x%04x)!\n",
2052 sc->sc_dev.dv_xname, hdr->cmd);
2053 break;
2054 }
2055
2056 splx(s);
2057
2058 return (0);
2059 }