awi.c revision 1.5 1 /* $NetBSD: awi.c,v 1.5 1999/11/08 13:24:00 sommerfeld Exp $ */
2
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Bill Sommerfeld
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38 /*
39 * Driver for AMD 802.11 firmware.
40 * Uses am79c930 chip driver to talk to firmware running on the am79c930.
41 *
42 * More-or-less a generic ethernet-like if driver, with 802.11 gorp added.
43 */
44
45 /*
46 * todo:
47 * - don't print "management timeout"/"assoc with" for normal
48 * association keepalive goo.
49 * - multicast filter.
50 * - use cluster mbufs on rx?
51 * - fix device reset so it's more likely to work
52 * - allow i/o-space-only access to device (over in am79c930.c)
53 * - show status goo through ifmedia.
54 *
55 * more todo:
56 * - deal with more 802.11 frames.
57 * - send reassoc request
58 * - deal with reassoc response
59 * - send/deal with disassociation
60 * - deal with "full" access points (no room for me).
61 * - power save mode
62 * - if no traffic, let ourselves gracefully desync?
63 *
64 * later:
65 * - SSID preferences
66 * - need ioctls for poking at the MIBs
67 * - implement ad-hoc mode (including bss creation).
68 * - decide when to do "ad hoc" vs. infrastructure mode (IFF_LINK flags?)
69 * (focus on inf. mode since that will be needed for ietf)
70 * - deal with DH vs. FH versions of the card
71 * - deal with faster cards (2mb/s)
72 * - ?WEP goo (mmm, rc4) (it looks not particularly useful).
73 * - ifmedia revision.
74 * - common 802.11 mibish things.
75 * - common 802.11 media layer.
76 */
77
78 #include "opt_inet.h"
79 #include "opt_ns.h"
80 #include "bpfilter.h"
81 #include "rnd.h"
82
83 #include <sys/param.h>
84 #include <sys/systm.h>
85 #include <sys/kernel.h>
86 #include <sys/mbuf.h>
87 #include <sys/socket.h>
88 #include <sys/ioctl.h>
89 #include <sys/errno.h>
90 #include <sys/syslog.h>
91 #include <sys/select.h>
92 #include <sys/device.h>
93 #if NRND > 0
94 #include <sys/rnd.h>
95 #endif
96
97 #include <net/if.h>
98 #include <net/if_dl.h>
99 #include <net/if_ether.h>
100 #include <net/if_media.h>
101
102 #ifdef INET
103 #include <netinet/in.h>
104 #include <netinet/in_systm.h>
105 #include <netinet/in_var.h>
106 #include <netinet/ip.h>
107 #include <netinet/if_inarp.h>
108 #endif
109
110 #ifdef NS
111 #include <netns/ns.h>
112 #include <netns/ns_if.h>
113 #endif
114
115 #if NBPFILTER > 0
116 #include <net/bpf.h>
117 #include <net/bpfdesc.h>
118 #endif
119
120 #include <machine/cpu.h>
121 #include <machine/bus.h>
122 #include <machine/intr.h>
123
124 #include <dev/ic/am79c930reg.h>
125 #include <dev/ic/am79c930var.h>
126 #include <dev/ic/awireg.h>
127 #include <dev/ic/awivar.h>
128
129 void awi_insane __P((struct awi_softc *sc));
130 int awi_intlock __P((struct awi_softc *sc));
131 void awi_intunlock __P((struct awi_softc *sc));
132 void awi_intrinit __P((struct awi_softc *sc));
133 u_int8_t awi_read_intst __P((struct awi_softc *sc));
134 void awi_stop __P((struct awi_softc *sc));
135 void awi_init __P((struct awi_softc *sc));
136 void awi_set_mc __P((struct awi_softc *sc));
137 void awi_rxint __P((struct awi_softc *));
138 void awi_txint __P((struct awi_softc *));
139 void awi_tx_packet __P((struct awi_softc *, int, struct mbuf *));
140
141 void awi_rcv __P((struct awi_softc *, struct mbuf *, u_int32_t, u_int8_t));
142 void awi_rcv_mgt __P((struct awi_softc *, struct mbuf *, u_int32_t, u_int8_t));
143 void awi_rcv_data __P((struct awi_softc *, struct mbuf *));
144 void awi_rcv_ctl __P((struct awi_softc *, struct mbuf *));
145
146 int awi_enable __P((struct awi_softc *sc));
147 void awi_disable __P((struct awi_softc *sc));
148
149 void awi_zero __P((struct awi_softc *, u_int32_t, u_int32_t));
150
151 void awi_cmd __P((struct awi_softc *, u_int8_t));
152 void awi_cmd_test_if __P((struct awi_softc *));
153 void awi_cmd_get_mib __P((struct awi_softc *sc, u_int8_t, u_int8_t, u_int8_t));
154 void awi_cmd_txinit __P((struct awi_softc *sc));
155 void awi_cmd_scan __P((struct awi_softc *sc));
156 void awi_scan_next __P((struct awi_softc *sc));
157 void awi_try_sync __P((struct awi_softc *sc));
158 void awi_cmd_set_ss __P((struct awi_softc *sc));
159 void awi_cmd_set_promisc __P((struct awi_softc *sc));
160 void awi_cmd_set_allmulti __P((struct awi_softc *sc));
161 void awi_cmd_set_infra __P((struct awi_softc *sc));
162 void awi_cmd_set_notap __P((struct awi_softc *sc));
163 void awi_cmd_get_myaddr __P((struct awi_softc *sc));
164
165
166 void awi_cmd_scan_done __P((struct awi_softc *sc, u_int8_t));
167 void awi_cmd_sync_done __P((struct awi_softc *sc, u_int8_t));
168 void awi_cmd_set_ss_done __P((struct awi_softc *sc, u_int8_t));
169 void awi_cmd_set_allmulti_done __P((struct awi_softc *sc, u_int8_t));
170 void awi_cmd_set_promisc_done __P((struct awi_softc *sc, u_int8_t));
171 void awi_cmd_set_infra_done __P((struct awi_softc *sc, u_int8_t));
172 void awi_cmd_set_notap_done __P((struct awi_softc *sc, u_int8_t));
173 void awi_cmd_get_myaddr_done __P((struct awi_softc *sc, u_int8_t));
174
175 void awi_reset __P((struct awi_softc *));
176 void awi_init_1 __P((struct awi_softc *));
177 void awi_init_2 __P((struct awi_softc *, u_int8_t));
178 void awi_mibdump __P((struct awi_softc *, u_int8_t));
179 void awi_init_read_bufptrs_done __P((struct awi_softc *, u_int8_t));
180 void awi_init_4 __P((struct awi_softc *, u_int8_t));
181 void awi_init_5 __P((struct awi_softc *, u_int8_t));
182 void awi_init_6 __P((struct awi_softc *, u_int8_t));
183 void awi_running __P((struct awi_softc *));
184
185 void awi_init_txdescr __P((struct awi_softc *));
186 void awi_init_txd __P((struct awi_softc *, int, int, int, int));
187
188 void awi_watchdog __P((struct ifnet *));
189 void awi_start __P((struct ifnet *));
190 int awi_ioctl __P((struct ifnet *, u_long, caddr_t));
191 void awi_dump_rxchain __P((struct awi_softc *, char *, u_int32_t *));
192
193 void awi_send_frame __P((struct awi_softc *, struct mbuf *));
194 void awi_send_authreq __P((struct awi_softc *));
195 void awi_send_assocreq __P((struct awi_softc *));
196 void awi_parse_tlv __P((u_int8_t *base, u_int8_t *end, u_int8_t **vals, u_int8_t *lens, size_t nattr));
197
198 u_int8_t *awi_add_rates __P((struct awi_softc *, struct mbuf *, u_int8_t *));
199 u_int8_t *awi_add_ssid __P((struct awi_softc *, struct mbuf *, u_int8_t *));
200 void * awi_init_hdr __P((struct awi_softc *, struct mbuf *, int, int));
201
202 void awi_hexdump __P((char *tag, u_int8_t *data, int len));
203 void awi_card_hexdump __P((struct awi_softc *, char *tag, u_int32_t offset, int len));
204
205 int awi_drop_output __P((struct ifnet *, struct mbuf *,
206 struct sockaddr *, struct rtentry *));
207 void awi_drop_input __P((struct ifnet *, struct mbuf *));
208 struct mbuf *awi_output_kludge __P((struct awi_softc *, struct mbuf *));
209 void awi_set_timer __P((struct awi_softc *));
210 void awi_restart_scan __P((struct awi_softc *));
211
212 static const u_int8_t snap_magic[] = { 0xaa, 0xaa, 3, 0, 0, 0 };
213
214 int awi_scan_keepalive = 10;
215
216 /*
217 * attach (called by bus-specific front end)
218 *
219 * look for banner message
220 * wait for selftests to complete (up to 2s??? eeee.)
221 * (do this with a timeout!!??!!)
222 * on timeout completion:
223 * issue test_interface command.
224 * get_mib command to locate TX buffer.
225 * set_mib command to set any non-default variables.
226 * init tx first.
227 * init rx second with enable receiver command
228 *
229 * mac mgmt portion executes sync command to start BSS
230 *
231 */
232
233 /*
234 * device shutdown routine.
235 */
236
237 /*
238 * device appears to be insane. rather than hanging, whap device upside
239 * the head on next timeout.
240 */
241
242 void
243 awi_insane(sc)
244 struct awi_softc *sc;
245 {
246 struct ifnet *ifp = sc->sc_ifp;
247 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
248
249 /* whap device on next timeout. */
250 sc->sc_state = AWI_ST_INSANE;
251 ifp->if_timer = 1;
252 }
253
254 void
255 awi_set_timer (sc)
256 struct awi_softc *sc;
257 {
258 if (sc->sc_tx_timer || sc->sc_scan_timer ||
259 sc->sc_mgt_timer || sc->sc_cmd_timer)
260 sc->sc_ifp->if_timer = 1;
261 }
262
263
264 /*
265 * Copy m0 into the given TX descriptor and give the descriptor to the
266 * device so it starts transmiting..
267 */
268
269 void
270 awi_tx_packet (sc, txd, m0)
271 struct awi_softc *sc;
272 int txd;
273 struct mbuf *m0;
274 {
275 u_int32_t frame = sc->sc_txd[txd].frame;
276 u_int32_t len = sc->sc_txd[txd].len;
277 struct mbuf *m;
278
279 for (m = m0; m != NULL; m = m->m_next) {
280 u_int32_t nmove;
281 nmove = min(len, m->m_len);
282 awi_write_bytes (sc, frame, m->m_data, nmove);
283 if (nmove != m->m_len) {
284 printf("%s: large frame truncated\n",
285 sc->sc_dev.dv_xname);
286 break;
287 }
288 frame += nmove;
289 len -= nmove;
290 }
291
292 awi_init_txd (sc,
293 txd,
294 AWI_TXD_ST_OWN,
295 frame - sc->sc_txd[txd].frame,
296 AWI_RATE_1MBIT);
297
298 #if 0
299 awi_card_hexdump (sc, "txd to go", sc->sc_txd[txd].descr,
300 AWI_TXD_SIZE);
301 #endif
302
303 }
304
305 /*
306 * XXX KLUDGE XXX
307 *
308 * Convert ethernet-formatted frame into 802.11 data frame
309 * for infrastructure mode.
310 */
311
312 struct mbuf *
313 awi_output_kludge (sc, m0)
314 struct awi_softc *sc;
315 struct mbuf *m0;
316 {
317 u_int8_t *framehdr;
318 u_int8_t *llchdr;
319 u_int8_t dstaddr[ETHER_ADDR_LEN];
320 struct awi_mac_header *amhdr;
321 u_int16_t etype;
322 struct ether_header *eh = mtod(m0, struct ether_header *);
323
324 #if 0
325 awi_hexdump("etherframe", m0->m_data, m0->m_len);
326 #endif
327
328 memcpy(dstaddr, eh->ether_dhost, sizeof(dstaddr));
329 etype = eh->ether_type;
330
331 m_adj(m0, sizeof(struct ether_header));
332
333 M_PREPEND(m0, sizeof(struct awi_mac_header) + 8, M_DONTWAIT);
334
335 if (m0 == NULL) {
336 printf("oops, prepend failed\n");
337 return NULL;
338 }
339
340 if (m0->m_len < 32) {
341 printf("oops, prepend only left %d bytes\n", m0->m_len);
342 m_freem(m0);
343 return NULL;
344 }
345 framehdr = mtod(m0, u_int8_t *);
346 amhdr = mtod(m0, struct awi_mac_header *);
347
348 amhdr->awi_fc = IEEEWL_FC_VERS |
349 IEEEWL_FC_TYPE_DATA<<IEEEWL_FC_TYPE_SHIFT;
350 amhdr->awi_f2 = IEEEWL_FC2_TODS;
351
352 memcpy(amhdr->awi_addr3, dstaddr, ETHER_ADDR_LEN); /* ether DST */
353 memcpy(amhdr->awi_addr1, sc->sc_active_bss.bss_id, ETHER_ADDR_LEN);
354 memcpy(amhdr->awi_addr2, sc->sc_my_addr, ETHER_ADDR_LEN);
355 amhdr->awi_duration = 0;
356 amhdr->awi_seqctl = 0;
357 llchdr = (u_int8_t *) (amhdr + 1);
358 memcpy(llchdr, snap_magic, 6);
359 memcpy(llchdr+6, &etype, 2);
360
361 return m0;
362 }
363 /*
364 * device start routine
365 *
366 * loop while there are free tx buffer descriptors and mbufs in the queue:
367 * -> copy mbufs to tx buffer and free mbufs.
368 * -> mark txd as good to go (OWN bit set, all others clear)
369 */
370
371 void
372 awi_start(ifp)
373 struct ifnet *ifp;
374 {
375 struct awi_softc *sc = ifp->if_softc;
376 struct mbuf *m0;
377 int opending;
378
379 if ((ifp->if_flags & IFF_RUNNING) == 0) {
380 printf("%s: start called while not running\n",
381 sc->sc_dev.dv_xname);
382 return;
383 }
384
385 /*
386 * loop through send queue, setting up tx descriptors
387 * until we either run out of stuff to send, or descriptors
388 * to send them in.
389 */
390 opending = sc->sc_txpending;
391
392 while (sc->sc_txpending < sc->sc_ntxd) {
393 /*
394 * Grab a packet off the queue.
395 */
396 IF_DEQUEUE (&sc->sc_mgtq, m0);
397
398 if (m0 == NULL) {
399 /* XXX defer sending if not synched yet? */
400 IF_DEQUEUE (&ifp->if_snd, m0);
401 if (m0 == NULL)
402 break;
403 #if NBPFILTER > 0
404 /*
405 * Pass packet to bpf if there is a listener.
406 */
407 if (ifp->if_bpf)
408 bpf_mtap(ifp->if_bpf, m0);
409 #endif
410 /*
411 * We've got an ethernet-format frame.
412 * we need to mangle it into 802.11 form..
413 */
414 m0 = awi_output_kludge(sc, m0);
415 if (m0 == NULL)
416 continue;
417 }
418
419 awi_tx_packet(sc, sc->sc_txnext, m0);
420
421 sc->sc_txpending++;
422 sc->sc_txnext = (sc->sc_txnext + 1) % sc->sc_ntxd;
423
424 m_freem(m0);
425 }
426 if (sc->sc_txpending >= sc->sc_ntxd) {
427 /* no more slots available.. */
428 ifp->if_flags |= IFF_OACTIVE;
429 }
430 if (sc->sc_txpending != opending) {
431 /* set watchdog timer in case unit flakes out */
432 if (sc->sc_tx_timer == 0)
433 sc->sc_tx_timer = 5;
434 awi_set_timer(sc);
435 }
436 }
437
438 int
439 awi_enable(sc)
440 struct awi_softc *sc;
441 {
442 if (sc->sc_enabled == 0) {
443 if ((sc->sc_enable != NULL) && ((*sc->sc_enable)(sc) != 0)) {
444 printf("%s: device enable failed\n",
445 sc->sc_dev.dv_xname);
446 return (EIO);
447 }
448 awi_init(sc);
449 }
450 sc->sc_enabled = 1;
451 return 0;
452 }
453
454 void
455 awi_disable(sc)
456 struct awi_softc *sc;
457 {
458 if (sc->sc_enabled != 0 && sc->sc_disable != NULL) {
459 (*sc->sc_disable)(sc);
460 sc->sc_enabled = 0;
461 }
462 }
463
464
465
466 int
467 awi_intlock(sc)
468 struct awi_softc *sc;
469 {
470 int i, j;
471 u_int8_t lockout;
472
473 DELAY(5);
474 for (j=0; j<10; j++) {
475 for (i=0; i<AWI_LOCKOUT_SPIN; i++) {
476 lockout = awi_read_1(sc, AWI_LOCKOUT_HOST);
477 if (!lockout)
478 break;
479 DELAY(5);
480 }
481 if (lockout)
482 break;
483 awi_write_1 (sc, AWI_LOCKOUT_MAC, 1);
484 lockout = awi_read_1(sc, AWI_LOCKOUT_HOST);
485
486 if (!lockout)
487 break;
488 /* oops, lost the race.. try again */
489 awi_write_1 (sc, AWI_LOCKOUT_MAC, 0);
490 }
491
492 if (lockout) {
493 awi_insane(sc);
494 return 0;
495 }
496 return 1;
497 }
498
499 void
500 awi_intunlock(sc)
501 struct awi_softc *sc;
502 {
503 awi_write_1 (sc, AWI_LOCKOUT_MAC, 0);
504 }
505
506 void
507 awi_intrinit(sc)
508 struct awi_softc *sc;
509 {
510 u_int8_t intmask;
511
512 am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_ENECINT);
513
514 intmask = AWI_INT_GROGGY|AWI_INT_SCAN_CMPLT|
515 AWI_INT_TX|AWI_INT_RX|AWI_INT_CMD;
516
517 intmask = ~intmask;
518
519 if (!awi_intlock(sc))
520 return;
521
522 awi_write_1(sc, AWI_INTMASK, intmask);
523 awi_write_1(sc, AWI_INTMASK2, 0);
524
525 awi_intunlock(sc);
526 }
527
528 void awi_hexdump (char *tag, u_int8_t *data, int len)
529 {
530 int i;
531
532 printf("%s:", tag);
533 for (i=0; i<len; i++) {
534 printf(" %02x", data[i]);
535 }
536 printf("\n");
537 }
538
539 void awi_card_hexdump (sc, tag, offset, len)
540 struct awi_softc *sc;
541 char *tag;
542 u_int32_t offset;
543 int len;
544 {
545 int i;
546
547 printf("%s:", tag);
548 for (i=0; i<len; i++) {
549 printf(" %02x", awi_read_1(sc, offset+i));
550 }
551 printf("\n");
552 }
553
554 u_int8_t
555 awi_read_intst(sc)
556 struct awi_softc *sc;
557 {
558 u_int8_t state;
559
560 if (!awi_intlock(sc))
561 return 0;
562
563 /* we have int lock.. */
564
565 state = awi_read_1 (sc, AWI_INTSTAT);
566 awi_write_1(sc, AWI_INTSTAT, 0);
567
568 awi_intunlock(sc);
569
570 return state;
571 }
572
573
574 void
575 awi_parse_tlv (u_int8_t *base, u_int8_t *end, u_int8_t **vals, u_int8_t *lens, size_t nattr)
576 {
577 u_int8_t tag, len;
578
579 int i;
580
581 for (i=0; i<nattr; i++) {
582 vals[i] = NULL;
583 lens[i] = 0;
584 }
585
586 while (base < end) {
587 tag = base[0];
588 len = base[1];
589
590 base += 2;
591
592 if (tag < nattr) {
593 lens[tag] = len;
594 vals[tag] = base;
595 }
596 base += len;
597 }
598 }
599
600 void
601 awi_send_frame (sc, m)
602 struct awi_softc *sc;
603 struct mbuf *m;
604 {
605 IF_ENQUEUE(&sc->sc_mgtq, m);
606
607 awi_start(sc->sc_ifp);
608 }
609
610 void *
611 awi_init_hdr (sc, m, f1, f2)
612 struct awi_softc *sc;
613 struct mbuf *m;
614 int f1;
615 int f2;
616 {
617 struct awi_mac_header *amhp;
618
619 /*
620 * initialize 802.11 mac header in mbuf, return pointer to next byte..
621 */
622
623 amhp = mtod(m, struct awi_mac_header *);
624
625 amhp->awi_fc = f1;
626 amhp->awi_f2 = f2;
627 amhp->awi_duration = 0;
628
629 memcpy(amhp->awi_addr1, sc->sc_active_bss.bss_id, ETHER_ADDR_LEN);
630 memcpy(amhp->awi_addr2, sc->sc_my_addr, ETHER_ADDR_LEN);
631 memcpy(amhp->awi_addr3, sc->sc_active_bss.bss_id, ETHER_ADDR_LEN);
632
633 amhp->awi_seqctl = 0;
634
635 return amhp+1;
636 }
637
638
639
640 u_int8_t *
641 awi_add_rates (sc, m, ptr)
642 struct awi_softc *sc;
643 struct mbuf *m;
644 u_int8_t *ptr;
645 {
646 *ptr++ = 1; /* XXX */
647 *ptr++ = 1; /* XXX */
648 *ptr++ = 0x82; /* XXX */
649 return ptr;
650 }
651
652 u_int8_t *
653 awi_add_ssid (sc, m, ptr)
654 struct awi_softc *sc;
655 struct mbuf *m;
656 u_int8_t *ptr;
657 {
658 int len = sc->sc_active_bss.sslen;
659 *ptr++ = 0; /* XXX */
660 *ptr++ = len;
661 memcpy(ptr, sc->sc_active_bss.ssid, len);
662 ptr += len;
663 return ptr;
664 }
665
666
667
668 void
669 awi_send_authreq (sc)
670 struct awi_softc *sc;
671 {
672 struct mbuf *m;
673 struct awi_auth_hdr *amahp;
674 u_int8_t *tlvptr;
675
676 MGETHDR(m, M_DONTWAIT, MT_DATA);
677
678 /*
679 * form an "association request" message.
680 */
681
682 /*
683 * auth alg number. 2 bytes. = 0
684 * auth txn seq number = 2 bytes = 1
685 * status code = 2 bytes = 0
686 * challenge text (not present)
687 */
688
689 if (m == 0)
690 return; /* we'll try again later.. */
691
692 amahp = awi_init_hdr (sc, m,
693 (IEEEWL_FC_VERS |
694 (IEEEWL_FC_TYPE_MGT << IEEEWL_FC_TYPE_SHIFT) |
695 (IEEEWL_SUBTYPE_AUTH << IEEEWL_FC_SUBTYPE_SHIFT)),
696 0);
697
698 amahp->awi_algno[0] = 0;
699 amahp->awi_algno[1] = 0;
700 amahp->awi_seqno[0] = 1;
701 amahp->awi_seqno[1] = 0;
702 amahp->awi_status[0] = 0;
703 amahp->awi_status[1] = 0;
704
705 /*
706 * form an "authentication" message.
707 */
708
709 tlvptr = (u_int8_t *)(amahp+1);
710
711 tlvptr = awi_add_ssid(sc, m, tlvptr);
712 tlvptr = awi_add_rates(sc, m, tlvptr);
713
714 m->m_len = tlvptr - mtod(m, u_int8_t *);
715
716 awi_send_frame(sc, m);
717
718 sc->sc_mgt_timer = 2;
719 awi_set_timer(sc);
720 }
721
722 void
723 awi_send_assocreq (sc)
724 struct awi_softc *sc;
725 {
726 struct mbuf *m;
727 struct awi_assoc_hdr *amahp;
728 u_int8_t *tlvptr;
729
730 MGETHDR(m, M_DONTWAIT, MT_DATA);
731
732 /*
733 * form an "association request" message.
734 */
735
736 if (m == 0)
737 return; /* we'll try again later.. */
738
739 /*
740 * cap info (2 bytes)
741 * listen interval (2 bytes)
742 * ssid (variable)
743 * supported rates (variable)
744 */
745
746 amahp = awi_init_hdr (sc, m,
747 IEEEWL_FC_TYPE_MGT, IEEEWL_SUBTYPE_ASSOCREQ);
748
749 amahp->awi_cap_info[0] = 4; /* XXX magic (CF-pollable) */
750 amahp->awi_cap_info[1] = 0;
751 amahp->awi_li[0] = 1;
752 amahp->awi_li[1] = 0;
753
754 tlvptr = (u_int8_t *)(amahp+1);
755
756 tlvptr = awi_add_ssid(sc, m, tlvptr);
757 tlvptr = awi_add_rates(sc, m, tlvptr);
758
759 m->m_len = tlvptr - mtod(m, u_int8_t *);
760
761 awi_send_frame(sc, m);
762
763 sc->sc_mgt_timer = 2;
764 awi_set_timer(sc);
765 }
766
767 #if 0
768 void
769 awi_send_reassocreq (sc)
770 {
771
772 /*
773 * form an "reassociation request" message.
774 */
775
776 /* 2 bytes frame control
777 00100000 00000000
778 2 bytes goo
779 00000000 00000000
780 address 1: bssid
781 address 2: my address
782 address 3: bssid
783 2 bytes seq/ctl
784 00000000 00000000
785
786 cap info (2 bytes)
787 listen interval (2 bytes)
788 current ap address (6 bytes)
789 ssid (variable)
790 supported rates (va
791 */
792 }
793
794 #endif
795
796 void
797 awi_rcv_ctl (sc, m)
798 struct awi_softc *sc;
799 struct mbuf *m;
800 {
801 printf("%s: ctl\n", sc->sc_dev.dv_xname);
802 }
803
804 void
805 awi_rcv_data (sc, m)
806 struct awi_softc *sc;
807 struct mbuf *m;
808 {
809 struct ifnet *ifp = sc->sc_ifp;
810 u_int8_t *llc;
811 u_int8_t *to, *from;
812 struct awi_mac_header *amhp;
813
814 sc->sc_scan_timer = awi_scan_keepalive; /* user data is as good
815 as a beacon as a keepalive.. */
816
817 amhp = mtod(m, struct awi_mac_header *);
818
819 /*
820 * we have: 4 bytes useless goo.
821 * 3 x 6 bytes MAC addresses.
822 * 2 bytes goo.
823 * 802.x LLC header, SNAP header, and data.
824 *
825 * for now, we fake up a "normal" ethernet header and feed
826 * this to the appropriate input routine.
827 */
828
829 llc = (u_int8_t *)(amhp+1);
830
831 if (amhp->awi_f2 & IEEEWL_FC2_TODS) {
832 printf("drop packet to DS\n");
833 goto drop;
834 }
835
836 to = amhp->awi_addr1;
837 if (amhp->awi_f2 & IEEEWL_FC2_FROMDS)
838 from = amhp->awi_addr3;
839 else
840 from = amhp->awi_addr2;
841 if (memcmp (llc, snap_magic, 6) != 0)
842 goto drop;
843
844 /* XXX overwrite llc with "from" address */
845 /* XXX overwrite llc-6 with "to" address */
846 memcpy(llc, from, ETHER_ADDR_LEN);
847 memcpy(llc-6, to, ETHER_ADDR_LEN);
848
849 m_adj(m, sizeof(struct awi_mac_header) + sizeof(struct awi_llc_header)
850 - sizeof(struct ether_header));
851
852 #if NBPFILTER > 0
853 /*
854 * Pass packet to bpf if there is a listener.
855 */
856 if (ifp->if_bpf)
857 bpf_mtap(ifp->if_bpf, m);
858 #endif
859
860 #if __NetBSD_Version__ > 104010000
861 m->m_flags |= M_HASFCS;
862 (*ifp->if_input)(ifp, m);
863 #else
864 {
865 struct ether_header *eh;
866 eh = mtod(m, struct ether_header *);
867 m_adj(m, sizeof(*eh));
868 m_adj(m, -ETHER_CRC_LEN);
869 ether_input(ifp, eh, m);
870 }
871 #endif
872 return;
873 drop:
874 m_freem(m);
875 }
876
877 void
878 awi_rcv_mgt (sc, m, rxts, rssi)
879 struct awi_softc *sc;
880 struct mbuf *m;
881 u_int32_t rxts;
882 u_int8_t rssi;
883 {
884 u_int8_t subtype;
885 u_int8_t *framehdr, *mgthdr, *end, *timestamp;
886 struct awi_auth_hdr *auhp;
887
888 #define IEEEWL_MGT_NATTR 10 /* XXX */
889 u_int8_t *attr[IEEEWL_MGT_NATTR];
890 u_int8_t attrlen[IEEEWL_MGT_NATTR];
891 u_int8_t *addr1, *addr2, *addr3;
892 u_int8_t *sa, *da, *bss;
893
894 framehdr = mtod(m, u_int8_t *);
895
896 /*
897 * mgt frame:
898 * 2 bytes frame goo
899 * 2 bytes duration
900 * 6 bytes a1
901 * 6 bytes a2
902 * 6 bytes a3
903 * 2 bytes seq control.
904 * --
905 * 24 bytes goo.
906 */
907
908 subtype = (framehdr[IEEEWL_FC] & IEEEWL_FC_SUBTYPE_MASK)
909 >> IEEEWL_FC_SUBTYPE_SHIFT;
910
911 addr1 = framehdr + 4; /* XXX */
912 addr2 = addr1+ETHER_ADDR_LEN;
913 addr3 = addr2+ETHER_ADDR_LEN;
914
915 /* XXX look at to/from DS bits here!! */
916 da = addr1;
917 sa = addr3;
918 bss = addr2;
919
920 framehdr = mtod(m, u_int8_t *);
921 end = framehdr + m->m_len;
922 end -= 4; /* trim TLV */
923
924 mgthdr = framehdr + 24; /* XXX magic */
925
926 switch (subtype) {
927
928 case IEEEWL_SUBTYPE_ASSOCRESP:
929 /*
930 * this acknowledges that the AP will be forwarding traffic
931 * for us..
932 *
933 * contains:
934 * cap info
935 * status code
936 * AId
937 * supported rates.
938 */
939 #if 0
940 printf("assoc_resp\n");
941 /* XXX should look in "status" of received message.. */
942 #endif
943 awi_drvstate (sc, AWI_DRV_INFASSOC);
944 sc->sc_state = AWI_ST_RUNNING;
945 sc->sc_mgt_timer = AWI_ASSOC_REFRESH;
946 awi_set_timer(sc);
947 if (sc->sc_new_bss) {
948 printf("%s: associated with %s, SSID: %s\n",
949 sc->sc_dev.dv_xname,
950 ether_sprintf(sc->sc_active_bss.bss_id),
951 sc->sc_active_bss.ssid);
952 sc->sc_new_bss = 0;
953 }
954
955 /* XXX set media status to "i see carrier" */
956 break;
957
958 case IEEEWL_SUBTYPE_REASSOCRESP:
959 /*
960 * this indicates that we've moved from one AP to another
961 * within the same DS.
962 */
963 printf("reassoc_resp\n");
964
965 break;
966
967 case IEEEWL_SUBTYPE_PROBEREQ:
968 /* discard */
969 break;
970
971 case IEEEWL_SUBTYPE_PROBERESP:
972 /*
973 * 8 bytes timestamp.
974 * 2 bytes beacon intvl.
975 * 2 bytes cap info.
976 * then tlv data..
977 */
978 timestamp = mgthdr;
979
980 /* now, into the tlv goo.. */
981 mgthdr += 12; /* XXX magic */
982 awi_parse_tlv (mgthdr, end, attr, attrlen, IEEEWL_MGT_NATTR);
983
984 if (attr[IEEEWL_MGT_TLV_SSID] &&
985 attr[IEEEWL_MGT_TLV_FHPARMS] &&
986 attrlen[IEEEWL_MGT_TLV_SSID] < AWI_SSID_LEN) {
987 struct awi_bss_binding *bp = NULL;
988 int i;
989
990 for (i=0; i< sc->sc_nbindings; i++) {
991 struct awi_bss_binding *bp1 =
992 &sc->sc_bindings[i];
993 if (memcmp(bp1->bss_id, bss, ETHER_ADDR_LEN) == 0) {
994 bp = bp1;
995 break;
996 }
997 }
998
999 if (bp == NULL && sc->sc_nbindings < NBND) {
1000 bp = &sc->sc_bindings[sc->sc_nbindings++];
1001 }
1002 if (bp != NULL) {
1003 u_int8_t *fhparms =
1004 attr[IEEEWL_MGT_TLV_FHPARMS];
1005
1006 bp->sslen = attrlen[IEEEWL_MGT_TLV_SSID];
1007
1008 memcpy(bp->ssid, attr[IEEEWL_MGT_TLV_SSID],
1009 bp->sslen);
1010 bp->ssid[bp->sslen] = 0;
1011
1012 memcpy(bp->bss_id, bss, ETHER_ADDR_LEN);
1013
1014 /* XXX more magic numbers.. */
1015 bp->dwell_time = fhparms[0] | (fhparms[1]<<8);
1016 bp->chanset = fhparms[2];
1017 bp->pattern = fhparms[3];
1018 bp->index = fhparms[4];
1019 bp->rssi = rssi;
1020 bp->rxtime = rxts;
1021 memcpy(bp->bss_timestamp, timestamp, 8);
1022 }
1023 }
1024
1025 break;
1026
1027 case IEEEWL_SUBTYPE_BEACON:
1028 /*
1029 * Note that AP is still alive so we don't have to go looking
1030 * for one for a while.
1031 *
1032 * XXX Beacons from other AP's should be recorded for
1033 * potential use if we lose this AP.. (also, may want
1034 * to notice if rssi of new AP is significantly
1035 * stronger than old one and jump ship..)
1036 */
1037 if ((sc->sc_state >= AWI_ST_SYNCED) &&
1038 (memcmp (addr2, sc->sc_active_bss.bss_id,
1039 ETHER_ADDR_LEN) == 0)) {
1040 sc->sc_scan_timer = awi_scan_keepalive;
1041 awi_set_timer(sc);
1042 }
1043
1044 break;
1045
1046 case IEEEWL_SUBTYPE_DISSOC:
1047 printf("dissoc\n");
1048
1049 break;
1050
1051 case IEEEWL_SUBTYPE_AUTH:
1052 /*
1053 * woohoo! somebody likes us!
1054 */
1055
1056 auhp = (struct awi_auth_hdr *)mgthdr;
1057
1058 if ((auhp->awi_status[0] == 0) && (auhp->awi_status[1] == 0))
1059 {
1060 awi_drvstate (sc, AWI_DRV_INFAUTH);
1061 sc->sc_state = AWI_ST_AUTHED;
1062 awi_send_assocreq (sc);
1063 }
1064 break;
1065
1066 case IEEEWL_SUBTYPE_DEAUTH:
1067 printf("%s: received deauth\n", sc->sc_dev.dv_xname);
1068 sc->sc_state = AWI_ST_SYNCED;
1069 sc->sc_new_bss = 1;
1070 awi_send_authreq(sc);
1071 break;
1072 default:
1073 printf("unk mgt subtype %x\n", subtype);
1074 break;
1075 }
1076 m_freem(m); /* done.. */
1077 }
1078
1079
1080
1081
1082
1083 /*
1084 * Do 802.11 receive processing. "m" contains a receive frame;
1085 * rxts is the local receive timestamp
1086 */
1087
1088 void
1089 awi_rcv (sc, m, rxts, rssi)
1090 struct awi_softc *sc;
1091 struct mbuf *m;
1092 u_int32_t rxts;
1093 u_int8_t rssi;
1094 {
1095 u_int8_t *framehdr;
1096 u_int8_t framectl;
1097
1098 framehdr = mtod(m, u_int8_t *);
1099
1100 /*
1101 * peek at first byte of frame header.
1102 * check version subfield (must be zero)
1103 * check type subfield (00 = mgt, 01 = ctl, 10 = data)
1104 * check subtype field (next four bits)
1105 */
1106
1107 /*
1108 * Not counting WDS mode, the IEEE 802.11 frame header format
1109 * has *three* MAC addresses.
1110 * (source, destination, and BSS).
1111 *
1112 * The BSS indicates which wireless "cable segment" we're part of;
1113 * we discover this dynamically..
1114 *
1115 * Not content to put them in a fixed order, the exact
1116 * ordering of these addresses depends on other attribute bits
1117 * in the frame control word!
1118 *
1119 * an alternate presentation which is more self-consistent:
1120 * address 1 is the "wireless destination" -- either the
1121 * station address,
1122 * for wireless->wireless traffic, or the BSS id of an AP.
1123 *
1124 * address 2 is the "wireless source" -- either the
1125 * station address of a wireless node, or the BSS id of an AP.
1126 *
1127 * address 3 is the "other address" -- for STA->AP, the
1128 * eventual destination; for AP->STA, the original source, and
1129 * for ad-hoc mode, the BSS id..
1130 */
1131
1132 framectl = framehdr[IEEEWL_FC];
1133
1134 if ((framectl & IEEEWL_FC_VERS_MASK) != IEEEWL_FC_VERS) {
1135 printf("wrong vers. drop");
1136 goto drop;
1137 }
1138
1139 switch (framectl & IEEEWL_FC_TYPE_MASK) {
1140 case IEEEWL_FC_TYPE_MGT << IEEEWL_FC_TYPE_SHIFT:
1141 awi_rcv_mgt (sc, m, rxts, rssi);
1142 m = 0;
1143 break;
1144
1145 case IEEEWL_FC_TYPE_DATA << IEEEWL_FC_TYPE_SHIFT:
1146 awi_rcv_data (sc, m);
1147 m = 0;
1148 break;
1149
1150 case IEEEWL_FC_TYPE_CTL << IEEEWL_FC_TYPE_SHIFT:
1151 awi_rcv_ctl (sc, m);
1152 default:
1153 goto drop;
1154 }
1155
1156 drop:
1157 if (m) m_freem(m);
1158 }
1159
1160
1161 void
1162 awi_dump_rxchain (sc, what, descr)
1163 struct awi_softc *sc;
1164 char *what;
1165 u_int32_t *descr;
1166 {
1167 u_int32_t next, cur;
1168 int i;
1169 struct ifnet *ifp = sc->sc_ifp;
1170 u_int8_t *mptr;
1171 int mleft;
1172
1173 struct mbuf *top = NULL, *m = NULL, *m1 = NULL;
1174 cur = *descr;
1175
1176
1177 if (cur & AWI_RXD_NEXT_LAST)
1178 return;
1179
1180 for (i=0;i<1000;i++) {
1181 u_int16_t len;
1182 u_int8_t state, rate, rssi, index;
1183 u_int32_t frame;
1184 u_int32_t rxts;
1185
1186 top = 0;
1187
1188 next = awi_read_4(sc, cur + AWI_RXD_NEXT);
1189
1190 if (next & AWI_RXD_NEXT_LAST)
1191 break;
1192
1193 state = awi_read_1(sc, cur + AWI_RXD_HOST_DESC_STATE);
1194 len = awi_read_2 (sc, cur + AWI_RXD_LEN);
1195 rate = awi_read_1 (sc, cur + AWI_RXD_RATE);
1196 rssi = awi_read_1 (sc, cur + AWI_RXD_RSSI);
1197 index = awi_read_1 (sc, cur + AWI_RXD_INDEX);
1198 frame = awi_read_4 (sc, cur + AWI_RXD_START_FRAME);
1199 rxts = awi_read_4 (sc, cur + AWI_RXD_LOCALTIME);
1200
1201 /*
1202 * only the low order bits of "frame" and "next" are valid.
1203 * (the documentation doesn't mention this).
1204 */
1205 frame &= 0xffff;
1206 next &= 0xffff;
1207
1208 if (state & AWI_RXD_ST_CONSUMED) {
1209 state |= AWI_RXD_ST_CONSUMED | AWI_RXD_ST_OWN;
1210 awi_write_1(sc, cur + AWI_RXD_HOST_DESC_STATE, state);
1211 } else {
1212 MGETHDR(top, M_DONTWAIT, MT_DATA);
1213 if (top != 0) {
1214 if (len >= MINCLSIZE)
1215 MCLGET(top, M_DONTWAIT);
1216
1217 m = top;
1218 m->m_pkthdr.rcvif = ifp;
1219 m->m_pkthdr.len = 0;
1220 m->m_len = 0;
1221
1222 mleft = (m->m_flags & M_EXT) ?
1223 MCLBYTES : MHLEN;
1224 mptr = mtod(m, u_int8_t *);
1225 }
1226 for(;;) {
1227 if (top != 0) {
1228 /* copy data into mbuf */
1229 while (len > 0) {
1230 int nmove = min (len, mleft);
1231
1232 awi_read_bytes (sc, frame, mptr, nmove);
1233 len -= nmove;
1234 mleft -= nmove;
1235 mptr += nmove;
1236 frame += nmove;
1237
1238 top->m_pkthdr.len += nmove;
1239 m->m_len += nmove;
1240
1241 if (mleft == 0) {
1242 /* Get next mbuf.. */
1243 MGET(m1, M_DONTWAIT, MT_DATA);
1244 if (m1 == NULL) {
1245 m_freem(top);
1246 top = NULL;
1247 }
1248 m->m_next = m1;
1249 m = m1;
1250 m->m_len = 0;
1251
1252 mleft = MLEN;
1253 mptr = mtod(m, u_int8_t *);
1254 }
1255 }
1256 }
1257 state |= AWI_RXD_ST_CONSUMED | AWI_RXD_ST_OWN;
1258 awi_write_1(sc, cur + AWI_RXD_HOST_DESC_STATE, state);
1259
1260 if (state & AWI_RXD_ST_LF)
1261 break;
1262
1263 if (next & AWI_RXD_NEXT_LAST)
1264 panic("awi oops"); /* XXX */
1265
1266 /* XXX deal with dummy frames here?? */
1267
1268 cur = next;
1269 state = awi_read_1(sc, cur + AWI_RXD_HOST_DESC_STATE);
1270 len = awi_read_2 (sc, cur + AWI_RXD_LEN);
1271 rate = awi_read_1 (sc, cur + AWI_RXD_RATE);
1272 rssi = awi_read_1 (sc, cur + AWI_RXD_RSSI);
1273 index = awi_read_1 (sc, cur + AWI_RXD_INDEX);
1274 frame = awi_read_4 (sc, cur + AWI_RXD_START_FRAME);
1275 frame &= 0xffff;
1276 next &= 0xffff;
1277 }
1278 }
1279 if (top) {
1280 awi_rcv(sc, top, rxts, rssi);
1281 top = 0;
1282 }
1283 cur = next;
1284 }
1285 *descr = cur;
1286 }
1287
1288
1289
1290
1291 void
1292 awi_rxint (sc)
1293 struct awi_softc *sc;
1294 {
1295 awi_dump_rxchain (sc, "mgt", &sc->sc_rx_mgt_desc);
1296 awi_dump_rxchain (sc, "data", &sc->sc_rx_data_desc);
1297 }
1298
1299 void
1300 awi_init_txd (sc, tx, flag, len, rate)
1301 struct awi_softc *sc;
1302 int tx;
1303 int flag;
1304 int len;
1305 int rate;
1306 {
1307 u_int32_t txdbase = sc->sc_txd[tx].descr;
1308 u_int32_t framebase = sc->sc_txd[tx].frame;
1309 u_int32_t nextbase = sc->sc_txd[(tx+1)%sc->sc_ntxd].descr;
1310
1311 awi_write_4 (sc, txdbase + AWI_TXD_START, framebase);
1312 awi_write_4 (sc, txdbase + AWI_TXD_NEXT, nextbase);
1313 awi_write_4 (sc, txdbase + AWI_TXD_LENGTH, len);
1314 awi_write_1 (sc, txdbase + AWI_TXD_RATE, rate);
1315 /* zeroize tail end of txd */
1316 awi_write_4 (sc, txdbase + AWI_TXD_NDA, 0);
1317 awi_write_4 (sc, txdbase + AWI_TXD_NRA, 0);
1318 /* Init state last; firmware keys off of this to know when to start tx */
1319 awi_write_1 (sc, txdbase + AWI_TXD_STATE, flag);
1320 }
1321
1322 void
1323 awi_init_txdescr (sc)
1324 struct awi_softc *sc;
1325 {
1326 int i;
1327 u_int32_t offset = sc->sc_txbase;
1328
1329 sc->sc_txfirst = 0;
1330 sc->sc_txnext = 0;
1331
1332 sc->sc_ntxd = sc->sc_txlen / (AWI_FRAME_SIZE + AWI_TXD_SIZE);
1333 if (sc->sc_ntxd > NTXD) {
1334 sc->sc_ntxd = NTXD;
1335 printf("oops, no, only %d\n", sc->sc_ntxd);
1336 }
1337
1338 /* Allocate TXD's */
1339 for (i=0; i<sc->sc_ntxd; i++) {
1340 sc->sc_txd[i].descr = offset;
1341 offset += AWI_TXD_SIZE;
1342 }
1343 /* now, allocate buffer space to each txd.. */
1344 for (i=0; i<sc->sc_ntxd; i++) {
1345 sc->sc_txd[i].frame = offset;
1346 sc->sc_txd[i].len = AWI_FRAME_SIZE;
1347 offset += AWI_FRAME_SIZE;
1348
1349 }
1350
1351 /* now, initialize the TX descriptors into a circular linked list. */
1352
1353 for (i= 0; i<sc->sc_ntxd; i++) {
1354 awi_init_txd(sc, i, 0, 0, 0);
1355 }
1356 }
1357
1358 void
1359 awi_txint (sc)
1360 struct awi_softc *sc;
1361 {
1362 struct ifnet *ifp = sc->sc_ifp;
1363 int txfirst;
1364
1365 sc->sc_tx_timer = 0;
1366
1367 txfirst = sc->sc_txfirst;
1368 while (sc->sc_txpending > 0) {
1369 u_int8_t flags = awi_read_1 (sc, sc->sc_txd[txfirst].descr +
1370 AWI_TXD_STATE);
1371
1372 if (flags & AWI_TXD_ST_OWN)
1373 break;
1374
1375 if (flags & AWI_TXD_ST_ERROR) {
1376 /* increment oerrs */;
1377 }
1378
1379 txfirst = (txfirst + 1) % sc->sc_ntxd;
1380 sc->sc_txpending--;
1381 }
1382
1383 sc->sc_txfirst = txfirst;
1384
1385 if (sc->sc_txpending < sc->sc_ntxd)
1386 ifp->if_flags &= ~IFF_OACTIVE;
1387
1388 /*
1389 * see which descriptors are done..
1390 */
1391
1392 awi_start(sc->sc_ifp);
1393 }
1394
1395
1396
1397
1398 /*
1399 * device interrupt routine.
1400 *
1401 * lock out MAC
1402 * loop:
1403 * look at intr status, DTRT.
1404 *
1405 * on tx done, reclaim free buffers from tx, call start.
1406 * on rx done, look at rx queue, copy to mbufs, mark as free,
1407 * hand to ether media layer rx routine.
1408 * on cmd done, call cmd cmpl continuation.
1409 *
1410 */
1411
1412 int
1413 awi_intr(arg)
1414 void *arg;
1415 {
1416 struct awi_softc *sc = arg;
1417 int handled = 0;
1418
1419 if (sc->sc_state == AWI_ST_OFF) {
1420 u_int8_t intstate = awi_read_intst (sc);
1421 return intstate != 0;
1422 }
1423
1424 /* disable power down, (and implicitly ack interrupt) */
1425 am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_DISPWDN);
1426 awi_write_1(sc, AWI_DIS_PWRDN, 1);
1427
1428 for (;;) {
1429 u_int8_t intstate = awi_read_intst (sc);
1430
1431 if (!intstate)
1432 break;
1433
1434 handled = 1;
1435
1436 if (intstate & AWI_INT_RX)
1437 awi_rxint(sc);
1438
1439 if (intstate & AWI_INT_TX)
1440 awi_txint(sc);
1441
1442 if (intstate & AWI_INT_CMD) {
1443 u_int8_t status;
1444
1445 if (!(sc->sc_flags & AWI_FL_CMD_INPROG))
1446 printf("%s: no command in progress?\n",
1447 sc->sc_dev.dv_xname);
1448 status = awi_read_1(sc, AWI_CMD_STATUS);
1449 awi_write_1 (sc, AWI_CMD, 0);
1450 sc->sc_cmd_timer = 0;
1451 sc->sc_flags &= ~AWI_FL_CMD_INPROG;
1452
1453 if (sc->sc_completion)
1454 (*sc->sc_completion)(sc, status);
1455 }
1456 if (intstate & AWI_INT_SCAN_CMPLT) {
1457 if (sc->sc_flags & AWI_FL_CMD_INPROG) {
1458 panic("i can't take it any more");
1459 }
1460 /*
1461 * scan completion heuristic..
1462 */
1463 if ((sc->sc_nbindings >= NBND)
1464 || ((sc->sc_scan_timer == 0) &&
1465 (sc->sc_nbindings > 0)))
1466 awi_try_sync(sc);
1467 else
1468 awi_scan_next(sc);
1469 }
1470
1471 }
1472 /* reenable power down */
1473 am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_DISPWDN);
1474 awi_write_1(sc, AWI_DIS_PWRDN, 0);
1475
1476 return handled;
1477 }
1478
1479 /*
1480 * device stop routine
1481 */
1482
1483 void
1484 awi_stop(sc)
1485 struct awi_softc *sc;
1486 {
1487 struct ifnet *ifp = sc->sc_ifp;
1488
1489 /* Turn off timer.. */
1490 ifp->if_timer = 0;
1491 sc->sc_state = AWI_ST_OFF;
1492 (void) awi_read_intst (sc);
1493 /*
1494 * XXX for pcmcia, there's no point in disabling the device,
1495 * as it's about to be powered off..
1496 * for non-PCMCIA attachments, we should, however, stop
1497 * the receiver and transmitter here.
1498 */
1499 }
1500
1501 /*
1502 * Watchdog routine, triggered by timer.
1503 * This does periodic maintainance-type tasks on the interface.
1504 */
1505
1506 void
1507 awi_watchdog(ifp)
1508 struct ifnet *ifp;
1509 {
1510 struct awi_softc *sc = ifp->if_softc;
1511 u_int8_t test;
1512 int i;
1513
1514 if (sc->sc_state == AWI_ST_OFF)
1515 /* nothing to do */
1516 return;
1517 else if (sc->sc_state == AWI_ST_INSANE) {
1518 awi_reset(sc);
1519 return;
1520 } else if (sc->sc_state == AWI_ST_SELFTEST) {
1521 /* check for selftest completion.. */
1522 test = awi_read_1(sc, AWI_SELFTEST);
1523 if ((test & 0xf0) == 0xf0) { /* XXX magic numbers */
1524 if (test == AWI_SELFTEST_PASSED) {
1525 awi_init_1(sc);
1526 } else {
1527 printf("%s: selftest failed (code %x)\n",
1528 sc->sc_dev.dv_xname, test);
1529 awi_reset(sc);
1530 }
1531 }
1532 sc->sc_selftest_tries++;
1533 /* still running. try again on next tick */
1534 if (sc->sc_selftest_tries < 5) {
1535 ifp->if_timer = 1;
1536 } else {
1537 /*
1538 * XXX should power down card, wait 1s, power it back
1539 * up again..
1540 */
1541 printf("%s: device failed to complete selftest (code %x)\n",
1542 sc->sc_dev.dv_xname, test);
1543 ifp->if_timer = 0;
1544 }
1545 return;
1546 }
1547
1548
1549 /*
1550 * command timer: if it goes to zero, device failed to respond.
1551 * boot to the head.
1552 */
1553 if (sc->sc_cmd_timer) {
1554 sc->sc_cmd_timer--;
1555 if (sc->sc_cmd_timer == 0) {
1556 sc->sc_flags &= ~AWI_FL_CMD_INPROG;
1557
1558 printf("%s: timeout waiting for command completion\n",
1559 sc->sc_dev.dv_xname);
1560 test = awi_read_1(sc, AWI_CMD_STATUS);
1561 printf("%s: cmd status: %x\n", sc->sc_dev.dv_xname, test);
1562 test = awi_read_1(sc, AWI_CMD);
1563 printf("%s: cmd: %x\n", sc->sc_dev.dv_xname, test);
1564 awi_card_hexdump(sc, "CSB", AWI_CSB, 16);
1565 awi_reset(sc);
1566 return;
1567 }
1568 }
1569 /*
1570 * Transmit timer. If it goes to zero, device failed to deliver a
1571 * tx complete interrupt. boot to the head.
1572 */
1573 if (sc->sc_tx_timer) {
1574 sc->sc_tx_timer--;
1575 if ((sc->sc_tx_timer == 0) && (sc->sc_txpending)) {
1576 awi_card_hexdump(sc, "CSB", AWI_CSB, 16);
1577 printf("%s: transmit timeout\n", sc->sc_dev.dv_xname);
1578 awi_card_hexdump(sc, "last_txd", AWI_LAST_TXD, 5*4);
1579 for (i=0; i<sc->sc_ntxd; i++) {
1580 awi_card_hexdump(sc, "txd",
1581 sc->sc_txd[i].descr, AWI_TXD_SIZE);
1582 }
1583 awi_reset(sc);
1584 return;
1585 }
1586 }
1587 /*
1588 * Scan timer.
1589 * When synched, this is used to notice when we've stopped
1590 * receiving beacons and should attempt to resynch.
1591 *
1592 * When unsynched, this is used to notice if we've received an
1593 * interesting probe response and should synch up.
1594 */
1595
1596 if (sc->sc_scan_timer) {
1597 sc->sc_scan_timer--;
1598 if (sc->sc_scan_timer == 0) {
1599 if (sc->sc_state == AWI_ST_SCAN) {
1600 /*
1601 * XXX what if device fails to deliver
1602 * a scan-completion interrupt?
1603 */
1604 } else {
1605 printf("%s: no recent beacon from %s; rescanning\n",
1606 sc->sc_dev.dv_xname,
1607 ether_sprintf(sc->sc_active_bss.bss_id));
1608 awi_restart_scan(sc);
1609 }
1610 }
1611 }
1612
1613 /*
1614 * Management timer. Used to know when to send auth
1615 * requests and associate requests.
1616 */
1617 if (sc->sc_mgt_timer) {
1618 sc->sc_mgt_timer--;
1619 if (sc->sc_mgt_timer == 0) {
1620 switch (sc->sc_state)
1621 {
1622 case AWI_ST_SYNCED:
1623 case AWI_ST_RUNNING:
1624 sc->sc_state = AWI_ST_SYNCED;
1625 awi_send_authreq(sc);
1626 break;
1627 case AWI_ST_AUTHED:
1628 awi_send_assocreq(sc);
1629 break;
1630 default:
1631 printf("weird state for mgt timeout!\n");
1632 break;
1633 }
1634 }
1635 }
1636 awi_set_timer(sc);
1637 }
1638
1639 void
1640 awi_set_mc (sc)
1641 struct awi_softc *sc;
1642 {
1643 /* XXX not implemented yet.. */
1644 }
1645
1646 /*
1647 * init routine
1648 */
1649
1650 /*
1651 * ioctl routine
1652 * SIOCSIFADDR sets IFF_UP
1653 * SIOCIFMTU
1654 * SIOCSIFFLAGS
1655 * SIOCADDMULTI/SIOCDELMULTI
1656 */
1657
1658 int
1659 awi_ioctl(ifp, cmd, data)
1660 register struct ifnet *ifp;
1661 u_long cmd;
1662 caddr_t data;
1663 {
1664 struct awi_softc *sc = ifp->if_softc;
1665 struct ifaddr *ifa = (struct ifaddr *)data;
1666 struct ifreq *ifr = (struct ifreq *)data;
1667 int s, error = 0;
1668
1669 s = splnet();
1670
1671 switch (cmd) {
1672 case SIOCSIFADDR:
1673 if ((error = awi_enable(sc)) != 0)
1674 break;
1675
1676 ifp->if_flags |= IFF_UP;
1677
1678 /* XXX other AF support: inet6, NS, ... */
1679 switch (ifa->ifa_addr->sa_family) {
1680 #ifdef INET
1681 case AF_INET:
1682 arp_ifinit(sc->sc_ifp, ifa);
1683 break;
1684 #endif
1685 default:
1686 break;
1687 }
1688 break;
1689
1690 case SIOCSIFFLAGS:
1691 if ((ifp->if_flags & IFF_UP) == 0 &&
1692 (sc->sc_state != AWI_ST_OFF)) {
1693 /*
1694 * If interface is marked down and it is enabled, then
1695 * stop it.
1696 */
1697 ifp->if_flags &= ~IFF_RUNNING;
1698 awi_stop(sc);
1699 awi_disable(sc);
1700 } else if ((ifp->if_flags & IFF_UP) != 0 &&
1701 (ifp->if_flags & IFF_RUNNING) == 0) {
1702 /*
1703 * If interface is marked up and it is stopped, then
1704 * start it.
1705 */
1706 if ((error = awi_enable(sc)) != 0)
1707 break;
1708 } else if ((ifp->if_flags & IFF_UP) != 0) {
1709 /*
1710 * Deal with other flags that change hardware
1711 * state, i.e. IFF_PROMISC.
1712 */
1713 awi_set_mc(sc);
1714 }
1715 break;
1716 case SIOCADDMULTI:
1717 case SIOCDELMULTI:
1718 error = (cmd == SIOCADDMULTI) ?
1719 ether_addmulti(ifr, &sc->sc_ec) :
1720 ether_delmulti(ifr, &sc->sc_ec);
1721 if (error == ENETRESET) {
1722 error = 0;
1723 awi_set_mc(sc);
1724 }
1725 break;
1726
1727 default:
1728 error = EINVAL;
1729 break;
1730
1731 }
1732 splx(s);
1733 return error;
1734
1735 }
1736
1737 int awi_activate (self, act)
1738 struct device *self;
1739 enum devact act;
1740 {
1741 int s = splnet();
1742 panic("awi_activate");
1743
1744 #if 0
1745 switch (act) {
1746 case DVACT_ACTIVATE:
1747 rv = EOPNOTSUPP;
1748 break;
1749
1750 case DVACT_DEACTIVATE:
1751 #ifdef notyet
1752 /* First, kill off the interface. */
1753 if_detach(sc->sc_ethercom.ec_if);
1754 #endif
1755
1756 /* Now disable the interface. */
1757 awidisable(sc);
1758 break;
1759 }
1760 #endif
1761 splx(s);
1762
1763 }
1764
1765 int
1766 awi_drop_output (ifp, m0, dst, rt0)
1767 struct ifnet *ifp;
1768 struct mbuf *m0;
1769 struct sockaddr *dst;
1770 struct rtentry *rt0;
1771 {
1772 m_freem(m0);
1773 return 0;
1774 }
1775
1776 void
1777 awi_drop_input (ifp, m0)
1778 struct ifnet *ifp;
1779 struct mbuf *m0;
1780 {
1781 m_freem(m0);
1782 }
1783
1784 int awi_attach (sc, macaddr)
1785 struct awi_softc *sc;
1786 u_int8_t *macaddr;
1787 {
1788 struct ifnet *ifp = &sc->sc_ec.ec_if;
1789 u_int8_t version[AWI_BANNER_LEN];
1790
1791 sc->sc_ifp = ifp;
1792
1793 awi_read_bytes (sc, AWI_BANNER, version, AWI_BANNER_LEN);
1794 printf("%s: firmware %s\n", sc->sc_dev.dv_xname, version);
1795
1796 memcpy(sc->sc_my_addr, macaddr, ETHER_ADDR_LEN);
1797 printf("%s: 802.11 address %s\n", sc->sc_dev.dv_xname,
1798 ether_sprintf(sc->sc_my_addr));
1799
1800
1801 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
1802 ifp->if_softc = sc;
1803 ifp->if_start = awi_start;
1804 ifp->if_ioctl = awi_ioctl;
1805 ifp->if_watchdog = awi_watchdog;
1806 ifp->if_mtu = ETHERMTU;
1807 /* XXX simplex may not be correct here.. */
1808 ifp->if_flags =
1809 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
1810
1811 sc->sc_mgtq.ifq_maxlen = 5;
1812
1813 if_attach(ifp);
1814 ether_ifattach(ifp, sc->sc_my_addr);
1815 ifp->if_hdrlen = 32; /* 802.11 headers are bigger.. */
1816
1817 #if NBPFILTER > 0
1818 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
1819 #endif
1820 return 0;
1821 }
1822
1823 void
1824 awi_zero (sc, from, to)
1825 struct awi_softc *sc;
1826 u_int32_t from, to;
1827 {
1828 u_int32_t i;
1829 for (i=from; i<to; i++)
1830 awi_write_1(sc, i, 0);
1831 }
1832
1833 void
1834 awi_init (sc)
1835 struct awi_softc *sc;
1836 {
1837 struct ifnet *ifp = sc->sc_ifp;
1838
1839 sc->sc_scan_duration = 100; /* scan for 100ms */
1840
1841 /*
1842 * Maybe we should randomize these....
1843 */
1844 sc->sc_scan_chanset = IEEEWL_FH_CHANSET_MIN;
1845 sc->sc_scan_pattern = IEEEWL_FH_PATTERN_MIN;
1846
1847 sc->sc_flags &= ~AWI_FL_CMD_INPROG;
1848
1849 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1850 ifp->if_timer = 0;
1851
1852 sc->sc_cmd_timer = 0;
1853 sc->sc_tx_timer = 0;
1854 sc->sc_mgt_timer = 0;
1855 sc->sc_scan_timer = 0;
1856
1857 sc->sc_nbindings = 0;
1858
1859 /*
1860 * this reset sequence doesn't seem to always do the trick.
1861 * hard-power-cycling the card may do it..
1862 */
1863
1864 /*
1865 * reset the hardware, just to be sure.
1866 * (bring out the big hammer here..)
1867 */
1868 /* XXX insert delay here? */
1869
1870 am79c930_gcr_setbits (&sc->sc_chip, AM79C930_GCR_CORESET);
1871 delay(10); /* XXX arbitrary value */
1872
1873 /*
1874 * clear control memory regions (firmware should do this but...)
1875 */
1876 awi_zero(sc, AWI_LAST_TXD, AWI_BUFFERS);
1877
1878 awi_drvstate(sc, AWI_DRV_RESET);
1879 sc->sc_selftest_tries = 0;
1880
1881 /*
1882 * release reset
1883 */
1884 am79c930_gcr_clearbits (&sc->sc_chip, AM79C930_GCR_CORESET);
1885 delay(10);
1886
1887 sc->sc_state = AWI_ST_SELFTEST;
1888 ifp->if_timer = 1;
1889
1890 }
1891
1892 void
1893 awi_cmd (sc, opcode)
1894 struct awi_softc *sc;
1895 u_int8_t opcode;
1896 {
1897 if (sc->sc_flags & AWI_FL_CMD_INPROG)
1898 panic("%s: command reentered", sc->sc_dev.dv_xname);
1899
1900 sc->sc_flags |= AWI_FL_CMD_INPROG;
1901
1902 /* issue test-interface command */
1903 awi_write_1(sc, AWI_CMD, opcode);
1904
1905 awi_write_1(sc, AWI_CMD_STATUS, 0);
1906
1907 sc->sc_cmd_timer = 2;
1908 awi_set_timer(sc);
1909 }
1910
1911 void
1912 awi_cmd_test_if (sc)
1913 struct awi_softc *sc;
1914 {
1915 awi_cmd (sc, AWI_CMD_NOP);
1916 }
1917
1918 void
1919 awi_cmd_get_mib (sc, var, offset, len)
1920 struct awi_softc *sc;
1921 u_int8_t var;
1922 u_int8_t offset;
1923 u_int8_t len;
1924 {
1925 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, var);
1926 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, len);
1927 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX, offset);
1928
1929 awi_cmd (sc, AWI_CMD_GET_MIB);
1930 }
1931
1932 void
1933 awi_cmd_txinit (sc)
1934 struct awi_softc *sc;
1935 {
1936 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_DATA, sc->sc_txbase);
1937 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_MGT, 0);
1938 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_BCAST, 0);
1939 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_PS, 0);
1940 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_CF, 0);
1941
1942 awi_cmd (sc, AWI_CMD_INIT_TX);
1943 }
1944
1945 int awi_max_chan = -1;
1946 int awi_min_chan = 1000;
1947 int awi_max_pattern = -1;
1948 int awi_min_pattern = 1000;
1949
1950
1951 /*
1952 * timeout-driven routine: complete device init once device has passed
1953 * selftest.
1954 */
1955
1956 void awi_init_1 (sc)
1957 struct awi_softc *sc;
1958 {
1959 struct ifnet *ifp = sc->sc_ifp;
1960
1961 awi_intrinit(sc);
1962
1963 sc->sc_state = AWI_ST_IFTEST;
1964
1965 if (ifp->if_flags & IFF_DEBUG) {
1966 awi_card_hexdump(sc, "init_1 CSB", AWI_CSB, 16);
1967 sc->sc_completion = awi_mibdump;
1968 } else
1969 sc->sc_completion = awi_init_2;
1970
1971 sc->sc_curmib = 0;
1972
1973 awi_cmd_test_if (sc);
1974 }
1975
1976 void awi_mibdump (sc, status)
1977 struct awi_softc *sc;
1978 u_int8_t status;
1979 {
1980 u_int8_t mibblk[256];
1981
1982 if (status != AWI_STAT_OK) {
1983 printf("%s: pre-mibread failed (card unhappy?)\n",
1984 sc->sc_dev.dv_xname);
1985 awi_reset(sc);
1986 return;
1987 }
1988
1989 if (sc->sc_curmib != 0) {
1990 awi_read_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA,
1991 mibblk, 72);
1992 awi_hexdump("mib", mibblk, 72);
1993 }
1994 if (sc->sc_curmib > AWI_MIB_LAST) {
1995 awi_init_2 (sc, status);
1996 } else {
1997 sc->sc_completion = awi_mibdump;
1998 printf("mib %d\n", sc->sc_curmib);
1999 awi_cmd_get_mib (sc, sc->sc_curmib, 0, 30);
2000 sc->sc_curmib++;
2001 /* skip over reserved MIB's.. */
2002 if ((sc->sc_curmib == 1) || (sc->sc_curmib == 6))
2003 sc->sc_curmib++;
2004 }
2005 }
2006
2007
2008 /*
2009 * called on completion of test-interface command in first-stage init.
2010 */
2011
2012 void awi_init_2 (sc, status)
2013 struct awi_softc *sc;
2014 u_int8_t status;
2015 {
2016 /* did it succeed? */
2017 if (status != AWI_STAT_OK) {
2018 printf("%s: nop failed (card unhappy?)\n",
2019 sc->sc_dev.dv_xname);
2020 awi_reset(sc);
2021 }
2022
2023 sc->sc_state = AWI_ST_MIB_GET;
2024 sc->sc_completion = awi_init_read_bufptrs_done;
2025
2026 awi_cmd_get_mib (sc, AWI_MIB_LOCAL, 0, AWI_MIB_LOCAL_SIZE);
2027 }
2028
2029 void awi_init_read_bufptrs_done (sc, status)
2030 struct awi_softc *sc;
2031 u_int8_t status;
2032 {
2033 if (status != AWI_STAT_OK) {
2034 printf("%s: get_mib failed (card unhappy?)\n",
2035 sc->sc_dev.dv_xname);
2036 awi_reset(sc);
2037 }
2038
2039 sc->sc_txbase = awi_read_4 (sc,
2040 AWI_CMD_PARAMS+AWI_CA_MIB_DATA+AWI_MIB_LOCAL_TXB_OFFSET);
2041 sc->sc_txlen = awi_read_4 (sc,
2042 AWI_CMD_PARAMS+AWI_CA_MIB_DATA+AWI_MIB_LOCAL_TXB_SIZE);
2043 sc->sc_rxbase = awi_read_4 (sc,
2044 AWI_CMD_PARAMS+AWI_CA_MIB_DATA+AWI_MIB_LOCAL_RXB_OFFSET);
2045 sc->sc_rxlen = awi_read_4 (sc,
2046 AWI_CMD_PARAMS+AWI_CA_MIB_DATA+AWI_MIB_LOCAL_RXB_SIZE);
2047 /*
2048 * XXX consider repartitioning buffer space to allow for
2049 * more efficient usage.
2050 * 6144: 3 txds, 1476 waste (current partition)
2051 * better splits:
2052 * 4864: 3 txds, 196 waste
2053 * 6400: 4 txds, 176 waste
2054 * 7936: 5 txds, 156 waste
2055 */
2056
2057 #if 0
2058 printf("tx offset: %x\n", sc->sc_txbase);
2059 printf("tx size: %x\n", sc->sc_txlen);
2060 printf("rx offset: %x\n", sc->sc_rxbase);
2061 printf("rx size: %x\n", sc->sc_rxlen);
2062 #endif
2063
2064 sc->sc_state = AWI_ST_MIB_SET;
2065 awi_cmd_set_notap(sc);
2066 }
2067
2068 void awi_cmd_set_notap (sc)
2069 struct awi_softc *sc;
2070 {
2071 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, AWI_MIB_LOCAL);
2072 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, 1);
2073 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX,
2074 AWI_MIB_LOCAL_ACTING_AS_AP);
2075
2076 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, 0);
2077 sc->sc_completion = awi_cmd_set_notap_done;
2078 awi_cmd (sc, AWI_CMD_SET_MIB);
2079 }
2080
2081 void awi_cmd_set_notap_done (sc, status)
2082 struct awi_softc *sc;
2083 u_int8_t status;
2084 {
2085 if (status != AWI_STAT_OK) {
2086 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2087 printf("%s: set_infra failed (card unhappy?); erroffset %d\n",
2088 sc->sc_dev.dv_xname,
2089 erroffset);
2090 awi_reset(sc);
2091 return;
2092 }
2093 awi_cmd_set_infra (sc);
2094 }
2095
2096 void awi_cmd_set_infra (sc)
2097 struct awi_softc *sc;
2098 {
2099
2100 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, AWI_MIB_LOCAL);
2101 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, 1);
2102 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX,
2103 AWI_MIB_LOCAL_INFRA_MODE);
2104
2105 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, 1);
2106 sc->sc_completion = awi_cmd_set_infra_done;
2107 awi_cmd (sc, AWI_CMD_SET_MIB);
2108 }
2109
2110 void awi_cmd_set_infra_done (sc, status)
2111 struct awi_softc *sc;
2112 u_int8_t status;
2113 {
2114 #if 0
2115 printf("set_infra done\n");
2116 #endif
2117 if (status != AWI_STAT_OK) {
2118 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2119 printf("%s: set_infra failed (card unhappy?); erroffset %d\n",
2120 sc->sc_dev.dv_xname,
2121 erroffset);
2122 awi_reset(sc);
2123 return;
2124 }
2125 #if 0
2126 printf("%s: set_infra done\n", sc->sc_dev.dv_xname);
2127 #endif
2128 awi_cmd_set_allmulti (sc);
2129 }
2130
2131 void awi_cmd_set_allmulti (sc)
2132 struct awi_softc *sc;
2133 {
2134 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, AWI_MIB_LOCAL);
2135 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, 1);
2136 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX,
2137 AWI_MIB_LOCAL_FILTMULTI);
2138 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, 0);
2139 sc->sc_completion = awi_cmd_set_allmulti_done;
2140 awi_cmd (sc, AWI_CMD_SET_MIB);
2141 }
2142
2143 void awi_cmd_set_allmulti_done (sc, status)
2144 struct awi_softc *sc;
2145 u_int8_t status;
2146 {
2147 if (status != AWI_STAT_OK) {
2148 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2149 printf("%s: set_almulti_done failed (card unhappy?); erroffset %d\n",
2150 sc->sc_dev.dv_xname,
2151 erroffset);
2152 awi_reset(sc);
2153 return;
2154 }
2155 awi_cmd_set_promisc (sc);
2156 }
2157
2158 void awi_cmd_set_promisc (sc)
2159 struct awi_softc *sc;
2160 {
2161 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, AWI_MIB_MAC);
2162 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, 1);
2163 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX,
2164 AWI_MIB_MAC_PROMISC);
2165 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, 0); /* XXX */
2166 sc->sc_completion = awi_cmd_set_promisc_done;
2167 awi_cmd (sc, AWI_CMD_SET_MIB);
2168 }
2169
2170 void awi_cmd_set_promisc_done (sc, status)
2171 struct awi_softc *sc;
2172 u_int8_t status;
2173 {
2174 #if 0
2175 printf("set promisc_done\n");
2176 #endif
2177
2178 if (status != AWI_STAT_OK) {
2179 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2180 printf("%s: set_promisc_done failed (card unhappy?); erroffset %d\n",
2181 sc->sc_dev.dv_xname,
2182 erroffset);
2183 awi_reset(sc);
2184 return;
2185 }
2186 #if 0
2187 printf("%s: set_promisc done\n", sc->sc_dev.dv_xname);
2188 #endif
2189
2190 awi_init_txdescr(sc);
2191
2192 sc->sc_state = AWI_ST_TXINIT;
2193 sc->sc_completion = awi_init_4;
2194 awi_cmd_txinit(sc);
2195 }
2196
2197 void
2198 awi_init_4 (sc, status)
2199 struct awi_softc *sc;
2200 u_int8_t status;
2201 {
2202 #if 0
2203 printf("%s: awi_init_4, st %x\n", sc->sc_dev.dv_xname, status);
2204 awi_card_hexdump(sc, "init_4 CSB", AWI_CSB, 16);
2205 #endif
2206
2207 if (status != AWI_STAT_OK) {
2208 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2209 printf("%s: init_tx failed (card unhappy?); erroffset %d\n",
2210 sc->sc_dev.dv_xname,
2211 erroffset);
2212 awi_reset(sc);
2213 return;
2214 }
2215
2216 sc->sc_state = AWI_ST_RXINIT;
2217 sc->sc_completion = awi_init_5;
2218
2219 awi_cmd (sc, AWI_CMD_INIT_RX);
2220 }
2221
2222 void awi_init_5 (sc, status)
2223 struct awi_softc *sc;
2224 u_int8_t status;
2225 {
2226 #if 0
2227 struct ifnet *ifp = sc->sc_ifp;
2228 #endif
2229
2230 #if 0
2231 printf("%s: awi_init_5, st %x\n", sc->sc_dev.dv_xname, status);
2232 awi_card_hexdump(sc, "init_5 CSB", AWI_CSB, 16);
2233 #endif
2234
2235 if (status != AWI_STAT_OK) {
2236 printf("%s: init_rx failed (card unhappy?)\n",
2237 sc->sc_dev.dv_xname);
2238 awi_reset(sc);
2239 return;
2240 }
2241
2242 sc->sc_rx_data_desc = awi_read_4(sc, AWI_CMD_PARAMS+AWI_CA_IRX_DATA_DESC);
2243 sc->sc_rx_mgt_desc = awi_read_4(sc, AWI_CMD_PARAMS+AWI_CA_IRX_PS_DESC);
2244
2245 #if 0
2246 printf("%s: data desc %x, mgt desc %x\n", sc->sc_dev.dv_xname,
2247 sc->sc_rx_data_desc, sc->sc_rx_mgt_desc);
2248 #endif
2249 awi_restart_scan(sc);
2250 }
2251
2252 void awi_restart_scan (sc)
2253 struct awi_softc *sc;
2254 {
2255 sc->sc_scan_timer = 2;
2256 sc->sc_mgt_timer = 0;
2257 awi_set_timer(sc);
2258
2259 sc->sc_nbindings = 0;
2260 sc->sc_state = AWI_ST_SCAN;
2261 awi_drvstate (sc, AWI_DRV_INFSC);
2262 awi_cmd_scan (sc);
2263 }
2264
2265 void
2266 awi_cmd_scan (sc)
2267 struct awi_softc *sc;
2268 {
2269
2270 awi_write_2 (sc, AWI_CMD_PARAMS+AWI_CA_SCAN_DURATION,
2271 sc->sc_scan_duration);
2272 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SET,
2273 sc->sc_scan_chanset);
2274 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SCAN_PATTERN,
2275 sc->sc_scan_pattern);
2276 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SCAN_IDX, 1);
2277 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SUSP, 0);
2278
2279 sc->sc_completion = awi_cmd_scan_done;
2280 awi_cmd (sc, AWI_CMD_SCAN);
2281 }
2282
2283 void
2284 awi_cmd_scan_done (sc, status)
2285 struct awi_softc *sc;
2286 u_int8_t status;
2287 {
2288 #if 0
2289 int erroffset;
2290 #endif
2291 if (status == AWI_STAT_OK) {
2292 if (sc->sc_scan_chanset > awi_max_chan)
2293 awi_max_chan = sc->sc_scan_chanset;
2294 if (sc->sc_scan_chanset < awi_min_chan)
2295 awi_min_chan = sc->sc_scan_chanset;
2296 if (sc->sc_scan_pattern > awi_max_pattern)
2297 awi_max_pattern = sc->sc_scan_pattern;
2298 if (sc->sc_scan_pattern < awi_min_pattern)
2299 awi_min_pattern = sc->sc_scan_pattern;
2300
2301 return;
2302 }
2303 #if 0
2304 erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2305 printf("%s: scan failed; erroffset %d\n", sc->sc_dev.dv_xname,
2306 erroffset);
2307 #endif
2308 /* wait for response or scan timeout.. */
2309 }
2310
2311 void
2312 awi_scan_next (sc)
2313 struct awi_softc *sc;
2314 {
2315 sc->sc_scan_pattern++;
2316 if (sc->sc_scan_pattern > IEEEWL_FH_PATTERN_MAX) {
2317 sc->sc_scan_pattern = IEEEWL_FH_PATTERN_MIN;
2318
2319 sc->sc_scan_chanset++;
2320 if (sc->sc_scan_chanset > IEEEWL_FH_CHANSET_MAX)
2321 sc->sc_scan_chanset = IEEEWL_FH_CHANSET_MIN;
2322 }
2323 #if 0
2324 printf("scan: pattern %x chanset %x\n", sc->sc_scan_pattern,
2325 sc->sc_scan_chanset);
2326 #endif
2327
2328 awi_cmd_scan(sc);
2329 }
2330
2331 void
2332 awi_try_sync (sc)
2333 struct awi_softc *sc;
2334 {
2335 int max_rssi = 0, best = 0;
2336 int i;
2337 struct awi_bss_binding *bp = NULL;
2338
2339 /* pick one with best rssi */
2340 for (i=0; i<sc->sc_nbindings; i++) {
2341 bp = &sc->sc_bindings[i];
2342
2343 if (bp->rssi > max_rssi) {
2344 max_rssi = bp->rssi;
2345 best = i;
2346 }
2347 }
2348
2349 #if 0
2350 printf("best: %d\n", best);
2351 #endif
2352 if (bp == NULL) {
2353 return;
2354 }
2355 sc->sc_scan_timer = awi_scan_keepalive;
2356
2357 bp = &sc->sc_bindings[best];
2358 memcpy(&sc->sc_active_bss, bp, sizeof(*bp));
2359 sc->sc_new_bss = 1;
2360
2361 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_SET, bp->chanset);
2362 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_PATTERN, bp->pattern);
2363 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_IDX, bp->index);
2364 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_STARTBSS, 0);
2365
2366 awi_write_2 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_DWELL, bp->dwell_time);
2367 awi_write_2 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_MBZ, 0);
2368
2369 awi_write_bytes (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_TIMESTAMP,
2370 bp->bss_timestamp, 8);
2371 awi_write_4 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_REFTIME, bp->rxtime);
2372
2373 sc->sc_completion = awi_cmd_sync_done;
2374
2375 awi_cmd (sc, AWI_CMD_SYNC);
2376
2377 }
2378
2379 void
2380 awi_cmd_sync_done (sc, status)
2381 struct awi_softc *sc;
2382 u_int8_t status;
2383 {
2384 if (status != AWI_STAT_OK) {
2385 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2386 printf("%s: sync_done failed (card unhappy?); erroffset %d\n",
2387 sc->sc_dev.dv_xname,
2388 erroffset);
2389 awi_reset(sc);
2390 return;
2391 }
2392
2393 /*
2394 * at this point, the card should be synchronized with the AP
2395 * we heard from. tell the card what BSS and ESS it's running in..
2396 */
2397
2398 awi_drvstate (sc, AWI_DRV_INFSY);
2399 #if 0
2400 printf("%s: sync done, setting bss/iss parameters\n",
2401 sc->sc_dev.dv_xname);
2402 awi_hexdump ("bss", sc->sc_active_bss.bss_id, ETHER_ADDR_LEN);
2403 printf("ssid: %s\n", sc->sc_active_bss.ssid);
2404 #endif
2405 awi_cmd_set_ss (sc);
2406 }
2407
2408
2409 void awi_cmd_set_ss (sc)
2410 struct awi_softc *sc;
2411 {
2412 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, AWI_MIB_MAC_MGT);
2413 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE,
2414 ETHER_ADDR_LEN + AWI_MIB_MGT_ESS_SIZE);
2415 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX,
2416 AWI_MIB_MGT_BSS_ID);
2417
2418 awi_write_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA,
2419 sc->sc_active_bss.bss_id, ETHER_ADDR_LEN);
2420 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA+ETHER_ADDR_LEN,
2421 0); /* XXX */
2422 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA+ETHER_ADDR_LEN+1,
2423 sc->sc_active_bss.sslen);
2424 awi_write_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA+8,
2425 sc->sc_active_bss.ssid, AWI_MIB_MGT_ESS_SIZE-2);
2426
2427 sc->sc_completion = awi_cmd_set_ss_done;
2428 awi_cmd (sc, AWI_CMD_SET_MIB);
2429 }
2430
2431 void awi_cmd_set_ss_done (sc, status)
2432 struct awi_softc *sc;
2433 u_int8_t status;
2434 {
2435 if (status != AWI_STAT_OK) {
2436 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2437 printf("%s: set_ss_done failed (card unhappy?); erroffset %d\n",
2438 sc->sc_dev.dv_xname,
2439 erroffset);
2440 awi_reset(sc);
2441 return;
2442 }
2443 #if 0
2444 printf("%s: set_ss done\n", sc->sc_dev.dv_xname);
2445 #endif
2446
2447 awi_running (sc);
2448
2449 /*
2450 * now, we *should* be getting broadcast frames..
2451 */
2452 sc->sc_state = AWI_ST_SYNCED;
2453 awi_send_authreq (sc);
2454
2455 }
2456
2457 void awi_running (sc)
2458 struct awi_softc *sc;
2459
2460 {
2461 struct ifnet *ifp = sc->sc_ifp;
2462
2463 /*
2464 * Who knows what it is to be running?
2465 * Only he who is running knows..
2466 */
2467 ifp->if_flags |= IFF_RUNNING;
2468 awi_start(ifp);
2469 }
2470
2471
2472 void awi_reset (sc)
2473 struct awi_softc *sc;
2474 {
2475 printf("%s: reset\n", sc->sc_dev.dv_xname);
2476
2477 }
2478