]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ray/if_ray.c
This commit was generated by cvs2svn to compensate for changes in r58650,
[FreeBSD/FreeBSD.git] / sys / dev / 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  * $Id: if_ray.c,v 1.8 2000/03/08 08:53:36 dmlb Exp $
32  *
33  */
34
35 /*      $NetBSD: if_ray.c,v 1.12 2000/02/07 09:36:27 augustss Exp $     */
36 /* 
37  * Copyright (c) 2000 Christian E. Hopps
38  * All rights reserved.
39  * 
40  * Redistribution and use in source and binary forms, with or without
41  * modification, are permitted provided that the following conditions
42  * are met:
43  * 1. Redistributions of source code must retain the above copyright
44  *    notice, this list of conditions and the following disclaimer.
45  * 2. Redistributions in binary form must reproduce the above copyright
46  *    notice, this list of conditions and the following disclaimer in the
47  *    documentation and/or other materials provided with the distribution.
48  * 3. Neither the name of the author nor the names of any co-contributors
49  *    may be used to endorse or promote products derived from this software
50  *    without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62  * SUCH DAMAGE.
63  */
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. The -stable versions of FreeBSD have a real
72  * problem managing and setting up the correct memory maps. This
73  * driver should reset the memory maps correctly under PAO and non-PAO
74  * -stable systems. Work is in hand to fix these problems for -current.
75  *
76  * So, if you want to use this driver make sure that
77  *      options RAY_NEED_CM_FIXUP
78  *      options RAY_NEED_CM_REMAPPING
79  * are in your kernel configuration file.
80  *
81  * The first fixes the brain deadness of pccardd (where it reads the
82  * CIS for common memory, sets it all up and then throws it all away
83  * assuming the card is an ed driver...). Note that this could be
84  * dangerous (because it doesn't interact with pccardd) if you
85  * use other memory mapped cards at the same time.
86  *
87  * The second option ensures that common memory is remapped whenever
88  * we are going to access it (we can't just do it once, as something
89  * like pccardd may have read the attribute memory and pccard.c
90  * doesn't re-map the last active window - it remaps the last
91  * non-active window...).
92  *
93  *
94  * Ad-hoc and infra-structure modes
95  * ================================
96  * 
97  * At present only the ad-hoc mode is being worked on.
98  *
99  * Apart from just writing the code for infrastructure mode I have a
100  * few concerns about both the Linux and NetBSD drivers in this area.
101  * They don't seem to differentiate between the MAC address of the AP
102  * and the BSS_ID of the network. I presume this is handled when
103  * joining a managed n/w and the network parameters are updated, but
104  * I'm not sure. How does this interact with ARP? For mobility we want
105  * to be able to move around without worrying about which AP we are
106  * actually talking to - we should always talk to the BSS_ID.
107  *
108  * The Linux driver also seems to have the capability to act as an AP.
109  * I wonder what facilities the "AP" can provide within a driver? We can
110  * probably use the BRIDGE code to form an ESS but I don't think
111  * power saving etc. is easy.
112  *
113  *
114  * Packet translation/encapsulation
115  * ================================
116  * 
117  * Currently we only support the Webgear encapsulation
118  *      802.11  header <net/if_ieee80211.h>struct ieee80211_header
119  *      802.3   header <net/ethernet.h>struct ether_header
120  *      802.2   LLC header
121  *      802.2   SNAP header
122  *
123  * We should support whatever packet types the following drivers have
124  *      if_wi.c         FreeBSD, RFC1042
125  *      if_ray.c        NetBSD  Webgear, RFC1042
126  *      rayctl.c        Linux Webgear, RFC1042
127  * also whatever we can divine from the NDC Access points and Kanda's boxes.
128  *
129  * Most drivers appear to have a RFC1042 translation. The incoming packet is
130  *      802.11  header <net/if_ieee80211.h>struct ieee80211_header
131  *      802.2   LLC header
132  *      802.2   SNAP header
133  *
134  * This is translated to
135  *      802.3   header <net/ethernet.h>struct ether_header
136  *      802.2   LLC header
137  *      802.2   SNAP header
138  *
139  * Linux seems to look at the SNAP org_code and do some translations
140  * for IPX and APPLEARP on that. This just may be how Linux does IPX
141  * and NETATALK. Need to see how FreeBSD does these.
142  *
143  * Translation should be selected via if_media stuff or link types.
144  */
145
146 /*
147  * TODO
148  *
149  * _stop - mostly done
150  *      would be nice to understand shutdown/or power save to prevent RX
151  * _reset - done
152  *      just needs calling in the right places
153  *      converted panics to resets - when tx packets are the wrong length
154  *      may be needed in a couple of other places when I do more commands
155  * havenet - mostly done
156  *      i think i've got all the places to set it right, but not so sure
157  *      we reset it in all the right places
158  * _unload - done
159  *      recreated most of stop but as card is unplugged don't try and
160  *      access it to turn it off
161  * TX bpf - done
162  * RX bpf - done
163  *      I would much prefer to have the complete 802.11 packet dropped to
164  *      the bpf tap and then have a user land program parse the headers
165  *      as needed. This way, tcpdump -w can be used to grab the raw data. If
166  *      needed the 802.11 aware program can "translate" the .11 to ethernet
167  *      for tcpdump -r
168  * use std timeout code for download - done
169  *      was mainly moving a call and removing a load of stuff in
170  *      download_done as it duplicates check_ccs and ccs_done
171  * promisoius - done
172  * add the start_join_net - done
173  *      i needed it anyway
174  * remove startccs and startcmd - done
175  *      as those were used for the NetBSD start timeout
176  * multicast - done but UNTESTED
177  *      I don't have the ability/facilty to test this
178  * rxlevel - done
179  *      stats reported via raycontrol
180  * getparams ioctl - done
181  *      reported via raycontrol
182  * start_join_done needs a restart in download_done - done
183  *      now use netbsd style start up
184  * ioctls - done
185  *      use raycontrol
186  *      translation, BSS_ID, countrycode, changing mode
187  *
188  * shutdown
189  * ifp->if_hdr length
190  * _reset - check where needed
191  * apm
192  * faster TX routine
193  * more translations
194  * infrastructure mode - maybe need some of the old stuff for checking?
195  * differeniate between parameters set in attach and init
196  * spinning in ray_issue_cmd
197  * fix the XXX code in start_join_done
198  * make RAY_DEBUG a knob somehow - either sysctl or IFF_DEBUG
199  * ray_update_params_done needs work
200  * do an rx level and antenna cache, the antenna can be used to set c_antenna
201  *   for tx
202  * callout handles need rationalising. can probably remove timerh and
203  *   use ccs_timerh for download and sj_timerh
204  */
205
206 #define XXX             0
207 #define XXX_NETBSDTX    0
208 #define XXX_PROM        0
209
210 /*
211  * XXX build options - move to LINT
212  */
213
214 /*
215  * RAY_DEBUG settings
216  *
217  *      2       Recoverable error's
218  *      6       Subroutine entry
219  *      11      Startup CM dump
220  *      16      State transitions for start/join
221  *      21      CCS info
222  *      31      IOCTL calls
223  *      51      MBUFs dumped/packet types reported
224  */
225 #ifndef RAY_DEBUG
226 #define RAY_DEBUG               2
227 #endif
228
229 #define RAY_CCS_TIMEOUT         (hz/2)  /* Timeout for CCS commands */
230 #define RAY_CHECK_SCHED_TIMEOUT (hz)    /* Time to wait until command retry, should be > RAY_CCS_TIMEOUT */
231
232 #define RAY_NEED_STARTJOIN_TIMO 0       /* Might be needed with build 4 */
233 #define RAY_SJ_TIMEOUT          (90*hz) /* Timeout for failing STARTJOIN commands - only used with RAY_NEED_STARTJOIN_TIMO */
234
235 #define RAY_NEED_CM_FIXUP       1       /* Needed until pccardd hacks for ed drivers are removed (pccardd forces 16bit memory and 0x4000 size) THIS IS A DANGEROUS THING TO USE IF YOU USE OTHER MEMORY MAPPED PCCARDS */
236
237 #define RAY_NEED_CM_REMAPPING   1       /* Needed until pccard maps more than one memory area */
238
239 #define RAY_RESET_TIMEOUT       (5*hz)  /* Timeout for resetting the card */
240
241 #define RAY_USE_CALLOUT_STOP    0       /* Set for kernels with callout_stop function - 3.3 and above */
242
243 #define RAY_SIMPLE_TX           1       /* Simple TX routine */
244 #define RAY_DECENT_TX           0       /* Decent TX routine - tbd */
245 /*
246  * XXX build options - move to LINT
247  */
248
249 /*
250  * Debugging odds and odds
251  */
252 #ifndef RAY_DEBUG
253 #define RAY_DEBUG 0
254 #endif /* RAY_DEBUG */
255
256 #if RAY_DEBUG > 0
257
258 /* XXX This macro assumes that common memory is mapped into kernel space and
259  * XXX does not indirect through SRAM macros - it should
260  */
261 #define RAY_DHEX8(p, l) do { if (RAY_DEBUG > 10) {              \
262     u_int8_t *i;                                                \
263     for (i = p; i < (u_int8_t *)(p+l); i += 8)                  \
264         printf("  0x%08lx %8D\n",                               \
265                 (unsigned long)i, (unsigned char *)i, " ");     \
266 } } while (0)
267
268 #define RAY_DPRINTFN(l, x) do { if (RAY_DEBUG > l) {            \
269     printf x ;                                                  \
270 } } while (0)
271
272 #define RAY_DNET_DUMP(sc, s) do { if (RAY_DEBUG > 15) {                 \
273     printf("ray%d: Current network parameters%s\n", (sc)->unit, (s));   \
274     printf("  bss_id %6D\n", (sc)->sc_c.np_bss_id, ":");                \
275     printf("  inited 0x%02x\n", (sc)->sc_c.np_inited);                  \
276     printf("  def_txrate 0x%02x\n", (sc)->sc_c.np_def_txrate);          \
277     printf("  encrypt 0x%02x\n", (sc)->sc_c.np_encrypt);                \
278     printf("  net_type 0x%02x\n", (sc)->sc_c.np_net_type);              \
279     printf("  ssid \"%.32s\"\n", (sc)->sc_c.np_ssid);                   \
280     printf("       %8D\n", (sc)->sc_c.np_ssid, " ");                    \
281     printf("       %8D\n", (sc)->sc_c.np_ssid+8, " ");                  \
282     printf("       %8D\n", (sc)->sc_c.np_ssid+16, " ");                 \
283     printf("       %8D\n", (sc)->sc_c.np_ssid+24, " ");                 \
284     printf("  priv_start 0x%02x\n", (sc)->sc_c.np_priv_start);          \
285     printf("  priv_join 0x%02x\n", (sc)->sc_c.np_priv_join);            \
286     printf("ray%d: Desired network parameters%s\n", (sc)->unit, (s));   \
287     printf("  bss_id %6D\n", (sc)->sc_d.np_bss_id, ":");                \
288     printf("  inited 0x%02x\n", (sc)->sc_d.np_inited);                  \
289     printf("  def_txrate 0x%02x\n", (sc)->sc_d.np_def_txrate);          \
290     printf("  encrypt 0x%02x\n", (sc)->sc_d.np_encrypt);                \
291     printf("  net_type 0x%02x\n", (sc)->sc_d.np_net_type);              \
292     printf("  ssid \"%.32s\"\n", (sc)->sc_d.np_ssid);                   \
293     printf("       %8D\n", (sc)->sc_c.np_ssid, " ");                    \
294     printf("       %8D\n", (sc)->sc_c.np_ssid+8, " ");                  \
295     printf("       %8D\n", (sc)->sc_c.np_ssid+16, " ");                 \
296     printf("       %8D\n", (sc)->sc_c.np_ssid+24, " ");                 \
297     printf("  priv_start 0x%02x\n", (sc)->sc_d.np_priv_start);          \
298     printf("  priv_join 0x%02x\n", (sc)->sc_d.np_priv_join);            \
299 } } while (0)
300
301 #else
302 #define RAY_DHEX8(p, l)
303 #define RAY_DPRINTFN(l,x)
304 #define RAY_DNET_DUMP(sc, s)
305 #endif /* RAY_DEBUG > 0 */
306
307 #if RAY_DEBUG > 50
308 #define RAY_DMBUF_DUMP(sc, m, s)        ray_dump_mbuf((sc), (m), (s))
309 #else
310 #define RAY_DMBUF_DUMP(sc, m, s)
311 #endif /* RAY_DEBUG > 10 */
312
313 #include "ray.h"
314 #include "card.h"
315 #include "apm.h"
316 #include "bpfilter.h"
317
318 #if NRAY > 0
319
320 #include <sys/param.h>
321 #include <sys/cdefs.h>
322 #include <sys/conf.h>
323 #include <sys/errno.h>
324 #include <sys/kernel.h>
325 #include <sys/malloc.h>
326 #include <sys/mbuf.h>
327 #include <sys/callout.h>
328 #include <sys/select.h>
329 #include <sys/socket.h>
330 #include <sys/sockio.h>
331 #include <sys/systm.h>
332 #include <sys/sysctl.h>
333 #include <sys/uio.h>
334 #include <sys/proc.h>
335 #include <sys/ucred.h>
336
337 #include <net/if.h>
338 #include <net/if_arp.h>
339 #include <net/ethernet.h>
340 #include <net/if_dl.h>
341 #include <net/if_media.h>
342 #include <net/if_mib.h>
343
344 #if NBPFILTER > 0
345 #include <net/bpf.h>
346 #endif /* NBPFILTER */
347
348 #include <machine/clock.h>
349 #include <machine/md_var.h>
350 #include <machine/bus_pio.h>
351 #include <machine/bus.h>
352
353 #include <i386/isa/isa.h>
354 #include <i386/isa/isa_device.h>
355
356 #include <i386/isa/if_ieee80211.h>
357 #include <i386/isa/if_rayreg.h>
358 #include <i386/isa/if_raymib.h>
359
360 #if NCARD > 0
361 #include <pccard/cardinfo.h>
362 #include <pccard/cis.h>
363 #include <pccard/driver.h>
364 #include <pccard/slot.h>
365 #endif /* NCARD */
366
367 #if NAPM > 0
368 #include <machine/apm_bios.h>
369 #endif /* NAPM */
370
371 /*
372  * Sysctl knobs
373  */
374 static int ray_debug = RAY_DEBUG;
375
376 SYSCTL_NODE(_hw, OID_AUTO, ray, CTLFLAG_RW, 0, "Raylink Driver");
377 SYSCTL_INT(_hw_ray, OID_AUTO, debug, CTLFLAG_RW, &ray_debug, RAY_DEBUG, "");
378
379 /*
380  * Network parameters, used twice in sotfc to store what we want and what
381  * we have.
382  *
383  * XXX promisc in here too?
384  * XXX sc_station_addr in here too (for changing mac address)
385  */
386 struct ray_nw_param {
387     struct ray_cmd_net  p_1;
388     u_int8_t            np_ap_status;
389     struct ray_net_params \
390                         p_2;
391     u_int8_t            np_countrycode;
392 };
393 #define np_upd_param    p_1.c_upd_param
394 #define np_bss_id       p_1.c_bss_id
395 #define np_inited       p_1.c_inited
396 #define np_def_txrate   p_1.c_def_txrate
397 #define np_encrypt      p_1.c_encrypt
398 #define np_net_type     p_2.p_net_type
399 #define np_ssid         p_2.p_ssid
400 #define np_priv_start   p_2.p_privacy_must_start
401 #define np_priv_join    p_2.p_privacy_can_join
402
403 /*
404  * One of these structures per allocated device
405  */
406 struct ray_softc {
407
408     struct arpcom       arpcom;         /* Ethernet common              */
409     struct ifmedia      ifmedia;        /* Ifnet common                 */
410     struct callout_handle \
411                         ccs_timerh;     /* Handle for ccs timeouts      */
412     struct callout_handle \
413                         reset_timerh;   /* Handle for reset timer       */
414     struct callout_handle \
415                         start_timerh;   /* Handle for start timer       */
416 #if RAY_NEED_STARTJOIN_TIMO
417     struct callout_handle \
418                         sj_timerh;      /* Handle for start_join timer  */
419 #endif /* RAY_NEED_STARTJOIN_TIMO */
420     char                *card_type;     /* Card model name              */
421     char                *vendor;        /* Card manufacturer            */
422
423     int                 unit;           /* Unit number                  */
424     u_char              gone;           /* 1 = Card bailed out          */
425     caddr_t             maddr;          /* Shared RAM Address           */
426     int                 flags;          /* Start up flags               */
427
428     int                 translation;    /* Packet translation types     */
429
430 #if (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP)
431     int                 slotnum;        /* Slot number                  */
432     struct mem_desc     md;             /* Map info for common memory   */
433 #endif /* (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP) */
434
435     struct ray_ecf_startup_v5 \
436                         sc_ecf_startup; /* Startup info from card       */
437
438     struct ray_nw_param sc_c;           /* current network params       */
439     struct ray_nw_param sc_d;           /* desired network params       */
440     int                 sc_havenet;     /* true if we have a network    */
441     int                 sc_promisc;     /* current set value            */
442     int                 sc_running;     /* things we are doing          */
443     int                 sc_scheduled;   /* things we need to do         */
444     int                 sc_timoneed;    /* set if timeout is sched      */
445     int                 sc_timocheck;   /* set if timeout is sched      */
446     u_int8_t            sc_ccsinuse[64];/* ccss' in use -- not for tx   */
447
448     int                 sc_checkcounters;
449     u_int64_t           sc_rxoverflow;  /* Number of rx overflows       */
450     u_int64_t           sc_rxcksum;     /* Number of checksum errors    */
451     u_int64_t           sc_rxhcksum;    /* Number of header checksum errors */
452     u_int8_t            sc_rxnoise;     /* Average receiver level       */
453
454     struct ray_param_req \
455                         *sc_repreq;     /* used to return values        */
456     struct ray_param_req \
457                         *sc_updreq;     /* to the user                  */
458 };
459 static struct ray_softc ray_softc[NRAY];
460
461 #define sc_station_addr sc_ecf_startup.e_station_addr
462 #define sc_version      sc_ecf_startup.e_fw_build_string
463 #define sc_tibsize      sc_ecf_startup.e_tibsize
464
465 /* Commands -- priority given to LSB */
466 #define SCP_FIRST               0x0001
467 #define SCP_UPDATESUBCMD        0x0001
468 #define SCP_STARTASSOC          0x0002
469 #define SCP_REPORTPARAMS        0x0004
470 #define SCP_IFSTART             0x0008
471
472 /* Update sub commands -- issues are serialized priority to LSB */
473 #define SCP_UPD_FIRST           0x0100
474 #define SCP_UPD_STARTUP         0x0100
475 #define SCP_UPD_STARTJOIN       0x0200
476 #define SCP_UPD_PROMISC         0x0400
477 #define SCP_UPD_MCAST           0x0800
478 #define SCP_UPD_UPDATEPARAMS    0x1000
479 #define SCP_UPD_SHIFT           8
480 #define SCP_UPD_MASK            0xff00
481
482 /* These command (a subset of the update set) require timeout checking */
483 #define SCP_TIMOCHECK_CMD_MASK  \
484         (SCP_UPD_UPDATEPARAMS | SCP_UPD_STARTUP | SCP_UPD_MCAST | \
485         SCP_UPD_PROMISC)
486
487 /*
488  * Translation types
489  */
490 /* XXX maybe better as part of the if structure? */
491 #define SC_TRANSLATE_WEBGEAR    0
492
493 /*
494  * Prototyping
495  */
496 static int      ray_attach              __P((struct isa_device *dev));
497 static int      ray_alloc_ccs           __P((struct ray_softc *sc, size_t *ccsp, u_int cmd, u_int track));
498 static void     ray_ccs_done            __P((struct ray_softc *sc, size_t ccs));
499 static void     ray_check_ccs           __P((void *arg));
500 static void     ray_check_scheduled     __P((void *arg));
501 static void     ray_cmd_cancel          __P((struct ray_softc *sc, int cmdf));
502 static void     ray_cmd_done            __P((struct ray_softc *sc, int cmdf));
503 static int      ray_cmd_is_running      __P((struct ray_softc *sc, int cmdf));
504 static int      ray_cmd_is_scheduled    __P((struct ray_softc *sc, int cmdf));
505 static void     ray_cmd_ran             __P((struct ray_softc *sc, int cmdf));
506 static void     ray_cmd_schedule        __P((struct ray_softc *sc, int cmdf));
507 static void     ray_download_done       __P((struct ray_softc *sc));
508 static void     ray_download_params     __P((struct ray_softc *sc));
509 #if RAY_DEBUG > 50
510 static void     ray_dump_mbuf           __P((struct ray_softc *sc, struct mbuf *m, char *s));
511 #endif /* RAY_DEBUG > 50 */
512 static u_int8_t ray_free_ccs            __P((struct ray_softc *sc, size_t ccs));
513 #if XXX_NETBSDTX
514 static void     ray_free_ccs_chain      __P((struct ray_softc *sc, u_int ni));
515 #endif /* XXX_NETBSDTX */
516 static int      ray_intr                __P((struct pccard_devinfo *dev_p));
517 static int      ray_ioctl               __P((struct ifnet *ifp, u_long command, caddr_t data));
518 static void     ray_init                __P((void *xsc));
519 static int      ray_issue_cmd           __P((struct ray_softc *sc, size_t ccs, u_int track));
520 static int      ray_pccard_init         __P((struct pccard_devinfo *dev_p));
521 static int      ray_pccard_intr         __P((struct pccard_devinfo *dev_p));
522 static void     ray_pccard_unload       __P((struct pccard_devinfo *dev_p));
523 static int      ray_probe               __P((struct isa_device *dev));
524 static void     ray_rcs_intr            __P((struct ray_softc *sc, size_t ccs));
525
526 static void     ray_report_params       __P((struct ray_softc *sc));
527 static void     ray_reset               __P((struct ray_softc *sc));
528 static void     ray_reset_timo          __P((void *xsc));
529 static void     ray_rx                  __P((struct ray_softc *sc, size_t rcs));
530 static void     ray_set_pending         __P((struct ray_softc *sc, u_int cmdf));
531 static int      ray_simple_cmd          __P((struct ray_softc *sc, u_int cmd, u_int track));
532 static void     ray_start               __P((struct ifnet *ifp));
533 static void     ray_start_assoc         __P((struct ray_softc *sc));
534 static void     ray_start_done          __P((struct ray_softc *sc, size_t ccs, u_int8_t status));
535 static void     ray_start_sc            __P((struct ray_softc *sc));
536 static void     ray_start_timo          __P((void *xsc));
537 static size_t   ray_start_wrhdr         __P((struct ray_softc *sc, struct ether_header *eh, size_t bufp));
538 static void     ray_start_join_done     __P((struct ray_softc *sc, size_t ccs, u_int8_t status));
539 static void     ray_start_join_net      __P((struct ray_softc *sc));
540 #if RAY_NEED_STARTJOIN_TIMO
541 static void     ray_start_join_timo     __P((void *xsc));
542 #endif /* RAY_NEED_STARTJOIN_TIMO */
543 static void     ray_stop                __P((struct ray_softc *sc));
544 static void     ray_update_error_counters \
545                                         __P((struct ray_softc *sc));
546 static void     ray_update_mcast        __P((struct ray_softc *sc)); 
547 static void     ray_update_params       __P((struct ray_softc *sc));
548 static void     ray_update_params_done  __P((struct ray_softc *sc, size_t ccs, u_int stat));
549 static void     ray_update_promisc      __P((struct ray_softc *sc));
550 static void     ray_update_subcmd       __P((struct ray_softc *sc));
551 static int      ray_user_update_params  __P((struct ray_softc *sc, struct ray_param_req *pr));
552 static int      ray_user_report_params  __P((struct ray_softc *sc, struct ray_param_req *pr));
553 static int      ray_user_report_stats   __P((struct ray_softc *sc, struct ray_stats_req *sr));
554 static void     ray_watchdog            __P((struct ifnet *ifp));
555
556 /*
557  * PCMCIA driver definition
558  */
559 PCCARD_MODULE(ray, ray_pccard_init, ray_pccard_unload, ray_pccard_intr, 0, net_imask);
560
561 /*
562  * ISA driver definition
563  */
564 struct isa_driver raydriver = {
565     ray_probe,
566     ray_attach,
567     "ray",
568     1
569 };
570
571 /*
572  * Command function tables - based on bit index in SCP_xx
573  */
574 typedef void (*ray_cmd_func_t)(struct ray_softc *);
575 static ray_cmd_func_t ray_cmdtab[] = {
576         ray_update_subcmd,      /* SCP_UPDATESUBCMD */
577         ray_start_assoc,        /* SCP_STARTASSOC */
578         ray_report_params,      /* SCP_REPORTPARAMS */
579         ray_start_sc            /* SCP_IFSTART */
580 };
581 static int ray_ncmdtab = sizeof(ray_cmdtab) / sizeof(*ray_cmdtab);
582
583 static ray_cmd_func_t ray_subcmdtab[] = {
584         ray_download_params,    /* SCP_UPD_STARTUP */
585         ray_start_join_net,     /* SCP_UPD_STARTJOIN */
586         ray_update_promisc,     /* SCP_UPD_PROMISC */
587         ray_update_mcast,       /* SCP_UPD_MCAST */
588         ray_update_params       /* SCP_UPD_UPDATEPARAMS */
589 };
590 static int ray_nsubcmdtab = sizeof(ray_subcmdtab) / sizeof(*ray_subcmdtab);
591
592 /*
593  * Indirections for reading/writing shared memory - from NetBSD/if_ray.c
594  */
595 #ifndef offsetof
596 #define offsetof(type, member) \
597     ((size_t)(&((type *)0)->member))
598 #endif /* offsetof */
599
600 #define SRAM_READ_1(sc, off) \
601     (u_int8_t)*((sc)->maddr + (off))
602 /* ((u_int8_t)bus_space_read_1((sc)->sc_memt, (sc)->sc_memh, (off))) */
603
604 #define SRAM_READ_FIELD_1(sc, off, s, f) \
605     SRAM_READ_1(sc, (off) + offsetof(struct s, f))
606
607 #define SRAM_READ_FIELD_2(sc, off, s, f)                        \
608     ((((u_int16_t)SRAM_READ_1(sc, (off) + offsetof(struct s, f)) << 8) \
609     |(SRAM_READ_1(sc, (off) + 1 + offsetof(struct s, f)))))
610
611 #define SRAM_READ_FIELD_N(sc, off, s, f, p, n)  \
612     ray_read_region(sc, (off) + offsetof(struct s, f), (p), (n))
613
614 #define ray_read_region(sc, off, vp, n) \
615     bcopy((sc)->maddr + (off), (vp), (n))
616
617 #define SRAM_WRITE_1(sc, off, val)      \
618     *((sc)->maddr + (off)) = (val)
619 /* bus_space_write_1((sc)->sc_memt, (sc)->sc_memh, (off), (val)) */
620
621 #define SRAM_WRITE_FIELD_1(sc, off, s, f, v)    \
622     SRAM_WRITE_1(sc, (off) + offsetof(struct s, f), (v))
623
624 #define SRAM_WRITE_FIELD_2(sc, off, s, f, v) do {       \
625     SRAM_WRITE_1(sc, (off) + offsetof(struct s, f), (((v) >> 8 ) & 0xff)); \
626     SRAM_WRITE_1(sc, (off) + 1 + offsetof(struct s, f), ((v) & 0xff)); \
627 } while (0)
628
629 #define SRAM_WRITE_FIELD_N(sc, off, s, f, p, n) \
630     ray_write_region(sc, (off) + offsetof(struct s, f), (p), (n))
631
632 #define ray_write_region(sc, off, vp, n) \
633     bcopy((vp), (sc)->maddr + (off), (n))
634
635 /*
636  * Macro's and constants
637  */
638 #ifndef RAY_CCS_TIMEOUT
639 #define RAY_CCS_TIMEOUT         (hz / 2)
640 #endif
641 #ifndef RAY_CHECK_SCHED_TIMEOUT
642 #define RAY_CHECK_SCHED_TIMEOUT (hz)
643 #endif
644 #ifndef RAY_RESET_TIMEOUT
645 #define RAY_RESET_TIMEOUT       (10 * hz)
646 #endif
647 #ifndef RAY_START_TIMEOUT
648 #define RAY_START_TIMEOUT       (hz / 2)
649 #endif
650 #if RAY_SIMPLE_TX
651 #define RAY_IFQ_MAXLEN          (2)
652 #else if RAY_DECENT_TX
653 #define RAY_IFQ_MAXLEN          (RAY_CCS_TX_LAST+1)
654 #endif
655 #define RAY_CCS_FREE(sc, ccs) \
656     SRAM_WRITE_FIELD_1((sc), (ccs), ray_cmd, c_status, RAY_CCS_STATUS_FREE)
657 #define RAY_ECF_READY(sc)       (!(ray_read_reg(sc, RAY_ECFIR) & RAY_ECFIR_IRQ))
658 #define RAY_ECF_START_CMD(sc)   ray_attr_write((sc), RAY_ECFIR, RAY_ECFIR_IRQ)
659 #define RAY_HCS_CLEAR_INTR(sc)  ray_attr_write((sc), RAY_HCSIR, 0)
660 #define RAY_HCS_INTR(sc)        (ray_read_reg(sc, RAY_HCSIR) & RAY_HCSIR_IRQ)
661
662 /*
663  * As described in if_xe.c...
664  *
665  * Horrid stuff for accessing CIS tuples and remapping common memory...
666  */
667 #define CARD_MAJOR              50
668 static int      ray_attr_write  __P((struct ray_softc *sc, off_t offset, u_int8_t byte));
669 static int      ray_attr_read   __P((struct ray_softc *sc, off_t offset, u_int8_t *buf, int size));
670 static u_int8_t ray_read_reg    __P((struct ray_softc *sc, off_t reg));
671
672 #if (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP)
673 static void     ray_attr_getmap __P((struct ray_softc *sc));
674 static void     ray_attr_cm     __P((struct ray_softc *sc));
675 #define RAY_MAP_CM(sc)          ray_attr_cm(sc)
676 #else
677 #define RAY_MAP_CM(sc)
678 #endif /* (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP) */
679
680 /*
681  * PCCard initialise.
682  */
683 static int
684 ray_pccard_init (dev_p)
685     struct pccard_devinfo   *dev_p;
686 {
687     struct ray_softc    *sc;
688     int                 doRemap;
689
690     RAY_DPRINTFN(5, ("ray%d: PCCard probe\n", dev_p->isahd.id_unit));
691
692     if (dev_p->isahd.id_unit >= NRAY)
693         return (ENODEV);
694
695     sc = &ray_softc[dev_p->isahd.id_unit];
696
697 #if (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP)
698     sc->slotnum = dev_p->slt->slotnum;
699     ray_attr_getmap(sc);
700     RAY_DPRINTFN(1, ("ray%d: Memory window flags 0x%02x, start %p, size 0x%x, card address 0x%lx\n", sc->unit, sc->md.flags, sc->md.start, sc->md.size, sc->md.card));
701 #endif /* (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP) */
702
703 #if RAY_NEED_CM_FIXUP
704     doRemap = 0;
705     if (sc->md.start == 0x0) {
706         printf("ray%d: pccardd did not map CM - giving up\n", sc->unit);
707         return (ENXIO);
708     }
709     if (sc->md.flags != MDF_ACTIVE) {
710         printf("ray%d: Fixing up CM flags from 0x%x to 0x40\n",
711                 sc->unit, sc->md.flags);
712         doRemap = 1;
713         sc->md.flags = MDF_ACTIVE;
714     }
715     if (sc->md.size != 0xc000) {
716         printf("ray%d: Fixing up CM size from 0x%x to 0xc000\n",
717                 sc->unit, sc->md.size);
718         doRemap = 1;
719         sc->md.size = 0xc000;
720         dev_p->isahd.id_msize = sc->md.size;
721     }
722     if (sc->md.card != 0) {
723         printf("ray%d: Fixing up CM card address from 0x%lx to 0x0\n",
724                 sc->unit, sc->md.card);
725         doRemap = 1;
726         sc->md.card = 0;
727     }
728     if (doRemap)
729         ray_attr_cm(sc);
730 #endif /* RAY_NEED_CM_FIXUP */
731
732     sc->gone = 0;
733     sc->unit = dev_p->isahd.id_unit;
734     sc->maddr = dev_p->isahd.id_maddr;
735     sc->flags = dev_p->isahd.id_flags;
736
737     printf("ray%d: <Raylink/IEEE 802.11> maddr %p msize 0x%x irq %d flags 0x%x on isa (PC-Card slot %d)\n",
738         sc->unit,
739         sc->maddr,
740         dev_p->isahd.id_msize,
741         ffs(dev_p->isahd.id_irq) - 1,
742         sc->flags,
743         sc->slotnum);
744
745     if (ray_attach(&dev_p->isahd))
746         return (ENXIO);
747
748     return (0);
749 }
750
751 /*
752  * PCCard unload.
753  */
754 static void
755 ray_pccard_unload (dev_p)
756     struct pccard_devinfo       *dev_p;
757 {
758     struct ray_softc            *sc;
759     struct ifnet                *ifp;
760
761     RAY_DPRINTFN(5, ("ray%d: PCCard unload\n", dev_p->isahd.id_unit));
762
763     sc = &ray_softc[dev_p->isahd.id_unit];
764     ifp = &sc->arpcom.ac_if;
765
766     if (sc->gone) {
767         printf("ray%d: already unloaded\n", sc->unit);
768         return;
769     }
770
771     /*
772      * Clear out timers and sort out driver state
773      *
774      * We use callout_stop to unconditionally kill the ccs and general
775      * timers as they are used with multiple arguments.
776      */
777 #if RAY_USE_CALLOUT_STOP
778     callout_stop(sc->ccs_timerh);
779     callout_stop(sc->reset_timerh);
780 #else
781     untimeout(ray_check_ccs, sc, sc->ccs_timerh);
782     untimeout(ray_check_scheduled, sc, sc->ccs_timerh);
783     untimeout(ray_reset_timo, sc, sc->reset_timerh);
784 #endif /* RAY_USE_CALLOUT_STOP */
785 #if RAY_NEED_STARTJOIN_TIMO
786     untimeout(ray_start_join_timo, sc, sc->sj_timerh);
787 #endif /* RAY_NEED_STARTJOIN_TIMO */
788     untimeout(ray_start_timo, sc, sc->start_timerh);
789     sc->sc_havenet = 0;
790
791     /*
792      * Mark as not running
793      */
794     ifp->if_flags &= ~IFF_RUNNING;
795     ifp->if_flags &= ~IFF_OACTIVE;
796
797     /*
798      * Cleardown interface
799      */
800     if_down(ifp); /* XXX should be if_detach for -current */
801
802     /*
803      * Mark card as gone
804      */
805     sc->gone = 1;
806     printf("ray%d: unloaded\n", sc->unit);
807
808     return;
809 }
810
811 /*
812  * process an interrupt
813  */
814 static int
815 ray_pccard_intr (dev_p)
816     struct pccard_devinfo       *dev_p;
817 {
818     return (ray_intr(dev_p));
819 }
820
821 /*
822  * ISA probe routine.
823  */
824 static int
825 ray_probe (dev_p)
826     struct isa_device           *dev_p;
827 {
828
829     RAY_DPRINTFN(5, ("ray%d: ISA probe\n", dev_p->id_unit));
830
831     return (0);
832 }
833
834 /*
835  * ISA/PCCard attach.
836  */
837 static int
838 ray_attach (dev_p)
839     struct isa_device           *dev_p;
840 {
841     struct ray_softc            *sc;
842     struct ray_ecf_startup_v5   *ep;
843     struct ifnet                *ifp;
844     char                        ifname[IFNAMSIZ];
845
846     RAY_DPRINTFN(5, ("ray%d: ISA/PCCard attach\n", dev_p->id_unit));
847
848     sc = &ray_softc[dev_p->id_unit];
849     RAY_MAP_CM(sc);
850
851     if (sc->gone) {
852         printf("ray%d: unloaded before attach!\n", sc->unit);
853         return (1);
854     }
855
856     /*
857      * Read startup results, check the card is okay and work out what
858      * version we are using.
859      */
860     ep = &sc->sc_ecf_startup;
861     ray_read_region(sc, RAY_ECF_TO_HOST_BASE, ep, sizeof(sc->sc_ecf_startup));
862     if (ep->e_status != RAY_ECFS_CARD_OK) {
863         printf("ray%d: card failed self test: status 0x%b\n", sc->unit,
864             ep->e_status,
865             "\020"                      /* print in hex */
866             "\001RESERVED0"
867             "\002PROC_SELF_TEST"
868             "\003PROG_MEM_CHECKSUM"
869             "\004DATA_MEM_TEST"
870             "\005RX_CALIBRATION"
871             "\006FW_VERSION_COMPAT"
872             "\007RERSERVED1"
873             "\008TEST_COMPLETE"
874         );
875         return (1);
876     }
877     if (sc->sc_version != RAY_ECFS_BUILD_4 &&
878         sc->sc_version != RAY_ECFS_BUILD_5
879        ) {
880         printf("ray%d: unsupported firmware version 0x%0x\n", sc->unit,
881             ep->e_fw_build_string);
882         return (1);
883     }
884
885     if (bootverbose || RAY_DEBUG) {
886         printf("ray%d: Start Up Results\n", sc->unit);
887         if (sc->sc_version == RAY_ECFS_BUILD_4)
888             printf("  Firmware version 4\n");
889         else
890             printf("  Firmware version 5\n");
891         printf("  Status 0x%x\n", ep->e_status);
892         printf("  Ether address %6D\n", ep->e_station_addr, ":");
893         if (sc->sc_version == RAY_ECFS_BUILD_4) {
894             printf("  Program checksum %0x\n", ep->e_resv0);
895             printf("  CIS checksum %0x\n", ep->e_rates[0]);
896         } else {
897             printf("  (reserved word) %0x\n", ep->e_resv0);
898             printf("  Supported rates %8D\n", ep->e_rates, ":");
899         }
900         printf("  Japan call sign %12D\n", ep->e_japan_callsign, ":");
901         if (sc->sc_version == RAY_ECFS_BUILD_5) {
902             printf("  Program checksum %0x\n", ep->e_prg_cksum);
903             printf("  CIS checksum %0x\n", ep->e_cis_cksum);
904             printf("  Firmware version %0x\n", ep->e_fw_build_string);
905             printf("  Firmware revision %0x\n", ep->e_fw_build);
906             printf("  (reserved word) %0x\n", ep->e_fw_resv);
907             printf("  ASIC version %0x\n", ep->e_asic_version);
908             printf("  TIB size %0x\n", ep->e_tibsize);
909         }
910     }
911
912     /* Reset any pending interrupts */
913     RAY_HCS_CLEAR_INTR(sc);
914
915     /*
916      * Set the parameters that will survive stop/init
917      *
918      * Do not update these in ray_init's parameter setup
919      */
920 #if XXX
921     see the ray_init section for stuff to move
922 #endif
923     bzero(&sc->sc_d, sizeof(struct ray_nw_param));
924     bzero(&sc->sc_c, sizeof(struct ray_nw_param));
925
926     /*
927      * Initialise the network interface structure
928      */
929     bcopy((char *)&ep->e_station_addr,
930           (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
931     ifp = &sc->arpcom.ac_if;
932     ifp->if_softc = sc;
933     ifp->if_name = "ray";
934     ifp->if_unit = sc->unit;
935     ifp->if_timer = 0;
936     ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
937 #if XXX
938     ifp->if_hdr = ...; make this big enough to hold the .11 and .3 headers
939 #endif
940     ifp->if_baudrate = 1000000; /* Is this baud or bps ;-) */
941
942     ifp->if_output = ether_output;
943     ifp->if_start = ray_start;
944     ifp->if_ioctl = ray_ioctl;
945     ifp->if_watchdog = ray_watchdog;
946     ifp->if_init = ray_init;
947     ifp->if_snd.ifq_maxlen = RAY_IFQ_MAXLEN;
948
949     /*
950      * If this logical interface has already been attached,
951      * don't attach it again or chaos will ensue.
952      */
953     sprintf(ifname, "ray%d", sc->unit);
954
955     if (ifunit(ifname) == NULL) {
956         callout_handle_init(&sc->ccs_timerh);
957         callout_handle_init(&sc->reset_timerh);
958 #if RAY_NEED_STARTJOIN_TIMO
959         callout_handle_init(&sc->sj_timerh);
960 #endif /* RAY_NEED_STARTJOIN_TIMO */
961         callout_handle_init(&sc->start_timerh);
962         if_attach(ifp);
963         ether_ifattach(ifp);
964 #if NBPFILTER > 0
965         bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
966 #endif /* NBFFILTER */
967
968 #if XXX
969         this looks like a good idea
970         at_shutdown(ray_shutdown, sc, SHUTDOWN_POST_SYNC);
971 #endif /* XXX */
972     }
973
974     return (0);
975 }
976
977 /*
978  * Network initialisation.
979  *
980  * Start up flow is as follows.
981  * The kernel calls ray_init when the interface is assigned an address.
982  * 
983  * ray_init does a bit of house keeping before calling ray_download_params.
984  *
985  * ray_download_params fills the startup parameter structure out and
986  * sends it to the card. The download command simply completes, so we
987  * use the timeout code in ray_check_ccs instead of spin locking. The
988  * passes flow to the standard ccs handler and we eventually end up in
989  * ray_download_done.
990  *
991  * ray_download_done tells the card to start an adhoc network or join
992  * a managed network. This should complete via the interrupt
993  * mechanism, but the NetBSD driver includes a timeout for some buggy
994  * stuff somewhere - I've left the hooks in but don't use them. The
995  * interrupt handler passes control to ray_start_join_done - the ccs
996  * is handled by the interrupt mechanism.
997  *
998  * Once ray_start_join_done has checked the ccs and uploaded/updated
999  * the network parameters we are ready to process packets. It is then
1000  * safe to call ray_start which is done by the interrupt handler.
1001  */
1002 static void
1003 ray_init (xsc)
1004     void                        *xsc;
1005 {
1006     struct ray_softc            *sc = xsc;
1007     struct ray_ecf_startup_v5   *ep;
1008     struct ifnet                *ifp;
1009     size_t                      ccs;
1010     int                         i;
1011
1012     RAY_DPRINTFN(5, ("ray%d: Network init\n", sc->unit));
1013     RAY_MAP_CM(sc);
1014
1015     if (sc->gone) {
1016         printf("ray%d: unloaded before init!\n", sc->unit);
1017         return;
1018     }
1019
1020     ifp = &sc->arpcom.ac_if;
1021
1022     if ((ifp->if_flags & IFF_RUNNING))
1023         ray_stop(sc);
1024
1025     /*
1026      * Reset instance variables
1027      *
1028      * The first set are network parameters that are read back when
1029      * the card starts or joins the network.
1030      *
1031      * The second set are network parameters that are downloaded to
1032      * the card.
1033      *
1034      * The third set are driver parameters.
1035      *
1036      * All of the variables in these sets can be updated by the card or ioctls.
1037      */
1038 #if XXX
1039     see the ray_attach section for stuff to move
1040 #endif
1041     sc->sc_d.np_upd_param = 0;
1042     bzero(sc->sc_d.np_bss_id, ETHER_ADDR_LEN);
1043     sc->sc_d.np_inited = 0;
1044     sc->sc_d.np_def_txrate = RAY_MIB_BASIC_RATE_SET_DEFAULT;
1045     sc->sc_d.np_encrypt = 0;
1046
1047     sc->sc_d.np_ap_status = RAY_MIB_AP_STATUS_DEFAULT;
1048     sc->sc_d.np_net_type = RAY_MIB_NET_TYPE_DEFAULT;
1049     bzero(sc->sc_d.np_ssid, IEEE80211_NWID_LEN);
1050     strncpy(sc->sc_d.np_ssid, RAY_MIB_SSID_DEFAULT, IEEE80211_NWID_LEN);
1051     sc->sc_d.np_priv_start = RAY_MIB_PRIVACY_MUST_START_DEFAULT;
1052     sc->sc_d.np_priv_join = RAY_MIB_PRIVACY_CAN_JOIN_DEFAULT;
1053     sc->sc_promisc = !!(ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI));
1054
1055     sc->sc_havenet = 0;
1056     sc->translation = SC_TRANSLATE_WEBGEAR;
1057
1058     /* Set all ccs to be free */
1059     bzero(sc->sc_ccsinuse, sizeof(sc->sc_ccsinuse));
1060     ccs = RAY_CCS_ADDRESS(0);
1061     for (i = 0; i < RAY_CCS_LAST; ccs += RAY_CCS_SIZE, i++)
1062             RAY_CCS_FREE(sc, ccs);
1063
1064     /* Clear any pending interrupts */
1065     RAY_HCS_CLEAR_INTR(sc);
1066
1067 #if XXX
1068     Not sure why I really need this - maybe best to deal with
1069     this when resets are requested by me?
1070 #endif /* XXX */
1071     /*
1072      * Get startup results - the card may have been reset
1073      */
1074     ep = &sc->sc_ecf_startup;
1075     ray_read_region(sc, RAY_ECF_TO_HOST_BASE, ep, sizeof(sc->sc_ecf_startup));
1076     if (ep->e_status != RAY_ECFS_CARD_OK) {
1077         printf("ray%d: card failed self test: status 0x%b\n", sc->unit,
1078             ep->e_status,
1079             "\020"                      /* print in hex */
1080             "\001RESERVED0"
1081             "\002PROC_SELF_TEST"
1082             "\003PROG_MEM_CHECKSUM"
1083             "\004DATA_MEM_TEST"
1084             "\005RX_CALIBRATION"
1085             "\006FW_VERSION_COMPAT"
1086             "\007RERSERVED1"
1087             "\008TEST_COMPLETE"
1088         );
1089         return; /* XXX This doesn't mark the interface as down */
1090     }
1091
1092     /*
1093      * Fixup tib size to be correct - on build 4 it is garbage
1094      */
1095     if (sc->sc_version == RAY_ECFS_BUILD_4 && sc->sc_tibsize == 0x55)
1096         sc->sc_tibsize = sizeof(struct ray_tx_tib);
1097
1098     /*
1099      * We are now up and running. Next we have to download network
1100      * configuration into the card. We are busy until download is done.
1101      */
1102     ifp->if_flags |= IFF_RUNNING | IFF_OACTIVE;
1103
1104     ray_download_params(sc);
1105
1106     return;
1107 }
1108
1109 /*
1110  * Network stop.
1111  *
1112  * Assumes that a ray_init is used to restart the card.
1113  *
1114  */
1115 static void
1116 ray_stop (sc)
1117     struct ray_softc    *sc;
1118 {
1119     struct ifnet        *ifp;
1120     int                 s;
1121
1122     RAY_DPRINTFN(5, ("ray%d: Network stop\n", sc->unit));
1123     RAY_MAP_CM(sc);
1124
1125     if (sc->gone) {
1126         printf("ray%d: unloaded before stop!\n", sc->unit);
1127         return;
1128     }
1129
1130     ifp = &sc->arpcom.ac_if;
1131
1132     /*
1133      * Clear out timers and sort out driver state
1134      */
1135 #if RAY_USE_CALLOUT_STOP
1136     callout_stop(sc->ccs_timerh);
1137     callout_stop(sc->reset_timerh);
1138 #else
1139     untimeout(ray_check_ccs, sc, sc->ccs_timerh);
1140     untimeout(ray_check_scheduled, sc, sc->ccs_timerh);
1141     untimeout(ray_reset_timo, sc, sc->reset_timerh);
1142 #endif /* RAY_USE_CALLOUT_STOP */
1143 #if RAY_NEED_STARTJOIN_TIMO
1144     untimeout(ray_start_join_timo, sc, sc->sj_timerh);
1145 #endif /* RAY_NEED_STARTJOIN_TIMO */
1146     untimeout(ray_start_timo, sc, sc->start_timerh);
1147     sc->sc_havenet = 0;
1148     sc->sc_rxoverflow = 0;
1149     sc->sc_rxcksum = 0;
1150     sc->sc_rxhcksum = 0;
1151     sc->sc_rxnoise = 0;
1152
1153     /*
1154      * Inhibit card - if we can't prevent reception then do not worry;
1155      * stopping a NIC only guarantees no TX.
1156      */
1157     s = splimp();
1158     /* XXX what does the SHUTDOWN command do? Or power saving in COR */
1159     splx(s);
1160
1161     /*
1162      * Mark as not running
1163      */
1164     ifp->if_flags &= ~IFF_RUNNING;
1165     ifp->if_flags &= ~IFF_OACTIVE;
1166
1167     return;
1168 }
1169
1170 /*
1171  * Reset the card
1172  *
1173  * I'm using the soft reset command in the COR register. I'm not sure
1174  * if the sequence is right but it does seem to do the right thing. A
1175  * nano second after reset is written the flashing light goes out, and
1176  * a few seconds after the default is written the main card light goes
1177  * out. We wait a while and then re-init the card.
1178  */
1179 static void
1180 ray_reset (sc)
1181     struct ray_softc    *sc;
1182 {
1183     struct ifnet        *ifp;
1184
1185     RAY_DPRINTFN(5, ("ray%d: ray_reset\n", sc->unit));
1186     RAY_MAP_CM(sc);
1187
1188     ifp = &sc->arpcom.ac_if;
1189
1190     if (ifp->if_flags & IFF_RUNNING)
1191         ray_stop(sc);
1192
1193     printf("ray%d: resetting card\n", sc->unit);
1194     ray_attr_write((sc), RAY_COR, RAY_COR_RESET);
1195     ray_attr_write((sc), RAY_COR, RAY_COR_DEFAULT);
1196     sc->reset_timerh = timeout(ray_reset_timo, sc, RAY_RESET_TIMEOUT);
1197
1198     return;
1199 }
1200
1201 /*
1202  * Finishing resetting and restarting the card
1203  */
1204 static void
1205 ray_reset_timo (xsc)
1206     void                *xsc;
1207 {
1208     struct ray_softc    *sc = xsc;
1209
1210     RAY_DPRINTFN(5, ("ray%d: ray_reset_timo\n", sc->unit));
1211     RAY_MAP_CM(sc);
1212
1213     if (!RAY_ECF_READY(sc)) {
1214         RAY_DPRINTFN(1, ("ray%d: ray_reset_timo still busy, re-schedule\n",
1215                 sc->unit));
1216         sc->reset_timerh = timeout(ray_reset_timo, sc, RAY_RESET_TIMEOUT);
1217         return;
1218     }
1219
1220     RAY_HCS_CLEAR_INTR(sc);
1221     ray_init(sc);
1222
1223     return;
1224 }
1225
1226 static void
1227 ray_watchdog (ifp)
1228     register struct ifnet       *ifp;
1229 {
1230     struct ray_softc *sc;
1231
1232     RAY_DPRINTFN(5, ("ray%d: Network watchdog\n", ifp->if_unit));
1233
1234     sc = ifp->if_softc;
1235     RAY_MAP_CM(sc);
1236
1237     if (sc->gone) {
1238         printf("ray%d: unloaded before watchdog!\n", sc->unit);
1239         return;
1240     }
1241
1242     printf("ray%d: watchdog timeout\n", sc->unit);
1243
1244 /* XXX may need to have remedial action here
1245    for example
1246         ray_reset
1247             ray_stop
1248             ...
1249             ray_init
1250
1251     do we only use on TX?
1252         if so then we should clear OACTIVE etc.
1253
1254 */
1255
1256     return;
1257 }
1258
1259 /*
1260  * Network ioctl request.
1261  */
1262 static int
1263 ray_ioctl (ifp, command, data)
1264     register struct ifnet       *ifp;
1265     u_long                      command;
1266     caddr_t                     data;
1267 {
1268     struct ray_softc *sc;
1269     struct ray_param_req pr;
1270     struct ray_stats_req sr;
1271     struct ifreq *ifr;
1272     int s, error, error2;
1273
1274     RAY_DPRINTFN(5, ("ray%d: Network ioctl\n", ifp->if_unit));
1275
1276     sc = ifp->if_softc;
1277     RAY_MAP_CM(sc);
1278
1279     if (sc->gone) {
1280         printf("ray%d: unloaded before ioctl!\n", sc->unit);
1281         ifp->if_flags &= ~IFF_RUNNING;
1282         return (ENXIO);
1283     }
1284
1285     ifr = (struct ifreq *)data;
1286     error = 0;
1287     error2 = 0;
1288
1289     s = splimp();
1290
1291     switch (command) {
1292
1293         case SIOCSIFADDR:
1294         case SIOCGIFADDR:
1295         case SIOCSIFMTU:
1296             RAY_DPRINTFN(30, ("ray%d: ioctl SIFADDR/GIFADDR/SIFMTU\n", sc->unit));
1297             error = ether_ioctl(ifp, command, data);
1298             break;
1299
1300         case SIOCSIFFLAGS:
1301             RAY_DPRINTFN(30, ("ray%d: for SIFFLAGS\n", sc->unit));
1302             /*
1303              * If the interface is marked up and stopped, then start
1304              * it. If it is marked down and running, then stop it.
1305              */
1306             if (ifp->if_flags & IFF_UP) {
1307                 if (!(ifp->if_flags & IFF_RUNNING))
1308                     ray_init(sc);
1309                 ray_update_promisc(sc);
1310             } else {
1311                 if (ifp->if_flags & IFF_RUNNING)
1312                     ray_stop(sc);
1313             }
1314             /* XXX DROP THROUGH or not? */
1315
1316         case SIOCADDMULTI:
1317         case SIOCDELMULTI:
1318             RAY_DPRINTFN(30, ("ray%d: ioctl called for ADDMULTI/DELMULTI\n", sc->unit));
1319             ray_update_mcast(sc);
1320             error = 0;
1321             break;
1322
1323         case SIOCSRAYPARAM:
1324             RAY_DPRINTFN(30, ("ray%d: ioctl called for SRAYPARAM\n", sc->unit));
1325             if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr))))
1326                 break;
1327             error = ray_user_update_params(sc, &pr);
1328             error2 = copyout(&pr, ifr->ifr_data, sizeof(pr));
1329             error = error2 ? error2 : error;
1330             break;
1331
1332         case SIOCGRAYPARAM:
1333             RAY_DPRINTFN(30, ("ray%d: ioctl called for GRAYPARAM\n", sc->unit));
1334             if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr))))
1335                 break;
1336             error = ray_user_report_params(sc, &pr);
1337             error2 = copyout(&pr, ifr->ifr_data, sizeof(pr));
1338             error = error2 ? error2 : error;
1339             break;
1340
1341         case SIOCGRAYSTATS:
1342             RAY_DPRINTFN(30, ("ray%d: ioctl called for GRAYSTATS\n", sc->unit));
1343             error = ray_user_report_stats(sc, &sr);
1344             error2 = copyout(&sr, ifr->ifr_data, sizeof(sr));
1345             error = error2 ? error2 : error;
1346             break;
1347
1348         case SIOCGIFFLAGS:
1349             RAY_DPRINTFN(30, ("ray%d: ioctl called for GIFFLAGS\n", sc->unit));
1350             error = EINVAL;
1351             break;
1352
1353         case SIOCGIFMETRIC:
1354             RAY_DPRINTFN(30, ("ray%d: ioctl called for GIFMETRIC\n", sc->unit));
1355             error = EINVAL;
1356             break;
1357
1358         case SIOCGIFMTU:
1359             RAY_DPRINTFN(30, ("ray%d: ioctl called for GIFMTU\n", sc->unit));
1360             error = EINVAL;
1361             break;
1362
1363         case SIOCGIFPHYS:
1364             RAY_DPRINTFN(30, ("ray%d: ioctl called for GIFPYHS\n", sc->unit));
1365             error = EINVAL;
1366             break;
1367
1368         case SIOCSIFMEDIA:
1369             RAY_DPRINTFN(30, ("ray%d: ioctl called for SIFMEDIA\n", sc->unit));
1370             error = EINVAL;
1371         break;
1372
1373         case SIOCGIFMEDIA:
1374             RAY_DPRINTFN(30, ("ray%d: ioctl called for GIFMEDIA\n", sc->unit));
1375             error = EINVAL;
1376             break;
1377
1378         default:
1379             error = EINVAL;
1380     }
1381
1382     splx(s);
1383
1384     return (error);
1385 }
1386
1387 /*
1388  * Network start.
1389  *
1390  * Start sending a packet.
1391  *
1392  * We make two assumptions here:
1393  *  1) That the current priority is set to splimp _before_ this code
1394  *     is called *and* is returned to the appropriate priority after
1395  *     return
1396  *  2) That the IFF_OACTIVE flag is checked before this code is called
1397  *     (i.e. that the output part of the interface is idle)
1398  */
1399 static void
1400 ray_start (ifp)
1401     struct ifnet        *ifp;
1402 {
1403     RAY_DPRINTFN(5, ("ray%d: ray_start\n", ifp->if_unit));
1404
1405     ray_start_sc(ifp->if_softc);
1406 }
1407
1408 static void
1409 ray_start_sc (sc)
1410     struct ray_softc            *sc;
1411 {
1412     struct ifnet                *ifp;
1413     struct mbuf                 *m0, *m;
1414     struct ether_header         *eh;
1415     size_t                      ccs, bufp;
1416     int                         i, pktlen, len;
1417     u_int8_t                    status;
1418
1419     RAY_DPRINTFN(5, ("ray%d: ray_start_sc\n", sc->unit));
1420     RAY_MAP_CM(sc);
1421
1422     ifp = &sc->arpcom.ac_if;
1423  
1424     /*
1425      * Some simple checks first
1426      */
1427     if (sc->gone) {
1428         printf("ray%d: unloaded before start!\n", sc->unit);
1429         return;
1430     }
1431     if ((ifp->if_flags & IFF_RUNNING) == 0 || !sc->sc_havenet)
1432         return;
1433     if (!RAY_ECF_READY(sc)) {
1434         RAY_DPRINTFN(1, ("ray%d: ray_start busy, schedule a timeout\n",
1435                 sc->unit));
1436         sc->start_timerh = timeout(ray_start_timo, sc, RAY_START_TIMEOUT);
1437         return;
1438     } else
1439         untimeout(ray_start_timo, sc, sc->start_timerh);
1440
1441     /*
1442      * Simple one packet at a time TX routine - probably appaling performance
1443      * and we certainly chew CPU. However bing to windows boxes shows
1444      * a reliance on the far end too:
1445      *
1446      * 1500k default rate
1447      *
1448      * Libretto 50CT (75MHz Pentium) with FreeBSD-3.1 to
1449      *   Nonname box Windows 95C (133MHz AMD 5x86)               996109bps
1450      *   AST J30 Windows 95A (100MHz Pentium)                   1307791bps
1451      *
1452      * 2000k default rate
1453      *
1454      * Libretto 50CT (75MHz Pentium) with FreeBSD-3.1 to
1455      *   Nonname box Windows 95C (133MHz AMD 5x86)              1087049bps
1456      *   AST J30 Windows 95A (100MHz Pentium)                   1307791bps
1457      *
1458      * Flow is
1459      *          get a ccs
1460      *          build the packet
1461      *          set IFF_OACTIVE
1462      *          interrupt the card to send the packet
1463      *          exit
1464      *
1465      *          wait for interrupt telling us the packet has been sent
1466      *          clear IFF_OACTIVE
1467      *          get called by the interrupt routine if any packets left
1468      */
1469
1470     /*
1471      * Find a free ccs; if none available wave good bye and exit.
1472      *
1473      * We find a ccs before we process the mbuf so that we are sure it
1474      * is worthwhile processing the packet. All errors in the mbuf
1475      * processing are either errors in the mbuf or gross configuration
1476      * errors and the packet wouldn't get through anyway.
1477      *
1478      * Don't forget to clear the ccs on errors.
1479      */
1480     i = RAY_CCS_TX_FIRST;
1481     do {
1482         status = SRAM_READ_FIELD_1(sc, RAY_CCS_ADDRESS(i), ray_cmd, c_status);
1483         if (status == RAY_CCS_STATUS_FREE)
1484             break;
1485         i++;
1486     } while (i <= RAY_CCS_TX_LAST);
1487     if (i > RAY_CCS_TX_LAST) {
1488         ifp->if_flags |= IFF_OACTIVE;
1489         return;
1490     }
1491     RAY_DPRINTFN(20, ("ray%d: ray_start using ccs 0x%02x\n", sc->unit, i));
1492
1493     /*
1494      * Reserve and fill the ccs - must do the length later.
1495      *
1496      * Even though build 4 and build 5 have different fields all these
1497      * are common apart from tx_rate. Neither the NetBSD driver or Linux
1498      * driver bother to overwrite this for build 4 cards.
1499      */
1500     ccs = RAY_CCS_ADDRESS(i);
1501     bufp = RAY_TX_BASE + i * RAY_TX_BUF_SIZE;
1502     bufp += sc->sc_tibsize;
1503     SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_status, RAY_CCS_STATUS_BUSY);
1504     SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_cmd, RAY_CMD_TX_REQ);
1505     SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_link, RAY_CCS_LINK_NULL);
1506     SRAM_WRITE_FIELD_2(sc, ccs, ray_cmd_tx, c_bufp, bufp);
1507     SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_tx_rate, sc->sc_c.np_def_txrate);
1508     SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_apm_mode, 0); /* XXX */
1509     SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_antenna, 0); /* XXX */
1510     bufp += sizeof(struct ray_tx_phy_header);
1511     
1512     /*
1513      * Get the mbuf and process it - we have to remember to free the
1514      * ccs if there are any errors
1515      */
1516     IF_DEQUEUE(&ifp->if_snd, m0);
1517     if (m0 == NULL) {
1518         RAY_CCS_FREE(sc, ccs);
1519         return;
1520     }
1521
1522     for (pktlen = 0, m = m0; m != NULL; m = m->m_next) {
1523         pktlen += m->m_len;
1524     }
1525     if (pktlen > ETHER_MAX_LEN - ETHER_CRC_LEN) {
1526         RAY_DPRINTFN(1, ("ray%d: mbuf too long %d\n", sc->unit, pktlen));
1527         RAY_CCS_FREE(sc, ccs);
1528         ifp->if_oerrors++;
1529         m_freem(m0);
1530         return;
1531     }
1532
1533     /* XXX
1534      * I would much prefer to have the complete 802.11 packet dropped to
1535      * the bpf tap and then have a user land program parse the headers
1536      * as needed. This way, tcpdump -w can be used to grab the raw data. If
1537      * needed the 802.11 aware program can "translate" the .11 to ethernet
1538      * for tcpdump -r.
1539      */
1540 #if NBPFILTER > 0
1541     if (ifp->if_bpf)
1542         bpf_mtap(ifp, m0);
1543 #endif /* NBPFILTER */
1544
1545     /*
1546      * Translation - capability as described earlier
1547      *
1548      * Each case must write the 802.11 header using ray_start_wrhdr,
1549      * passing a pointer to the ethernet header in and getting a new
1550      * tc buffer pointer. Next remove/modify/addto the 802.3 and 802.2
1551      * headers as needed.
1552      *
1553      * We've pulled up the mbuf for you.
1554      *
1555      */
1556     if (m0->m_len < sizeof(struct ether_header))
1557         m = m_pullup(m, sizeof(struct ether_header));
1558     if (m0 == NULL) {
1559         RAY_DPRINTFN(1, ("ray%d: ray_start could not pullup ether\n", sc->unit));
1560         RAY_CCS_FREE(sc, ccs);
1561         ifp->if_oerrors++;
1562         return;
1563     }
1564     eh = mtod(m0, struct ether_header *);
1565     switch (sc->translation) {
1566
1567         case SC_TRANSLATE_WEBGEAR:
1568             bufp = ray_start_wrhdr(sc, eh, bufp);
1569             break;
1570
1571         default:
1572             printf("ray%d: ray_start unknown translation type 0x%x - why?\n",
1573                         sc->unit, sc->translation);
1574             RAY_CCS_FREE(sc, ccs);
1575             ifp->if_oerrors++;
1576             m0 = m_free(m0);
1577             return;
1578
1579     }
1580     if (m0 == NULL) {
1581         RAY_DPRINTFN(1, ("ray%d: ray_start could not translate mbuf\n", sc->unit));
1582         RAY_CCS_FREE(sc, ccs);
1583         ifp->if_oerrors++;
1584         return;
1585     }
1586     pktlen = sizeof(struct ieee80211_header);
1587
1588     /*
1589      * Copy the mbuf to the buffer in common memory
1590      *
1591      * We panic and don't bother wrapping as ethernet packets are 1518
1592      * bytes, we checked the mbuf earlier, and our TX buffers are 2048
1593      * bytes. We don't have 530 bytes of headers etc. so something
1594      * must be fubar.
1595      */
1596     for (m = m0; m != NULL; m = m->m_next) {
1597         pktlen += m->m_len;
1598         if ((len = m->m_len) == 0)
1599             continue;
1600         if ((bufp + len) < RAY_TX_END)
1601             ray_write_region(sc, bufp, mtod(m, u_int8_t *), len);
1602         else 
1603             panic("ray%d: ray_start tx buffer overflow\n", sc->unit);
1604         bufp += len;
1605     }
1606     RAY_DMBUF_DUMP(sc, m0, "ray_start");
1607
1608     m_free(m0);
1609
1610     /*
1611      * Fill in a few loose ends and kick the card to send the packet
1612      */
1613     if (!RAY_ECF_READY(sc)) {
1614         /*
1615          * From NetBSD code:
1616          *
1617          * If this can really happen perhaps we need to save
1618          * the chain and use it later.  I think this might
1619          * be a confused state though because we check above
1620          * and don't issue any commands between.
1621          */
1622         printf("ray%d: ray_tx device busy\n", sc->unit);
1623         RAY_CCS_FREE(sc, ccs);
1624         ifp->if_oerrors++;
1625         return;
1626     }
1627     SRAM_WRITE_FIELD_2(sc, ccs, ray_cmd_tx, c_len, pktlen);
1628     SRAM_WRITE_1(sc, RAY_SCB_CCSI, ccs);
1629     ifp->if_opackets++;
1630     ifp->if_flags |= IFF_OACTIVE;
1631     RAY_ECF_START_CMD(sc);
1632
1633     return;
1634 }
1635 #if XXX_NETBSDTX
1636 netbsd
1637
1638 driver uses a loop
1639     repeat
1640         get a ccs
1641         get a mbuf
1642         translate and send packet to shared ram
1643     until (no more ccs's) || (no more mbuf's)
1644
1645     send ccs chain to card
1646
1647     exit
1648
1649 Linux
1650
1651 driver is simple single shot packet (with a lot of spinlocks!)
1652
1653 general
1654
1655 the tx space is 0x7000 = 28kB, and TX  buffer size is 2048 so there
1656 can be 14 requests at 2kB each
1657
1658 from this 2k we have to remove the TIB - whatever that is - for data
1659
1660
1661 netbsd:
1662         we need to call _start after receiveing a packet to see
1663         if any packets were queued whilst in the interrupt
1664
1665         there is a potential race in obtaining ccss for the tx, in that
1666         we might be in _start synchronously and then an rx interrupt
1667         occurs. the rx will call _start and steal tx ccs from underneath
1668         the interrupted entry.
1669
1670         toptions
1671                 dont call _start from rx interrupt
1672
1673                 find a safe way of locking
1674
1675                 find a better way of obtaining ccs using next free avilable?
1676
1677                 look at other drivers
1678
1679                 use tsleep/wakeup
1680
1681                 some form of ring to hold ccs
1682
1683                 free lsit
1684
1685                 rework calling
1686 #endif XXX_NETBSDTX
1687
1688 /*
1689  * TX completion routine.
1690  *
1691  * Clear ccs and network flags.
1692  */
1693 static void
1694 ray_start_done (sc, ccs, status)
1695     struct ray_softc    *sc;
1696     size_t              ccs;
1697     u_int8_t            status;
1698 {
1699     struct ifnet        *ifp;
1700     char                *status_string[] = RAY_CCS_STATUS_STRINGS;
1701
1702     RAY_DPRINTFN(5, ("ray%d: ray_start_done\n", sc->unit));
1703     RAY_MAP_CM(sc);
1704
1705     ifp = &sc->arpcom.ac_if;
1706
1707     if (status != RAY_CCS_STATUS_COMPLETE) {
1708         printf("ray%d: ray_start tx completed but status is %s.\n",
1709                 sc->unit, status_string[status]);
1710         ifp->if_oerrors++;
1711     }
1712
1713     RAY_CCS_FREE(sc, ccs);
1714     ifp->if_timer = 0;
1715     if (ifp->if_flags & IFF_OACTIVE)
1716         ifp->if_flags &= ~IFF_OACTIVE;
1717
1718     return;
1719 }
1720
1721 /*
1722  * Start timeout routine.
1723  *
1724  * Used when card was busy but we needed to send a packet.
1725  */
1726 static void
1727 ray_start_timo (xsc)
1728     void                *xsc;
1729 {
1730     struct ray_softc    *sc = xsc;
1731     struct ifnet        *ifp;
1732     int                 s;
1733
1734     RAY_DPRINTFN(5, ("ray%d: ray_start_timo\n", sc->unit));
1735     RAY_MAP_CM(sc);
1736
1737     ifp = &sc->arpcom.ac_if;
1738
1739     if (!(ifp->if_flags & IFF_OACTIVE) && (ifp->if_snd.ifq_head != NULL)) {
1740         s = splimp();
1741         ray_start(ifp);
1742         splx(s);
1743     }
1744
1745     return;
1746 }
1747
1748 /*
1749  * Write an 802.11 header into the TX buffer and return the
1750  * adjusted buffer pointer.
1751  */
1752 static size_t
1753 ray_start_wrhdr (sc, eh, bufp)
1754     struct ray_softc            *sc;
1755     struct ether_header         *eh;
1756     size_t                      bufp;
1757 {
1758     struct ieee80211_header     header;
1759
1760     RAY_DPRINTFN(5, ("ray%d: ray_start_wrhdr\n", sc->unit));
1761     RAY_MAP_CM(sc);
1762
1763     bzero(&header, sizeof(struct ieee80211_header));
1764
1765     header.i_fc[0] = (IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA);
1766     if (sc->sc_c.np_net_type == RAY_MIB_NET_TYPE_ADHOC) {
1767
1768         header.i_fc[1] = IEEE80211_FC1_STA_TO_STA;
1769         bcopy(eh->ether_dhost, header.i_addr1, ETHER_ADDR_LEN);
1770         bcopy(eh->ether_shost, header.i_addr2, ETHER_ADDR_LEN);
1771         bcopy(sc->sc_c.np_bss_id, header.i_addr3, ETHER_ADDR_LEN);
1772
1773     } else {
1774         if (sc->sc_c.np_ap_status == RAY_MIB_AP_STATUS_TERMINAL) {
1775             
1776             header.i_fc[1] = IEEE80211_FC1_STA_TO_AP;
1777             bcopy(sc->sc_c.np_bss_id, header.i_addr1, ETHER_ADDR_LEN);
1778             bcopy(eh->ether_shost, header.i_addr2, ETHER_ADDR_LEN);
1779             bcopy(eh->ether_dhost, header.i_addr3, ETHER_ADDR_LEN);
1780
1781         } else
1782             printf("ray%d: ray_start can't be an AP yet\n", sc->unit);
1783     }
1784
1785     ray_write_region(sc, bufp, (u_int8_t *)&header,
1786             sizeof(struct ieee80211_header));
1787
1788     return (bufp + sizeof(struct ieee80211_header));
1789 }
1790
1791 /*
1792  * receive a packet from the card
1793  */
1794 static void
1795 ray_rx (sc, rcs)
1796     struct ray_softc            *sc;
1797     size_t                      rcs;
1798 {
1799     struct ieee80211_header     *header;
1800     struct ether_header         *eh;
1801     struct ifnet                *ifp;
1802     struct mbuf                 *m0;
1803     size_t                      pktlen, fraglen, readlen, tmplen;
1804     size_t                      bufp, ebufp;
1805     u_int8_t                    *dst, *src;
1806     u_int8_t                    fc;
1807     u_int                       first, ni, i;
1808
1809     RAY_DPRINTFN(5, ("ray%d: ray_rx\n", sc->unit));
1810     RAY_MAP_CM(sc);
1811
1812     RAY_DPRINTFN(20, ("ray%d: rcs chain - using rcs 0x%x\n", sc->unit, rcs));
1813
1814     ifp = &sc->arpcom.ac_if;
1815     m0 = NULL;
1816     readlen = 0;
1817
1818     /*
1819      * Get first part of packet and the length. Do some sanity checks
1820      * and get a mbuf.
1821      */
1822     first = RAY_CCS_INDEX(rcs);
1823     pktlen = SRAM_READ_FIELD_2(sc, rcs, ray_cmd_rx, c_pktlen);
1824
1825     if ((pktlen > MCLBYTES) || (pktlen < sizeof(struct ieee80211_header))) {
1826         RAY_DPRINTFN(1, ("ray%d: ray_rx packet is too big or too small\n",
1827             sc->unit));
1828         ifp->if_ierrors++;
1829         goto skip_read;
1830     }
1831
1832     MGETHDR(m0, M_DONTWAIT, MT_DATA);
1833     if (m0 == NULL) {
1834         RAY_DPRINTFN(1, ("ray%d: ray_rx MGETHDR failed\n", sc->unit));
1835         ifp->if_ierrors++;
1836         goto skip_read;
1837     }
1838     if (pktlen > MHLEN) {
1839         MCLGET(m0, M_DONTWAIT);
1840         if ((m0->m_flags & M_EXT) == 0) {
1841             RAY_DPRINTFN(1, ("ray%d: ray_rx MCLGET failed\n", sc->unit));
1842             ifp->if_ierrors++;
1843             m_freem(m0);
1844             m0 = NULL;
1845             goto skip_read;
1846         }
1847     }
1848     m0->m_pkthdr.rcvif = ifp;
1849     m0->m_pkthdr.len = pktlen;
1850     m0->m_len = pktlen;
1851     dst = mtod(m0, u_int8_t *);
1852
1853     /*
1854      * Walk the fragment chain to build the complete packet.
1855      *
1856      * The use of two index variables removes a race with the
1857      * hardware. If one index were used the clearing of the CCS would
1858      * happen before reading the next pointer and the hardware can get in.
1859      * Not my idea but verbatim from the NetBSD driver.
1860      */
1861     i = ni = first;
1862     while ((i = ni) && (i != RAY_CCS_LINK_NULL)) {
1863         rcs = RAY_CCS_ADDRESS(i);
1864         ni = SRAM_READ_FIELD_1(sc, rcs, ray_cmd_rx, c_nextfrag);
1865         bufp = SRAM_READ_FIELD_2(sc, rcs, ray_cmd_rx, c_bufp);
1866         fraglen = SRAM_READ_FIELD_2(sc, rcs, ray_cmd_rx, c_len);
1867         RAY_DPRINTFN(50, ("ray%d: ray_rx frag index %d len %d bufp 0x%x ni %d\n",
1868                 sc->unit, i, fraglen, (int)bufp, ni));
1869
1870         if (fraglen + readlen > pktlen) {
1871             RAY_DPRINTFN(1, ("ray%d: ray_rx bad length current 0x%x pktlen 0x%x\n",
1872                     sc->unit, fraglen + readlen, pktlen));
1873             ifp->if_ierrors++;
1874             m_freem(m0);
1875             m0 = NULL;
1876             goto skip_read;
1877         }
1878         if ((i < RAY_RCS_FIRST) || (i > RAY_RCS_LAST)) {
1879             printf("ray%d: ray_rx bad rcs index 0x%x\n", sc->unit, i);
1880             ifp->if_ierrors++;
1881             m_freem(m0);
1882             m0 = NULL;
1883             goto skip_read;
1884         }
1885
1886         ebufp = bufp + fraglen;
1887         if (ebufp <= RAY_RX_END)
1888             ray_read_region(sc, bufp, dst, fraglen);
1889         else {
1890             ray_read_region(sc, bufp, dst, (tmplen = RAY_RX_END - bufp));
1891             ray_read_region(sc, RAY_RX_BASE, dst + tmplen, ebufp - RAY_RX_END);
1892         }
1893         dst += fraglen;
1894         readlen += fraglen;
1895     }
1896
1897 skip_read:
1898
1899     /*
1900      * Walk the chain again to free the rcss.
1901      */
1902     i = ni = first;
1903     while ((i = ni) && (i != RAY_CCS_LINK_NULL)) {
1904         rcs = RAY_CCS_ADDRESS(i);
1905         ni = SRAM_READ_FIELD_1(sc, rcs, ray_cmd_rx, c_nextfrag);
1906         RAY_CCS_FREE(sc, rcs);
1907     }
1908
1909     if (m0 == NULL)
1910         return;
1911
1912     RAY_DMBUF_DUMP(sc, m0, "ray_rx");
1913
1914     /*
1915      * Check the 802.11 packet type and obtain the .11 src addresses.
1916      *
1917      * XXX CTL and MGT packets will have separate functions, DATA with here
1918      *
1919      * XXX This needs some work for INFRA mode
1920      */
1921     header = mtod(m0, struct ieee80211_header *);
1922     fc = header->i_fc[0];
1923     if ((fc & IEEE80211_FC0_VERSION_MASK) != IEEE80211_FC0_VERSION_0) {
1924         RAY_DPRINTFN(1, ("ray%d: header not version 0 fc 0x%x\n", sc->unit, fc));
1925         ifp->if_ierrors++;
1926         m_freem(m0);
1927         return;
1928     }
1929     switch (fc & IEEE80211_FC0_TYPE_MASK) {
1930
1931         case IEEE80211_FC0_TYPE_MGT:
1932             printf("ray%d: ray_rx got a MGT packet - why?\n", sc->unit);
1933             ifp->if_ierrors++;
1934             m_freem(m0);
1935             return;
1936
1937         case IEEE80211_FC0_TYPE_CTL:
1938             printf("ray%d: ray_rx got a CTL packet - why?\n", sc->unit);
1939             ifp->if_ierrors++;
1940             m_freem(m0);
1941             return;
1942
1943         case IEEE80211_FC0_TYPE_DATA:
1944             RAY_DPRINTFN(50, ("ray%d: ray_rx got a DATA packet\n", sc->unit));
1945             break;
1946
1947         default:
1948             printf("ray%d: ray_rx got a unknown packet fc0 0x%x - why?\n",
1949                         sc->unit, fc);
1950             ifp->if_ierrors++;
1951             m_freem(m0);
1952             return;
1953
1954     }
1955     fc = header->i_fc[1];
1956     switch (fc & IEEE80211_FC1_DS_MASK) {
1957
1958         case IEEE80211_FC1_STA_TO_STA:
1959             src = header->i_addr2;
1960             RAY_DPRINTFN(50, ("ray%d: ray_rx packet from sta %6D\n",
1961                     sc->unit, src, ":"));
1962             break;
1963
1964         case IEEE80211_FC1_STA_TO_AP:
1965             RAY_DPRINTFN(1, ("ray%d: ray_rx packet from sta %6D to ap %6D\n",
1966                     sc->unit,
1967                     header->i_addr2, ":", header->i_addr3, ":"));
1968             ifp->if_ierrors++;
1969             m_freem(m0);
1970             break;
1971
1972         case IEEE80211_FC1_AP_TO_STA:
1973             RAY_DPRINTFN(1, ("ray%d: ray_rx packet from ap %6D\n",
1974                     sc->unit,
1975                     header->i_addr3, ":"));
1976             ifp->if_ierrors++;
1977             m_freem(m0);
1978             break;
1979
1980         case IEEE80211_FC1_AP_TO_AP:
1981             RAY_DPRINTFN(1, ("ray%d: ray_rx saw packet between aps %6D %6D\n",
1982                     sc->unit,
1983                     header->i_addr1, ":", header->i_addr2, ":"));
1984             ifp->if_ierrors++;
1985             m_freem(m0);
1986             return;
1987
1988         default:
1989             printf("ray%d: ray_rx packet type unknown fc1 0x%x - why?\n",
1990                     sc->unit, fc);
1991             ifp->if_ierrors++;
1992             m_freem(m0);
1993             return;
1994     }
1995
1996     /*
1997      * Translation - capability as described earlier
1998      *
1999      * Each case must remove the 802.11 header and leave an 802.3
2000      * header in the mbuf copy addresses as needed.
2001      */
2002     switch (sc->translation) {
2003
2004         case SC_TRANSLATE_WEBGEAR:
2005             /* Nice and easy - just trim the 802.11 header */
2006             m_adj(m0, sizeof(struct ieee80211_header));
2007             break;
2008
2009         default:
2010             printf("ray%d: ray_rx unknown translation type 0x%x - why?\n",
2011                         sc->unit, sc->translation);
2012             ifp->if_ierrors++;
2013             m_freem(m0);
2014             return;
2015
2016     }
2017
2018     /*
2019      * Finally, do a bit of house keeping before sending the packet
2020      * up the stack.
2021      */
2022     ifp->if_ipackets++;
2023 #if NBPFILTER > 0
2024     if (ifp->if_bpf)
2025         bpf_mtap(ifp, m0);
2026 #endif /* NBPFILTER */
2027 #if XXX_PROM
2028 if_wi.c - might be needed if we hear our own broadcasts in promiscuous mode
2029 but will not be if we dont see them
2030         if ((ifp->if_flags & IFF_PROMISC) &&
2031             (bcmp(eh->ether_shost, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN) &&
2032             (eh->ether_dhost[0] & 1) == 0)
2033         ) {
2034             m_freem(m0);
2035             return;
2036         }
2037 #endif /* XXX_PROM */
2038     eh = mtod(m0, struct ether_header *);
2039     m_adj(m0, sizeof(struct ether_header));
2040     ether_input(ifp, eh, m0);
2041
2042     return;
2043 }
2044
2045 /******************************************************************************
2046  * XXX NOT KNF FROM HERE UP
2047  ******************************************************************************/
2048 /*
2049  * an update params command has completed lookup which command and
2050  * the status
2051  *
2052  * XXX this isn't finished yet, we need to grok the command used
2053  */
2054 static void
2055 ray_update_params_done(struct ray_softc *sc, size_t ccs, u_int stat)
2056 {
2057         RAY_DPRINTFN(5, ("ray%d: ray_update_params_done\n", sc->unit));
2058         RAY_MAP_CM(sc);
2059
2060         RAY_DPRINTFN(20, ("ray%d: ray_update_params_done stat %d\n",
2061             sc->unit, stat));
2062
2063         /* this will get more complex as we add commands */
2064         if (stat == RAY_CCS_STATUS_FAIL) {
2065                 printf("ray%d: failed to update a promisc\n", sc->unit);
2066                 /* XXX should probably reset */
2067                 /* rcmd = ray_reset; */
2068         }
2069
2070         if (sc->sc_running & SCP_UPD_PROMISC) {
2071                 ray_cmd_done(sc, SCP_UPD_PROMISC);
2072                 sc->sc_promisc = SRAM_READ_1(sc, RAY_HOST_TO_ECF_BASE);
2073                 RAY_DPRINTFN(20, ("ray%d: new promisc value %d\n", sc->unit,
2074                     sc->sc_promisc));
2075         } else if (sc->sc_updreq) {
2076                 ray_cmd_done(sc, SCP_UPD_UPDATEPARAMS);
2077                 /* get the update parameter */
2078                 sc->sc_updreq->r_failcause =
2079                     SRAM_READ_FIELD_1(sc, ccs, ray_cmd_update, c_failcause);
2080                 sc->sc_updreq = 0;
2081                 wakeup(ray_update_params);
2082                 ray_start_join_net(sc);
2083         }
2084 }
2085
2086 /*
2087  *  check too see if we have any pending commands.
2088  */
2089 static void
2090 ray_check_scheduled(void *arg)
2091 {
2092         struct ray_softc *sc;
2093         int s, i, mask;
2094
2095         s = splnet();
2096         sc = arg;
2097
2098         RAY_DPRINTFN(5, ("ray%d: ray_check_scheduled\n", sc->unit));
2099         RAY_MAP_CM(sc);
2100
2101         RAY_DPRINTFN(20, (
2102             "ray%d: ray_check_scheduled schd 0x%x running 0x%x ready %d\n",
2103             sc->unit, sc->sc_scheduled, sc->sc_running, RAY_ECF_READY(sc)));
2104
2105         if (sc->sc_timoneed) {
2106                 untimeout(ray_check_scheduled, sc, sc->ccs_timerh);
2107                 sc->sc_timoneed = 0;
2108         }
2109
2110         /* if update subcmd is running -- clear it in scheduled */
2111         if (sc->sc_running & SCP_UPDATESUBCMD)
2112                 sc->sc_scheduled &= ~SCP_UPDATESUBCMD;
2113
2114         mask = SCP_FIRST;
2115         for (i = 0; i < ray_ncmdtab; mask <<= 1, i++) {
2116                 if ((sc->sc_scheduled & ~SCP_UPD_MASK) == 0)
2117                         break;
2118                 if (!RAY_ECF_READY(sc))
2119                         break;
2120                 if (sc->sc_scheduled & mask)
2121                         (*ray_cmdtab[i])(sc);
2122         }
2123
2124         RAY_DPRINTFN(20, (
2125             "ray%d: ray_check_scheduled sched 0x%x running 0x%x ready %d\n",
2126             sc->unit, sc->sc_scheduled, sc->sc_running, RAY_ECF_READY(sc)));
2127
2128         if (sc->sc_scheduled & ~SCP_UPD_MASK)
2129                 ray_set_pending(sc, sc->sc_scheduled);
2130
2131         splx(s);
2132 }
2133
2134 /*
2135  * check for unreported returns
2136  *
2137  * this routine is coded to only expect one outstanding request for the
2138  * timed out requests at a time, but thats all that can be outstanding
2139  * per hardware limitations
2140  */
2141 static void
2142 ray_check_ccs(void *arg)
2143 {
2144         struct ray_softc *sc;
2145         u_int i, cmd, stat;
2146         size_t ccs;
2147         int s;
2148
2149         s = splnet();
2150         sc = arg;
2151
2152         RAY_DPRINTFN(5, ("ray%d: ray_check_ccs\n", sc->unit));
2153         RAY_MAP_CM(sc);
2154
2155         ccs = 0;
2156         stat = RAY_CCS_STATUS_FAIL;
2157         sc->sc_timocheck = 0;
2158         for (i = RAY_CCS_CMD_FIRST; i <= RAY_CCS_CMD_LAST; i++) {
2159                 if (!sc->sc_ccsinuse[i])
2160                         continue;
2161                 ccs = RAY_CCS_ADDRESS(i);
2162                 cmd = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd);
2163                 switch (cmd) {
2164                 case RAY_CMD_START_PARAMS:
2165                 case RAY_CMD_UPDATE_MCAST:
2166                 case RAY_CMD_UPDATE_PARAMS:
2167                         stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status);
2168                         RAY_DPRINTFN(20, ("ray%d: check ccs idx %d ccs 0x%x "
2169                             "cmd 0x%x stat %d\n", sc->unit, i,
2170                             ccs, cmd, stat));
2171                         goto breakout;
2172                 }
2173         }
2174 breakout:
2175         /* see if we got one of the commands we are looking for */
2176         if (i > RAY_CCS_CMD_LAST)
2177                 ; /* nothign */
2178         else if (stat == RAY_CCS_STATUS_FREE) {
2179                 stat = RAY_CCS_STATUS_COMPLETE;
2180                 ray_ccs_done(sc, ccs);
2181         } else if (stat != RAY_CCS_STATUS_BUSY) {
2182                 if (sc->sc_ccsinuse[i] == 1) {
2183                         /* give a chance for the interrupt to occur */
2184                         sc->sc_ccsinuse[i] = 2;
2185                         if (!sc->sc_timocheck) {
2186                                 sc->ccs_timerh = timeout(ray_check_ccs, sc, 1);
2187                                 sc->sc_timocheck = 1;
2188                         }
2189                 } else
2190                         ray_ccs_done(sc, ccs);
2191         } else {
2192                 sc->ccs_timerh = timeout(ray_check_ccs, sc, RAY_CCS_TIMEOUT);
2193                 sc->sc_timocheck = 1;
2194         }
2195         splx(s);
2196 }
2197
2198 /*
2199  * read the counters, the card implements the following protocol
2200  * to keep the values from being changed while read:  It checks
2201  * the `own' bit and if zero writes the current internal counter
2202  * value, it then sets the `own' bit to 1.  If the `own' bit was 1 it
2203  * incremenets its internal counter.  The user thus reads the counter
2204  * if the `own' bit is one and then sets the own bit to 0.
2205  */
2206 static void
2207 ray_update_error_counters(struct ray_softc *sc)
2208 {
2209         size_t csc;
2210
2211         RAY_DPRINTFN(5, ("ray%d: ray_update_error_counters\n", sc->unit));
2212         RAY_MAP_CM(sc);
2213
2214         /* try and update the error counters */
2215         csc = RAY_STATUS_BASE;
2216         if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_mrxo_own)) {
2217                 sc->sc_rxoverflow +=
2218                     SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_mrx_overflow);
2219                 SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_mrxo_own, 0);
2220         }
2221         if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_mrxc_own)) {
2222                 sc->sc_rxcksum +=
2223                     SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_mrx_overflow);
2224                 SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_mrxc_own, 0);
2225         }
2226         if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_rxhc_own)) {
2227                 sc->sc_rxhcksum +=
2228                     SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_rx_hcksum);
2229                 SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_rxhc_own, 0);
2230         }
2231         sc->sc_rxnoise = SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_rx_noise);
2232 }
2233
2234 /*
2235  * Process CCS command completion - called from ray_intr
2236  */
2237 static void
2238 ray_ccs_done(struct ray_softc *sc, size_t ccs)
2239 {
2240         u_int cmd, stat;
2241     
2242         RAY_DPRINTFN(5, ("ray%d: ray_ccs_done\n", sc->unit));
2243         RAY_MAP_CM(sc);
2244
2245         cmd = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd);
2246         stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status);
2247
2248         RAY_DPRINTFN(20, ("ray%d: ccs idx %d ccs 0x%x cmd 0x%x status %d\n",
2249             sc->unit, RAY_CCS_INDEX(ccs), ccs, cmd, stat));
2250
2251         switch (cmd) {
2252
2253         case RAY_CMD_START_PARAMS:
2254                 RAY_DPRINTFN(20, ("ray%d: ray_ccs_done got START_PARAMS\n",
2255                     sc->unit));
2256                 ray_download_done(sc);
2257                 break;
2258
2259         case RAY_CMD_UPDATE_PARAMS:
2260                 RAY_DPRINTFN(20, ("ray%d: ray_ccs_done got UPDATE_PARAMS\n",
2261                     sc->unit));
2262                 ray_update_params_done(sc, ccs, stat);
2263                 break;
2264
2265         case RAY_CMD_REPORT_PARAMS:
2266                 RAY_DPRINTFN(20, ("ray%d: ray_ccs_done got REPORT_PARAMS\n",
2267                     sc->unit));
2268                 /* get the reported parameters */
2269                 ray_cmd_done(sc, SCP_REPORTPARAMS);
2270                 if (!sc->sc_repreq)
2271                         break;
2272                 sc->sc_repreq->r_failcause =
2273                     SRAM_READ_FIELD_1(sc, ccs, ray_cmd_report, c_failcause);
2274                 sc->sc_repreq->r_len =
2275                     SRAM_READ_FIELD_1(sc, ccs, ray_cmd_report, c_len);
2276                 ray_read_region(sc, RAY_ECF_TO_HOST_BASE, sc->sc_repreq->r_data,
2277                     sc->sc_repreq->r_len);
2278                 sc->sc_repreq = 0;
2279                 wakeup(ray_report_params);
2280                 break;
2281
2282         case RAY_CMD_UPDATE_MCAST:
2283                 RAY_DPRINTFN(20, ("ray%d: ray_ccs_done got UPDATE_MCAST\n",
2284                     sc->unit));
2285                 ray_cmd_done(sc, SCP_UPD_MCAST);
2286                 if (stat == RAY_CCS_STATUS_FAIL)
2287                         ray_reset(sc);
2288                 break;
2289
2290         case RAY_CMD_START_NET:
2291         case RAY_CMD_JOIN_NET:
2292                 RAY_DPRINTFN(20, ("ray%d: ray_ccs_done got START|JOIN_NET\n",
2293                     sc->unit));
2294                 ray_start_join_done(sc, ccs, stat);
2295                 break;
2296
2297         case RAY_CMD_TX_REQ:
2298                 RAY_DPRINTFN(20, ("ray%d: ray_ccs_done got TX_REQ\n",
2299                     sc->unit));
2300                 ray_start_done(sc, ccs, stat);
2301                 goto done;
2302
2303         case RAY_CMD_START_ASSOC:
2304                 RAY_DPRINTFN(20, ("ray%d: ray_ccs_done got START_ASSOC\n",
2305                     sc->unit));
2306                 ray_cmd_done(sc, SCP_STARTASSOC);
2307                 if (stat == RAY_CCS_STATUS_FAIL)
2308                         ray_start_join_net(sc); /* XXX check */
2309                 else {
2310                         sc->sc_havenet = 1;
2311                 }
2312                 break;
2313
2314         case RAY_CMD_UPDATE_APM:
2315                 RAY_DPRINTFN(20, ("ray%d: ray_ccs_done got UPDATE_APM\n",
2316                     sc->unit));
2317                 XXX;
2318                 break;
2319
2320         case RAY_CMD_TEST_MEM:
2321                 printf("ray%d: ray_ccs_done got TEST_MEM - why?\n", sc->unit);
2322                 break;
2323
2324         case RAY_CMD_SHUTDOWN:
2325                 printf("ray%d: ray_ccs_done got SHUTDOWN - why?\n", sc->unit);
2326                 break;
2327
2328         case RAY_CMD_DUMP_MEM:
2329                 printf("ray%d: ray_ccs_done got DUMP_MEM - why?\n", sc->unit);
2330                 break;
2331
2332         case RAY_CMD_START_TIMER:
2333                 printf("ray%d: ray_ccs_done got START_TIMER - why?\n",
2334                     sc->unit);
2335                 break;
2336
2337         default:
2338                 printf("ray%d: ray_ccs_done unknown command 0x%x\n",
2339                     sc->unit, cmd);
2340                 break;
2341         }
2342
2343         ray_free_ccs(sc, ccs);
2344 done:
2345         /*
2346          * see if needed things can be done now that a command
2347          * has completed
2348          */
2349         ray_check_scheduled(sc);
2350 }
2351
2352 /*
2353  * Process ECF command request - called from ray_intr
2354  */
2355 static void
2356 ray_rcs_intr(struct ray_softc *sc, size_t rcs)
2357 {
2358         struct ifnet *ifp;
2359         u_int cmd, status;
2360     
2361         RAY_DPRINTFN(5, ("ray%d: ray_rcs_intr\n", sc->unit));
2362         RAY_MAP_CM(sc);
2363
2364         ifp = &sc->arpcom.ac_if;
2365
2366         cmd = SRAM_READ_FIELD_1(sc, rcs, ray_cmd, c_cmd);
2367         status = SRAM_READ_FIELD_1(sc, rcs, ray_cmd, c_status);
2368         RAY_DPRINTFN(20, ("ray%d: rcs idx %d rcs 0x%x cmd 0x%x status %d\n",
2369             sc->unit, RAY_CCS_INDEX(rcs), rcs, cmd, status));
2370
2371         switch (cmd) {
2372
2373         case RAY_ECMD_RX_DONE:
2374                 RAY_DPRINTFN(20, ("ray%d: ray_rcs_intr got RX_DONE\n",
2375                     sc->unit));
2376                 ray_rx(sc, rcs);
2377                 break;
2378
2379         case RAY_ECMD_REJOIN_DONE:
2380                 RAY_DPRINTFN(20, ("ray%d: ray_rcs_intr got REJOIN_DONE\n",
2381                     sc->unit));
2382                 sc->sc_havenet = 1; /* Should not be here but in function */
2383                 XXX;
2384                 break;
2385
2386         case RAY_ECMD_ROAM_START:
2387                 RAY_DPRINTFN(20, ("ray%d: ray_rcs_intr got ROAM_START\n",
2388                     sc->unit));
2389                 sc->sc_havenet = 0; /* Should not be here but in function */
2390                 XXX;
2391                 break;
2392
2393         case RAY_ECMD_JAPAN_CALL_SIGNAL:
2394                 printf("ray%d: ray_rcs_intr got JAPAN_CALL_SIGNAL - why?\n",
2395                     sc->unit);
2396                 break;
2397
2398         default:
2399                 printf("ray%d: ray_rcs_intr unknown command 0x%x\n",
2400                     sc->unit, cmd);
2401                 break;
2402         }
2403
2404         RAY_CCS_FREE(sc, rcs);
2405 }
2406
2407 /*
2408  * process an interrupt
2409  */
2410 static int
2411 ray_intr(struct pccard_devinfo *dev_p)
2412 {
2413         struct ray_softc *sc;
2414         struct ifnet *ifp;
2415         int i, count;
2416
2417         sc = &ray_softc[dev_p->isahd.id_unit];
2418
2419         RAY_DPRINTFN(5, ("ray%d: ray_intr\n", sc->unit));
2420         RAY_MAP_CM(sc);
2421
2422         ifp = &sc->arpcom.ac_if;
2423
2424         if (sc->gone) {
2425                 printf("ray%d: unloaded before interrupt!\n", sc->unit);
2426                 return (0);
2427         }
2428
2429         if ((++sc->sc_checkcounters % 32) == 0)
2430                 ray_update_error_counters(sc);
2431
2432         /*
2433          * Check that the interrupt was for us, if so get the rcs/ccs
2434          * and vector on the command contained within it.
2435          */
2436         if (!RAY_HCS_INTR(sc))
2437                 count = 0;
2438         else {
2439                 count = 1;
2440                 i = SRAM_READ_1(sc, RAY_SCB_RCSI);
2441                 if (i <= RAY_CCS_LAST)
2442                         ray_ccs_done(sc, RAY_CCS_ADDRESS(i));
2443                 else if (i <= RAY_RCS_LAST)
2444                         ray_rcs_intr(sc, RAY_CCS_ADDRESS(i));
2445                 else
2446                     printf("ray%d: ray_intr bad ccs index %d\n", sc->unit, i);
2447         }
2448
2449         if (count)
2450                 RAY_HCS_CLEAR_INTR(sc);
2451
2452         RAY_DPRINTFN(10, ("ray%d: interrupt %s handled\n",
2453             sc->unit, count?"was":"not"));
2454
2455         /* Send any packets lying around */
2456         if (!(ifp->if_flags & IFF_OACTIVE) && (ifp->if_snd.ifq_head != NULL))
2457                 ray_start(ifp);
2458
2459         return (count);
2460 }
2461
2462 /*
2463  * Generic CCS handling
2464  */
2465
2466 #if XXX_NETBSDTX
2467 /*
2468  * free the chain of descriptors -- used for freeing allocated tx chains
2469  */
2470 static void
2471 ray_free_ccs_chain(struct ray_softc *sc, u_int ni)
2472 {
2473         u_int i;
2474
2475         RAY_DPRINTFN(5, ("ray%d: ray_free_ccs_chain\n", sc->unit));
2476         RAY_MAP_CM(sc);
2477
2478         while ((i = ni) != RAY_CCS_LINK_NULL) {
2479                 ni = SRAM_READ_FIELD_1(sc, RAY_CCS_ADDRESS(i), ray_cmd, c_link);
2480                 RAY_CCS_FREE(sc, RAY_CCS_ADDRESS(i));
2481         }
2482 }
2483 #endif XXX_NETBSDTX
2484
2485 /*
2486  * free up a cmd and return the old status.
2487  * this routine is only used for commands.
2488  */
2489 static u_int8_t
2490 ray_free_ccs(struct ray_softc *sc, size_t ccs)
2491 {
2492         u_int8_t stat;
2493
2494         RAY_DPRINTFN(5, ("ray%d: ray_free_ccs\n", sc->unit));
2495         RAY_MAP_CM(sc);
2496
2497         stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status);
2498         RAY_CCS_FREE(sc, ccs);
2499         if (ccs <= RAY_CCS_ADDRESS(RAY_CCS_LAST))
2500                 sc->sc_ccsinuse[RAY_CCS_INDEX(ccs)] = 0;
2501         RAY_DPRINTFN(20, ("ray%d: ray_free_ccs freed 0x%02x\n",
2502             sc->unit, RAY_CCS_INDEX(ccs)));
2503
2504         return (stat);
2505 }
2506
2507 /*
2508  * Obtain a free ccs buffer.
2509  *
2510  * returns 1 and in `ccsp' the bus offset of the free ccs 
2511  * or 0 if none are free
2512  *
2513  * If `track' is not zero, handles tracking this command
2514  * possibly indicating a callback is needed and setting a timeout
2515  * also if ECF isn't ready we terminate earlier to avoid overhead.
2516  *
2517  * this routine is only used for commands
2518  */
2519 static int
2520 ray_alloc_ccs(struct ray_softc *sc, size_t *ccsp, u_int cmd, u_int track)
2521 {
2522         size_t ccs;
2523         u_int i;
2524
2525         RAY_DPRINTFN(5, ("ray%d: ray_alloc_ccs\n", sc->unit));
2526         RAY_MAP_CM(sc);
2527
2528         /* for tracked commands, if not ready just set pending */
2529         if (track && !RAY_ECF_READY(sc)) {
2530                 ray_cmd_schedule(sc, track);
2531                 return (0);
2532         }
2533
2534         for (i = RAY_CCS_CMD_FIRST; i <= RAY_CCS_CMD_LAST; i++) {
2535                 /* probe here to make the card go */
2536                 (void)SRAM_READ_FIELD_1(sc, RAY_CCS_ADDRESS(i), ray_cmd,
2537                     c_status);
2538                 if (!sc->sc_ccsinuse[i])
2539                         break;
2540         }
2541         if (i > RAY_CCS_CMD_LAST) {
2542             if (track)
2543                     ray_cmd_schedule(sc, track);
2544             return (0);
2545         }
2546         sc->sc_ccsinuse[i] = 1;
2547         ccs = RAY_CCS_ADDRESS(i);
2548         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_BUSY);
2549         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_cmd, cmd);
2550         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_link, RAY_CCS_LINK_NULL);
2551
2552         *ccsp = ccs;
2553         return (1);
2554 }
2555
2556 /*
2557  * this function sets the pending bit for the command given in 'need'
2558  * and schedules a timeout if none is scheduled already.  Any command
2559  * that uses the `host to ecf' region must be serialized.
2560  */
2561 static void
2562 ray_set_pending(struct ray_softc *sc, u_int cmdf)
2563 {
2564         RAY_DPRINTFN(5, ("ray%d: ray_set_pending\n", sc->unit));
2565         RAY_MAP_CM(sc);
2566         RAY_DPRINTFN(20, ("ray%d: ray_set_pending 0x%0x\n", sc->unit, cmdf));
2567
2568         sc->sc_scheduled |= cmdf;
2569         if (!sc->sc_timoneed) {
2570                 RAY_DPRINTFN(20, ("ray%d: ray_set_pending new timo\n",
2571                     sc->unit));
2572                 sc->ccs_timerh = timeout(ray_check_scheduled, sc,
2573                     RAY_CHECK_SCHED_TIMEOUT);
2574                 sc->sc_timoneed = 1;
2575         }
2576 }
2577
2578 /*
2579  * schedule the `cmdf' for completion later
2580  */
2581 static void
2582 ray_cmd_schedule(struct ray_softc *sc, int cmdf)
2583 {
2584         int track;
2585
2586         RAY_DPRINTFN(5, ("ray%d: ray_cmd_schedule\n", sc->unit));
2587         RAY_MAP_CM(sc);
2588         RAY_DPRINTFN(20, ("ray%d: ray_cmd_schedule 0x%x\n", sc->unit, cmdf));
2589
2590         track = cmdf;
2591         if ((cmdf & SCP_UPD_MASK) == 0)
2592                 ray_set_pending(sc, track);
2593         else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) {
2594                 /* don't do timeout mechaniscm if subcmd already going */
2595                 sc->sc_scheduled |= cmdf;
2596         } else
2597                 ray_set_pending(sc, cmdf | SCP_UPDATESUBCMD);
2598 }
2599
2600 /*
2601  * check to see if `cmdf' has been scheduled
2602  */
2603 static int
2604 ray_cmd_is_scheduled(struct ray_softc *sc, int cmdf)
2605 {
2606         RAY_DPRINTFN(5, ("ray%d: ray_cmd_is_scheduled\n", sc->unit));
2607         RAY_MAP_CM(sc);
2608         RAY_DPRINTFN(20, ("ray%d: ray_cmd_is_scheduled 0x%x\n",
2609             sc->unit, cmdf));
2610
2611         return ((sc->sc_scheduled & cmdf) ? 1 : 0);
2612 }
2613
2614 /*
2615  * cancel a scheduled command (not a running one though!)
2616  */
2617 static void
2618 ray_cmd_cancel(struct ray_softc *sc, int cmdf)
2619 {
2620         RAY_DPRINTFN(5, ("ray%d: ray_cmd_cancel\n", sc->unit));
2621         RAY_MAP_CM(sc);
2622         RAY_DPRINTFN(20, ("ray%d: ray_cmd_cancel 0x%x\n", sc->unit, cmdf));
2623
2624         sc->sc_scheduled &= ~cmdf;
2625         if ((cmdf & SCP_UPD_MASK) && (sc->sc_scheduled & SCP_UPD_MASK) == 0)
2626                 sc->sc_scheduled &= ~SCP_UPDATESUBCMD;
2627
2628         /* if nothing else needed cancel the timer */
2629         if (sc->sc_scheduled == 0 && sc->sc_timoneed) {
2630                 untimeout(ray_check_scheduled, sc, sc->ccs_timerh);
2631                 sc->sc_timoneed = 0;
2632         }
2633 }
2634
2635 /*
2636  * called to indicate the 'cmdf' has been issued
2637  */
2638 static void
2639 ray_cmd_ran(struct ray_softc *sc, int cmdf)
2640 {
2641         RAY_DPRINTFN(5, ("ray%d: ray_cmd_ran\n", sc->unit));
2642         RAY_MAP_CM(sc);
2643         RAY_DPRINTFN(20, ("ray%d: ray_cmd_ran 0x%x\n", sc->unit, cmdf));
2644
2645         if (cmdf & SCP_UPD_MASK)
2646                 sc->sc_running |= cmdf | SCP_UPDATESUBCMD;
2647         else
2648                 sc->sc_running |= cmdf;
2649
2650         if ((cmdf & SCP_TIMOCHECK_CMD_MASK) && !sc->sc_timocheck) {
2651                 sc->ccs_timerh = timeout(ray_check_ccs, sc, RAY_CCS_TIMEOUT);
2652                 sc->sc_timocheck = 1;
2653         }
2654 }
2655
2656 /*
2657  * check to see if `cmdf' has been issued
2658  */
2659 static int
2660 ray_cmd_is_running(struct ray_softc *sc, int cmdf)
2661 {
2662         RAY_DPRINTFN(5, ("ray%d: ray_cmd_is_running\n", sc->unit));
2663         RAY_MAP_CM(sc);
2664         RAY_DPRINTFN(20, ("ray%d: ray_cmd_is_running 0x%x\n", sc->unit, cmdf));
2665
2666         return ((sc->sc_running & cmdf) ? 1 : 0);
2667 }
2668
2669 /*
2670  * the given `cmdf' that was issued has completed
2671  */
2672 static void
2673 ray_cmd_done(struct ray_softc *sc, int cmdf)
2674 {
2675         RAY_DPRINTFN(5, ("ray%d: ray_cmd_done\n", sc->unit));
2676         RAY_MAP_CM(sc);
2677         RAY_DPRINTFN(20, ("ray%d: ray_cmd_done 0x%x\n", sc->unit, cmdf));
2678
2679         sc->sc_running &= ~cmdf;
2680         if (cmdf & SCP_UPD_MASK) {
2681                 sc->sc_running &= ~SCP_UPDATESUBCMD;
2682                 if (sc->sc_scheduled & SCP_UPD_MASK)
2683                         ray_cmd_schedule(sc, sc->sc_scheduled & SCP_UPD_MASK);
2684         }
2685         if ((sc->sc_running & SCP_TIMOCHECK_CMD_MASK) == 0 && sc->sc_timocheck){
2686                 untimeout(ray_check_ccs, sc, sc->ccs_timerh);
2687                 sc->sc_timocheck = 0;
2688         }
2689 }
2690
2691 /*
2692  * issue the command
2693  * only used for commands not tx
2694  */
2695 static int
2696 ray_issue_cmd(struct ray_softc *sc, size_t ccs, u_int track)
2697 {
2698         u_int i;
2699
2700         RAY_DPRINTFN(5, ("ray%d: ray_cmd_issue\n", sc->unit));
2701         RAY_MAP_CM(sc);
2702
2703         /*
2704          * XXX other drivers did this, but I think 
2705          * what we really want to do is just make sure we don't
2706          * get here or that spinning is ok
2707          */
2708         i = 0;
2709         while (!RAY_ECF_READY(sc))
2710                 if (++i > 50) {
2711                         printf("\n");
2712                         (void)ray_free_ccs(sc, ccs);
2713                         if (track)
2714                                 ray_cmd_schedule(sc, track);
2715                         return (0);
2716                 } else if (i == 1)
2717                         printf("ray%d: ray_issue_cmd spinning", sc->unit);
2718                 else
2719                         printf(".");
2720
2721         SRAM_WRITE_1(sc, RAY_SCB_CCSI, RAY_CCS_INDEX(ccs));
2722         RAY_ECF_START_CMD(sc);
2723         ray_cmd_ran(sc, track);
2724
2725         return (1);
2726 }
2727
2728 /*
2729  * send a simple command if we can
2730  */
2731 static int
2732 ray_simple_cmd(struct ray_softc *sc, u_int cmd, u_int track)
2733 {
2734         size_t ccs;
2735
2736         RAY_DPRINTFN(5, ("ray%d: ray_simple_cmd\n", sc->unit));
2737         RAY_MAP_CM(sc);
2738
2739         return (ray_alloc_ccs(sc, &ccs, cmd, track) &&
2740             ray_issue_cmd(sc, ccs, track));
2741 }
2742
2743 /*
2744  * Functions based on CCS commands
2745  */
2746
2747 /*
2748  * run a update subcommand
2749  */
2750 static void
2751 ray_update_subcmd(struct ray_softc *sc)
2752 {
2753         struct ifnet *ifp;
2754         int submask, i;
2755
2756         RAY_DPRINTFN(5, ("ray%d: ray_update_subcmd\n", sc->unit));
2757         RAY_MAP_CM(sc);
2758
2759         ray_cmd_cancel(sc, SCP_UPDATESUBCMD);
2760
2761         ifp = &sc->arpcom.ac_if;
2762         if ((ifp->if_flags & IFF_RUNNING) == 0)
2763                 return;
2764         submask = SCP_UPD_FIRST;
2765         for (i = 0; i < ray_nsubcmdtab; submask <<= 1, i++) {
2766                 if ((sc->sc_scheduled & SCP_UPD_MASK) == 0)
2767                         break;
2768                 /* when done the next command will be scheduled */
2769                 if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD))
2770                         break;
2771                 if (!RAY_ECF_READY(sc))
2772                         break;
2773                 /*
2774                  * give priority to LSB -- e.g., if previous loop reschuled
2775                  * doing this command after calling the function won't catch
2776                  * if a later command sets an earlier bit
2777                  */
2778                 if (sc->sc_scheduled & ((submask - 1) & SCP_UPD_MASK))
2779                         break;
2780                 if (sc->sc_scheduled & submask)
2781                         (*ray_subcmdtab[i])(sc);
2782         }
2783 }
2784
2785 /*
2786  * report a parameter
2787  */
2788 static void
2789 ray_report_params(struct ray_softc *sc)
2790 {
2791         struct ifnet *ifp;
2792         size_t ccs;
2793
2794         RAY_DPRINTFN(5, ("ray%d: ray_report_params\n", sc->unit));
2795         RAY_MAP_CM(sc);
2796
2797         ray_cmd_cancel(sc, SCP_REPORTPARAMS);
2798
2799         ifp = &sc->arpcom.ac_if;
2800
2801         if (!sc->sc_repreq)
2802                 return;
2803
2804         /* do the issue check before equality check */
2805         if ((ifp->if_flags & IFF_RUNNING) == 0)
2806                 return;
2807         else if (ray_cmd_is_running(sc, SCP_REPORTPARAMS)) {
2808                 ray_cmd_schedule(sc, SCP_REPORTPARAMS);
2809                 return;
2810         } else if (!ray_alloc_ccs(sc, &ccs, RAY_CMD_REPORT_PARAMS,
2811             SCP_REPORTPARAMS))
2812                 return;
2813
2814         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_report, c_paramid,
2815             sc->sc_repreq->r_paramid);
2816         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_report, c_nparam, 1);
2817         (void)ray_issue_cmd(sc, ccs, SCP_REPORTPARAMS);
2818 }
2819
2820 /*
2821  * start an association
2822  */
2823 static void
2824 ray_start_assoc(struct ray_softc *sc)
2825 {
2826         struct ifnet *ifp;
2827
2828         RAY_DPRINTFN(5, ("ray%d: ray_start_assoc\n", sc->unit));
2829         RAY_MAP_CM(sc);
2830
2831         ifp = &sc->arpcom.ac_if;
2832
2833         ray_cmd_cancel(sc, SCP_STARTASSOC);
2834         if ((ifp->if_flags & IFF_RUNNING) == 0)
2835                 return;
2836         else if (ray_cmd_is_running(sc, SCP_STARTASSOC))
2837                 return;
2838         (void)ray_simple_cmd(sc, RAY_CMD_START_ASSOC, SCP_STARTASSOC);
2839 }
2840
2841 /******************************************************************************
2842  * XXX NOT KNF FROM HERE DOWN                                                 *
2843  ******************************************************************************/
2844 /*
2845  * Subcommand functions that use the SCP_UPDATESUBCMD command
2846  * (and are serialized with respect to other update sub commands
2847  */
2848
2849 /*
2850  * Download start up structures to card.
2851  *
2852  * Part of ray_init, download, startjoin control flow.
2853  */
2854 static void
2855 ray_download_params (sc)
2856     struct ray_softc    *sc;
2857 {
2858     struct ray_mib_4    ray_mib_4_default;
2859     struct ray_mib_5    ray_mib_5_default;
2860
2861     RAY_DPRINTFN(5, ("ray%d: Downloading startup parameters\n", sc->unit));
2862     RAY_MAP_CM(sc);
2863
2864     ray_cmd_cancel(sc, SCP_UPD_STARTUP);
2865
2866 #define MIB4(m)         ray_mib_4_default.##m
2867 #define MIB5(m)         ray_mib_5_default.##m
2868 #define PUT2(p, v)      \
2869     do { (p)[0] = ((v >> 8) & 0xff); (p)[1] = (v & 0xff); } while(0)
2870
2871      /*
2872       * Firmware version 4 defaults - see if_raymib.h for details
2873       */
2874      MIB4(mib_net_type)                 = sc->sc_d.np_net_type;
2875      MIB4(mib_ap_status)                = sc->sc_d.np_ap_status;
2876      bcopy(sc->sc_d.np_ssid, MIB4(mib_ssid), IEEE80211_NWID_LEN);
2877      MIB4(mib_scan_mode)                = RAY_MIB_SCAN_MODE_DEFAULT;
2878      MIB4(mib_apm_mode)                 = RAY_MIB_APM_MODE_DEFAULT;
2879      bcopy(sc->sc_station_addr, MIB4(mib_mac_addr), ETHER_ADDR_LEN);
2880 PUT2(MIB4(mib_frag_thresh),               RAY_MIB_FRAG_THRESH_DEFAULT);
2881 PUT2(MIB4(mib_dwell_time),                RAY_MIB_DWELL_TIME_V4);
2882 PUT2(MIB4(mib_beacon_period),             RAY_MIB_BEACON_PERIOD_V4);
2883      MIB4(mib_dtim_interval)            = RAY_MIB_DTIM_INTERVAL_DEFAULT;
2884      MIB4(mib_max_retry)                = RAY_MIB_MAX_RETRY_DEFAULT;
2885      MIB4(mib_ack_timo)                 = RAY_MIB_ACK_TIMO_DEFAULT;
2886      MIB4(mib_sifs)                     = RAY_MIB_SIFS_DEFAULT;
2887      MIB4(mib_difs)                     = RAY_MIB_DIFS_DEFAULT;
2888      MIB4(mib_pifs)                     = RAY_MIB_PIFS_V4;
2889 PUT2(MIB4(mib_rts_thresh),                RAY_MIB_RTS_THRESH_DEFAULT);
2890 PUT2(MIB4(mib_scan_dwell),                RAY_MIB_SCAN_DWELL_V4);
2891 PUT2(MIB4(mib_scan_max_dwell),            RAY_MIB_SCAN_MAX_DWELL_V4);
2892      MIB4(mib_assoc_timo)               = RAY_MIB_ASSOC_TIMO_DEFAULT;
2893      MIB4(mib_adhoc_scan_cycle)         = RAY_MIB_ADHOC_SCAN_CYCLE_DEFAULT;
2894      MIB4(mib_infra_scan_cycle)         = RAY_MIB_INFRA_SCAN_CYCLE_DEFAULT;
2895      MIB4(mib_infra_super_scan_cycle)   = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT;
2896      MIB4(mib_promisc)                  = RAY_MIB_PROMISC_DEFAULT;
2897 PUT2(MIB4(mib_uniq_word),                 RAY_MIB_UNIQ_WORD_DEFAULT);
2898      MIB4(mib_slot_time)                = RAY_MIB_SLOT_TIME_V4;
2899      MIB4(mib_roam_low_snr_thresh)      = RAY_MIB_ROAM_LOW_SNR_THRESH_DEFAULT;
2900      MIB4(mib_low_snr_count)            = RAY_MIB_LOW_SNR_COUNT_DEFAULT;
2901      MIB4(mib_infra_missed_beacon_count)= RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT;
2902      MIB4(mib_adhoc_missed_beacon_count)= RAY_MIB_ADHOC_MISSED_BEACON_COUNT_DEFAULT;
2903      MIB4(mib_country_code)             = RAY_MIB_COUNTRY_CODE_DEFAULT;
2904      MIB4(mib_hop_seq)                  = RAY_MIB_HOP_SEQ_DEFAULT;
2905      MIB4(mib_hop_seq_len)              = RAY_MIB_HOP_SEQ_LEN_V4;
2906      MIB4(mib_cw_max)                   = RAY_MIB_CW_MAX_V4;
2907      MIB4(mib_cw_min)                   = RAY_MIB_CW_MIN_V4;
2908      MIB4(mib_noise_filter_gain)        = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT;
2909      MIB4(mib_noise_limit_offset)       = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT;
2910      MIB4(mib_rssi_thresh_offset)       = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT;
2911      MIB4(mib_busy_thresh_offset)       = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT;
2912      MIB4(mib_sync_thresh)              = RAY_MIB_SYNC_THRESH_DEFAULT;
2913      MIB4(mib_test_mode)                = RAY_MIB_TEST_MODE_DEFAULT;
2914      MIB4(mib_test_min_chan)            = RAY_MIB_TEST_MIN_CHAN_DEFAULT;
2915      MIB4(mib_test_max_chan)            = RAY_MIB_TEST_MAX_CHAN_DEFAULT;
2916
2917      /*
2918       * Firmware version 5 defaults - see if_raymib.h for details
2919       */
2920      MIB5(mib_net_type)                 = sc->sc_d.np_net_type;
2921      MIB4(mib_ap_status)                = sc->sc_d.np_ap_status;
2922      bcopy(sc->sc_d.np_ssid, MIB5(mib_ssid), IEEE80211_NWID_LEN);
2923      MIB5(mib_scan_mode)                = RAY_MIB_SCAN_MODE_DEFAULT;
2924      MIB5(mib_apm_mode)                 = RAY_MIB_APM_MODE_DEFAULT;
2925      bcopy(sc->sc_station_addr, MIB5(mib_mac_addr), ETHER_ADDR_LEN);
2926 PUT2(MIB5(mib_frag_thresh),               RAY_MIB_FRAG_THRESH_DEFAULT);
2927 PUT2(MIB5(mib_dwell_time),                RAY_MIB_DWELL_TIME_V5);
2928 PUT2(MIB5(mib_beacon_period),             RAY_MIB_BEACON_PERIOD_V5);
2929      MIB5(mib_dtim_interval)            = RAY_MIB_DTIM_INTERVAL_DEFAULT;
2930      MIB5(mib_max_retry)                = RAY_MIB_MAX_RETRY_DEFAULT;
2931      MIB5(mib_ack_timo)                 = RAY_MIB_ACK_TIMO_DEFAULT;
2932      MIB5(mib_sifs)                     = RAY_MIB_SIFS_DEFAULT;
2933      MIB5(mib_difs)                     = RAY_MIB_DIFS_DEFAULT;
2934      MIB5(mib_pifs)                     = RAY_MIB_PIFS_V5;
2935 PUT2(MIB5(mib_rts_thresh),                RAY_MIB_RTS_THRESH_DEFAULT);
2936 PUT2(MIB5(mib_scan_dwell),                RAY_MIB_SCAN_DWELL_V5);
2937 PUT2(MIB5(mib_scan_max_dwell),            RAY_MIB_SCAN_MAX_DWELL_V5);
2938      MIB5(mib_assoc_timo)               = RAY_MIB_ASSOC_TIMO_DEFAULT;
2939      MIB5(mib_adhoc_scan_cycle)         = RAY_MIB_ADHOC_SCAN_CYCLE_DEFAULT;
2940      MIB5(mib_infra_scan_cycle)         = RAY_MIB_INFRA_SCAN_CYCLE_DEFAULT;
2941      MIB5(mib_infra_super_scan_cycle)   = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT;
2942      MIB5(mib_promisc)                  = RAY_MIB_PROMISC_DEFAULT;
2943 PUT2(MIB5(mib_uniq_word),                 RAY_MIB_UNIQ_WORD_DEFAULT);
2944      MIB5(mib_slot_time)                = RAY_MIB_SLOT_TIME_V5;
2945      MIB5(mib_roam_low_snr_thresh)      = RAY_MIB_ROAM_LOW_SNR_THRESH_DEFAULT;
2946      MIB5(mib_low_snr_count)            = RAY_MIB_LOW_SNR_COUNT_DEFAULT;
2947      MIB5(mib_infra_missed_beacon_count)= RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT;
2948      MIB5(mib_adhoc_missed_beacon_count)= RAY_MIB_ADHOC_MISSED_BEACON_COUNT_DEFAULT;
2949      MIB5(mib_country_code)             = RAY_MIB_COUNTRY_CODE_DEFAULT;
2950      MIB5(mib_hop_seq)                  = RAY_MIB_HOP_SEQ_DEFAULT;
2951      MIB5(mib_hop_seq_len)              = RAY_MIB_HOP_SEQ_LEN_V5;
2952 PUT2(MIB5(mib_cw_max),                    RAY_MIB_CW_MAX_V5);
2953 PUT2(MIB5(mib_cw_min),                    RAY_MIB_CW_MIN_V5);
2954      MIB5(mib_noise_filter_gain)        = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT;
2955      MIB5(mib_noise_limit_offset)       = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT;
2956      MIB5(mib_rssi_thresh_offset)       = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT;
2957      MIB5(mib_busy_thresh_offset)       = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT;
2958      MIB5(mib_sync_thresh)              = RAY_MIB_SYNC_THRESH_DEFAULT;
2959      MIB5(mib_test_mode)                = RAY_MIB_TEST_MODE_DEFAULT;
2960      MIB5(mib_test_min_chan)            = RAY_MIB_TEST_MIN_CHAN_DEFAULT;
2961      MIB5(mib_test_max_chan)            = RAY_MIB_TEST_MAX_CHAN_DEFAULT;
2962      MIB5(mib_allow_probe_resp)         = RAY_MIB_ALLOW_PROBE_RESP_DEFAULT;
2963      MIB5(mib_privacy_must_start)       = sc->sc_d.np_priv_start;
2964      MIB5(mib_privacy_can_join)         = sc->sc_d.np_priv_join;
2965      MIB5(mib_basic_rate_set[0])        = sc->sc_d.np_def_txrate;
2966
2967     if (!RAY_ECF_READY(sc)) {
2968         printf("ray%d: ray_download_params something is already happening\n",
2969                 sc->unit);
2970         ray_reset(sc);
2971     }
2972
2973     if (sc->sc_version == RAY_ECFS_BUILD_4)
2974         ray_write_region(sc, RAY_HOST_TO_ECF_BASE,
2975                          &ray_mib_4_default, sizeof(ray_mib_4_default));
2976     else
2977         ray_write_region(sc, RAY_HOST_TO_ECF_BASE,
2978                          &ray_mib_5_default, sizeof(ray_mib_5_default));
2979
2980     if (!ray_simple_cmd(sc, RAY_CMD_START_PARAMS, SCP_UPD_STARTUP))
2981         printf("ray%d: ray_download_params can't issue command\n", sc->unit);
2982
2983     RAY_DPRINTFN(15, ("ray%d: Download now awaiting completion\n", sc->unit));
2984
2985     return;
2986 }
2987
2988 /*
2989  * Download completion routine.
2990  *
2991  * Part of ray_init, download, start_join control flow.
2992  *
2993  * As START_PARAMS is an update command ray_check_ccs has checked the
2994  * ccs status and re-scheduled timeouts if needed.
2995  */
2996 static void
2997 ray_download_done (sc)
2998     struct ray_softc    *sc;
2999 {
3000
3001     RAY_DPRINTFN(5, ("ray%d: ray_download_done\n", sc->unit));
3002     RAY_MAP_CM(sc);
3003
3004     ray_cmd_done(sc, SCP_UPD_STARTUP);
3005
3006     /* 
3007      * Fake the current network parameter settings so start_join_net
3008      * will not bother updating them to the card (we would need to
3009      * zero these anyway, so we might as well copy).
3010      */
3011     sc->sc_c.np_net_type = sc->sc_d.np_net_type;
3012     bcopy(sc->sc_d.np_ssid, sc->sc_c.np_ssid, IEEE80211_NWID_LEN);
3013         
3014     ray_start_join_net(sc);
3015 }
3016
3017 /*
3018  * start or join a network
3019  */
3020 static void
3021 ray_start_join_net(struct ray_softc *sc)
3022 {
3023         struct ray_net_params np;
3024         struct ifnet *ifp;
3025         size_t ccs;
3026         int cmd, update;
3027
3028
3029         RAY_DPRINTFN(5, ("ray%d: ray_start_join_net\n", sc->unit));
3030         RAY_MAP_CM(sc);
3031
3032         ifp = &sc->arpcom.ac_if;
3033
3034         ray_cmd_cancel(sc, SCP_UPD_STARTJOIN);
3035         if ((ifp->if_flags & IFF_RUNNING) == 0)
3036                 return;
3037
3038         /* XXX check we may not want to re-issue */
3039         if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) {
3040                 ray_cmd_schedule(sc, SCP_UPD_STARTJOIN);
3041                 return;
3042         }
3043
3044         if (sc->sc_d.np_net_type == RAY_MIB_NET_TYPE_ADHOC)
3045                 cmd = RAY_CMD_START_NET;
3046         else
3047                 cmd = RAY_CMD_JOIN_NET;
3048
3049         if (!ray_alloc_ccs(sc, &ccs, cmd, SCP_UPD_STARTJOIN)) {
3050                 printf("ray%d: ray_start_join_net can't get a CCS\n", sc->unit);
3051                 ray_reset(sc);
3052         }
3053
3054         update = 0;
3055         if (bcmp(sc->sc_c.np_ssid, sc->sc_d.np_ssid, IEEE80211_NWID_LEN))
3056                 update++;
3057         if (sc->sc_c.np_net_type != sc->sc_d.np_net_type)
3058                 update++;
3059
3060         if (update) {
3061                 sc->sc_havenet = 0;
3062
3063                 bzero(&np, sizeof(np));
3064                 np.p_net_type = sc->sc_d.np_net_type;
3065                 bcopy(sc->sc_d.np_ssid, np.p_ssid,  IEEE80211_NWID_LEN);
3066                 np.p_privacy_must_start = sc->sc_d.np_priv_start;
3067                 np.p_privacy_can_join = sc->sc_d.np_priv_join;
3068
3069                 ray_write_region(sc, RAY_HOST_TO_ECF_BASE, &np, sizeof(np));
3070                 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_upd_param, 1);
3071         } else
3072                 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_upd_param, 0);
3073
3074         RAY_DPRINTFN(15, ("ray%d: ray_start_join_net %s updating nw params\n",
3075             sc->unit, update?"is":"not"));
3076
3077         if (!ray_issue_cmd(sc, ccs, SCP_UPD_STARTJOIN)) {
3078             printf("ray%d: ray_start_join_net can't issue cmd\n", sc->unit);
3079             ray_reset(sc);
3080         }
3081
3082 #if RAY_NEED_STARTJOIN_TIMO
3083         sc->sj_timerh = timeout(ray_start_join_timo, sc, RAY_SJ_TIMEOUT);
3084 #endif /* RAY_NEED_STARTJOIN_TIMO */
3085 }
3086
3087 #if RAY_NEED_STARTJOIN_TIMO
3088 /*
3089  * Back stop catcher for start_join command. The NetBSD driver
3090  * suggests that they need it to catch a bug in the firmware or the
3091  * parameters they use - they are not sure. I'll just panic as I seem
3092  * to get interrupts back fine and I have version 4 firmware.
3093  */
3094 static void
3095 ray_start_join_timo (xsc)
3096     void                *xsc;
3097 {
3098     struct ray_softc    *sc = xsc;
3099
3100     RAY_DPRINTFN(5, ("ray%d: ray_start_join_timo\n", sc->unit));
3101     RAY_MAP_CM(sc);
3102
3103     panic("ray%d: ray-start_join_timo occured\n", sc->unit);
3104
3105     return;
3106 }
3107 #endif /* RAY_NEED_STARTJOIN_TIMO */
3108
3109 /*
3110  * Complete start or join command.
3111  *
3112  * Part of ray_init, download, start_join control flow.
3113  */
3114 static void
3115 ray_start_join_done (sc, ccs, status)
3116     struct ray_softc    *sc;
3117     size_t              ccs;
3118     u_int8_t            status;
3119 {
3120     struct ifnet        *ifp;
3121     u_int8_t            o_net_type;
3122
3123     RAY_DPRINTFN(5, ("ray%d: ray_start_join_done\n", sc->unit));
3124     RAY_MAP_CM(sc);
3125
3126     ifp = &sc->arpcom.ac_if;
3127
3128 #if RAY_NEED_STARTJOIN_TIMO
3129     untimeout(ray_start_join_timo, sc, sc->sj_timerh);
3130 #endif /* RAY_NEED_STARTJOIN_TIMO */
3131
3132     ray_cmd_done(sc, SCP_UPD_STARTJOIN);
3133
3134     /*
3135      * XXX This switch and the following test are badly done. I
3136      * XXX need to take remedial action in each case branch and
3137      * XXX return from there. Then remove the test.
3138      * XXX FAIL comment 
3139      * XXX    if we fired the start command we successfully set the card up
3140      * XXX    so just restart ray_start_join sequence and dont reset the card
3141      * XXX    may need to split download_done for this
3142      * XXX FREE
3143      * XXX    not sure
3144      * XXX BUSY
3145      * XXX    maybe timeout but why would we get an interrupt when
3146      * XXX    the card is not finished? 
3147      */
3148     switch (status) {
3149
3150         case RAY_CCS_STATUS_FREE:
3151         case RAY_CCS_STATUS_BUSY:
3152             printf("ray%d: ray_start_join_done status is FREE/BUSY - why?\n",
3153                         sc->unit);
3154             break;
3155
3156         case RAY_CCS_STATUS_COMPLETE:
3157             break;
3158
3159         case RAY_CCS_STATUS_FAIL:
3160             printf("ray%d: ray_start_join_done status is FAIL - why?\n",
3161                         sc->unit);
3162             sc->sc_havenet = 0;
3163             break;
3164
3165         default:
3166             printf("ray%d: ray_start_join_done unknown status 0x%x\n",
3167                         sc->unit, status);
3168             break;
3169     }
3170     if (status != RAY_CCS_STATUS_COMPLETE)
3171         return;
3172
3173     /*
3174      * If the command completed correctly, get a few network parameters
3175      * from the ccs and active the network.
3176      */
3177     ray_read_region(sc, ccs, &sc->sc_c.p_1, sizeof(struct ray_cmd_net));
3178
3179     /* adjust values for buggy build 4 */
3180     if (sc->sc_c.np_def_txrate == 0x55)
3181             sc->sc_c.np_def_txrate = sc->sc_d.np_def_txrate;
3182     if (sc->sc_c.np_encrypt == 0x55)
3183             sc->sc_c.np_encrypt = sc->sc_d.np_encrypt;
3184
3185     /* card is telling us to update the network parameters */
3186     if (sc->sc_c.np_upd_param) {
3187         RAY_DPRINTFN(1, ("ray%d: sj_done card updating parameters - why?\n",
3188                 sc->unit));
3189         o_net_type = sc->sc_c.np_net_type; /* XXX this may be wrong? */
3190         ray_read_region(sc, RAY_HOST_TO_ECF_BASE,
3191                 &sc->sc_c.p_2, sizeof(struct ray_net_params));
3192         if (sc->sc_c.np_net_type != o_net_type) {
3193             printf("ray%d: sj_done card changing network type - why?\n",
3194                 sc->unit);
3195 #if XXX
3196             restart ray_start_join sequence
3197             may need to split download_done for this
3198 #endif
3199         }
3200     }
3201     RAY_DNET_DUMP(sc, " after start/join network completed.");
3202
3203     /*
3204      * Hurrah! The network is now active.
3205      *
3206      * Clearing IFF_OACTIVE will ensure that the system will queue packets.
3207      * Just before we return from the interrupt context we check to
3208      * see if packets have been queued.
3209      */
3210     ray_cmd_schedule(sc, SCP_UPD_MCAST|SCP_UPD_PROMISC);
3211
3212     if (SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd) == RAY_CMD_JOIN_NET)
3213         ray_start_assoc(sc);
3214     else {
3215         sc->sc_havenet = 1;
3216         ifp->if_flags &= ~IFF_OACTIVE;
3217     }
3218
3219     return;
3220 }
3221
3222 /******************************************************************************
3223  * XXX NOT KNF FROM HERE UP
3224  ******************************************************************************/
3225
3226 /*
3227  * set the card in/out of promiscuous mode
3228  */
3229 static void
3230 ray_update_promisc(struct ray_softc *sc)
3231 {
3232         struct ifnet *ifp;
3233         size_t ccs;
3234         int promisc;
3235
3236         RAY_DPRINTFN(5, ("ray%d: ray_update_promisc\n", sc->unit));
3237         RAY_MAP_CM(sc);
3238
3239         ifp = &sc->arpcom.ac_if;
3240         ray_cmd_cancel(sc, SCP_UPD_PROMISC);
3241
3242         /* do the issue check before equality check */
3243         promisc = !!(ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI));
3244         if ((ifp->if_flags & IFF_RUNNING) == 0)
3245                 return;
3246         else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) {
3247                 ray_cmd_schedule(sc, SCP_UPD_PROMISC);
3248                 return;
3249         } else if (promisc == sc->sc_promisc)
3250                 return;
3251         else if (!ray_alloc_ccs(sc,&ccs,RAY_CMD_UPDATE_PARAMS, SCP_UPD_PROMISC))
3252                 return;
3253         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_paramid, RAY_MIB_PROMISC);
3254         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_nparam, 1);
3255         SRAM_WRITE_1(sc, RAY_HOST_TO_ECF_BASE, promisc);
3256         (void)ray_issue_cmd(sc, ccs, SCP_UPD_PROMISC);
3257 }
3258
3259 /*
3260  * update the parameter based on what the user passed in
3261  */
3262 static void
3263 ray_update_params(struct ray_softc *sc)
3264 {
3265         struct ifnet *ifp;
3266         size_t ccs;
3267
3268         RAY_DPRINTFN(5, ("ray%d: ray_update_params\n", sc->unit));
3269         RAY_MAP_CM(sc);
3270
3271         ifp = &sc->arpcom.ac_if;
3272
3273         ray_cmd_cancel(sc, SCP_UPD_UPDATEPARAMS);
3274         if (!sc->sc_updreq) {
3275                 /* XXX do we need to wakeup here? */
3276                 return;
3277         }
3278
3279         /* do the issue check before equality check */
3280         if ((ifp->if_flags & IFF_RUNNING) == 0)
3281                 return;
3282         else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) {
3283                 ray_cmd_schedule(sc, SCP_UPD_UPDATEPARAMS);
3284                 return;
3285         } else if (!ray_alloc_ccs(sc, &ccs, RAY_CMD_UPDATE_PARAMS,
3286             SCP_UPD_UPDATEPARAMS))
3287                 return;
3288
3289         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_paramid,
3290             sc->sc_updreq->r_paramid);
3291         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_nparam, 1);
3292         ray_write_region(sc, RAY_HOST_TO_ECF_BASE, sc->sc_updreq->r_data,
3293             sc->sc_updreq->r_len);
3294
3295         (void)ray_issue_cmd(sc, ccs, SCP_UPD_UPDATEPARAMS);
3296 }
3297
3298 /*
3299  * set the multicast filter list
3300  */
3301 static void
3302 ray_update_mcast(struct ray_softc *sc)
3303 {
3304         struct ifnet *ifp;
3305         struct ifmultiaddr *ifma;
3306         size_t ccs, bufp;
3307         int count;
3308
3309         RAY_DPRINTFN(5, ("ray%d: ray_update_mcast\n", sc->unit));
3310         RAY_MAP_CM(sc);
3311
3312         ifp = &sc->arpcom.ac_if;
3313         
3314         ray_cmd_cancel(sc, SCP_UPD_MCAST);
3315
3316         for (ifma = ifp->if_multiaddrs.lh_first, count = 0; ifma != NULL;
3317             ifma = ifma->ifma_link.le_next, count++)
3318
3319         /* track this stuff even when not running */
3320         if (count > 16) {
3321                 ifp->if_flags |= IFF_ALLMULTI;
3322                 ray_update_promisc(sc);
3323                 return;
3324         } else if (ifp->if_flags & IFF_ALLMULTI) {
3325                 ifp->if_flags &= ~IFF_ALLMULTI;
3326                 ray_update_promisc(sc);
3327         }
3328
3329         if ((ifp->if_flags & IFF_RUNNING) == 0)
3330                 return;
3331         else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) {
3332                 ray_cmd_schedule(sc, SCP_UPD_MCAST);
3333                 return;
3334         } else if (!ray_alloc_ccs(sc,&ccs, RAY_CMD_UPDATE_MCAST, SCP_UPD_MCAST))
3335                 return;
3336         SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update_mcast, c_nmcast, count);
3337         bufp = RAY_HOST_TO_ECF_BASE;
3338         for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
3339             ifma = ifma->ifma_link.le_next) {
3340                 ray_write_region(
3341                     sc,
3342                     bufp,
3343                     LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
3344                     ETHER_ADDR_LEN
3345                 );
3346                 bufp += ETHER_ADDR_LEN;
3347         }
3348         (void)ray_issue_cmd(sc, ccs, SCP_UPD_MCAST);
3349 }
3350
3351 /*
3352  * User issued commands
3353  */
3354
3355 /*
3356  * issue a update params
3357  *
3358  * expected to be called in sleapable context -- intended for user stuff
3359  */
3360 static int
3361 ray_user_update_params(struct ray_softc *sc, struct ray_param_req *pr)
3362 {
3363         struct ifnet *ifp;
3364         int rv;
3365
3366         RAY_DPRINTFN(5, ("ray%d: ray_user_update_params\n", sc->unit));
3367         RAY_MAP_CM(sc);
3368
3369         ifp = &sc->arpcom.ac_if;
3370
3371         if ((ifp->if_flags & IFF_RUNNING) == 0) {
3372                 pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP;
3373                 return (EIO);
3374         }
3375
3376         if (pr->r_paramid > RAY_MIB_MAX) {
3377                 return (EINVAL);
3378         }
3379
3380         /*
3381          * Handle certain parameters specially
3382          */
3383         switch (pr->r_paramid) {
3384         case RAY_MIB_NET_TYPE:
3385                 if (sc->sc_c.np_net_type == *pr->r_data)
3386                         return (0);
3387                 sc->sc_d.np_net_type = *pr->r_data;
3388                 if (ifp->if_flags & IFF_RUNNING)
3389                         ray_start_join_net(sc);
3390                 return (0);
3391
3392         case RAY_MIB_SSID:
3393                 if (!bcmp(sc->sc_c.np_ssid, pr->r_data, IEEE80211_NWID_LEN))
3394                         return (0);
3395                 bcopy(pr->r_data, sc->sc_d.np_ssid, IEEE80211_NWID_LEN);
3396                 if (ifp->if_flags & IFF_RUNNING)
3397                         ray_start_join_net(sc);
3398                 return (0);
3399
3400         case RAY_MIB_BASIC_RATE_SET:
3401                 sc->sc_d.np_def_txrate = *pr->r_data;
3402                 break;
3403
3404         case RAY_MIB_AP_STATUS: /* Unsupported */
3405         case RAY_MIB_MAC_ADDR:  /* XXX Need interface up */
3406         case RAY_MIB_PROMISC:   /* BPF */
3407                 return (EINVAL);
3408                 break;
3409
3410         default:
3411                 break;
3412         }
3413
3414         if (pr->r_paramid > RAY_MIB_LASTUSER) {
3415                 return (EINVAL);
3416         }
3417
3418         /* wait to be able to issue the command */
3419         rv = 0;
3420         while (ray_cmd_is_running(sc, SCP_UPD_UPDATEPARAMS) ||
3421             ray_cmd_is_scheduled(sc, SCP_UPD_UPDATEPARAMS)) {
3422                 rv = tsleep(ray_update_params, 0|PCATCH, "cmd in use", 0);
3423                 if (rv)
3424                         return (rv);
3425                 if ((ifp->if_flags & IFF_RUNNING) == 0) {
3426                         pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP;
3427                         return (EIO);
3428                 }
3429         }
3430
3431         pr->r_failcause = RAY_FAILCAUSE_WAITING;
3432         sc->sc_updreq = pr;
3433         ray_cmd_schedule(sc, SCP_UPD_UPDATEPARAMS);
3434         ray_check_scheduled(sc);
3435
3436         while (pr->r_failcause == RAY_FAILCAUSE_WAITING)
3437                 (void)tsleep(ray_update_params, 0, "waiting cmd", 0);
3438         wakeup(ray_update_params);
3439
3440         return (0);
3441 }
3442
3443 /*
3444  * issue a report params
3445  *
3446  * expected to be called in sleapable context -- intended for user stuff
3447  */
3448 static int
3449 ray_user_report_params(struct ray_softc *sc, struct ray_param_req *pr)
3450 {
3451         struct ifnet *ifp;
3452         int mib_sizes[] = RAY_MIB_SIZES;
3453         int rv;
3454
3455         RAY_DPRINTFN(5, ("ray%d: ray_user_report_params\n", sc->unit));
3456         RAY_MAP_CM(sc);
3457
3458         ifp = &sc->arpcom.ac_if;
3459
3460         if ((ifp->if_flags & IFF_RUNNING) == 0) {
3461                 pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP;
3462                 return (EIO);
3463         }
3464         
3465         /* test for illegal values or immediate responses */
3466         if (pr->r_paramid > RAY_MIB_LASTUSER) {
3467                 switch (pr->r_paramid) {
3468
3469                 case  RAY_MIB_VERSION:
3470                         if (sc->sc_version == RAY_ECFS_BUILD_4)
3471                             *pr->r_data = 4;
3472                         else
3473                             *pr->r_data = 5;
3474                         break;
3475
3476                 case  RAY_MIB_CUR_BSSID:
3477                         bcopy(sc->sc_c.np_bss_id, pr->r_data, ETHER_ADDR_LEN);
3478                         break;
3479                 case  RAY_MIB_CUR_INITED:
3480                         *pr->r_data = sc->sc_c.np_inited;
3481                         break;
3482                 case  RAY_MIB_CUR_DEF_TXRATE:
3483                         *pr->r_data = sc->sc_c.np_def_txrate;
3484                         break;
3485                 case  RAY_MIB_CUR_ENCRYPT:
3486                         *pr->r_data = sc->sc_c.np_encrypt;
3487                         break;
3488                 case  RAY_MIB_CUR_NET_TYPE:
3489                         *pr->r_data = sc->sc_c.np_net_type;
3490                         break;
3491                 case  RAY_MIB_CUR_SSID:
3492                         bcopy(sc->sc_c.np_ssid, pr->r_data, IEEE80211_NWID_LEN);
3493                         break;
3494                 case  RAY_MIB_CUR_PRIV_START:
3495                         *pr->r_data = sc->sc_c.np_priv_start;
3496                         break;
3497                 case  RAY_MIB_CUR_PRIV_JOIN:
3498                         *pr->r_data = sc->sc_c.np_priv_join;
3499                         break;
3500
3501                 case  RAY_MIB_DES_BSSID:
3502                         bcopy(sc->sc_d.np_bss_id, pr->r_data, ETHER_ADDR_LEN);
3503                         break;
3504                 case  RAY_MIB_DES_INITED:
3505                         *pr->r_data = sc->sc_d.np_inited;
3506                         break;
3507                 case  RAY_MIB_DES_DEF_TXRATE:
3508                         *pr->r_data = sc->sc_d.np_def_txrate;
3509                         break;
3510                 case  RAY_MIB_DES_ENCRYPT:
3511                         *pr->r_data = sc->sc_d.np_encrypt;
3512                         break;
3513                 case  RAY_MIB_DES_NET_TYPE:
3514                         *pr->r_data = sc->sc_d.np_net_type;
3515                         break;
3516                 case  RAY_MIB_DES_SSID:
3517                         bcopy(sc->sc_d.np_ssid, pr->r_data, IEEE80211_NWID_LEN);
3518                         break;
3519                 case  RAY_MIB_DES_PRIV_START:
3520                         *pr->r_data = sc->sc_d.np_priv_start;
3521                         break;
3522                 case  RAY_MIB_DES_PRIV_JOIN:
3523                         *pr->r_data = sc->sc_d.np_priv_join;
3524                         break;
3525
3526                 default:
3527                         return (EINVAL);
3528                         break;
3529                 }
3530                 pr->r_failcause = 0;
3531                 pr->r_len = mib_sizes[pr->r_paramid];
3532                 return (0);
3533         }
3534
3535         /* wait to be able to issue the command */
3536         rv = 0;
3537         while (ray_cmd_is_running(sc, SCP_REPORTPARAMS)
3538             || ray_cmd_is_scheduled(sc, SCP_REPORTPARAMS)) {
3539                 rv = tsleep(ray_report_params, 0|PCATCH, "cmd in use", 0);
3540                 if (rv)
3541                         return (rv);
3542                 if ((ifp->if_flags & IFF_RUNNING) == 0) {
3543                         pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP;
3544                         return (EIO);
3545                 }
3546         }
3547
3548         pr->r_failcause = RAY_FAILCAUSE_WAITING;
3549         sc->sc_repreq = pr;
3550         ray_cmd_schedule(sc, SCP_REPORTPARAMS);
3551         ray_check_scheduled(sc);
3552
3553         while (pr->r_failcause == RAY_FAILCAUSE_WAITING)
3554                 (void)tsleep(ray_report_params, 0, "waiting cmd", 0);
3555         wakeup(ray_report_params);
3556
3557         return (0);
3558 }
3559
3560 /*
3561  * return the error counters
3562  */
3563 static int
3564 ray_user_report_stats(struct ray_softc *sc, struct ray_stats_req *sr)
3565 {
3566         struct ifnet *ifp;
3567
3568         RAY_DPRINTFN(5, ("ray%d: ray_user_report_stats\n", sc->unit));
3569         RAY_MAP_CM(sc);
3570
3571         ifp = &sc->arpcom.ac_if;
3572
3573         if ((ifp->if_flags & IFF_RUNNING) == 0) {
3574                 return (EIO);
3575         }
3576
3577         sr->rxoverflow = sc->sc_rxoverflow;
3578         sr->rxcksum = sc->sc_rxcksum;
3579         sr->rxhcksum = sc->sc_rxhcksum;
3580         sr->rxnoise = sc->sc_rxnoise;
3581
3582         return(0);
3583 }
3584 /******************************************************************************
3585  * XXX NOT KNF FROM HERE DOWN
3586  ******************************************************************************/
3587
3588 /*
3589  * Routines to read from/write to the attribute memory.
3590  *
3591  * Taken from if_xe.c.
3592  *
3593  * Until there is a real way of accessing the attribute memory from a driver
3594  * these have to stay.
3595  *
3596  * The hack to use the crdread/crdwrite device functions causes the attribute
3597  * memory to be remapped into the controller and looses the mapping of
3598  * the common memory.
3599  *
3600  * We cheat by using PIOCSMEM and assume that the common memory window
3601  * is in window 0 of the card structure.
3602  *
3603  * Also
3604  *      pccard/pcic.c/crdread does mark the unmapped window as inactive
3605  *      pccard/pccard.c/map_mem toggles the mapping of a window on
3606  *      successive calls
3607  *
3608  */
3609 #if (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP)
3610 static void
3611 ray_attr_getmap (struct ray_softc *sc)
3612 {
3613     struct ucred        uc;
3614     struct pcred        pc;
3615     struct proc         p;
3616     int                 result;
3617
3618     RAY_DPRINTFN(5, ("ray%d: attempting to get map for common memory\n",
3619             sc->unit));
3620
3621     sc->md.window = 0;
3622
3623     p.p_cred = &pc;
3624     p.p_cred->pc_ucred = &uc;
3625     p.p_cred->pc_ucred->cr_uid = 0;
3626
3627     result = cdevsw[CARD_MAJOR]->d_ioctl(makedev(CARD_MAJOR, sc->slotnum), PIOCGMEM, (caddr_t)&sc->md, 0, &p);
3628
3629     return;
3630 }
3631
3632 static void
3633 ray_attr_cm (struct ray_softc *sc)
3634 {
3635     struct ucred uc;
3636     struct pcred pc;
3637     struct proc p;
3638
3639     RAY_DPRINTFN(100, ("ray%d: attempting to remap common memory\n", sc->unit));
3640
3641     p.p_cred = &pc;
3642     p.p_cred->pc_ucred = &uc;
3643     p.p_cred->pc_ucred->cr_uid = 0;
3644
3645     cdevsw[CARD_MAJOR]->d_ioctl(makedev(CARD_MAJOR, sc->slotnum), PIOCSMEM, (caddr_t)&sc->md, 0, &p);
3646
3647     return;
3648 }
3649 #endif /* (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP) */
3650
3651 static int
3652 ray_attr_write (struct ray_softc *sc, off_t offset, u_int8_t byte)
3653 {
3654   struct iovec iov;
3655   struct uio uios;
3656   int err;
3657
3658   iov.iov_base = &byte;
3659   iov.iov_len = sizeof(byte);
3660
3661   uios.uio_iov = &iov;
3662   uios.uio_iovcnt = 1;
3663   uios.uio_offset = offset;
3664   uios.uio_resid = sizeof(byte);
3665   uios.uio_segflg = UIO_SYSSPACE;
3666   uios.uio_rw = UIO_WRITE;
3667   uios.uio_procp = 0;
3668
3669   err = cdevsw[CARD_MAJOR]->d_write(makedev(CARD_MAJOR, sc->slotnum), &uios, 0);
3670
3671 #if RAY_NEED_CM_REMAPPING
3672   ray_attr_cm(sc);
3673 #endif /* RAY_NEED_CM_REMAPPING */
3674
3675   return (err);
3676 }
3677
3678 static int
3679 ray_attr_read (struct ray_softc *sc, off_t offset, u_int8_t *buf, int size)
3680 {
3681   struct iovec iov;
3682   struct uio uios;
3683   int err;
3684
3685   iov.iov_base = buf;
3686   iov.iov_len = size;
3687
3688   uios.uio_iov = &iov;
3689   uios.uio_iovcnt = 1;
3690   uios.uio_offset = offset;
3691   uios.uio_resid = size;
3692   uios.uio_segflg = UIO_SYSSPACE;
3693   uios.uio_rw = UIO_READ;
3694   uios.uio_procp = 0;
3695
3696   err =  cdevsw[CARD_MAJOR]->d_read(makedev(CARD_MAJOR, sc->slotnum), &uios, 0);
3697
3698 #if RAY_NEED_CM_REMAPPING
3699   ray_attr_cm(sc);
3700 #endif /* RAY_NEED_CM_REMAPPING */
3701
3702   return (err);
3703 }
3704
3705 static u_int8_t
3706 ray_read_reg (sc, reg)
3707     struct ray_softc    *sc;
3708     off_t               reg;
3709 {
3710     u_int8_t            byte;
3711
3712     ray_attr_read(sc, reg, &byte, 1);
3713
3714     return (byte);
3715 }
3716
3717 #if RAY_DEBUG > 50
3718 static void
3719 ray_dump_mbuf(sc, m, s)
3720     struct ray_softc    *sc;
3721     struct mbuf         *m;
3722     char                *s;
3723 {
3724     u_int8_t            *d, *ed;
3725     u_int               i;
3726     char                p[17];
3727
3728     printf("ray%d: %s mbuf dump:", sc->unit, s);
3729     i = 0;
3730     bzero(p, 17);
3731     for (; m; m = m->m_next) {
3732         d = mtod(m, u_int8_t *);
3733         ed = d + m->m_len;
3734
3735         for (; d < ed; i++, d++) {
3736             if ((i % 16) == 0) {
3737                 printf("  %s\n\t", p);
3738             } else if ((i % 8) == 0)
3739                 printf("  ");
3740             printf(" %02x", *d);
3741             p[i % 16] = ((*d >= 0x20) && (*d < 0x80)) ? *d : '.';
3742         }
3743     }
3744     if ((i - 1) % 16)
3745         printf("%s\n", p);
3746 }
3747 #endif /* RAY_DEBUG > 50 */
3748
3749
3750 #endif /* NRAY */