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