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