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