]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ray/if_ray.c
Completed start/join code (well only infrastructure mode)
[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$
32  *
33  */
34
35 #define XXX             0
36 #define XXX_TRACKING    0
37
38 /*
39  * XXX build options - move to LINT
40  */
41 #define RAY_DEBUG               100     /* Big numbers get more verbose */
42 #define RAY_CCS_TIMEOUT         (hz/2)  /* Timeout for CCS commands - only used for downloading startup parameters */
43 #define RAY_NEED_STARTJOIN_TIMO 0       /* Might be needed with build 4 */
44 #define RAY_SJ_TIMEOUT          (90*hz) /* Timeout for failing STARTJOIN commands - only used with RAY_NEED_STARTJOIN_TIMO */
45 #define RAY_NEED_CM_REMAPPING   1       /* Needed until pccard maps more than one memory area */
46 #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 */
47 /*
48  * XXX build options - move to LINT
49  */
50
51 /*
52  * Debugging odds and odds
53  */
54 #ifndef RAY_DEBUG
55 #define RAY_DEBUG 0
56 #endif /* RAY_DEBUG */
57
58 #if RAY_DEBUG > 0
59
60 #define RAY_DHEX8(p, l) do { if (RAY_DEBUG > 10) {              \
61     u_int8_t *i;                                                \
62     for (i = p; i < (u_int8_t *)(p+l); i += 8)                  \
63         printf("  0x%08lx %8D\n",                               \
64                 (unsigned long)i, (unsigned char *)i, " ");     \
65 } } while (0)
66
67 #define RAY_DPRINTF(x) do { if (RAY_DEBUG) {                    \
68     printf x ;                                                  \
69 } } while (0)
70
71 #define RAY_DNET_DUMP(sc, s) do { if (RAY_DEBUG) {                      \
72     printf("ray%d: Network parameters%s\n", (sc)->unit, (s));           \
73     printf("  bss_id %6D\n", (sc)->sc_bss_id, ":");                     \
74     printf("  inited 0x%02x\n", (sc)->sc_inited);                       \
75     printf("  def_txrate 0x%02x\n", (sc)->sc_def_txrate);               \
76     printf("  encrypt 0x%02x\n", (sc)->sc_encrypt);                     \
77     printf("  net_type 0x%02x\n", (sc)->sc_net_type);                   \
78     printf("  ssid \"%.32s\"\n", (sc)->sc_ssid);                        \
79     printf("  priv_start 0x%02x\n", (sc)->sc_priv_start);               \
80     printf("  priv_join 0x%02x\n", (sc)->sc_priv_join);                 \
81 } } while (0)
82
83 #else
84 #define RAY_HEX8(p, l)
85 #define RAY_DPRINTF(x)
86 #define RAY_DNET_DUMP(sc, s)
87 #endif /* RAY_DEBUG > 0 */
88
89 #if RAY_DEBUG > 10
90 #define RAY_DMBUF_DUMP(sc, m, s)        ray_dump_mbuf((sc), (m), (s))
91 #else
92 #define RAY_DMBUF_DUMP(sc, m, s)
93 #endif /* RAY_DEBUG > 10 */
94
95 #include "ray.h"
96 #include "card.h"
97 #include "apm.h"
98 #include "bpfilter.h"
99
100 #if NRAY > 0
101
102 #include <sys/param.h>
103 #include <sys/cdefs.h>
104 #include <sys/conf.h>
105 #include <sys/errno.h>
106 #include <sys/kernel.h>
107 #include <sys/malloc.h>
108 #include <sys/mbuf.h>
109 #include <sys/select.h>
110 #include <sys/socket.h>
111 #include <sys/sockio.h>
112 #include <sys/systm.h>
113 #include <sys/uio.h>
114 #include <sys/proc.h>
115 #include <sys/ucred.h>
116
117 #include <net/if.h>
118 #include <net/if_arp.h>
119 #include <net/ethernet.h>
120 #include <net/if_dl.h>
121 #include <net/if_media.h>
122 #include <net/if_mib.h>
123 #include <i386/isa/if_ieee80211.h>
124
125 #if NBPFILTER > 0
126 #include <net/bpf.h>
127 #endif /* NBPFILTER */
128
129 #include <machine/clock.h>
130 #include <machine/md_var.h>
131 #include <machine/bus_pio.h>
132 #include <machine/bus.h>
133
134 #include <i386/isa/isa.h>
135 #include <i386/isa/isa_device.h>
136 #include <i386/isa/if_rayreg.h>
137 #include <i386/isa/if_raymib.h>
138
139 #if NCARD > 0
140 #include <pccard/cardinfo.h>
141 #include <pccard/cis.h>
142 #include <pccard/driver.h>
143 #include <pccard/slot.h>
144 #endif /* NCARD */
145
146 #if NAPM > 0
147 #include <machine/apm_bios.h>
148 #endif /* NAPM */
149
150 /*
151  * One of these structures per allocated device
152  */
153 struct ray_softc {
154
155     struct arpcom       arpcom;         /* Ethernet common              */
156     struct ifmedia      ifmedia;        /* Ifnet common                 */
157     struct callout_handle \
158                         timerh;         /* Handle for timer             */
159 #if RAY_NEED_STARTJOIN_TIMO
160     struct callout_handle \
161                         sj_timerh;      /* Handle for start_join timer  */
162 #endif /* RAY_NEED_STARTJOIN_TIMO */
163
164     char                *card_type;     /* Card model name              */
165     char                *vendor;        /* Card manufacturer            */
166
167     int                 unit;           /* Unit number                  */
168     u_char              gone;           /* 1 = Card bailed out          */
169     int                 irq;            /* Assigned IRQ                 */
170     caddr_t             maddr;          /* Shared RAM Address           */
171     int                 msize;          /* Shared RAM Size              */
172
173     int                 translation;    /* Packet translation types     */
174     /* XXX these can go when attribute reading is fixed */
175     int                 slotnum;        /* Slot number                  */
176     struct mem_desc     md;             /* Map info for common memory   */
177
178     struct ray_ecf_startup_v5 \
179                         sc_ecf_startup; /* Startup info from card       */
180
181     u_int8_t            sc_ccsinuse[64];/* ccss' in use -- not for tx   */
182     size_t              sc_ccs;         /* ccs used by non-scheduled,   */
183                                         /* non-overlapping procedures   */
184
185     struct ray_cmd_net  sc_cnet_1;      /* current network params from  */
186     struct ray_net_params sc_cnet_2;    /* starting/joining a network   */
187
188 #if 0
189     u_int8_t            sc_cnwid[IEEE80211_NWID_LEN];   /* Last nwid */
190     u_int8_t            sc_dnwid[IEEE80211_NWID_LEN];   /* Desired nwid */
191     u_int8_t            sc_omode;       /* Old operating mode SC_MODE_xx */
192     u_int8_t            sc_mode;        /* Current operating mode SC_MODE_xx */
193     u_int8_t            sc_countrycode; /* Current country code */
194     u_int8_t            sc_dcountrycode;/* Desired country code */
195 #endif
196     int                 sc_havenet;     /* true if we have aquired a network */
197 };
198 static struct ray_softc ray_softc[NRAY];
199
200 #define sc_station_addr sc_ecf_startup.e_station_addr
201 #define sc_version      sc_ecf_startup.e_fw_build_string
202 #define sc_tibsize      sc_ecf_startup.e_tibsize
203
204 #define sc_upd_param    sc_cnet_1.c_upd_param
205 #define sc_bss_id       sc_cnet_1.c_bss_id
206 #define sc_inited       sc_cnet_1.c_inited
207 #define sc_def_txrate   sc_cnet_1.c_def_txrate
208 #define sc_encrypt      sc_cnet_1.c_encrypt
209 #define sc_net_type     sc_cnet_2.p_net_type
210 #define sc_ssid         sc_cnet_2.p_ssid
211 #define sc_priv_start   sc_cnet_2.p_privacy_must_start
212 #define sc_priv_join    sc_cnet_2.p_privacy_can_join
213 /*XXX add to debug macro too */
214
215 /* Commands -- priority given to LSB */
216 #define SCP_FIRST               0x0001
217 #define SCP_UPDATESUBCMD        0x0001
218 #define SCP_STARTASSOC          0x0002
219 #define SCP_REPORTPARAMS        0x0004
220 #define SCP_IFSTART             0x0008
221
222 /* Update sub commands -- issues are serialized priority to LSB */
223 #define SCP_UPD_FIRST           0x0100
224 #define SCP_UPD_STARTUP         0x0100
225 #define SCP_UPD_STARTJOIN       0x0200
226 #define SCP_UPD_PROMISC         0x0400
227 #define SCP_UPD_MCAST           0x0800
228 #define SCP_UPD_UPDATEPARAMS    0x1000
229 #define SCP_UPD_SHIFT           8
230 #define SCP_UPD_MASK            0xff00
231
232 /* These command (a subset of the update set) require timeout checking */
233 #define SCP_TIMOCHECK_CMD_MASK  \
234         (SCP_UPD_UPDATEPARAMS | SCP_UPD_STARTUP | SCP_UPD_MCAST | \
235         SCP_UPD_PROMISC)
236 /* Translation types */
237 /* XXX maybe better as part of the if structure? */
238 #define SC_TRANSLATE_WEBGEAR    0
239
240 /*
241  * PCMCIA driver definition
242  */
243 static int       ray_pccard_init        __P((struct pccard_devinfo *dev_p));
244 static void      ray_pccard_unload      __P((struct pccard_devinfo *dev_p));
245 static int       ray_pccard_intr        __P((struct pccard_devinfo *dev_p));
246
247 PCCARD_MODULE(ray, ray_pccard_init, ray_pccard_unload, ray_pccard_intr, 0, net_imask);
248
249 /*
250  * ISA driver definition
251  */
252 static int       ray_probe              __P((struct isa_device *dev));
253 static int       ray_attach             __P((struct isa_device *dev));
254 struct isa_driver raydriver = {
255     ray_probe,
256     ray_attach,
257     "ray",
258     1
259 };
260
261 /*
262  * Network driver definition
263  */
264 static void      ray_start              __P((struct ifnet *ifp));
265 static int       ray_ioctl              __P((struct ifnet *ifp, u_long command, caddr_t data));
266 static void      ray_watchdog           __P((struct ifnet *ifp));
267 static void      ray_init               __P((void *xsc));
268 static void      ray_stop               __P((struct ray_softc *sc));
269
270 /*
271  * Internal utilites
272  */
273 static int      ray_alloc_ccs           __P((struct ray_softc *sc, size_t *ccsp, u_int cmd, u_int track));
274 static void     ray_ccs_done            __P((struct ray_softc *sc, size_t ccs));
275 static void     ray_download_params     __P((struct ray_softc *sc));
276 static void     ray_download_timo       __P((void *xsc));
277 static u_int8_t ray_free_ccs            __P((struct ray_softc *sc, size_t ccs));
278 static int      ray_issue_cmd           __P((struct ray_softc *sc, size_t ccs, u_int track));
279 static void     ray_rcs_intr            __P((struct ray_softc *sc, size_t ccs));
280 static void     ray_rx                  __P((struct ray_softc *sc, size_t rcs));
281 static void     ray_start_join_done     __P((struct ray_softc *sc, size_t ccs, u_int8_t status));
282 #if RAY_NEED_STARTJOIN_TIMO
283 static void     ray_start_join_timo     __P((void *xsc));
284 #endif /* RAY_NEED_STARTJOIN_TIMO */
285 #if RAY_DEBUG > 10
286 static void     ray_dump_mbuf           __P((struct ray_softc *sc, struct mbuf *m, char *s));
287 #endif /* RAY_DEBUG > 10 */
288
289 /*
290  * Indirections for reading/writing shared memory - from NetBSD/if_ray.c
291  */
292 #ifndef offsetof
293 #define offsetof(type, member) \
294     ((size_t)(&((type *)0)->member))
295 #endif /* offsetof */
296
297 #define SRAM_READ_1(sc, off) \
298     (u_int8_t)*((sc)->maddr + (off))
299 /* ((u_int8_t)bus_space_read_1((sc)->sc_memt, (sc)->sc_memh, (off))) */
300
301 #define SRAM_READ_FIELD_1(sc, off, s, f) \
302     SRAM_READ_1(sc, (off) + offsetof(struct s, f))
303
304 #define SRAM_READ_FIELD_2(sc, off, s, f)                        \
305     ((((u_int16_t)SRAM_READ_1(sc, (off) + offsetof(struct s, f)) << 8) \
306     |(SRAM_READ_1(sc, (off) + 1 + offsetof(struct s, f)))))
307
308 #define SRAM_READ_FIELD_N(sc, off, s, f, p, n)  \
309     ray_read_region(sc, (off) + offsetof(struct s, f), (p), (n))
310
311 #define ray_read_region(sc, off, vp, n) \
312     bcopy((sc)->maddr + (off), (vp), (n))
313
314 #define SRAM_WRITE_1(sc, off, val)      \
315     *((sc)->maddr + (off)) = (val)
316 /* bus_space_write_1((sc)->sc_memt, (sc)->sc_memh, (off), (val)) */
317
318 #define SRAM_WRITE_FIELD_1(sc, off, s, f, v)    \
319     SRAM_WRITE_1(sc, (off) + offsetof(struct s, f), (v))
320
321 #define SRAM_WRITE_FIELD_2(sc, off, s, f, v) do {       \
322     SRAM_WRITE_1(sc, (off) + offsetof(struct s, f), (((v) >> 8 ) & 0xff)); \
323     SRAM_WRITE_1(sc, (off) + 1 + offsetof(struct s, f), ((v) & 0xff)); \
324 } while (0)
325
326 #define SRAM_WRITE_FIELD_N(sc, off, s, f, p, n) \
327     ray_write_region(sc, (off) + offsetof(struct s, f), (p), (n))
328
329 #define ray_write_region(sc, off, vp, n) \
330     bcopy((vp), (sc)->maddr + (off), (n))
331
332 /*
333  * Macro's
334  */
335 #ifndef RAY_CCS_TIMEOUT
336 #define RAY_CCS_TIMEOUT         (hz / 2)
337 #endif
338 #define RAY_ECF_READY(sc)       (!(ray_read_reg(sc, RAY_ECFIR) & RAY_ECFIR_IRQ))
339 #define RAY_ECF_START_CMD(sc)   ray_attr_write((sc), RAY_ECFIR, RAY_ECFIR_IRQ)
340 #define RAY_HCS_CLEAR_INTR(sc)  ray_attr_write((sc), RAY_HCSIR, 0)
341 #define RAY_HCS_INTR(sc)        (ray_read_reg(sc, RAY_HCSIR) & RAY_HCSIR_IRQ)
342
343 /*
344  * XXX
345  * As described in if_xe.c...
346  *
347  * Horrid stuff for accessing CIS tuples and remapping common memory...
348  * XXX
349  */
350 #define CARD_MAJOR              50
351 static int      ray_attr_write  __P((struct ray_softc *sc, off_t offset, u_int8_t byte));
352 static int      ray_attr_read   __P((struct ray_softc *sc, off_t offset, u_int8_t *buf, int size));
353 static u_int8_t ray_read_reg    __P((struct ray_softc *sc, off_t reg));
354
355 #if RAY_NEED_CM_REMAPPING
356 static void     ray_attr_getmap __P((struct ray_softc *sc));
357 static void     ray_attr_cm     __P((struct ray_softc *sc));
358 #define RAY_MAP_CM(sc)          ray_attr_cm(sc)
359 #else
360 #define RAY_MAP_CM(sc)
361 #endif /* RAY_NEED_CM_REMAPPING */
362
363 /*
364  * PCCard initialise.
365  */
366 static int
367 ray_pccard_init (dev_p)
368     struct pccard_devinfo   *dev_p;
369 {
370     struct ray_softc    *sc;
371     u_int32_t           irq;
372     int                 j;
373
374     RAY_DPRINTF(("ray%d: PCCard probe\n", dev_p->isahd.id_unit));
375
376     if (dev_p->isahd.id_unit >= NRAY)
377         return(ENODEV);
378
379     sc = &ray_softc[dev_p->isahd.id_unit];
380     sc->gone = 0;
381     sc->unit = dev_p->isahd.id_unit;
382     sc->slotnum = dev_p->slt->slotnum;
383
384     /* Get IRQ - encoded as a bitmask. */
385     irq = dev_p->isahd.id_irq;
386     for (j = 0; j < 32; j++) {
387         if (irq & 0x1)
388                 break;
389         irq >>= 1;
390     }
391     sc->irq = j;
392     sc->maddr = dev_p->isahd.id_maddr;
393     sc->msize = dev_p->isahd.id_msize;
394
395     printf("ray%d: <Raylink/IEEE 802.11> maddr 0x%lx msize 0x%x irq %d on isa (PC-Card slot %d)\n",
396         sc->unit, (unsigned long)sc->maddr, sc->msize, sc->irq, sc->slotnum);
397
398 #if RAY_NEED_CM_REMAPPING
399     ray_attr_getmap(sc);
400 #endif /* RAY_NEED_CM_REMAPPING */
401
402     if (ray_attach(&dev_p->isahd))
403         return(ENXIO);
404
405     return(0);
406 }
407
408 /*
409  * PCCard unload.
410  */
411 static void
412 ray_pccard_unload (dev_p)
413     struct pccard_devinfo       *dev_p;
414 {
415     struct ray_softc            *sc;
416     struct ifnet                *ifp;
417
418     RAY_DPRINTF(("ray%d: PCCard unload\n", dev_p->isahd.id_unit));
419
420     sc = &ray_softc[dev_p->isahd.id_unit];
421
422     if (sc->gone) {
423         printf("ray%d: already unloaded\n", sc->unit);
424         return;
425     }
426
427     /* Cleardown interface */
428     ifp = &sc->arpcom.ac_if;
429     ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
430     if_down(ifp); /* XXX probably should be if_detach but I don't know if it works in 3.1 */
431
432     /* Mark card as gone */
433     sc->gone = 1;
434     printf("ray%d: unloaded\n", sc->unit);
435
436     return;
437 }
438
439 /*
440  * PCCard interrupt.
441  */
442 /* XXX return 1 if we take interrupt, 0 otherwise */
443 static int
444 ray_pccard_intr (dev_p)
445     struct pccard_devinfo       *dev_p;
446 {
447     struct ray_softc            *sc;
448     int                         ccsi, handled;
449
450     RAY_DPRINTF(("ray%d: PCCard intr\n", dev_p->isahd.id_unit));
451
452     sc = &ray_softc[dev_p->isahd.id_unit];
453     RAY_MAP_CM(sc);
454
455     if (sc->gone) {
456         printf("ray%d: unloaded before interrupt!\n", sc->unit);
457         return(0);
458     }
459
460     /*
461      * Check that the interrupt was for us, if so get the rcs/ccs and vector
462      * on the command contained within it.
463      */
464     if (!RAY_HCS_INTR(sc)) {
465
466         handled = 0;
467
468     } else {
469
470         handled = 1;
471         ccsi = SRAM_READ_1(sc, RAY_SCB_RCSI);
472         if (ccsi <= RAY_CCS_LAST)
473             ray_ccs_done(sc, RAY_CCS_ADDRESS(ccsi));
474         else if (ccsi <= RAY_RCS_LAST)
475             ray_rcs_intr(sc, RAY_CCS_ADDRESS(ccsi));
476         else
477             printf("ray%d: ray_intr bad ccs index %d\n", sc->unit, ccsi);
478
479 #if XXX
480         ccs_done and rcs_intr return function pointers - why dont
481         they just do it themselves? its not as if each command only
482         requires a single function call - things like start_join_net
483         call a couple on the way...
484         if (rcmd)
485             (*rcmd)(sc);
486 #endif
487
488     }
489
490     if (handled)
491         RAY_HCS_CLEAR_INTR(sc);
492
493     RAY_DPRINTF(("ray%d: interrupt %s handled\n",
494                 sc->unit, handled?"was":"not"));
495
496     return(handled);
497 }
498
499 /*
500  * ISA probe routine.
501  */
502 static int
503 ray_probe (dev_p)
504     struct isa_device           *dev_p;
505 {
506
507     RAY_DPRINTF(("ray%d: ISA probe\n", dev_p->id_unit));
508
509     return(0);
510 }
511
512 /*
513  * ISA/PCCard attach.
514  */
515 static int
516 ray_attach (dev_p)
517     struct isa_device           *dev_p;
518 {
519     struct ray_softc            *sc;
520     struct ray_ecf_startup_v5   *ep;
521     struct ifnet                *ifp;
522     char                        ifname[IFNAMSIZ];
523
524     RAY_DPRINTF(("ray%d: ISA/PCCard attach\n", dev_p->id_unit));
525
526     sc = &ray_softc[dev_p->id_unit];
527     RAY_MAP_CM(sc);
528
529     if (sc->gone) {
530         printf("ray%d: unloaded before attach!\n", sc->unit);
531         return(0);
532     }
533
534     /*
535      * Read startup results, check the card is okay and work out what
536      * version we are using.
537      */
538     ep = &sc->sc_ecf_startup;
539     ray_read_region(sc, RAY_ECF_TO_HOST_BASE, ep, sizeof(sc->sc_ecf_startup));
540     if (ep->e_status != RAY_ECFS_CARD_OK) {
541         printf("ray%d: card failed self test: status 0x%b\n", sc->unit,
542             ep->e_status,
543             "\020"                      /* print in hex */
544             "\001RESERVED0"
545             "\002PROC_SELF_TEST"
546             "\003PROG_MEM_CHECKSUM"
547             "\004DATA_MEM_TEST"
548             "\005RX_CALIBRATION"
549             "\006FW_VERSION_COMPAT"
550             "\007RERSERVED1"
551             "\008TEST_COMPLETE"
552         );
553         return(0);
554     }
555     if (sc->sc_version != RAY_ECFS_BUILD_4 &&
556         sc->sc_version != RAY_ECFS_BUILD_5
557        ) {
558         printf("ray%d: unsupported firmware version 0x%0x\n", sc->unit,
559             ep->e_fw_build_string);
560         return(0);
561     }
562
563     if (bootverbose || RAY_DEBUG) {
564         printf("ray%d: Start Up Results\n", sc->unit);
565         if (RAY_DEBUG > 10)
566             RAY_DHEX8((u_int8_t *)sc->maddr + RAY_ECF_TO_HOST_BASE, 0x40);
567         if (sc->sc_version == RAY_ECFS_BUILD_4)
568             printf("  Firmware version 4\n");
569         else
570             printf("  Firmware version 5\n");
571         printf("  Status 0x%x\n", ep->e_status);
572         printf("  Ether address %6D\n", ep->e_station_addr, ":");
573         if (sc->sc_version == RAY_ECFS_BUILD_4) {
574             printf("  Program checksum %0x\n", ep->e_resv0);
575             printf("  CIS checksum %0x\n", ep->e_rates[0]);
576         } else {
577             printf("  (reserved word) %0x\n", ep->e_resv0);
578             printf("  Supported rates %8D\n", ep->e_rates, ":");
579         }
580         printf("  Japan call sign %12D\n", ep->e_japan_callsign, ":");
581         if (sc->sc_version == RAY_ECFS_BUILD_5) {
582             printf("  Program checksum %0x\n", ep->e_prg_cksum);
583             printf("  CIS checksum %0x\n", ep->e_cis_cksum);
584             printf("  Firmware version %0x\n", ep->e_fw_build_string);
585             printf("  Firmware revision %0x\n", ep->e_fw_build);
586             printf("  (reserved word) %0x\n", ep->e_fw_resv);
587             printf("  ASIC version %0x\n", ep->e_asic_version);
588             printf("  TIB size %0x\n", ep->e_tibsize);
589         }
590     }
591
592     /* Reset any pending interrupts */
593     RAY_HCS_CLEAR_INTR(sc);
594
595     /*
596      * Set the parameters that will survive stop/init
597      *
598      * Do not update these in ray_init's parameter setup
599      */
600 #if XXX
601      see the ray_init section for stuff to move here
602 #endif
603
604     /*
605      * Initialise the network interface structure
606      */
607     bcopy((char *)&ep->e_station_addr,
608           (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
609     ifp = &sc->arpcom.ac_if;
610     ifp->if_softc = sc;
611     ifp->if_name = "ray";
612     ifp->if_unit = sc->unit;
613     ifp->if_timer = 0;
614     ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX ); /* XXX - IFF_MULTICAST */
615 #if XXX
616     ifp->if_hdr = ...; make this big enough to hold the .11 and .3 headers
617 #endif
618     ifp->if_baudrate = 1000000; /* XXX Is this baud or bps ;-) */
619
620     ifp->if_output = ether_output;
621     ifp->if_start = ray_start;
622     ifp->if_ioctl = ray_ioctl;
623     ifp->if_watchdog = ray_watchdog;
624     ifp->if_init = ray_init;
625     ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
626
627     /*
628      * If this logical interface has already been attached,
629      * don't attach it again or chaos will ensue.
630      */
631     sprintf(ifname, "ray%d", sc->unit);
632
633     if (ifunit(ifname) == NULL) {
634         callout_handle_init(&sc->timerh);
635 #if RAY_NEED_STARTJOIN_TIMO
636         callout_handle_init(&sc->sj_timerh);
637 #endif /* RAY_NEED_STARTJOIN_TIMO */
638         if_attach(ifp);
639         ether_ifattach(ifp);
640 #if NBPFILTER > 0
641         bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
642 #endif /* NBFFILTER */
643
644 #if XXX
645         this looks like a good idea
646         at_shutdown(ray_shutdown, sc, SHUTDOWN_POST_SYNC);
647 #endif /* XXX */
648     }
649
650     return(0);
651 }
652
653 /*
654  * Network start.
655  *
656  * Start output on interface.  We make two assumptions here:
657  *  1) that the current priority is set to splimp _before_ this code
658  *     is called *and* is returned to the appropriate priority after
659  *     return
660  *  2) that the IFF_OACTIVE flag is checked before this code is called
661  *     (i.e. that the output part of the interface is idle)
662  */
663 static void
664 ray_start (ifp)
665     register struct ifnet       *ifp;
666 {
667     struct ray_softc *sc;
668
669     RAY_DPRINTF(("ray%d: Network start\n", ifp->if_unit));
670
671     sc = ifp->if_softc;
672     RAY_MAP_CM(sc);
673
674     if (sc->gone) {
675         printf("ray%d: unloaded before start!\n", sc->unit);
676         return;
677     }
678
679 /* XXX mark output queue full so the kernel waits */
680 ifp->if_flags |= IFF_OACTIVE;
681
682 /* XXX if_xe code is clean but if_ed does more checks at top */
683  
684     return;
685 }
686
687 /*
688  * Network ioctl request.
689  */
690 static int
691 ray_ioctl (ifp, command, data)
692     register struct ifnet       *ifp;
693     u_long                      command;
694     caddr_t                     data;
695 {
696     struct ray_softc *sc;
697     int s, error = 0;
698
699     RAY_DPRINTF(("ray%d: Network ioctl\n", ifp->if_unit));
700
701     sc = ifp->if_softc;
702     RAY_MAP_CM(sc);
703
704     if (sc->gone) {
705         printf("ray%d: unloaded before ioctl!\n", sc->unit);
706         ifp->if_flags &= ~IFF_RUNNING;
707         return ENXIO;
708     }
709
710     s = splimp();
711
712     switch (command) {
713
714         case SIOCSIFADDR:
715         case SIOCGIFADDR:
716         case SIOCSIFMTU:
717             RAY_DPRINTF(("ray%d: ioctl SIFADDR/GIFADDR/SIFMTU\n", sc->unit));
718             error = ether_ioctl(ifp, command, data);
719             break;
720
721         case SIOCSIFFLAGS:
722             RAY_DPRINTF(("ray%d: for SIFFLAGS\n", sc->unit));
723             /*
724              * If the interface is marked up and stopped, then start
725              * it. If it is marked down and running, then stop it.
726              */
727             if (ifp->if_flags & IFF_UP) {
728                 if (!(ifp->if_flags & IFF_RUNNING))
729                     ray_init(sc);
730             } else {
731                 if (ifp->if_flags & IFF_RUNNING)
732                     ray_stop(sc);
733             }
734             /* DROP THROUGH */
735
736 #if XXX
737         case SIOCADDMULTI:
738         case SIOCDELMULTI:
739             RAY_DPRINTF(("ray%d: ioctl called for ADDMULTI/DELMULTI\n, sc->unit"));
740             /*
741              * Multicast list has (maybe) changed; set the hardware filter
742              * accordingly. This also serves to deal with promiscuous mode
743              * if we have a BPF listener active.
744              */
745             ray_setmulti(sc);
746 #endif /* XXX */
747
748             error = 0;
749             break;
750
751 case SIOCGIFFLAGS:
752     RAY_DPRINTF(("ray%d: ioctl called for GIFFLAGS\n", sc->unit));
753     error = EINVAL;
754     break;
755 case SIOCGIFMETRIC:
756     RAY_DPRINTF(("ray%d: ioctl called for GIFMETRIC\n", sc->unit));
757     error = EINVAL;
758     break;
759 case SIOCGIFMTU:
760     RAY_DPRINTF(("ray%d: ioctl called for GIFMTU\n", sc->unit));
761     error = EINVAL;
762     break;
763 case SIOCGIFPHYS:
764     RAY_DPRINTF(("ray%d: ioctl called for GIFPYHS\n", sc->unit));
765     error = EINVAL;
766     break;
767 case SIOCSIFMEDIA:
768     RAY_DPRINTF(("ray%d: ioctl called for SIFMEDIA\n", sc->unit));
769     error = EINVAL;
770     break;
771 case SIOCGIFMEDIA:
772     RAY_DPRINTF(("ray%d: ioctl called for GIFMEDIA\n", sc->unit));
773 #if RAY_DUMP_CM_ON_GIFMEDIA
774     RAY_DPRINTF(("ray%d: RAY_SCB\n", sc->unit));
775     RAY_DHEX8((u_int8_t *)sc->maddr + RAY_SCB_BASE, 0x20);
776     RAY_DPRINTF(("ray%d: RAY_STATUS\n", sc->unit));
777     RAY_DNET_DUMP(sc, ".");
778 #endif /* RAY_DUMP_CM_ON_GIFMEDIA */
779     error = EINVAL;
780     break;
781
782         default:
783             error = EINVAL;
784     }
785
786     (void)splx(s);
787
788     return(error);
789 }
790
791 static void
792 ray_watchdog (ifp)
793     register struct ifnet       *ifp;
794 {
795     struct ray_softc *sc;
796
797     RAY_DPRINTF(("ray%d: Network watchdog\n", ifp->if_unit));
798
799     sc = ifp->if_softc;
800     RAY_MAP_CM(sc);
801
802     if (sc->gone) {
803         printf("ray%d: unloaded before watchdog!\n", sc->unit);
804         return;
805     }
806
807     printf("ray%d: watchdog timeout\n", sc->unit);
808
809 /* XXX may need to have remedial action here
810    for example
811         ray_reset - may be useful elsewhere
812                 ray_stop
813                 ...
814                 ray_init
815 */
816
817     return;
818 }
819
820 /*
821  * Network initialisation.
822  */
823 static void
824 ray_init (xsc)
825     void                        *xsc;
826 {
827     struct ray_softc            *sc = xsc;
828     struct ray_ecf_startup_v5   *ep;
829     struct ifnet                *ifp;
830     size_t                      ccs;
831     int                         i;
832
833     RAY_DPRINTF(("ray%d: Network init\n", sc->unit));
834     RAY_MAP_CM(sc);
835
836     if (sc->gone) {
837         printf("ray%d: unloaded before init!\n", sc->unit);
838         return;
839     }
840
841     ifp = &sc->arpcom.ac_if;
842
843     if ((ifp->if_flags & IFF_RUNNING))
844         ray_stop(sc);
845
846     /*
847      * Reset instance variables
848      *
849      * The first set are network parameters that are fully initialised
850      * when the card starts or joins the network.
851      *
852      * The second set are network parameters that are downloaded to
853      * the card.
854      *
855      * All of the variables in these sets can be updated by the card or ioctls.
856      */
857     sc->sc_upd_param = 0;
858     bzero(sc->sc_bss_id, sizeof(sc->sc_bss_id));
859     sc->sc_inited = 0;
860     sc->sc_def_txrate = 0;
861     sc->sc_encrypt = 0;
862
863     sc->translation = SC_TRANSLATE_WEBGEAR;
864
865 #if XXX
866     these might be better in _attach so updated values are kept
867     over up/down events
868
869     we probably also need a few more
870         countrycode
871 #endif
872     sc->sc_net_type = RAY_MIB_NET_TYPE_DEFAULT;
873     bzero(&sc->sc_ssid, sizeof(sc->sc_ssid));
874     strncpy(sc->sc_ssid, RAY_MIB_SSID_DEFAULT, RAY_MAXSSIDLEN);
875     sc->sc_priv_start = RAY_MIB_PRIVACY_MUST_START_DEFAULT;
876     sc->sc_priv_join = RAY_MIB_PRIVACY_CAN_JOIN_DEFAULT;
877
878     sc->sc_havenet = 0;
879 #if XXX
880 NetBSD
881     sc->sc_scheduled = 0;
882     sc->sc_running = 0;
883     sc->sc_txfree = RAY_CCS_NTX;
884     sc->sc_checkcounters = 0;
885 #endif
886
887     /* Set all ccs to be free */
888     bzero(sc->sc_ccsinuse, sizeof(sc->sc_ccsinuse));
889     sc->sc_ccs = RAY_CCS_LAST + 1;
890     ccs = RAY_CCS_ADDRESS(0);
891     for (i = 0; i < RAY_CCS_LAST; ccs += RAY_CCS_SIZE, i++)
892             SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_FREE);
893
894     /* Clear any pending interrupts */
895     RAY_HCS_CLEAR_INTR(sc);
896
897     /*
898      * Get startup results - the card may have been reset
899      */
900     ep = &sc->sc_ecf_startup;
901     ray_read_region(sc, RAY_ECF_TO_HOST_BASE, ep, sizeof(sc->sc_ecf_startup));
902     if (ep->e_status != RAY_ECFS_CARD_OK) {
903         printf("ray%d: card failed self test: status 0x%b\n", sc->unit,
904             ep->e_status,
905             "\020"                      /* print in hex */
906             "\001RESERVED0"
907             "\002PROC_SELF_TEST"
908             "\003PROG_MEM_CHECKSUM"
909             "\004DATA_MEM_TEST"
910             "\005RX_CALIBRATION"
911             "\006FW_VERSION_COMPAT"
912             "\007RERSERVED1"
913             "\008TEST_COMPLETE"
914         );
915 #if XXX
916         return; /* XXX This doesn't mark the interface as down */
917 #endif /* XXX */
918     }
919
920     /*
921      * Fixup tib size to be correct - on build 4 it is garbage
922      */
923     if (sc->sc_version == RAY_ECFS_BUILD_4 && sc->sc_tibsize == 0x55)
924         sc->sc_tibsize = 32;
925
926     /*
927      * We are now up and running. Next we have to download network
928      * configuration into the card. We are busy until download is done.
929      */
930     ifp->if_flags |= IFF_RUNNING | IFF_OACTIVE;
931 #if XXX
932     /* set this now so it gets set in the download */
933     sc->sc_promisc = !!(sc->sc_if.if_flags & (IFF_PROMISC|IFF_ALLMULTI));
934 #endif /* XXX */
935     ray_download_params(sc);
936
937 #if XXX
938     need to understand how the doenload finishes first
939
940     Start up flow is as follows.
941
942         The kernel calls ray_init when the interface is assigned an address.
943
944         ray_init does a bit of house keeping before calling ray_download_params.
945
946         ray_download_params fills the startup parameter structure out and
947         sends it to the card. The download command simply completes so
948         we use schedule a timeout function call to ray_download_timo.
949         We pass the ccs in use via sc->sc_css.
950
951         ray_download_timo checks the ccs for command completion/errors.
952         Then it tells the card to start an adhoc or join a managed
953         network. This should complete via the interrupt mechanism, but
954         the NetBSD driver includes a timeout for some buggy stuff somewhere.
955         I've left the hooks in but don't use them. The interrupt handler
956         passes control to ray_start_join_done - the ccs is handled by
957         the interrupt mechanism.
958
959         Once ray_start_join_done has checked the ccs and
960         uploaded/updated the network parameters we are ready to
961         process packets. It can then call ray_start.
962 #endif /* XXX */
963
964     return;
965 }
966
967 /*
968  * Network stop.
969  */
970 static void
971 ray_stop (sc)
972     struct ray_softc    *sc;
973 {
974     struct ifnet        *ifp;
975
976     RAY_DPRINTF(("ray%d: Network stop\n", sc->unit));
977     RAY_MAP_CM(sc);
978
979     if (sc->gone) {
980         printf("ray%d: unloaded before stop!\n", sc->unit);
981         return;
982     }
983
984     ifp = &sc->arpcom.ac_if;
985
986 /* XXX stuff here please to kill activity on the card and drain down transmissons */
987
988     /* Mark as not running */
989     ifp->if_flags &= ~IFF_RUNNING;
990
991     return;
992 }
993
994 /*
995  * Process CCS command completion - called from ray_intr
996  */
997 static void
998 ray_ccs_done (sc, ccs)
999     struct ray_softc    *sc;
1000     size_t              ccs;
1001 {
1002     u_int               cmd, status;
1003     
1004     RAY_DPRINTF(("ray%d: Processing ccs %d\n", sc->unit, RAY_CCS_INDEX(ccs)));
1005     RAY_MAP_CM(sc);
1006
1007     cmd = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd);
1008     status = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status);
1009     RAY_DPRINTF(("ray%d: ccs idx %d ccs 0x%x cmd 0x%x stat %d\n",
1010                 sc->unit, RAY_CCS_INDEX(ccs), ccs, cmd, status));
1011
1012     /* XXX should we panic on unrecognised commands or just ignore them?
1013      * maybe I'll macroize the printf's */
1014     switch (cmd) {
1015         case RAY_CMD_START_PARAMS:
1016             printf("ray%d: ray_ccs_done got START_PARAMS - why?\n", sc->unit);
1017             break;
1018
1019         case RAY_CMD_UPDATE_PARAMS:
1020             RAY_DPRINTF(("ray%d: ray_ccs_done got UPDATE_PARAMS\n", sc->unit));
1021             XXX;
1022             break;
1023
1024         case RAY_CMD_REPORT_PARAMS:
1025             RAY_DPRINTF(("ray%d: ray_ccs_done got REPORT_PARAMS\n", sc->unit));
1026             XXX;
1027             break;
1028
1029         case RAY_CMD_UPDATE_MCAST:
1030             RAY_DPRINTF(("ray%d: ray_ccs_done got UPDATE_MCAST\n", sc->unit));
1031             XXX;
1032             break;
1033
1034         case RAY_CMD_UPDATE_APM:
1035             RAY_DPRINTF(("ray%d: ray_ccs_done got UPDATE_APM\n", sc->unit));
1036             XXX;
1037             break;
1038
1039         case RAY_CMD_START_NET:
1040         case RAY_CMD_JOIN_NET:
1041             RAY_DPRINTF(("ray%d: ray_ccs_done got START|JOIN_NET\n", sc->unit));
1042             ray_start_join_done(sc, ccs, status);
1043             break;
1044
1045         case RAY_CMD_START_ASSOC:
1046             RAY_DPRINTF(("ray%d: ray_ccs_done got START_ASSOC\n", sc->unit));
1047             XXX;
1048             break;
1049
1050         case RAY_CMD_TX_REQ:
1051             RAY_DPRINTF(("ray%d: ray_ccs_done got TX_REQ\n", sc->unit));
1052             XXX;
1053             break;
1054
1055         case RAY_CMD_TEST_MEM:
1056             printf("ray%d: ray_ccs_done got TEST_MEM - why?\n", sc->unit);
1057             break;
1058
1059         case RAY_CMD_SHUTDOWN:
1060             printf("ray%d: ray_ccs_done got SHUTDOWN - why?\n", sc->unit);
1061             break;
1062
1063         case RAY_CMD_DUMP_MEM:
1064             printf("ray%d: ray_ccs_done got DUMP_MEM - why?\n", sc->unit);
1065             break;
1066
1067         case RAY_CMD_START_TIMER:
1068             printf("ray%d: ray_ccs_done got START_TIMER - why?\n", sc->unit);
1069             break;
1070
1071         default:
1072             printf("ray%d: ray_ccs_done unknown command 0x%x\n", sc->unit, cmd);
1073             break;
1074     }
1075
1076     ray_free_ccs(sc, ccs);
1077
1078     return;
1079 }
1080
1081 /*
1082  * Process ECF command request - called from ray_intr
1083  */
1084 static void
1085 ray_rcs_intr (sc, rcs)
1086     struct ray_softc    *sc;
1087     size_t              rcs;
1088 {
1089     struct ifnet        *ifp;
1090     u_int               cmd, status;
1091     
1092     RAY_DPRINTF(("ray%d: Processing rcs %d\n", sc->unit, RAY_CCS_INDEX(rcs)));
1093     RAY_MAP_CM(sc);
1094
1095     ifp = &sc->arpcom.ac_if;
1096
1097     cmd = SRAM_READ_FIELD_1(sc, rcs, ray_cmd, c_cmd);
1098     status = SRAM_READ_FIELD_1(sc, rcs, ray_cmd, c_status);
1099     RAY_DPRINTF(("ray%d: rcs idx %d rcs 0x%x cmd 0x%x stat %d\n",
1100                 sc->unit, RAY_CCS_INDEX(rcs), rcs, cmd, status));
1101
1102     /* XXX should we panic on unrecognised commands or just ignore them?
1103      * maybe I'll macroize the printf's */
1104     switch (cmd) {
1105         case RAY_ECMD_RX_DONE:
1106             printf("ray%d: ray_rcs_intr got RX_DONE\n", sc->unit);
1107             ray_rx(sc, rcs);
1108             break;
1109
1110         case RAY_ECMD_REJOIN_DONE:
1111             RAY_DPRINTF(("ray%d: ray_rcs_intr got UPDATE_PARAMS\n", sc->unit));
1112             XXX;
1113             break;
1114
1115         case RAY_ECMD_ROAM_START:
1116             RAY_DPRINTF(("ray%d: ray_rcs_intr got ROAM_START\n", sc->unit));
1117             XXX;
1118             break;
1119
1120         case RAY_ECMD_JAPAN_CALL_SIGNAL:
1121             printf("ray%d: ray_rcs_intr got JAPAN_CALL_SIGNAL - why?\n",
1122                         sc->unit);
1123             break;
1124
1125         default:
1126             printf("ray%d: ray_rcs_intr unknown command 0x%x\n",
1127                         sc->unit, cmd);
1128             break;
1129     }
1130
1131     SRAM_WRITE_FIELD_1(sc, rcs, ray_cmd, c_status, RAY_CCS_STATUS_FREE);
1132
1133     return;
1134 }
1135
1136 /*
1137  * Receive a packet
1138  */
1139 static void
1140 ray_rx (sc, rcs)
1141     struct ray_softc            *sc;
1142     size_t                      rcs;
1143 {
1144     struct ieee80211_header     *header;
1145     struct ether_header         *eh;
1146     struct ifnet                *ifp;
1147     struct mbuf                 *m;
1148     size_t                      pktlen, fraglen, readlen, tmplen;
1149     size_t                      bufp, ebufp;
1150     u_int8_t                    *dst, *src;
1151     u_int8_t                    fc;
1152     u_int                       first, ni, i;
1153
1154     RAY_DPRINTF(("ray%d: ray_rx\n", sc->unit));
1155     RAY_MAP_CM(sc);
1156
1157     RAY_DPRINTF(("ray%d: rcs chain - using rcs 0x%x\n", sc->unit, rcs));
1158
1159     ifp = &sc->arpcom.ac_if;
1160     m = NULL;
1161     readlen = 0;
1162
1163     /*
1164      * Get first part of packet and the length. Do some sanity checks
1165      * and get a mbuf.
1166      */
1167     first = RAY_CCS_INDEX(rcs);
1168     pktlen = SRAM_READ_FIELD_2(sc, rcs, ray_cmd_rx, c_pktlen);
1169
1170     if ((pktlen > MCLBYTES) || (pktlen < 1/*XXX should be header size*/)) {
1171         RAY_DPRINTF(("ray%d: ray_rx packet is too big or too small\n",
1172             sc->unit));
1173         ifp->if_ierrors++;
1174         goto skip_read;
1175     }
1176
1177     MGETHDR(m, M_DONTWAIT, MT_DATA);
1178     if (m == NULL) {
1179         RAY_DPRINTF(("ray%d: ray_rx MGETHDR failed\n", sc->unit));
1180         ifp->if_ierrors++;
1181         goto skip_read;
1182     }
1183     if (pktlen > MHLEN) {
1184         MCLGET(m, M_DONTWAIT);
1185         if ((m->m_flags & M_EXT) == 0) {
1186             RAY_DPRINTF(("ray%d: ray_rx MCLGET failed\n", sc->unit));
1187             ifp->if_ierrors++;
1188             m_freem(m);
1189             m = 0;
1190             goto skip_read;
1191         }
1192     }
1193     m->m_pkthdr.rcvif = ifp;
1194     m->m_pkthdr.len = pktlen;
1195     m->m_len = pktlen;
1196     dst = mtod(m, u_int8_t *);
1197
1198     /*
1199      * Walk the fragment chain to build the complete packet.
1200      *
1201      * The use of two index variables removes a race with the
1202      * hardware. If one index were used the clearing of the CCS would
1203      * happen before reading the next pointer and the hardware can get in.
1204      * Not my idea but verbatim from the NetBSD driver.
1205      */
1206     i = ni = first;
1207     while ((i = ni) && (i != RAY_CCS_LINK_NULL)) {
1208         rcs = RAY_CCS_ADDRESS(i);
1209         ni = SRAM_READ_FIELD_1(sc, rcs, ray_cmd_rx, c_nextfrag);
1210         bufp = SRAM_READ_FIELD_2(sc, rcs, ray_cmd_rx, c_bufp);
1211         fraglen = SRAM_READ_FIELD_2(sc, rcs, ray_cmd_rx, c_len);
1212         RAY_DPRINTF(("ray%d: ray_rx frag index %d len %d bufp 0x%x ni %d\n",
1213                 sc->unit, i, fraglen, (int)bufp, ni));
1214
1215         if (fraglen + readlen > pktlen) {
1216             RAY_DPRINTF(("ray%d: ray_rx bad length current 0x%x pktlen 0x%x\n",
1217                     sc->unit, fraglen + readlen, pktlen));
1218             ifp->if_ierrors++;
1219             m_freem(m);
1220             m = 0;
1221             goto skip_read;
1222         }
1223         if ((i < RAY_RCS_FIRST) || (i > RAY_RCS_LAST)) {
1224             printf("ray%d: ray_rx bad rcs index 0x%x\n", sc->unit, i);
1225             ifp->if_ierrors++;
1226             m_freem(m);
1227             m = 0;
1228             goto skip_read;
1229         }
1230
1231         ebufp = bufp + fraglen;
1232         if (ebufp <= RAY_RX_END)
1233             ray_read_region(sc, bufp, dst, fraglen);
1234         else {
1235             ray_read_region(sc, bufp, dst, (tmplen = RAY_RX_END - bufp));
1236             ray_read_region(sc, RAY_RX_BASE, dst + tmplen, ebufp - RAY_RX_END);
1237         }
1238         dst += fraglen;
1239         readlen += fraglen;
1240     }
1241
1242 skip_read:
1243
1244     /*
1245      * Walk the chain again to free the rcss.
1246      */
1247     i = ni = first;
1248 RAY_DPRINTF(("ray%d: ray_rx cleaning rcs fragments ", sc->unit));
1249     while ((i = ni) && (i != RAY_CCS_LINK_NULL)) {
1250 RAY_DPRINTF(("%d ", i));
1251         rcs = RAY_CCS_ADDRESS(i);
1252         ni = SRAM_READ_FIELD_1(sc, rcs, ray_cmd_rx, c_nextfrag);
1253         SRAM_WRITE_FIELD_1(sc, rcs, ray_cmd, c_status, RAY_CCS_STATUS_FREE);
1254     }
1255 RAY_DPRINTF(("\n"));
1256
1257     if (!m)
1258         return;
1259
1260     RAY_DPRINTF(("ray%d: ray_rx got packet pktlen %d actual %d\n",
1261             sc->unit, pktlen, readlen));
1262     RAY_DMBUF_DUMP(sc, m, "ray_rx");
1263
1264     /*
1265      * Check the 802.11 packet type and obtain the .11 src address.
1266      *
1267      * XXX CTL and MGT packets will have separate functions,
1268      *     DATA dealt with here
1269      */
1270     header = mtod(m, struct ieee80211_header *);
1271     fc = header->i_fc[0];
1272     if ((fc & IEEE80211_FC0_VERSION_MASK) != IEEE80211_FC0_VERSION_0) {
1273         RAY_DPRINTF(("ray%d: header not version 0 fc 0x%x\n", sc->unit, fc));
1274         m_freem(m);
1275         return;
1276     }
1277     switch (fc & IEEE80211_FC0_TYPE_MASK) {
1278
1279         case IEEE80211_FC0_TYPE_MGT:
1280             printf("ray%d: ray_rx got a .11 MGT packet - why?\n", sc->unit);
1281             m_freem(m);
1282             return;
1283
1284         case IEEE80211_FC0_TYPE_CTL:
1285             printf("ray%d: ray_rx got a .11 CTL packet - why?\n", sc->unit);
1286             m_freem(m);
1287             return;
1288
1289         case IEEE80211_FC0_TYPE_DATA:
1290             RAY_DPRINTF(("ray%d: ray_rx got a .11 DATA packet\n", sc->unit));
1291             break;
1292
1293         default:
1294             printf("ray%d: ray_rx got a unknown .11 packet fc0 0x%x - why?\n",
1295                         sc->unit, fc);
1296             m_freem(m);
1297             return;
1298
1299     }
1300     fc = header->i_fc[1];
1301     switch (fc & IEEE80211_FC1_RCVFROM_MASK) {
1302
1303         case IEEE80211_FC1_RCVFROM_TERMINAL:
1304             src = header->i_addr2;
1305             RAY_DPRINTF(("ray%d: ray_rx got packet from station %6D\n",
1306                         sc->unit, src, ":"));
1307             break;
1308
1309         case IEEE80211_FC1_RCVFROM_AP:
1310             src = header->i_addr3;
1311             RAY_DPRINTF(("ray%d: ray_rx got packet from ap %6D\n",
1312                         sc->unit, src, ":"));
1313             break;
1314
1315         case IEEE80211_FC1_RCVFROM_AP2AP:
1316             RAY_DPRINTF(("ray%d: ray_rx saw packet between aps %6D %6D %6D\n",
1317                         sc->unit, header->i_addr1, ":", header->i_addr2, ":",
1318                         header->i_addr3, ":"));
1319             m_freem(m);
1320             return;
1321
1322         default:
1323             printf("ray%d: ray_rx packet type unknown fc1 0x%x - why?\n",
1324                 sc->unit, fc);
1325             m_freem(m);
1326             return;
1327     }
1328
1329     /*
1330      * XXX
1331      * 
1332      * Currently only support the Webgear encapsulation
1333      *          802.11  header <net/if_ieee80211.h>struct ieee80211_header
1334      *          802.3   header <net/ethernet.h>struct ether_header
1335      *          802.2   LLC header
1336      *          802.2   SNAP header
1337      *
1338      * We should support whatever packet types the following drivers have
1339      *          if_wi.c         FreeBSD, RFC1042
1340      *          if_ray.c        NetBSD  Webgear, RFC1042
1341      *          rayctl.c        Linux Webgear, RFC1042
1342      * also whatever we can divine from the NDC Access points and
1343      * Kanda's boxes.
1344      *
1345      * Most appear to have a RFC1042 translation. The incoming packet is
1346      *          802.11  header <net/if_ieee80211.h>struct ieee80211_header
1347      *          802.2   LLC header
1348      *          802.2   SNAP header
1349      *
1350      * This is translated to
1351      *          802.3   header <net/ethernet.h>struct ether_header
1352      *          802.2   LLC header
1353      *          802.2   SNAP header
1354      *
1355      * Linux seems to look at the SNAP org_code and do some translations
1356      * for IPX and APPLEARP on that. This just may be how Linux does IPX
1357      * and NETATALK. Need to see how FreeBSD does these.
1358      *
1359      * Translation should be selected via if_media stuff or link types.
1360      */
1361     switch (sc->translation) {
1362
1363         case SC_TRANSLATE_WEBGEAR:
1364             /* XXX error checking ? how? */
1365             eh = (struct ether_header *)(header + 1);
1366             m_adj(m, sizeof(struct ieee80211_header)+sizeof(struct ether_header));
1367             break;
1368
1369         default:
1370             printf("ray%d: ray_rx unknown translation type 0x%x - why?\n",
1371                         sc->unit, sc->translation);
1372             m_freem(m);
1373             return;
1374
1375     }
1376
1377 #if NBPFILTER > 0
1378     /* Handle BPF listeners. */
1379     if (ifp->if_bpf)
1380         bpf_mtap(ifp, m);
1381 #endif /* NBPFILTER */
1382 #if XXX
1383 if_wi.c - might be needed if we hear our own broadcasts in promiscuous mode
1384         if ((ifp->if_flags & IFF_PROMISC) &&
1385             (bcmp(eh->ether_shost, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN) &&
1386             (eh->ether_dhost[0] & 1) == 0)
1387         ) {
1388             m_freem(m);
1389             return;
1390         }
1391 #endif /* XXX */
1392
1393     ether_input(ifp, eh, m);
1394
1395     return;
1396 }
1397
1398 /*
1399  * Download start up structures to card.
1400  *
1401  * Part of ray_init, download, startjoin control flow.
1402  */
1403 static void
1404 ray_download_params (sc)
1405     struct ray_softc    *sc;
1406 {
1407     struct ray_mib_4    ray_mib_4_default;
1408     struct ray_mib_5    ray_mib_5_default;
1409
1410     RAY_DPRINTF(("ray%d: Downloading startup parameters\n", sc->unit));
1411     RAY_MAP_CM(sc);
1412
1413     RAY_DNET_DUMP(sc, " before we download them.");
1414 #if XXX
1415 netbsd
1416     ray_cmd_cancel(sc, SCP_UPD_STARTUP);
1417 #endif /* XXX */
1418
1419 #define MIB4(m)         ray_mib_4_default.##m
1420 #define MIB5(m)         ray_mib_5_default.##m
1421 #define PUT2(p, v)      \
1422     do { (p)[0] = ((v >> 8) & 0xff); (p)[1] = (v & 0xff); } while(0)
1423
1424      /*
1425       * Firmware version 4 defaults - see if_raymib.h for details
1426       */
1427      MIB4(mib_net_type)                 = sc->sc_net_type;
1428      MIB4(mib_ap_status)                = RAY_MIB_AP_STATUS_DEFAULT;
1429      strncpy(MIB4(mib_ssid), sc->sc_ssid, RAY_MAXSSIDLEN);
1430      MIB4(mib_scan_mode)                = RAY_MIB_SCAN_MODE_DEFAULT;
1431      MIB4(mib_apm_mode)                 = RAY_MIB_APM_MODE_DEFAULT;
1432      bcopy(sc->sc_station_addr, MIB4(mib_mac_addr), ETHER_ADDR_LEN);
1433 PUT2(MIB4(mib_frag_thresh),               RAY_MIB_FRAG_THRESH_DEFAULT);
1434 PUT2(MIB4(mib_dwell_time),                RAY_MIB_DWELL_TIME_V4);
1435 PUT2(MIB4(mib_beacon_period),             RAY_MIB_BEACON_PERIOD_V4);
1436      MIB4(mib_dtim_interval)            = RAY_MIB_DTIM_INTERVAL_DEFAULT;
1437      MIB4(mib_max_retry)                = RAY_MIB_MAX_RETRY_DEFAULT;
1438      MIB4(mib_ack_timo)                 = RAY_MIB_ACK_TIMO_DEFAULT;
1439      MIB4(mib_sifs)                     = RAY_MIB_SIFS_DEFAULT;
1440      MIB4(mib_difs)                     = RAY_MIB_DIFS_DEFAULT;
1441      MIB4(mib_pifs)                     = RAY_MIB_PIFS_V4;
1442 PUT2(MIB4(mib_rts_thresh),                RAY_MIB_RTS_THRESH_DEFAULT);
1443 PUT2(MIB4(mib_scan_dwell),                RAY_MIB_SCAN_DWELL_V4);
1444 PUT2(MIB4(mib_scan_max_dwell),            RAY_MIB_SCAN_MAX_DWELL_V4);
1445      MIB4(mib_assoc_timo)               = RAY_MIB_ASSOC_TIMO_DEFAULT;
1446      MIB4(mib_adhoc_scan_cycle)         = RAY_MIB_ADHOC_SCAN_CYCLE_DEFAULT;
1447      MIB4(mib_infra_scan_cycle)         = RAY_MIB_INFRA_SCAN_CYCLE_DEFAULT;
1448      MIB4(mib_infra_super_scan_cycle)   = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT;
1449      MIB4(mib_promisc)                  = RAY_MIB_PROMISC_DEFAULT;
1450 PUT2(MIB4(mib_uniq_word),                 RAY_MIB_UNIQ_WORD_DEFAULT);
1451      MIB4(mib_slot_time)                = RAY_MIB_SLOT_TIME_V4;
1452      MIB4(mib_roam_low_snr_thresh)      = RAY_MIB_ROAM_LOW_SNR_THRESH_DEFAULT;
1453      MIB4(mib_low_snr_count)            = RAY_MIB_LOW_SNR_COUNT_DEFAULT;
1454      MIB4(mib_infra_missed_beacon_count)= RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT;
1455      MIB4(mib_adhoc_missed_beacon_count)= RAY_MIB_ADHOC_MISSED_BEACON_COUNT_DEFAULT;
1456      MIB4(mib_country_code)             = RAY_MIB_COUNTRY_CODE_DEFAULT;
1457      MIB4(mib_hop_seq)                  = RAY_MIB_HOP_SEQ_DEFAULT;
1458      MIB4(mib_hop_seq_len)              = RAY_MIB_HOP_SEQ_LEN_V4;
1459      MIB4(mib_cw_max)                   = RAY_MIB_CW_MAX_V4;
1460      MIB4(mib_cw_min)                   = RAY_MIB_CW_MIN_V4;
1461      MIB4(mib_noise_filter_gain)        = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT;
1462      MIB4(mib_noise_limit_offset)       = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT;
1463      MIB4(mib_rssi_thresh_offset)       = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT;
1464      MIB4(mib_busy_thresh_offset)       = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT;
1465      MIB4(mib_sync_thresh)              = RAY_MIB_SYNC_THRESH_DEFAULT;
1466      MIB4(mib_test_mode)                = RAY_MIB_TEST_MODE_DEFAULT;
1467      MIB4(mib_test_min_chan)            = RAY_MIB_TEST_MIN_CHAN_DEFAULT;
1468      MIB4(mib_test_max_chan)            = RAY_MIB_TEST_MAX_CHAN_DEFAULT;
1469
1470      /*
1471       * Firmware version 5 defaults - see if_raymib.h for details
1472       */
1473      MIB5(mib_net_type)                 = sc->sc_net_type;
1474      MIB5(mib_ap_status)                = RAY_MIB_AP_STATUS_DEFAULT;
1475      strncpy(MIB5(mib_ssid), sc->sc_ssid, RAY_MAXSSIDLEN);
1476      MIB5(mib_scan_mode)                = RAY_MIB_SCAN_MODE_DEFAULT;
1477      MIB5(mib_apm_mode)                 = RAY_MIB_APM_MODE_DEFAULT;
1478      bcopy(sc->sc_station_addr, MIB5(mib_mac_addr), ETHER_ADDR_LEN);
1479 PUT2(MIB5(mib_frag_thresh),               RAY_MIB_FRAG_THRESH_DEFAULT);
1480 PUT2(MIB5(mib_dwell_time),                RAY_MIB_DWELL_TIME_V5);
1481 PUT2(MIB5(mib_beacon_period),             RAY_MIB_BEACON_PERIOD_V5);
1482      MIB5(mib_dtim_interval)            = RAY_MIB_DTIM_INTERVAL_DEFAULT;
1483      MIB5(mib_max_retry)                = RAY_MIB_MAX_RETRY_DEFAULT;
1484      MIB5(mib_ack_timo)                 = RAY_MIB_ACK_TIMO_DEFAULT;
1485      MIB5(mib_sifs)                     = RAY_MIB_SIFS_DEFAULT;
1486      MIB5(mib_difs)                     = RAY_MIB_DIFS_DEFAULT;
1487      MIB5(mib_pifs)                     = RAY_MIB_PIFS_V5;
1488 PUT2(MIB5(mib_rts_thresh),                RAY_MIB_RTS_THRESH_DEFAULT);
1489 PUT2(MIB5(mib_scan_dwell),                RAY_MIB_SCAN_DWELL_V5);
1490 PUT2(MIB5(mib_scan_max_dwell),            RAY_MIB_SCAN_MAX_DWELL_V5);
1491      MIB5(mib_assoc_timo)               = RAY_MIB_ASSOC_TIMO_DEFAULT;
1492      MIB5(mib_adhoc_scan_cycle)         = RAY_MIB_ADHOC_SCAN_CYCLE_DEFAULT;
1493      MIB5(mib_infra_scan_cycle)         = RAY_MIB_INFRA_SCAN_CYCLE_DEFAULT;
1494      MIB5(mib_infra_super_scan_cycle)   = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT;
1495      MIB5(mib_promisc)                  = RAY_MIB_PROMISC_DEFAULT;
1496 PUT2(MIB5(mib_uniq_word),                 RAY_MIB_UNIQ_WORD_DEFAULT);
1497      MIB5(mib_slot_time)                = RAY_MIB_SLOT_TIME_V5;
1498      MIB5(mib_roam_low_snr_thresh)      = RAY_MIB_ROAM_LOW_SNR_THRESH_DEFAULT;
1499      MIB5(mib_low_snr_count)            = RAY_MIB_LOW_SNR_COUNT_DEFAULT;
1500      MIB5(mib_infra_missed_beacon_count)= RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT;
1501      MIB5(mib_adhoc_missed_beacon_count)= RAY_MIB_ADHOC_MISSED_BEACON_COUNT_DEFAULT;
1502      MIB5(mib_country_code)             = RAY_MIB_COUNTRY_CODE_DEFAULT;
1503      MIB5(mib_hop_seq)                  = RAY_MIB_HOP_SEQ_DEFAULT;
1504      MIB5(mib_hop_seq_len)              = RAY_MIB_HOP_SEQ_LEN_V5;
1505 PUT2(MIB5(mib_cw_max),                    RAY_MIB_CW_MAX_V5);
1506 PUT2(MIB5(mib_cw_min),                    RAY_MIB_CW_MIN_V5);
1507      MIB5(mib_noise_filter_gain)        = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT;
1508      MIB5(mib_noise_limit_offset)       = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT;
1509      MIB5(mib_rssi_thresh_offset)       = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT;
1510      MIB5(mib_busy_thresh_offset)       = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT;
1511      MIB5(mib_sync_thresh)              = RAY_MIB_SYNC_THRESH_DEFAULT;
1512      MIB5(mib_test_mode)                = RAY_MIB_TEST_MODE_DEFAULT;
1513      MIB5(mib_test_min_chan)            = RAY_MIB_TEST_MIN_CHAN_DEFAULT;
1514      MIB5(mib_test_max_chan)            = RAY_MIB_TEST_MAX_CHAN_DEFAULT;
1515      MIB5(mib_allow_probe_resp)         = RAY_MIB_ALLOW_PROBE_RESP_DEFAULT;
1516      MIB5(mib_privacy_must_start)       = RAY_MIB_PRIVACY_MUST_START_DEFAULT;
1517      MIB5(mib_privacy_can_join)         = sc->sc_priv_start;
1518      MIB5(mib_basic_rate_set[0])        = sc->sc_priv_join;
1519
1520     if (!RAY_ECF_READY(sc))
1521         panic("ray%d: ray_download_params something is already happening\n",
1522                 sc->unit);
1523
1524     if (sc->sc_version == RAY_ECFS_BUILD_4)
1525         ray_write_region(sc, RAY_HOST_TO_ECF_BASE,
1526                          &ray_mib_4_default, sizeof(ray_mib_4_default));
1527     else
1528         ray_write_region(sc, RAY_HOST_TO_ECF_BASE,
1529                          &ray_mib_5_default, sizeof(ray_mib_5_default));
1530
1531 /* XXX
1532  * NetBSD
1533  * hand expanding ray_simple_cmd
1534  * we dont do any of the clever timeout stuff yet (i.e. ray_cmd_ran) just
1535  * simple check
1536  *
1537  *      if (!ray_simple_cmd(sc, RAY_CMD_START_PARAMS, SCP_UPD_STARTUP))
1538  *          panic("ray_download_params issue");
1539  *
1540  *      ray_simple_cmd ==
1541  *          ray_alloc_ccs(sc, &ccs, cmd, track) &&
1542  *          ray_issue_cmd(sc, ccs, track));
1543  *
1544  */
1545     /*
1546      * Get a free command ccs and issue the command - there is nothing
1547      * to fill in for a START_PARAMS command. The start parameters
1548      * command just gets serviced, so we use a timeout to complete the
1549      * sequence.
1550      */
1551     if (!ray_alloc_ccs(sc, &sc->sc_ccs, RAY_CMD_START_PARAMS, SCP_UPD_STARTUP))
1552         panic("ray%d: ray_download_params can't get a CCS\n", sc->unit);
1553
1554     if (!ray_issue_cmd(sc, sc->sc_ccs, SCP_UPD_STARTUP))
1555         panic("ray%d: ray_download_params can't issue command\n", sc->unit);
1556
1557     sc->timerh = timeout(ray_download_timo, sc, RAY_CCS_TIMEOUT);
1558
1559     RAY_DPRINTF(("ray%d: Download now awaiting timeout\n", sc->unit));
1560
1561     return;
1562 }
1563
1564 /*
1565  * Download timeout routine.
1566  *
1567  * Part of ray_init, download, start_join control flow.
1568  */
1569 static void
1570 ray_download_timo (xsc)
1571     void                *xsc;
1572 {
1573     struct ray_softc    *sc = xsc;
1574     size_t              ccs;
1575     u_int8_t            status, cmd;
1576
1577     RAY_DPRINTF(("ray%d: ray_download_timo\n", sc->unit));
1578     RAY_MAP_CM(sc);
1579
1580     status = SRAM_READ_FIELD_1(sc, sc->sc_ccs, ray_cmd, c_status);
1581     cmd = SRAM_READ_FIELD_1(sc, sc->sc_ccs, ray_cmd, c_cmd);
1582     RAY_DPRINTF(("ray%d: check rayidx %d ccs 0x%x cmd 0x%x stat %d\n",
1583                 sc->unit, RAY_CCS_INDEX(sc->sc_ccs), sc->sc_ccs, cmd, status));
1584     if ((cmd != RAY_CMD_START_PARAMS) || (status != RAY_CCS_STATUS_FREE))
1585         printf("ray%d: Download ccs odd cmd = 0x%02x, status = 0x%02x",
1586                 sc->unit, cmd, status);
1587         /*XXX so what do we do? reset or retry? */
1588         /*XXX this gets triggered when we try and re-reset the ipaddress 
1589          *    ray_init gets called */
1590
1591     /*
1592      * If the card is still busy, re-schedule ourself
1593      */
1594     if (status == RAY_CCS_STATUS_BUSY) {
1595         RAY_DPRINTF(("ray%d: ray_download_timo - still busy, see you soon\n",
1596                 sc->unit));
1597         sc->timerh = timeout(ray_download_timo, sc, RAY_CCS_TIMEOUT);
1598     }
1599
1600     /* Clear the ccs */
1601     ray_free_ccs(sc, sc->sc_ccs);
1602     sc->sc_ccs = RAY_CCS_LAST + 1;
1603
1604 #if XXX
1605 NetBSD clear IFF_OACTIVE at this point
1606 #endif
1607     /*
1608      * Grab a ccs and don't bother updating the network parameters.
1609      * Issue the start/join command and we get interrupted back.
1610      */
1611     if (sc->sc_net_type == RAY_MIB_NET_TYPE_ADHOC)
1612             cmd = RAY_CMD_START_NET;
1613     else
1614             cmd = RAY_CMD_JOIN_NET;
1615
1616     if (!ray_alloc_ccs(sc, &ccs, cmd, SCP_UPD_STARTJOIN))
1617         panic("ray%d: ray_download_timo can't get a CCS to start/join net\n",
1618                 sc->unit);
1619
1620     SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_upd_param, 0);
1621
1622     if (!ray_issue_cmd(sc, ccs, SCP_UPD_STARTJOIN))
1623         panic("ray%d: ray_download_timo can't issue start/join\n", sc->unit);
1624
1625 #if RAY_NEED_STARTJOIN_TIMO
1626     sc->sj_timerh = timeout(ray_start_join_timo, sc, RAY_CCS_TIMEOUT);
1627 #endif /* RAY_NEED_STARTJOIN_TIMO */
1628
1629     RAY_DPRINTF(("ray%d: Start-join awaiting interrupt/timeout\n", sc->unit));
1630
1631     return;
1632 }
1633
1634 /*
1635  * Complete start or join command.
1636  *
1637  * Part of ray_init, download, start_join control flow.
1638  */
1639 static void
1640 ray_start_join_done (sc, ccs, status)
1641     struct ray_softc    *sc;
1642     size_t              ccs;
1643     u_int8_t            status;
1644 {
1645     u_int8_t            o_net_type;
1646
1647     RAY_DPRINTF(("ray%d: ray_start_join_done\n", sc->unit));
1648     RAY_MAP_CM(sc);
1649
1650 #if RAY_NEED_STARTJOIN_TIMO
1651     untimeout(ray_start_join_timo, sc, sc->sj_timerh);
1652 #endif /* RAY_NEED_STARTJOIN_TIMO */
1653
1654 #if XXX_TRACKING
1655     ray_cmd_done(sc, SCP_UPD_STARTJOIN);
1656 #endif /* XXX_TRACKING */
1657
1658     switch (status) {
1659
1660         case RAY_CCS_STATUS_FREE:
1661         case RAY_CCS_STATUS_BUSY:
1662             printf("ray%d: ray_start_join_done status is FREE/BUSY - why?\n",
1663                         sc->unit);
1664             break;
1665
1666         case RAY_CCS_STATUS_COMPLETE:
1667             break;
1668
1669         case RAY_CCS_STATUS_FAIL:
1670             printf("ray%d: ray_start_join_done status is FAIL - why?\n",
1671                         sc->unit);
1672 #if XXX
1673             restart ray_start_join sequence 
1674             may need to split download_done for this
1675 #endif
1676             break;
1677
1678         default:
1679             printf("ray%d: ray_start_join_done unknown status 0x%x\n",
1680                         sc->unit, status);
1681             break;
1682     }
1683
1684     /*
1685      * If the command completed correctly, get a few network parameters
1686      * from the ccs and active the nextwork.
1687      */
1688     if (status == RAY_CCS_STATUS_COMPLETE) {
1689
1690         ray_read_region(sc, ccs, &sc->sc_cnet_1, sizeof(struct ray_cmd_net));
1691
1692         /* adjust values for buggy build 4 */
1693         if (sc->sc_def_txrate == 0x55)
1694                 sc->sc_def_txrate = RAY_MIB_BASIC_RATE_SET_1500K;
1695         if (sc->sc_encrypt == 0x55)
1696                 sc->sc_encrypt = 0;
1697
1698         /* card is telling us to update the network parameters */
1699         if (sc->sc_upd_param) {
1700             RAY_DPRINTF(("ray%d: ray_start_join_done card request update of network parameters\n", sc->unit));
1701             o_net_type = sc->sc_net_type;
1702             ray_read_region(sc, RAY_HOST_TO_ECF_BASE,
1703                 &sc->sc_cnet_2, sizeof(struct ray_net_params));
1704             if (sc->sc_net_type != o_net_type) {
1705                 printf("ray%d: ray_start_join_done card request change of network type - why?\n", sc->unit);
1706 #if XXX
1707     restart ray_start_join sequence ?
1708     may need to split download_timo for this
1709 #endif
1710             }
1711         }
1712         RAY_DNET_DUMP(sc, " after start/join network completed.");
1713
1714 #if XXX
1715         netbsd has already cleared OACTIVE so packets may be queued
1716         need to know interrupt level before calling ray_start
1717
1718         is ray_intr_start === ray_start?
1719                 yup apart from groking the sc from the ifp
1720
1721         /* network is now active */
1722         ray_cmd_schedule(sc, SCP_UPD_MCAST|SCP_UPD_PROMISC);
1723         if (cmd == RAY_CMD_JOIN_NET)
1724                 return (ray_start_assoc);
1725         else {
1726                 sc->sc_havenet = 1;
1727                 return (ray_intr_start);
1728         }
1729 #endif
1730
1731     }
1732
1733     return;
1734 };
1735
1736 #if RAY_NEED_STARTJOIN_TIMO
1737 /*
1738  * Back stop catcher for start_join command. The NetBSD driver
1739  * suggests that they need it to catch a bug in the firmware or the
1740  * parameters they use - they are not sure. I'll just panic as I seem
1741  * to get interrupts back fine and I have version 4 firmware.
1742  */
1743 static void
1744 ray_start_join_timo (xsc)
1745     void                *xsc;
1746 {
1747     struct ray_softc    *sc = xsc;
1748
1749     RAY_DPRINTF(("ray%d: ray_start_join_timo\n", sc->unit));
1750     RAY_MAP_CM(sc);
1751
1752     panic("ray%d: ray-start_join_timo occured\n", sc->unit);
1753
1754     return;
1755 }
1756 #endif /* RAY_NEED_STARTJOIN_TIMO */
1757
1758 /*
1759  * Obtain a free ccs buffer.
1760  *
1761  * Returns 1 and in `ccsp' the bus offset of the free ccs 
1762  * or 0 if none are free
1763  *
1764  * If `track' is not zero, handles tracking this command
1765  * possibly indicating a callback is needed and setting a timeout
1766  * also if ECF isn't ready we terminate earlier to avoid overhead.
1767  *
1768  * This routine is only used for commands
1769  */
1770 static int
1771 ray_alloc_ccs (sc, ccsp, cmd, track)
1772     struct      ray_softc *sc;
1773     size_t      *ccsp;
1774     u_int       cmd, track;
1775 {
1776     size_t      ccs;
1777     u_int       i;
1778
1779     RAY_DPRINTF(("ray%d: ray_alloc_ccs for cmd %d\n", sc->unit, cmd));
1780     RAY_MAP_CM(sc);
1781
1782 #if XXX
1783         /* for tracked commands, if not ready just set pending */
1784         if (track && !RAY_ECF_READY(sc)) {
1785                 ray_cmd_schedule(sc, track);
1786                 return (0);
1787         }
1788 #endif /* XXX */
1789
1790     for (i = RAY_CCS_CMD_FIRST; i <= RAY_CCS_CMD_LAST; i++) {
1791         /* probe here to make the card go */
1792         (void)SRAM_READ_FIELD_1(sc, RAY_CCS_ADDRESS(i), ray_cmd, c_status);
1793         if (!sc->sc_ccsinuse[i])
1794             break;
1795     }
1796     if (i > RAY_CCS_CMD_LAST) {
1797 #if XXX
1798         if (track)
1799                 ray_cmd_schedule(sc, track);
1800 #endif /* XXX */
1801         return (0);
1802     }
1803     sc->sc_ccsinuse[i] = 1;
1804     ccs = RAY_CCS_ADDRESS(i);
1805     SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_BUSY);
1806     SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_cmd, cmd);
1807     SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_link, RAY_CCS_LINK_NULL);
1808
1809     *ccsp = ccs;
1810     return (1);
1811 }
1812
1813 /*
1814  * Free up a ccs/cmd and return the old status.
1815  * This routine is only used for commands.
1816  */
1817 static u_int8_t
1818 ray_free_ccs (sc, ccs)
1819     struct      ray_softc *sc;
1820     size_t      ccs;
1821 {
1822     u_int8_t    stat;
1823
1824     RAY_DPRINTF(("ray%d: free_ccs 0x%02x\n", sc->unit, RAY_CCS_INDEX(ccs)));
1825     RAY_MAP_CM(sc);
1826
1827     stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status);
1828     SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_FREE);
1829     if (ccs <= RAY_CCS_ADDRESS(RAY_CCS_LAST))
1830             sc->sc_ccsinuse[RAY_CCS_INDEX(ccs)] = 0;
1831
1832     return (stat);
1833 }
1834
1835 /*
1836  * Issue a command by writing the mailbox and tickling the card.
1837  * Only used for commands not transmitted packets.
1838  */
1839 static int
1840 ray_issue_cmd(sc, ccs, track)
1841     struct      ray_softc *sc;
1842     size_t      ccs;
1843     u_int       track;
1844 {
1845     u_int       i;
1846
1847     RAY_DPRINTF(("ray%d: ray_cmd_issue, track = 0x%x\n", sc->unit, track));
1848     RAY_MAP_CM(sc);
1849
1850     /*
1851      * XXX other drivers did this, but I think 
1852      * what we really want to do is just make sure we don't
1853      * get here or that spinning is ok
1854      */
1855     i = 0;
1856     while (!RAY_ECF_READY(sc))
1857         if (++i > 50) {
1858             ray_free_ccs(sc, ccs);
1859 #if XXX_TRACKING
1860             if (track)
1861                 ray_cmd_schedule(sc, track);
1862 #endif /* XXX_TRACKING */
1863             return (0);
1864         }
1865
1866     SRAM_WRITE_1(sc, RAY_SCB_CCSI, RAY_CCS_INDEX(ccs));
1867     RAY_ECF_START_CMD(sc);
1868 #if XXX_TRACKING
1869     ray_cmd_ran(sc, track);
1870 #endif /* XXX_TRACKING */
1871
1872     return (1);
1873 }
1874
1875 #if RAY_DEBUG > 10
1876 static void
1877 ray_dump_mbuf(sc, m, s)
1878     struct ray_softc    *sc;
1879     struct mbuf         *m;
1880     char                *s;
1881 {
1882     u_int8_t            *d, *ed;
1883     u_int               i;
1884     char                p[17];
1885
1886     printf("ray%d: %s mbuf dump:", sc->unit, s);
1887     i = 0;
1888     bzero(p, 17);
1889     for (; m; m = m->m_next) {
1890         d = mtod(m, u_int8_t *);
1891         ed = d + m->m_len;
1892
1893         for (; d < ed; i++, d++) {
1894             if ((i % 16) == 0) {
1895                 printf("  %s\n\t", p);
1896             } else if ((i % 8) == 0)
1897                 printf("  ");
1898             printf(" %02x", *d);
1899             p[i % 16] = ((*d >= 0x20) && (*d < 0x80)) ? *d : '.';
1900         }
1901     }
1902     if ((i - 1) % 16)
1903         printf("%s\n", p);
1904 }
1905 #endif /* RAY_DEBUG > 10 */
1906
1907 /*
1908  * Routines to read from/write to the attribute memory.
1909  *
1910  * Taken from if_xe.c.
1911  *
1912  * Until there is a real way of accessing the attribute memory from a driver
1913  * these have to stay.
1914  *
1915  * The hack to use the crdread/crdwrite device functions causes the attribute
1916  * memory to be remapped into the controller and looses the mapping of
1917  * the common memory.
1918  *
1919  * We cheat by using PIOCSMEM and assume that the common memory window
1920  * is in window 0 of the card structure.
1921  *
1922  * Also
1923  *      pccard/pcic.c/crdread does mark the unmapped window as inactive
1924  *      pccard/pccard.c/map_mem toggles the mapping of a window on
1925  *      successive calls
1926  *
1927  */
1928 #if RAY_NEED_CM_REMAPPING
1929 static void
1930 ray_attr_getmap (struct ray_softc *sc)
1931 {
1932     struct ucred uc;
1933     struct pcred pc;
1934     struct proc p;
1935
1936     RAY_DPRINTF(("ray%d: attempting to get map for common memory\n", sc->unit));
1937
1938     sc->md.window = 0;
1939
1940     p.p_cred = &pc;
1941     p.p_cred->pc_ucred = &uc;
1942     p.p_cred->pc_ucred->cr_uid = 0;
1943
1944     RAY_DPRINTF(("  ioctl returns 0x%0x\n", cdevsw[CARD_MAJOR]->d_ioctl(makedev(CARD_MAJOR, sc->slotnum), PIOCGMEM, (caddr_t)&sc->md, 0, &p)));
1945
1946     RAY_DPRINTF(("  flags 0x%02x, start 0x%p, size 0x%08x, card address 0x%lx\n", sc->md.flags, sc->md.start, sc->md.size, sc->md.card));
1947
1948     return;
1949 }
1950
1951 static void
1952 ray_attr_cm (struct ray_softc *sc)
1953 {
1954     struct ucred uc;
1955     struct pcred pc;
1956     struct proc p;
1957
1958     RAY_DPRINTF(("ray%d: attempting to remap common memory\n", sc->unit));
1959
1960     p.p_cred = &pc;
1961     p.p_cred->pc_ucred = &uc;
1962     p.p_cred->pc_ucred->cr_uid = 0;
1963
1964     cdevsw[CARD_MAJOR]->d_ioctl(makedev(CARD_MAJOR, sc->slotnum), PIOCSMEM, (caddr_t)&sc->md, 0, &p);
1965
1966     return;
1967 }
1968 #endif /* RAY_NEED_CM_REMAPPING */
1969
1970 static int
1971 ray_attr_write (struct ray_softc *sc, off_t offset, u_int8_t byte)
1972 {
1973   struct iovec iov;
1974   struct uio uios;
1975   int err;
1976
1977   iov.iov_base = &byte;
1978   iov.iov_len = sizeof(byte);
1979
1980   uios.uio_iov = &iov;
1981   uios.uio_iovcnt = 1;
1982   uios.uio_offset = offset;
1983   uios.uio_resid = sizeof(byte);
1984   uios.uio_segflg = UIO_SYSSPACE;
1985   uios.uio_rw = UIO_WRITE;
1986   uios.uio_procp = 0;
1987
1988   err = cdevsw[CARD_MAJOR]->d_write(makedev(CARD_MAJOR, sc->slotnum), &uios, 0);
1989
1990 #if RAY_NEED_CM_REMAPPING
1991   ray_attr_cm(sc);
1992 #endif /* RAY_NEED_CM_REMAPPING */
1993
1994   return(err);
1995 }
1996
1997 static int
1998 ray_attr_read (struct ray_softc *sc, off_t offset, u_int8_t *buf, int size)
1999 {
2000   struct iovec iov;
2001   struct uio uios;
2002   int err;
2003
2004   iov.iov_base = buf;
2005   iov.iov_len = size;
2006
2007   uios.uio_iov = &iov;
2008   uios.uio_iovcnt = 1;
2009   uios.uio_offset = offset;
2010   uios.uio_resid = size;
2011   uios.uio_segflg = UIO_SYSSPACE;
2012   uios.uio_rw = UIO_READ;
2013   uios.uio_procp = 0;
2014
2015   err =  cdevsw[CARD_MAJOR]->d_read(makedev(CARD_MAJOR, sc->slotnum), &uios, 0);
2016
2017 #if RAY_NEED_CM_REMAPPING
2018   ray_attr_cm(sc);
2019 #endif /* RAY_NEED_CM_REMAPPING */
2020
2021   return(err);
2022 }
2023
2024 static u_int8_t
2025 ray_read_reg (sc, reg)
2026     struct ray_softc    *sc;
2027     off_t               reg;
2028 {
2029     u_int8_t            byte;
2030
2031     ray_attr_read(sc, reg, &byte, 1);
2032
2033     return(byte);
2034 }
2035
2036 #if XXX
2037 /*
2038  * Could be replaced by the following macro
2039  * RAY_ECF_READY(sc)    (!(REG_READ(sc, RAY_ECFIR) & RAY_ECFIR_IRQ))
2040  * where reg_read is a suitable macro to read a byte in the attribute memory.
2041  */
2042 static int
2043 ray_ecf_ready(struct ray_softc *sc)
2044 {
2045     u_int8_t    byte;
2046
2047     ray_attr_read(sc, RAY_ECFIR, &byte, 1);
2048
2049     return (!(byte & RAY_ECFIR_IRQ));
2050 }
2051
2052 /*
2053  * Could be replaced by the following macro
2054  * RAY_HCS_INTR(sc)     (REG_READ(sc, RAY_HCSIR) & RAY_HCSIR_IRQ)
2055  * where reg_read is a suitable macro to read a byte in the attribute memory.
2056  */
2057 static int
2058 ray_hcs_intr(struct ray_softc *sc)
2059 {
2060     u_int8_t    byte;
2061
2062     ray_attr_read(sc, RAY_HCSIR, &byte, 1);
2063
2064     return (byte & RAY_HCSIR_IRQ);
2065 }
2066 #endif
2067
2068 #endif /* NRAY */