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