awi.c revision 1.3 1 /* $NetBSD: awi.c,v 1.3 1999/11/05 05:13:36 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 m = top;
1209 m->m_pkthdr.rcvif = ifp;
1210 m->m_pkthdr.len = 0;
1211 m->m_len = 0;
1212
1213 mleft = MHLEN;
1214 mptr = mtod(m, u_int8_t *);
1215 }
1216 for(;;) {
1217 if (top != 0) {
1218 /* copy data into mbuf */
1219 while (len > 0) {
1220 int nmove = min (len, mleft);
1221
1222 awi_read_bytes (sc, frame, mptr, nmove);
1223 len -= nmove;
1224 mleft -= nmove;
1225 mptr += nmove;
1226 frame += nmove;
1227
1228 top->m_pkthdr.len += nmove;
1229 m->m_len += nmove;
1230
1231 if (mleft == 0) {
1232 /* Get next mbuf.. */
1233 MGET(m1, M_DONTWAIT, MT_DATA);
1234 if (m1 == NULL) {
1235 panic("awi mget"); /* XXX */
1236 }
1237 m->m_next = m1;
1238 m = m1;
1239 m->m_len = 0;
1240
1241 mleft = MLEN;
1242 mptr = mtod(m, u_int8_t *);
1243 }
1244 }
1245 }
1246 state |= AWI_RXD_ST_CONSUMED | AWI_RXD_ST_OWN;
1247 awi_write_1(sc, cur + AWI_RXD_HOST_DESC_STATE, state);
1248
1249 if (state & AWI_RXD_ST_LF)
1250 break;
1251
1252 if (next & AWI_RXD_NEXT_LAST)
1253 panic("awi oops"); /* XXX */
1254
1255 /* XXX deal with dummy frames here?? */
1256
1257 cur = next;
1258 state = awi_read_1(sc, cur + AWI_RXD_HOST_DESC_STATE);
1259 len = awi_read_2 (sc, cur + AWI_RXD_LEN);
1260 rate = awi_read_1 (sc, cur + AWI_RXD_RATE);
1261 rssi = awi_read_1 (sc, cur + AWI_RXD_RSSI);
1262 index = awi_read_1 (sc, cur + AWI_RXD_INDEX);
1263 frame = awi_read_4 (sc, cur + AWI_RXD_START_FRAME);
1264 frame &= 0xffff;
1265 next &= 0xffff;
1266 }
1267 }
1268 if (top) {
1269 awi_rcv(sc, top, rxts, rssi);
1270 top = 0;
1271 }
1272 cur = next;
1273 }
1274 *descr = cur;
1275 }
1276
1277
1278
1279
1280 void
1281 awi_rxint (sc)
1282 struct awi_softc *sc;
1283 {
1284 awi_dump_rxchain (sc, "mgt", &sc->sc_rx_mgt_desc);
1285 awi_dump_rxchain (sc, "data", &sc->sc_rx_data_desc);
1286 }
1287
1288 void
1289 awi_init_txd (sc, tx, flag, len, rate)
1290 struct awi_softc *sc;
1291 int tx;
1292 int flag;
1293 int len;
1294 int rate;
1295 {
1296 u_int32_t txdbase = sc->sc_txd[tx].descr;
1297 u_int32_t framebase = sc->sc_txd[tx].frame;
1298 u_int32_t nextbase = sc->sc_txd[(tx+1)%sc->sc_ntxd].descr;
1299
1300 awi_write_4 (sc, txdbase + AWI_TXD_START, framebase);
1301 awi_write_4 (sc, txdbase + AWI_TXD_NEXT, nextbase);
1302 awi_write_4 (sc, txdbase + AWI_TXD_LENGTH, len);
1303 awi_write_1 (sc, txdbase + AWI_TXD_RATE, rate);
1304 /* zeroize tail end of txd */
1305 awi_write_4 (sc, txdbase + AWI_TXD_NDA, 0);
1306 awi_write_4 (sc, txdbase + AWI_TXD_NRA, 0);
1307 /* Init state last; firmware keys off of this to know when to start tx */
1308 awi_write_1 (sc, txdbase + AWI_TXD_STATE, flag);
1309 }
1310
1311 void
1312 awi_init_txdescr (sc)
1313 struct awi_softc *sc;
1314 {
1315 int i;
1316 u_int32_t offset = sc->sc_txbase;
1317
1318 sc->sc_txfirst = 0;
1319 sc->sc_txnext = 0;
1320
1321 sc->sc_ntxd = sc->sc_txlen / (AWI_FRAME_SIZE + AWI_TXD_SIZE);
1322 if (sc->sc_ntxd > NTXD) {
1323 sc->sc_ntxd = NTXD;
1324 printf("oops, no, only %d\n", sc->sc_ntxd);
1325 }
1326
1327 /* Allocate TXD's */
1328 for (i=0; i<sc->sc_ntxd; i++) {
1329 sc->sc_txd[i].descr = offset;
1330 offset += AWI_TXD_SIZE;
1331 }
1332 /* now, allocate buffer space to each txd.. */
1333 for (i=0; i<sc->sc_ntxd; i++) {
1334 sc->sc_txd[i].frame = offset;
1335 sc->sc_txd[i].len = AWI_FRAME_SIZE;
1336 offset += AWI_FRAME_SIZE;
1337
1338 }
1339
1340 /* now, initialize the TX descriptors into a circular linked list. */
1341
1342 for (i= 0; i<sc->sc_ntxd; i++) {
1343 awi_init_txd(sc, i, 0, 0, 0);
1344 }
1345 }
1346
1347 void
1348 awi_txint (sc)
1349 struct awi_softc *sc;
1350 {
1351 struct ifnet *ifp = sc->sc_ifp;
1352 int txfirst;
1353
1354 sc->sc_tx_timer = 0;
1355
1356 txfirst = sc->sc_txfirst;
1357 while (sc->sc_txpending > 0) {
1358 u_int8_t flags = awi_read_1 (sc, sc->sc_txd[txfirst].descr +
1359 AWI_TXD_STATE);
1360
1361 if (flags & AWI_TXD_ST_OWN)
1362 break;
1363
1364 if (flags & AWI_TXD_ST_ERROR) {
1365 /* increment oerrs */;
1366 }
1367
1368 txfirst = (txfirst + 1) % sc->sc_ntxd;
1369 sc->sc_txpending--;
1370 }
1371
1372 sc->sc_txfirst = txfirst;
1373
1374 if (sc->sc_txpending < sc->sc_ntxd)
1375 ifp->if_flags &= ~IFF_OACTIVE;
1376
1377 /*
1378 * see which descriptors are done..
1379 */
1380
1381 awi_start(sc->sc_ifp);
1382 }
1383
1384
1385
1386
1387 /*
1388 * device interrupt routine.
1389 *
1390 * lock out MAC
1391 * loop:
1392 * look at intr status, DTRT.
1393 *
1394 * on tx done, reclaim free buffers from tx, call start.
1395 * on rx done, look at rx queue, copy to mbufs, mark as free,
1396 * hand to ether media layer rx routine.
1397 * on cmd done, call cmd cmpl continuation.
1398 *
1399 */
1400
1401 int
1402 awi_intr(arg)
1403 void *arg;
1404 {
1405 struct awi_softc *sc = arg;
1406 int handled = 0;
1407
1408 if (sc->sc_state == AWI_ST_OFF) {
1409 u_int8_t intstate = awi_read_intst (sc);
1410 return intstate != 0;
1411 }
1412
1413 /* disable power down, (and implicitly ack interrupt) */
1414 am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_DISPWDN);
1415 awi_write_1(sc, AWI_DIS_PWRDN, 1);
1416
1417 for (;;) {
1418 u_int8_t intstate = awi_read_intst (sc);
1419
1420 if (!intstate)
1421 break;
1422
1423 handled = 1;
1424
1425 if (intstate & AWI_INT_RX)
1426 awi_rxint(sc);
1427
1428 if (intstate & AWI_INT_TX)
1429 awi_txint(sc);
1430
1431 if (intstate & AWI_INT_CMD) {
1432 u_int8_t status;
1433
1434 if (!(sc->sc_flags & AWI_FL_CMD_INPROG))
1435 printf("%s: no command in progress?\n",
1436 sc->sc_dev.dv_xname);
1437 status = awi_read_1(sc, AWI_CMD_STATUS);
1438 awi_write_1 (sc, AWI_CMD, 0);
1439 sc->sc_cmd_timer = 0;
1440 sc->sc_flags &= ~AWI_FL_CMD_INPROG;
1441
1442 if (sc->sc_completion)
1443 (*sc->sc_completion)(sc, status);
1444 }
1445 if (intstate & AWI_INT_SCAN_CMPLT) {
1446 if (sc->sc_flags & AWI_FL_CMD_INPROG) {
1447 panic("i can't take it any more");
1448 }
1449 /*
1450 * scan completion heuristic..
1451 */
1452 if ((sc->sc_nbindings >= NBND)
1453 || ((sc->sc_scan_timer == 0) &&
1454 (sc->sc_nbindings > 0)))
1455 awi_try_sync(sc);
1456 else
1457 awi_scan_next(sc);
1458 }
1459
1460 }
1461 /* reenable power down */
1462 am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_DISPWDN);
1463 awi_write_1(sc, AWI_DIS_PWRDN, 0);
1464
1465 return handled;
1466 }
1467
1468 /*
1469 * device stop routine
1470 */
1471
1472 void
1473 awi_stop(sc)
1474 struct awi_softc *sc;
1475 {
1476 struct ifnet *ifp = sc->sc_ifp;
1477
1478 /* Turn off timer.. */
1479 ifp->if_timer = 0;
1480 sc->sc_state = AWI_ST_OFF;
1481 (void) awi_read_intst (sc);
1482 /*
1483 * XXX for pcmcia, there's no point in disabling the device,
1484 * as it's about to be powered off..
1485 * for non-PCMCIA attachments, we should, however, stop
1486 * the receiver and transmitter here.
1487 */
1488 }
1489
1490 /*
1491 * Watchdog routine, triggered by timer.
1492 * This does periodic maintainance-type tasks on the interface.
1493 */
1494
1495 void
1496 awi_watchdog(ifp)
1497 struct ifnet *ifp;
1498 {
1499 struct awi_softc *sc = ifp->if_softc;
1500 u_int8_t test;
1501 int i;
1502
1503 if (sc->sc_state == AWI_ST_OFF)
1504 /* nothing to do */
1505 return;
1506 else if (sc->sc_state == AWI_ST_INSANE) {
1507 awi_reset(sc);
1508 return;
1509 } else if (sc->sc_state == AWI_ST_SELFTEST) {
1510 /* check for selftest completion.. */
1511 test = awi_read_1(sc, AWI_SELFTEST);
1512 if ((test & 0xf0) == 0xf0) { /* XXX magic numbers */
1513 if (test == AWI_SELFTEST_PASSED) {
1514 awi_init_1(sc);
1515 } else {
1516 printf("%s: selftest failed (code %x)\n",
1517 sc->sc_dev.dv_xname, test);
1518 awi_reset(sc);
1519 }
1520 }
1521 sc->sc_selftest_tries++;
1522 /* still running. try again on next tick */
1523 if (sc->sc_selftest_tries < 5) {
1524 ifp->if_timer = 1;
1525 } else {
1526 /*
1527 * XXX should power down card, wait 1s, power it back
1528 * up again..
1529 */
1530 printf("%s: device failed to complete selftest (code %x)\n",
1531 sc->sc_dev.dv_xname, test);
1532 ifp->if_timer = 0;
1533 }
1534 return;
1535 }
1536
1537
1538 /*
1539 * command timer: if it goes to zero, device failed to respond.
1540 * boot to the head.
1541 */
1542 if (sc->sc_cmd_timer) {
1543 sc->sc_cmd_timer--;
1544 if (sc->sc_cmd_timer == 0) {
1545 sc->sc_flags &= ~AWI_FL_CMD_INPROG;
1546
1547 printf("%s: timeout waiting for command completion\n",
1548 sc->sc_dev.dv_xname);
1549 test = awi_read_1(sc, AWI_CMD_STATUS);
1550 printf("%s: cmd status: %x\n", sc->sc_dev.dv_xname, test);
1551 test = awi_read_1(sc, AWI_CMD);
1552 printf("%s: cmd: %x\n", sc->sc_dev.dv_xname, test);
1553 awi_card_hexdump(sc, "CSB", AWI_CSB, 16);
1554 awi_reset(sc);
1555 return;
1556 }
1557 }
1558 /*
1559 * Transmit timer. If it goes to zero, device failed to deliver a
1560 * tx complete interrupt. boot to the head.
1561 */
1562 if (sc->sc_tx_timer) {
1563 sc->sc_tx_timer--;
1564 if ((sc->sc_tx_timer == 0) && (sc->sc_txpending)) {
1565 awi_card_hexdump(sc, "CSB", AWI_CSB, 16);
1566 printf("%s: transmit timeout\n", sc->sc_dev.dv_xname);
1567 awi_card_hexdump(sc, "last_txd", AWI_LAST_TXD, 5*4);
1568 for (i=0; i<sc->sc_ntxd; i++) {
1569 awi_card_hexdump(sc, "txd",
1570 sc->sc_txd[i].descr, AWI_TXD_SIZE);
1571 }
1572 awi_reset(sc);
1573 return;
1574 }
1575 }
1576 /*
1577 * Scan timer.
1578 * When synched, this is used to notice when we've stopped
1579 * receiving beacons and should attempt to resynch.
1580 *
1581 * When unsynched, this is used to notice if we've received an
1582 * interesting probe response and should synch up.
1583 */
1584
1585 if (sc->sc_scan_timer) {
1586 sc->sc_scan_timer--;
1587 if (sc->sc_scan_timer == 0) {
1588 if (sc->sc_state == AWI_ST_SCAN) {
1589 /*
1590 * XXX what if device fails to deliver
1591 * a scan-completion interrupt?
1592 */
1593 } else {
1594 printf("%s: no recent beacon from %s; rescanning\n",
1595 sc->sc_dev.dv_xname,
1596 ether_sprintf(sc->sc_active_bss.bss_id));
1597 awi_restart_scan(sc);
1598 }
1599 }
1600 }
1601
1602 /*
1603 * Management timer. Used to know when to send auth
1604 * requests and associate requests.
1605 */
1606 if (sc->sc_mgt_timer) {
1607 sc->sc_mgt_timer--;
1608 if (sc->sc_mgt_timer == 0) {
1609 switch (sc->sc_state)
1610 {
1611 case AWI_ST_SYNCED:
1612 case AWI_ST_RUNNING:
1613 sc->sc_state = AWI_ST_SYNCED;
1614 awi_send_authreq(sc);
1615 break;
1616 case AWI_ST_AUTHED:
1617 awi_send_assocreq(sc);
1618 break;
1619 default:
1620 printf("weird state for mgt timeout!\n");
1621 break;
1622 }
1623 }
1624 }
1625 awi_set_timer(sc);
1626 }
1627
1628 void
1629 awi_set_mc (sc)
1630 struct awi_softc *sc;
1631 {
1632 /* XXX not implemented yet.. */
1633 }
1634
1635 /*
1636 * init routine
1637 */
1638
1639 /*
1640 * ioctl routine
1641 * SIOCSIFADDR sets IFF_UP
1642 * SIOCIFMTU
1643 * SIOCSIFFLAGS
1644 * SIOCADDMULTI/SIOCDELMULTI
1645 */
1646
1647 int
1648 awi_ioctl(ifp, cmd, data)
1649 register struct ifnet *ifp;
1650 u_long cmd;
1651 caddr_t data;
1652 {
1653 struct awi_softc *sc = ifp->if_softc;
1654 struct ifaddr *ifa = (struct ifaddr *)data;
1655 #if 0
1656 struct ifreq *ifr = (struct ifreq *)data;
1657 #endif
1658 int s, error = 0;
1659
1660 s = splnet();
1661
1662 switch (cmd) {
1663 case SIOCSIFADDR:
1664 if ((error = awi_enable(sc)) != 0)
1665 break;
1666
1667 ifp->if_flags |= IFF_UP;
1668
1669 /* XXX other AF support: inet6, NS, ... */
1670 switch (ifa->ifa_addr->sa_family) {
1671 #ifdef INET
1672 case AF_INET:
1673 arp_ifinit(&sc->sc_ec.ec_if, ifa);
1674 break;
1675 #endif
1676 default:
1677 break;
1678 }
1679 break;
1680
1681 case SIOCSIFFLAGS:
1682 if ((ifp->if_flags & IFF_UP) == 0 &&
1683 (sc->sc_state != AWI_ST_OFF)) {
1684 /*
1685 * If interface is marked down and it is enabled, then
1686 * stop it.
1687 */
1688 ifp->if_flags &= ~IFF_RUNNING;
1689 awi_stop(sc);
1690 awi_disable(sc);
1691 } else if ((ifp->if_flags & IFF_UP) != 0 &&
1692 (ifp->if_flags & IFF_RUNNING) == 0) {
1693 /*
1694 * If interface is marked up and it is stopped, then
1695 * start it.
1696 */
1697 if ((error = awi_enable(sc)) != 0)
1698 break;
1699 } else if ((ifp->if_flags & IFF_UP) != 0) {
1700 /*
1701 * Deal with other flags that change hardware
1702 * state, i.e. IFF_PROMISC.
1703 */
1704 awi_set_mc(sc);
1705 }
1706 break;
1707 default:
1708 error = EINVAL;
1709 break;
1710
1711 }
1712 splx(s);
1713 return error;
1714
1715 }
1716
1717 int awi_activate (self, act)
1718 struct device *self;
1719 enum devact act;
1720 {
1721 int s = splnet();
1722 panic("awi_activate");
1723
1724 #if 0
1725 switch (act) {
1726 case DVACT_ACTIVATE:
1727 rv = EOPNOTSUPP;
1728 break;
1729
1730 case DVACT_DEACTIVATE:
1731 #ifdef notyet
1732 /* First, kill off the interface. */
1733 if_detach(sc->sc_ethercom.ec_if);
1734 #endif
1735
1736 /* Now disable the interface. */
1737 awidisable(sc);
1738 break;
1739 }
1740 #endif
1741 splx(s);
1742
1743 }
1744
1745 int
1746 awi_drop_output (ifp, m0, dst, rt0)
1747 struct ifnet *ifp;
1748 struct mbuf *m0;
1749 struct sockaddr *dst;
1750 struct rtentry *rt0;
1751 {
1752 m_freem(m0);
1753 return 0;
1754 }
1755
1756 void
1757 awi_drop_input (ifp, m0)
1758 struct ifnet *ifp;
1759 struct mbuf *m0;
1760 {
1761 m_freem(m0);
1762 }
1763
1764 int awi_attach (sc)
1765 struct awi_softc *sc;
1766 {
1767 struct ifnet *ifp = &sc->sc_ec.ec_if;
1768 u_int8_t version[AWI_BANNER_LEN];
1769
1770 sc->sc_ifp = ifp;
1771
1772 awi_read_bytes (sc, AWI_BANNER, version, AWI_BANNER_LEN);
1773 printf("%s: firmware %s\n", sc->sc_dev.dv_xname, version);
1774
1775 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
1776 ifp->if_softc = sc;
1777 ifp->if_start = awi_start;
1778 ifp->if_ioctl = awi_ioctl;
1779 ifp->if_watchdog = awi_watchdog;
1780 ifp->if_mtu = ETHERMTU;
1781 /* XXX simplex may not be correct here.. */
1782 ifp->if_flags =
1783 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
1784
1785 sc->sc_mgtq.ifq_maxlen = 5;
1786
1787 if_attach(ifp);
1788 /* Defer ether_ifattach, bpfattach until we get enaddr. */
1789 ifp->if_output = awi_drop_output;
1790 #if __NetBSD_Version__ > 104010000
1791 ifp->if_input = awi_drop_input;
1792 #endif
1793
1794 #if NBPFILTER > 0
1795 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
1796 #endif
1797 return 0;
1798 }
1799
1800 void
1801 awi_zero (sc, from, to)
1802 struct awi_softc *sc;
1803 u_int32_t from, to;
1804 {
1805 u_int32_t i;
1806 for (i=from; i<to; i++)
1807 awi_write_1(sc, i, 0);
1808 }
1809
1810 void
1811 awi_init (sc)
1812 struct awi_softc *sc;
1813 {
1814 struct ifnet *ifp = sc->sc_ifp;
1815
1816 sc->sc_scan_duration = 100; /* scan for 100ms */
1817
1818 /*
1819 * Maybe we should randomize these....
1820 */
1821 sc->sc_scan_chanset = IEEEWL_FH_CHANSET_MIN;
1822 sc->sc_scan_pattern = IEEEWL_FH_PATTERN_MIN;
1823
1824 sc->sc_flags &= ~AWI_FL_CMD_INPROG;
1825
1826 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1827 ifp->if_timer = 0;
1828
1829 sc->sc_cmd_timer = 0;
1830 sc->sc_tx_timer = 0;
1831 sc->sc_mgt_timer = 0;
1832 sc->sc_scan_timer = 0;
1833
1834 sc->sc_nbindings = 0;
1835
1836 /*
1837 * this reset sequence doesn't seem to always do the trick.
1838 * hard-power-cycling the card may do it..
1839 */
1840
1841 /*
1842 * reset the hardware, just to be sure.
1843 * (bring out the big hammer here..)
1844 */
1845 /* XXX insert delay here? */
1846
1847 am79c930_gcr_setbits (&sc->sc_chip, AM79C930_GCR_CORESET);
1848 delay(10); /* XXX arbitrary value */
1849
1850 /*
1851 * clear control memory regions (firmware should do this but...)
1852 */
1853 awi_zero(sc, AWI_LAST_TXD, AWI_BUFFERS);
1854
1855 awi_drvstate(sc, AWI_DRV_RESET);
1856 sc->sc_selftest_tries = 0;
1857
1858 /*
1859 * release reset
1860 */
1861 am79c930_gcr_clearbits (&sc->sc_chip, AM79C930_GCR_CORESET);
1862 delay(10);
1863
1864 sc->sc_state = AWI_ST_SELFTEST;
1865 ifp->if_timer = 1;
1866
1867 }
1868
1869 void
1870 awi_cmd (sc, opcode)
1871 struct awi_softc *sc;
1872 u_int8_t opcode;
1873 {
1874 if (sc->sc_flags & AWI_FL_CMD_INPROG)
1875 panic("%s: command reentered", sc->sc_dev.dv_xname);
1876
1877 sc->sc_flags |= AWI_FL_CMD_INPROG;
1878
1879 /* issue test-interface command */
1880 awi_write_1(sc, AWI_CMD, opcode);
1881
1882 awi_write_1(sc, AWI_CMD_STATUS, 0);
1883
1884 sc->sc_cmd_timer = 2;
1885 awi_set_timer(sc);
1886 }
1887
1888 void
1889 awi_cmd_test_if (sc)
1890 struct awi_softc *sc;
1891 {
1892 awi_cmd (sc, AWI_CMD_NOP);
1893 }
1894
1895 void
1896 awi_cmd_get_mib (sc, var, offset, len)
1897 struct awi_softc *sc;
1898 u_int8_t var;
1899 u_int8_t offset;
1900 u_int8_t len;
1901 {
1902 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, var);
1903 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, len);
1904 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX, offset);
1905
1906 awi_cmd (sc, AWI_CMD_GET_MIB);
1907 }
1908
1909 void
1910 awi_cmd_txinit (sc)
1911 struct awi_softc *sc;
1912 {
1913 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_DATA, sc->sc_txbase);
1914 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_MGT, 0);
1915 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_BCAST, 0);
1916 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_PS, 0);
1917 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_CF, 0);
1918
1919 awi_cmd (sc, AWI_CMD_INIT_TX);
1920 }
1921
1922 int awi_max_chan = -1;
1923 int awi_min_chan = 1000;
1924 int awi_max_pattern = -1;
1925 int awi_min_pattern = 1000;
1926
1927
1928 /*
1929 * timeout-driven routine: complete device init once device has passed
1930 * selftest.
1931 */
1932
1933 void awi_init_1 (sc)
1934 struct awi_softc *sc;
1935 {
1936 struct ifnet *ifp = sc->sc_ifp;
1937
1938 awi_intrinit(sc);
1939
1940 sc->sc_state = AWI_ST_IFTEST;
1941
1942 if (ifp->if_flags & IFF_DEBUG) {
1943 awi_card_hexdump(sc, "init_1 CSB", AWI_CSB, 16);
1944 sc->sc_completion = awi_mibdump;
1945 } else
1946 sc->sc_completion = awi_init_2;
1947
1948 sc->sc_curmib = 0;
1949
1950 awi_cmd_test_if (sc);
1951 }
1952
1953 void awi_mibdump (sc, status)
1954 struct awi_softc *sc;
1955 u_int8_t status;
1956 {
1957 u_int8_t mibblk[256];
1958
1959 if (status != AWI_STAT_OK) {
1960 printf("%s: pre-mibread failed (card unhappy?)\n",
1961 sc->sc_dev.dv_xname);
1962 awi_reset(sc);
1963 return;
1964 }
1965
1966 if (sc->sc_curmib != 0) {
1967 awi_read_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA,
1968 mibblk, 72);
1969 awi_hexdump("mib", mibblk, 72);
1970 }
1971 if (sc->sc_curmib > AWI_MIB_LAST) {
1972 awi_init_2 (sc, status);
1973 } else {
1974 sc->sc_completion = awi_mibdump;
1975 printf("mib %d\n", sc->sc_curmib);
1976 awi_cmd_get_mib (sc, sc->sc_curmib, 0, 30);
1977 sc->sc_curmib++;
1978 /* skip over reserved MIB's.. */
1979 if ((sc->sc_curmib == 1) || (sc->sc_curmib == 6))
1980 sc->sc_curmib++;
1981 }
1982 }
1983
1984
1985 /*
1986 * called on completion of test-interface command in first-stage init.
1987 */
1988
1989 void awi_init_2 (sc, status)
1990 struct awi_softc *sc;
1991 u_int8_t status;
1992 {
1993 /* did it succeed? */
1994 if (status != AWI_STAT_OK) {
1995 printf("%s: nop failed (card unhappy?)\n",
1996 sc->sc_dev.dv_xname);
1997 awi_reset(sc);
1998 }
1999
2000 sc->sc_state = AWI_ST_MIB_GET;
2001 sc->sc_completion = awi_init_read_bufptrs_done;
2002
2003 awi_cmd_get_mib (sc, AWI_MIB_LOCAL, 0, AWI_MIB_LOCAL_SIZE);
2004 }
2005
2006 void awi_init_read_bufptrs_done (sc, status)
2007 struct awi_softc *sc;
2008 u_int8_t status;
2009 {
2010 if (status != AWI_STAT_OK) {
2011 printf("%s: get_mib failed (card unhappy?)\n",
2012 sc->sc_dev.dv_xname);
2013 awi_reset(sc);
2014 }
2015
2016 sc->sc_txbase = awi_read_4 (sc,
2017 AWI_CMD_PARAMS+AWI_CA_MIB_DATA+AWI_MIB_LOCAL_TXB_OFFSET);
2018 sc->sc_txlen = awi_read_4 (sc,
2019 AWI_CMD_PARAMS+AWI_CA_MIB_DATA+AWI_MIB_LOCAL_TXB_SIZE);
2020 sc->sc_rxbase = awi_read_4 (sc,
2021 AWI_CMD_PARAMS+AWI_CA_MIB_DATA+AWI_MIB_LOCAL_RXB_OFFSET);
2022 sc->sc_rxlen = awi_read_4 (sc,
2023 AWI_CMD_PARAMS+AWI_CA_MIB_DATA+AWI_MIB_LOCAL_RXB_SIZE);
2024 /*
2025 * XXX consider repartitioning buffer space to allow for
2026 * more efficient usage.
2027 * 6144: 3 txds, 1476 waste (current partition)
2028 * better splits:
2029 * 4864: 3 txds, 196 waste
2030 * 6400: 4 txds, 176 waste
2031 * 7936: 5 txds, 156 waste
2032 */
2033
2034 #if 0
2035 printf("tx offset: %x\n", sc->sc_txbase);
2036 printf("tx size: %x\n", sc->sc_txlen);
2037 printf("rx offset: %x\n", sc->sc_rxbase);
2038 printf("rx size: %x\n", sc->sc_rxlen);
2039 #endif
2040
2041 awi_cmd_get_myaddr (sc);
2042 }
2043
2044 void awi_cmd_get_myaddr (sc)
2045 struct awi_softc *sc;
2046 {
2047 sc->sc_completion = awi_cmd_get_myaddr_done;
2048
2049 awi_cmd_get_mib (sc, AWI_MIB_MAC_ADDR, 0, ETHER_ADDR_LEN);
2050 }
2051
2052 void awi_cmd_get_myaddr_done (sc, status)
2053 struct awi_softc *sc;
2054 u_int8_t status;
2055 {
2056 struct ifnet *ifp = sc->sc_ifp;
2057 u_int8_t newaddr[ETHER_ADDR_LEN];
2058
2059 if (status != AWI_STAT_OK) {
2060 printf("%s: nop failed (card unhappy?)\n",
2061 sc->sc_dev.dv_xname);
2062 awi_reset(sc);
2063 return;
2064 }
2065
2066 awi_read_bytes (sc, AWI_CMD_PARAMS + AWI_CA_MIB_DATA,
2067 newaddr, sizeof(newaddr));
2068
2069 if (memcmp (newaddr, sc->sc_my_addr, sizeof(newaddr)) != 0) {
2070 printf("%s: 802.11 address %s\n", sc->sc_dev.dv_xname,
2071 ether_sprintf(newaddr));
2072 memcpy(sc->sc_my_addr, newaddr, sizeof(newaddr));
2073 }
2074 ether_ifattach(ifp, sc->sc_my_addr);
2075 ifp->if_hdrlen = 32;
2076
2077 sc->sc_state = AWI_ST_MIB_SET;
2078 awi_cmd_set_notap(sc);
2079 }
2080
2081 void awi_cmd_set_notap (sc)
2082 struct awi_softc *sc;
2083 {
2084 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, AWI_MIB_LOCAL);
2085 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, 1);
2086 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX,
2087 AWI_MIB_LOCAL_ACTING_AS_AP);
2088
2089 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, 0);
2090 sc->sc_completion = awi_cmd_set_notap_done;
2091 awi_cmd (sc, AWI_CMD_SET_MIB);
2092 }
2093
2094 void awi_cmd_set_notap_done (sc, status)
2095 struct awi_softc *sc;
2096 u_int8_t status;
2097 {
2098 if (status != AWI_STAT_OK) {
2099 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2100 printf("%s: set_infra failed (card unhappy?); erroffset %d\n",
2101 sc->sc_dev.dv_xname,
2102 erroffset);
2103 awi_reset(sc);
2104 return;
2105 }
2106 awi_cmd_set_infra (sc);
2107 }
2108
2109 void awi_cmd_set_infra (sc)
2110 struct awi_softc *sc;
2111 {
2112
2113 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, AWI_MIB_LOCAL);
2114 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, 1);
2115 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX,
2116 AWI_MIB_LOCAL_INFRA_MODE);
2117
2118 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, 1);
2119 sc->sc_completion = awi_cmd_set_infra_done;
2120 awi_cmd (sc, AWI_CMD_SET_MIB);
2121 }
2122
2123 void awi_cmd_set_infra_done (sc, status)
2124 struct awi_softc *sc;
2125 u_int8_t status;
2126 {
2127 #if 0
2128 printf("set_infra done\n");
2129 #endif
2130 if (status != AWI_STAT_OK) {
2131 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2132 printf("%s: set_infra failed (card unhappy?); erroffset %d\n",
2133 sc->sc_dev.dv_xname,
2134 erroffset);
2135 awi_reset(sc);
2136 return;
2137 }
2138 #if 0
2139 printf("%s: set_infra done\n", sc->sc_dev.dv_xname);
2140 #endif
2141 awi_cmd_set_allmulti (sc);
2142 }
2143
2144 void awi_cmd_set_allmulti (sc)
2145 struct awi_softc *sc;
2146 {
2147 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, AWI_MIB_LOCAL);
2148 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, 1);
2149 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX,
2150 AWI_MIB_LOCAL_FILTMULTI);
2151 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, 0);
2152 sc->sc_completion = awi_cmd_set_allmulti_done;
2153 awi_cmd (sc, AWI_CMD_SET_MIB);
2154 }
2155
2156 void awi_cmd_set_allmulti_done (sc, status)
2157 struct awi_softc *sc;
2158 u_int8_t status;
2159 {
2160 if (status != AWI_STAT_OK) {
2161 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2162 printf("%s: set_almulti_done failed (card unhappy?); erroffset %d\n",
2163 sc->sc_dev.dv_xname,
2164 erroffset);
2165 awi_reset(sc);
2166 return;
2167 }
2168 awi_cmd_set_promisc (sc);
2169 }
2170
2171 void awi_cmd_set_promisc (sc)
2172 struct awi_softc *sc;
2173 {
2174 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, AWI_MIB_MAC);
2175 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, 1);
2176 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX,
2177 AWI_MIB_MAC_PROMISC);
2178 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, 0); /* XXX */
2179 sc->sc_completion = awi_cmd_set_promisc_done;
2180 awi_cmd (sc, AWI_CMD_SET_MIB);
2181 }
2182
2183 void awi_cmd_set_promisc_done (sc, status)
2184 struct awi_softc *sc;
2185 u_int8_t status;
2186 {
2187 #if 0
2188 printf("set promisc_done\n");
2189 #endif
2190
2191 if (status != AWI_STAT_OK) {
2192 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2193 printf("%s: set_promisc_done failed (card unhappy?); erroffset %d\n",
2194 sc->sc_dev.dv_xname,
2195 erroffset);
2196 awi_reset(sc);
2197 return;
2198 }
2199 #if 0
2200 printf("%s: set_promisc done\n", sc->sc_dev.dv_xname);
2201 #endif
2202
2203 awi_init_txdescr(sc);
2204
2205 sc->sc_state = AWI_ST_TXINIT;
2206 sc->sc_completion = awi_init_4;
2207 awi_cmd_txinit(sc);
2208 }
2209
2210 void
2211 awi_init_4 (sc, status)
2212 struct awi_softc *sc;
2213 u_int8_t status;
2214 {
2215 #if 0
2216 printf("%s: awi_init_4, st %x\n", sc->sc_dev.dv_xname, status);
2217 awi_card_hexdump(sc, "init_4 CSB", AWI_CSB, 16);
2218 #endif
2219
2220 if (status != AWI_STAT_OK) {
2221 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2222 printf("%s: init_tx failed (card unhappy?); erroffset %d\n",
2223 sc->sc_dev.dv_xname,
2224 erroffset);
2225 awi_reset(sc);
2226 return;
2227 }
2228
2229 sc->sc_state = AWI_ST_RXINIT;
2230 sc->sc_completion = awi_init_5;
2231
2232 awi_cmd (sc, AWI_CMD_INIT_RX);
2233 }
2234
2235 void awi_init_5 (sc, status)
2236 struct awi_softc *sc;
2237 u_int8_t status;
2238 {
2239 #if 0
2240 struct ifnet *ifp = sc->sc_ifp;
2241 #endif
2242
2243 #if 0
2244 printf("%s: awi_init_5, st %x\n", sc->sc_dev.dv_xname, status);
2245 awi_card_hexdump(sc, "init_5 CSB", AWI_CSB, 16);
2246 #endif
2247
2248 if (status != AWI_STAT_OK) {
2249 printf("%s: init_rx failed (card unhappy?)\n",
2250 sc->sc_dev.dv_xname);
2251 awi_reset(sc);
2252 return;
2253 }
2254
2255 sc->sc_rx_data_desc = awi_read_4(sc, AWI_CMD_PARAMS+AWI_CA_IRX_DATA_DESC);
2256 sc->sc_rx_mgt_desc = awi_read_4(sc, AWI_CMD_PARAMS+AWI_CA_IRX_PS_DESC);
2257
2258 #if 0
2259 printf("%s: data desc %x, mgt desc %x\n", sc->sc_dev.dv_xname,
2260 sc->sc_rx_data_desc, sc->sc_rx_mgt_desc);
2261 #endif
2262 awi_restart_scan(sc);
2263 }
2264
2265 void awi_restart_scan (sc)
2266 struct awi_softc *sc;
2267 {
2268 sc->sc_scan_timer = 1;
2269 sc->sc_mgt_timer = 0;
2270 awi_set_timer(sc);
2271
2272 sc->sc_nbindings = 0;
2273 sc->sc_state = AWI_ST_SCAN;
2274 awi_drvstate (sc, AWI_DRV_INFSC);
2275 awi_cmd_scan (sc);
2276 }
2277
2278 void
2279 awi_cmd_scan (sc)
2280 struct awi_softc *sc;
2281 {
2282
2283 awi_write_2 (sc, AWI_CMD_PARAMS+AWI_CA_SCAN_DURATION,
2284 sc->sc_scan_duration);
2285 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SET,
2286 sc->sc_scan_chanset);
2287 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SCAN_PATTERN,
2288 sc->sc_scan_pattern);
2289 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SCAN_IDX, 1);
2290 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SUSP, 0);
2291
2292 sc->sc_completion = awi_cmd_scan_done;
2293 awi_cmd (sc, AWI_CMD_SCAN);
2294 }
2295
2296 void
2297 awi_cmd_scan_done (sc, status)
2298 struct awi_softc *sc;
2299 u_int8_t status;
2300 {
2301 #if 0
2302 int erroffset;
2303 #endif
2304 if (status == AWI_STAT_OK) {
2305 if (sc->sc_scan_chanset > awi_max_chan)
2306 awi_max_chan = sc->sc_scan_chanset;
2307 if (sc->sc_scan_chanset < awi_min_chan)
2308 awi_min_chan = sc->sc_scan_chanset;
2309 if (sc->sc_scan_pattern > awi_max_pattern)
2310 awi_max_pattern = sc->sc_scan_pattern;
2311 if (sc->sc_scan_pattern < awi_min_pattern)
2312 awi_min_pattern = sc->sc_scan_pattern;
2313
2314 return;
2315 }
2316 #if 0
2317 erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2318 printf("%s: scan failed; erroffset %d\n", sc->sc_dev.dv_xname,
2319 erroffset);
2320 #endif
2321 /* wait for response or scan timeout.. */
2322 }
2323
2324 void
2325 awi_scan_next (sc)
2326 struct awi_softc *sc;
2327 {
2328 sc->sc_scan_pattern++;
2329 if (sc->sc_scan_pattern > IEEEWL_FH_PATTERN_MAX) {
2330 sc->sc_scan_pattern = IEEEWL_FH_PATTERN_MIN;
2331
2332 sc->sc_scan_chanset++;
2333 if (sc->sc_scan_chanset > IEEEWL_FH_CHANSET_MAX)
2334 sc->sc_scan_chanset = IEEEWL_FH_CHANSET_MIN;
2335 }
2336 #if 0
2337 printf("scan: pattern %x chanset %x\n", sc->sc_scan_pattern,
2338 sc->sc_scan_chanset);
2339 #endif
2340
2341 awi_cmd_scan(sc);
2342 }
2343
2344 void
2345 awi_try_sync (sc)
2346 struct awi_softc *sc;
2347 {
2348 int max_rssi = 0, best = 0;
2349 int i;
2350 struct awi_bss_binding *bp = NULL;
2351
2352 /* pick one with best rssi */
2353 for (i=0; i<sc->sc_nbindings; i++) {
2354 bp = &sc->sc_bindings[i];
2355
2356 if (bp->rssi > max_rssi) {
2357 max_rssi = bp->rssi;
2358 best = i;
2359 }
2360 }
2361
2362 #if 0
2363 printf("best: %d\n", best);
2364 #endif
2365 if (bp == NULL) {
2366 return;
2367 }
2368 sc->sc_scan_timer = 2;
2369
2370 bp = &sc->sc_bindings[best];
2371 memcpy(&sc->sc_active_bss, bp, sizeof(*bp));
2372 sc->sc_new_bss = 1;
2373
2374 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_SET, bp->chanset);
2375 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_PATTERN, bp->pattern);
2376 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_IDX, bp->index);
2377 awi_write_1 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_STARTBSS, 0);
2378
2379 awi_write_2 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_DWELL, bp->dwell_time);
2380 awi_write_2 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_MBZ, 0);
2381
2382 awi_write_bytes (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_TIMESTAMP,
2383 bp->bss_timestamp, 8);
2384 awi_write_4 (sc, AWI_CMD_PARAMS+AWI_CA_SYNC_REFTIME, bp->rxtime);
2385
2386 sc->sc_completion = awi_cmd_sync_done;
2387
2388 awi_cmd (sc, AWI_CMD_SYNC);
2389
2390 }
2391
2392 void
2393 awi_cmd_sync_done (sc, status)
2394 struct awi_softc *sc;
2395 u_int8_t status;
2396 {
2397 if (status != AWI_STAT_OK) {
2398 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2399 printf("%s: sync_done failed (card unhappy?); erroffset %d\n",
2400 sc->sc_dev.dv_xname,
2401 erroffset);
2402 awi_reset(sc);
2403 return;
2404 }
2405
2406 /*
2407 * at this point, the card should be synchronized with the AP
2408 * we heard from. tell the card what BSS and ESS it's running in..
2409 */
2410
2411 awi_drvstate (sc, AWI_DRV_INFSY);
2412 #if 0
2413 printf("%s: sync done, setting bss/iss parameters\n",
2414 sc->sc_dev.dv_xname);
2415 awi_hexdump ("bss", sc->sc_active_bss.bss_id, ETHER_ADDR_LEN);
2416 printf("ssid: %s\n", sc->sc_active_bss.ssid);
2417 #endif
2418 awi_cmd_set_ss (sc);
2419 }
2420
2421
2422 void awi_cmd_set_ss (sc)
2423 struct awi_softc *sc;
2424 {
2425 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, AWI_MIB_MAC_MGT);
2426 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE,
2427 ETHER_ADDR_LEN + AWI_MIB_MGT_ESS_SIZE);
2428 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX,
2429 AWI_MIB_MGT_BSS_ID);
2430
2431 awi_write_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA,
2432 sc->sc_active_bss.bss_id, ETHER_ADDR_LEN);
2433 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA+ETHER_ADDR_LEN,
2434 0); /* XXX */
2435 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA+ETHER_ADDR_LEN+1,
2436 sc->sc_active_bss.sslen);
2437 awi_write_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA+8,
2438 sc->sc_active_bss.ssid, AWI_MIB_MGT_ESS_SIZE-2);
2439
2440 sc->sc_completion = awi_cmd_set_ss_done;
2441 awi_cmd (sc, AWI_CMD_SET_MIB);
2442 }
2443
2444 void awi_cmd_set_ss_done (sc, status)
2445 struct awi_softc *sc;
2446 u_int8_t status;
2447 {
2448 if (status != AWI_STAT_OK) {
2449 int erroffset = awi_read_1 (sc, AWI_ERROR_OFFSET);
2450 printf("%s: set_ss_done failed (card unhappy?); erroffset %d\n",
2451 sc->sc_dev.dv_xname,
2452 erroffset);
2453 awi_reset(sc);
2454 return;
2455 }
2456 #if 0
2457 printf("%s: set_ss done\n", sc->sc_dev.dv_xname);
2458 #endif
2459
2460 awi_running (sc);
2461
2462 /*
2463 * now, we *should* be getting broadcast frames..
2464 */
2465 sc->sc_state = AWI_ST_SYNCED;
2466 awi_send_authreq (sc);
2467
2468 }
2469
2470 void awi_running (sc)
2471 struct awi_softc *sc;
2472
2473 {
2474 struct ifnet *ifp = sc->sc_ifp;
2475
2476 /*
2477 * Who knows what it is to be running?
2478 * Only he who is running knows..
2479 */
2480 ifp->if_flags |= IFF_RUNNING;
2481 awi_start(ifp);
2482 }
2483
2484
2485 void awi_reset (sc)
2486 struct awi_softc *sc;
2487 {
2488 printf("%s: reset\n", sc->sc_dev.dv_xname);
2489
2490 }
2491