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