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