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