Merge from vendor branch BINUTILS:
[dragonfly.git] / sys / dev / netif / an / if_an.c
1 /*
2  * Copyright (c) 1997, 1998, 1999
3  *      Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Bill Paul.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * $FreeBSD: src/sys/dev/an/if_an.c,v 1.2.2.13 2003/02/11 03:32:48 ambrisko Exp $
33  * $DragonFly: src/sys/dev/netif/an/if_an.c,v 1.9 2004/01/06 01:40:46 dillon Exp $
34  *
35  * $FreeBSD: src/sys/dev/an/if_an.c,v 1.2.2.13 2003/02/11 03:32:48 ambrisko Exp $
36  */
37
38 /*
39  * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD.
40  *
41  * Written by Bill Paul <wpaul@ctr.columbia.edu>
42  * Electrical Engineering Department
43  * Columbia University, New York City
44  */
45
46 /*
47  * The Aironet 4500/4800 series cards come in PCMCIA, ISA and PCI form.
48  * This driver supports all three device types (PCI devices are supported
49  * through an extra PCI shim: /sys/dev/an/if_an_pci.c). ISA devices can be
50  * supported either using hard-coded IO port/IRQ settings or via Plug
51  * and Play. The 4500 series devices support 1Mbps and 2Mbps data rates.
52  * The 4800 devices support 1, 2, 5.5 and 11Mbps rates.
53  *
54  * Like the WaveLAN/IEEE cards, the Aironet NICs are all essentially
55  * PCMCIA devices. The ISA and PCI cards are a combination of a PCMCIA
56  * device and a PCMCIA to ISA or PCMCIA to PCI adapter card. There are
57  * a couple of important differences though:
58  *
59  * - Lucent ISA card looks to the host like a PCMCIA controller with
60  *   a PCMCIA WaveLAN card inserted. This means that even desktop
61  *   machines need to be configured with PCMCIA support in order to
62  *   use WaveLAN/IEEE ISA cards. The Aironet cards on the other hand
63  *   actually look like normal ISA and PCI devices to the host, so
64  *   no PCMCIA controller support is needed
65  *
66  * The latter point results in a small gotcha. The Aironet PCMCIA
67  * cards can be configured for one of two operating modes depending
68  * on how the Vpp1 and Vpp2 programming voltages are set when the
69  * card is activated. In order to put the card in proper PCMCIA
70  * operation (where the CIS table is visible and the interface is
71  * programmed for PCMCIA operation), both Vpp1 and Vpp2 have to be
72  * set to 5 volts. FreeBSD by default doesn't set the Vpp voltages,
73  * which leaves the card in ISA/PCI mode, which prevents it from
74  * being activated as an PCMCIA device.
75  *
76  * Note that some PCMCIA controller software packages for Windows NT
77  * fail to set the voltages as well.
78  *
79  * The Aironet devices can operate in both station mode and access point
80  * mode. Typically, when programmed for station mode, the card can be set
81  * to automatically perform encapsulation/decapsulation of Ethernet II
82  * and 802.3 frames within 802.11 frames so that the host doesn't have
83  * to do it itself. This driver doesn't program the card that way: the
84  * driver handles all of the encapsulation/decapsulation itself.
85  */
86
87 #include "opt_inet.h"
88
89 #ifdef INET
90 #define ANCACHE                 /* enable signal strength cache */
91 #endif
92
93 #include <sys/param.h>
94 #include <sys/systm.h>
95 #include <sys/sockio.h>
96 #include <sys/mbuf.h>
97 #include <sys/proc.h>
98 #include <sys/kernel.h>
99 #include <sys/proc.h>
100 #include <sys/ucred.h>
101 #include <sys/socket.h>
102 #ifdef ANCACHE
103 #include <sys/syslog.h>
104 #endif
105 #include <sys/sysctl.h>
106 #include <machine/clock.h>      /* for DELAY */  
107
108 #include <sys/module.h>
109 #include <sys/sysctl.h>
110 #include <sys/bus.h>
111 #include <machine/bus.h>
112 #include <sys/rman.h>
113 #include <machine/resource.h>
114 #include <sys/malloc.h>
115
116 #include <net/if.h>
117 #include <net/if_arp.h>
118 #include <net/ethernet.h>
119 #include <net/if_dl.h>
120 #include <net/if_types.h>
121 #include <net/if_ieee80211.h>
122 #include <net/if_media.h>
123
124 #ifdef INET
125 #include <netinet/in.h>
126 #include <netinet/in_systm.h>
127 #include <netinet/in_var.h>
128 #include <netinet/ip.h>
129 #endif
130
131 #include <net/bpf.h>
132
133 #include <machine/md_var.h>
134
135 #include "if_aironet_ieee.h"
136 #include "if_anreg.h"
137
138 /* These are global because we need them in sys/pci/if_an_p.c. */
139 static void an_reset            (struct an_softc *);
140 static int                      an_init_mpi350_desc     (struct an_softc *);
141 static int an_ioctl             (struct ifnet *, u_long, caddr_t);
142 static void an_init             (void *);
143 static int an_init_tx_ring      (struct an_softc *);
144 static void an_start            (struct ifnet *);
145 static void an_watchdog         (struct ifnet *);
146 static void an_rxeof            (struct an_softc *);
147 static void an_txeof            (struct an_softc *, int);
148
149 static void an_promisc          (struct an_softc *, int);
150 static int an_cmd               (struct an_softc *, int, int);
151 static int an_cmd_struct        (struct an_softc *, struct an_command *,
152                                         struct an_reply *);
153 static int an_read_record       (struct an_softc *, struct an_ltv_gen *);
154 static int an_write_record      (struct an_softc *, struct an_ltv_gen *);
155 static int an_read_data         (struct an_softc *, int,
156                                         int, caddr_t, int);
157 static int an_write_data        (struct an_softc *, int,
158                                         int, caddr_t, int);
159 static int an_seek              (struct an_softc *, int, int, int);
160 static int an_alloc_nicmem      (struct an_softc *, int, int *);
161 static int an_dma_malloc        (struct an_softc *, bus_size_t,
162                                         struct an_dma_alloc *, int);
163 static void an_dma_free         (struct an_softc *, 
164                                         struct an_dma_alloc *);
165 static void an_dma_malloc_cb    (void *, bus_dma_segment_t *, int, int);
166 static void an_stats_update     (void *);
167 static void an_setdef           (struct an_softc *, struct an_req *);
168 #ifdef ANCACHE
169 static void an_cache_store      (struct an_softc *, struct ether_header *,
170                                         struct mbuf *, u_int8_t, u_int8_t);
171 #endif
172
173 /* function definitions for use with the Cisco's Linux configuration
174    utilities
175 */
176
177 static int readrids             (struct ifnet*, struct aironet_ioctl*);
178 static int writerids            (struct ifnet*, struct aironet_ioctl*);
179 static int flashcard            (struct ifnet*, struct aironet_ioctl*);
180
181 static int cmdreset             (struct ifnet *);
182 static int setflashmode         (struct ifnet *);
183 static int flashgchar           (struct ifnet *,int,int);
184 static int flashpchar           (struct ifnet *,int,int);
185 static int flashputbuf          (struct ifnet *);
186 static int flashrestart         (struct ifnet *);
187 static int WaitBusy             (struct ifnet *, int);
188 static int unstickbusy          (struct ifnet *);
189
190 static void an_dump_record      (struct an_softc *,struct an_ltv_gen *,
191                                     char *);
192
193 static int an_media_change      (struct ifnet *);
194 static void an_media_status     (struct ifnet *, struct ifmediareq *);
195
196 static int      an_dump = 0;
197 static int      an_cache_mode = 0;
198
199 #define DBM 0
200 #define PERCENT 1
201 #define RAW 2
202
203 static char an_conf[256];
204 static char an_conf_cache[256];
205
206 DECLARE_DUMMY_MODULE(if_an);
207
208 /* sysctl vars */
209
210 SYSCTL_NODE(_hw, OID_AUTO, an, CTLFLAG_RD, 0, "Wireless driver parameters");
211
212 static int
213 sysctl_an_dump(SYSCTL_HANDLER_ARGS)
214 {
215         int     error, r, last;
216         char    *s = an_conf;
217
218         last = an_dump;
219
220         switch (an_dump) {
221         case 0:
222                 strcpy(an_conf, "off");
223                 break;
224         case 1:
225                 strcpy(an_conf, "type");
226                 break;
227         case 2:
228                 strcpy(an_conf, "dump");
229                 break;
230         default:
231                 snprintf(an_conf, 5, "%x", an_dump);
232                 break;
233         }
234
235         error = sysctl_handle_string(oidp, an_conf, sizeof(an_conf), req);
236
237         if (strncmp(an_conf,"off", 3) == 0) {
238                 an_dump = 0;
239         }
240         if (strncmp(an_conf,"dump", 4) == 0) {
241                 an_dump = 1;
242         }
243         if (strncmp(an_conf,"type", 4) == 0) {
244                 an_dump = 2;
245         }
246         if (*s == 'f') {
247                 r = 0;
248                 for (;;s++) {
249                         if ((*s >= '0') && (*s <= '9')) {
250                                 r = r * 16 + (*s - '0');
251                         } else if ((*s >= 'a') && (*s <= 'f')) {
252                                 r = r * 16 + (*s - 'a' + 10);
253                         } else {
254                                 break;
255                         }
256                 }
257                 an_dump = r;
258         }
259         if (an_dump != last)
260                 printf("Sysctl changed for Aironet driver\n");
261
262         return error;
263 }
264
265 SYSCTL_PROC(_hw_an, OID_AUTO, an_dump, CTLTYPE_STRING | CTLFLAG_RW,
266             0, sizeof(an_conf), sysctl_an_dump, "A", "");
267
268 static int
269 sysctl_an_cache_mode(SYSCTL_HANDLER_ARGS)
270 {
271         int     error, last;
272
273         last = an_cache_mode;
274
275         switch (an_cache_mode) {
276         case 1:
277                 strcpy(an_conf_cache, "per");
278                 break;
279         case 2:
280                 strcpy(an_conf_cache, "raw");
281                 break;
282         default:
283                 strcpy(an_conf_cache, "dbm");
284                 break;
285         }
286
287         error = sysctl_handle_string(oidp, an_conf_cache, 
288                         sizeof(an_conf_cache), req);
289
290         if (strncmp(an_conf_cache,"dbm", 3) == 0) {
291                 an_cache_mode = 0;
292         }
293         if (strncmp(an_conf_cache,"per", 3) == 0) {
294                 an_cache_mode = 1;
295         }
296         if (strncmp(an_conf_cache,"raw", 3) == 0) {
297                 an_cache_mode = 2;
298         }
299
300         return error;
301 }
302
303 SYSCTL_PROC(_hw_an, OID_AUTO, an_cache_mode, CTLTYPE_STRING | CTLFLAG_RW,
304             0, sizeof(an_conf_cache), sysctl_an_cache_mode, "A", "");
305
306 /*
307  * We probe for an Aironet 4500/4800 card by attempting to
308  * read the default SSID list. On reset, the first entry in
309  * the SSID list will contain the name "tsunami." If we don't
310  * find this, then there's no card present.
311  */
312 int
313 an_probe(dev)
314         device_t                dev;
315 {
316         struct an_softc *sc = device_get_softc(dev);
317         struct an_ltv_ssidlist  ssid;
318         int     error;
319
320         bzero((char *)&ssid, sizeof(ssid));
321
322         error = an_alloc_port(dev, 0, AN_IOSIZ);
323         if (error != 0)
324                 return (0);
325
326         /* can't do autoprobing */
327         if (rman_get_start(sc->port_res) == -1)
328                 return(0);
329
330         /*
331          * We need to fake up a softc structure long enough
332          * to be able to issue commands and call some of the
333          * other routines.
334          */
335         sc->an_bhandle = rman_get_bushandle(sc->port_res);
336         sc->an_btag = rman_get_bustag(sc->port_res);
337         sc->an_unit = device_get_unit(dev);
338
339         ssid.an_len = sizeof(ssid);
340         ssid.an_type = AN_RID_SSIDLIST;
341
342         /* Make sure interrupts are disabled. */
343         CSR_WRITE_2(sc, AN_INT_EN(sc->mpi350), 0);
344         CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), 0xFFFF);
345
346         an_reset(sc);
347         /* No need for an_init_mpi350_desc since it will be done in attach */
348
349         if (an_cmd(sc, AN_CMD_READCFG, 0))
350                 return(0);
351
352         if (an_read_record(sc, (struct an_ltv_gen *)&ssid))
353                 return(0);
354
355         /* See if the ssid matches what we expect ... but doesn't have to */
356         if (strcmp(ssid.an_ssid1, AN_DEF_SSID))
357                 return(0);
358
359         return(AN_IOSIZ);
360 }
361
362 /*
363  * Allocate a port resource with the given resource id.
364  */
365 int
366 an_alloc_port(dev, rid, size)
367         device_t dev;
368         int rid;
369         int size;
370 {
371         struct an_softc *sc = device_get_softc(dev);
372         struct resource *res;
373
374         res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
375                                  0ul, ~0ul, size, RF_ACTIVE);
376         if (res) {
377                 sc->port_rid = rid;
378                 sc->port_res = res;
379                 return (0);
380         } else {
381                 return (ENOENT);
382         }
383 }
384
385 /*
386  * Allocate a memory resource with the given resource id.
387  */
388 int an_alloc_memory(device_t dev, int rid, int size)
389 {
390         struct an_softc *sc = device_get_softc(dev);
391         struct resource *res;
392
393         res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
394                                  0ul, ~0ul, size, RF_ACTIVE);
395         if (res) {
396                 sc->mem_rid = rid;
397                 sc->mem_res = res;
398                 sc->mem_used = size;
399                 return (0);
400         } else {
401                 return (ENOENT);
402         }
403 }
404
405 /*
406  * Allocate a auxilary memory resource with the given resource id.
407  */
408 int an_alloc_aux_memory(device_t dev, int rid, int size)
409 {
410         struct an_softc *sc = device_get_softc(dev);
411         struct resource *res;
412
413         res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
414                                  0ul, ~0ul, size, RF_ACTIVE);
415         if (res) {
416                 sc->mem_aux_rid = rid;
417                 sc->mem_aux_res = res;
418                 sc->mem_aux_used = size;
419                 return (0);
420         } else {
421                 return (ENOENT);
422         }
423 }
424
425 /*
426  * Allocate an irq resource with the given resource id.
427  */
428 int
429 an_alloc_irq(dev, rid, flags)
430         device_t dev;
431         int rid;
432         int flags;
433 {
434         struct an_softc *sc = device_get_softc(dev);
435         struct resource *res;
436
437         res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
438                                  0ul, ~0ul, 1, (RF_ACTIVE | flags));
439         if (res) {
440                 sc->irq_rid = rid;
441                 sc->irq_res = res;
442                 return (0);
443         } else {
444                 return (ENOENT);
445         }
446 }
447
448 static void
449 an_dma_malloc_cb(arg, segs, nseg, error)
450         void *arg;
451         bus_dma_segment_t *segs;
452         int nseg;
453         int error;
454 {
455         bus_addr_t *paddr = (bus_addr_t*) arg;
456         *paddr = segs->ds_addr;
457 }
458
459 /*
460  * Alloc DMA memory and set the pointer to it
461  */
462 static int
463 an_dma_malloc(sc, size, dma, mapflags)
464         struct an_softc *sc;
465         bus_size_t size;
466         struct an_dma_alloc *dma;
467         int mapflags;
468 {
469         int r;
470
471         r = bus_dmamap_create(sc->an_dtag, BUS_DMA_NOWAIT, &dma->an_dma_map);
472         if (r != 0)
473                 goto fail_0;
474
475         r = bus_dmamem_alloc(sc->an_dtag, (void**) &dma->an_dma_vaddr,
476                              BUS_DMA_NOWAIT, &dma->an_dma_map);
477         if (r != 0)
478                 goto fail_1;
479
480         r = bus_dmamap_load(sc->an_dtag, dma->an_dma_map, dma->an_dma_vaddr,
481                             size,
482                             an_dma_malloc_cb,
483                             &dma->an_dma_paddr,
484                             mapflags | BUS_DMA_NOWAIT);
485         if (r != 0)
486                 goto fail_2;
487
488         dma->an_dma_size = size;
489         return (0);
490
491 fail_2:
492         bus_dmamap_unload(sc->an_dtag, dma->an_dma_map);
493 fail_1:
494         bus_dmamem_free(sc->an_dtag, dma->an_dma_vaddr, dma->an_dma_map);
495 fail_0:
496         bus_dmamap_destroy(sc->an_dtag, dma->an_dma_map);
497         dma->an_dma_map = NULL;
498         return (r);
499 }
500
501 static void
502 an_dma_free(sc, dma)
503         struct an_softc *sc;
504         struct an_dma_alloc *dma;
505 {
506         bus_dmamap_unload(sc->an_dtag, dma->an_dma_map);
507         bus_dmamem_free(sc->an_dtag, dma->an_dma_vaddr, dma->an_dma_map);
508         bus_dmamap_destroy(sc->an_dtag, dma->an_dma_map);
509 }
510
511 /*
512  * Release all resources
513  */
514 void
515 an_release_resources(dev)
516         device_t dev;
517 {
518         struct an_softc *sc = device_get_softc(dev);
519         int i;
520
521         if (sc->port_res) {
522                 bus_release_resource(dev, SYS_RES_IOPORT,
523                                      sc->port_rid, sc->port_res);
524                 sc->port_res = 0;
525         }
526         if (sc->mem_res) {
527                 bus_release_resource(dev, SYS_RES_MEMORY,
528                                      sc->mem_rid, sc->mem_res);
529                 sc->mem_res = 0;
530         }
531         if (sc->mem_aux_res) {
532                 bus_release_resource(dev, SYS_RES_MEMORY,
533                                      sc->mem_aux_rid, sc->mem_aux_res);
534                 sc->mem_aux_res = 0;
535         }
536         if (sc->irq_res) {
537                 bus_release_resource(dev, SYS_RES_IRQ,
538                                      sc->irq_rid, sc->irq_res);
539                 sc->irq_res = 0;
540         }
541         if (sc->an_rid_buffer.an_dma_paddr) {
542                 an_dma_free(sc, &sc->an_rid_buffer);
543         }
544         for (i = 0; i < AN_MAX_RX_DESC; i++)
545                 if (sc->an_rx_buffer[i].an_dma_paddr) {
546                         an_dma_free(sc, &sc->an_rx_buffer[i]);
547                 }
548         for (i = 0; i < AN_MAX_TX_DESC; i++)
549                 if (sc->an_tx_buffer[i].an_dma_paddr) {
550                         an_dma_free(sc, &sc->an_tx_buffer[i]);
551                 }
552         if (sc->an_dtag) {
553                 bus_dma_tag_destroy(sc->an_dtag);
554         }
555
556 }
557
558 int
559 an_init_mpi350_desc(sc)
560         struct an_softc *sc;
561 {
562         struct an_command       cmd_struct;
563         struct an_reply         reply;
564         struct an_card_rid_desc an_rid_desc;
565         struct an_card_rx_desc  an_rx_desc;
566         struct an_card_tx_desc  an_tx_desc;
567         int                     i, desc;
568
569         if(!sc->an_rid_buffer.an_dma_paddr)
570                 an_dma_malloc(sc, AN_RID_BUFFER_SIZE,
571                                  &sc->an_rid_buffer, 0);
572         for (i = 0; i < AN_MAX_RX_DESC; i++)
573                 if(!sc->an_rx_buffer[i].an_dma_paddr)
574                         an_dma_malloc(sc, AN_RX_BUFFER_SIZE,
575                                       &sc->an_rx_buffer[i], 0);
576         for (i = 0; i < AN_MAX_TX_DESC; i++)
577                 if(!sc->an_tx_buffer[i].an_dma_paddr)
578                         an_dma_malloc(sc, AN_TX_BUFFER_SIZE,
579                                       &sc->an_tx_buffer[i], 0);
580
581         /*
582          * Allocate RX descriptor
583          */
584         bzero(&reply,sizeof(reply));
585         cmd_struct.an_cmd   = AN_CMD_ALLOC_DESC;
586         cmd_struct.an_parm0 = AN_DESCRIPTOR_RX;
587         cmd_struct.an_parm1 = AN_RX_DESC_OFFSET;
588         cmd_struct.an_parm2 = AN_MAX_RX_DESC;
589         if (an_cmd_struct(sc, &cmd_struct, &reply)) {
590                 printf("an%d: failed to allocate RX descriptor\n", 
591                        sc->an_unit);
592                 return(EIO);
593         }
594
595         for (desc = 0; desc < AN_MAX_RX_DESC; desc++) {
596                 bzero(&an_rx_desc, sizeof(an_rx_desc));
597                 an_rx_desc.an_valid = 1;
598                 an_rx_desc.an_len = AN_RX_BUFFER_SIZE;
599                 an_rx_desc.an_done = 0;
600                 an_rx_desc.an_phys = sc->an_rx_buffer[desc].an_dma_paddr;
601
602                 for (i = 0; i < sizeof(an_rx_desc) / 4; i++)
603                         CSR_MEM_AUX_WRITE_4(sc, AN_RX_DESC_OFFSET 
604                                             + (desc * sizeof(an_rx_desc))
605                                             + (i * 4),
606                                             ((u_int32_t*)&an_rx_desc)[i]);
607         }
608
609         /*
610          * Allocate TX descriptor
611          */
612
613         bzero(&reply,sizeof(reply));
614         cmd_struct.an_cmd   = AN_CMD_ALLOC_DESC;
615         cmd_struct.an_parm0 = AN_DESCRIPTOR_TX;
616         cmd_struct.an_parm1 = AN_TX_DESC_OFFSET;
617         cmd_struct.an_parm2 = AN_MAX_TX_DESC;
618         if (an_cmd_struct(sc, &cmd_struct, &reply)) {
619                 printf("an%d: failed to allocate TX descriptor\n", 
620                        sc->an_unit);
621                 return(EIO);
622         }
623
624         for (desc = 0; desc < AN_MAX_TX_DESC; desc++) {
625                 bzero(&an_tx_desc, sizeof(an_tx_desc));
626                 an_tx_desc.an_offset = 0;
627                 an_tx_desc.an_eoc = 0;
628                 an_tx_desc.an_valid = 0;
629                 an_tx_desc.an_len = 0;
630                 an_tx_desc.an_phys = sc->an_tx_buffer[desc].an_dma_paddr;
631
632                 for (i = 0; i < sizeof(an_tx_desc) / 4; i++)
633                         CSR_MEM_AUX_WRITE_4(sc, AN_TX_DESC_OFFSET
634                                             + (desc * sizeof(an_tx_desc))
635                                             + (i * 4),
636                                             ((u_int32_t*)&an_tx_desc)[i]);
637         }
638
639         /*
640          * Allocate RID descriptor
641          */
642
643         bzero(&reply,sizeof(reply));
644         cmd_struct.an_cmd   = AN_CMD_ALLOC_DESC;
645         cmd_struct.an_parm0 = AN_DESCRIPTOR_HOSTRW;
646         cmd_struct.an_parm1 = AN_HOST_DESC_OFFSET;
647         cmd_struct.an_parm2 = 1;
648         if (an_cmd_struct(sc, &cmd_struct, &reply)) {
649                 printf("an%d: failed to allocate host descriptor\n", 
650                        sc->an_unit);
651                 return(EIO);
652         }
653
654         bzero(&an_rid_desc, sizeof(an_rid_desc));
655         an_rid_desc.an_valid = 1;
656         an_rid_desc.an_len = AN_RID_BUFFER_SIZE;
657         an_rid_desc.an_rid = 0;
658         an_rid_desc.an_phys = sc->an_rid_buffer.an_dma_paddr;
659
660         for (i = 0; i < sizeof(an_rid_desc) / 4; i++)
661                 CSR_MEM_AUX_WRITE_4(sc, AN_HOST_DESC_OFFSET + i * 4, 
662                                     ((u_int32_t*)&an_rid_desc)[i]);
663
664         return(0);
665 }
666
667 int
668 an_attach(sc, unit, flags)
669         struct an_softc *sc;
670         int unit;
671         int flags;
672 {
673         struct ifnet            *ifp = &sc->arpcom.ac_if;
674         int                     error;
675
676         sc->an_gone = 0;
677         sc->an_associated = 0;
678         sc->an_monitor = 0;
679         sc->an_was_monitor = 0;
680         sc->an_flash_buffer = NULL;
681
682         /* Reset the NIC. */
683         an_reset(sc);
684         if (sc->mpi350) {
685                 error = an_init_mpi350_desc(sc);
686                 if (error)
687                         return(error);
688         }
689
690         /* Load factory config */
691         if (an_cmd(sc, AN_CMD_READCFG, 0)) {
692                 printf("an%d: failed to load config data\n", sc->an_unit);
693                 return(EIO);
694         }
695
696         /* Read the current configuration */
697         sc->an_config.an_type = AN_RID_GENCONFIG;
698         sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
699         if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
700                 printf("an%d: read record failed\n", sc->an_unit);
701                 return(EIO);
702         }
703
704         /* Read the card capabilities */
705         sc->an_caps.an_type = AN_RID_CAPABILITIES;
706         sc->an_caps.an_len = sizeof(struct an_ltv_caps);
707         if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) {
708                 printf("an%d: read record failed\n", sc->an_unit);
709                 return(EIO);
710         }
711
712         /* Read ssid list */
713         sc->an_ssidlist.an_type = AN_RID_SSIDLIST;
714         sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist);
715         if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) {
716                 printf("an%d: read record failed\n", sc->an_unit);
717                 return(EIO);
718         }
719
720         /* Read AP list */
721         sc->an_aplist.an_type = AN_RID_APLIST;
722         sc->an_aplist.an_len = sizeof(struct an_ltv_aplist);
723         if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) {
724                 printf("an%d: read record failed\n", sc->an_unit);
725                 return(EIO);
726         }
727
728 #ifdef ANCACHE
729         /* Read the RSSI <-> dBm map */
730         sc->an_have_rssimap = 0;
731         if (sc->an_caps.an_softcaps & 8) {
732                 sc->an_rssimap.an_type = AN_RID_RSSI_MAP;
733                 sc->an_rssimap.an_len = sizeof(struct an_ltv_rssi_map);
734                 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_rssimap)) {
735                         printf("an%d: unable to get RSSI <-> dBM map\n", sc->an_unit);
736                 } else {
737                         printf("an%d: got RSSI <-> dBM map\n", sc->an_unit);
738                         sc->an_have_rssimap = 1;
739                 }
740         } else {
741                 printf("an%d: no RSSI <-> dBM map\n", sc->an_unit);
742         }
743 #endif
744
745         bcopy((char *)&sc->an_caps.an_oemaddr,
746            (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
747
748         printf("an%d: Ethernet address: %6D\n", sc->an_unit,
749             sc->arpcom.ac_enaddr, ":");
750
751         ifp->if_softc = sc;
752         if_initname(ifp, "an", unit);
753         ifp->if_mtu = ETHERMTU;
754         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
755         ifp->if_ioctl = an_ioctl;
756         ifp->if_output = ether_output;
757         ifp->if_start = an_start;
758         ifp->if_watchdog = an_watchdog;
759         ifp->if_init = an_init;
760         ifp->if_baudrate = 10000000;
761         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
762
763         bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename));
764         bcopy(AN_DEFAULT_NODENAME, sc->an_config.an_nodename,
765             sizeof(AN_DEFAULT_NODENAME) - 1);
766
767         bzero(sc->an_ssidlist.an_ssid1, sizeof(sc->an_ssidlist.an_ssid1));
768         bcopy(AN_DEFAULT_NETNAME, sc->an_ssidlist.an_ssid1,
769             sizeof(AN_DEFAULT_NETNAME) - 1);
770         sc->an_ssidlist.an_ssid1_len = strlen(AN_DEFAULT_NETNAME);
771
772         sc->an_config.an_opmode =
773             AN_OPMODE_INFRASTRUCTURE_STATION;
774
775         sc->an_tx_rate = 0;
776         bzero((char *)&sc->an_stats, sizeof(sc->an_stats));
777
778         ifmedia_init(&sc->an_ifmedia, 0, an_media_change, an_media_status);
779 #define ADD(m, c)       ifmedia_add(&sc->an_ifmedia, (m), (c), NULL)
780         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
781             IFM_IEEE80211_ADHOC, 0), 0);
782         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
783         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
784             IFM_IEEE80211_ADHOC, 0), 0);
785         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
786         if (sc->an_caps.an_rates[2] == AN_RATE_5_5MBPS) {
787                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
788                     IFM_IEEE80211_ADHOC, 0), 0);
789                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
790         }
791         if (sc->an_caps.an_rates[3] == AN_RATE_11MBPS) {
792                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
793                     IFM_IEEE80211_ADHOC, 0), 0);
794                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
795         }
796         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
797             IFM_IEEE80211_ADHOC, 0), 0);
798         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
799 #undef  ADD
800         ifmedia_set(&sc->an_ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
801             0, 0));
802
803         /*
804          * Call MI attach routine.
805          */
806         ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
807         callout_handle_init(&sc->an_stat_ch);
808
809         return(0);
810 }
811
812 static void
813 an_rxeof(sc)
814         struct an_softc *sc;
815 {
816         struct ifnet   *ifp;
817         struct ether_header *eh;
818         struct ieee80211_frame *ih;
819         struct an_rxframe rx_frame;
820         struct an_rxframe_802_3 rx_frame_802_3;
821         struct mbuf    *m;
822         int             len, id, error = 0, i, count = 0;
823         int             ieee80211_header_len;
824         u_char          *bpf_buf;
825         u_short         fc1;
826         struct an_card_rx_desc an_rx_desc;
827         u_int8_t        *buf;
828
829         ifp = &sc->arpcom.ac_if;
830
831         if (!sc->mpi350) {
832                 id = CSR_READ_2(sc, AN_RX_FID);
833
834                 if (sc->an_monitor && (ifp->if_flags & IFF_PROMISC)) {
835                         /* read raw 802.11 packet */
836                         bpf_buf = sc->buf_802_11;
837
838                         /* read header */
839                         if (an_read_data(sc, id, 0x0, (caddr_t)&rx_frame,
840                                          sizeof(rx_frame))) {
841                                 ifp->if_ierrors++;
842                                 return;
843                         }
844
845                         /*
846                          * skip beacon by default since this increases the
847                          * system load a lot
848                          */
849
850                         if (!(sc->an_monitor & AN_MONITOR_INCLUDE_BEACON) &&
851                             (rx_frame.an_frame_ctl & 
852                              IEEE80211_FC0_SUBTYPE_BEACON)) {
853                                 return;
854                         }
855
856                         if (sc->an_monitor & AN_MONITOR_AIRONET_HEADER) {
857                                 len = rx_frame.an_rx_payload_len
858                                         + sizeof(rx_frame);
859                                 /* Check for insane frame length */
860                                 if (len > sizeof(sc->buf_802_11)) {
861                                         printf("an%d: oversized packet "
862                                                "received (%d, %d)\n",
863                                                sc->an_unit, len, MCLBYTES);
864                                         ifp->if_ierrors++;
865                                         return;
866                                 }
867
868                                 bcopy((char *)&rx_frame,
869                                       bpf_buf, sizeof(rx_frame));
870
871                                 error = an_read_data(sc, id, sizeof(rx_frame),
872                                             (caddr_t)bpf_buf+sizeof(rx_frame),
873                                             rx_frame.an_rx_payload_len);
874                         } else {
875                                 fc1=rx_frame.an_frame_ctl >> 8;
876                                 ieee80211_header_len = 
877                                         sizeof(struct ieee80211_frame);
878                                 if ((fc1 & IEEE80211_FC1_DIR_TODS) &&
879                                     (fc1 & IEEE80211_FC1_DIR_FROMDS)) {
880                                         ieee80211_header_len += ETHER_ADDR_LEN;
881                                 }
882
883                                 len = rx_frame.an_rx_payload_len
884                                         + ieee80211_header_len;
885                                 /* Check for insane frame length */
886                                 if (len > sizeof(sc->buf_802_11)) {
887                                         printf("an%d: oversized packet "
888                                                "received (%d, %d)\n",
889                                                sc->an_unit, len, MCLBYTES);
890                                         ifp->if_ierrors++;
891                                         return;
892                                 }
893
894                                 ih = (struct ieee80211_frame *)bpf_buf;
895
896                                 bcopy((char *)&rx_frame.an_frame_ctl,
897                                       (char *)ih, ieee80211_header_len);
898
899                                 error = an_read_data(sc, id, sizeof(rx_frame) +
900                                             rx_frame.an_gaplen,
901                                             (caddr_t)ih +ieee80211_header_len,
902                                             rx_frame.an_rx_payload_len);
903                         }
904                         /* dump raw 802.11 packet to bpf and skip ip stack */
905                         if (ifp->if_bpf != NULL) {
906                                 bpf_tap(ifp, bpf_buf, len);
907                         }
908                 } else {
909                         MGETHDR(m, M_NOWAIT, MT_DATA);
910                         if (m == NULL) {
911                                 ifp->if_ierrors++;
912                                 return;
913                         }
914                         MCLGET(m, M_NOWAIT);
915                         if (!(m->m_flags & M_EXT)) {
916                                 m_freem(m);
917                                 ifp->if_ierrors++;
918                                 return;
919                         }
920                         m->m_pkthdr.rcvif = ifp;
921                         /* Read Ethernet encapsulated packet */
922
923 #ifdef ANCACHE
924                         /* Read NIC frame header */
925                         if (an_read_data(sc, id, 0, (caddr_t)&rx_frame, 
926                                          sizeof(rx_frame))) {
927                                 ifp->if_ierrors++;
928                                 return;
929                         }
930 #endif
931                         /* Read in the 802_3 frame header */
932                         if (an_read_data(sc, id, 0x34, 
933                                          (caddr_t)&rx_frame_802_3,
934                                          sizeof(rx_frame_802_3))) {
935                                 ifp->if_ierrors++;
936                                 return;
937                         }
938                         if (rx_frame_802_3.an_rx_802_3_status != 0) {
939                                 ifp->if_ierrors++;
940                                 return;
941                         }
942                         /* Check for insane frame length */
943                         len = rx_frame_802_3.an_rx_802_3_payload_len;
944                         if (len > sizeof(sc->buf_802_11)) {
945                                 printf("an%d: oversized packet "
946                                        "received (%d, %d)\n",
947                                        sc->an_unit, len, MCLBYTES);
948                                 ifp->if_ierrors++;
949                                 return;
950                         }
951                         m->m_pkthdr.len = m->m_len =
952                                 rx_frame_802_3.an_rx_802_3_payload_len + 12;
953
954                         eh = mtod(m, struct ether_header *);
955
956                         bcopy((char *)&rx_frame_802_3.an_rx_dst_addr,
957                               (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
958                         bcopy((char *)&rx_frame_802_3.an_rx_src_addr,
959                               (char *)&eh->ether_shost, ETHER_ADDR_LEN);
960
961                         /* in mbuf header type is just before payload */
962                         error = an_read_data(sc, id, 0x44, 
963                                     (caddr_t)&(eh->ether_type),
964                                     rx_frame_802_3.an_rx_802_3_payload_len);
965
966                         if (error) {
967                                 m_freem(m);
968                                 ifp->if_ierrors++;
969                                 return;
970                         }
971                         ifp->if_ipackets++;
972
973                         /* Receive packet. */
974                         m_adj(m, sizeof(struct ether_header));
975 #ifdef ANCACHE
976                         an_cache_store(sc, eh, m,
977                                 rx_frame.an_rx_signal_strength,
978                                 rx_frame.an_rsvd0);
979 #endif
980                         ether_input(ifp, eh, m);
981                 }
982
983         } else { /* MPI-350 */
984                 for (count = 0; count < AN_MAX_RX_DESC; count++){
985                         for (i = 0; i < sizeof(an_rx_desc) / 4; i++)
986                                 ((u_int32_t*)&an_rx_desc)[i] 
987                                         = CSR_MEM_AUX_READ_4(sc, 
988                                                 AN_RX_DESC_OFFSET 
989                                                 + (count * sizeof(an_rx_desc))
990                                                 + (i * 4));
991
992                         if (an_rx_desc.an_done && !an_rx_desc.an_valid) {
993                                 buf = sc->an_rx_buffer[count].an_dma_vaddr;
994
995                                 MGETHDR(m, M_NOWAIT, MT_DATA);
996                                 if (m == NULL) {
997                                         ifp->if_ierrors++;
998                                         return;
999                                 }
1000                                 MCLGET(m, M_NOWAIT);
1001                                 if (!(m->m_flags & M_EXT)) {
1002                                         m_freem(m);
1003                                         ifp->if_ierrors++;
1004                                         return;
1005                                 }
1006                                 m->m_pkthdr.rcvif = ifp;
1007                                 /* Read Ethernet encapsulated packet */
1008
1009                                 /* 
1010                                  * No ANCACHE support since we just get back
1011                                  * an Ethernet packet no 802.11 info
1012                                  */
1013 #if 0
1014 #ifdef ANCACHE
1015                                 /* Read NIC frame header */
1016                                 bcopy(buf, (caddr_t)&rx_frame, 
1017                                       sizeof(rx_frame));
1018 #endif
1019 #endif
1020                                 /* Check for insane frame length */
1021                                 len = an_rx_desc.an_len + 12;
1022                                 if (len > MCLBYTES) {
1023                                         printf("an%d: oversized packet "
1024                                                "received (%d, %d)\n",
1025                                                sc->an_unit, len, MCLBYTES);
1026                                         ifp->if_ierrors++;
1027                                         return;
1028                                 }
1029
1030                                 m->m_pkthdr.len = m->m_len =
1031                                         an_rx_desc.an_len + 12;
1032                                 
1033                                 eh = mtod(m, struct ether_header *);
1034                                 
1035                                 bcopy(buf, (char *)eh,
1036                                       m->m_pkthdr.len);
1037                                 
1038                                 ifp->if_ipackets++;
1039                                 
1040                                 /* Receive packet. */
1041                                 m_adj(m, sizeof(struct ether_header));
1042 #if 0
1043 #ifdef ANCACHE
1044                                 an_cache_store(sc, eh, m, 
1045                                         rx_frame.an_rx_signal_strength,
1046                                         rx_frame.an_rsvd0);
1047 #endif
1048 #endif
1049                                 ether_input(ifp, eh, m);
1050                         
1051                                 an_rx_desc.an_valid = 1;
1052                                 an_rx_desc.an_len = AN_RX_BUFFER_SIZE;
1053                                 an_rx_desc.an_done = 0;
1054                                 an_rx_desc.an_phys = 
1055                                         sc->an_rx_buffer[count].an_dma_paddr;
1056                         
1057                                 for (i = 0; i < sizeof(an_rx_desc) / 4; i++)
1058                                         CSR_MEM_AUX_WRITE_4(sc, 
1059                                                 AN_RX_DESC_OFFSET 
1060                                                 + (count * sizeof(an_rx_desc))
1061                                                 + (i * 4),
1062                                                 ((u_int32_t*)&an_rx_desc)[i]);
1063                                 
1064                         } else {
1065                                 printf("an%d: Didn't get valid RX packet "
1066                                        "%x %x %d\n",
1067                                        sc->an_unit,
1068                                        an_rx_desc.an_done,
1069                                        an_rx_desc.an_valid, an_rx_desc.an_len);
1070                         }
1071                 }
1072         }
1073 }
1074
1075 static void
1076 an_txeof(sc, status)
1077         struct an_softc         *sc;
1078         int                     status;
1079 {
1080         struct ifnet            *ifp;
1081         int                     id, i;
1082
1083         ifp = &sc->arpcom.ac_if;
1084
1085         ifp->if_timer = 0;
1086         ifp->if_flags &= ~IFF_OACTIVE;
1087
1088         if (!sc->mpi350) {
1089                 id = CSR_READ_2(sc, AN_TX_CMP_FID);
1090
1091                 if (status & AN_EV_TX_EXC) {
1092                         ifp->if_oerrors++;
1093                 } else
1094                         ifp->if_opackets++;
1095
1096                 for (i = 0; i < AN_TX_RING_CNT; i++) {
1097                         if (id == sc->an_rdata.an_tx_ring[i]) {
1098                                 sc->an_rdata.an_tx_ring[i] = 0;
1099                                 break;
1100                         }
1101                 }
1102
1103                 AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT);
1104         } else { /* MPI 350 */
1105                 AN_INC(sc->an_rdata.an_tx_cons, AN_MAX_TX_DESC);
1106                 if (sc->an_rdata.an_tx_prod ==
1107                     sc->an_rdata.an_tx_cons)
1108                         sc->an_rdata.an_tx_empty = 1;
1109         }
1110
1111         return;
1112 }
1113
1114 /*
1115  * We abuse the stats updater to check the current NIC status. This
1116  * is important because we don't want to allow transmissions until
1117  * the NIC has synchronized to the current cell (either as the master
1118  * in an ad-hoc group, or as a station connected to an access point).
1119  */
1120 static void
1121 an_stats_update(xsc)
1122         void                    *xsc;
1123 {
1124         struct an_softc         *sc;
1125         struct ifnet            *ifp;
1126         int                     s;
1127
1128         s = splimp();
1129
1130         sc = xsc;
1131         ifp = &sc->arpcom.ac_if;
1132
1133         sc->an_status.an_type = AN_RID_STATUS;
1134         sc->an_status.an_len = sizeof(struct an_ltv_status);
1135         an_read_record(sc, (struct an_ltv_gen *)&sc->an_status);
1136
1137         if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC)
1138                 sc->an_associated = 1;
1139         else
1140                 sc->an_associated = 0;
1141
1142         /* Don't do this while we're transmitting */
1143         if (ifp->if_flags & IFF_OACTIVE) {
1144                 sc->an_stat_ch = timeout(an_stats_update, sc, hz);
1145                 splx(s);
1146                 return;
1147         }
1148
1149         sc->an_stats.an_len = sizeof(struct an_ltv_stats);
1150         sc->an_stats.an_type = AN_RID_32BITS_CUM;
1151         an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len);
1152
1153         sc->an_stat_ch = timeout(an_stats_update, sc, hz);
1154         splx(s);
1155
1156         return;
1157 }
1158
1159 void
1160 an_intr(xsc)
1161         void                    *xsc;
1162 {
1163         struct an_softc         *sc;
1164         struct ifnet            *ifp;
1165         u_int16_t               status;
1166
1167         sc = (struct an_softc*)xsc;
1168
1169         if (sc->an_gone)
1170                 return;
1171
1172         ifp = &sc->arpcom.ac_if;
1173
1174         /* Disable interrupts. */
1175         CSR_WRITE_2(sc, AN_INT_EN(sc->mpi350), 0);
1176
1177         status = CSR_READ_2(sc, AN_EVENT_STAT(sc->mpi350));
1178         CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), ~AN_INTRS);
1179
1180         if (status & AN_EV_AWAKE) {
1181                 CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_AWAKE);
1182         }
1183
1184         if (status & AN_EV_LINKSTAT) {
1185                 if (CSR_READ_2(sc, AN_LINKSTAT(sc->mpi350)) 
1186                     == AN_LINKSTAT_ASSOCIATED)
1187                         sc->an_associated = 1;
1188                 else
1189                         sc->an_associated = 0;
1190                 CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_LINKSTAT);
1191         }
1192
1193         if (status & AN_EV_RX) {
1194                 an_rxeof(sc);
1195                 CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_RX);
1196         }
1197
1198         if (status & AN_EV_TX) {
1199                 an_txeof(sc, status);
1200                 CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_TX);
1201         }
1202
1203         if (status & AN_EV_TX_EXC) {
1204                 an_txeof(sc, status);
1205                 CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_TX_EXC);
1206         }
1207
1208         if (status & AN_EV_ALLOC)
1209                 CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_ALLOC);
1210
1211         /* Re-enable interrupts. */
1212         CSR_WRITE_2(sc, AN_INT_EN(sc->mpi350), AN_INTRS);
1213
1214         if ((ifp->if_flags & IFF_UP) && (ifp->if_snd.ifq_head != NULL))
1215                 an_start(ifp);
1216
1217         return;
1218 }
1219
1220 static int
1221 an_cmd_struct(sc, cmd, reply)
1222         struct an_softc         *sc;
1223         struct an_command       *cmd;
1224         struct an_reply         *reply;
1225 {
1226         int                     i;
1227
1228         for (i = 0; i != AN_TIMEOUT; i++) {
1229                 if (CSR_READ_2(sc, AN_COMMAND(sc->mpi350)) & AN_CMD_BUSY) {
1230                         DELAY(1000);
1231                 } else
1232                         break;
1233         }
1234         if( i == AN_TIMEOUT) {
1235                 printf("BUSY\n");
1236                 return(ETIMEDOUT);
1237         }
1238
1239         CSR_WRITE_2(sc, AN_PARAM0(sc->mpi350), cmd->an_parm0);
1240         CSR_WRITE_2(sc, AN_PARAM1(sc->mpi350), cmd->an_parm1);
1241         CSR_WRITE_2(sc, AN_PARAM2(sc->mpi350), cmd->an_parm2);
1242         CSR_WRITE_2(sc, AN_COMMAND(sc->mpi350), cmd->an_cmd);
1243
1244         for (i = 0; i < AN_TIMEOUT; i++) {
1245                 if (CSR_READ_2(sc, AN_EVENT_STAT(sc->mpi350)) & AN_EV_CMD)
1246                         break;
1247                 DELAY(1000);
1248         }
1249
1250         reply->an_resp0 = CSR_READ_2(sc, AN_RESP0(sc->mpi350));
1251         reply->an_resp1 = CSR_READ_2(sc, AN_RESP1(sc->mpi350));
1252         reply->an_resp2 = CSR_READ_2(sc, AN_RESP2(sc->mpi350));
1253         reply->an_status = CSR_READ_2(sc, AN_STATUS(sc->mpi350));
1254
1255         if (CSR_READ_2(sc, AN_COMMAND(sc->mpi350)) & AN_CMD_BUSY)
1256                 CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_CLR_STUCK_BUSY);
1257
1258         /* Ack the command */
1259         CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_CMD);
1260
1261         if (i == AN_TIMEOUT)
1262                 return(ETIMEDOUT);
1263
1264         return(0);
1265 }
1266
1267 static int
1268 an_cmd(sc, cmd, val)
1269         struct an_softc         *sc;
1270         int                     cmd;
1271         int                     val;
1272 {
1273         int                     i, s = 0;
1274
1275         CSR_WRITE_2(sc, AN_PARAM0(sc->mpi350), val);
1276         CSR_WRITE_2(sc, AN_PARAM1(sc->mpi350), 0);
1277         CSR_WRITE_2(sc, AN_PARAM2(sc->mpi350), 0);
1278         CSR_WRITE_2(sc, AN_COMMAND(sc->mpi350), cmd);
1279
1280         for (i = 0; i < AN_TIMEOUT; i++) {
1281                 if (CSR_READ_2(sc, AN_EVENT_STAT(sc->mpi350)) & AN_EV_CMD)
1282                         break;
1283                 else {
1284                         if (CSR_READ_2(sc, AN_COMMAND(sc->mpi350)) == cmd)
1285                                 CSR_WRITE_2(sc, AN_COMMAND(sc->mpi350), cmd);
1286                 }
1287         }
1288
1289         for (i = 0; i < AN_TIMEOUT; i++) {
1290                 CSR_READ_2(sc, AN_RESP0(sc->mpi350));
1291                 CSR_READ_2(sc, AN_RESP1(sc->mpi350));
1292                 CSR_READ_2(sc, AN_RESP2(sc->mpi350));
1293                 s = CSR_READ_2(sc, AN_STATUS(sc->mpi350));
1294                 if ((s & AN_STAT_CMD_CODE) == (cmd & AN_STAT_CMD_CODE))
1295                         break;
1296         }
1297
1298         /* Ack the command */
1299         CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_CMD);
1300
1301         if (CSR_READ_2(sc, AN_COMMAND(sc->mpi350)) & AN_CMD_BUSY)
1302                 CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_CLR_STUCK_BUSY);
1303
1304         if (i == AN_TIMEOUT)
1305                 return(ETIMEDOUT);
1306
1307         return(0);
1308 }
1309
1310 /*
1311  * This reset sequence may look a little strange, but this is the
1312  * most reliable method I've found to really kick the NIC in the
1313  * head and force it to reboot correctly.
1314  */
1315 static void
1316 an_reset(sc)
1317         struct an_softc         *sc;
1318 {
1319         if (sc->an_gone)
1320                 return;
1321
1322         an_cmd(sc, AN_CMD_ENABLE, 0);
1323         an_cmd(sc, AN_CMD_FW_RESTART, 0);
1324         an_cmd(sc, AN_CMD_NOOP2, 0);
1325
1326         if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT)
1327                 printf("an%d: reset failed\n", sc->an_unit);
1328
1329         an_cmd(sc, AN_CMD_DISABLE, 0);
1330
1331         return;
1332 }
1333
1334 /*
1335  * Read an LTV record from the NIC.
1336  */
1337 static int
1338 an_read_record(sc, ltv)
1339         struct an_softc         *sc;
1340         struct an_ltv_gen       *ltv;
1341 {
1342         struct an_ltv_gen       *an_ltv;
1343         struct an_card_rid_desc an_rid_desc;
1344         struct an_command       cmd;
1345         struct an_reply         reply;
1346         u_int16_t               *ptr;
1347         u_int8_t                *ptr2;
1348         int                     i, len;
1349
1350         if (ltv->an_len < 4 || ltv->an_type == 0)
1351                 return(EINVAL);
1352
1353         if (!sc->mpi350){
1354                 /* Tell the NIC to enter record read mode. */
1355                 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) {
1356                         printf("an%d: RID access failed\n", sc->an_unit);
1357                         return(EIO);
1358                 }
1359
1360                 /* Seek to the record. */
1361                 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) {
1362                         printf("an%d: seek to record failed\n", sc->an_unit);
1363                         return(EIO);
1364                 }
1365
1366                 /*
1367                  * Read the length and record type and make sure they
1368                  * match what we expect (this verifies that we have enough
1369                  * room to hold all of the returned data).
1370                  * Length includes type but not length.
1371                  */
1372                 len = CSR_READ_2(sc, AN_DATA1);
1373                 if (len > (ltv->an_len - 2)) {
1374                         printf("an%d: record length mismatch -- expected %d, "
1375                                "got %d for Rid %x\n", sc->an_unit,
1376                                ltv->an_len - 2, len, ltv->an_type);
1377                         len = ltv->an_len - 2;
1378                 } else {
1379                         ltv->an_len = len + 2;
1380                 }
1381
1382                 /* Now read the data. */
1383                 len -= 2;       /* skip the type */
1384                 ptr = &ltv->an_val;
1385                 for (i = len; i > 1; i -= 2)
1386                         *ptr++ = CSR_READ_2(sc, AN_DATA1);
1387                 if (i) {
1388                         ptr2 = (u_int8_t *)ptr;
1389                         *ptr2 = CSR_READ_1(sc, AN_DATA1);
1390                 }
1391         } else { /* MPI-350 */
1392                 an_rid_desc.an_valid = 1;
1393                 an_rid_desc.an_len = AN_RID_BUFFER_SIZE;
1394                 an_rid_desc.an_rid = 0;
1395                 an_rid_desc.an_phys = sc->an_rid_buffer.an_dma_paddr;
1396                 bzero(sc->an_rid_buffer.an_dma_vaddr, AN_RID_BUFFER_SIZE);
1397
1398                 bzero(&cmd, sizeof(cmd));
1399                 bzero(&reply, sizeof(reply));
1400                 cmd.an_cmd = AN_CMD_ACCESS|AN_ACCESS_READ;
1401                 cmd.an_parm0 = ltv->an_type;
1402
1403                 for (i = 0; i < sizeof(an_rid_desc) / 4; i++)
1404                         CSR_MEM_AUX_WRITE_4(sc, AN_HOST_DESC_OFFSET + i * 4, 
1405                                             ((u_int32_t*)&an_rid_desc)[i]);
1406
1407                 if (an_cmd_struct(sc, &cmd, &reply)
1408                     || reply.an_status & AN_CMD_QUAL_MASK) {
1409                         printf("an%d: failed to read RID %x %x %x %x %x, %d\n", 
1410                                sc->an_unit, ltv->an_type, 
1411                                reply.an_status,
1412                                reply.an_resp0,
1413                                reply.an_resp1,
1414                                reply.an_resp2,
1415                                i);
1416                         return(EIO);
1417                 }
1418
1419                 an_ltv = (struct an_ltv_gen *)sc->an_rid_buffer.an_dma_vaddr;
1420                 if (an_ltv->an_len + 2 < an_rid_desc.an_len) {
1421                         an_rid_desc.an_len = an_ltv->an_len;
1422                 }
1423
1424                 if (an_rid_desc.an_len > 2)
1425                         bcopy(&an_ltv->an_type,
1426                               &ltv->an_val, 
1427                               an_rid_desc.an_len - 2);
1428                 ltv->an_len = an_rid_desc.an_len + 2;
1429         }
1430
1431         if (an_dump)
1432                 an_dump_record(sc, ltv, "Read");
1433
1434         return(0);
1435 }
1436
1437 /*
1438  * Same as read, except we inject data instead of reading it.
1439  */
1440 static int
1441 an_write_record(sc, ltv)
1442         struct an_softc         *sc;
1443         struct an_ltv_gen       *ltv;
1444 {
1445         struct an_card_rid_desc an_rid_desc;
1446         struct an_command       cmd;
1447         struct an_reply         reply;
1448         char                    *buf;
1449         u_int16_t               *ptr;
1450         u_int8_t                *ptr2;
1451         int                     i, len;
1452
1453         if (an_dump)
1454                 an_dump_record(sc, ltv, "Write");
1455
1456         if (!sc->mpi350){
1457                 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type))
1458                         return(EIO);
1459
1460                 if (an_seek(sc, ltv->an_type, 0, AN_BAP1))
1461                         return(EIO);
1462
1463                 /*
1464                  * Length includes type but not length.
1465                  */
1466                 len = ltv->an_len - 2;
1467                 CSR_WRITE_2(sc, AN_DATA1, len);
1468
1469                 len -= 2;       /* skip the type */
1470                 ptr = &ltv->an_val;
1471                 for (i = len; i > 1; i -= 2)
1472                         CSR_WRITE_2(sc, AN_DATA1, *ptr++);
1473                 if (i) {
1474                         ptr2 = (u_int8_t *)ptr;
1475                         CSR_WRITE_1(sc, AN_DATA0, *ptr2);
1476                 }
1477
1478                 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type))
1479                         return(EIO);
1480         } else { 
1481                 /* MPI-350 */
1482
1483                 for (i = 0; i != AN_TIMEOUT; i++) {
1484                         if (CSR_READ_2(sc, AN_COMMAND(sc->mpi350)) 
1485                             & AN_CMD_BUSY) {
1486                                 DELAY(10);
1487                         } else
1488                                 break;
1489                 }
1490                 if (i == AN_TIMEOUT) {
1491                         printf("BUSY\n");
1492                 }
1493
1494                 an_rid_desc.an_valid = 1;
1495                 an_rid_desc.an_len = ltv->an_len - 2;
1496                 an_rid_desc.an_rid = ltv->an_type;
1497                 an_rid_desc.an_phys = sc->an_rid_buffer.an_dma_paddr;
1498
1499                 bcopy(&ltv->an_type, sc->an_rid_buffer.an_dma_vaddr,
1500                       an_rid_desc.an_len);
1501
1502                 bzero(&cmd,sizeof(cmd));
1503                 bzero(&reply,sizeof(reply));
1504                 cmd.an_cmd = AN_CMD_ACCESS|AN_ACCESS_WRITE;
1505                 cmd.an_parm0 = ltv->an_type;
1506
1507                 for (i = 0; i < sizeof(an_rid_desc) / 4; i++)
1508                         CSR_MEM_AUX_WRITE_4(sc, AN_HOST_DESC_OFFSET + i * 4, 
1509                                             ((u_int32_t*)&an_rid_desc)[i]);
1510
1511                 if ((i = an_cmd_struct(sc, &cmd, &reply))) {
1512                         printf("an%d: failed to write RID 1 %x %x %x %x %x, %d\n", 
1513                             sc->an_unit, ltv->an_type, 
1514                             reply.an_status,
1515                             reply.an_resp0,
1516                             reply.an_resp1,
1517                             reply.an_resp2,
1518                             i);
1519                         return(EIO);
1520                 }
1521
1522                 ptr = (u_int16_t *)buf;
1523
1524                 if (reply.an_status & AN_CMD_QUAL_MASK) {
1525                         printf("an%d: failed to write RID 2 %x %x %x %x %x, %d\n", 
1526                             sc->an_unit, ltv->an_type, 
1527                             reply.an_status,
1528                             reply.an_resp0,
1529                             reply.an_resp1,
1530                             reply.an_resp2,
1531                             i);
1532                         return(EIO);
1533                 }
1534         }
1535
1536         return(0);
1537 }
1538
1539 static void
1540 an_dump_record(sc, ltv, string)
1541         struct an_softc         *sc;
1542         struct an_ltv_gen       *ltv;
1543         char                    *string;
1544 {
1545         u_int8_t                *ptr2;
1546         int                     len;
1547         int                     i;
1548         int                     count = 0;
1549         char                    buf[17], temp;
1550
1551         len = ltv->an_len - 4;
1552         printf("an%d: RID %4x, Length %4d, Mode %s\n",
1553                 sc->an_unit, ltv->an_type, ltv->an_len - 4, string);
1554
1555         if (an_dump == 1 || (an_dump == ltv->an_type)) {
1556                 printf("an%d:\t", sc->an_unit);
1557                 bzero(buf,sizeof(buf));
1558
1559                 ptr2 = (u_int8_t *)&ltv->an_val;
1560                 for (i = len; i > 0; i--) {
1561                         printf("%02x ", *ptr2);
1562
1563                         temp = *ptr2++;
1564                         if (temp >= ' ' && temp <= '~')
1565                                 buf[count] = temp;
1566                         else if (temp >= 'A' && temp <= 'Z')
1567                                 buf[count] = temp;
1568                         else
1569                                 buf[count] = '.';
1570                         if (++count == 16) {
1571                                 count = 0;
1572                                 printf("%s\n",buf);
1573                                 printf("an%d:\t", sc->an_unit);
1574                                 bzero(buf,sizeof(buf));
1575                         }
1576                 }
1577                 for (; count != 16; count++) {
1578                         printf("   ");
1579                 }
1580                 printf(" %s\n",buf);
1581         }
1582 }
1583
1584 static int
1585 an_seek(sc, id, off, chan)
1586         struct an_softc         *sc;
1587         int                     id, off, chan;
1588 {
1589         int                     i;
1590         int                     selreg, offreg;
1591
1592         switch (chan) {
1593         case AN_BAP0:
1594                 selreg = AN_SEL0;
1595                 offreg = AN_OFF0;
1596                 break;
1597         case AN_BAP1:
1598                 selreg = AN_SEL1;
1599                 offreg = AN_OFF1;
1600                 break;
1601         default:
1602                 printf("an%d: invalid data path: %x\n", sc->an_unit, chan);
1603                 return(EIO);
1604         }
1605
1606         CSR_WRITE_2(sc, selreg, id);
1607         CSR_WRITE_2(sc, offreg, off);
1608
1609         for (i = 0; i < AN_TIMEOUT; i++) {
1610                 if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR)))
1611                         break;
1612         }
1613
1614         if (i == AN_TIMEOUT)
1615                 return(ETIMEDOUT);
1616
1617         return(0);
1618 }
1619
1620 static int
1621 an_read_data(sc, id, off, buf, len)
1622         struct an_softc         *sc;
1623         int                     id, off;
1624         caddr_t                 buf;
1625         int                     len;
1626 {
1627         int                     i;
1628         u_int16_t               *ptr;
1629         u_int8_t                *ptr2;
1630
1631         if (off != -1) {
1632                 if (an_seek(sc, id, off, AN_BAP1))
1633                         return(EIO);
1634         }
1635
1636         ptr = (u_int16_t *)buf;
1637         for (i = len; i > 1; i -= 2)
1638                 *ptr++ = CSR_READ_2(sc, AN_DATA1);
1639         if (i) {
1640                 ptr2 = (u_int8_t *)ptr;
1641                 *ptr2 = CSR_READ_1(sc, AN_DATA1);
1642         }
1643
1644         return(0);
1645 }
1646
1647 static int
1648 an_write_data(sc, id, off, buf, len)
1649         struct an_softc         *sc;
1650         int                     id, off;
1651         caddr_t                 buf;
1652         int                     len;
1653 {
1654         int                     i;
1655         u_int16_t               *ptr;
1656         u_int8_t                *ptr2;
1657
1658         if (off != -1) {
1659                 if (an_seek(sc, id, off, AN_BAP0))
1660                         return(EIO);
1661         }
1662
1663         ptr = (u_int16_t *)buf;
1664         for (i = len; i > 1; i -= 2)
1665                 CSR_WRITE_2(sc, AN_DATA0, *ptr++);
1666         if (i) {
1667                 ptr2 = (u_int8_t *)ptr;
1668                 CSR_WRITE_1(sc, AN_DATA0, *ptr2);
1669         }
1670
1671         return(0);
1672 }
1673
1674 /*
1675  * Allocate a region of memory inside the NIC and zero
1676  * it out.
1677  */
1678 static int
1679 an_alloc_nicmem(sc, len, id)
1680         struct an_softc         *sc;
1681         int                     len;
1682         int                     *id;
1683 {
1684         int                     i;
1685
1686         if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) {
1687                 printf("an%d: failed to allocate %d bytes on NIC\n",
1688                     sc->an_unit, len);
1689                 return(ENOMEM);
1690         }
1691
1692         for (i = 0; i < AN_TIMEOUT; i++) {
1693                 if (CSR_READ_2(sc, AN_EVENT_STAT(sc->mpi350)) & AN_EV_ALLOC)
1694                         break;
1695         }
1696
1697         if (i == AN_TIMEOUT)
1698                 return(ETIMEDOUT);
1699
1700         CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_ALLOC);
1701         *id = CSR_READ_2(sc, AN_ALLOC_FID);
1702
1703         if (an_seek(sc, *id, 0, AN_BAP0))
1704                 return(EIO);
1705
1706         for (i = 0; i < len / 2; i++)
1707                 CSR_WRITE_2(sc, AN_DATA0, 0);
1708
1709         return(0);
1710 }
1711
1712 static void
1713 an_setdef(sc, areq)
1714         struct an_softc         *sc;
1715         struct an_req           *areq;
1716 {
1717         struct sockaddr_dl      *sdl;
1718         struct ifaddr           *ifa;
1719         struct ifnet            *ifp;
1720         struct an_ltv_genconfig *cfg;
1721         struct an_ltv_ssidlist  *ssid;
1722         struct an_ltv_aplist    *ap;
1723         struct an_ltv_gen       *sp;
1724
1725         ifp = &sc->arpcom.ac_if;
1726
1727         switch (areq->an_type) {
1728         case AN_RID_GENCONFIG:
1729                 cfg = (struct an_ltv_genconfig *)areq;
1730
1731                 ifa = ifnet_addrs[ifp->if_index - 1];
1732                 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
1733                 bcopy((char *)&cfg->an_macaddr, (char *)&sc->arpcom.ac_enaddr,
1734                     ETHER_ADDR_LEN);
1735                 bcopy((char *)&cfg->an_macaddr, LLADDR(sdl), ETHER_ADDR_LEN);
1736
1737                 bcopy((char *)cfg, (char *)&sc->an_config,
1738                         sizeof(struct an_ltv_genconfig));
1739                 break;
1740         case AN_RID_SSIDLIST:
1741                 ssid = (struct an_ltv_ssidlist *)areq;
1742                 bcopy((char *)ssid, (char *)&sc->an_ssidlist,
1743                         sizeof(struct an_ltv_ssidlist));
1744                 break;
1745         case AN_RID_APLIST:
1746                 ap = (struct an_ltv_aplist *)areq;
1747                 bcopy((char *)ap, (char *)&sc->an_aplist,
1748                         sizeof(struct an_ltv_aplist));
1749                 break;
1750         case AN_RID_TX_SPEED:
1751                 sp = (struct an_ltv_gen *)areq;
1752                 sc->an_tx_rate = sp->an_val;
1753
1754                 /* Read the current configuration */
1755                 sc->an_config.an_type = AN_RID_GENCONFIG;
1756                 sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
1757                 an_read_record(sc, (struct an_ltv_gen *)&sc->an_config);
1758                 cfg = &sc->an_config;
1759
1760                 /* clear other rates and set the only one we want */
1761                 bzero(cfg->an_rates, sizeof(cfg->an_rates));
1762                 cfg->an_rates[0] = sc->an_tx_rate;
1763
1764                 /* Save the new rate */
1765                 sc->an_config.an_type = AN_RID_GENCONFIG;
1766                 sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
1767                 break;
1768         case AN_RID_WEP_TEMP:
1769                 /* Cache the temp keys */
1770                 bcopy(areq, 
1771                     &sc->an_temp_keys[((struct an_ltv_key *)areq)->kindex], 
1772                     sizeof(struct an_ltv_key));
1773         case AN_RID_WEP_PERM:
1774         case AN_RID_LEAPUSERNAME:
1775         case AN_RID_LEAPPASSWORD:
1776                 /* Disable the MAC. */
1777                 an_cmd(sc, AN_CMD_DISABLE, 0);
1778
1779                 /* Write the key */
1780                 an_write_record(sc, (struct an_ltv_gen *)areq);
1781
1782                 /* Turn the MAC back on. */
1783                 an_cmd(sc, AN_CMD_ENABLE, 0);
1784
1785                 break;
1786         case AN_RID_MONITOR_MODE:
1787                 cfg = (struct an_ltv_genconfig *)areq;
1788                 bpfdetach(ifp);
1789                 if (ng_ether_detach_p != NULL)
1790                         (*ng_ether_detach_p) (ifp);
1791                 sc->an_monitor = cfg->an_len;
1792
1793                 if (sc->an_monitor & AN_MONITOR) {
1794                         if (sc->an_monitor & AN_MONITOR_AIRONET_HEADER) {
1795                                 bpfattach(ifp, DLT_AIRONET_HEADER,
1796                                         sizeof(struct ether_header));
1797                         } else {
1798                                 bpfattach(ifp, DLT_IEEE802_11,
1799                                         sizeof(struct ether_header));
1800                         }
1801                 } else {
1802                         bpfattach(ifp, DLT_EN10MB,
1803                                   sizeof(struct ether_header));
1804                         if (ng_ether_attach_p != NULL)
1805                                 (*ng_ether_attach_p) (ifp);
1806                 }
1807                 break;
1808         default:
1809                 printf("an%d: unknown RID: %x\n", sc->an_unit, areq->an_type);
1810                 return;
1811                 break;
1812         }
1813
1814
1815         /* Reinitialize the card. */
1816         if (ifp->if_flags)
1817                 an_init(sc);
1818
1819         return;
1820 }
1821
1822 /*
1823  * Derived from Linux driver to enable promiscious mode.
1824  */
1825
1826 static void
1827 an_promisc(sc, promisc)
1828         struct an_softc         *sc;
1829         int                     promisc;
1830 {
1831         if (sc->an_was_monitor)
1832                 an_reset(sc);
1833                 if (sc->mpi350)
1834                         an_init_mpi350_desc(sc);        
1835         if (sc->an_monitor || sc->an_was_monitor)
1836                 an_init(sc);
1837
1838         sc->an_was_monitor = sc->an_monitor;
1839         an_cmd(sc, AN_CMD_SET_MODE, promisc ? 0xffff : 0);
1840
1841         return;
1842 }
1843
1844 static int
1845 an_ioctl(ifp, command, data)
1846         struct ifnet            *ifp;
1847         u_long                  command;
1848         caddr_t                 data;
1849 {
1850         int                     s, error = 0;
1851         int                     len;
1852         int                     i;
1853         struct an_softc         *sc;
1854         struct ifreq            *ifr;
1855         struct thread           *td = curthread;
1856         struct ieee80211req     *ireq;
1857         u_int8_t                tmpstr[IEEE80211_NWID_LEN*2];
1858         u_int8_t                *tmpptr;
1859         struct an_ltv_genconfig *config;
1860         struct an_ltv_key       *key;
1861         struct an_ltv_status    *status;
1862         struct an_ltv_ssidlist  *ssids;
1863         int                     mode;
1864         struct aironet_ioctl    l_ioctl;
1865
1866         sc = ifp->if_softc;
1867         s = splimp();
1868         ifr = (struct ifreq *)data;
1869         ireq = (struct ieee80211req *)data;
1870
1871         config = (struct an_ltv_genconfig *)&sc->areq;
1872         key = (struct an_ltv_key *)&sc->areq;
1873         status = (struct an_ltv_status *)&sc->areq;
1874         ssids = (struct an_ltv_ssidlist *)&sc->areq;
1875
1876         if (sc->an_gone) {
1877                 error = ENODEV;
1878                 goto out;
1879         }
1880
1881         switch (command) {
1882         case SIOCSIFADDR:
1883         case SIOCGIFADDR:
1884         case SIOCSIFMTU:
1885                 error = ether_ioctl(ifp, command, data);
1886                 break;
1887         case SIOCSIFFLAGS:
1888                 if (ifp->if_flags & IFF_UP) {
1889                         if (ifp->if_flags & IFF_RUNNING &&
1890                             ifp->if_flags & IFF_PROMISC &&
1891                             !(sc->an_if_flags & IFF_PROMISC)) {
1892                                 an_promisc(sc, 1);
1893                         } else if (ifp->if_flags & IFF_RUNNING &&
1894                             !(ifp->if_flags & IFF_PROMISC) &&
1895                             sc->an_if_flags & IFF_PROMISC) {
1896                                 an_promisc(sc, 0);
1897                         } else
1898                                 an_init(sc);
1899                 } else {
1900                         if (ifp->if_flags & IFF_RUNNING)
1901                                 an_stop(sc);
1902                 }
1903                 sc->an_if_flags = ifp->if_flags;
1904                 error = 0;
1905                 break;
1906         case SIOCSIFMEDIA:
1907         case SIOCGIFMEDIA:
1908                 error = ifmedia_ioctl(ifp, ifr, &sc->an_ifmedia, command);
1909                 break;
1910         case SIOCADDMULTI:
1911         case SIOCDELMULTI:
1912                 /* The Aironet has no multicast filter. */
1913                 error = 0;
1914                 break;
1915         case SIOCGAIRONET:
1916                 error = copyin(ifr->ifr_data, &sc->areq, sizeof(sc->areq));
1917                 if (error != 0)
1918                         break;
1919 #ifdef ANCACHE
1920                 if (sc->areq.an_type == AN_RID_ZERO_CACHE) {
1921                         error = suser(td);
1922                         if (error)
1923                                 break;
1924                         sc->an_sigitems = sc->an_nextitem = 0;
1925                         break;
1926                 } else if (sc->areq.an_type == AN_RID_READ_CACHE) {
1927                         char *pt = (char *)&sc->areq.an_val;
1928                         bcopy((char *)&sc->an_sigitems, (char *)pt,
1929                             sizeof(int));
1930                         pt += sizeof(int);
1931                         sc->areq.an_len = sizeof(int) / 2;
1932                         bcopy((char *)&sc->an_sigcache, (char *)pt,
1933                             sizeof(struct an_sigcache) * sc->an_sigitems);
1934                         sc->areq.an_len += ((sizeof(struct an_sigcache) *
1935                             sc->an_sigitems) / 2) + 1;
1936                 } else
1937 #endif
1938                 if (an_read_record(sc, (struct an_ltv_gen *)&sc->areq)) {
1939                         error = EINVAL;
1940                         break;
1941                 }
1942                 error = copyout(&sc->areq, ifr->ifr_data, sizeof(sc->areq));
1943                 break;
1944         case SIOCSAIRONET:
1945                 if ((error = suser(td)))
1946                         goto out;
1947                 error = copyin(ifr->ifr_data, &sc->areq, sizeof(sc->areq));
1948                 if (error != 0)
1949                         break;
1950                 an_setdef(sc, &sc->areq);
1951                 break;
1952         case SIOCGPRIVATE_0:              /* used by Cisco client utility */
1953                 if ((error = suser(td)))
1954                         goto out;
1955                 copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
1956                 mode = l_ioctl.command;
1957
1958                 if (mode >= AIROGCAP && mode <= AIROGSTATSD32) {
1959                         error = readrids(ifp, &l_ioctl);
1960                 } else if (mode >= AIROPCAP && mode <= AIROPLEAPUSR) {
1961                         error = writerids(ifp, &l_ioctl);
1962                 } else if (mode >= AIROFLSHRST && mode <= AIRORESTART) {
1963                         error = flashcard(ifp, &l_ioctl);
1964                 } else {
1965                         error =-1;
1966                 }
1967
1968                 /* copy out the updated command info */
1969                 copyout(&l_ioctl, ifr->ifr_data, sizeof(l_ioctl));
1970
1971                 break;
1972         case SIOCGPRIVATE_1:              /* used by Cisco client utility */
1973                 if ((error = suser(td)))
1974                         goto out;
1975                 copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
1976                 l_ioctl.command = 0;
1977                 error = AIROMAGIC;
1978                 copyout(&error, l_ioctl.data, sizeof(error));
1979                 error = 0;
1980                 break;
1981         case SIOCG80211:
1982                 sc->areq.an_len = sizeof(sc->areq);
1983                 /* was that a good idea DJA we are doing a short-cut */
1984                 switch (ireq->i_type) {
1985                 case IEEE80211_IOC_SSID:
1986                         if (ireq->i_val == -1) {
1987                                 sc->areq.an_type = AN_RID_STATUS;
1988                                 if (an_read_record(sc,
1989                                     (struct an_ltv_gen *)&sc->areq)) {
1990                                         error = EINVAL;
1991                                         break;
1992                                 }
1993                                 len = status->an_ssidlen;
1994                                 tmpptr = status->an_ssid;
1995                         } else if (ireq->i_val >= 0) {
1996                                 sc->areq.an_type = AN_RID_SSIDLIST;
1997                                 if (an_read_record(sc,
1998                                     (struct an_ltv_gen *)&sc->areq)) {
1999                                         error = EINVAL;
2000                                         break;
2001                                 }
2002                                 if (ireq->i_val == 0) {
2003                                         len = ssids->an_ssid1_len;
2004                                         tmpptr = ssids->an_ssid1;
2005                                 } else if (ireq->i_val == 1) {
2006                                         len = ssids->an_ssid2_len;
2007                                         tmpptr = ssids->an_ssid2;
2008                                 } else if (ireq->i_val == 2) {
2009                                         len = ssids->an_ssid3_len;
2010                                         tmpptr = ssids->an_ssid3;
2011                                 } else {
2012                                         error = EINVAL;
2013                                         break;
2014                                 }
2015                         } else {
2016                                 error = EINVAL;
2017                                 break;
2018                         }
2019                         if (len > IEEE80211_NWID_LEN) {
2020                                 error = EINVAL;
2021                                 break;
2022                         }
2023                         ireq->i_len = len;
2024                         bzero(tmpstr, IEEE80211_NWID_LEN);
2025                         bcopy(tmpptr, tmpstr, len);
2026                         error = copyout(tmpstr, ireq->i_data,
2027                             IEEE80211_NWID_LEN);
2028                         break;
2029                 case IEEE80211_IOC_NUMSSIDS:
2030                         ireq->i_val = 3;
2031                         break;
2032                 case IEEE80211_IOC_WEP:
2033                         sc->areq.an_type = AN_RID_ACTUALCFG;
2034                         if (an_read_record(sc,
2035                             (struct an_ltv_gen *)&sc->areq)) {
2036                                 error = EINVAL;
2037                                 break;
2038                         }
2039                         if (config->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) {
2040                                 if (config->an_authtype &
2041                                     AN_AUTHTYPE_ALLOW_UNENCRYPTED)
2042                                         ireq->i_val = IEEE80211_WEP_MIXED;
2043                                 else
2044                                         ireq->i_val = IEEE80211_WEP_ON;
2045                         } else {
2046                                 ireq->i_val = IEEE80211_WEP_OFF;
2047                         }
2048                         break;
2049                 case IEEE80211_IOC_WEPKEY:
2050                         /*
2051                          * XXX: I'm not entierly convinced this is
2052                          * correct, but it's what is implemented in
2053                          * ancontrol so it will have to do until we get
2054                          * access to actual Cisco code.
2055                          */
2056                         if (ireq->i_val < 0 || ireq->i_val > 8) {
2057                                 error = EINVAL;
2058                                 break;
2059                         }
2060                         len = 0;
2061                         if (ireq->i_val < 5) {
2062                                 sc->areq.an_type = AN_RID_WEP_TEMP;
2063                                 for (i = 0; i < 5; i++) {
2064                                         if (an_read_record(sc,
2065                                             (struct an_ltv_gen *)&sc->areq)) {
2066                                                 error = EINVAL;
2067                                                 break;
2068                                         }
2069                                         if (key->kindex == 0xffff)
2070                                                 break;
2071                                         if (key->kindex == ireq->i_val)
2072                                                 len = key->klen;
2073                                         /* Required to get next entry */
2074                                         sc->areq.an_type = AN_RID_WEP_PERM;
2075                                 }
2076                                 if (error != 0)
2077                                         break;
2078                         }
2079                         /* We aren't allowed to read the value of the
2080                          * key from the card so we just output zeros
2081                          * like we would if we could read the card, but
2082                          * denied the user access.
2083                          */
2084                         bzero(tmpstr, len);
2085                         ireq->i_len = len;
2086                         error = copyout(tmpstr, ireq->i_data, len);
2087                         break;
2088                 case IEEE80211_IOC_NUMWEPKEYS:
2089                         ireq->i_val = 9; /* include home key */
2090                         break;
2091                 case IEEE80211_IOC_WEPTXKEY:
2092                         /*
2093                          * For some strange reason, you have to read all
2094                          * keys before you can read the txkey.
2095                          */
2096                         sc->areq.an_type = AN_RID_WEP_TEMP;
2097                         for (i = 0; i < 5; i++) {
2098                                 if (an_read_record(sc,
2099                                     (struct an_ltv_gen *) &sc->areq)) {
2100                                         error = EINVAL;
2101                                         break;
2102                                 }
2103                                 if (key->kindex == 0xffff)
2104                                         break;
2105                                 /* Required to get next entry */
2106                                 sc->areq.an_type = AN_RID_WEP_PERM;
2107                         }
2108                         if (error != 0)
2109                                 break;
2110
2111                         sc->areq.an_type = AN_RID_WEP_PERM;
2112                         key->kindex = 0xffff;
2113                         if (an_read_record(sc,
2114                             (struct an_ltv_gen *)&sc->areq)) {
2115                                 error = EINVAL;
2116                                 break;
2117                         }
2118                         ireq->i_val = key->mac[0];
2119                         /*
2120                          * Check for home mode.  Map home mode into
2121                          * 5th key since that is how it is stored on
2122                          * the card
2123                          */
2124                         sc->areq.an_len  = sizeof(struct an_ltv_genconfig);
2125                         sc->areq.an_type = AN_RID_GENCONFIG;
2126                         if (an_read_record(sc,
2127                             (struct an_ltv_gen *)&sc->areq)) {
2128                                 error = EINVAL;
2129                                 break;
2130                         }
2131                         if (config->an_home_product & AN_HOME_NETWORK)
2132                                 ireq->i_val = 4;
2133                         break;
2134                 case IEEE80211_IOC_AUTHMODE:
2135                         sc->areq.an_type = AN_RID_ACTUALCFG;
2136                         if (an_read_record(sc,
2137                             (struct an_ltv_gen *)&sc->areq)) {
2138                                 error = EINVAL;
2139                                 break;
2140                         }
2141                         if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
2142                             AN_AUTHTYPE_NONE) {
2143                             ireq->i_val = IEEE80211_AUTH_NONE;
2144                         } else if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
2145                             AN_AUTHTYPE_OPEN) {
2146                             ireq->i_val = IEEE80211_AUTH_OPEN;
2147                         } else if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
2148                             AN_AUTHTYPE_SHAREDKEY) {
2149                             ireq->i_val = IEEE80211_AUTH_SHARED;
2150                         } else
2151                                 error = EINVAL;
2152                         break;
2153                 case IEEE80211_IOC_STATIONNAME:
2154                         sc->areq.an_type = AN_RID_ACTUALCFG;
2155                         if (an_read_record(sc,
2156                             (struct an_ltv_gen *)&sc->areq)) {
2157                                 error = EINVAL;
2158                                 break;
2159                         }
2160                         ireq->i_len = sizeof(config->an_nodename);
2161                         tmpptr = config->an_nodename;
2162                         bzero(tmpstr, IEEE80211_NWID_LEN);
2163                         bcopy(tmpptr, tmpstr, ireq->i_len);
2164                         error = copyout(tmpstr, ireq->i_data,
2165                             IEEE80211_NWID_LEN);
2166                         break;
2167                 case IEEE80211_IOC_CHANNEL:
2168                         sc->areq.an_type = AN_RID_STATUS;
2169                         if (an_read_record(sc,
2170                             (struct an_ltv_gen *)&sc->areq)) {
2171                                 error = EINVAL;
2172                                 break;
2173                         }
2174                         ireq->i_val = status->an_cur_channel;
2175                         break;
2176                 case IEEE80211_IOC_POWERSAVE:
2177                         sc->areq.an_type = AN_RID_ACTUALCFG;
2178                         if (an_read_record(sc,
2179                             (struct an_ltv_gen *)&sc->areq)) {
2180                                 error = EINVAL;
2181                                 break;
2182                         }
2183                         if (config->an_psave_mode == AN_PSAVE_NONE) {
2184                                 ireq->i_val = IEEE80211_POWERSAVE_OFF;
2185                         } else if (config->an_psave_mode == AN_PSAVE_CAM) {
2186                                 ireq->i_val = IEEE80211_POWERSAVE_CAM;
2187                         } else if (config->an_psave_mode == AN_PSAVE_PSP) {
2188                                 ireq->i_val = IEEE80211_POWERSAVE_PSP;
2189                         } else if (config->an_psave_mode == AN_PSAVE_PSP_CAM) {
2190                                 ireq->i_val = IEEE80211_POWERSAVE_PSP_CAM;
2191                         } else
2192                                 error = EINVAL;
2193                         break;
2194                 case IEEE80211_IOC_POWERSAVESLEEP:
2195                         sc->areq.an_type = AN_RID_ACTUALCFG;
2196                         if (an_read_record(sc,
2197                             (struct an_ltv_gen *)&sc->areq)) {
2198                                 error = EINVAL;
2199                                 break;
2200                         }
2201                         ireq->i_val = config->an_listen_interval;
2202                         break;
2203                 }
2204                 break;
2205         case SIOCS80211:
2206                 if ((error = suser(td)))
2207                         goto out;
2208                 sc->areq.an_len = sizeof(sc->areq);
2209                 /*
2210                  * We need a config structure for everything but the WEP
2211                  * key management and SSIDs so we get it now so avoid
2212                  * duplicating this code every time.
2213                  */
2214                 if (ireq->i_type != IEEE80211_IOC_SSID &&
2215                     ireq->i_type != IEEE80211_IOC_WEPKEY &&
2216                     ireq->i_type != IEEE80211_IOC_WEPTXKEY) {
2217                         sc->areq.an_type = AN_RID_GENCONFIG;
2218                         if (an_read_record(sc,
2219                             (struct an_ltv_gen *)&sc->areq)) {
2220                                 error = EINVAL;
2221                                 break;
2222                         }
2223                 }
2224                 switch (ireq->i_type) {
2225                 case IEEE80211_IOC_SSID:
2226                         sc->areq.an_type = AN_RID_SSIDLIST;
2227                         if (an_read_record(sc,
2228                             (struct an_ltv_gen *)&sc->areq)) {
2229                                 error = EINVAL;
2230                                 break;
2231                         }
2232                         if (ireq->i_len > IEEE80211_NWID_LEN) {
2233                                 error = EINVAL;
2234                                 break;
2235                         }
2236                         switch (ireq->i_val) {
2237                         case 0:
2238                                 error = copyin(ireq->i_data,
2239                                     ssids->an_ssid1, ireq->i_len);
2240                                 ssids->an_ssid1_len = ireq->i_len;
2241                                 break;
2242                         case 1:
2243                                 error = copyin(ireq->i_data,
2244                                     ssids->an_ssid2, ireq->i_len);
2245                                 ssids->an_ssid2_len = ireq->i_len;
2246                                 break;
2247                         case 2:
2248                                 error = copyin(ireq->i_data,
2249                                     ssids->an_ssid3, ireq->i_len);
2250                                 ssids->an_ssid3_len = ireq->i_len;
2251                                 break;
2252                         default:
2253                                 error = EINVAL;
2254                                 break;
2255                         }
2256                         break;
2257                 case IEEE80211_IOC_WEP:
2258                         switch (ireq->i_val) {
2259                         case IEEE80211_WEP_OFF:
2260                                 config->an_authtype &=
2261                                     ~(AN_AUTHTYPE_PRIVACY_IN_USE |
2262                                     AN_AUTHTYPE_ALLOW_UNENCRYPTED);
2263                                 break;
2264                         case IEEE80211_WEP_ON:
2265                                 config->an_authtype |=
2266                                     AN_AUTHTYPE_PRIVACY_IN_USE;
2267                                 config->an_authtype &=
2268                                     ~AN_AUTHTYPE_ALLOW_UNENCRYPTED;
2269                                 break;
2270                         case IEEE80211_WEP_MIXED:
2271                                 config->an_authtype |=
2272                                     AN_AUTHTYPE_PRIVACY_IN_USE |
2273                                     AN_AUTHTYPE_ALLOW_UNENCRYPTED;
2274                                 break;
2275                         default:
2276                                 error = EINVAL;
2277                                 break;
2278                         }
2279                         break;
2280                 case IEEE80211_IOC_WEPKEY:
2281                         if (ireq->i_val < 0 || ireq->i_val > 8 ||
2282                             ireq->i_len > 13) {
2283                                 error = EINVAL;
2284                                 break;
2285                         }
2286                         error = copyin(ireq->i_data, tmpstr, 13);
2287                         if (error != 0)
2288                                 break;
2289                         /*
2290                          * Map the 9th key into the home mode
2291                          * since that is how it is stored on
2292                          * the card
2293                          */
2294                         bzero(&sc->areq, sizeof(struct an_ltv_key));
2295                         sc->areq.an_len = sizeof(struct an_ltv_key);
2296                         key->mac[0] = 1;        /* The others are 0. */
2297                         if (ireq->i_val < 4) {
2298                                 sc->areq.an_type = AN_RID_WEP_TEMP;
2299                                 key->kindex = ireq->i_val;
2300                         } else {
2301                                 sc->areq.an_type = AN_RID_WEP_PERM;
2302                                 key->kindex = ireq->i_val - 4;
2303                         }
2304                         key->klen = ireq->i_len;
2305                         bcopy(tmpstr, key->key, key->klen);
2306                         break;
2307                 case IEEE80211_IOC_WEPTXKEY:
2308                         if (ireq->i_val < 0 || ireq->i_val > 4) {
2309                                 error = EINVAL;
2310                                 break;
2311                         }
2312
2313                         /*
2314                          * Map the 5th key into the home mode
2315                          * since that is how it is stored on
2316                          * the card
2317                          */
2318                         sc->areq.an_len  = sizeof(struct an_ltv_genconfig);
2319                         sc->areq.an_type = AN_RID_ACTUALCFG;
2320                         if (an_read_record(sc,
2321                             (struct an_ltv_gen *)&sc->areq)) {
2322                                 error = EINVAL;
2323                                 break;
2324                         }
2325                         if (ireq->i_val ==  4) {
2326                                 config->an_home_product |= AN_HOME_NETWORK;
2327                                 ireq->i_val = 0;
2328                         } else {
2329                                 config->an_home_product &= ~AN_HOME_NETWORK;
2330                         }
2331
2332                         sc->an_config.an_home_product
2333                                 = config->an_home_product;
2334
2335                         /* update configuration */
2336                         an_init(sc);
2337
2338                         bzero(&sc->areq, sizeof(struct an_ltv_key));
2339                         sc->areq.an_len = sizeof(struct an_ltv_key);
2340                         sc->areq.an_type = AN_RID_WEP_PERM;
2341                         key->kindex = 0xffff;
2342                         key->mac[0] = ireq->i_val;
2343                         break;
2344                 case IEEE80211_IOC_AUTHMODE:
2345                         switch (ireq->i_val) {
2346                         case IEEE80211_AUTH_NONE:
2347                                 config->an_authtype = AN_AUTHTYPE_NONE |
2348                                     (config->an_authtype & ~AN_AUTHTYPE_MASK);
2349                                 break;
2350                         case IEEE80211_AUTH_OPEN:
2351                                 config->an_authtype = AN_AUTHTYPE_OPEN |
2352                                     (config->an_authtype & ~AN_AUTHTYPE_MASK);
2353                                 break;
2354                         case IEEE80211_AUTH_SHARED:
2355                                 config->an_authtype = AN_AUTHTYPE_SHAREDKEY |
2356                                     (config->an_authtype & ~AN_AUTHTYPE_MASK);
2357                                 break;
2358                         default:
2359                                 error = EINVAL;
2360                         }
2361                         break;
2362                 case IEEE80211_IOC_STATIONNAME:
2363                         if (ireq->i_len > 16) {
2364                                 error = EINVAL;
2365                                 break;
2366                         }
2367                         bzero(config->an_nodename, 16);
2368                         error = copyin(ireq->i_data,
2369                             config->an_nodename, ireq->i_len);
2370                         break;
2371                 case IEEE80211_IOC_CHANNEL:
2372                         /*
2373                          * The actual range is 1-14, but if you set it
2374                          * to 0 you get the default so we let that work
2375                          * too.
2376                          */
2377                         if (ireq->i_val < 0 || ireq->i_val >14) {
2378                                 error = EINVAL;
2379                                 break;
2380                         }
2381                         config->an_ds_channel = ireq->i_val;
2382                         break;
2383                 case IEEE80211_IOC_POWERSAVE:
2384                         switch (ireq->i_val) {
2385                         case IEEE80211_POWERSAVE_OFF:
2386                                 config->an_psave_mode = AN_PSAVE_NONE;
2387                                 break;
2388                         case IEEE80211_POWERSAVE_CAM:
2389                                 config->an_psave_mode = AN_PSAVE_CAM;
2390                                 break;
2391                         case IEEE80211_POWERSAVE_PSP:
2392                                 config->an_psave_mode = AN_PSAVE_PSP;
2393                                 break;
2394                         case IEEE80211_POWERSAVE_PSP_CAM:
2395                                 config->an_psave_mode = AN_PSAVE_PSP_CAM;
2396                                 break;
2397                         default:
2398                                 error = EINVAL;
2399                                 break;
2400                         }
2401                         break;
2402                 case IEEE80211_IOC_POWERSAVESLEEP:
2403                         config->an_listen_interval = ireq->i_val;
2404                         break;
2405                 }
2406
2407                 if (!error)
2408                         an_setdef(sc, &sc->areq);
2409                 break;
2410         default:
2411                 error = EINVAL;
2412                 break;
2413         }
2414 out:
2415         splx(s);
2416
2417         return(error != 0);
2418 }
2419
2420 static int
2421 an_init_tx_ring(sc)
2422         struct an_softc         *sc;
2423 {
2424         int                     i;
2425         int                     id;
2426
2427         if (sc->an_gone)
2428                 return (0);
2429
2430         if (!sc->mpi350) {
2431                 for (i = 0; i < AN_TX_RING_CNT; i++) {
2432                         if (an_alloc_nicmem(sc, 1518 +
2433                             0x44, &id))
2434                                 return(ENOMEM);
2435                         sc->an_rdata.an_tx_fids[i] = id;
2436                         sc->an_rdata.an_tx_ring[i] = 0;
2437                 }
2438         }
2439
2440         sc->an_rdata.an_tx_prod = 0;
2441         sc->an_rdata.an_tx_cons = 0;
2442         sc->an_rdata.an_tx_empty = 1;
2443
2444         return(0);
2445 }
2446
2447 static void
2448 an_init(xsc)
2449         void                    *xsc;
2450 {
2451         struct an_softc         *sc = xsc;
2452         struct ifnet            *ifp = &sc->arpcom.ac_if;
2453         int                     s;
2454
2455         s = splimp();
2456
2457         if (sc->an_gone) {
2458                 splx(s);
2459                 return;
2460         }
2461
2462         if (ifp->if_flags & IFF_RUNNING)
2463                 an_stop(sc);
2464
2465         sc->an_associated = 0;
2466
2467         /* Allocate the TX buffers */
2468         if (an_init_tx_ring(sc)) {
2469                 an_reset(sc);
2470                 if (sc->mpi350)
2471                         an_init_mpi350_desc(sc);        
2472                 if (an_init_tx_ring(sc)) {
2473                         printf("an%d: tx buffer allocation "
2474                             "failed\n", sc->an_unit);
2475                         splx(s);
2476                         return;
2477                 }
2478         }
2479
2480         /* Set our MAC address. */
2481         bcopy((char *)&sc->arpcom.ac_enaddr,
2482             (char *)&sc->an_config.an_macaddr, ETHER_ADDR_LEN);
2483
2484         if (ifp->if_flags & IFF_BROADCAST)
2485                 sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR;
2486         else
2487                 sc->an_config.an_rxmode = AN_RXMODE_ADDR;
2488
2489         if (ifp->if_flags & IFF_MULTICAST)
2490                 sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR;
2491
2492         if (ifp->if_flags & IFF_PROMISC) {
2493                 if (sc->an_monitor & AN_MONITOR) {
2494                         if (sc->an_monitor & AN_MONITOR_ANY_BSS) {
2495                                 sc->an_config.an_rxmode |=
2496                                     AN_RXMODE_80211_MONITOR_ANYBSS |
2497                                     AN_RXMODE_NO_8023_HEADER;
2498                         } else {
2499                                 sc->an_config.an_rxmode |=
2500                                     AN_RXMODE_80211_MONITOR_CURBSS |
2501                                     AN_RXMODE_NO_8023_HEADER;
2502                         }
2503                 }
2504         }
2505
2506         if (sc->an_have_rssimap)
2507                 sc->an_config.an_rxmode |= AN_RXMODE_NORMALIZED_RSSI;
2508
2509         /* Set the ssid list */
2510         sc->an_ssidlist.an_type = AN_RID_SSIDLIST;
2511         sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist);
2512         if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) {
2513                 printf("an%d: failed to set ssid list\n", sc->an_unit);
2514                 splx(s);
2515                 return;
2516         }
2517
2518         /* Set the AP list */
2519         sc->an_aplist.an_type = AN_RID_APLIST;
2520         sc->an_aplist.an_len = sizeof(struct an_ltv_aplist);
2521         if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) {
2522                 printf("an%d: failed to set AP list\n", sc->an_unit);
2523                 splx(s);
2524                 return;
2525         }
2526
2527         /* Set the configuration in the NIC */
2528         sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
2529         sc->an_config.an_type = AN_RID_GENCONFIG;
2530         if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
2531                 printf("an%d: failed to set configuration\n", sc->an_unit);
2532                 splx(s);
2533                 return;
2534         }
2535
2536         /* Enable the MAC */
2537         if (an_cmd(sc, AN_CMD_ENABLE, 0)) {
2538                 printf("an%d: failed to enable MAC\n", sc->an_unit);
2539                 splx(s);
2540                 return;
2541         }
2542
2543         if (ifp->if_flags & IFF_PROMISC)
2544                 an_cmd(sc, AN_CMD_SET_MODE, 0xffff);
2545
2546         /* enable interrupts */
2547         CSR_WRITE_2(sc, AN_INT_EN(sc->mpi350), AN_INTRS);
2548
2549         ifp->if_flags |= IFF_RUNNING;
2550         ifp->if_flags &= ~IFF_OACTIVE;
2551
2552         sc->an_stat_ch = timeout(an_stats_update, sc, hz);
2553         splx(s);
2554
2555         return;
2556 }
2557
2558 static void
2559 an_start(ifp)
2560         struct ifnet            *ifp;
2561 {
2562         struct an_softc         *sc;
2563         struct mbuf             *m0 = NULL;
2564         struct an_txframe_802_3 tx_frame_802_3;
2565         struct ether_header     *eh;
2566         int                     id, idx, i;
2567         unsigned char           txcontrol;
2568         struct an_card_tx_desc an_tx_desc;
2569         u_int8_t                *ptr;
2570         u_int8_t                *buf;
2571
2572         sc = ifp->if_softc;
2573
2574         if (sc->an_gone)
2575                 return;
2576
2577         if (ifp->if_flags & IFF_OACTIVE)
2578                 return;
2579
2580         if (!sc->an_associated)
2581                 return;
2582
2583         /* We can't send in monitor mode so toss any attempts. */
2584         if (sc->an_monitor && (ifp->if_flags & IFF_PROMISC)) {
2585                 for (;;) {
2586                         IF_DEQUEUE(&ifp->if_snd, m0);
2587                         if (m0 == NULL)
2588                                 break;
2589                         m_freem(m0);
2590                 }
2591                 return;
2592         }
2593
2594         idx = sc->an_rdata.an_tx_prod;
2595
2596         if (!sc->mpi350) {
2597                 bzero((char *)&tx_frame_802_3, sizeof(tx_frame_802_3));
2598
2599                 while (sc->an_rdata.an_tx_ring[idx] == 0) {
2600                         IF_DEQUEUE(&ifp->if_snd, m0);
2601                         if (m0 == NULL)
2602                                 break;
2603
2604                         id = sc->an_rdata.an_tx_fids[idx];
2605                         eh = mtod(m0, struct ether_header *);
2606
2607                         bcopy((char *)&eh->ether_dhost,
2608                               (char *)&tx_frame_802_3.an_tx_dst_addr, 
2609                               ETHER_ADDR_LEN);
2610                         bcopy((char *)&eh->ether_shost,
2611                               (char *)&tx_frame_802_3.an_tx_src_addr, 
2612                               ETHER_ADDR_LEN);
2613
2614                         /* minus src/dest mac & type */
2615                         tx_frame_802_3.an_tx_802_3_payload_len =
2616                                 m0->m_pkthdr.len - 12;  
2617
2618                         m_copydata(m0, sizeof(struct ether_header) - 2 ,
2619                                    tx_frame_802_3.an_tx_802_3_payload_len,
2620                                    (caddr_t)&sc->an_txbuf);
2621
2622                         txcontrol = AN_TXCTL_8023;
2623                         /* write the txcontrol only */
2624                         an_write_data(sc, id, 0x08, (caddr_t)&txcontrol,
2625                                       sizeof(txcontrol));
2626
2627                         /* 802_3 header */
2628                         an_write_data(sc, id, 0x34, (caddr_t)&tx_frame_802_3,
2629                                       sizeof(struct an_txframe_802_3));
2630
2631                         /* in mbuf header type is just before payload */
2632                         an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf,
2633                                       tx_frame_802_3.an_tx_802_3_payload_len);
2634
2635                         /*
2636                          * If there's a BPF listner, bounce a copy of
2637                          * this frame to him.
2638                          */
2639                         if (ifp->if_bpf)
2640                                 bpf_mtap(ifp, m0);
2641
2642                         m_freem(m0);
2643                         m0 = NULL;
2644
2645                         sc->an_rdata.an_tx_ring[idx] = id;
2646                         if (an_cmd(sc, AN_CMD_TX, id))
2647                                 printf("an%d: xmit failed\n", sc->an_unit);
2648
2649                         AN_INC(idx, AN_TX_RING_CNT);
2650                 }
2651         } else { /* MPI-350 */
2652                 while (sc->an_rdata.an_tx_empty ||
2653                     idx != sc->an_rdata.an_tx_cons) {
2654                         IF_DEQUEUE(&ifp->if_snd, m0);
2655                         if (m0 == NULL) {
2656                                 break;
2657                         }
2658                         buf = sc->an_tx_buffer[idx].an_dma_vaddr;
2659
2660                         eh = mtod(m0, struct ether_header *);
2661
2662                         /* DJA optimize this to limit bcopy */
2663                         bcopy((char *)&eh->ether_dhost,
2664                               (char *)&tx_frame_802_3.an_tx_dst_addr, 
2665                               ETHER_ADDR_LEN);
2666                         bcopy((char *)&eh->ether_shost,
2667                               (char *)&tx_frame_802_3.an_tx_src_addr, 
2668                               ETHER_ADDR_LEN);
2669
2670                         /* minus src/dest mac & type */
2671                         tx_frame_802_3.an_tx_802_3_payload_len =
2672                                 m0->m_pkthdr.len - 12; 
2673
2674                         m_copydata(m0, sizeof(struct ether_header) - 2 ,
2675                                    tx_frame_802_3.an_tx_802_3_payload_len,
2676                                    (caddr_t)&sc->an_txbuf);
2677
2678                         txcontrol = AN_TXCTL_8023;
2679                         /* write the txcontrol only */
2680                         bcopy((caddr_t)&txcontrol, &buf[0x08],
2681                               sizeof(txcontrol));
2682
2683                         /* 802_3 header */
2684                         bcopy((caddr_t)&tx_frame_802_3, &buf[0x34],
2685                               sizeof(struct an_txframe_802_3));
2686
2687                         /* in mbuf header type is just before payload */
2688                         bcopy((caddr_t)&sc->an_txbuf, &buf[0x44],
2689                               tx_frame_802_3.an_tx_802_3_payload_len);
2690
2691
2692                         bzero(&an_tx_desc, sizeof(an_tx_desc));
2693                         an_tx_desc.an_offset = 0;
2694                         an_tx_desc.an_eoc = 1;
2695                         an_tx_desc.an_valid = 1;
2696                         an_tx_desc.an_len =  0x44 +
2697                                 tx_frame_802_3.an_tx_802_3_payload_len;
2698                         an_tx_desc.an_phys = sc->an_tx_buffer[idx].an_dma_paddr;
2699                         ptr = (u_int8_t*)&an_tx_desc;
2700                         for (i = 0; i < sizeof(an_tx_desc); i++) {
2701                                 CSR_MEM_AUX_WRITE_1(sc, AN_TX_DESC_OFFSET + i,
2702                                                     ptr[i]);
2703                         }
2704
2705                         /*
2706                          * If there's a BPF listner, bounce a copy of
2707                          * this frame to him.
2708                          */
2709                         if (ifp->if_bpf)
2710                                 bpf_mtap(ifp, m0);
2711
2712                         m_freem(m0);
2713                         m0 = NULL;
2714
2715                         CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), AN_EV_ALLOC);
2716
2717                         AN_INC(idx, AN_MAX_TX_DESC);
2718                         sc->an_rdata.an_tx_empty = 0;
2719                 }
2720         }
2721
2722         if (m0 != NULL)
2723                 ifp->if_flags |= IFF_OACTIVE;
2724
2725         sc->an_rdata.an_tx_prod = idx;
2726
2727         /*
2728          * Set a timeout in case the chip goes out to lunch.
2729          */
2730         ifp->if_timer = 5;
2731
2732         return;
2733 }
2734
2735 void
2736 an_stop(sc)
2737         struct an_softc         *sc;
2738 {
2739         struct ifnet            *ifp;
2740         int                     i;
2741         int                     s;
2742
2743         s = splimp();
2744
2745         if (sc->an_gone) {
2746                 splx(s);
2747                 return;
2748         }
2749
2750         ifp = &sc->arpcom.ac_if;
2751
2752         an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0);
2753         CSR_WRITE_2(sc, AN_INT_EN(sc->mpi350), 0);
2754         an_cmd(sc, AN_CMD_DISABLE, 0);
2755
2756         for (i = 0; i < AN_TX_RING_CNT; i++)
2757                 an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]);
2758
2759         untimeout(an_stats_update, sc, sc->an_stat_ch);
2760
2761         ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
2762
2763         if (sc->an_flash_buffer) {
2764                 free(sc->an_flash_buffer, M_DEVBUF);
2765                 sc->an_flash_buffer = NULL;
2766         }
2767
2768         splx(s);
2769
2770         return;
2771 }
2772
2773 static void
2774 an_watchdog(ifp)
2775         struct ifnet            *ifp;
2776 {
2777         struct an_softc         *sc;
2778         int                     s;
2779
2780         sc = ifp->if_softc;
2781         s = splimp();
2782
2783         if (sc->an_gone) {
2784                 splx(s);
2785                 return;
2786         }
2787
2788         printf("an%d: device timeout\n", sc->an_unit);
2789
2790         an_reset(sc);
2791         if (sc->mpi350)
2792                 an_init_mpi350_desc(sc);        
2793         an_init(sc);
2794
2795         ifp->if_oerrors++;
2796         splx(s);
2797
2798         return;
2799 }
2800
2801 void
2802 an_shutdown(dev)
2803         device_t                dev;
2804 {
2805         struct an_softc         *sc;
2806
2807         sc = device_get_softc(dev);
2808         an_stop(sc);
2809
2810         return;
2811 }
2812
2813 void
2814 an_resume(dev)
2815         device_t                dev;
2816 {
2817         struct an_softc         *sc;
2818         struct ifnet            *ifp;
2819         int                     i;
2820
2821         sc = device_get_softc(dev);
2822         ifp = &sc->arpcom.ac_if;
2823
2824         an_reset(sc);
2825         if (sc->mpi350)
2826                 an_init_mpi350_desc(sc);        
2827         an_init(sc);
2828
2829         /* Recovery temporary keys */
2830         for (i = 0; i < 4; i++) {
2831                 sc->areq.an_type = AN_RID_WEP_TEMP;
2832                 sc->areq.an_len = sizeof(struct an_ltv_key);            
2833                 bcopy(&sc->an_temp_keys[i],
2834                     &sc->areq, sizeof(struct an_ltv_key));
2835                 an_setdef(sc, &sc->areq);
2836         }
2837
2838         if (ifp->if_flags & IFF_UP)
2839                 an_start(ifp);
2840
2841         return;
2842 }
2843
2844 #ifdef ANCACHE
2845 /* Aironet signal strength cache code.
2846  * store signal/noise/quality on per MAC src basis in
2847  * a small fixed cache.  The cache wraps if > MAX slots
2848  * used.  The cache may be zeroed out to start over.
2849  * Two simple filters exist to reduce computation:
2850  * 1. ip only (literally 0x800, ETHERTYPE_IP) which may be used
2851  * to ignore some packets.  It defaults to ip only.
2852  * it could be used to focus on broadcast, non-IP 802.11 beacons.
2853  * 2. multicast/broadcast only.  This may be used to
2854  * ignore unicast packets and only cache signal strength
2855  * for multicast/broadcast packets (beacons); e.g., Mobile-IP
2856  * beacons and not unicast traffic.
2857  *
2858  * The cache stores (MAC src(index), IP src (major clue), signal,
2859  *      quality, noise)
2860  *
2861  * No apologies for storing IP src here.  It's easy and saves much
2862  * trouble elsewhere.  The cache is assumed to be INET dependent,
2863  * although it need not be.
2864  *
2865  * Note: the Aironet only has a single byte of signal strength value
2866  * in the rx frame header, and it's not scaled to anything sensible.
2867  * This is kind of lame, but it's all we've got.
2868  */
2869
2870 #ifdef documentation
2871
2872 int an_sigitems;                                /* number of cached entries */
2873 struct an_sigcache an_sigcache[MAXANCACHE];  /*  array of cache entries */
2874 int an_nextitem;                                /*  index/# of entries */
2875
2876
2877 #endif
2878
2879 /* control variables for cache filtering.  Basic idea is
2880  * to reduce cost (e.g., to only Mobile-IP agent beacons
2881  * which are broadcast or multicast).  Still you might
2882  * want to measure signal strength anth unicast ping packets
2883  * on a pt. to pt. ant. setup.
2884  */
2885 /* set true if you want to limit cache items to broadcast/mcast
2886  * only packets (not unicast).  Useful for mobile-ip beacons which
2887  * are broadcast/multicast at network layer.  Default is all packets
2888  * so ping/unicast anll work say anth pt. to pt. antennae setup.
2889  */
2890 static int an_cache_mcastonly = 0;
2891 SYSCTL_INT(_hw_an, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW,
2892         &an_cache_mcastonly, 0, "");
2893
2894 /* set true if you want to limit cache items to IP packets only
2895 */
2896 static int an_cache_iponly = 1;
2897 SYSCTL_INT(_hw_an, OID_AUTO, an_cache_iponly, CTLFLAG_RW,
2898         &an_cache_iponly, 0, "");
2899
2900 /*
2901  * an_cache_store, per rx packet store signal
2902  * strength in MAC (src) indexed cache.
2903  */
2904 static void
2905 an_cache_store (sc, eh, m, rx_rssi, rx_quality)
2906         struct an_softc *sc;
2907         struct ether_header *eh;
2908         struct mbuf *m;
2909         u_int8_t rx_rssi;
2910         u_int8_t rx_quality;
2911 {
2912         struct ip *ip = 0;
2913         int i;
2914         static int cache_slot = 0;      /* use this cache entry */
2915         static int wrapindex = 0;       /* next "free" cache entry */
2916         int type_ipv4 = 0;
2917
2918         /* filters:
2919          * 1. ip only
2920          * 2. configurable filter to throw out unicast packets,
2921          * keep multicast only.
2922          */
2923
2924         if ((ntohs(eh->ether_type) == ETHERTYPE_IP)) {
2925                 type_ipv4 = 1;
2926         }
2927
2928         /* filter for ip packets only
2929         */
2930         if ( an_cache_iponly && !type_ipv4) {
2931                 return;
2932         }
2933
2934         /* filter for broadcast/multicast only
2935          */
2936         if (an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
2937                 return;
2938         }
2939
2940 #ifdef SIGDEBUG
2941         printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n",
2942                 rx_rssi & 0xffff, rx_rssi >> 8, rx_rssi & 0xff);
2943 #endif
2944
2945         /* find the ip header.  we want to store the ip_src
2946          * address.
2947          */
2948         if (type_ipv4) {
2949                 ip = mtod(m, struct ip *);
2950         }
2951
2952         /* do a linear search for a matching MAC address
2953          * in the cache table
2954          * . MAC address is 6 bytes,
2955          * . var w_nextitem holds total number of entries already cached
2956          */
2957         for (i = 0; i < sc->an_nextitem; i++) {
2958                 if (! bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc,  6 )) {
2959                         /* Match!,
2960                          * so we already have this entry,
2961                          * update the data
2962                          */
2963                         break;
2964                 }
2965         }
2966
2967         /* did we find a matching mac address?
2968          * if yes, then overwrite a previously existing cache entry
2969          */
2970         if (i < sc->an_nextitem )   {
2971                 cache_slot = i;
2972         }
2973         /* else, have a new address entry,so
2974          * add this new entry,
2975          * if table full, then we need to replace LRU entry
2976          */
2977         else    {
2978
2979                 /* check for space in cache table
2980                  * note: an_nextitem also holds number of entries
2981                  * added in the cache table
2982                  */
2983                 if ( sc->an_nextitem < MAXANCACHE ) {
2984                         cache_slot = sc->an_nextitem;
2985                         sc->an_nextitem++;
2986                         sc->an_sigitems = sc->an_nextitem;
2987                 }
2988                 /* no space found, so simply wrap anth wrap index
2989                  * and "zap" the next entry
2990                  */
2991                 else {
2992                         if (wrapindex == MAXANCACHE) {
2993                                 wrapindex = 0;
2994                         }
2995                         cache_slot = wrapindex++;
2996                 }
2997         }
2998
2999         /* invariant: cache_slot now points at some slot
3000          * in cache.
3001          */
3002         if (cache_slot < 0 || cache_slot >= MAXANCACHE) {
3003                 log(LOG_ERR, "an_cache_store, bad index: %d of "
3004                     "[0..%d], gross cache error\n",
3005                     cache_slot, MAXANCACHE);
3006                 return;
3007         }
3008
3009         /*  store items in cache
3010          *  .ip source address
3011          *  .mac src
3012          *  .signal, etc.
3013          */
3014         if (type_ipv4) {
3015                 sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
3016         }
3017         bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc,  6);
3018
3019
3020         switch (an_cache_mode) {
3021         case DBM:
3022                 if (sc->an_have_rssimap) {
3023                         sc->an_sigcache[cache_slot].signal = 
3024                                 - sc->an_rssimap.an_entries[rx_rssi].an_rss_dbm;
3025                         sc->an_sigcache[cache_slot].quality = 
3026                                 - sc->an_rssimap.an_entries[rx_quality].an_rss_dbm;
3027                 } else {
3028                         sc->an_sigcache[cache_slot].signal = rx_rssi - 100;
3029                         sc->an_sigcache[cache_slot].quality = rx_quality - 100;
3030                 }
3031                 break;
3032         case PERCENT:
3033                 if (sc->an_have_rssimap) {
3034                         sc->an_sigcache[cache_slot].signal = 
3035                                 sc->an_rssimap.an_entries[rx_rssi].an_rss_pct;
3036                         sc->an_sigcache[cache_slot].quality = 
3037                                 sc->an_rssimap.an_entries[rx_quality].an_rss_pct;
3038                 } else {
3039                         if (rx_rssi > 100)
3040                                 rx_rssi = 100;
3041                         if (rx_quality > 100)
3042                                 rx_quality = 100;
3043                         sc->an_sigcache[cache_slot].signal = rx_rssi;
3044                         sc->an_sigcache[cache_slot].quality = rx_quality;
3045                 }
3046                 break;
3047         case RAW:
3048                 sc->an_sigcache[cache_slot].signal = rx_rssi;
3049                 sc->an_sigcache[cache_slot].quality = rx_quality;
3050                 break;
3051         }
3052
3053         sc->an_sigcache[cache_slot].noise = 0;
3054
3055         return;
3056 }
3057 #endif
3058
3059 static int
3060 an_media_change(ifp)
3061         struct ifnet            *ifp;
3062 {
3063         struct an_softc *sc = ifp->if_softc;
3064         struct an_ltv_genconfig *cfg;
3065         int otype = sc->an_config.an_opmode;
3066         int orate = sc->an_tx_rate;
3067
3068         if ((sc->an_ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0)
3069                 sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC;
3070         else
3071                 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION;
3072
3073         switch (IFM_SUBTYPE(sc->an_ifmedia.ifm_cur->ifm_media)) {
3074         case IFM_IEEE80211_DS1:
3075                 sc->an_tx_rate = AN_RATE_1MBPS;
3076                 break;
3077         case IFM_IEEE80211_DS2:
3078                 sc->an_tx_rate = AN_RATE_2MBPS;
3079                 break;
3080         case IFM_IEEE80211_DS5:
3081                 sc->an_tx_rate = AN_RATE_5_5MBPS;
3082                 break;
3083         case IFM_IEEE80211_DS11:
3084                 sc->an_tx_rate = AN_RATE_11MBPS;
3085                 break;
3086         case IFM_AUTO:
3087                 sc->an_tx_rate = 0;
3088                 break;
3089         }
3090
3091         if (orate != sc->an_tx_rate) {
3092                 /* Read the current configuration */
3093                 sc->an_config.an_type = AN_RID_GENCONFIG;
3094                 sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
3095                 an_read_record(sc, (struct an_ltv_gen *)&sc->an_config);
3096                 cfg = &sc->an_config;
3097
3098                 /* clear other rates and set the only one we want */
3099                 bzero(cfg->an_rates, sizeof(cfg->an_rates));
3100                 cfg->an_rates[0] = sc->an_tx_rate;
3101
3102                 /* Save the new rate */
3103                 sc->an_config.an_type = AN_RID_GENCONFIG;
3104                 sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
3105         }
3106
3107         if (otype != sc->an_config.an_opmode ||
3108             orate != sc->an_tx_rate)
3109                 an_init(sc);
3110
3111         return(0);
3112 }
3113
3114 static void
3115 an_media_status(ifp, imr)
3116         struct ifnet            *ifp;
3117         struct ifmediareq       *imr;
3118 {
3119         struct an_ltv_status    status;
3120         struct an_softc         *sc = ifp->if_softc;
3121
3122         status.an_len = sizeof(status);
3123         status.an_type = AN_RID_STATUS;
3124         if (an_read_record(sc, (struct an_ltv_gen *)&status)) {
3125                 /* If the status read fails, just lie. */
3126                 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media;
3127                 imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
3128         }
3129
3130         if (sc->an_tx_rate == 0) {
3131                 imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
3132                 if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC)
3133                         imr->ifm_active |= IFM_IEEE80211_ADHOC;
3134                 switch (status.an_current_tx_rate) {
3135                 case AN_RATE_1MBPS:
3136                         imr->ifm_active |= IFM_IEEE80211_DS1;
3137                         break;
3138                 case AN_RATE_2MBPS:
3139                         imr->ifm_active |= IFM_IEEE80211_DS2;
3140                         break;
3141                 case AN_RATE_5_5MBPS:
3142                         imr->ifm_active |= IFM_IEEE80211_DS5;
3143                         break;
3144                 case AN_RATE_11MBPS:
3145                         imr->ifm_active |= IFM_IEEE80211_DS11;
3146                         break;
3147                 }
3148         } else {
3149                 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media;
3150         }
3151
3152         imr->ifm_status = IFM_AVALID;
3153         if (status.an_opmode & AN_STATUS_OPMODE_ASSOCIATED)
3154                 imr->ifm_status |= IFM_ACTIVE;
3155 }
3156
3157 /********************** Cisco utility support routines *************/
3158
3159 /*
3160  * ReadRids & WriteRids derived from Cisco driver additions to Ben Reed's
3161  * Linux driver
3162  */
3163
3164 static int
3165 readrids(ifp, l_ioctl)
3166         struct ifnet   *ifp;
3167         struct aironet_ioctl *l_ioctl;
3168 {
3169         unsigned short  rid;
3170         struct an_softc *sc;
3171
3172         switch (l_ioctl->command) {
3173         case AIROGCAP:
3174                 rid = AN_RID_CAPABILITIES;
3175                 break;
3176         case AIROGCFG:
3177                 rid = AN_RID_GENCONFIG;
3178                 break;
3179         case AIROGSLIST:
3180                 rid = AN_RID_SSIDLIST;
3181                 break;
3182         case AIROGVLIST:
3183                 rid = AN_RID_APLIST;
3184                 break;
3185         case AIROGDRVNAM:
3186                 rid = AN_RID_DRVNAME;
3187                 break;
3188         case AIROGEHTENC:
3189                 rid = AN_RID_ENCAPPROTO;
3190                 break;
3191         case AIROGWEPKTMP:
3192                 rid = AN_RID_WEP_TEMP;
3193                 break;
3194         case AIROGWEPKNV:
3195                 rid = AN_RID_WEP_PERM;
3196                 break;
3197         case AIROGSTAT:
3198                 rid = AN_RID_STATUS;
3199                 break;
3200         case AIROGSTATSD32:
3201                 rid = AN_RID_32BITS_DELTA;
3202                 break;
3203         case AIROGSTATSC32:
3204                 rid = AN_RID_32BITS_CUM;
3205                 break;
3206         default:
3207                 rid = 999;
3208                 break;
3209         }
3210
3211         if (rid == 999) /* Is bad command */
3212                 return -EINVAL;
3213
3214         sc = ifp->if_softc;
3215         sc->areq.an_len  = AN_MAX_DATALEN;
3216         sc->areq.an_type = rid;
3217
3218         an_read_record(sc, (struct an_ltv_gen *)&sc->areq);
3219
3220         l_ioctl->len = sc->areq.an_len - 4;     /* just data */
3221
3222         /* the data contains the length at first */
3223         if (copyout(&(sc->areq.an_len), l_ioctl->data,
3224                     sizeof(sc->areq.an_len))) {
3225                 return -EFAULT;
3226         }
3227         /* Just copy the data back */
3228         if (copyout(&(sc->areq.an_val), l_ioctl->data + 2,
3229                     l_ioctl->len)) {
3230                 return -EFAULT;
3231         }
3232         return 0;
3233 }
3234
3235 static int
3236 writerids(ifp, l_ioctl)
3237         struct ifnet   *ifp;
3238         struct aironet_ioctl *l_ioctl;
3239 {
3240         struct an_softc *sc;
3241         int             rid, command;
3242
3243         sc = ifp->if_softc;
3244         rid = 0;
3245         command = l_ioctl->command;
3246
3247         switch (command) {
3248         case AIROPSIDS:
3249                 rid = AN_RID_SSIDLIST;
3250                 break;
3251         case AIROPCAP:
3252                 rid = AN_RID_CAPABILITIES;
3253                 break;
3254         case AIROPAPLIST:
3255                 rid = AN_RID_APLIST;
3256                 break;
3257         case AIROPCFG:
3258                 rid = AN_RID_GENCONFIG;
3259                 break;
3260         case AIROPMACON:
3261                 an_cmd(sc, AN_CMD_ENABLE, 0);
3262                 return 0;
3263                 break;
3264         case AIROPMACOFF:
3265                 an_cmd(sc, AN_CMD_DISABLE, 0);
3266                 return 0;
3267                 break;
3268         case AIROPSTCLR:
3269                 /*
3270                  * This command merely clears the counts does not actually
3271                  * store any data only reads rid. But as it changes the cards
3272                  * state, I put it in the writerid routines.
3273                  */
3274
3275                 rid = AN_RID_32BITS_DELTACLR;
3276                 sc = ifp->if_softc;
3277                 sc->areq.an_len = AN_MAX_DATALEN;
3278                 sc->areq.an_type = rid;
3279
3280                 an_read_record(sc, (struct an_ltv_gen *)&sc->areq);
3281                 l_ioctl->len = sc->areq.an_len - 4;     /* just data */
3282
3283                 /* the data contains the length at first */
3284                 if (copyout(&(sc->areq.an_len), l_ioctl->data,
3285                             sizeof(sc->areq.an_len))) {
3286                         return -EFAULT;
3287                 }
3288                 /* Just copy the data */
3289                 if (copyout(&(sc->areq.an_val), l_ioctl->data + 2,
3290                             l_ioctl->len)) {
3291                         return -EFAULT;
3292                 }
3293                 return 0;
3294                 break;
3295         case AIROPWEPKEY:
3296                 rid = AN_RID_WEP_TEMP;
3297                 break;
3298         case AIROPWEPKEYNV:
3299                 rid = AN_RID_WEP_PERM;
3300                 break;
3301         case AIROPLEAPUSR:
3302                 rid = AN_RID_LEAPUSERNAME;
3303                 break;
3304         case AIROPLEAPPWD:
3305                 rid = AN_RID_LEAPPASSWORD;
3306                 break;
3307         default:
3308                 return -EOPNOTSUPP;
3309         }
3310
3311         if (rid) {
3312                 if (l_ioctl->len > sizeof(sc->areq.an_val) + 4)
3313                         return -EINVAL;
3314                 sc->areq.an_len = l_ioctl->len + 4;     /* add type & length */
3315                 sc->areq.an_type = rid;
3316
3317                 /* Just copy the data back */
3318                 copyin((l_ioctl->data) + 2, &sc->areq.an_val,
3319                        l_ioctl->len);
3320
3321                 an_cmd(sc, AN_CMD_DISABLE, 0);
3322                 an_write_record(sc, (struct an_ltv_gen *)&sc->areq);
3323                 an_cmd(sc, AN_CMD_ENABLE, 0);
3324                 return 0;
3325         }
3326         return -EOPNOTSUPP;
3327 }
3328
3329 /*
3330  * General Flash utilities derived from Cisco driver additions to Ben Reed's
3331  * Linux driver
3332  */
3333
3334 #define FLASH_DELAY(x)  tsleep(ifp, 0, "flash", ((x) / hz) + 1);
3335 #define FLASH_COMMAND   0x7e7e
3336 #define FLASH_SIZE      32 * 1024
3337
3338 static int
3339 unstickbusy(ifp)
3340         struct ifnet   *ifp;
3341 {
3342         struct an_softc *sc = ifp->if_softc;
3343
3344         if (CSR_READ_2(sc, AN_COMMAND(sc->mpi350)) & AN_CMD_BUSY) {
3345                 CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), 
3346                             AN_EV_CLR_STUCK_BUSY);
3347                 return 1;
3348         }
3349         return 0;
3350 }
3351
3352 /*
3353  * Wait for busy completion from card wait for delay uSec's Return true for
3354  * success meaning command reg is clear
3355  */
3356
3357 static int
3358 WaitBusy(ifp, uSec)
3359         struct ifnet   *ifp;
3360         int             uSec;
3361 {
3362         int             statword = 0xffff;
3363         int             delay = 0;
3364         struct an_softc *sc = ifp->if_softc;
3365
3366         while ((statword & AN_CMD_BUSY) && delay <= (1000 * 100)) {
3367                 FLASH_DELAY(10);
3368                 delay += 10;
3369                 statword = CSR_READ_2(sc, AN_COMMAND(sc->mpi350));
3370
3371                 if ((AN_CMD_BUSY & statword) && (delay % 200)) {
3372                         unstickbusy(ifp);
3373                 }
3374         }
3375
3376         return 0 == (AN_CMD_BUSY & statword);
3377 }
3378
3379 /*
3380  * STEP 1) Disable MAC and do soft reset on card.
3381  */
3382
3383 static int
3384 cmdreset(ifp)
3385         struct ifnet   *ifp;
3386 {
3387         int             status;
3388         struct an_softc *sc = ifp->if_softc;
3389
3390         an_stop(sc);
3391
3392         an_cmd(sc, AN_CMD_DISABLE, 0);
3393
3394         if (!(status = WaitBusy(ifp, AN_TIMEOUT))) {
3395                 printf("an%d: Waitbusy hang b4 RESET =%d\n",
3396                        sc->an_unit, status);
3397                 return -EBUSY;
3398         }
3399         CSR_WRITE_2(sc, AN_COMMAND(sc->mpi350), AN_CMD_FW_RESTART);
3400
3401         FLASH_DELAY(1000);      /* WAS 600 12/7/00 */
3402
3403
3404         if (!(status = WaitBusy(ifp, 100))) {
3405                 printf("an%d: Waitbusy hang AFTER RESET =%d\n",
3406                        sc->an_unit, status);
3407                 return -EBUSY;
3408         }
3409         return 0;
3410 }
3411
3412 /*
3413  * STEP 2) Put the card in legendary flash mode
3414  */
3415
3416 static int
3417 setflashmode(ifp)
3418         struct ifnet   *ifp;
3419 {
3420         int             status;
3421         struct an_softc *sc = ifp->if_softc;
3422
3423         CSR_WRITE_2(sc, AN_SW0(sc->mpi350), FLASH_COMMAND);
3424         CSR_WRITE_2(sc, AN_SW1(sc->mpi350), FLASH_COMMAND);
3425         CSR_WRITE_2(sc, AN_SW0(sc->mpi350), FLASH_COMMAND);
3426         CSR_WRITE_2(sc, AN_COMMAND(sc->mpi350), FLASH_COMMAND);
3427
3428         /*
3429          * mdelay(500); // 500ms delay
3430          */
3431
3432         FLASH_DELAY(500);
3433
3434         if (!(status = WaitBusy(ifp, AN_TIMEOUT))) {
3435                 printf("Waitbusy hang after setflash mode\n");
3436                 return -EIO;
3437         }
3438         return 0;
3439 }
3440
3441 /*
3442  * Get a character from the card matching matchbyte Step 3)
3443  */
3444
3445 static int
3446 flashgchar(ifp, matchbyte, dwelltime)
3447         struct ifnet   *ifp;
3448         int             matchbyte;
3449         int             dwelltime;
3450 {
3451         int             rchar;
3452         unsigned char   rbyte = 0;
3453         int             success = -1;
3454         struct an_softc *sc = ifp->if_softc;
3455
3456
3457         do {
3458                 rchar = CSR_READ_2(sc, AN_SW1(sc->mpi350));
3459
3460                 if (dwelltime && !(0x8000 & rchar)) {
3461                         dwelltime -= 10;
3462                         FLASH_DELAY(10);
3463                         continue;
3464                 }
3465                 rbyte = 0xff & rchar;
3466
3467                 if ((rbyte == matchbyte) && (0x8000 & rchar)) {
3468                         CSR_WRITE_2(sc, AN_SW1(sc->mpi350), 0);
3469                         success = 1;
3470                         break;
3471                 }
3472                 if (rbyte == 0x81 || rbyte == 0x82 || rbyte == 0x83 || rbyte == 0x1a || 0xffff == rchar)
3473                         break;
3474                 CSR_WRITE_2(sc, AN_SW1(sc->mpi350), 0);
3475
3476         } while (dwelltime > 0);
3477         return success;
3478 }
3479
3480 /*
3481  * Put character to SWS0 wait for dwelltime x 50us for  echo .
3482  */
3483
3484 static int
3485 flashpchar(ifp, byte, dwelltime)
3486         struct ifnet   *ifp;
3487         int             byte;
3488         int             dwelltime;
3489 {
3490         int             echo;
3491         int             pollbusy, waittime;
3492         struct an_softc *sc = ifp->if_softc;
3493
3494         byte |= 0x8000;
3495
3496         if (dwelltime == 0)
3497                 dwelltime = 200;
3498
3499         waittime = dwelltime;
3500
3501         /*
3502          * Wait for busy bit d15 to go false indicating buffer empty
3503          */
3504         do {
3505                 pollbusy = CSR_READ_2(sc, AN_SW0(sc->mpi350));
3506
3507                 if (pollbusy & 0x8000) {
3508                         FLASH_DELAY(50);
3509                         waittime -= 50;
3510                         continue;
3511                 } else
3512                         break;
3513         }
3514         while (waittime >= 0);
3515
3516         /* timeout for busy clear wait */
3517
3518         if (waittime <= 0) {
3519                 printf("an%d: flash putchar busywait timeout! \n",
3520                        sc->an_unit);
3521                 return -1;
3522         }
3523         /*
3524          * Port is clear now write byte and wait for it to echo back
3525          */
3526         do {
3527                 CSR_WRITE_2(sc, AN_SW0(sc->mpi350), byte);
3528                 FLASH_DELAY(50);
3529                 dwelltime -= 50;
3530                 echo = CSR_READ_2(sc, AN_SW1(sc->mpi350));
3531         } while (dwelltime >= 0 && echo != byte);
3532
3533
3534         CSR_WRITE_2(sc, AN_SW1(sc->mpi350), 0);
3535
3536         return echo == byte;
3537 }
3538
3539 /*
3540  * Transfer 32k of firmware data from user buffer to our buffer and send to
3541  * the card
3542  */
3543
3544 static int
3545 flashputbuf(ifp)
3546         struct ifnet   *ifp;
3547 {
3548         unsigned short *bufp;
3549         int             nwords;
3550         struct an_softc *sc = ifp->if_softc;
3551
3552         /* Write stuff */
3553
3554         bufp = sc->an_flash_buffer;
3555
3556         if (!sc->mpi350) {
3557                 CSR_WRITE_2(sc, AN_AUX_PAGE, 0x100);
3558                 CSR_WRITE_2(sc, AN_AUX_OFFSET, 0);
3559
3560                 for (nwords = 0; nwords != FLASH_SIZE / 2; nwords++) {
3561                         CSR_WRITE_2(sc, AN_AUX_DATA, bufp[nwords] & 0xffff);
3562                 }
3563         } else {
3564                 for (nwords = 0; nwords != FLASH_SIZE / 4; nwords++) {
3565                         CSR_MEM_AUX_WRITE_4(sc, 0x8000, 
3566                                 ((u_int32_t *)bufp)[nwords] & 0xffff);
3567                 }
3568         }
3569
3570         CSR_WRITE_2(sc, AN_SW0(sc->mpi350), 0x8000);
3571
3572         return 0;
3573 }
3574
3575 /*
3576  * After flashing restart the card.
3577  */
3578
3579 static int
3580 flashrestart(ifp)
3581         struct ifnet   *ifp;
3582 {
3583         int             status = 0;
3584         struct an_softc *sc = ifp->if_softc;
3585
3586         FLASH_DELAY(1024);              /* Added 12/7/00 */
3587
3588         an_init(sc);
3589
3590         FLASH_DELAY(1024);              /* Added 12/7/00 */
3591         return status;
3592 }
3593
3594 /*
3595  * Entry point for flash ioclt.
3596  */
3597
3598 static int
3599 flashcard(ifp, l_ioctl)
3600         struct ifnet   *ifp;
3601         struct aironet_ioctl *l_ioctl;
3602 {
3603         int             z = 0, status;
3604         struct an_softc *sc;
3605
3606         sc = ifp->if_softc;
3607         if (sc->mpi350) {
3608                 printf("an%d: flashing not supported on MPI 350 yet\n", 
3609                        sc->an_unit);
3610                 return(-1);
3611         }
3612         status = l_ioctl->command;
3613
3614         switch (l_ioctl->command) {
3615         case AIROFLSHRST:
3616                 return cmdreset(ifp);
3617                 break;
3618         case AIROFLSHSTFL:
3619                 if (sc->an_flash_buffer) {
3620                         free(sc->an_flash_buffer, M_DEVBUF);
3621                         sc->an_flash_buffer = NULL;
3622                 }
3623                 sc->an_flash_buffer = malloc(FLASH_SIZE, M_DEVBUF, 0);
3624                 if (sc->an_flash_buffer)
3625                         return setflashmode(ifp);
3626                 else
3627                         return ENOBUFS;
3628                 break;
3629         case AIROFLSHGCHR:      /* Get char from aux */
3630                 copyin(l_ioctl->data, &sc->areq, l_ioctl->len);
3631                 z = *(int *)&sc->areq;
3632                 if ((status = flashgchar(ifp, z, 8000)) == 1)
3633                         return 0;
3634                 else
3635                         return -1;
3636                 break;
3637         case AIROFLSHPCHR:      /* Send char to card. */
3638                 copyin(l_ioctl->data, &sc->areq, l_ioctl->len);
3639                 z = *(int *)&sc->areq;
3640                 if ((status = flashpchar(ifp, z, 8000)) == -1)
3641                         return -EIO;
3642                 else
3643                         return 0;
3644                 break;
3645         case AIROFLPUTBUF:      /* Send 32k to card */
3646                 if (l_ioctl->len > FLASH_SIZE) {
3647                         printf("an%d: Buffer to big, %x %x\n", sc->an_unit,
3648                                l_ioctl->len, FLASH_SIZE);
3649                         return -EINVAL;
3650                 }
3651                 copyin(l_ioctl->data, sc->an_flash_buffer, l_ioctl->len);
3652
3653                 if ((status = flashputbuf(ifp)) != 0)
3654                         return -EIO;
3655                 else
3656                         return 0;
3657                 break;
3658         case AIRORESTART:
3659                 if ((status = flashrestart(ifp)) != 0) {
3660                         printf("an%d: FLASHRESTART returned %d\n",
3661                                sc->an_unit, status);
3662                         return -EIO;
3663                 } else
3664                         return 0;
3665
3666                 break;
3667         default:
3668                 return -EINVAL;
3669         }
3670
3671         return -EINVAL;
3672 }