Misc cleanups to take care of GCC3.x warnings. Missing 'U' and 'LL'
[dragonfly.git] / sys / dev / netif / ray / if_ray.c
1 /*
2  * Copyright (C) 2000
3  * Dr. Duncan McLennan Barclay, dmlb@ragnet.demon.co.uk.
4  *
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the author nor the names of any co-contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY DUNCAN BARCLAY AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL DUNCAN BARCLAY OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $FreeBSD: src/sys/dev/ray/if_ray.c,v 1.47.2.4 2001/08/14 22:54:05 dmlb Exp $
32  * $DragonFly: src/sys/dev/netif/ray/Attic/if_ray.c,v 1.6 2003/11/15 21:05:41 dillon Exp $
33  *
34  */
35
36 /*      $NetBSD: if_ray.c,v 1.12 2000/02/07 09:36:27 augustss Exp $     */
37 /* 
38  * Copyright (c) 2000 Christian E. Hopps
39  * All rights reserved.
40  * 
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. Neither the name of the author nor the names of any co-contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  */
65
66 /*
67  * Card configuration
68  * ==================
69  *
70  * This card is unusual in that it uses both common and attribute
71  * memory whilst working. It should use common memory and an IO port.
72  *
73  * The bus resource allocations need to work around the brain deadness
74  * of pccardd (where it reads the CIS for common memory, sets it all
75  * up and then throws it all away assuming the card is an ed
76  * driver...). Note that this could be dangerous (because it doesn't
77  * interact with pccardd) if you use other memory mapped cards in the
78  * same pccard slot as currently old mappings are not cleaned up very well
79  * by the bus_release_resource methods or pccardd.
80  *
81  * There is no support for running this driver on 4.0.
82  *
83  * Ad-hoc and infra-structure modes
84  * ================================
85  * 
86  * The driver supports ad-hoc mode for V4 firmware and infrastructure
87  * mode for V5 firmware. V5 firmware in ad-hoc mode is untested and should
88  * work.
89  *
90  * The Linux driver also seems to have the capability to act as an AP.
91  * I wonder what facilities the "AP" can provide within a driver? We can
92  * probably use the BRIDGE code to form an ESS but I don't think
93  * power saving etc. is easy.
94  *
95  *
96  * Packet framing/encapsulation/translation
97  * ========================================
98  * 
99  * Currently we support the Webgear encapsulation:
100  *      802.11  header <net/if_ieee80211.h>struct ieee80211_frame
101  *      802.3   header <net/ethernet.h>struct ether_header
102  *      IP/ARP  payload
103  *
104  * and RFC1042 encapsulation of IP datagrams (translation):
105  *      802.11  header <net/if_ieee80211.h>struct ieee80211_frame
106  *      802.2   LLC header
107  *      802.2   SNAP header
108  *      802.3   Ethertype
109  *      IP/ARP  payload
110  *
111  * Framing should be selected via if_media stuff or link types but
112  * is currently hardcoded to:
113  *      V4      encapsulation
114  *      V5      translation
115  *
116  *
117  * Authentication
118  * ==============
119  *
120  * 802.11 provides two authentication mechanisms. The first is a very
121  * simple host based mechanism (like xhost) called Open System and the
122  * second is a more complex challenge/response called Shared Key built
123  * ontop of WEP.
124  *
125  * This driver only supports Open System and does not implement any
126  * host based control lists. In otherwords authentication is always
127  * granted to hosts wanting to authenticate with this station. This is
128  * the only sensible behaviour as the Open System mechanism uses MAC
129  * addresses to identify hosts. Send me patches if you need it!
130  */
131
132 /*
133  * ***check all XXX_INFRA code - reassoc not done well at all!
134  * ***watchdog to catch screwed up removals?
135  * ***error handling of RAY_COM_RUNQ
136  * ***error handling of ECF command completions
137  * ***can't seem to create a n/w that Win95 wants to see.
138  * ***remove panic in ray_com_ecf by re-quing or timeout
139  * ***use new ioctl stuff - probably need to change RAY_COM_FCHKRUNNING things?
140  *      consider user doing:
141  *              ifconfig ray0 192.168.200.38 -bssid "freed"
142  *              ifconfig ray0 192.168.200.38 -bssid "fred"
143  *      here the second one would be missed in this code
144  * check that v5 needs timeouts on ecf commands
145  * write up driver structure in comments above
146  * UPDATE_PARAMS seems to return via an interrupt - maybe the timeout
147  *      is needed for wrong values?
148  * proper setting of mib_hop_seq_len with country code for v4 firmware
149  *      best done with raycontrol?
150  * countrycode setting is broken I think
151  *      userupdate should trap and do via startjoin etc.
152  * fragmentation when rx level drops?
153  * v5 might not need download
154  *      defaults are as documented apart from hop_seq_length
155  *      settings are sane for ad-hoc not infra
156  *
157  * driver state
158  *      most state is implied by the sequence of commands in the runq
159  *      but in fact any of the rx and tx path that uses variables
160  *      in the sc_c are potentially going to get screwed?
161  *
162  * infra mode stuff
163  *      proper handling of the basic rate set - see the manual
164  *      all ray_sj, ray_assoc sequencues need a "nicer" solution as we
165  *              remember association and authentication
166  *      need to consider WEP
167  *      acting as ap - should be able to get working from the manual
168  *      need to finish RAY_ECMD_REJOIN_DONE
169  *      finish authenitcation code, it doesn't handle errors/timeouts/
170  *      REJOIN etc.
171  *
172  * ray_nw_param
173  *      promisc in here too? - done
174  *      should be able to update the parameters before we download to the
175  *              device. This means we must attach a desired struct to the
176  *              runq entry and maybe have another big case statement to
177  *              move these desired into current when not running.
178  *              init must then use the current settings (pre-loaded
179  *              in attach now!) and pass to download. But we can't access
180  *              current nw params outside of the runq - ahhh
181  *      differeniate between parameters set in attach and init
182  *      sc_station_addr in here too (for changing mac address)
183  *      move desired into the command structure?
184  *      take downloaded MIB from a complete nw_param?
185  *      longer term need to attach a desired nw params to the runq entry
186  *
187  *
188  * RAY_COM_RUNQ errors
189  *
190  * if sleeping in ccs_alloc with eintr/erestart/enxio/enodev
191  *      erestart        try again from the top
192  *                      XXX do not malloc more comqs
193  *                      XXX ccs allocation hard
194  *      eintr           clean up and return
195  *      enxio           clean up and return - done in macro
196  *
197  * if sleeping in runq_arr itself with eintr/erestart/enxio/enodev
198  *      erestart        try again from the top
199  *                      XXX do not malloc more comqs
200  *                      XXX ccs allocation hard
201  *                      XXX reinsert comqs at head of list
202  *      eintr           clean up and return
203  *      enxio           clean up and return - done in macro
204  */
205
206 #define XXX             0
207 #define XXX_ACTING_AP   0
208 #define XXX_INFRA       0
209 #define RAY_DEBUG       (                               \
210                         /* RAY_DBG_AUTH         | */    \
211                         /* RAY_DBG_SUBR         | */    \
212                         /* RAY_DBG_BOOTPARAM    | */    \
213                         /* RAY_DBG_STARTJOIN    | */    \
214                         /* RAY_DBG_CCS          | */    \
215                         /* RAY_DBG_IOCTL        | */    \
216                         /* RAY_DBG_MBUF         | */    \
217                         /* RAY_DBG_RX           | */    \
218                         /* RAY_DBG_CM           | */    \
219                         /* RAY_DBG_COM          | */    \
220                         /* RAY_DBG_STOP         | */    \
221                         /* RAY_DBG_CTL          | */    \
222                         /* RAY_DBG_MGT          | */    \
223                         /* RAY_DBG_TX           | */    \
224                         /* RAY_DBG_DCOM         | */    \
225                         0                               \
226                         )
227
228 /*
229  * XXX build options - move to LINT
230  */
231 #define RAY_CM_RID              0       /* pccardd abuses windows 0 and 1 */
232 #define RAY_AM_RID              3       /* pccardd abuses windows 0 and 1 */
233 #define RAY_COM_TIMEOUT         (hz/2)  /* Timeout for CCS commands */
234 #define RAY_TX_TIMEOUT          (hz/2)  /* Timeout for rescheduling TX */
235 #define RAY_ECF_SPIN_DELAY      1000    /* Wait 1ms before checking ECF ready */
236 #define RAY_ECF_SPIN_TRIES      10      /* Wait this many times for ECF ready */
237 /*
238  * XXX build options - move to LINT
239  */
240
241 #ifndef RAY_DEBUG
242 #define RAY_DEBUG               0x0000
243 #endif /* RAY_DEBUG */
244
245 #include <sys/param.h>
246 #include <sys/systm.h>
247 #include <sys/malloc.h>
248 #include <sys/kernel.h>
249
250 #include <machine/bus.h>
251 #include <machine/resource.h>
252 #include <machine/clock.h>
253 #include <sys/bus.h>
254 #include <sys/rman.h>
255
256 #include <sys/mbuf.h>
257 #include <sys/socket.h>
258 #include <sys/sockio.h>
259
260 #include <net/bpf.h>
261 #include <net/ethernet.h>
262 #include <net/if.h>
263 #include <net/if_arp.h>
264 #include <net/if_dl.h>
265 #include <net/if_ieee80211.h>
266 #include <net/if_llc.h>
267
268 #include <machine/limits.h>
269
270 #include <bus/pccard/pccardvar.h>
271 #include "card_if.h"
272
273 #include "if_rayreg.h"
274 #include "if_raymib.h"
275 #include "if_raydbg.h"
276 #include "if_rayvar.h"
277
278 /*
279  * Prototyping
280  */
281 static int      ray_attach              (device_t);
282 static int      ray_ccs_alloc           (struct ray_softc *sc, size_t *ccsp, char *wmesg);
283 static void     ray_ccs_fill            (struct ray_softc *sc, size_t ccs, u_int cmd);
284 static void     ray_ccs_free            (struct ray_softc *sc, size_t ccs);
285 static int      ray_ccs_tx              (struct ray_softc *sc, size_t *ccsp, size_t *bufpp);
286 static void     ray_com_ecf             (struct ray_softc *sc, struct ray_comq_entry *com);
287 static void     ray_com_ecf_done        (struct ray_softc *sc);
288 static void     ray_com_ecf_timo        (void *xsc);
289 static struct ray_comq_entry *
290                 ray_com_init            (struct ray_comq_entry *com, ray_comqfn_t function, int flags, char *mesg);
291 static struct ray_comq_entry *
292                 ray_com_malloc          (ray_comqfn_t function, int flags, char *mesg);
293 static void     ray_com_runq            (struct ray_softc *sc);
294 static int      ray_com_runq_add        (struct ray_softc *sc, struct ray_comq_entry *com[], int ncom, char *wmesg);
295 static void     ray_com_runq_done       (struct ray_softc *sc);
296 static int      ray_detach              (device_t);
297 static void     ray_init                (void *xsc);
298 static int      ray_init_user           (struct ray_softc *sc);
299 static void     ray_init_assoc          (struct ray_softc *sc, struct ray_comq_entry *com);
300 static void     ray_init_assoc_done     (struct ray_softc *sc, u_int8_t status, size_t ccs);
301 static void     ray_init_auth           (struct ray_softc *sc, struct ray_comq_entry *com);
302 static int      ray_init_auth_send      (struct ray_softc *sc, u_int8_t *dst, int sequence);
303 static void     ray_init_auth_done      (struct ray_softc *sc, u_int8_t status);
304 static void     ray_init_download       (struct ray_softc *sc, struct ray_comq_entry *com);
305 static void     ray_init_download_done  (struct ray_softc *sc, u_int8_t status, size_t ccs);
306 static void     ray_init_download_v4    (struct ray_softc *sc, struct ray_comq_entry *com);
307 static void     ray_init_download_v5    (struct ray_softc *sc, struct ray_comq_entry *com);
308 static void     ray_init_mcast          (struct ray_softc *sc, struct ray_comq_entry *com);
309 static void     ray_init_sj             (struct ray_softc *sc, struct ray_comq_entry *com);
310 static void     ray_init_sj_done        (struct ray_softc *sc, u_int8_t status, size_t ccs);
311 static void     ray_intr                (void *xsc);
312 static void     ray_intr_ccs            (struct ray_softc *sc, u_int8_t cmd, u_int8_t status, size_t ccs);
313 static void     ray_intr_rcs            (struct ray_softc *sc, u_int8_t cmd, size_t ccs);
314 static void     ray_intr_updt_errcntrs  (struct ray_softc *sc);
315 static int      ray_ioctl               (struct ifnet *ifp, u_long command, caddr_t data);
316 static void     ray_mcast               (struct ray_softc *sc, struct ray_comq_entry *com); 
317 static void     ray_mcast_done          (struct ray_softc *sc, u_int8_t status, size_t ccs); 
318 static int      ray_mcast_user          (struct ray_softc *sc); 
319 static int      ray_probe               (device_t);
320 static void     ray_promisc             (struct ray_softc *sc, struct ray_comq_entry *com); 
321 static void     ray_repparams           (struct ray_softc *sc, struct ray_comq_entry *com);
322 static void     ray_repparams_done      (struct ray_softc *sc, u_int8_t status, size_t ccs);
323 static int      ray_repparams_user      (struct ray_softc *sc, struct ray_param_req *pr);
324 static int      ray_repstats_user       (struct ray_softc *sc, struct ray_stats_req *sr);
325 static int      ray_res_alloc_am        (struct ray_softc *sc);
326 static int      ray_res_alloc_cm        (struct ray_softc *sc);
327 static int      ray_res_alloc_irq       (struct ray_softc *sc);
328 static void     ray_res_release         (struct ray_softc *sc);
329 static void     ray_rx                  (struct ray_softc *sc, size_t rcs);
330 static void     ray_rx_ctl              (struct ray_softc *sc, struct mbuf *m0);
331 static void     ray_rx_data             (struct ray_softc *sc, struct mbuf *m0, u_int8_t siglev, u_int8_t antenna);
332 static void     ray_rx_mgt              (struct ray_softc *sc, struct mbuf *m0);
333 static void     ray_rx_mgt_auth         (struct ray_softc *sc, struct mbuf *m0);
334 static void     ray_rx_mgt_beacon       (struct ray_softc *sc, struct mbuf *m0);
335 static void     ray_rx_mgt_info         (struct ray_softc *sc, struct mbuf *m0, struct ieee80211_information *elements);
336 static void     ray_rx_update_cache     (struct ray_softc *sc, u_int8_t *src, u_int8_t siglev, u_int8_t antenna);
337 static void     ray_stop                (struct ray_softc *sc, struct ray_comq_entry *com);
338 static int      ray_stop_user           (struct ray_softc *sc);
339 static void     ray_tx                  (struct ifnet *ifp);
340 static void     ray_tx_done             (struct ray_softc *sc, u_int8_t status, size_t ccs);
341 static void     ray_tx_timo             (void *xsc);
342 static int      ray_tx_send             (struct ray_softc *sc, size_t ccs, int pktlen, u_int8_t *dst);
343 static size_t   ray_tx_wrhdr            (struct ray_softc *sc, size_t bufp, u_int8_t type, u_int8_t fc1, u_int8_t *addr1, u_int8_t *addr2, u_int8_t *addr3);
344 static void     ray_upparams            (struct ray_softc *sc, struct ray_comq_entry *com);
345 static void     ray_upparams_done       (struct ray_softc *sc, u_int8_t status, size_t ccs);
346 static int      ray_upparams_user       (struct ray_softc *sc, struct ray_param_req *pr);
347 static void     ray_watchdog            (struct ifnet *ifp);
348 static u_int8_t ray_tx_best_antenna     (struct ray_softc *sc, u_int8_t *dst);
349
350 #if RAY_DEBUG & RAY_DBG_COM
351 static void     ray_com_ecf_check       (struct ray_softc *sc, size_t ccs, char *mesg);
352 #endif /* RAY_DEBUG & RAY_DBG_COM */
353 #if RAY_DEBUG & RAY_DBG_MBUF
354 static void     ray_dump_mbuf           (struct ray_softc *sc, struct mbuf *m, char *s);
355 #endif /* RAY_DEBUG & RAY_DBG_MBUF */
356
357 /*
358  * PC-Card (PCMCIA) driver definition
359  */
360 static device_method_t ray_methods[] = {
361         /* Device interface */
362         DEVMETHOD(device_probe,         ray_probe),
363         DEVMETHOD(device_attach,        ray_attach),
364         DEVMETHOD(device_detach,        ray_detach),
365
366         { 0, 0 }
367 };
368
369 static driver_t ray_driver = {
370         "ray",
371         ray_methods,
372         sizeof(struct ray_softc)
373 };
374
375 static devclass_t ray_devclass;
376
377 DRIVER_MODULE(ray, pccard, ray_driver, ray_devclass, 0, 0);
378
379 /* 
380  * Probe for the card by checking its startup results.
381  *
382  * Fixup any bugs/quirks for different firmware.
383  */
384 static int
385 ray_probe(device_t dev)
386 {
387         struct ray_softc *sc = device_get_softc(dev);
388         struct ray_ecf_startup_v5 *ep = &sc->sc_ecf_startup;
389         int error;
390
391         sc->dev = dev;
392         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
393
394         /*
395          * Read startup results from the card.
396          */
397         error = ray_res_alloc_cm(sc);
398         if (error)
399                 return (error);
400         error = ray_res_alloc_am(sc);
401         if (error) {
402                 ray_res_release(sc);
403                 return (error);
404         }
405         RAY_MAP_CM(sc);
406         SRAM_READ_REGION(sc, RAY_ECF_TO_HOST_BASE, ep,
407             sizeof(sc->sc_ecf_startup));
408         ray_res_release(sc);
409
410         /*
411          * Check the card is okay and work out what version we are using.
412          */
413         if (ep->e_status != RAY_ECFS_CARD_OK) {
414                 RAY_PRINTF(sc, "card failed self test 0x%b",
415                     ep->e_status, RAY_ECFS_PRINTFB);
416                 return (ENXIO);
417         }
418         if (sc->sc_version != RAY_ECFS_BUILD_4 &&
419             sc->sc_version != RAY_ECFS_BUILD_5) {
420                 RAY_PRINTF(sc, "unsupported firmware version 0x%0x",
421                     ep->e_fw_build_string);
422                 return (ENXIO);
423         }
424         RAY_DPRINTF(sc, RAY_DBG_BOOTPARAM, "found a card");
425         sc->sc_gone = 0;
426
427         /*
428          * Fixup tib size to be correct - on build 4 it is garbage
429          */
430         if (sc->sc_version == RAY_ECFS_BUILD_4 && sc->sc_tibsize == 0x55)
431                 sc->sc_tibsize = sizeof(struct ray_tx_tib);
432
433         return (0);
434 }
435
436 /*
437  * Attach the card into the kernel
438  */
439 static int
440 ray_attach(device_t dev)
441 {
442         struct ray_softc *sc = device_get_softc(dev);
443         struct ray_ecf_startup_v5 *ep = &sc->sc_ecf_startup;
444         struct ifnet *ifp = &sc->arpcom.ac_if;
445         size_t ccs;
446         int i, error;
447
448         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
449
450         if ((sc == NULL) || (sc->sc_gone))
451                 return (ENXIO);
452
453         /*
454          * Grab the resources I need
455          */
456         error = ray_res_alloc_cm(sc);
457         if (error)
458                 return (error);
459         error = ray_res_alloc_am(sc);
460         if (error) {
461                 ray_res_release(sc);
462                 return (error);
463         }
464         error = ray_res_alloc_irq(sc);
465         if (error) {
466                 ray_res_release(sc);
467                 return (error);
468         }
469
470         /*
471          * Reset any pending interrupts
472          */
473         RAY_HCS_CLEAR_INTR(sc);
474
475         /*
476          * Set the parameters that will survive stop/init and
477          * reset a few things on the card.
478          *
479          * Do not update these in ray_init_download's parameter setup
480          *
481          * XXX see the ray_init_download section for stuff to move
482          */
483         RAY_MAP_CM(sc);
484         bzero(&sc->sc_d, sizeof(struct ray_nw_param));
485         bzero(&sc->sc_c, sizeof(struct ray_nw_param));
486
487         /* Clear statistics counters */
488         sc->sc_rxoverflow = 0;
489         sc->sc_rxcksum = 0;
490         sc->sc_rxhcksum = 0;
491         sc->sc_rxnoise = 0;
492
493         /* Clear signal and antenna cache */
494         bzero(sc->sc_siglevs, sizeof(sc->sc_siglevs));
495
496         /* Set all ccs to be free */
497         bzero(sc->sc_ccsinuse, sizeof(sc->sc_ccsinuse));
498         ccs = RAY_CCS_ADDRESS(0);
499         for (i = 0; i < RAY_CCS_LAST; ccs += RAY_CCS_SIZE, i++)
500                 RAY_CCS_FREE(sc, ccs);
501
502         /*
503          * Initialise the network interface structure
504          */
505         bcopy((char *)&ep->e_station_addr,
506             (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
507         ifp->if_softc = sc;
508         ifp->if_name = "ray";
509         ifp->if_unit = device_get_unit(dev);
510         ifp->if_timer = 0;
511         ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
512         ifp->if_hdrlen = sizeof(struct ieee80211_frame) + 
513             sizeof(struct ether_header);
514         ifp->if_baudrate = 1000000; /* Is this baud or bps ;-) */
515         ifp->if_output = ether_output;
516         ifp->if_start = ray_tx;
517         ifp->if_ioctl = ray_ioctl;
518         ifp->if_watchdog = ray_watchdog;
519         ifp->if_init = ray_init;
520         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
521
522         ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
523
524         /*
525          * Initialise the timers and driver
526          */
527         callout_handle_init(&sc->com_timerh);
528         callout_handle_init(&sc->tx_timerh);
529         TAILQ_INIT(&sc->sc_comq);
530
531         /*
532          * Print out some useful information
533          */
534         if (bootverbose || (RAY_DEBUG & RAY_DBG_BOOTPARAM)) {
535                 RAY_PRINTF(sc, "start up results");
536                 if (sc->sc_version == RAY_ECFS_BUILD_4)
537                         printf(".  Firmware version 4\n");
538                 else
539                         printf(".  Firmware version 5\n");
540                 printf(".  Status 0x%b\n", ep->e_status, RAY_ECFS_PRINTFB);
541                 printf(".  Ether address %6D\n", ep->e_station_addr, ":");
542                 if (sc->sc_version == RAY_ECFS_BUILD_4) {
543                         printf(".  Program checksum %0x\n", ep->e_resv0);
544                         printf(".  CIS checksum %0x\n", ep->e_rates[0]);
545                 } else {
546                         printf(".  (reserved word) %0x\n", ep->e_resv0);
547                         printf(".  Supported rates %8D\n", ep->e_rates, ":");
548                 }
549                 printf(".  Japan call sign %12D\n", ep->e_japan_callsign, ":");
550                 if (sc->sc_version == RAY_ECFS_BUILD_5) {
551                         printf(".  Program checksum %0x\n", ep->e_prg_cksum);
552                         printf(".  CIS checksum %0x\n", ep->e_cis_cksum);
553                         printf(".  Firmware version %0x\n",
554                             ep->e_fw_build_string);
555                         printf(".  Firmware revision %0x\n", ep->e_fw_build);
556                         printf(".  (reserved word) %0x\n", ep->e_fw_resv);
557                         printf(".  ASIC version %0x\n", ep->e_asic_version);
558                         printf(".  TIB size %0x\n", ep->e_tibsize);
559                 }
560         }
561
562         return (0);
563 }
564
565 /*
566  * Detach the card
567  *
568  * This is usually called when the card is ejected, but
569  * can be caused by a modunload of a controller driver.
570  * The idea is to reset the driver's view of the device
571  * and ensure that any driver entry points such as
572  * read and write do not hang.
573  */
574 static int
575 ray_detach(device_t dev)
576 {
577         struct ray_softc *sc = device_get_softc(dev);
578         struct ifnet *ifp = &sc->arpcom.ac_if;
579         struct ray_comq_entry *com;
580         int s;
581
582         s = splimp();
583
584         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STOP, "");
585
586         if ((sc == NULL) || (sc->sc_gone))
587                 return (0);
588
589         /*
590          * Mark as not running and detach the interface.
591          *
592          * N.B. if_detach can trigger ioctls so we do it first and
593          * then clean the runq.
594          */
595         sc->sc_gone = 1;
596         sc->sc_c.np_havenet = 0;
597         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
598         ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
599
600         /*
601          * Stop the runq and wake up anyone sleeping for us.
602          */
603         untimeout(ray_com_ecf_timo, sc, sc->com_timerh);
604         untimeout(ray_tx_timo, sc, sc->tx_timerh);
605         com = TAILQ_FIRST(&sc->sc_comq);
606         for (com = TAILQ_FIRST(&sc->sc_comq); com != NULL;
607             com = TAILQ_NEXT(com, c_chain)) {
608                 com->c_flags |= RAY_COM_FDETACHED;
609                 com->c_retval = 0;
610                 RAY_DPRINTF(sc, RAY_DBG_STOP, "looking at com %p %b",
611                     com, com->c_flags, RAY_COM_FLAGS_PRINTFB);
612                 if (com->c_flags & RAY_COM_FWOK) {
613                         RAY_DPRINTF(sc, RAY_DBG_STOP, "waking com %p", com);
614                         wakeup(com->c_wakeup);
615                 }
616         }
617         
618         /*
619          * Release resources
620          */
621         ray_res_release(sc);
622         RAY_DPRINTF(sc, RAY_DBG_STOP, "unloading complete");
623
624         splx(s);
625
626         return (0);
627 }
628
629 /*
630  * Network ioctl request.
631  */
632 static int
633 ray_ioctl(register struct ifnet *ifp, u_long command, caddr_t data)
634 {
635         struct ray_softc *sc = ifp->if_softc;
636         struct ray_param_req pr;
637         struct ray_stats_req sr;
638         struct ifreq *ifr = (struct ifreq *)data;
639         int s, error, error2;
640
641         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_IOCTL, "");
642
643         if ((sc == NULL) || (sc->sc_gone))
644                 return (ENXIO);
645
646         error = error2 = 0;
647         s = splimp();
648
649         switch (command) {
650
651         case SIOCGIFADDR:
652         case SIOCSIFMTU:
653         case SIOCSIFADDR:
654                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFADDR/SIFMTU");
655                 error = ether_ioctl(ifp, command, data);
656 /* XXX SIFADDR used to fall through to SIOCSIFFLAGS */
657                 break;
658
659         case SIOCSIFFLAGS:
660                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "SIFFLAGS 0x%0x", ifp->if_flags);
661                 /*
662                  * If the interface is marked up we call ray_init_user.
663                  * This will deal with mcast and promisc flags as well as
664                  * initialising the hardware if it needs it.
665                  */
666                 if (ifp->if_flags & IFF_UP)
667                         error = ray_init_user(sc);
668                 else
669                         error = ray_stop_user(sc);
670                 break;
671
672         case SIOCADDMULTI:
673         case SIOCDELMULTI:
674                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "ADDMULTI/DELMULTI");
675                 error = ray_mcast_user(sc);
676                 break;
677
678         case SIOCSRAYPARAM:
679                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "SRAYPARAM");
680                 if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr))))
681                         break;
682                 error = ray_upparams_user(sc, &pr);
683                 error2 = copyout(&pr, ifr->ifr_data, sizeof(pr));
684                 error = error2 ? error2 : error;
685                 break;
686
687         case SIOCGRAYPARAM:
688                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GRAYPARAM");
689                 if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr))))
690                         break;
691                 error = ray_repparams_user(sc, &pr);
692                 error2 = copyout(&pr, ifr->ifr_data, sizeof(pr));
693                 error = error2 ? error2 : error;
694                 break;
695
696         case SIOCGRAYSTATS:
697                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GRAYSTATS");
698                 error = ray_repstats_user(sc, &sr);
699                 error2 = copyout(&sr, ifr->ifr_data, sizeof(sr));
700                 error = error2 ? error2 : error;
701                 break;
702
703         case SIOCGRAYSIGLEV:
704                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GRAYSIGLEV");
705                 error = copyout(sc->sc_siglevs, ifr->ifr_data,
706                     sizeof(sc->sc_siglevs));
707                 break;
708
709         case SIOCGIFFLAGS:
710                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFFLAGS");
711                 error = EINVAL;
712                 break;
713
714         case SIOCGIFMETRIC:
715                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFMETRIC");
716                 error = EINVAL;
717                 break;
718
719         case SIOCGIFMTU:
720                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFMTU");
721                 error = EINVAL;
722                 break;
723
724         case SIOCGIFPHYS:
725                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFPYHS");
726                 error = EINVAL;
727                 break;
728
729         case SIOCSIFMEDIA:
730                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "SIFMEDIA");
731                 error = EINVAL;
732                 break;
733
734         case SIOCGIFMEDIA:
735                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFMEDIA");
736                 error = EINVAL;
737                 break;
738
739         default:
740                 error = EINVAL;
741
742         }
743
744         splx(s);
745
746         return (error);
747 }
748
749 /*
750  * Ethernet layer entry to ray_init - discard errors
751  */
752 static void
753 ray_init(void *xsc)
754 {
755         struct ray_softc *sc = (struct ray_softc *)xsc;
756
757         ray_init_user(sc);
758 }
759
760 /*
761  * User land entry to network initialisation and changes in interface flags.
762  * 
763  * We do a very little work here, just creating runq entries to
764  * processes the actions needed to cope with interface flags. We do it
765  * this way in case there are runq entries outstanding from earlier
766  * ioctls that modify the interface flags.
767  *
768  * Returns values are either 0 for success, a varity of resource allocation
769  * failures or errors in the command sent to the card.
770  *
771  * Note, IFF_RUNNING is eventually set by init_sj_done or init_assoc_done
772  */
773 static int
774 ray_init_user(struct ray_softc *sc)
775 {
776         struct ray_comq_entry *com[6];
777         int error, ncom;
778
779         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, "");
780
781         /*
782          * Create the following runq entries to bring the card up.
783          *
784          *              init_download   - download the network to the card
785          *              init_mcast      - reset multicast list
786          *              init_sj         - find or start a BSS
787          *              init_auth       - authenticate with a ESSID if needed
788          *              init_assoc      - associate with a ESSID if needed
789          *
790          * They are only actually executed if the card is not running.
791          * We may enter this routine from a simple change of IP
792          * address and do not need to get the card to do these things.
793          * However, we cannot perform the check here as there may be
794          * commands in the runq that change the IFF_RUNNING state of
795          * the interface.
796          */
797         ncom = 0;
798         com[ncom++] = RAY_COM_MALLOC(ray_init_download, RAY_COM_FCHKRUNNING);
799         com[ncom++] = RAY_COM_MALLOC(ray_init_mcast, RAY_COM_FCHKRUNNING);
800         com[ncom++] = RAY_COM_MALLOC(ray_init_sj, RAY_COM_FCHKRUNNING);
801         com[ncom++] = RAY_COM_MALLOC(ray_init_auth, RAY_COM_FCHKRUNNING);
802         com[ncom++] = RAY_COM_MALLOC(ray_init_assoc, RAY_COM_FCHKRUNNING);
803
804         /*
805          * Create runq entries to process flags
806          *
807          *              promisc         - set/reset PROMISC and ALLMULTI flags
808          *
809          * They are only actually executed if the card is running
810          */
811         com[ncom++] = RAY_COM_MALLOC(ray_promisc, 0);
812
813         RAY_COM_RUNQ(sc, com, ncom, "rayinit", error);
814
815         /* XXX no real error processing from anything yet! */
816
817         RAY_COM_FREE(com, ncom);
818
819         return (error);
820 }
821
822 /*
823  * Runq entry for resetting driver and downloading start up structures to card
824  */
825 static void
826 ray_init_download(struct ray_softc *sc, struct ray_comq_entry *com)
827 {
828         struct ifnet *ifp = &sc->arpcom.ac_if;
829
830         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, "");
831
832         /* If the card already running we might not need to download */
833         RAY_COM_CHKRUNNING(sc, com, ifp);
834
835         /*
836          * Reset instance variables
837          *
838          * The first set are network parameters that are read back when
839          * the card starts or joins the network.
840          *
841          * The second set are network parameters that are downloaded to
842          * the card.
843          *
844          * The third set are driver parameters.
845          *
846          * All of the variables in these sets can be updated by the
847          * card or ioctls.
848          *
849          * XXX see the ray_attach section for stuff to move
850          */
851         sc->sc_d.np_upd_param = 0;
852         bzero(sc->sc_d.np_bss_id, ETHER_ADDR_LEN);
853         sc->sc_d.np_inited = 0;
854         sc->sc_d.np_def_txrate = RAY_MIB_BASIC_RATE_SET_DEFAULT;
855         sc->sc_d.np_encrypt = 0;
856
857         bzero(sc->sc_d.np_ssid, IEEE80211_NWID_LEN);
858         if (sc->sc_version == RAY_ECFS_BUILD_4) {
859                 sc->sc_d.np_net_type = RAY_MIB_NET_TYPE_V4;
860                 strncpy(sc->sc_d.np_ssid, RAY_MIB_SSID_V4, IEEE80211_NWID_LEN);
861                 sc->sc_d.np_ap_status = RAY_MIB_AP_STATUS_V4;
862                 sc->sc_d.np_framing = RAY_FRAMING_ENCAPSULATION;
863         } else {
864                 sc->sc_d.np_net_type = RAY_MIB_NET_TYPE_V5;
865                 strncpy(sc->sc_d.np_ssid, RAY_MIB_SSID_V5, IEEE80211_NWID_LEN);
866                 sc->sc_d.np_ap_status = RAY_MIB_AP_STATUS_V5;
867                 sc->sc_d.np_framing = RAY_FRAMING_TRANSLATION;
868         }
869         sc->sc_d.np_priv_start = RAY_MIB_PRIVACY_MUST_START_DEFAULT;
870         sc->sc_d.np_priv_join = RAY_MIB_PRIVACY_CAN_JOIN_DEFAULT;
871         sc->sc_d.np_promisc = !!(ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI));
872
873 /* XXX this is a hack whilst I transition the code. The instance
874  * XXX variables above should be set somewhere else. This is needed for
875  * XXX start_join */
876 bcopy(&sc->sc_d, &com->c_desired, sizeof(struct ray_nw_param));
877             
878         /*
879          * Download the right firmware defaults
880          */
881         if (sc->sc_version == RAY_ECFS_BUILD_4)
882                 ray_init_download_v4(sc, com);
883         else
884                 ray_init_download_v5(sc, com);
885
886         /*
887          * Kick the card
888          */
889         ray_ccs_fill(sc, com->c_ccs, RAY_CMD_DOWNLOAD_PARAMS);
890         ray_com_ecf(sc, com);
891 }
892
893 #define PUT2(p, v)      \
894     do { (p)[0] = ((v >> 8) & 0xff); (p)[1] = (v & 0xff); } while(0)
895 /*
896  * Firmware version 4 defaults - see if_raymib.h for details
897  */
898 static void
899 ray_init_download_v4(struct ray_softc *sc, struct ray_comq_entry *com)
900 {
901         struct ray_mib_4 ray_mib_4_default;
902
903         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, "");
904         RAY_MAP_CM(sc);
905
906 #define MIB4(m)         ray_mib_4_default.m
907
908         MIB4(mib_net_type)              = com->c_desired.np_net_type;
909         MIB4(mib_ap_status)             = com->c_desired.np_ap_status;
910         bcopy(com->c_desired.np_ssid, MIB4(mib_ssid), IEEE80211_NWID_LEN);
911         MIB4(mib_scan_mode)             = RAY_MIB_SCAN_MODE_V4;
912         MIB4(mib_apm_mode)              = RAY_MIB_APM_MODE_V4;
913         bcopy(sc->sc_station_addr, MIB4(mib_mac_addr), ETHER_ADDR_LEN);
914    PUT2(MIB4(mib_frag_thresh),            RAY_MIB_FRAG_THRESH_V4);
915    PUT2(MIB4(mib_dwell_time),             RAY_MIB_DWELL_TIME_V4);
916    PUT2(MIB4(mib_beacon_period),          RAY_MIB_BEACON_PERIOD_V4);
917         MIB4(mib_dtim_interval)         = RAY_MIB_DTIM_INTERVAL_V4;
918         MIB4(mib_max_retry)             = RAY_MIB_MAX_RETRY_V4;
919         MIB4(mib_ack_timo)              = RAY_MIB_ACK_TIMO_V4;
920         MIB4(mib_sifs)                  = RAY_MIB_SIFS_V4;
921         MIB4(mib_difs)                  = RAY_MIB_DIFS_V4;
922         MIB4(mib_pifs)                  = RAY_MIB_PIFS_V4;
923    PUT2(MIB4(mib_rts_thresh),             RAY_MIB_RTS_THRESH_V4);
924    PUT2(MIB4(mib_scan_dwell),             RAY_MIB_SCAN_DWELL_V4);
925    PUT2(MIB4(mib_scan_max_dwell),         RAY_MIB_SCAN_MAX_DWELL_V4);
926         MIB4(mib_assoc_timo)            = RAY_MIB_ASSOC_TIMO_V4;
927         MIB4(mib_adhoc_scan_cycle)      = RAY_MIB_ADHOC_SCAN_CYCLE_V4;
928         MIB4(mib_infra_scan_cycle)      = RAY_MIB_INFRA_SCAN_CYCLE_V4;
929         MIB4(mib_infra_super_scan_cycle)
930                                         = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_V4;
931         MIB4(mib_promisc)               = com->c_desired.np_promisc;
932    PUT2(MIB4(mib_uniq_word),              RAY_MIB_UNIQ_WORD_V4);
933         MIB4(mib_slot_time)             = RAY_MIB_SLOT_TIME_V4;
934         MIB4(mib_roam_low_snr_thresh)   = RAY_MIB_ROAM_LOW_SNR_THRESH_V4;
935         MIB4(mib_low_snr_count)         = RAY_MIB_LOW_SNR_COUNT_V4;
936         MIB4(mib_infra_missed_beacon_count)
937                                         = RAY_MIB_INFRA_MISSED_BEACON_COUNT_V4;
938         MIB4(mib_adhoc_missed_beacon_count)     
939                                         = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_V4;
940         MIB4(mib_country_code)          = RAY_MIB_COUNTRY_CODE_V4;
941         MIB4(mib_hop_seq)               = RAY_MIB_HOP_SEQ_V4;
942         MIB4(mib_hop_seq_len)           = RAY_MIB_HOP_SEQ_LEN_V4;
943         MIB4(mib_cw_max)                = RAY_MIB_CW_MAX_V4;
944         MIB4(mib_cw_min)                = RAY_MIB_CW_MIN_V4;
945         MIB4(mib_noise_filter_gain)     = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT;
946         MIB4(mib_noise_limit_offset)    = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT;
947         MIB4(mib_rssi_thresh_offset)    = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT;
948         MIB4(mib_busy_thresh_offset)    = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT;
949         MIB4(mib_sync_thresh)           = RAY_MIB_SYNC_THRESH_DEFAULT;
950         MIB4(mib_test_mode)             = RAY_MIB_TEST_MODE_DEFAULT;
951         MIB4(mib_test_min_chan)         = RAY_MIB_TEST_MIN_CHAN_DEFAULT;
952         MIB4(mib_test_max_chan)         = RAY_MIB_TEST_MAX_CHAN_DEFAULT;
953 #undef MIB4
954
955         SRAM_WRITE_REGION(sc, RAY_HOST_TO_ECF_BASE,
956             &ray_mib_4_default, sizeof(ray_mib_4_default));
957 }
958
959 /*
960  * Firmware version 5 defaults - see if_raymib.h for details
961  */
962 static void
963 ray_init_download_v5(struct ray_softc *sc, struct ray_comq_entry *com)
964 {
965         struct ray_mib_5 ray_mib_5_default;
966
967         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, "");
968         RAY_MAP_CM(sc);
969
970 #define MIB5(m)         ray_mib_5_default.m
971         MIB5(mib_net_type)              = com->c_desired.np_net_type;
972         MIB5(mib_ap_status)             = com->c_desired.np_ap_status;
973         bcopy(com->c_desired.np_ssid, MIB5(mib_ssid), IEEE80211_NWID_LEN);
974         MIB5(mib_scan_mode)             = RAY_MIB_SCAN_MODE_V5;
975         MIB5(mib_apm_mode)              = RAY_MIB_APM_MODE_V5;
976         bcopy(sc->sc_station_addr, MIB5(mib_mac_addr), ETHER_ADDR_LEN);
977    PUT2(MIB5(mib_frag_thresh),            RAY_MIB_FRAG_THRESH_V5);
978    PUT2(MIB5(mib_dwell_time),             RAY_MIB_DWELL_TIME_V5);
979    PUT2(MIB5(mib_beacon_period),          RAY_MIB_BEACON_PERIOD_V5);
980         MIB5(mib_dtim_interval)         = RAY_MIB_DTIM_INTERVAL_V5;
981         MIB5(mib_max_retry)             = RAY_MIB_MAX_RETRY_V5;
982         MIB5(mib_ack_timo)              = RAY_MIB_ACK_TIMO_V5;
983         MIB5(mib_sifs)                  = RAY_MIB_SIFS_V5;
984         MIB5(mib_difs)                  = RAY_MIB_DIFS_V5;
985         MIB5(mib_pifs)                  = RAY_MIB_PIFS_V5;
986    PUT2(MIB5(mib_rts_thresh),             RAY_MIB_RTS_THRESH_V5);
987    PUT2(MIB5(mib_scan_dwell),             RAY_MIB_SCAN_DWELL_V5);
988    PUT2(MIB5(mib_scan_max_dwell),         RAY_MIB_SCAN_MAX_DWELL_V5);
989         MIB5(mib_assoc_timo)            = RAY_MIB_ASSOC_TIMO_V5;
990         MIB5(mib_adhoc_scan_cycle)      = RAY_MIB_ADHOC_SCAN_CYCLE_V5;
991         MIB5(mib_infra_scan_cycle)      = RAY_MIB_INFRA_SCAN_CYCLE_V5;
992         MIB5(mib_infra_super_scan_cycle)
993                                         = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_V5;
994         MIB5(mib_promisc)               = com->c_desired.np_promisc;
995    PUT2(MIB5(mib_uniq_word),              RAY_MIB_UNIQ_WORD_V5);
996         MIB5(mib_slot_time)             = RAY_MIB_SLOT_TIME_V5;
997         MIB5(mib_roam_low_snr_thresh)   = RAY_MIB_ROAM_LOW_SNR_THRESH_V5;
998         MIB5(mib_low_snr_count) = RAY_MIB_LOW_SNR_COUNT_V5;
999         MIB5(mib_infra_missed_beacon_count)
1000                                         = RAY_MIB_INFRA_MISSED_BEACON_COUNT_V5;
1001         MIB5(mib_adhoc_missed_beacon_count)
1002                                         = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_V5;
1003         MIB5(mib_country_code)          = RAY_MIB_COUNTRY_CODE_V5;
1004         MIB5(mib_hop_seq)               = RAY_MIB_HOP_SEQ_V5;
1005         MIB5(mib_hop_seq_len)           = RAY_MIB_HOP_SEQ_LEN_V5;
1006    PUT2(MIB5(mib_cw_max),                 RAY_MIB_CW_MAX_V5);
1007    PUT2(MIB5(mib_cw_min),                 RAY_MIB_CW_MIN_V5);
1008         MIB5(mib_noise_filter_gain)     = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT;
1009         MIB5(mib_noise_limit_offset)    = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT;
1010         MIB5(mib_rssi_thresh_offset)    = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT;
1011         MIB5(mib_busy_thresh_offset)    = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT;
1012         MIB5(mib_sync_thresh)           = RAY_MIB_SYNC_THRESH_DEFAULT;
1013         MIB5(mib_test_mode)             = RAY_MIB_TEST_MODE_DEFAULT;
1014         MIB5(mib_test_min_chan)         = RAY_MIB_TEST_MIN_CHAN_DEFAULT;
1015         MIB5(mib_test_max_chan)         = RAY_MIB_TEST_MAX_CHAN_DEFAULT;
1016         MIB5(mib_allow_probe_resp)      = RAY_MIB_ALLOW_PROBE_RESP_DEFAULT;
1017         MIB5(mib_privacy_must_start)    = com->c_desired.np_priv_start;
1018         MIB5(mib_privacy_can_join)      = com->c_desired.np_priv_join;
1019         MIB5(mib_basic_rate_set[0])     = com->c_desired.np_def_txrate;
1020 #undef MIB5
1021
1022         SRAM_WRITE_REGION(sc, RAY_HOST_TO_ECF_BASE,
1023             &ray_mib_5_default, sizeof(ray_mib_5_default));
1024 }
1025 #undef PUT2
1026
1027 /*
1028  * Download completion routine
1029  */
1030 static void
1031 ray_init_download_done(struct ray_softc *sc, u_int8_t status, size_t ccs)
1032 {
1033         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, "");
1034         RAY_COM_CHECK(sc, ccs);
1035
1036         RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */
1037
1038         ray_com_ecf_done(sc);
1039 }
1040
1041 /*
1042  * Runq entry to empty the multicast filter list
1043  */
1044 static void
1045 ray_init_mcast(struct ray_softc *sc, struct ray_comq_entry *com)
1046 {
1047         struct ifnet *ifp = &sc->arpcom.ac_if;
1048
1049         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, "");
1050         RAY_MAP_CM(sc);
1051
1052         /* If the card already running we might not need to reset the list */
1053         RAY_COM_CHKRUNNING(sc, com, ifp);
1054
1055         /*
1056          * Kick the card
1057          */
1058         ray_ccs_fill(sc, com->c_ccs, RAY_CMD_UPDATE_MCAST);
1059         SRAM_WRITE_FIELD_1(sc, com->c_ccs, ray_cmd_update_mcast, c_nmcast, 0);
1060
1061         ray_com_ecf(sc, com);
1062 }
1063
1064 /*
1065  * Runq entry to starting or joining a network
1066  */
1067 static void
1068 ray_init_sj(struct ray_softc *sc, struct ray_comq_entry *com)
1069 {
1070         struct ifnet *ifp = &sc->arpcom.ac_if;
1071         struct ray_net_params np;
1072         int update;
1073
1074         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, "");
1075         RAY_MAP_CM(sc);
1076
1077         /* If the card already running we might not need to start the n/w */
1078         RAY_COM_CHKRUNNING(sc, com, ifp);
1079
1080         /*
1081          * Set up the right start or join command and determine
1082          * whether we should tell the card about a change in operating
1083          * parameters.
1084          */
1085         sc->sc_c.np_havenet = 0;
1086         if (sc->sc_d.np_net_type == RAY_MIB_NET_TYPE_ADHOC)
1087                 ray_ccs_fill(sc, com->c_ccs, RAY_CMD_START_NET);
1088         else
1089                 ray_ccs_fill(sc, com->c_ccs, RAY_CMD_JOIN_NET);
1090
1091         update = 0;
1092         if (sc->sc_c.np_net_type != sc->sc_d.np_net_type)
1093                 update++;
1094         if (bcmp(sc->sc_c.np_ssid, sc->sc_d.np_ssid, IEEE80211_NWID_LEN))
1095                 update++;
1096         if (sc->sc_c.np_priv_join != sc->sc_d.np_priv_join)
1097                 update++;
1098         if (sc->sc_c.np_priv_start != sc->sc_d.np_priv_start)
1099                 update++;
1100         RAY_DPRINTF(sc, RAY_DBG_STARTJOIN,
1101             "%s updating nw params", update?"is":"not");
1102         if (update) {
1103                 bzero(&np, sizeof(np));
1104                 np.p_net_type = sc->sc_d.np_net_type;
1105                 bcopy(sc->sc_d.np_ssid, np.p_ssid,  IEEE80211_NWID_LEN);
1106                 np.p_privacy_must_start = sc->sc_d.np_priv_start;
1107                 np.p_privacy_can_join = sc->sc_d.np_priv_join;
1108                 SRAM_WRITE_REGION(sc, RAY_HOST_TO_ECF_BASE, &np, sizeof(np));
1109                 SRAM_WRITE_FIELD_1(sc, com->c_ccs, ray_cmd_net, c_upd_param, 1);
1110         } else
1111                 SRAM_WRITE_FIELD_1(sc, com->c_ccs, ray_cmd_net, c_upd_param, 0);
1112
1113         /*
1114          * Kick the card
1115          */
1116         ray_com_ecf(sc, com);
1117 }
1118
1119 /*
1120  * Complete start command or intermediate step in assoc command
1121  */
1122 static void
1123 ray_init_sj_done(struct ray_softc *sc, u_int8_t status, size_t ccs)
1124 {
1125         struct ifnet *ifp = &sc->arpcom.ac_if;
1126
1127         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, "");
1128         RAY_MAP_CM(sc);
1129         RAY_COM_CHECK(sc, ccs);
1130
1131         RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */
1132
1133         /*
1134          * Read back network parameters that the ECF sets
1135          */
1136         SRAM_READ_REGION(sc, ccs, &sc->sc_c.p_1, sizeof(struct ray_cmd_net));
1137
1138         /* Adjust values for buggy firmware */
1139         if (sc->sc_c.np_inited == 0x55)
1140                 sc->sc_c.np_inited = 0;
1141         if (sc->sc_c.np_def_txrate == 0x55)
1142                 sc->sc_c.np_def_txrate = sc->sc_d.np_def_txrate;
1143         if (sc->sc_c.np_encrypt == 0x55)
1144                 sc->sc_c.np_encrypt = sc->sc_d.np_encrypt;
1145
1146         /*
1147          * Update our local state if we updated the network parameters
1148          * when the START_NET or JOIN_NET was issued.
1149          */
1150         if (sc->sc_c.np_upd_param) {
1151                 RAY_DPRINTF(sc, RAY_DBG_STARTJOIN, "updated parameters");
1152                 SRAM_READ_REGION(sc, RAY_HOST_TO_ECF_BASE,
1153                     &sc->sc_c.p_2, sizeof(struct ray_net_params));
1154         }
1155
1156         /*
1157          * Hurrah! The network is now active.
1158          *
1159          * Clearing IFF_OACTIVE will ensure that the system will send us
1160          * packets. Just before we return from the interrupt context
1161          * we check to see if packets have been queued.
1162          */
1163         if (SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd) == RAY_CMD_START_NET) {
1164                 sc->sc_c.np_havenet = 1;
1165                 sc->sc_c.np_framing = sc->sc_d.np_framing;
1166                 ifp->if_flags |= IFF_RUNNING;
1167                 ifp->if_flags &= ~IFF_OACTIVE;
1168         }
1169
1170         ray_com_ecf_done(sc);
1171 }
1172
1173 /*
1174  * Runq entry to authenticate with an access point or another station
1175  */
1176 static void
1177 ray_init_auth(struct ray_softc *sc, struct ray_comq_entry *com)
1178 {
1179         struct ifnet *ifp = &sc->arpcom.ac_if;
1180
1181         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN | RAY_DBG_AUTH, "");
1182
1183         /* If card already running we might not need to authenticate */
1184         RAY_COM_CHKRUNNING(sc, com, ifp);
1185
1186         /*
1187          * XXX Don't do anything if we are not in a managed network
1188          *
1189          * XXX V4 adhoc does not need this, V5 adhoc unknown
1190          */
1191         if (sc->sc_c.np_net_type != RAY_MIB_NET_TYPE_INFRA) {
1192                 ray_com_runq_done(sc);
1193                 return;
1194         }
1195
1196 /*
1197  * XXX_AUTH need to think of run queue when doing auths from request i.e. would
1198  * XXX_AUTH need to have auth at top of runq?
1199  * XXX_AUTH ditto for sending any auth response packets...what about timeouts?
1200  */
1201
1202         /*
1203          * Kick the card
1204          */
1205 /* XXX_AUTH check exit status and retry or fail as we can't associate without this */
1206         ray_init_auth_send(sc, sc->sc_c.np_bss_id, IEEE80211_AUTH_OPEN_REQUEST);
1207 }
1208
1209 /*
1210  * Build and send an authentication packet
1211  *
1212  * If an error occurs, returns 1 else returns 0.
1213  */
1214 static int
1215 ray_init_auth_send(struct ray_softc *sc, u_int8_t *dst, int sequence)
1216 {
1217         size_t ccs, bufp;
1218         int pktlen = 0;
1219
1220         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN | RAY_DBG_AUTH, "");
1221
1222         /* Get a control block */
1223         if (ray_ccs_tx(sc, &ccs, &bufp)) {
1224                 RAY_RECERR(sc, "could not obtain a ccs");
1225                 return (1);
1226         }
1227
1228         /* Fill the header in */
1229         bufp = ray_tx_wrhdr(sc, bufp,
1230             IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_AUTH,
1231             IEEE80211_FC1_DIR_NODS,
1232             dst,
1233             sc->arpcom.ac_enaddr,
1234             sc->sc_c.np_bss_id);
1235
1236         /* Add algorithm number */
1237         SRAM_WRITE_1(sc, bufp + pktlen++, IEEE80211_AUTH_ALG_OPEN);
1238         SRAM_WRITE_1(sc, bufp + pktlen++, 0);
1239
1240         /* Add sequence number */
1241         SRAM_WRITE_1(sc, bufp + pktlen++, sequence);
1242         SRAM_WRITE_1(sc, bufp + pktlen++, 0);
1243
1244         /* Add status code */
1245         SRAM_WRITE_1(sc, bufp + pktlen++, 0);
1246         SRAM_WRITE_1(sc, bufp + pktlen++, 0);
1247         pktlen += sizeof(struct ieee80211_frame);
1248
1249         return (ray_tx_send(sc, ccs, pktlen, dst));
1250 }
1251
1252 /*
1253  * Complete authentication runq
1254  */
1255 static void
1256 ray_init_auth_done(struct ray_softc *sc, u_int8_t status)
1257 {
1258         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN | RAY_DBG_AUTH, "");
1259
1260         if (status != IEEE80211_STATUS_SUCCESS)
1261                 RAY_RECERR(sc, "authentication failed with status %d", status);
1262 /*
1263  * XXX_AUTH retry? if not just recall ray_init_auth_send and dont clear runq?
1264  * XXX_AUTH association requires that authenitcation is successful
1265  * XXX_AUTH before we associate, and the runq is the only way to halt the
1266  * XXX_AUTH progress of associate.
1267  * XXX_AUTH In this case I might not need the RAY_AUTH_NEEDED state
1268  */
1269         ray_com_runq_done(sc);
1270 }
1271
1272 /*
1273  * Runq entry to starting an association with an access point
1274  */
1275 static void
1276 ray_init_assoc(struct ray_softc *sc, struct ray_comq_entry *com)
1277 {
1278         struct ifnet *ifp = &sc->arpcom.ac_if;
1279
1280         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, "");
1281
1282         /* If the card already running we might not need to associate */
1283         RAY_COM_CHKRUNNING(sc, com, ifp);
1284
1285         /*
1286          * Don't do anything if we are not in a managed network
1287          */
1288         if (sc->sc_c.np_net_type != RAY_MIB_NET_TYPE_INFRA) {
1289                 ray_com_runq_done(sc);
1290                 return;
1291         }
1292
1293         /*
1294          * Kick the card
1295          */
1296         ray_ccs_fill(sc, com->c_ccs, RAY_CMD_START_ASSOC);
1297         ray_com_ecf(sc, com);
1298 }
1299
1300 /*
1301  * Complete association
1302  */
1303 static void
1304 ray_init_assoc_done(struct ray_softc *sc, u_int8_t status, size_t ccs)
1305 {
1306         struct ifnet *ifp = &sc->arpcom.ac_if;
1307
1308         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, "");
1309         RAY_COM_CHECK(sc, ccs);
1310
1311         RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */
1312         
1313         /*
1314          * Hurrah! The network is now active.
1315          *
1316          * Clearing IFF_OACTIVE will ensure that the system will send us
1317          * packets. Just before we return from the interrupt context
1318          * we check to see if packets have been queued.
1319          */
1320         sc->sc_c.np_havenet = 1;
1321         sc->sc_c.np_framing = sc->sc_d.np_framing;
1322         ifp->if_flags |= IFF_RUNNING;
1323         ifp->if_flags &= ~IFF_OACTIVE;
1324
1325         ray_com_ecf_done(sc);
1326 }
1327
1328 /*
1329  * Network stop.
1330  *
1331  * Inhibit card - if we can't prevent reception then do not worry;
1332  * stopping a NIC only guarantees no TX.
1333  *
1334  * The change to the interface flags is done via the runq so that any
1335  * existing commands can execute normally.
1336  */
1337 static int
1338 ray_stop_user(struct ray_softc *sc)
1339 {
1340         struct ray_comq_entry *com[1];
1341         int error, ncom;
1342
1343         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STOP, "");
1344
1345         /*
1346          * Schedule the real stop routine
1347          */
1348         ncom = 0;
1349         com[ncom++] = RAY_COM_MALLOC(ray_stop, 0);
1350
1351         RAY_COM_RUNQ(sc, com, ncom, "raystop", error);
1352
1353         /* XXX no real error processing from anything yet! */
1354
1355         RAY_COM_FREE(com, ncom);
1356
1357         return (error);
1358 }
1359
1360 /*
1361  * Runq entry for stopping the interface activity
1362  */
1363 static void
1364 ray_stop(struct ray_softc *sc, struct ray_comq_entry *com)
1365 {
1366         struct ifnet *ifp = &sc->arpcom.ac_if;
1367         struct mbuf *m;
1368
1369         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STOP, "");
1370
1371         /*
1372          * Mark as not running and drain output queue
1373          */
1374         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1375         ifp->if_timer = 0;
1376         for (;;) {
1377                 IF_DEQUEUE(&ifp->if_snd, m);
1378                 if (m == NULL)
1379                         break;
1380                 m_freem(m);
1381         }
1382
1383         ray_com_runq_done(sc);
1384 }
1385
1386 static void
1387 ray_watchdog(struct ifnet *ifp)
1388 {
1389         struct ray_softc *sc = ifp->if_softc;
1390
1391         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
1392         RAY_MAP_CM(sc);
1393
1394         if ((sc == NULL) || (sc->sc_gone))
1395                 return;
1396
1397         RAY_PRINTF(sc, "watchdog timeout");
1398 }
1399
1400 /*
1401  * Transmit packet handling
1402  */
1403
1404 /*
1405  * Send a packet.
1406  *
1407  * We make two assumptions here:
1408  *  1) That the current priority is set to splimp _before_ this code
1409  *     is called *and* is returned to the appropriate priority after
1410  *     return
1411  *  2) That the IFF_OACTIVE flag is checked before this code is called
1412  *     (i.e. that the output part of the interface is idle)
1413  *
1414  * A simple one packet at a time TX routine is used - we don't bother
1415  * chaining TX buffers. Performance is sufficient to max out the
1416  * wireless link on a P75.
1417  *
1418  * AST J30 Windows 95A (100MHz Pentium) to
1419  *   Libretto 50CT FreeBSD-3.1 (75MHz Pentium)          167.37kB/s
1420  *   Nonname box FreeBSD-3.4 (233MHz AMD K6)            161.82kB/s
1421  *
1422  * Libretto 50CT FreeBSD-3.1 (75MHz Pentium) to
1423  *   AST J30 Windows 95A (100MHz Pentium)               167.37kB/s
1424  *   Nonname box FreeBSD-3.4 (233MHz AMD K6)            161.38kB/s
1425  *
1426  * Given that 160kB/s is saturating the 2Mb/s wireless link we
1427  * are about there.
1428  *
1429  * In short I'm happy that the added complexity of chaining TX
1430  * packets together isn't worth it for my machines.
1431  */
1432 static void
1433 ray_tx(struct ifnet *ifp)
1434 {
1435         struct ray_softc *sc = ifp->if_softc;
1436         struct mbuf *m0, *m;
1437         struct ether_header *eh;
1438         struct llc *llc;
1439         size_t ccs, bufp;
1440         int pktlen, len;
1441
1442         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_TX, "");
1443         RAY_MAP_CM(sc);
1444
1445         /*
1446          * Some simple checks first - some are overkill
1447          */
1448         if ((sc == NULL) || (sc->sc_gone))
1449                 return;
1450         if (!(ifp->if_flags & IFF_RUNNING)) {
1451                 RAY_RECERR(sc, "cannot transmit - not running");
1452                 return;
1453         }
1454         if (!sc->sc_c.np_havenet) {
1455                 RAY_RECERR(sc, "cannot transmit - no network");
1456                 return;
1457         }
1458         if (!RAY_ECF_READY(sc)) {
1459                 /* Can't assume that the ECF is busy because of this driver */
1460                 if ((sc->tx_timerh.callout == NULL) ||
1461                     (!callout_active(sc->tx_timerh.callout))) {
1462                         sc->tx_timerh =
1463                             timeout(ray_tx_timo, sc, RAY_TX_TIMEOUT);
1464                         return;
1465                     }
1466         } else
1467                 untimeout(ray_tx_timo, sc, sc->tx_timerh);
1468
1469         /*
1470          * We find a ccs before we process the mbuf so that we are sure it
1471          * is worthwhile processing the packet. All errors in the mbuf
1472          * processing are either errors in the mbuf or gross configuration
1473          * errors and the packet wouldn't get through anyway.
1474          */
1475         if (ray_ccs_tx(sc, &ccs, &bufp)) {
1476                 ifp->if_flags |= IFF_OACTIVE;
1477                 return;
1478         }
1479     
1480         /*
1481          * Get the mbuf and process it - we have to remember to free the
1482          * ccs if there are any errors.
1483          */
1484         IF_DEQUEUE(&ifp->if_snd, m0);
1485         if (m0 == NULL) {
1486                 RAY_CCS_FREE(sc, ccs);
1487                 return;
1488         }
1489
1490         pktlen = m0->m_pkthdr.len;
1491         if (pktlen > ETHER_MAX_LEN - ETHER_CRC_LEN) {
1492                 RAY_RECERR(sc, "mbuf too long %d", pktlen);
1493                 RAY_CCS_FREE(sc, ccs);
1494                 ifp->if_oerrors++;
1495                 m_freem(m0);
1496                 return;
1497         }
1498
1499         m0 = m_pullup(m0, sizeof(struct ether_header));
1500         if (m0 == NULL) {
1501                 RAY_RECERR(sc, "could not pullup ether");
1502                 RAY_CCS_FREE(sc, ccs);
1503                 ifp->if_oerrors++;
1504                 return;
1505         }
1506         eh = mtod(m0, struct ether_header *);
1507
1508         /*
1509          * Write the 802.11 header according to network type etc.
1510          */
1511         if (sc->sc_c.np_net_type == RAY_MIB_NET_TYPE_ADHOC)
1512                 bufp = ray_tx_wrhdr(sc, bufp,
1513                     IEEE80211_FC0_TYPE_DATA,
1514                     IEEE80211_FC1_DIR_NODS,
1515                     eh->ether_dhost,
1516                     eh->ether_shost,
1517                     sc->sc_c.np_bss_id);
1518         else
1519                 if (sc->sc_c.np_ap_status == RAY_MIB_AP_STATUS_TERMINAL)
1520                         bufp = ray_tx_wrhdr(sc, bufp,
1521                             IEEE80211_FC0_TYPE_DATA,
1522                             IEEE80211_FC1_DIR_TODS,
1523                             sc->sc_c.np_bss_id,
1524                             eh->ether_shost,
1525                             eh->ether_dhost);
1526                 else
1527                         bufp = ray_tx_wrhdr(sc, bufp,
1528                             IEEE80211_FC0_TYPE_DATA,
1529                             IEEE80211_FC1_DIR_FROMDS,
1530                             eh->ether_dhost,
1531                             sc->sc_c.np_bss_id,
1532                             eh->ether_shost);
1533
1534         /*
1535          * Framing
1536          *
1537          * Add to the mbuf.
1538          */
1539         switch (sc->sc_c.np_framing) {
1540
1541         case RAY_FRAMING_ENCAPSULATION:
1542                 /* Nice and easy - nothing! (just add an 802.11 header) */
1543                 break;
1544
1545         case RAY_FRAMING_TRANSLATION:
1546                 /*
1547                  * Drop the first address in the ethernet header and
1548                  * write an LLC and SNAP header over the second.
1549                  */
1550                 m_adj(m0, ETHER_ADDR_LEN);
1551                 if (m0 == NULL) {
1552                         RAY_RECERR(sc, "could not get space for 802.2 header");
1553                         RAY_CCS_FREE(sc, ccs);
1554                         ifp->if_oerrors++;
1555                         return;
1556                 }
1557                 llc = mtod(m0, struct llc *);
1558                 llc->llc_dsap = LLC_SNAP_LSAP;
1559                 llc->llc_ssap = LLC_SNAP_LSAP;
1560                 llc->llc_control = LLC_UI;
1561                 llc->llc_un.type_snap.org_code[0] = 0;
1562                 llc->llc_un.type_snap.org_code[1] = 0;
1563                 llc->llc_un.type_snap.org_code[2] = 0;
1564                 break;
1565
1566         default:
1567                 RAY_RECERR(sc, "unknown framing type %d", sc->sc_c.np_framing);
1568                 RAY_CCS_FREE(sc, ccs);
1569                 ifp->if_oerrors++;
1570                 m_freem(m0);
1571                 return;
1572
1573         }
1574         if (m0 == NULL) {
1575                 RAY_RECERR(sc, "could not frame packet");
1576                 RAY_CCS_FREE(sc, ccs);
1577                 ifp->if_oerrors++;
1578                 return;
1579         }
1580         RAY_MBUF_DUMP(sc, RAY_DBG_TX, m0, "framed packet");
1581
1582         /*
1583          * Copy the mbuf to the buffer in common memory
1584          *
1585          * We drop and don't bother wrapping as Ethernet packets are 1518
1586          * bytes, we checked the mbuf earlier, and our TX buffers are 2048
1587          * bytes. We don't have 530 bytes of headers etc. so something
1588          * must be fubar.
1589          */
1590         pktlen = sizeof(struct ieee80211_frame);
1591         for (m = m0; m != NULL; m = m->m_next) {
1592                 pktlen += m->m_len;
1593                 if ((len = m->m_len) == 0)
1594                         continue;
1595                 if ((bufp + len) < RAY_TX_END)
1596                         SRAM_WRITE_REGION(sc, bufp, mtod(m, u_int8_t *), len);
1597                 else {
1598                         RAY_RECERR(sc, "tx buffer overflow");
1599                         RAY_CCS_FREE(sc, ccs);
1600                         ifp->if_oerrors++;
1601                         m_freem(m0);
1602                         return;
1603                 }
1604                 bufp += len;
1605         }
1606
1607         /*
1608          * Send it off
1609          */
1610         if (ray_tx_send(sc, ccs, pktlen, eh->ether_dhost))
1611                 ifp->if_oerrors++;
1612         else
1613                 ifp->if_opackets++;
1614         m_freem(m0);
1615 }
1616
1617 /*
1618  * Start timeout routine.
1619  *
1620  * Used when card was busy but we needed to send a packet.
1621  */
1622 static void
1623 ray_tx_timo(void *xsc)
1624 {
1625         struct ray_softc *sc = (struct ray_softc *)xsc;
1626         struct ifnet *ifp = &sc->arpcom.ac_if;
1627         int s;
1628
1629         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
1630
1631         if (!(ifp->if_flags & IFF_OACTIVE) && (ifp->if_snd.ifq_head != NULL)) {
1632                 s = splimp();
1633                 ray_tx(ifp);
1634                 splx(s);
1635         }
1636 }
1637
1638 /*
1639  * Write an 802.11 header into the Tx buffer space and return the
1640  * adjusted buffer pointer.
1641  */
1642 static size_t
1643 ray_tx_wrhdr(struct ray_softc *sc, size_t bufp, u_int8_t type, u_int8_t fc1, u_int8_t *addr1, u_int8_t *addr2, u_int8_t *addr3)
1644 {
1645         struct ieee80211_frame header;
1646
1647         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_TX, "");
1648         RAY_MAP_CM(sc);
1649
1650         bzero(&header, sizeof(struct ieee80211_frame));
1651         header.i_fc[0] = (IEEE80211_FC0_VERSION_0 | type);
1652         header.i_fc[1] = fc1;
1653         bcopy(addr1, header.i_addr1, ETHER_ADDR_LEN);
1654         bcopy(addr2, header.i_addr2, ETHER_ADDR_LEN);
1655         bcopy(addr3, header.i_addr3, ETHER_ADDR_LEN);
1656
1657         SRAM_WRITE_REGION(sc, bufp, (u_int8_t *)&header,
1658             sizeof(struct ieee80211_frame));
1659
1660         return (bufp + sizeof(struct ieee80211_frame));
1661 }
1662
1663 /*
1664  * Fill in a few loose ends and kick the card to send the packet
1665  *
1666  * Returns 0 on success, 1 on failure
1667  */
1668 static int
1669 ray_tx_send(struct ray_softc *sc, size_t ccs, int pktlen, u_int8_t *dst)
1670 {
1671         int i = 0;
1672
1673         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_TX, "");
1674         RAY_MAP_CM(sc);
1675
1676         while (!RAY_ECF_READY(sc)) {
1677                 DELAY(RAY_ECF_SPIN_DELAY);
1678                 if (++i > RAY_ECF_SPIN_TRIES) {
1679                         RAY_RECERR(sc, "ECF busy, dropping packet");
1680                         RAY_CCS_FREE(sc, ccs);
1681                         return (1);
1682                 }
1683         }
1684         if (i != 0)
1685                 RAY_RECERR(sc, "spun %d times", i);
1686
1687         SRAM_WRITE_FIELD_2(sc, ccs, ray_cmd_tx, c_len, pktlen);
1688         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_antenna,
1689             ray_tx_best_antenna(sc, dst));
1690         SRAM_WRITE_1(sc, RAY_SCB_CCSI, RAY_CCS_INDEX(ccs));
1691         RAY_ECF_START_CMD(sc);
1692
1693         return (0);
1694 }
1695
1696 /*
1697  * Determine best antenna to use from rx level and antenna cache
1698  */
1699 static u_int8_t
1700 ray_tx_best_antenna(struct ray_softc *sc, u_int8_t *dst)
1701 {
1702         struct ray_siglev *sl;
1703         int i;
1704         u_int8_t antenna;
1705
1706         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_TX, "");
1707
1708         if (sc->sc_version == RAY_ECFS_BUILD_4) 
1709                 return (0);
1710
1711         /* try to find host */
1712         for (i = 0; i < RAY_NSIGLEVRECS; i++) {
1713                 sl = &sc->sc_siglevs[i];
1714                 if (bcmp(sl->rsl_host, dst, ETHER_ADDR_LEN) == 0)
1715                         goto found;
1716         }
1717         /* not found, return default setting */
1718         return (0);
1719
1720 found:
1721         /* This is a simple thresholding scheme that takes the mean
1722          * of the best antenna history. This is okay but as it is a
1723          * filter, it adds a bit of lag in situations where the
1724          * best antenna swaps from one side to the other slowly. Don't know
1725          * how likely this is given the horrible fading though.
1726          */
1727         antenna = 0;
1728         for (i = 0; i < RAY_NANTENNA; i++) {
1729                 antenna += sl->rsl_antennas[i];
1730         }
1731
1732         return (antenna > (RAY_NANTENNA >> 1));
1733 }
1734
1735 /*
1736  * Transmit now complete so clear ccs and network flags.
1737  */
1738 static void
1739 ray_tx_done(struct ray_softc *sc, u_int8_t status, size_t ccs)
1740 {
1741         struct ifnet *ifp = &sc->arpcom.ac_if;
1742
1743         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_TX, "");
1744
1745         RAY_CCSERR(sc, status, if_oerrors);
1746
1747         RAY_CCS_FREE(sc, ccs);
1748         ifp->if_timer = 0;
1749         if (ifp->if_flags & IFF_OACTIVE)
1750             ifp->if_flags &= ~IFF_OACTIVE;
1751 }
1752
1753 /*
1754  * Receiver packet handling
1755  */
1756
1757 /*
1758  * Receive a packet from the card
1759  */
1760 static void
1761 ray_rx(struct ray_softc *sc, size_t rcs)
1762 {
1763         struct ieee80211_frame *header;
1764         struct ifnet *ifp = &sc->arpcom.ac_if;
1765         struct mbuf *m0;
1766         size_t pktlen, fraglen, readlen, tmplen;
1767         size_t bufp, ebufp;
1768         u_int8_t siglev, antenna;
1769         u_int first, ni, i;
1770         u_int8_t *mp;
1771
1772         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
1773         RAY_MAP_CM(sc);
1774
1775         RAY_DPRINTF(sc, RAY_DBG_CCS, "using rcs 0x%x", rcs);
1776
1777         m0 = NULL;
1778         readlen = 0;
1779
1780         /*
1781          * Get first part of packet and the length. Do some sanity checks
1782          * and get a mbuf.
1783          */
1784         first = RAY_CCS_INDEX(rcs);
1785         pktlen = SRAM_READ_FIELD_2(sc, rcs, ray_cmd_rx, c_pktlen);
1786         siglev = SRAM_READ_FIELD_1(sc, rcs, ray_cmd_rx, c_siglev);
1787         antenna = SRAM_READ_FIELD_1(sc, rcs, ray_cmd_rx, c_antenna);
1788
1789         if ((pktlen > MCLBYTES) || (pktlen < sizeof(struct ieee80211_frame))) {
1790                 RAY_RECERR(sc, "packet too big or too small");
1791                 ifp->if_ierrors++;
1792                 goto skip_read;
1793         }
1794
1795         MGETHDR(m0, M_DONTWAIT, MT_DATA);
1796         if (m0 == NULL) {
1797                 RAY_RECERR(sc, "MGETHDR failed");
1798                 ifp->if_ierrors++;
1799                 goto skip_read;
1800         }
1801         if (pktlen > MHLEN) {
1802                 MCLGET(m0, M_DONTWAIT);
1803                 if (!(m0->m_flags & M_EXT)) {
1804                         RAY_RECERR(sc, "MCLGET failed");
1805                         ifp->if_ierrors++;
1806                         m_freem(m0);
1807                         m0 = NULL;
1808                         goto skip_read;
1809                 }
1810         }
1811         m0->m_pkthdr.rcvif = ifp;
1812         m0->m_pkthdr.len = pktlen;
1813         m0->m_len = pktlen;
1814         mp = mtod(m0, u_int8_t *);
1815
1816         /*
1817          * Walk the fragment chain to build the complete packet.
1818          *
1819          * The use of two index variables removes a race with the
1820          * hardware. If one index were used the clearing of the CCS would
1821          * happen before reading the next pointer and the hardware can get in.
1822          * Not my idea but verbatim from the NetBSD driver.
1823          */
1824         i = ni = first;
1825         while ((i = ni) && (i != RAY_CCS_LINK_NULL)) {
1826                 rcs = RAY_CCS_ADDRESS(i);
1827                 ni = SRAM_READ_FIELD_1(sc, rcs, ray_cmd_rx, c_nextfrag);
1828                 bufp = SRAM_READ_FIELD_2(sc, rcs, ray_cmd_rx, c_bufp);
1829                 fraglen = SRAM_READ_FIELD_2(sc, rcs, ray_cmd_rx, c_len);
1830                 if (fraglen + readlen > pktlen) {
1831                         RAY_RECERR(sc, "bad length current 0x%x pktlen 0x%x",
1832                             fraglen + readlen, pktlen);
1833                         ifp->if_ierrors++;
1834                         m_freem(m0);
1835                         m0 = NULL;
1836                         goto skip_read;
1837                 }
1838                 if ((i < RAY_RCS_FIRST) || (i > RAY_RCS_LAST)) {
1839                         RAY_RECERR(sc, "bad rcs index 0x%x", i);
1840                         ifp->if_ierrors++;
1841                         m_freem(m0);
1842                         m0 = NULL;
1843                         goto skip_read;
1844                 }
1845
1846                 ebufp = bufp + fraglen;
1847                 if (ebufp <= RAY_RX_END)
1848                         SRAM_READ_REGION(sc, bufp, mp, fraglen);
1849                 else {
1850                         SRAM_READ_REGION(sc, bufp, mp,
1851                             (tmplen = RAY_RX_END - bufp));
1852                         SRAM_READ_REGION(sc, RAY_RX_BASE, mp + tmplen,
1853                             ebufp - RAY_RX_END);
1854                 }
1855                 mp += fraglen;
1856                 readlen += fraglen;
1857         }
1858
1859 skip_read:
1860
1861         /*
1862          * Walk the chain again to free the rcss.
1863          */
1864         i = ni = first;
1865         while ((i = ni) && (i != RAY_CCS_LINK_NULL)) {
1866                 rcs = RAY_CCS_ADDRESS(i);
1867                 ni = SRAM_READ_FIELD_1(sc, rcs, ray_cmd_rx, c_nextfrag);
1868                 RAY_CCS_FREE(sc, rcs);
1869         }
1870
1871         if (m0 == NULL)
1872                 return;
1873
1874         /*
1875          * Check the 802.11 packet type and hand off to
1876          * appropriate functions.
1877          */
1878         header = mtod(m0, struct ieee80211_frame *);
1879         if ((header->i_fc[0] & IEEE80211_FC0_VERSION_MASK)
1880             != IEEE80211_FC0_VERSION_0) {
1881                 RAY_RECERR(sc, "header not version 0 fc0 0x%x",
1882                     header->i_fc[0]);
1883                 ifp->if_ierrors++;
1884                 m_freem(m0);
1885                 return;
1886         }
1887         switch (header->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
1888
1889         case IEEE80211_FC0_TYPE_DATA:
1890                 ray_rx_data(sc, m0, siglev, antenna);
1891                 break;
1892
1893         case IEEE80211_FC0_TYPE_MGT:
1894                 ray_rx_mgt(sc, m0);
1895                 break;
1896
1897         case IEEE80211_FC0_TYPE_CTL:
1898                 ray_rx_ctl(sc, m0);
1899                 break;
1900
1901         default:
1902                 RAY_RECERR(sc, "unknown packet fc0 0x%x", header->i_fc[0]);
1903                 ifp->if_ierrors++;
1904                 m_freem(m0);
1905         }
1906 }
1907
1908 /*
1909  * Deal with DATA packet types
1910  */
1911 static void
1912 ray_rx_data(struct ray_softc *sc, struct mbuf *m0, u_int8_t siglev, u_int8_t antenna)
1913 {
1914         struct ifnet *ifp = &sc->arpcom.ac_if;
1915         struct ieee80211_frame *header = mtod(m0, struct ieee80211_frame *);
1916         struct ether_header *eh;
1917         struct llc *llc;
1918         u_int8_t *sa = NULL, *da = NULL, *ra = NULL, *ta = NULL;
1919         int trim = 0;
1920
1921         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_RX, "");
1922
1923         /*
1924          * Check the the data packet subtype, some packets have
1925          * nothing in them so we will drop them here.
1926          */
1927         switch (header->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
1928
1929         case IEEE80211_FC0_SUBTYPE_DATA:
1930         case IEEE80211_FC0_SUBTYPE_CF_ACK:
1931         case IEEE80211_FC0_SUBTYPE_CF_POLL:
1932         case IEEE80211_FC0_SUBTYPE_CF_ACPL:
1933                 RAY_DPRINTF(sc, RAY_DBG_RX, "DATA packet");
1934                 break;
1935
1936         case IEEE80211_FC0_SUBTYPE_NODATA:
1937         case IEEE80211_FC0_SUBTYPE_CFACK:
1938         case IEEE80211_FC0_SUBTYPE_CFPOLL:
1939         case IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK:
1940                 RAY_DPRINTF(sc, RAY_DBG_RX, "NULL packet");
1941                 m_freem(m0);
1942                 return;
1943                 break;
1944
1945         default:
1946                 RAY_RECERR(sc, "reserved DATA packet subtype 0x%x",
1947                     header->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1948                 ifp->if_ierrors++;
1949                 m_freem(m0);
1950                 return;
1951         }
1952
1953         /*
1954          * Parse the To DS and From DS fields to determine the length
1955          * of the 802.11 header for use later on.
1956          *
1957          * Additionally, furtle out the right destination and
1958          * source MAC addresses for the packet. Packets may come via
1959          * APs so the MAC addresses of the immediate node may be
1960          * different from the node that actually sent us the packet.
1961          *
1962          *      da      destination address of final recipient
1963          *      sa      source address of orginator
1964          *      ra      receiver address of immediate recipient
1965          *      ta      transmitter address of immediate orginator
1966          *
1967          * Address matching is performed on da or sa with the AP or
1968          * BSSID in ra and ta.
1969          */
1970         RAY_MBUF_DUMP(sc, RAY_DBG_RX, m0, "(1) packet before framing");
1971         switch (header->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
1972
1973         case IEEE80211_FC1_DIR_NODS:
1974                 da = ra = header->i_addr1;
1975                 sa = ta = header->i_addr2;
1976                 trim = sizeof(struct ieee80211_frame);
1977                 RAY_DPRINTF(sc, RAY_DBG_RX, "from %6D to %6D",
1978                     sa, ":", da, ":");
1979                 break;
1980
1981         case IEEE80211_FC1_DIR_FROMDS:
1982                 da = ra = header->i_addr1;
1983                 ta = header->i_addr2;
1984                 sa = header->i_addr3;
1985                 trim = sizeof(struct ieee80211_frame);
1986                 RAY_DPRINTF(sc, RAY_DBG_RX, "ap %6D from %6D to %6D",
1987                     ta, ":", sa, ":", da, ":");
1988                 break;
1989
1990         case IEEE80211_FC1_DIR_TODS:
1991                 ra = header->i_addr1;
1992                 sa = ta = header->i_addr2;
1993                 da = header->i_addr3;
1994                 trim = sizeof(struct ieee80211_frame);
1995                 RAY_DPRINTF(sc, RAY_DBG_RX, "from %6D to %6D ap %6D",
1996                     sa, ":", da, ":", ra, ":");
1997                 break;
1998
1999         case IEEE80211_FC1_DIR_DSTODS:
2000                 ra = header->i_addr1;
2001                 ta = header->i_addr2;
2002                 da = header->i_addr3;
2003                 sa = (u_int8_t *)header+1;
2004                 trim = sizeof(struct ieee80211_frame) + ETHER_ADDR_LEN;
2005                 RAY_DPRINTF(sc, RAY_DBG_RX, "from %6D to %6D ap %6D to %6D",
2006                     sa, ":", da, ":", ta, ":", ra, ":");
2007                 break;
2008         }
2009
2010         /*
2011          * Framing
2012          *
2013          * Each case must leave an Ethernet header and adjust trim.
2014          */
2015         switch (sc->sc_c.np_framing) {
2016
2017         case RAY_FRAMING_ENCAPSULATION:
2018                 /* A NOP as the Ethernet header is in the packet */
2019                 break;
2020
2021         case RAY_FRAMING_TRANSLATION:
2022                 /* Check that we have an LLC and SNAP sequence */
2023                 llc = (struct llc *)((u_int8_t *)header + trim);
2024                 if (llc->llc_dsap == LLC_SNAP_LSAP &&
2025                     llc->llc_ssap == LLC_SNAP_LSAP &&
2026                     llc->llc_control == LLC_UI &&
2027                     llc->llc_un.type_snap.org_code[0] == 0 &&
2028                     llc->llc_un.type_snap.org_code[1] == 0 &&
2029                     llc->llc_un.type_snap.org_code[2] == 0) {
2030                         /*
2031                          * This is not magic. RFC1042 header is 8
2032                          * bytes, with the last two bytes being the
2033                          * ether type. So all we need is another
2034                          * ETHER_ADDR_LEN bytes to write the
2035                          * destination into.
2036                          */
2037                         trim -= ETHER_ADDR_LEN;
2038                         eh = (struct ether_header *)((u_int8_t *)header + trim);
2039
2040                         /*
2041                          * Copy carefully to avoid mashing the MAC
2042                          * addresses. The address layout in the .11 header
2043                          * does make sense, honest, but it is a pain.
2044                          * 
2045                          * NODS         da sa           no risk              
2046                          * FROMDS       da ta sa        sa then da           
2047                          * DSTODS       ra ta da sa     sa then da           
2048                          * TODS         ra sa da        da then sa           
2049                          */
2050                         if (sa > da) {
2051                                 /* Copy sa first */
2052                                 bcopy(sa, eh->ether_shost, ETHER_ADDR_LEN);
2053                                 bcopy(da, eh->ether_dhost, ETHER_ADDR_LEN);
2054                         } else {
2055                                 /* Copy da first */
2056                                 bcopy(da, eh->ether_dhost, ETHER_ADDR_LEN);
2057                                 bcopy(sa, eh->ether_shost, ETHER_ADDR_LEN);
2058                         }
2059
2060                 } else {
2061
2062                         /* Assume RAY_FRAMING_ENCAPSULATION */
2063                         RAY_RECERR(sc,
2064                             "got encapsulated packet but in translation mode");
2065
2066                 }
2067                 break;
2068
2069         default:
2070                 RAY_RECERR(sc, "unknown framing type %d", sc->sc_c.np_framing);
2071                 ifp->if_ierrors++;
2072                 m_freem(m0);
2073                 return;
2074         }
2075         RAY_MBUF_DUMP(sc, RAY_DBG_RX, m0, "(2) packet after framing");
2076
2077         /*
2078          * Finally, do a bit of house keeping before sending the packet
2079          * up the stack.
2080          */
2081         m_adj(m0, trim);
2082         RAY_MBUF_DUMP(sc, RAY_DBG_RX, m0, "(3) packet after trimming");
2083         ifp->if_ipackets++;
2084         ray_rx_update_cache(sc, header->i_addr2, siglev, antenna);
2085         eh = mtod(m0, struct ether_header *);
2086         m_adj(m0, sizeof(struct ether_header));
2087         ether_input(ifp, eh, m0);
2088 }
2089
2090 /*
2091  * Deal with MGT packet types
2092  */
2093 static void
2094 ray_rx_mgt(struct ray_softc *sc, struct mbuf *m0)
2095 {
2096         struct ifnet *ifp = &sc->arpcom.ac_if;
2097         struct ieee80211_frame *header = mtod(m0, struct ieee80211_frame *);
2098
2099         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_MGT, "");
2100
2101         if ((header->i_fc[1] & IEEE80211_FC1_DIR_MASK) !=
2102             IEEE80211_FC1_DIR_NODS) {
2103                 RAY_RECERR(sc, "MGT TODS/FROMDS wrong fc1 0x%x",
2104                     header->i_fc[1] & IEEE80211_FC1_DIR_MASK);
2105                 ifp->if_ierrors++;
2106                 m_freem(m0);
2107                 return;
2108         }
2109
2110         /*
2111          * Check the the mgt packet subtype, some packets should be
2112          * dropped depending on the mode the station is in. See pg
2113          * 52(60) of docs
2114          *
2115          * P - proccess, J - Junk, E - ECF deals with, I - Illegal
2116          * ECF Proccesses
2117          *  AHDOC procces or junk
2118          *   INFRA STA process or junk
2119          *    INFRA AP process or jumk
2120          * 
2121          * +PPP IEEE80211_FC0_SUBTYPE_BEACON
2122          * +EEE IEEE80211_FC0_SUBTYPE_PROBE_REQ
2123          * +EEE IEEE80211_FC0_SUBTYPE_PROBE_RESP
2124          *  PPP IEEE80211_FC0_SUBTYPE_AUTH
2125          *  PPP IEEE80211_FC0_SUBTYPE_DEAUTH
2126          *  JJP IEEE80211_FC0_SUBTYPE_ASSOC_REQ
2127          *  JPJ IEEE80211_FC0_SUBTYPE_ASSOC_RESP
2128          *  JPP IEEE80211_FC0_SUBTYPE_DISASSOC
2129          *  JJP IEEE80211_FC0_SUBTYPE_REASSOC_REQ
2130          *  JPJ IEEE80211_FC0_SUBTYPE_REASSOC_RESP
2131          * +EEE IEEE80211_FC0_SUBTYPE_ATIM
2132          */
2133         RAY_MBUF_DUMP(sc, RAY_DBG_MGT, m0, "MGT packet");
2134         switch (header->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
2135
2136         case IEEE80211_FC0_SUBTYPE_BEACON:
2137                 RAY_DPRINTF(sc, RAY_DBG_MGT, "BEACON MGT packet");
2138                 ray_rx_mgt_beacon(sc, m0);
2139                 break;
2140
2141         case IEEE80211_FC0_SUBTYPE_AUTH:
2142                 RAY_DPRINTF(sc, RAY_DBG_MGT, "AUTH MGT packet");
2143                 ray_rx_mgt_auth(sc, m0);
2144                 break;
2145
2146         case IEEE80211_FC0_SUBTYPE_DEAUTH:
2147                 RAY_DPRINTF(sc, RAY_DBG_MGT, "DEAUTH MGT packet");
2148                 /* XXX ray_rx_mgt_deauth(sc, m0); */
2149                 break;
2150
2151         case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
2152         case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
2153                 RAY_DPRINTF(sc, RAY_DBG_MGT, "(RE)ASSOC_REQ MGT packet");
2154                 if ((sc->sc_c.np_net_type == RAY_MIB_NET_TYPE_INFRA) &&
2155                     (sc->sc_c.np_ap_status == RAY_MIB_AP_STATUS_AP))
2156                         RAY_RECERR(sc, "can't be an AP yet"); /* XXX_ACTING_AP */
2157                 break;
2158                         
2159         case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
2160         case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
2161                 RAY_DPRINTF(sc, RAY_DBG_MGT, "(RE)ASSOC_RESP MGT packet");
2162                 if ((sc->sc_c.np_net_type == RAY_MIB_NET_TYPE_INFRA) &&
2163                     (sc->sc_c.np_ap_status == RAY_MIB_AP_STATUS_TERMINAL))
2164                         RAY_RECERR(sc, "can't be in INFRA yet"); /* XXX_INFRA */
2165                 break;
2166
2167         case IEEE80211_FC0_SUBTYPE_DISASSOC:
2168                 RAY_DPRINTF(sc, RAY_DBG_MGT, "DISASSOC MGT packet");
2169                 if (sc->sc_c.np_net_type == RAY_MIB_NET_TYPE_INFRA)
2170                         RAY_RECERR(sc, "can't be in INFRA yet"); /* XXX_INFRA */
2171                 break;
2172
2173         case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
2174         case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
2175         case IEEE80211_FC0_SUBTYPE_ATIM:
2176                 RAY_RECERR(sc, "unexpected MGT packet subtype 0x%0x",
2177                     header->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2178                 ifp->if_ierrors++;
2179                 break;
2180                 
2181         default:
2182                 RAY_RECERR(sc, "reserved MGT packet subtype 0x%x",
2183                     header->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2184                 ifp->if_ierrors++;
2185         }
2186
2187         m_freem(m0);
2188 }
2189
2190 /*
2191  * Deal with BEACON management packet types
2192  * XXX furtle anything interesting out
2193  * XXX Note that there are rules governing what beacons to read
2194  * XXX see 8802 S7.2.3, S11.1.2.3
2195  * XXX is this actually useful?
2196  */
2197 static void
2198 ray_rx_mgt_beacon(struct ray_softc *sc, struct mbuf *m0)
2199 {
2200         struct ieee80211_frame *header = mtod(m0, struct ieee80211_frame *);
2201         ieee80211_mgt_beacon_t beacon = (u_int8_t *)(header+1);
2202         struct ieee80211_information elements;
2203
2204         u_int64_t *timestamp;
2205
2206         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_MGT, "");
2207
2208         timestamp = (u_int64_t *)beacon;
2209
2210 RAY_DPRINTF(sc, RAY_DBG_MGT, "timestamp\t0x%x", *timestamp);
2211 RAY_DPRINTF(sc, RAY_DBG_MGT, "interval\t\t0x%x", IEEE80211_BEACON_INTERVAL(beacon));
2212 RAY_DPRINTF(sc, RAY_DBG_MGT, "capability\t0x%x", IEEE80211_BEACON_CAPABILITY(beacon));
2213
2214         ray_rx_mgt_info(sc, m0, &elements);
2215
2216 }
2217
2218 static void
2219 ray_rx_mgt_info(struct ray_softc *sc, struct mbuf *m0, struct ieee80211_information *elements)
2220 {
2221         struct ifnet *ifp = &sc->arpcom.ac_if;
2222         struct ieee80211_frame *header = mtod(m0, struct ieee80211_frame *);
2223         ieee80211_mgt_beacon_t beacon = (u_int8_t *)(header+1);
2224         ieee80211_mgt_beacon_t bp, be;
2225         int len;
2226
2227         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_MGT, "");
2228
2229         bp = beacon + 12;
2230         be = mtod(m0, u_int8_t *) + m0->m_len;
2231         
2232         while (bp < be) {
2233                 len = *(bp + 1);
2234                 RAY_DPRINTF(sc, RAY_DBG_MGT, "id 0x%02x length %d", *bp, len);
2235
2236                 switch (*bp) {
2237
2238                 case IEEE80211_ELEMID_SSID:
2239                         if (len  > IEEE80211_NWID_LEN) {
2240                                 RAY_RECERR(sc, "bad SSD length: %d from %6D",
2241                                     len, header->i_addr2, ":");
2242                         }
2243                         strncpy(elements->ssid, bp + 2, len);
2244                         elements->ssid[len] = 0;
2245                         RAY_DPRINTF(sc, RAY_DBG_MGT,
2246                             "beacon ssid %s", elements->ssid);
2247                         break; 
2248
2249                 case IEEE80211_ELEMID_RATES:
2250                         RAY_DPRINTF(sc, RAY_DBG_MGT, "rates");
2251                         break;
2252
2253                 case IEEE80211_ELEMID_FHPARMS:
2254                         elements->fh.dwell = bp[2] + (bp[3] << 8);
2255                         elements->fh.set = bp[4];
2256                         elements->fh.pattern = bp[5];
2257                         elements->fh.index = bp[6];
2258                         RAY_DPRINTF(sc, RAY_DBG_MGT,
2259                             "fhparams dwell\t0x%04x", elements->fh.dwell);
2260                         RAY_DPRINTF(sc, RAY_DBG_MGT,
2261                             "fhparams set\t0x%02x", elements->fh.set);
2262                         RAY_DPRINTF(sc, RAY_DBG_MGT,
2263                             "fhparams pattern\t0x%02x", elements->fh.pattern);
2264                         RAY_DPRINTF(sc, RAY_DBG_MGT,
2265                             "fhparams index\t0x%02x", elements->fh.index);
2266                         break;
2267
2268                 case IEEE80211_ELEMID_DSPARMS:
2269                         RAY_RECERR(sc, "got direct sequence params!");
2270                         break;
2271
2272                 case IEEE80211_ELEMID_CFPARMS:
2273                         RAY_DPRINTF(sc, RAY_DBG_MGT, "cfparams");
2274                         break;
2275
2276                 case IEEE80211_ELEMID_TIM:
2277                         elements->tim.count = bp[2];
2278                         elements->tim.period = bp[3];
2279                         elements->tim.bitctl = bp[4];
2280                         RAY_DPRINTF(sc, RAY_DBG_MGT,
2281                             "tim count\t0x%02x", elements->tim.count);
2282                         RAY_DPRINTF(sc, RAY_DBG_MGT,
2283                             "tim period\t0x%02x", elements->tim.period);
2284                         RAY_DPRINTF(sc, RAY_DBG_MGT,
2285                             "tim bitctl\t0x%02x", elements->tim.bitctl);
2286 #if RAY_DEBUG & RAY_DBG_MGT
2287                         {
2288                                 int i;
2289                                 for (i = 5; i < len + 1; i++)
2290                                         RAY_DPRINTF(sc, RAY_DBG_MGT,
2291                                             "tim pvt[%03d]\t0x%02x", i-5, bp[i]);
2292                         }
2293 #endif
2294                         break;
2295                         
2296                 case IEEE80211_ELEMID_IBSSPARMS:
2297                         elements->ibss.atim = bp[2] + (bp[3] << 8);
2298                         RAY_DPRINTF(sc, RAY_DBG_MGT,
2299                             "ibssparams atim\t0x%02x", elements->ibss.atim);
2300                         break;
2301
2302                 case IEEE80211_ELEMID_CHALLENGE:
2303                         RAY_DPRINTF(sc, RAY_DBG_MGT, "challenge");
2304                         break;
2305
2306                 default:
2307                         RAY_RECERR(sc, "reserved MGT element id 0x%x", *bp);
2308                         ifp->if_ierrors++;break;
2309                 }
2310                 bp += bp[1] + 2; 
2311         }
2312 }
2313
2314 /*
2315  * Deal with AUTH management packet types
2316  */
2317 static void
2318 ray_rx_mgt_auth(struct ray_softc *sc, struct mbuf *m0)
2319 {
2320         struct ieee80211_frame *header = mtod(m0, struct ieee80211_frame *);
2321         ieee80211_mgt_auth_t auth = (u_int8_t *)(header+1);
2322
2323         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_AUTH, "");
2324
2325         switch (IEEE80211_AUTH_ALGORITHM(auth)) {
2326             
2327         case IEEE80211_AUTH_ALG_OPEN:
2328                 RAY_DPRINTF(sc, RAY_DBG_AUTH,
2329                     "open system authentication sequence number %d",
2330                     IEEE80211_AUTH_TRANSACTION(auth));
2331                 if (IEEE80211_AUTH_TRANSACTION(auth) ==
2332                     IEEE80211_AUTH_OPEN_REQUEST) {
2333
2334 /* XXX_AUTH use ray_init_auth_send */
2335
2336                 } else if (IEEE80211_AUTH_TRANSACTION(auth) == 
2337                     IEEE80211_AUTH_OPEN_RESPONSE)
2338                         ray_init_auth_done(sc, IEEE80211_AUTH_STATUS(auth));
2339                 break;
2340
2341         case IEEE80211_AUTH_ALG_SHARED:
2342                 RAY_RECERR(sc,
2343                     "shared key authentication sequence number %d",
2344                     IEEE80211_AUTH_TRANSACTION(auth));
2345                 break;
2346         
2347         default:
2348                 RAY_RECERR(sc,
2349                     "reserved authentication subtype 0x%04hx",
2350                     IEEE80211_AUTH_ALGORITHM(auth));
2351                 break;
2352         }
2353 }
2354
2355 /*
2356  * Deal with CTL packet types
2357  */
2358 static void
2359 ray_rx_ctl(struct ray_softc *sc, struct mbuf *m0)
2360 {
2361         struct ifnet *ifp = &sc->arpcom.ac_if;
2362         struct ieee80211_frame *header = mtod(m0, struct ieee80211_frame *);
2363
2364         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_CTL, "");
2365
2366         if ((header->i_fc[1] & IEEE80211_FC1_DIR_MASK) !=
2367             IEEE80211_FC1_DIR_NODS) {
2368                 RAY_RECERR(sc, "CTL TODS/FROMDS wrong fc1 0x%x",
2369                     header->i_fc[1] & IEEE80211_FC1_DIR_MASK);
2370                 ifp->if_ierrors++;
2371                 m_freem(m0);
2372                 return;
2373         }
2374
2375         /*
2376          * Check the the ctl packet subtype, some packets should be
2377          * dropped depending on the mode the station is in. The ECF
2378          * should deal with everything but the power save poll to an
2379          * AP. See pg 52(60) of docs.
2380          */
2381         RAY_MBUF_DUMP(sc, RAY_DBG_CTL, m0, "CTL packet");
2382         switch (header->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
2383
2384         case IEEE80211_FC0_SUBTYPE_PS_POLL:
2385                 RAY_DPRINTF(sc, RAY_DBG_CTL, "PS_POLL CTL packet");
2386                 if ((sc->sc_d.np_net_type == RAY_MIB_NET_TYPE_INFRA) &&
2387                     (sc->sc_c.np_ap_status == RAY_MIB_AP_STATUS_AP))
2388                         RAY_RECERR(sc, "can't be an AP yet"); /* XXX_ACTING_AP */
2389                 break;
2390
2391         case IEEE80211_FC0_SUBTYPE_RTS:
2392         case IEEE80211_FC0_SUBTYPE_CTS:
2393         case IEEE80211_FC0_SUBTYPE_ACK:
2394         case IEEE80211_FC0_SUBTYPE_CF_END:
2395         case IEEE80211_FC0_SUBTYPE_CF_END_ACK:
2396                 RAY_RECERR(sc, "unexpected CTL packet subtype 0x%0x",
2397                     header->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2398                 ifp->if_ierrors++;
2399                 break;
2400
2401         default:
2402                 RAY_RECERR(sc, "reserved CTL packet subtype 0x%x",
2403                     header->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2404                 ifp->if_ierrors++;
2405         }
2406
2407         m_freem(m0);
2408 }
2409
2410 /*
2411  * Update rx level and antenna cache
2412  */
2413 static void
2414 ray_rx_update_cache(struct ray_softc *sc, u_int8_t *src, u_int8_t siglev, u_int8_t antenna)
2415 {
2416         struct timeval mint;
2417         struct ray_siglev *sl;
2418         int i, mini;
2419
2420         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2421
2422         /* Try to find host */
2423         for (i = 0; i < RAY_NSIGLEVRECS; i++) {
2424                 sl = &sc->sc_siglevs[i];
2425                 if (bcmp(sl->rsl_host, src, ETHER_ADDR_LEN) == 0)
2426                         goto found;
2427         }
2428         /* Not found, find oldest slot */
2429         mini = 0;
2430         mint.tv_sec = LONG_MAX;
2431         mint.tv_usec = 0;
2432         for (i = 0; i < RAY_NSIGLEVRECS; i++) {
2433                 sl = &sc->sc_siglevs[i];
2434                 if (timevalcmp(&sl->rsl_time, &mint, <)) {
2435                         mini = i;
2436                         mint = sl->rsl_time;
2437                 }
2438         }
2439         sl = &sc->sc_siglevs[mini];
2440         bzero(sl->rsl_siglevs, RAY_NSIGLEV);
2441         bzero(sl->rsl_antennas, RAY_NANTENNA);
2442         bcopy(src, sl->rsl_host, ETHER_ADDR_LEN);
2443
2444 found:
2445         microtime(&sl->rsl_time);
2446         bcopy(sl->rsl_siglevs, &sl->rsl_siglevs[1], RAY_NSIGLEV-1);
2447         sl->rsl_siglevs[0] = siglev;
2448         if (sc->sc_version != RAY_ECFS_BUILD_4) {
2449                 bcopy(sl->rsl_antennas, &sl->rsl_antennas[1], RAY_NANTENNA-1);
2450                 sl->rsl_antennas[0] = antenna;
2451         }
2452 }
2453
2454 /*
2455  * Interrupt handling
2456  */
2457
2458 /*
2459  * Process an interrupt
2460  */
2461 static void
2462 ray_intr(void *xsc)
2463 {
2464         struct ray_softc *sc = (struct ray_softc *)xsc;
2465         struct ifnet *ifp = &sc->arpcom.ac_if;
2466         size_t ccs;
2467         u_int8_t cmd, status;
2468         int ccsi;
2469
2470         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2471         RAY_MAP_CM(sc);
2472
2473         if ((sc == NULL) || (sc->sc_gone))
2474                 return;
2475
2476         /*
2477          * Check that the interrupt was for us, if so get the rcs/ccs
2478          * and vector on the command contained within it.
2479          */
2480         if (RAY_HCS_INTR(sc)) {
2481                 ccsi = SRAM_READ_1(sc, RAY_SCB_RCSI);
2482                 ccs = RAY_CCS_ADDRESS(ccsi);
2483                 cmd = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd);
2484                 status = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status);
2485                 if (ccsi <= RAY_CCS_LAST)
2486                         ray_intr_ccs(sc, cmd, status, ccs);
2487                 else if (ccsi <= RAY_RCS_LAST)
2488                         ray_intr_rcs(sc, cmd, ccs);
2489                 else
2490                     RAY_RECERR(sc, "bad ccs index 0x%x", ccsi);
2491                 RAY_HCS_CLEAR_INTR(sc);
2492         }
2493
2494         /* Send any packets lying around and update error counters */
2495         if (!(ifp->if_flags & IFF_OACTIVE) && (ifp->if_snd.ifq_head != NULL))
2496                 ray_tx(ifp);
2497         if ((++sc->sc_checkcounters % 32) == 0)
2498                 ray_intr_updt_errcntrs(sc);
2499 }
2500
2501 /*
2502  * Read the error counters.
2503  */
2504 static void
2505 ray_intr_updt_errcntrs(struct ray_softc *sc)
2506 {
2507         size_t csc;
2508
2509         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2510         RAY_MAP_CM(sc);
2511
2512         /*
2513          * The card implements the following protocol to keep the
2514          * values from being changed while read: It checks the `own'
2515          * bit and if zero writes the current internal counter value,
2516          * it then sets the `own' bit to 1. If the `own' bit was 1 it
2517          * incremenets its internal counter. The user thus reads the
2518          * counter if the `own' bit is one and then sets the own bit
2519          * to 0.
2520          */
2521         csc = RAY_STATUS_BASE;
2522         if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_mrxo_own)) {
2523                 sc->sc_rxoverflow +=
2524                     SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_mrx_overflow);
2525                 SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_mrxo_own, 0);
2526         }
2527         if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_mrxc_own)) {
2528                 sc->sc_rxcksum +=
2529                     SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_mrx_overflow);
2530                 SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_mrxc_own, 0);
2531         }
2532         if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_rxhc_own)) {
2533                 sc->sc_rxhcksum +=
2534                     SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_rx_hcksum);
2535                 SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_rxhc_own, 0);
2536         }
2537         sc->sc_rxnoise = SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_rx_noise);
2538 }
2539
2540 /*
2541  * Process CCS command completion
2542  */
2543 static void
2544 ray_intr_ccs(struct ray_softc *sc, u_int8_t cmd, u_int8_t status, size_t ccs)
2545 {
2546         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2547
2548         switch (cmd) {
2549
2550         case RAY_CMD_DOWNLOAD_PARAMS:
2551                 RAY_DPRINTF(sc, RAY_DBG_COM, "START_PARAMS");
2552                 ray_init_download_done(sc, status, ccs);
2553                 break;
2554
2555         case RAY_CMD_UPDATE_PARAMS:
2556                 RAY_DPRINTF(sc, RAY_DBG_COM, "UPDATE_PARAMS");
2557                 ray_upparams_done(sc, status, ccs);
2558                 break;
2559
2560         case RAY_CMD_REPORT_PARAMS:
2561                 RAY_DPRINTF(sc, RAY_DBG_COM, "REPORT_PARAMS");
2562                 ray_repparams_done(sc, status, ccs);
2563                 break;
2564
2565         case RAY_CMD_UPDATE_MCAST:
2566                 RAY_DPRINTF(sc, RAY_DBG_COM, "UPDATE_MCAST");
2567                 ray_mcast_done(sc, status, ccs);
2568                 break;
2569
2570         case RAY_CMD_START_NET:
2571         case RAY_CMD_JOIN_NET:
2572                 RAY_DPRINTF(sc, RAY_DBG_COM, "START|JOIN_NET");
2573                 ray_init_sj_done(sc, status, ccs);
2574                 break;
2575
2576         case RAY_CMD_TX_REQ:
2577                 RAY_DPRINTF(sc, RAY_DBG_COM, "TX_REQ");
2578                 ray_tx_done(sc, status, ccs);
2579                 break;
2580
2581         case RAY_CMD_START_ASSOC:
2582                 RAY_DPRINTF(sc, RAY_DBG_COM, "START_ASSOC");
2583                 ray_init_assoc_done(sc, status, ccs);
2584                 break;
2585
2586         case RAY_CMD_UPDATE_APM:
2587                 RAY_RECERR(sc, "unexpected UPDATE_APM");
2588                 break;
2589
2590         case RAY_CMD_TEST_MEM:
2591                 RAY_RECERR(sc, "unexpected TEST_MEM");
2592                 break;
2593
2594         case RAY_CMD_SHUTDOWN:
2595                 RAY_RECERR(sc, "unexpected SHUTDOWN");
2596                 break;
2597
2598         case RAY_CMD_DUMP_MEM:
2599                 RAY_RECERR(sc, "unexpected DUMP_MEM");
2600                 break;
2601
2602         case RAY_CMD_START_TIMER:
2603                 RAY_RECERR(sc, "unexpected START_TIMER");
2604                 break;
2605
2606         default:
2607                 RAY_RECERR(sc, "unknown command 0x%x", cmd);
2608                 break;
2609         }
2610 }
2611
2612 /*
2613  * Process ECF command request
2614  */
2615 static void
2616 ray_intr_rcs(struct ray_softc *sc, u_int8_t cmd, size_t rcs)
2617 {
2618         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2619
2620         switch (cmd) {
2621
2622         case RAY_ECMD_RX_DONE:
2623                 RAY_DPRINTF(sc, RAY_DBG_RX, "RX_DONE");
2624                 ray_rx(sc, rcs);
2625                 break;
2626
2627         case RAY_ECMD_REJOIN_DONE:
2628                 RAY_DPRINTF(sc, RAY_DBG_RX, "REJOIN_DONE");
2629                 sc->sc_c.np_havenet = 1; /* XXX Should not be here but in function */
2630                 break;
2631
2632         case RAY_ECMD_ROAM_START:
2633                 RAY_DPRINTF(sc, RAY_DBG_RX, "ROAM_START");
2634                 sc->sc_c.np_havenet = 0; /* XXX Should not be here but in function */
2635                 break;
2636
2637         case RAY_ECMD_JAPAN_CALL_SIGNAL:
2638                 RAY_RECERR(sc, "unexpected JAPAN_CALL_SIGNAL");
2639                 break;
2640
2641         default:
2642                 RAY_RECERR(sc, "unknown command 0x%x", cmd);
2643                 break;
2644         }
2645
2646         RAY_CCS_FREE(sc, rcs);
2647 }
2648
2649 /*
2650  * User land entry to multicast list changes
2651  */
2652 static int
2653 ray_mcast_user(struct ray_softc *sc)
2654 {
2655         struct ray_comq_entry *com[2];
2656         int error, ncom;
2657
2658         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2659
2660         /*
2661          * Do all checking in the runq to preserve ordering.
2662          *
2663          * We run promisc to pick up changes to the ALL_MULTI
2664          * interface flag.
2665          */
2666         ncom = 0;
2667         com[ncom++] = RAY_COM_MALLOC(ray_mcast, 0);
2668         com[ncom++] = RAY_COM_MALLOC(ray_promisc, 0);
2669
2670         RAY_COM_RUNQ(sc, com, ncom, "raymcast", error);
2671
2672         /* XXX no real error processing from anything yet! */
2673
2674         RAY_COM_FREE(com, ncom);
2675
2676         return (error);
2677 }
2678
2679 /*
2680  * Runq entry to setting the multicast filter list
2681  *
2682  * MUST always be followed by a call to ray_promisc to pick up changes
2683  * to promisc flag
2684  */
2685 static void
2686 ray_mcast(struct ray_softc *sc, struct ray_comq_entry *com)
2687 {
2688         struct ifnet *ifp = &sc->arpcom.ac_if;
2689         struct ifmultiaddr *ifma;
2690         size_t bufp;
2691         int count = 0;
2692
2693         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2694         RAY_MAP_CM(sc);
2695
2696         /*
2697          * If card is not running we don't need to update this.
2698          */
2699         if (!(ifp->if_flags & IFF_RUNNING)) {
2700                 RAY_DPRINTF(sc, RAY_DBG_IOCTL, "not running");
2701                 ray_com_runq_done(sc);
2702                 return;
2703         }
2704
2705         /*
2706          * The multicast list is only 16 items long so use promiscuous
2707          * mode and don't bother updating the multicast list.
2708          */
2709         for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
2710             ifma = ifma->ifma_link.le_next)
2711                 count++;
2712         if (count == 0) {
2713                 ray_com_runq_done(sc);
2714                 return;
2715         } else if (count > 16) {
2716                 ifp->if_flags |= IFF_ALLMULTI;
2717                 ray_com_runq_done(sc);
2718                 return;
2719         } else if (ifp->if_flags & IFF_ALLMULTI)
2720                 ifp->if_flags &= ~IFF_ALLMULTI;
2721
2722         /*
2723          * Kick the card
2724          */
2725         ray_ccs_fill(sc, com->c_ccs, RAY_CMD_UPDATE_MCAST);
2726         SRAM_WRITE_FIELD_1(sc, com->c_ccs,
2727             ray_cmd_update_mcast, c_nmcast, count);
2728         bufp = RAY_HOST_TO_ECF_BASE;
2729         for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
2730             ifma = ifma->ifma_link.le_next) {
2731                 SRAM_WRITE_REGION(
2732                     sc,
2733                     bufp,
2734                     LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
2735                     ETHER_ADDR_LEN
2736                 );
2737                 bufp += ETHER_ADDR_LEN;
2738         }
2739
2740         ray_com_ecf(sc, com);
2741 }
2742
2743 /*
2744  * Complete the multicast filter list update
2745  */
2746 static void
2747 ray_mcast_done(struct ray_softc *sc, u_int8_t status, size_t ccs)
2748 {
2749         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, "");
2750         RAY_COM_CHECK(sc, ccs);
2751
2752         RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */
2753
2754         ray_com_ecf_done(sc);
2755 }
2756
2757 /*
2758  * Runq entry to set/reset promiscuous mode
2759  */
2760 static void
2761 ray_promisc(struct ray_softc *sc, struct ray_comq_entry *com)
2762 {
2763         struct ifnet *ifp = &sc->arpcom.ac_if;
2764
2765         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2766         RAY_MAP_CM(sc);
2767
2768         /*
2769          * If card not running or we already have the right flags
2770          * we don't need to update this
2771          */
2772         sc->sc_d.np_promisc = !!(ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI));
2773         if (!(ifp->if_flags & IFF_RUNNING) ||
2774             (sc->sc_c.np_promisc == sc->sc_d.np_promisc)) {
2775                 ray_com_runq_done(sc);
2776                 return;
2777         }
2778
2779         /*
2780          * Kick the card
2781          */
2782         ray_ccs_fill(sc, com->c_ccs, RAY_CMD_UPDATE_PARAMS);
2783         SRAM_WRITE_FIELD_1(sc, com->c_ccs,
2784             ray_cmd_update, c_paramid, RAY_MIB_PROMISC);
2785         SRAM_WRITE_FIELD_1(sc, com->c_ccs, ray_cmd_update, c_nparam, 1);
2786         SRAM_WRITE_1(sc, RAY_HOST_TO_ECF_BASE, sc->sc_d.np_promisc);
2787
2788         ray_com_ecf(sc, com);
2789 }
2790
2791 /*
2792  * User land entry to parameter reporting
2793  *
2794  * As we by pass the runq to report current parameters this function
2795  * only provides a snap shot of the driver's state.
2796  */
2797 static int
2798 ray_repparams_user(struct ray_softc *sc, struct ray_param_req *pr)
2799 {
2800         struct ray_comq_entry *com[1];
2801         int error, ncom;
2802
2803         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2804
2805         /*
2806          * Test for illegal values or immediate responses
2807          */
2808         if (pr->r_paramid > RAY_MIB_MAX)
2809                 return (EINVAL);
2810         if ((sc->sc_version == RAY_ECFS_BUILD_4) &&
2811             !(mib_info[pr->r_paramid][0] & RAY_V4))
2812                 return (EINVAL);
2813         if ((sc->sc_version == RAY_ECFS_BUILD_5) &&
2814             !(mib_info[pr->r_paramid][0] & RAY_V5))
2815                 return (EINVAL);
2816         if (pr->r_paramid > RAY_MIB_LASTUSER) {
2817                 switch (pr->r_paramid) {
2818
2819                 case  RAY_MIB_VERSION:
2820                         if (sc->sc_version == RAY_ECFS_BUILD_4)
2821                             *pr->r_data = RAY_V4;
2822                         else
2823                             *pr->r_data = RAY_V5;
2824                         break;
2825                 case  RAY_MIB_CUR_BSSID:
2826                         bcopy(sc->sc_c.np_bss_id, pr->r_data, ETHER_ADDR_LEN);
2827                         break;
2828                 case  RAY_MIB_CUR_INITED:
2829                         *pr->r_data = sc->sc_c.np_inited;
2830                         break;
2831                 case  RAY_MIB_CUR_DEF_TXRATE:
2832                         *pr->r_data = sc->sc_c.np_def_txrate;
2833                         break;
2834                 case  RAY_MIB_CUR_ENCRYPT:
2835                         *pr->r_data = sc->sc_c.np_encrypt;
2836                         break;
2837                 case  RAY_MIB_CUR_NET_TYPE:
2838                         *pr->r_data = sc->sc_c.np_net_type;
2839                         break;
2840                 case  RAY_MIB_CUR_SSID:
2841                         bcopy(sc->sc_c.np_ssid, pr->r_data, IEEE80211_NWID_LEN);
2842                         break;
2843                 case  RAY_MIB_CUR_PRIV_START:
2844                         *pr->r_data = sc->sc_c.np_priv_start;
2845                         break;
2846                 case  RAY_MIB_CUR_PRIV_JOIN:
2847                         *pr->r_data = sc->sc_c.np_priv_join;
2848                         break;
2849                 case  RAY_MIB_DES_BSSID:
2850                         bcopy(sc->sc_d.np_bss_id, pr->r_data, ETHER_ADDR_LEN);
2851                         break;
2852                 case  RAY_MIB_DES_INITED:
2853                         *pr->r_data = sc->sc_d.np_inited;
2854                         break;
2855                 case  RAY_MIB_DES_DEF_TXRATE:
2856                         *pr->r_data = sc->sc_d.np_def_txrate;
2857                         break;
2858                 case  RAY_MIB_DES_ENCRYPT:
2859                         *pr->r_data = sc->sc_d.np_encrypt;
2860                         break;
2861                 case  RAY_MIB_DES_NET_TYPE:
2862                         *pr->r_data = sc->sc_d.np_net_type;
2863                         break;
2864                 case  RAY_MIB_DES_SSID:
2865                         bcopy(sc->sc_d.np_ssid, pr->r_data, IEEE80211_NWID_LEN);
2866                         break;
2867                 case  RAY_MIB_DES_PRIV_START:
2868                         *pr->r_data = sc->sc_d.np_priv_start;
2869                         break;
2870                 case  RAY_MIB_DES_PRIV_JOIN:
2871                         *pr->r_data = sc->sc_d.np_priv_join;
2872                         break;
2873                 case  RAY_MIB_CUR_AP_STATUS:
2874                         *pr->r_data = sc->sc_c.np_ap_status;
2875                         break;
2876                 case  RAY_MIB_CUR_PROMISC:
2877                         *pr->r_data = sc->sc_c.np_promisc;
2878                         break;
2879                 case  RAY_MIB_DES_AP_STATUS:
2880                         *pr->r_data = sc->sc_d.np_ap_status;
2881                         break;
2882                 case  RAY_MIB_DES_PROMISC:
2883                         *pr->r_data = sc->sc_d.np_promisc;
2884                         break;
2885                 case RAY_MIB_CUR_FRAMING:
2886                         *pr->r_data = sc->sc_c.np_framing;
2887                         break;
2888                 case RAY_MIB_DES_FRAMING:
2889                         *pr->r_data = sc->sc_d.np_framing;
2890                         break;
2891
2892                 default:
2893                         return (EINVAL);
2894                         break;
2895                 }
2896                 pr->r_failcause = 0;
2897                 if (sc->sc_version == RAY_ECFS_BUILD_4)
2898                     pr->r_len = mib_info[pr->r_paramid][RAY_MIB_INFO_SIZ4];
2899                 else if (sc->sc_version == RAY_ECFS_BUILD_5)
2900                     pr->r_len = mib_info[pr->r_paramid][RAY_MIB_INFO_SIZ5];
2901                 return (0);
2902         }
2903
2904         pr->r_failcause = 0;
2905         ncom = 0;
2906         com[ncom++] = RAY_COM_MALLOC(ray_repparams, RAY_COM_FWOK);
2907         com[ncom-1]->c_pr = pr;
2908
2909         RAY_COM_RUNQ(sc, com, ncom, "rayrparm", error);
2910
2911         /* XXX no real error processing from anything yet! */
2912         if (!com[0]->c_retval && pr->r_failcause)
2913                 error = EINVAL;
2914
2915         RAY_COM_FREE(com, ncom);
2916
2917         return (error);
2918 }
2919
2920 /*
2921  * Runq entry to read the required parameter
2922  *
2923  * The card and driver are happy for parameters to be read
2924  * whenever the card is plugged in
2925  */
2926 static void
2927 ray_repparams(struct ray_softc *sc, struct ray_comq_entry *com)
2928 {
2929         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2930         RAY_MAP_CM(sc);
2931
2932         /*
2933          * Kick the card
2934          */
2935         ray_ccs_fill(sc, com->c_ccs, RAY_CMD_REPORT_PARAMS);
2936         SRAM_WRITE_FIELD_1(sc, com->c_ccs,
2937             ray_cmd_report, c_paramid, com->c_pr->r_paramid);
2938         SRAM_WRITE_FIELD_1(sc, com->c_ccs, ray_cmd_report, c_nparam, 1);
2939
2940         ray_com_ecf(sc, com);
2941 }
2942
2943 /*
2944  * Complete the parameter reporting
2945  */
2946 static void
2947 ray_repparams_done(struct ray_softc *sc, u_int8_t status, size_t ccs)
2948 {
2949         struct ray_comq_entry *com;
2950
2951         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2952         RAY_MAP_CM(sc);
2953         RAY_COM_CHECK(sc, ccs);
2954
2955         RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */
2956
2957         com = TAILQ_FIRST(&sc->sc_comq);
2958         com->c_pr->r_failcause =
2959             SRAM_READ_FIELD_1(sc, ccs, ray_cmd_report, c_failcause);
2960         com->c_pr->r_len =
2961             SRAM_READ_FIELD_1(sc, ccs, ray_cmd_report, c_len);
2962         SRAM_READ_REGION(sc, RAY_ECF_TO_HOST_BASE,
2963             com->c_pr->r_data, com->c_pr->r_len);
2964
2965         ray_com_ecf_done(sc);
2966 }
2967
2968 /*
2969  * User land entry (and exit) to the error counters
2970  */
2971 static int
2972 ray_repstats_user(struct ray_softc *sc, struct ray_stats_req *sr)
2973 {
2974         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2975
2976         sr->rxoverflow = sc->sc_rxoverflow;
2977         sr->rxcksum = sc->sc_rxcksum;
2978         sr->rxhcksum = sc->sc_rxhcksum;
2979         sr->rxnoise = sc->sc_rxnoise;
2980
2981         return (0);
2982 }
2983
2984 /*
2985  * User land entry to parameter update changes
2986  *
2987  * As a parameter change can cause the network parameters to be
2988  * invalid we have to re-start/join.
2989  */
2990 static int
2991 ray_upparams_user(struct ray_softc *sc, struct ray_param_req *pr)
2992 {
2993         struct ray_comq_entry *com[4];
2994         int error, ncom, todo;
2995 #define RAY_UPP_SJ      0x1
2996 #define RAY_UPP_PARAMS  0x2
2997
2998         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
2999
3000         /*
3001          * Check that the parameter is available based on firmware version
3002          */
3003         pr->r_failcause = 0;
3004         if (pr->r_paramid > RAY_MIB_LASTUSER)
3005                 return (EINVAL);
3006         if ((sc->sc_version == RAY_ECFS_BUILD_4) &&
3007             !(mib_info[pr->r_paramid][0] & RAY_V4))
3008                 return (EINVAL);
3009         if ((sc->sc_version == RAY_ECFS_BUILD_5) &&
3010             !(mib_info[pr->r_paramid][0] & RAY_V5))
3011                 return (EINVAL);
3012
3013         /*
3014          * Handle certain parameters specially
3015          */
3016         todo = 0;
3017         switch (pr->r_paramid) {
3018         case RAY_MIB_NET_TYPE:          /* Updated via START_NET JOIN_NET  */
3019                 sc->sc_d.np_net_type = *pr->r_data;
3020                 todo |= RAY_UPP_SJ;
3021                 break;
3022
3023         case RAY_MIB_SSID:              /* Updated via START_NET JOIN_NET  */
3024                 bcopy(pr->r_data, sc->sc_d.np_ssid, IEEE80211_NWID_LEN);
3025                 todo |= RAY_UPP_SJ;
3026                 break;
3027
3028         case RAY_MIB_PRIVACY_MUST_START:/* Updated via START_NET */
3029                 if (sc->sc_c.np_net_type != RAY_MIB_NET_TYPE_ADHOC)
3030                         return (EINVAL);
3031                 sc->sc_d.np_priv_start = *pr->r_data;
3032                 todo |= RAY_UPP_SJ;
3033                 break;
3034
3035         case RAY_MIB_PRIVACY_CAN_JOIN:  /* Updated via START_NET JOIN_NET  */
3036                 sc->sc_d.np_priv_join = *pr->r_data;
3037                 todo |= RAY_UPP_SJ;
3038                 break;
3039
3040         case RAY_MIB_BASIC_RATE_SET:
3041                 sc->sc_d.np_def_txrate = *pr->r_data;
3042                 todo |= RAY_UPP_PARAMS;
3043                 break;
3044
3045         case RAY_MIB_AP_STATUS: /* Unsupported */
3046         case RAY_MIB_MAC_ADDR:  /* XXX Need interface up but could be done */
3047         case RAY_MIB_PROMISC:   /* BPF */
3048                 return (EINVAL);
3049                 break;
3050
3051         default:
3052                 todo |= RAY_UPP_PARAMS;
3053                 todo |= RAY_UPP_SJ;
3054                 break;
3055         }
3056
3057         /*
3058          * Generate the runq entries as needed
3059          */
3060         ncom = 0;
3061         if (todo & RAY_UPP_PARAMS) {
3062                 com[ncom++] = RAY_COM_MALLOC(ray_upparams, 0);
3063                 com[ncom-1]->c_pr = pr;
3064         }
3065         if (todo & RAY_UPP_SJ) {
3066                 com[ncom++] = RAY_COM_MALLOC(ray_init_sj, 0);
3067                 com[ncom++] = RAY_COM_MALLOC(ray_init_auth, 0);
3068                 com[ncom++] = RAY_COM_MALLOC(ray_init_assoc, 0);
3069         }
3070
3071         RAY_COM_RUNQ(sc, com, ncom, "rayuparam", error);
3072
3073         /* XXX no real error processing from anything yet! */
3074         if (!com[0]->c_retval && pr->r_failcause)
3075                 error = EINVAL;
3076
3077         RAY_COM_FREE(com, ncom);
3078
3079         return (error);
3080 }
3081
3082 /*
3083  * Runq entry to update a parameter
3084  *
3085  * The card and driver are happy for parameters to be updated
3086  * whenever the card is plugged in
3087  *
3088  * XXX the above is a little bit of a lie until _download is sorted out and we
3089  * XXX keep local copies of things
3090  */
3091 static void
3092 ray_upparams(struct ray_softc *sc, struct ray_comq_entry *com)
3093 {
3094         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
3095         RAY_MAP_CM(sc);
3096
3097         ray_ccs_fill(sc, com->c_ccs, RAY_CMD_UPDATE_PARAMS);
3098
3099         SRAM_WRITE_FIELD_1(sc, com->c_ccs,
3100             ray_cmd_update, c_paramid, com->c_pr->r_paramid);
3101         SRAM_WRITE_FIELD_1(sc, com->c_ccs, ray_cmd_update, c_nparam, 1);
3102         SRAM_WRITE_REGION(sc, RAY_HOST_TO_ECF_BASE,
3103             com->c_pr->r_data, com->c_pr->r_len);
3104
3105         ray_com_ecf(sc, com);
3106 }
3107
3108 /*
3109  * Complete the parameter update, note that promisc finishes up here too
3110  */
3111 static void
3112 ray_upparams_done(struct ray_softc *sc, u_int8_t status, size_t ccs)
3113 {
3114         struct ray_comq_entry *com;
3115
3116         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
3117         RAY_MAP_CM(sc);
3118         RAY_COM_CHECK(sc, ccs);
3119
3120         RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */
3121
3122         com = TAILQ_FIRST(&sc->sc_comq);
3123
3124         switch (SRAM_READ_FIELD_1(sc, ccs, ray_cmd_update, c_paramid)) {
3125
3126         case RAY_MIB_PROMISC:
3127                 sc->sc_c.np_promisc = SRAM_READ_1(sc, RAY_HOST_TO_ECF_BASE);
3128                 RAY_DPRINTF(sc, RAY_DBG_IOCTL,
3129                     "promisc value %d", sc->sc_c.np_promisc);
3130                 break;
3131
3132         default:
3133                 com->c_pr->r_failcause =
3134                     SRAM_READ_FIELD_1(sc, ccs, ray_cmd_update, c_failcause);
3135                 break;
3136
3137         }
3138
3139         ray_com_ecf_done(sc);
3140 }
3141
3142 /*
3143  * Command queuing and execution
3144  */
3145
3146 /*
3147  * Set up a comq entry struct
3148  */
3149 static struct ray_comq_entry *
3150 ray_com_init(struct ray_comq_entry *com, ray_comqfn_t function, int flags, char *mesg)
3151 {
3152         com->c_function = function;
3153         com->c_flags = flags;
3154         com->c_retval = 0;
3155         com->c_ccs = NULL;
3156         com->c_wakeup = NULL;
3157         com->c_pr = NULL;
3158         com->c_mesg = mesg;
3159
3160         return (com);
3161 }
3162
3163 /*
3164  * Malloc and set up a comq entry struct
3165  */
3166 static struct ray_comq_entry *
3167 ray_com_malloc(ray_comqfn_t function, int flags, char *mesg)
3168 {
3169         struct ray_comq_entry *com;
3170
3171         MALLOC(com, struct ray_comq_entry *,
3172             sizeof(struct ray_comq_entry), M_RAYCOM, M_WAITOK);
3173     
3174         return (ray_com_init(com, function, flags, mesg));
3175 }
3176
3177 /*
3178  * Add an array of commands to the runq, get some ccs's for them and
3179  * then run, waiting on the last command.
3180  *
3181  * We add the commands to the queue first to preserve ioctl ordering.
3182  *
3183  * On recoverable errors, this routine removes the entries from the
3184  * runq. A caller can requeue the commands (and still preserve its own
3185  * processes ioctl ordering) but doesn't have to. When the card is
3186  * detached we get out quickly to prevent panics and don't bother
3187  * about the runq.
3188  */
3189 static int
3190 ray_com_runq_add(struct ray_softc *sc, struct ray_comq_entry *com[], int ncom, char *wmesg)
3191 {
3192         int i, error;
3193
3194         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_COM, "");
3195
3196         error = 0;
3197         /*
3198          * Add the commands to the runq but don't let it run until
3199          * the ccs's are allocated successfully
3200          */
3201         com[0]->c_flags |= RAY_COM_FWAIT;
3202         for (i = 0; i < ncom; i++) {
3203                 com[i]->c_wakeup = com[ncom-1];
3204                 RAY_DPRINTF(sc, RAY_DBG_COM, "adding %p", com[i]);
3205                 RAY_DCOM(sc, RAY_DBG_DCOM, com[i], "adding");
3206                 TAILQ_INSERT_TAIL(&sc->sc_comq, com[i], c_chain);
3207         }
3208         com[ncom-1]->c_flags |= RAY_COM_FWOK;
3209
3210         /*
3211          * Allocate ccs's for each command.
3212          */
3213         for (i = 0; i < ncom; i++) {
3214                 error = ray_ccs_alloc(sc, &com[i]->c_ccs, wmesg);
3215                 if (error == ENXIO)
3216                         return (ENXIO);
3217                 else if (error)
3218                         goto cleanup;
3219         }
3220
3221         /*
3222          * Allow the queue to run and sleep if needed.
3223          *
3224          * Iff the FDETACHED flag is set in the com entry we waited on
3225          * the driver is in a zombie state! The softc structure has been
3226          * freed by the generic bus detach methods - eek. We tread very
3227          * carefully!
3228          */
3229         com[0]->c_flags &= ~RAY_COM_FWAIT;
3230         ray_com_runq(sc);
3231         if (TAILQ_FIRST(&sc->sc_comq) != NULL) {
3232                 RAY_DPRINTF(sc, RAY_DBG_COM, "sleeping");
3233                 error = tsleep(com[ncom-1], PCATCH, wmesg, 0);
3234                 if (com[ncom-1]->c_flags & RAY_COM_FDETACHED)
3235                         return (ENXIO);
3236                 RAY_DPRINTF(sc, RAY_DBG_COM,
3237                     "awakened, tsleep returned 0x%x", error);
3238         } else
3239                 error = 0;
3240
3241 cleanup:
3242         /*
3243          * Only clean the queue on real errors - we don't care about it
3244          * when we detach as the queue entries are freed by the callers.
3245          */
3246         if (error && (error != ENXIO))
3247                 for (i = 0; i < ncom; i++)
3248                         if (!(com[i]->c_flags & RAY_COM_FCOMPLETED)) {
3249                                 RAY_DPRINTF(sc, RAY_DBG_COM, "removing %p",
3250                                     com[i]);
3251                                 RAY_DCOM(sc, RAY_DBG_DCOM, com[i], "removing");
3252                                 TAILQ_REMOVE(&sc->sc_comq, com[i], c_chain);
3253                                 ray_ccs_free(sc, com[i]->c_ccs);
3254                                 com[i]->c_ccs = NULL;
3255                         }
3256
3257         return (error);
3258 }
3259
3260 /*
3261  * Run the command at the head of the queue (if not already running)
3262  */
3263 static void
3264 ray_com_runq(struct ray_softc *sc)
3265 {
3266         struct ray_comq_entry *com;
3267
3268         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_COM, "");
3269
3270         com = TAILQ_FIRST(&sc->sc_comq);
3271         if ((com == NULL) ||
3272             (com->c_flags & RAY_COM_FRUNNING) ||
3273             (com->c_flags & RAY_COM_FWAIT) ||
3274             (com->c_flags & RAY_COM_FDETACHED))
3275                 return;
3276
3277         com->c_flags |= RAY_COM_FRUNNING;
3278         RAY_DPRINTF(sc, RAY_DBG_COM, "running %p", com);
3279         RAY_DCOM(sc, RAY_DBG_DCOM, com, "running");
3280         com->c_function(sc, com);
3281 }
3282
3283 /*
3284  * Remove run command, free ccs and wakeup caller.
3285  *
3286  * Minimal checks are done here as we ensure that the com and command
3287  * handler were matched up earlier. Must be called at splnet or higher
3288  * so that entries on the command queue are correctly removed.
3289  *
3290  * Remove the com from the comq, and wakeup the caller if it requested
3291  * to be woken. This is used for ensuring a sequence of commands
3292  * completes. Finally, re-run the queue.
3293  */
3294 static void
3295 ray_com_runq_done(struct ray_softc *sc)
3296 {
3297         struct ray_comq_entry *com;
3298
3299         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_COM, "");
3300
3301         com = TAILQ_FIRST(&sc->sc_comq); /* XXX shall we check this as below */
3302         RAY_DPRINTF(sc, RAY_DBG_COM, "removing %p", com);
3303         RAY_DCOM(sc, RAY_DBG_DCOM, com, "removing");
3304         TAILQ_REMOVE(&sc->sc_comq, com, c_chain);
3305
3306         com->c_flags &= ~RAY_COM_FRUNNING;
3307         com->c_flags |= RAY_COM_FCOMPLETED;
3308         com->c_retval = 0;
3309         ray_ccs_free(sc, com->c_ccs);
3310         com->c_ccs = NULL;
3311
3312         if (com->c_flags & RAY_COM_FWOK)
3313                 wakeup(com->c_wakeup);
3314
3315         ray_com_runq(sc);
3316
3317         /* XXX what about error on completion then? deal with when i fix
3318          * XXX the status checking
3319          *
3320          * XXX all the runq_done calls from IFF_RUNNING checks in runq
3321          * XXX routines should return EIO but shouldn't abort the runq
3322          */
3323 }
3324
3325 /*
3326  * Send a command to the ECF.
3327  */
3328 static void
3329 ray_com_ecf(struct ray_softc *sc, struct ray_comq_entry *com)
3330 {
3331         int i = 0;
3332
3333         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_COM, "");
3334         RAY_MAP_CM(sc);
3335
3336         while (!RAY_ECF_READY(sc)) {
3337                 DELAY(RAY_ECF_SPIN_DELAY);
3338                 if (++i > RAY_ECF_SPIN_TRIES)
3339                         RAY_PANIC(sc, "spun too long");
3340         }
3341         if (i != 0)
3342                 RAY_RECERR(sc, "spun %d times", i);
3343
3344         RAY_DPRINTF(sc, RAY_DBG_COM, "sending %p", com);
3345         RAY_DCOM(sc, RAY_DBG_DCOM, com, "sending");
3346         SRAM_WRITE_1(sc, RAY_SCB_CCSI, RAY_CCS_INDEX(com->c_ccs));
3347         RAY_ECF_START_CMD(sc);
3348
3349         if (RAY_COM_NEEDS_TIMO(
3350             SRAM_READ_FIELD_1(sc, com->c_ccs, ray_cmd, c_cmd))) {
3351                 RAY_DPRINTF(sc, RAY_DBG_COM, "adding timeout");
3352                 sc->com_timerh = timeout(ray_com_ecf_timo, sc, RAY_COM_TIMEOUT);
3353         }
3354 }
3355
3356 /*
3357  * Deal with commands that require a timeout to test completion.
3358  *
3359  * This routine is coded to only expect one outstanding request for the
3360  * timed out requests at a time, but thats all that can be outstanding
3361  * per hardware limitations and all that we issue anyway.
3362  *
3363  * We don't do any fancy testing of the command currently issued as we
3364  * know it must be a timeout based one...unless I've got this wrong!
3365  */
3366 static void
3367 ray_com_ecf_timo(void *xsc)
3368 {
3369         struct ray_softc *sc = (struct ray_softc *)xsc;
3370         struct ray_comq_entry *com;
3371         u_int8_t cmd, status;
3372         int s;
3373
3374         s = splnet();
3375
3376         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_COM, "");
3377         RAY_MAP_CM(sc);
3378
3379         com = TAILQ_FIRST(&sc->sc_comq);
3380
3381         cmd = SRAM_READ_FIELD_1(sc, com->c_ccs, ray_cmd, c_cmd);
3382         status = SRAM_READ_FIELD_1(sc, com->c_ccs, ray_cmd, c_status);
3383         switch (status) {
3384
3385         case RAY_CCS_STATUS_COMPLETE:
3386         case RAY_CCS_STATUS_FREE:                       /* Buggy firmware */
3387                 ray_intr_ccs(sc, cmd, status, com->c_ccs);
3388                 break;
3389
3390         case RAY_CCS_STATUS_BUSY:
3391                 sc->com_timerh = timeout(ray_com_ecf_timo, sc, RAY_COM_TIMEOUT);
3392                 break;
3393
3394         default:                                        /* Replicates NetBSD */
3395                 if (sc->sc_ccsinuse[RAY_CCS_INDEX(com->c_ccs)] == 1) {
3396                         /* give a chance for the interrupt to occur */
3397                         sc->sc_ccsinuse[RAY_CCS_INDEX(com->c_ccs)] = 2;
3398                         sc->com_timerh = timeout(ray_com_ecf_timo, sc,
3399                             RAY_COM_TIMEOUT);
3400                 } else
3401                         ray_intr_ccs(sc, cmd, status, com->c_ccs);
3402                 break;
3403
3404         }
3405
3406         splx(s);
3407 }
3408
3409 /*
3410  * Called when interrupt handler for the command has done all it
3411  * needs to. Will be called at splnet.
3412  */
3413 static void
3414 ray_com_ecf_done(struct ray_softc *sc)
3415 {
3416         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_COM, "");
3417
3418         untimeout(ray_com_ecf_timo, sc, sc->com_timerh);
3419
3420         ray_com_runq_done(sc);
3421 }
3422
3423 #if RAY_DEBUG & RAY_DBG_COM
3424 /*
3425  * Process completed ECF commands that probably came from the command queue
3426  *
3427  * This routine is called after vectoring the completed ECF command
3428  * to the appropriate _done routine. It helps check everything is okay.
3429  */
3430 static void
3431 ray_com_ecf_check(struct ray_softc *sc, size_t ccs, char *mesg)
3432 {
3433         struct ray_comq_entry *com;
3434
3435         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_COM, "%s", mesg);
3436
3437         com = TAILQ_FIRST(&sc->sc_comq);
3438
3439         if (com == NULL)
3440                 RAY_PANIC(sc, "no command queue");
3441         if (com->c_ccs != ccs)
3442                 RAY_PANIC(sc, "ccs's don't match");
3443 }
3444 #endif /* RAY_DEBUG & RAY_DBG_COM */
3445
3446 /*
3447  * CCS allocators
3448  */
3449
3450 /*
3451  * Obtain a ccs for a commmand
3452  *
3453  * Returns 0 and in `ccsp' the bus offset of the free ccs. Will block
3454  * awaiting free ccs if needed - if the sleep is interrupted
3455  * EINTR/ERESTART is returned, if the card is ejected we return ENXIO.
3456  */
3457 static int
3458 ray_ccs_alloc(struct ray_softc *sc, size_t *ccsp, char *wmesg)
3459 {
3460         size_t ccs;
3461         u_int i;
3462         int error;
3463
3464         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_CCS, "");
3465         RAY_MAP_CM(sc);
3466
3467         for (;;) {
3468                 for (i = RAY_CCS_CMD_FIRST; i <= RAY_CCS_CMD_LAST; i++) {
3469                         /* we probe here to make the card go */
3470                         (void)SRAM_READ_FIELD_1(sc, RAY_CCS_ADDRESS(i), ray_cmd,
3471                             c_status);
3472                         if (!sc->sc_ccsinuse[i])
3473                                 break;
3474                 }
3475                 if (i > RAY_CCS_CMD_LAST) {
3476                         RAY_DPRINTF(sc, RAY_DBG_CCS, "sleeping");
3477                         error = tsleep(ray_ccs_alloc, PCATCH, wmesg, 0);
3478                         if ((sc == NULL) || (sc->sc_gone))
3479                                 return (ENXIO);
3480                         RAY_DPRINTF(sc, RAY_DBG_CCS,
3481                             "awakened, tsleep returned 0x%x", error);
3482                         if (error)
3483                                 return (error);
3484                 } else
3485                         break;
3486         }
3487         RAY_DPRINTF(sc, RAY_DBG_CCS, "allocated 0x%02x", i);
3488         sc->sc_ccsinuse[i] = 1;
3489         ccs = RAY_CCS_ADDRESS(i);
3490         *ccsp = ccs;
3491
3492         return (0);
3493 }
3494
3495 /*
3496  * Fill the easy bits in of a pre-allocated CCS
3497  */
3498 static void
3499 ray_ccs_fill(struct ray_softc *sc, size_t ccs, u_int cmd)
3500 {
3501         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_CCS, "");
3502         RAY_MAP_CM(sc);
3503
3504         if (ccs == NULL)
3505                 RAY_PANIC(sc, "ccs not allocated");
3506
3507         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_BUSY);
3508         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_cmd, cmd);
3509         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_link, RAY_CCS_LINK_NULL);
3510 }
3511
3512 /*
3513  * Free up a ccs allocated via ray_ccs_alloc
3514  *
3515  * Return the old status. This routine is only used for ccs allocated via
3516  * ray_ccs_alloc (not tx, rx or ECF command requests).
3517  */
3518 static void
3519 ray_ccs_free(struct ray_softc *sc, size_t ccs)
3520 {
3521         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_CCS, "");
3522         RAY_MAP_CM(sc);
3523
3524 #if 1 | (RAY_DEBUG & RAY_DBG_CCS)
3525         if (!sc->sc_ccsinuse[RAY_CCS_INDEX(ccs)])
3526                 RAY_RECERR(sc, "freeing free ccs 0x%02x", RAY_CCS_INDEX(ccs));
3527 #endif /* RAY_DEBUG & RAY_DBG_CCS */
3528         if (!sc->sc_gone)
3529                 RAY_CCS_FREE(sc, ccs);
3530         sc->sc_ccsinuse[RAY_CCS_INDEX(ccs)] = 0;
3531         RAY_DPRINTF(sc, RAY_DBG_CCS, "freed 0x%02x", RAY_CCS_INDEX(ccs));
3532         wakeup(ray_ccs_alloc);
3533 }
3534
3535 /*
3536  * Obtain a ccs and tx buffer to transmit with and fill them in.
3537  *
3538  * Returns 0 and in `ccsp' the bus offset of the free ccs. Will not block
3539  * and if none available and will returns EAGAIN.
3540  *
3541  * The caller must fill in the length later.
3542  * The caller must clear the ccs on errors.
3543  */
3544 static int
3545 ray_ccs_tx(struct ray_softc *sc, size_t *ccsp, size_t *bufpp)
3546 {
3547         size_t ccs, bufp;
3548         int i;
3549         u_int8_t status;
3550
3551         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_CCS, "");
3552         RAY_MAP_CM(sc);
3553
3554         i = RAY_CCS_TX_FIRST;
3555         do {
3556                 status = SRAM_READ_FIELD_1(sc, RAY_CCS_ADDRESS(i),
3557                     ray_cmd, c_status);
3558                 if (status == RAY_CCS_STATUS_FREE)
3559                         break;
3560                 i++;
3561         } while (i <= RAY_CCS_TX_LAST);
3562         if (i > RAY_CCS_TX_LAST) {
3563                 return (EAGAIN);
3564         }
3565         RAY_DPRINTF(sc, RAY_DBG_CCS, "allocated 0x%02x", i);
3566
3567         /*
3568          * Reserve and fill the ccs - must do the length later.
3569          *
3570          * Even though build 4 and build 5 have different fields all these
3571          * are common apart from tx_rate. Neither the NetBSD driver or Linux
3572          * driver bother to overwrite this for build 4 cards.
3573          *
3574          * The start of the buffer must be aligned to a 256 byte boundary
3575          * (least significant byte of address = 0x00).
3576          */
3577         ccs = RAY_CCS_ADDRESS(i);
3578         bufp = RAY_TX_BASE + i * RAY_TX_BUF_SIZE;
3579         bufp += sc->sc_tibsize;
3580         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_status, RAY_CCS_STATUS_BUSY);
3581         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_cmd, RAY_CMD_TX_REQ);
3582         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_link, RAY_CCS_LINK_NULL);
3583         SRAM_WRITE_FIELD_2(sc, ccs, ray_cmd_tx, c_bufp, bufp);
3584         SRAM_WRITE_FIELD_1(sc,
3585             ccs, ray_cmd_tx, c_tx_rate, sc->sc_c.np_def_txrate);
3586         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_apm_mode, 0);
3587         bufp += sizeof(struct ray_tx_phy_header);
3588
3589         *ccsp = ccs;
3590         *bufpp = bufp;
3591         return (0);
3592 }
3593
3594 /*
3595  * Routines to obtain resources for the card
3596  */
3597
3598 /*
3599  * Allocate the attribute memory on the card
3600  *
3601  * The attribute memory space is abused by these devices as IO space. As such
3602  * the OS card services don't have a chance of knowing that they need to keep
3603  * the attribute space mapped. We have to do it manually.
3604  */
3605 static int
3606 ray_res_alloc_am(struct ray_softc *sc)
3607 {
3608         int error;
3609
3610         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_CM, "");
3611
3612         sc->am_rid = RAY_AM_RID;
3613         sc->am_res = bus_alloc_resource(sc->dev, SYS_RES_MEMORY,
3614             &sc->am_rid, 0UL, ~0UL, 0x1000, RF_ACTIVE);
3615         if (!sc->am_res) {
3616                 RAY_PRINTF(sc, "Cannot allocate attribute memory");
3617                 return (ENOMEM);
3618         }
3619         error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->dev), sc->dev,
3620             sc->am_rid, 0);
3621         if (error) {
3622                 RAY_PRINTF(sc, "CARD_SET_MEMORY_OFFSET returned 0x%0x", error);
3623                 return (error);
3624         }
3625         error = CARD_SET_RES_FLAGS(device_get_parent(sc->dev), sc->dev,
3626             SYS_RES_MEMORY, sc->am_rid, PCCARD_A_MEM_ATTR);
3627         if (error) {
3628                 RAY_PRINTF(sc, "CARD_SET_RES_FLAGS returned 0x%0x", error);
3629                 return (error);
3630         }
3631         error = CARD_SET_RES_FLAGS(device_get_parent(sc->dev), sc->dev,
3632             SYS_RES_MEMORY, sc->am_rid, PCCARD_A_MEM_8BIT);
3633         if (error) {
3634                 RAY_PRINTF(sc, "CARD_SET_RES_FLAGS returned 0x%0x", error);
3635                 return (error);
3636         }
3637         sc->am_bsh = rman_get_bushandle(sc->am_res);
3638         sc->am_bst = rman_get_bustag(sc->am_res);
3639
3640 #if RAY_DEBUG & (RAY_DBG_CM | RAY_DBG_BOOTPARAM)
3641 {
3642         u_long flags;
3643         u_int32_t offset;
3644         CARD_GET_RES_FLAGS(device_get_parent(sc->dev), sc->dev,
3645             SYS_RES_MEMORY, sc->am_rid, &flags);
3646         CARD_GET_MEMORY_OFFSET(device_get_parent(sc->dev), sc->dev,
3647             sc->am_rid, &offset);
3648         RAY_PRINTF(sc, "allocated attribute memory:\n"
3649             ".  start 0x%0lx count 0x%0lx flags 0x%0lx offset 0x%0x",
3650             bus_get_resource_start(sc->dev, SYS_RES_MEMORY, sc->am_rid),
3651             bus_get_resource_count(sc->dev, SYS_RES_MEMORY, sc->am_rid),
3652             flags, offset);
3653 }
3654 #endif /* RAY_DEBUG & (RAY_DBG_CM | RAY_DBG_BOOTPARAM) */
3655
3656         return (0);
3657 }
3658
3659 /*
3660  * Allocate the common memory on the card
3661  *
3662  * As this memory is described in the CIS, the OS card services should
3663  * have set the map up okay, but the card uses 8 bit RAM. This is not
3664  * described in the CIS.
3665  */
3666 static int
3667 ray_res_alloc_cm(struct ray_softc *sc)
3668 {
3669         u_long start, count, end;
3670         int error;
3671
3672         RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_CM, "");
3673
3674         RAY_DPRINTF(sc,RAY_DBG_CM | RAY_DBG_BOOTPARAM,
3675             "cm start 0x%0lx count 0x%0lx",
3676             bus_get_resource_start(sc->dev, SYS_RES_MEMORY, RAY_CM_RID),
3677             bus_get_resource_count(sc->dev, SYS_RES_MEMORY, RAY_CM_RID));
3678
3679         sc->cm_rid = RAY_CM_RID;
3680         start = bus_get_resource_start(sc->dev, SYS_RES_MEMORY, sc->cm_rid);
3681         count = bus_get_resource_count(sc->dev, SYS_RES_MEMORY, sc->cm_rid);
3682         end = start + count - 1;
3683         sc->cm_res = bus_alloc_resource(sc->dev, SYS_RES_MEMORY,
3684             &sc->cm_rid, start, end, count, RF_ACTIVE);
3685         if (!sc->cm_res) {
3686                 RAY_PRINTF(sc, "Cannot allocate common memory");
3687                 return (ENOMEM);
3688         }
3689         error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->dev), sc->dev,
3690             sc->cm_rid, 0);
3691         if (error) {
3692                 RAY_PRINTF(sc, "CARD_SET_MEMORY_OFFSET returned 0x%0x", error);
3693                 return (error);
3694         }
3695         error = CARD_SET_RES_FLAGS(device_get_parent(sc->dev), sc->dev,
3696             SYS_RES_MEMORY, sc->cm_rid, PCCARD_A_MEM_COM);
3697         if (error) {
3698                 RAY_PRINTF(sc, "CARD_SET_RES_FLAGS returned 0x%0x", error);
3699                 return (error);
3700         }
3701         error = CARD_SET_RES_FLAGS(device_get_parent(sc->dev), sc->dev,
3702             SYS_RES_MEMORY, sc->cm_rid, PCCARD_A_MEM_8BIT);
3703         if (error) {
3704                 RAY_PRINTF(sc, "CARD_SET_RES_FLAGS returned 0x%0x", error);
3705                 return (error);
3706         }
3707         sc->cm_bsh = rman_get_bushandle(sc->cm_res);
3708         sc->cm_bst = rman_get_bustag(sc->cm_res);
3709
3710 #if RAY_DEBUG & (RAY_DBG_CM | RAY_DBG_BOOTPARAM)
3711 {
3712         u_long flags;
3713         u_int32_t offset;
3714         CARD_GET_RES_FLAGS(device_get_parent(sc->dev), sc->dev,
3715             SYS_RES_MEMORY, sc->cm_rid, &flags);
3716         CARD_GET_MEMORY_OFFSET(device_get_parent(sc->dev), sc->dev,
3717             sc->cm_rid, &offset);
3718         RAY_PRINTF(sc, "allocated common memory:\n"
3719             ".  start 0x%0lx count 0x%0lx flags 0x%0lx offset 0x%0x",
3720             bus_get_resource_start(sc->dev, SYS_RES_MEMORY, sc->cm_rid),
3721             bus_get_resource_count(sc->dev, SYS_RES_MEMORY, sc->cm_rid),
3722             flags, offset);
3723 }
3724 #endif /* RAY_DEBUG & (RAY_DBG_CM | RAY_DBG_BOOTPARAM) */
3725
3726         return (0);
3727 }
3728
3729 /*
3730  * Get an irq and attach it to the bus
3731  */
3732 static int
3733 ray_res_alloc_irq(struct ray_softc *sc)
3734 {
3735         int error;
3736
3737         RAY_DPRINTF(sc, RAY_DBG_SUBR, "");
3738
3739         RAY_DPRINTF(sc,RAY_DBG_CM | RAY_DBG_BOOTPARAM,
3740             "irq start 0x%0lx count 0x%0lx",
3741             bus_get_resource_start(sc->dev, SYS_RES_IRQ, 0),
3742             bus_get_resource_count(sc->dev, SYS_RES_IRQ, 0));
3743
3744         sc->irq_rid = 0;
3745         sc->irq_res = bus_alloc_resource(sc->dev, SYS_RES_IRQ, &sc->irq_rid,
3746             0, ~0, 1, RF_ACTIVE);
3747         if (!sc->irq_res) {
3748                 RAY_PRINTF(sc, "Cannot allocate irq");
3749                 return (ENOMEM);
3750         }
3751         if ((error = bus_setup_intr(sc->dev, sc->irq_res, INTR_TYPE_NET,
3752             ray_intr, sc, &sc->irq_handle)) != 0) {
3753                 RAY_PRINTF(sc, "Failed to setup irq");
3754                 return (error);
3755         }
3756         RAY_DPRINTF(sc, RAY_DBG_CM | RAY_DBG_BOOTPARAM, "allocated irq:\n"
3757             ".  start 0x%0lx count 0x%0lx",
3758             bus_get_resource_start(sc->dev, SYS_RES_IRQ, sc->irq_rid),
3759             bus_get_resource_count(sc->dev, SYS_RES_IRQ, sc->irq_rid));
3760
3761         return (0);
3762 }
3763
3764 /*
3765  * Release all of the card's resources
3766  */
3767 static void
3768 ray_res_release(struct ray_softc *sc)
3769 {
3770         if (sc->irq_res != 0) {
3771                 bus_teardown_intr(sc->dev, sc->irq_res, sc->irq_handle);
3772                 bus_release_resource(sc->dev, SYS_RES_IRQ,
3773                     sc->irq_rid, sc->irq_res);
3774                 sc->irq_res = 0;
3775         }
3776         if (sc->am_res != 0) {
3777                 bus_release_resource(sc->dev, SYS_RES_MEMORY,
3778                     sc->am_rid, sc->am_res);
3779                 sc->am_res = 0;
3780         }
3781         if (sc->cm_res != 0) {
3782                 bus_release_resource(sc->dev, SYS_RES_MEMORY,
3783                     sc->cm_rid, sc->cm_res);
3784                 sc->cm_res = 0;
3785         }
3786 }
3787
3788 /*
3789  * mbuf dump
3790  */
3791 #if RAY_DEBUG & RAY_DBG_MBUF
3792 static void
3793 ray_dump_mbuf(struct ray_softc *sc, struct mbuf *m, char *s)
3794 {
3795         u_int8_t *d, *ed;
3796         u_int i;
3797         char p[17];
3798
3799         RAY_PRINTF(sc, "%s", s);
3800         RAY_PRINTF(sc, "\nm0->data\t0x%p\nm_pkthdr.len\t%d\nm_len\t%d",
3801             mtod(m, u_int8_t *), m->m_pkthdr.len, m->m_len);
3802         i = 0;
3803         bzero(p, 17);
3804         for (; m; m = m->m_next) {
3805                 d = mtod(m, u_int8_t *);
3806                 ed = d + m->m_len;
3807
3808                 for (; d < ed; i++, d++) {
3809                         if ((i % 16) == 0) {
3810                                 printf("  %s\n\t", p);
3811                         } else if ((i % 8) == 0)
3812                                 printf("  ");
3813                         printf(" %02x", *d);
3814                         p[i % 16] = ((*d >= 0x20) && (*d < 0x80)) ? *d : '.';
3815                 }
3816         }
3817         if ((i - 1) % 16)
3818                 printf("  %s\n", p);
3819 }
3820 #endif /* RAY_DEBUG & RAY_DBG_MBUF */