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