if_ray.c revision 1.3 1 /* $NetBSD: if_ray.c,v 1.3 2000/01/24 22:05:53 chopps Exp $ */
2 /*
3 * Copyright (c) 2000 Christian E. Hopps
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the names of any co-contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 /*
32 * Driver for the Raylink (Raytheon) / WebGear IEEE 802.11 (FH) WLANs
33 *
34 * 2-way communication with the card is through command structures
35 * stored in shared ram. To communicate with the card a free
36 * command structure is filled in and then the card is interrupted.
37 * The card does the same with a different set of command structures.
38 * Only one command can be processed at a time. This is indicated
39 * by the interrupt having not been cleared since it was last set.
40 * The bit is cleared when the command has been processed (although
41 * it may not yet be complete).
42 *
43 * This driver was only tested with the Aviator 2.4 wireless
44 * The author didn't have the pro version or raylink to test
45 * with.
46 *
47 * N.B. Its unclear yet whether the Aviator 2.4 cards interoperate
48 * with other 802.11 FH 2Mbps cards, since this was also untested.
49 * Given the nature of the buggy build 4 firmware there may be problems.
50 */
51
52 #include "opt_inet.h"
53 #include "bpfilter.h"
54
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/mbuf.h>
58 #include <sys/socket.h>
59 #include <sys/ioctl.h>
60 #include <sys/errno.h>
61 #include <sys/device.h>
62 #include <sys/kernel.h>
63 #include <sys/proc.h>
64
65 #include <net/if.h>
66 #include <net/if_dl.h>
67 #include <net/if_ether.h>
68 #include <net/if_media.h>
69 #include <net/if_llc.h>
70 #include <net/if_ieee80211.h>
71 #include <net/if_media.h>
72
73 #ifdef INET
74 #include <netinet/in.h>
75 #include <netinet/in_systm.h>
76 #include <netinet/in_var.h>
77 #include <netinet/ip.h>
78 #include <netinet/if_inarp.h>
79 #endif
80
81 #if NBPFILTER > 0
82 #include <net/bpf.h>
83 #include <net/bpfdesc.h>
84 #endif
85
86 #include <machine/cpu.h>
87 #include <machine/bus.h>
88 #include <machine/intr.h>
89
90 #include <dev/pcmcia/pcmciareg.h>
91 #include <dev/pcmcia/pcmciavar.h>
92 #include <dev/pcmcia/pcmciadevs.h>
93
94 #include <dev/pcmcia/if_rayreg.h>
95
96 #define RAY_DEBUG
97
98 #ifndef RAY_PID_COUNTRY_CODE_DEFAULT
99 #define RAY_PID_COUNTRY_CODE_DEFAULT RAY_PID_COUNTRY_CODE_USA
100 #endif
101
102 /* amount of time to poll for non-return of certain command status */
103 #ifndef RAY_CHECK_CCS_TIMEOUT
104 #define RAY_CHECK_CCS_TIMEOUT (hz / 2)
105 #endif
106
107 /* ammount of time to consider start/join failed */
108 #ifndef RAY_START_TIMEOUT
109 #define RAY_START_TIMEOUT (30 * hz)
110 #endif
111
112 /*
113 * if a command cannot execute because device is busy try later
114 * this is also done after interrupts and other command timeouts
115 * so we can use a large value safely.
116 */
117 #ifndef RAY_CHECK_SCHED_TIMEOUT
118 #define RAY_CHECK_SCHED_TIMEOUT (hz) /* XXX 5 */
119 #endif
120
121 #ifndef RAY_MODE_DEFAULT
122 #define RAY_MODE_DEFAULT SC_MODE_ADHOC
123 #endif
124
125 #ifndef RAY_DEF_NWID
126 #define RAY_DEF_NWID "NETWORK_NAME"
127 #endif
128
129 /*
130 * the number of times the HW is reset in 30s before disabling
131 * this is needed becuase resets take ~2s and currently pcmcia
132 * spins for the reset
133 */
134 #ifndef RAY_MAX_RESETS
135 #define RAY_MAX_RESETS 3
136 #endif
137
138 /*
139 * Types
140 */
141
142 struct ray_softc {
143 struct device sc_dev;
144 struct ethercom sc_ec;
145 struct ifmedia sc_media;
146
147 struct pcmcia_function *sc_pf;
148 struct pcmcia_mem_handle sc_mem;
149 int sc_window;
150 #if 0
151 struct pcmcia_mem_handle sc_amem;
152 int sc_awindow;
153 #endif
154 void *sc_ih;
155 void *sc_sdhook;
156 int sc_resetloop;
157
158 struct ray_ecf_startup sc_ecf_startup;
159 struct ray_startup_params_head sc_startup;
160 union {
161 struct ray_startup_params_tail_5 u_params_5;
162 struct ray_startup_params_tail_4 u_params_4;
163 } sc_u;
164
165 u_int8_t sc_ccsinuse[64]; /* ccs in use -- not for tx */
166 u_int sc_txfree; /* a free count for efficiency */
167
168 u_int8_t sc_bssid[ETHER_ADDR_LEN]; /* current net values */
169 u_int8_t sc_cnwid[IEEE80211_NWID_LEN]; /* last nwid */
170 u_int8_t sc_dnwid[IEEE80211_NWID_LEN]; /* desired nwid */
171 u_int8_t sc_omode; /* old operating mode SC_MODE_xx */
172 u_int8_t sc_mode; /* current operating mode SC_MODE_xx */
173 u_int8_t sc_countrycode; /* current country code */
174 u_int8_t sc_dcountrycode; /* desired country code */
175 int sc_havenet; /* true if we have aquired a network */
176 bus_size_t sc_txpad; /* tib size plus "phy" size */
177 u_int8_t sc_deftxrate; /* default transfer rate */
178 u_int8_t sc_encrypt;
179
180
181 int sc_promisc; /* current set value */
182 int sc_running; /* things we are doing */
183 int sc_scheduled; /* things we need to do */
184 int sc_timoneed; /* set if timeout is sched */
185 int sc_timocheck; /* set if timeout is sched */
186 bus_size_t sc_startccs; /* ccs of start/join */
187 u_int sc_startcmd; /* cmd (start | join) */
188
189 int sc_checkcounters;
190 u_int64_t sc_rxoverflow;
191 u_int64_t sc_rxcksum;
192 u_int64_t sc_rxhcksum;
193 u_int8_t sc_rxnoise;
194
195 /* use to return values to the user */
196 struct ray_param_req *sc_repreq;
197 struct ray_param_req *sc_updreq;
198 };
199 #define sc_memt sc_mem.memt
200 #define sc_memh sc_mem.memh
201 #define sc_ccrt sc_pf->pf_ccrt
202 #define sc_ccrh sc_pf->pf_ccrh
203 #define sc_startup_4 sc_u.u_params_4
204 #define sc_startup_5 sc_u.u_params_5
205 #define sc_version sc_ecf_startup.e_fw_build_string
206 #define sc_tibsize sc_ecf_startup.e_tib_size
207 #define sc_if sc_ec.ec_if
208 #define sc_xname sc_dev.dv_xname
209
210 /* modes of operation */
211 #define SC_MODE_ADHOC 0 /* ad-hoc mode */
212 #define SC_MODE_INFRA 1 /* infrastructure mode */
213
214 /* commands -- priority given to LSB */
215 #define SCP_FIRST 0x0001
216 #define SCP_UPDATESUBCMD 0x0001
217 #define SCP_STARTASSOC 0x0002
218 #define SCP_REPORTPARAMS 0x0004
219 #define SCP_IFSTART 0x0008
220
221 /* update sub commands -- issues are serialized priority to LSB */
222 #define SCP_UPD_FIRST 0x0100
223 #define SCP_UPD_STARTUP 0x0100
224 #define SCP_UPD_STARTJOIN 0x0200
225 #define SCP_UPD_PROMISC 0x0400
226 #define SCP_UPD_MCAST 0x0800
227 #define SCP_UPD_UPDATEPARAMS 0x1000
228 #define SCP_UPD_SHIFT 8
229 #define SCP_UPD_MASK 0xff00
230
231 /* these command (a subset of the update set) require timeout checking */
232 #define SCP_TIMOCHECK_CMD_MASK \
233 (SCP_UPD_UPDATEPARAMS | SCP_UPD_STARTUP | SCP_UPD_MCAST | \
234 SCP_UPD_PROMISC)
235
236
237 #define IFM_ADHOC \
238 IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_FH2, IFM_IEEE80211_ADHOC, 0)
239 #define IFM_INFRA \
240 IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_FH2, 0, 0)
241
242 typedef void (*ray_cmd_func_t)(struct ray_softc *);
243
244 #define SC_BUILD_5 0x5
245 #define SC_BUILD_4 0x55
246
247
248 static int ray_alloc_ccs __P((struct ray_softc *, bus_size_t *, u_int, u_int));
249 static bus_size_t ray_fill_in_tx_ccs __P((struct ray_softc *, size_t,
250 u_int, u_int));
251 static void ray_attach __P((struct device *, struct device *, void *));
252 static ray_cmd_func_t ray_ccs_done __P((struct ray_softc *, bus_size_t));
253 static void ray_check_ccs __P((void *));
254 static void ray_check_scheduled __P((void *));
255 static void ray_cmd_cancel __P((struct ray_softc *, int));
256 static void ray_cmd_schedule __P((struct ray_softc *, int));
257 static void ray_cmd_ran __P((struct ray_softc *, int));
258 static int ray_cmd_is_running __P((struct ray_softc *, int));
259 static int ray_cmd_is_scheduled __P((struct ray_softc *, int));
260 static void ray_cmd_done __P((struct ray_softc *, int));
261 static int ray_detach __P((struct device *, int));
262 static void ray_disable __P((struct ray_softc *));
263 static void ray_download_params __P((struct ray_softc *));
264 static int ray_enable __P((struct ray_softc *));
265 static u_int ray_find_free_tx_ccs __P((struct ray_softc *, u_int));
266 static u_int8_t ray_free_ccs __P((struct ray_softc *, bus_size_t));
267 static void ray_free_ccs_chain __P((struct ray_softc *, u_int));
268 static void ray_if_start __P((struct ifnet *));
269 static int ray_init __P((struct ray_softc *));
270 static int ray_intr __P((void *));
271 static void ray_intr_start __P((struct ray_softc *));
272 static int ray_ioctl __P((struct ifnet *, u_long, caddr_t));
273 static int ray_issue_cmd __P((struct ray_softc *, bus_size_t, u_int));
274 static int ray_match __P((struct device *, struct cfdata *, void *));
275 static int ray_media_change __P((struct ifnet *));
276 static void ray_media_status __P((struct ifnet *, struct ifmediareq *));
277 static ray_cmd_func_t ray_rccs_intr __P((struct ray_softc *, bus_size_t));
278 static void ray_read_region __P((struct ray_softc *, bus_size_t,void *,size_t));
279 static void ray_recv __P((struct ray_softc *, bus_size_t));
280 static void ray_report_params __P((struct ray_softc *));
281 static void ray_reset __P((struct ray_softc *));
282 static void ray_reset_resetloop __P((void *));
283 static void ray_set_pending __P((struct ray_softc *, u_int));
284 static void ray_shutdown __P((void *));
285 static int ray_simple_cmd __P((struct ray_softc *, u_int, u_int));
286 static void ray_start_assoc __P((struct ray_softc *));
287 static void ray_start_join_net __P((struct ray_softc *));
288 static ray_cmd_func_t ray_start_join_net_done __P((struct ray_softc *,
289 u_int, bus_size_t, u_int));
290 static void ray_start_join_timo __P((void *));
291 static void ray_stop __P((struct ray_softc *));
292 static void ray_update_error_counters __P((struct ray_softc *));
293 static void ray_update_mcast __P((struct ray_softc *));
294 static ray_cmd_func_t ray_update_params_done __P((struct ray_softc *,
295 bus_size_t, u_int));
296 static void ray_update_params __P((struct ray_softc *));
297 static void ray_update_promisc __P((struct ray_softc *));
298 static void ray_update_subcmd __P((struct ray_softc *));
299 static int ray_user_report_params __P((struct ray_softc *,
300 struct ray_param_req *));
301 static int ray_user_update_params __P((struct ray_softc *,
302 struct ray_param_req *));
303 static void ray_write_region __P((struct ray_softc *,bus_size_t,void *,size_t));
304
305
306 #ifdef RAY_DEBUG
307 static int ray_debug = 0;
308 static int ray_debug_xmit_sum = 0;
309 static int ray_debug_dump_desc = 0;
310 static int ray_debug_dump_rx = 0;
311 static int ray_debug_dump_tx = 0;
312 static struct timeval rtv, tv1, tv2, *ttp, *ltp;
313 #define RAY_DPRINTF(x) do { if (ray_debug) { \
314 struct timeval *tmp; \
315 microtime(ttp); \
316 timersub(ttp, ltp, &rtv); \
317 tmp = ttp; ttp = ltp; ltp = tmp; \
318 printf("%ld:%ld %ld:%06ld: ", ttp->tv_sec, ttp->tv_usec, rtv.tv_sec, rtv.tv_usec); \
319 printf x ; \
320 } } while (0)
321 #define RAY_DPRINTF_XMIT(x) do { if (ray_debug_xmit_sum) { \
322 struct timeval *tmp; \
323 microtime(ttp); \
324 timersub(ttp, ltp, &rtv); \
325 tmp = ttp; ttp = ltp; ltp = tmp; \
326 printf("%ld:%ld %ld:%06ld: ", ttp->tv_sec, ttp->tv_usec, rtv.tv_sec, rtv.tv_usec); \
327 printf x ; \
328 } } while (0)
329
330 #define HEXDF_NOCOMPRESS 0x1
331 #define HEXDF_NOOFFSET 0x2
332 #define HEXDF_NOASCII 0x4
333 void hexdump(const u_int8_t *, int, int, int, int);
334 static void ray_dump_mbuf __P((struct ray_softc *, struct mbuf *));
335
336 #else /* !RAY_DEBUG */
337
338 #define RAY_DPRINTF(x)
339 #define RAY_DPRINTF_XMIT(x)
340
341 #endif /* !RAY_DEBUG */
342
343
344 /*
345 * macros for writing to various regions in the mapped memory space
346 */
347
348 #if 0
349 /* read and write the registers in the CCR (attribute) space */
350 #define REG_WRITE(sc, off, val) \
351 bus_space_write_1((sc)->sc_amem.memt, (sc)->sc_amem.memh, (off), (val))
352
353 #define REG_READ(sc, off) \
354 bus_space_read_1((sc)->sc_amem.memt, (sc)->sc_amem.memh, (off))
355 #else
356 /* use already mapped ccrt */
357 #define REG_WRITE(sc, off, val) \
358 bus_space_write_1((sc)->sc_ccrt, (sc)->sc_ccrh, (off), (val))
359
360 #define REG_READ(sc, off) \
361 bus_space_read_1((sc)->sc_ccrt, (sc)->sc_ccrh, (off))
362 #endif
363
364 #define SRAM_READ_1(sc, off) \
365 ((u_int8_t)bus_space_read_1((sc)->sc_memt, (sc)->sc_memh, (off)))
366
367 #define SRAM_READ_FIELD_1(sc, off, s, f) \
368 SRAM_READ_1(sc, (off) + offsetof(struct s, f))
369
370 #define SRAM_READ_FIELD_2(sc, off, s, f) \
371 ((((u_int16_t)SRAM_READ_1(sc, (off) + offsetof(struct s, f)) << 8) \
372 |(SRAM_READ_1(sc, (off) + 1 + offsetof(struct s, f)))))
373
374 #define SRAM_READ_FIELD_N(sc, off, s, f, p, n) \
375 ray_read_region(sc, (off) + offsetof(struct s, f), (p), (n))
376
377 #define SRAM_WRITE_1(sc, off, val) \
378 bus_space_write_1((sc)->sc_memt, (sc)->sc_memh, (off), (val))
379
380 #define SRAM_WRITE_FIELD_1(sc, off, s, f, v) \
381 SRAM_WRITE_1(sc, (off) + offsetof(struct s, f), (v))
382
383 #define SRAM_WRITE_FIELD_2(sc, off, s, f, v) do { \
384 SRAM_WRITE_1(sc, (off) + offsetof(struct s, f), (((v) >> 8 ) & 0xff)); \
385 SRAM_WRITE_1(sc, (off) + 1 + offsetof(struct s, f), ((v) & 0xff)); \
386 } while (0)
387
388 #define SRAM_WRITE_FIELD_N(sc, off, s, f, p, n) \
389 ray_write_region(sc, (off) + offsetof(struct s, f), (p), (n))
390
391 /*
392 * Macros of general usefulness
393 */
394
395 #define M_PULLUP(m, s) do { \
396 if ((m)->m_len < (s)) \
397 (m) = m_pullup((m), (s)); \
398 } while (0)
399
400 #define RAY_ECF_READY(sc) (!(REG_READ(sc, RAY_ECFIR) & RAY_ECSIR_IRQ))
401 #define RAY_ECF_START_CMD(sc) REG_WRITE(sc, RAY_ECFIR, RAY_ECSIR_IRQ)
402 #define RAY_GET_INDEX(ccs) (((ccs) - RAY_CCS_BASE) / RAY_CCS_SIZE)
403 #define RAY_GET_CCS(i) (RAY_CCS_BASE + (i) * RAY_CCS_SIZE)
404
405 /*
406 * Globals
407 */
408
409 static u_int8_t llc_snapid[6] = { LLC_SNAP_LSAP, LLC_SNAP_LSAP, LLC_UI, };
410
411 /* based on bit index in SCP_xx */
412 static ray_cmd_func_t ray_cmdtab[] = {
413 ray_update_subcmd, /* SCP_UPDATESUBCMD */
414 ray_start_assoc, /* SCP_STARTASSOC */
415 ray_report_params, /* SCP_REPORTPARAMS */
416 ray_intr_start /* SCP_IFSTART */
417 };
418 static int ray_ncmdtab = sizeof(ray_cmdtab) / sizeof(*ray_cmdtab);
419
420 static ray_cmd_func_t ray_subcmdtab[] = {
421 ray_download_params, /* SCP_UPD_STARTUP */
422 ray_start_join_net, /* SCP_UPD_STARTJOIN */
423 ray_update_promisc, /* SCP_UPD_PROMISC */
424 ray_update_mcast, /* SCP_UPD_MCAST */
425 ray_update_params /* SCP_UPD_UPDATEPARAMS */
426 };
427 static int ray_nsubcmdtab = sizeof(ray_subcmdtab) / sizeof(*ray_subcmdtab);
428
429 /* autoconf information */
430 struct cfattach ray_ca = {
431 sizeof(struct ray_softc), ray_match, ray_attach, ray_detach, 0
432 };
433
434
435 /*
436 * Config Routines
437 */
438
439 static int
440 ray_match(parent, match, aux)
441 struct device *parent;
442 struct cfdata *match;
443 void *aux;
444 {
445 struct pcmcia_attach_args *pa = aux;
446
447 #ifdef RAY_DEBUG
448 if (!ltp) {
449 /* initialize timestamp XXX */
450 ttp = &tv1;
451 ltp = &tv2;
452 microtime(ltp);
453 }
454 #endif
455 return (pa->manufacturer == PCMCIA_VENDOR_RAYTHEON
456 && pa->product == PCMCIA_PRODUCT_RAYTHEON_WLAN);
457 }
458
459
460 static void
461 ray_attach(parent, self, aux)
462 struct device *parent, *self;
463 void *aux;
464 {
465 struct ray_ecf_startup *ep;
466 struct pcmcia_attach_args *pa;
467 struct ray_softc *sc;
468 struct ifnet *ifp;
469 bus_addr_t memoff;
470
471 pa = aux;
472 sc = (struct ray_softc *)self;
473 sc->sc_pf = pa->pf;
474 ifp = &sc->sc_if;
475 sc->sc_window = -1;
476 #if 0
477 sc->sc_awindow = -1;
478 #endif
479
480 /* enable the card */
481 pcmcia_function_init(sc->sc_pf, sc->sc_pf->cfe_head.sqh_first);
482 if (pcmcia_function_enable(sc->sc_pf)) {
483 printf(": failed to enable the card");
484 return;
485 }
486
487 /*
488 * map in the memory
489 */
490 if (pcmcia_mem_alloc(sc->sc_pf, RAY_SRAM_MEM_SIZE, &sc->sc_mem)) {
491 printf(": can\'t alloc shared memory\n");
492 goto fail;
493 }
494
495 if (pcmcia_mem_map(sc->sc_pf, PCMCIA_WIDTH_MEM8|PCMCIA_MEM_COMMON,
496 RAY_SRAM_MEM_BASE, RAY_SRAM_MEM_SIZE, &sc->sc_mem, &memoff,
497 &sc->sc_window)) {
498 printf(": can\'t map shared memory\n");
499 pcmcia_mem_free(sc->sc_pf, &sc->sc_mem);
500 goto fail;
501 }
502
503 #if 0
504 /* use the already mapped ccrt in our pf */
505 /*
506 * map in the memory
507 */
508 if (pcmcia_mem_alloc(sc->sc_pf, 0x1000, &sc->sc_amem)) {
509 printf(": can\'t alloc attr memory\n");
510 goto fail;
511 }
512
513 if (pcmcia_mem_map(sc->sc_pf, PCMCIA_MEM_ATTR, 0,
514 0x1000, &sc->sc_amem, &memoff, &sc->sc_awindow)) {
515 printf(": can\'t map attr memory\n");
516 pcmcia_mem_free(sc->sc_pf, &sc->sc_amem);
517 goto fail;
518 }
519 #endif
520
521 /* get startup results */
522 ep = &sc->sc_ecf_startup;
523 ray_read_region(sc, RAY_ECF_TO_HOST_BASE, ep,
524 sizeof(sc->sc_ecf_startup));
525
526 /* check to see that card initialized properly */
527 if (ep->e_status != RAY_ECFS_CARD_OK) {
528 printf(": card failed self test: status %d\n",
529 sc->sc_ecf_startup.e_status);
530 goto fail;
531 }
532
533 /* check firmware version */
534 if (sc->sc_version != SC_BUILD_4 && sc->sc_version != SC_BUILD_5) {
535 printf(": unsupported firmware version %d\n",
536 ep->e_fw_build_string);
537 goto fail;
538 }
539
540 /*
541 * set the parameters that will survive stop/init
542 */
543 memset(sc->sc_cnwid, 0, sizeof(sc->sc_cnwid));
544 memset(sc->sc_dnwid, 0, sizeof(sc->sc_dnwid));
545 strncpy(sc->sc_dnwid, RAY_DEF_NWID, sizeof(sc->sc_dnwid));
546 strncpy(sc->sc_cnwid, RAY_DEF_NWID, sizeof(sc->sc_dnwid));
547 sc->sc_omode = sc->sc_mode = RAY_MODE_DEFAULT;
548 sc->sc_countrycode = sc->sc_dcountrycode = RAY_PID_COUNTRY_CODE_DEFAULT;
549
550 /*
551 * attach the interface
552 */
553 /* The version isn't the most accurate way, but it's easy. */
554 if (sc->sc_version == SC_BUILD_4)
555 printf(": WebGear Aviator2.4\n");
556 else
557 printf(": Raytheon Raylink\n");
558 printf("%s: firmware version %d\n", sc->sc_dev.dv_xname,sc->sc_version);
559 printf("%s: supported rates %0x:%0x:%0x:%0x:%0x:%0x:%0x:%0x\n",
560 sc->sc_xname, ep->e_rates[0], ep->e_rates[1], ep->e_rates[2],
561 ep->e_rates[3], ep->e_rates[4], ep->e_rates[5], ep->e_rates[6],
562 ep->e_rates[7]);
563 printf("%s: 802.11 address %s\n", sc->sc_xname,
564 ether_sprintf(ep->e_station_addr));
565
566 memcpy(ifp->if_xname, sc->sc_xname, IFNAMSIZ);
567 ifp->if_softc = sc;
568 ifp->if_start = ray_if_start;
569 ifp->if_ioctl = ray_ioctl;
570 ifp->if_mtu = ETHERMTU;
571 ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST;
572 if_attach(ifp);
573 ether_ifattach(ifp, ep->e_station_addr);
574 /* need enough space for ieee80211_header + (snap or e2) */
575 ifp->if_hdrlen =
576 sizeof(struct ieee80211_frame) + sizeof(struct ether_header);
577
578 ifmedia_init(&sc->sc_media, 0, ray_media_change, ray_media_status);
579 ifmedia_add(&sc->sc_media, IFM_ADHOC, 0, 0);
580 ifmedia_add(&sc->sc_media, IFM_INFRA, 0, 0);
581 if (sc->sc_mode == SC_MODE_ADHOC)
582 ifmedia_set(&sc->sc_media, IFM_ADHOC);
583 else
584 ifmedia_set(&sc->sc_media, IFM_INFRA);
585
586 #if NBPFILTER > 0
587 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
588 #endif
589 /* disable the card */
590 pcmcia_function_disable(sc->sc_pf);
591
592 sc->sc_sdhook = shutdownhook_establish(ray_shutdown, sc);
593
594 return;
595 fail:
596 /* disable the card */
597 pcmcia_function_disable(sc->sc_pf);
598
599 /* free the alloc/map */
600 #if 0
601 if (sc->sc_awindow != -1) {
602 pcmcia_mem_unmap(sc->sc_pf, sc->sc_awindow);
603 pcmcia_mem_free(sc->sc_pf, &sc->sc_amem);
604 }
605 #endif
606 if (sc->sc_window != -1) {
607 pcmcia_mem_unmap(sc->sc_pf, sc->sc_window);
608 pcmcia_mem_free(sc->sc_pf, &sc->sc_mem);
609 }
610 }
611
612 static int
613 ray_detach(self, flags)
614 struct device *self;
615 int flags;
616 {
617 struct ray_softc *sc;
618
619 sc = (struct ray_softc *)self;
620 RAY_DPRINTF(("%s: detach\n", sc->sc_xname));
621
622 if (sc->sc_if.if_flags & IFF_RUNNING)
623 ray_disable(sc);
624
625 /* give back the memory */
626 #if 0
627 if (sc->sc_awindow != -1) {
628 pcmcia_mem_unmap(sc->sc_pf, sc->sc_awindow);
629 pcmcia_mem_free(sc->sc_pf, &sc->sc_amem);
630 }
631 #endif
632 if (sc->sc_window != -1) {
633 pcmcia_mem_unmap(sc->sc_pf, sc->sc_window);
634 pcmcia_mem_free(sc->sc_pf, &sc->sc_mem);
635 }
636
637 #ifdef notyet
638 /*
639 * Our softc is about to go away, so drop our reference
640 * to the ifnet.
641 */
642 if_delref(sc->sc_if);
643 return (0);
644 #else
645 return (EBUSY);
646 #endif
647 }
648
649 /*
650 * start the card running
651 */
652 static int
653 ray_enable(sc)
654 struct ray_softc *sc;
655 {
656 int error;
657
658 RAY_DPRINTF(("%s: enable\n", sc->sc_xname));
659
660 sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, ray_intr, sc);
661 if (sc->sc_ih == NULL)
662 return (EIO);
663 if ((error = ray_init(sc)))
664 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
665 return (error);
666 }
667
668 /*
669 * stop the card running
670 */
671 static void
672 ray_disable(sc)
673 struct ray_softc *sc;
674 {
675 RAY_DPRINTF(("%s: disable\n", sc->sc_xname));
676
677 if ((sc->sc_if.if_flags & IFF_RUNNING))
678 ray_stop(sc);
679
680 sc->sc_resetloop = 0;
681 sc->sc_rxoverflow = 0;
682 sc->sc_rxcksum = 0;
683 sc->sc_rxhcksum = 0;
684 sc->sc_rxnoise = 0;
685
686 if (sc->sc_ih)
687 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
688 sc->sc_ih = 0;
689 }
690
691 /*
692 * start the card running
693 */
694 static int
695 ray_init(sc)
696 struct ray_softc *sc;
697 {
698 struct ray_ecf_startup *ep;
699 bus_size_t ccs;
700 int i;
701
702 RAY_DPRINTF(("%s: init\n", sc->sc_xname));
703
704 if ((sc->sc_if.if_flags & IFF_RUNNING))
705 ray_stop(sc);
706
707 if (pcmcia_function_enable(sc->sc_pf))
708 return (EIO);
709
710 /* reset some values */
711 memset(sc->sc_ccsinuse, 0, sizeof(sc->sc_ccsinuse));
712 sc->sc_havenet = 0;
713 memset(sc->sc_bssid, 0, sizeof(sc->sc_bssid));
714 sc->sc_deftxrate = 0;
715 sc->sc_encrypt = 0;
716 sc->sc_txpad = 0;
717 sc->sc_promisc = 0;
718 sc->sc_scheduled = 0;
719 sc->sc_running = 0;
720 sc->sc_txfree = RAY_CCS_NTX;
721 sc->sc_checkcounters = 0;
722
723 /* get startup results */
724 ep = &sc->sc_ecf_startup;
725 ray_read_region(sc, RAY_ECF_TO_HOST_BASE, ep,
726 sizeof(sc->sc_ecf_startup));
727
728 /* check to see that card initialized properly */
729 if (ep->e_status != RAY_ECFS_CARD_OK) {
730 pcmcia_function_disable(sc->sc_pf);
731 printf("%s: card failed self test: status %d\n",
732 sc->sc_xname, sc->sc_ecf_startup.e_status);
733 return (EIO);
734 }
735
736 /* fixup tib size to be correct */
737 if (sc->sc_version == SC_BUILD_4 && sc->sc_tibsize == 0x55)
738 sc->sc_tibsize = 32;
739 sc->sc_txpad = sc->sc_tibsize;
740
741 /* set all ccs to be free */
742 ccs = RAY_GET_CCS(0);
743 for (i = 0; i < RAY_CCS_LAST; ccs += RAY_CCS_SIZE, i++)
744 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status,
745 RAY_CCS_STATUS_FREE);
746
747 #if 0
748 /* clear the interrupt if present */
749 REG_WRITE(sc, RAY_HCSIR, 0);
750 #endif
751
752 /* we are now up and running -- and are busy until download is cplt */
753 sc->sc_if.if_flags |= IFF_RUNNING | IFF_OACTIVE;
754
755 /* set this now so it gets set in the download */
756 sc->sc_promisc = !!(sc->sc_if.if_flags & (IFF_PROMISC|IFF_ALLMULTI));
757
758 /* call after we mark ourselves running */
759 ray_download_params(sc);
760
761 return (0);
762 }
763
764 /*
765 * stop the card running
766 */
767 static void
768 ray_stop(sc)
769 struct ray_softc *sc;
770 {
771 RAY_DPRINTF(("%s: stop\n", sc->sc_xname));
772
773 untimeout(ray_check_ccs, sc);
774 sc->sc_timocheck = 0;
775
776 untimeout(ray_check_scheduled, sc);
777 sc->sc_timoneed = 0;
778
779 if (sc->sc_repreq) {
780 sc->sc_repreq->r_failcause = RAY_FAILCAUSE_EDEVSTOP;
781 wakeup(ray_report_params);
782 }
783 if (sc->sc_updreq) {
784 sc->sc_repreq->r_failcause = RAY_FAILCAUSE_EDEVSTOP;
785 wakeup(ray_update_params);
786 }
787
788 sc->sc_if.if_flags &= ~IFF_RUNNING;
789 pcmcia_function_disable(sc->sc_pf);
790 }
791
792 /*
793 * reset the card
794 */
795 static void
796 ray_reset(sc)
797 struct ray_softc *sc;
798 {
799 if (++sc->sc_resetloop >= RAY_MAX_RESETS) {
800 if (sc->sc_resetloop == RAY_MAX_RESETS) {
801 printf("%s: unable to correct, disabling\n",
802 sc->sc_xname);
803 untimeout(ray_reset_resetloop, sc);
804 timeout((void (*)(void *))ray_disable, sc, 1);
805 }
806 } else {
807 printf("%s: unexpected failure resetting hw [%d more]\n",
808 sc->sc_xname, RAY_MAX_RESETS - sc->sc_resetloop);
809 untimeout(ray_reset_resetloop, sc);
810 ray_init(sc);
811 timeout(ray_reset_resetloop, sc, 30 * hz);
812 }
813 }
814
815 /*
816 * return resetloop to zero (enough time has expired to allow user to
817 * disable a whacked interface) the main reason for all this nonesense
818 * is that resets take ~2 seconds and currently the pcmcia code spins
819 * on these resets
820 */
821 static void
822 ray_reset_resetloop(arg)
823 void *arg;
824 {
825 struct ray_softc *sc;
826
827 sc = arg;
828 sc->sc_resetloop = 0;
829 }
830
831 static void
832 ray_shutdown(arg)
833 void *arg;
834 {
835 struct ray_softc *sc;
836
837 sc = arg;
838 ray_disable(sc);
839 }
840
841
842 static int
843 ray_ioctl(ifp, cmd, data)
844 struct ifnet *ifp;
845 u_long cmd;
846 caddr_t data;
847 {
848 u_int8_t nwid[IEEE80211_NWID_LEN];
849 struct ray_param_req pr;
850 struct ray_softc *sc;
851 struct ifreq *ifr;
852 struct ifaddr *ifa;
853 int error, error2, s;
854
855 sc = ifp->if_softc;
856 error = 0;
857
858 ifr = (struct ifreq *)data;
859
860 s = splnet();
861
862 RAY_DPRINTF(("%s: ioctl: cmd 0x%lx data 0x%lx\n", ifp->if_xname,
863 cmd, (long)data));
864 switch (cmd) {
865 case SIOCSIFADDR:
866 RAY_DPRINTF(("%s: ioctl: cmd SIOCSIFADDR\n", ifp->if_xname));
867 if ((ifp->if_flags & IFF_RUNNING) == 0)
868 if ((error = ray_enable(sc)))
869 break;
870 ifp->if_flags |= IFF_UP;
871 ifa = (struct ifaddr *)data;
872 switch (ifa->ifa_addr->sa_family) {
873 #ifdef INET
874 case AF_INET:
875 arp_ifinit(&sc->sc_if, ifa);
876 break;
877 #endif
878 default:
879 break;
880 }
881 break;
882 case SIOCSIFFLAGS:
883 RAY_DPRINTF(("%s: ioctl: cmd SIOCSIFFLAGS\n", ifp->if_xname));
884 if (ifp->if_flags & IFF_UP) {
885 if ((ifp->if_flags & IFF_RUNNING) == 0) {
886 if ((error = ray_enable(sc)))
887 break;
888 } else
889 ray_update_promisc(sc);
890 } else if (ifp->if_flags & IFF_RUNNING)
891 ray_disable(sc);
892 break;
893 case SIOCADDMULTI:
894 RAY_DPRINTF(("%s: ioctl: cmd SIOCADDMULTI\n", ifp->if_xname));
895 case SIOCDELMULTI:
896 if (cmd == SIOCDELMULTI)
897 RAY_DPRINTF(("%s: ioctl: cmd SIOCDELMULTI\n",
898 ifp->if_xname));
899 if (cmd == SIOCADDMULTI)
900 error = ether_addmulti(ifr, &sc->sc_ec);
901 else
902 error = ether_delmulti(ifr, &sc->sc_ec);
903 if (error == ENETRESET) {
904 error = 0;
905 ray_update_mcast(sc);
906 }
907 case SIOCSIFMEDIA:
908 RAY_DPRINTF(("%s: ioctl: cmd SIOCSIFMEDIA\n", ifp->if_xname));
909 case SIOCGIFMEDIA:
910 if (cmd == SIOCGIFMEDIA)
911 RAY_DPRINTF(("%s: ioctl: cmd SIOCGIFMEDIA\n",
912 ifp->if_xname));
913 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
914 break;
915 case SIOCSRAYPARAM:
916 RAY_DPRINTF(("%s: ioctl: cmd SIOCSRAYPARAM\n", ifp->if_xname));
917 if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr))))
918 break;
919 /* disallow certain command that have another interface */
920 switch (pr.r_paramid) {
921 case RAY_PID_NET_TYPE: /* through media opt */
922 case RAY_PID_AP_STATUS: /* unsupported */
923 case RAY_PID_SSID: /* use SIOC80211[GS]NWID */
924 case RAY_PID_MAC_ADDR: /* XXX need interface? */
925 case RAY_PID_PROMISC: /* bpf */
926 error = EINVAL;
927 break;
928 }
929 error = ray_user_update_params(sc, &pr);
930 error2 = copyout(&pr, ifr->ifr_data, sizeof(pr));
931 error = error2 ? error2 : error;
932 break;
933 case SIOCGRAYPARAM:
934 RAY_DPRINTF(("%s: ioctl: cmd SIOCGRAYPARAM\n", ifp->if_xname));
935 if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr))))
936 break;
937 error = ray_user_report_params(sc, &pr);
938 error2 = copyout(&pr, ifr->ifr_data, sizeof(pr));
939 error = error2 ? error2 : error;
940 break;
941 case SIOCS80211NWID:
942 RAY_DPRINTF(("%s: ioctl: cmd SIOCSNWID\n", ifp->if_xname));
943 /*
944 * if later people overwrite thats ok -- the latest version
945 * will always get start/joined even if it was set by
946 * a previous command
947 */
948 if ((error = copyin(ifr->ifr_data, nwid, sizeof(nwid))))
949 break;
950 if (!memcmp(sc->sc_dnwid, nwid, sizeof(nwid)))
951 break;
952 memcpy(sc->sc_dnwid, nwid, sizeof(nwid));
953 if (ifp->if_flags & IFF_RUNNING)
954 ray_start_join_net(sc);
955 break;
956 case SIOCG80211NWID:
957 RAY_DPRINTF(("%s: ioctl: cmd SIOCHNWID\n", ifp->if_xname));
958 error2 = copyout(sc->sc_cnwid, ifr->ifr_data,
959 IEEE80211_NWID_LEN);
960 break;
961 default:
962 RAY_DPRINTF(("%s: ioctl: unknown\n", ifp->if_xname));
963 error = EINVAL;
964 break;
965 }
966
967 RAY_DPRINTF(("%s: ioctl: returns %d\n", ifp->if_xname, error));
968
969 splx(s);
970
971 return (error);
972 }
973
974 /*
975 * ifnet interface to start transmission on the interface
976 */
977 static void
978 ray_if_start(ifp)
979 struct ifnet *ifp;
980 {
981 struct ray_softc *sc;
982
983 sc = ifp->if_softc;
984 ray_intr_start(sc);
985 }
986
987 static int
988 ray_media_change(ifp)
989 struct ifnet *ifp;
990 {
991 struct ray_softc *sc;
992
993 sc = ifp->if_softc;
994 RAY_DPRINTF(("%s: media change cur %d\n", ifp->if_xname,
995 sc->sc_media.ifm_cur->ifm_media));
996 if (sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC)
997 sc->sc_mode = SC_MODE_ADHOC;
998 else
999 sc->sc_mode = SC_MODE_INFRA;
1000 if (sc->sc_mode != sc->sc_omode)
1001 ray_start_join_net(sc);
1002 return (0);
1003 }
1004
1005 static void
1006 ray_media_status(ifp, imr)
1007 struct ifnet *ifp;
1008 struct ifmediareq *imr;
1009 {
1010 struct ray_softc *sc;
1011
1012 sc = ifp->if_softc;
1013
1014 RAY_DPRINTF(("%s: media status\n", ifp->if_xname));
1015
1016 imr->ifm_status = IFM_AVALID;
1017 if (sc->sc_havenet)
1018 imr->ifm_status |= IFM_ACTIVE;
1019
1020 if (sc->sc_mode == SC_MODE_ADHOC)
1021 imr->ifm_active = IFM_ADHOC;
1022 else
1023 imr->ifm_active = IFM_INFRA;
1024 }
1025
1026 /*
1027 * called to start from ray_intr. We don't check for pending
1028 * interrupt as a result
1029 */
1030 static void
1031 ray_intr_start(sc)
1032 struct ray_softc *sc;
1033 {
1034 struct ieee80211_frame *iframe;
1035 struct ether_header *eh;
1036 size_t len, pktlen, tmplen;
1037 bus_size_t bufp, ebufp;
1038 struct mbuf *m0, *m;
1039 struct ifnet *ifp;
1040 u_int firsti, hinti, previ, i;
1041 u_int16_t et;
1042 u_int8_t *d;
1043
1044 ifp = &sc->sc_if;
1045
1046 RAY_DPRINTF(("%s: start free %d qlen %d qmax %d\n",
1047 ifp->if_xname, sc->sc_txfree, ifp->if_snd.ifq_len,
1048 ifp->if_snd.ifq_maxlen));
1049
1050 ray_cmd_cancel(sc, SCP_IFSTART);
1051
1052 if ((ifp->if_flags & IFF_RUNNING) == 0 || !sc->sc_havenet)
1053 return;
1054
1055 if (ifp->if_snd.ifq_len == 0)
1056 return;
1057
1058 firsti = i = previ = RAY_CCS_LINK_NULL;
1059 hinti = RAY_CCS_TX_FIRST;
1060
1061 if (!RAY_ECF_READY(sc)) {
1062 ray_cmd_schedule(sc, SCP_IFSTART);
1063 return;
1064 }
1065
1066 for (;;) {
1067 /* if we have no descriptors be done */
1068 if (i == RAY_CCS_LINK_NULL) {
1069 i = ray_find_free_tx_ccs(sc, hinti);
1070 if (i == RAY_CCS_LINK_NULL) {
1071 ifp->if_flags |= IFF_OACTIVE;
1072 break;
1073 }
1074 }
1075
1076 IF_DEQUEUE(&ifp->if_snd, m0);
1077 if (!m0)
1078 break;
1079 RAY_DPRINTF(("%s: gotmbuf 0x%lx\n", ifp->if_xname, (long)m0));
1080 pktlen = m0->m_pkthdr.len;
1081 if (pktlen > ETHER_MAX_LEN - ETHER_CRC_LEN) {
1082 RAY_DPRINTF((
1083 "%s: mbuf too long %d\n", ifp->if_xname, pktlen));
1084 m_freem(m0);
1085 continue;
1086 }
1087 RAY_DPRINTF(("%s: mbuf.m_pkthdr.len %d\n", ifp->if_xname,
1088 (int)pktlen));
1089
1090 /* we need the ether_header now for pktlen adjustments */
1091 M_PULLUP(m0, sizeof(struct ether_header));
1092 if (!m0) {
1093 RAY_DPRINTF(( "%s: couldn\'t pullup ether header\n",
1094 ifp->if_xname));
1095 continue;
1096 }
1097 RAY_DPRINTF(("%s: got pulled up mbuf 0x%lx\n", ifp->if_xname,
1098 (long)m0));
1099
1100 /* first peek at the type of packet and figure out what to do */
1101 eh = mtod(m0, struct ether_header *);
1102 et = ntohs(eh->ether_type);
1103 if (ifp->if_flags & IFF_LINK0) {
1104 /* don't support llc for windows compat operation */
1105 if (et <= ETHERMTU) {
1106 m_freem(m0);
1107 continue;
1108 }
1109 tmplen = sizeof(struct ieee80211_frame);
1110 } else if (et > ETHERMTU) {
1111 /* adjust for LLC/SNAP header */
1112 tmplen= sizeof(struct ieee80211_frame) - ETHER_ADDR_LEN;
1113 }
1114 /* now get our space for the 802.11 frame */
1115 M_PREPEND(m0, tmplen, M_DONTWAIT);
1116 if (m0)
1117 M_PULLUP(m0, sizeof(struct ether_header) + tmplen);
1118 if (!m0) {
1119 RAY_DPRINTF(("%s: couldn\'t prepend header\n",
1120 ifp->if_xname));
1121 continue;
1122 }
1123 /* copy the frame into the mbuf for tapping */
1124 iframe = mtod(m0, struct ieee80211_frame *);
1125 eh = (struct ether_header *)((u_int8_t *)iframe + tmplen);
1126 iframe->i_fc[0] =
1127 (IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA);
1128 if (sc->sc_mode == SC_MODE_ADHOC) {
1129 iframe->i_fc[1] = IEEE80211_FC1_RCVFROM_TERMINAL;
1130 memcpy(iframe->i_addr1, eh->ether_dhost,ETHER_ADDR_LEN);
1131 memcpy(iframe->i_addr2, eh->ether_shost,ETHER_ADDR_LEN);
1132 memcpy(iframe->i_addr3, sc->sc_bssid, ETHER_ADDR_LEN);
1133 } else {
1134 iframe->i_fc[1] = IEEE80211_FC1_RCVFROM_AP;
1135 memcpy(iframe->i_addr1, sc->sc_bssid,ETHER_ADDR_LEN);
1136 memcpy(iframe->i_addr2, eh->ether_shost,ETHER_ADDR_LEN);
1137 memmove(iframe->i_addr3,eh->ether_dhost,ETHER_ADDR_LEN);
1138 }
1139 iframe->i_dur[0] = iframe->i_dur[1] = 0;
1140 iframe->i_seq[0] = iframe->i_seq[1] = 0;
1141
1142 /* if not using crummy E2 in 802.11 make it LLC/SNAP */
1143 if ((ifp->if_flags & IFF_LINK0) == 0 && et > ETHERMTU)
1144 memcpy(iframe + 1, llc_snapid, sizeof(llc_snapid));
1145
1146 RAY_DPRINTF(("%s: i %d previ %d\n", ifp->if_xname, i, previ));
1147
1148 if (firsti == RAY_CCS_LINK_NULL)
1149 firsti = i;
1150
1151 pktlen = m0->m_pkthdr.len;
1152 bufp = ray_fill_in_tx_ccs(sc, pktlen, i, previ);
1153 previ = hinti = i;
1154 i = RAY_CCS_LINK_NULL;
1155
1156 RAY_DPRINTF(("%s: bufp 0x%lx new pktlen %d\n",
1157 ifp->if_xname, (long)bufp, (int)pktlen));
1158
1159 /* copy out mbuf */
1160 for (m = m0; m; m = m->m_next) {
1161 if ((len = m->m_len) == 0)
1162 continue;
1163 RAY_DPRINTF((
1164 "%s: copying mbuf 0x%lx bufp 0x%lx len %d\n",
1165 ifp->if_xname, (long)m, (long)bufp, (int)len));
1166 d = mtod(m, u_int8_t *);
1167 ebufp = bufp + len;
1168 if (ebufp <= RAY_TX_END)
1169 ray_write_region(sc, bufp, d, len);
1170 else {
1171 panic("ray_intr_start"); /* XXX */
1172 /* wrapping */
1173 tmplen = ebufp - bufp;
1174 len -= tmplen;
1175 ray_write_region(sc, bufp, d, tmplen);
1176 d += tmplen;
1177 bufp = RAY_TX_BASE;
1178 ray_write_region(sc, bufp, d, len);
1179 }
1180 bufp += len;
1181 }
1182 #if NBPFILTER > 0
1183 if (ifp->if_bpf) {
1184 if (ifp->if_flags & IFF_LINK0) {
1185 m0->m_data += sizeof(struct ieee80211_frame);
1186 m0->m_len -= sizeof(struct ieee80211_frame);
1187 m0->m_pkthdr.len -= sizeof(struct ieee80211_frame);
1188 }
1189 bpf_mtap(ifp->if_bpf, m0);
1190 if (ifp->if_flags & IFF_LINK0) {
1191 m0->m_data -= sizeof(struct ieee80211_frame);
1192 m0->m_len += sizeof(struct ieee80211_frame);
1193 m0->m_pkthdr.len += sizeof(struct ieee80211_frame);
1194 }
1195 }
1196 #endif
1197
1198 #ifdef RAY_DEBUG
1199 if (ray_debug && ray_debug_dump_tx)
1200 ray_dump_mbuf(sc, m0);
1201 #endif
1202 m_freem(m0);
1203 }
1204
1205 if (firsti == RAY_CCS_LINK_NULL)
1206 return;
1207 i = 0;
1208 if (!RAY_ECF_READY(sc)) {
1209 /*
1210 * if this can really happen perhaps we need to save
1211 * the chain and use it later. I think this might
1212 * be a confused state though because we check above
1213 * and don't issue any commands between.
1214 */
1215 printf("%s: dropping tx packets device busy\n", sc->sc_xname);
1216 ray_free_ccs_chain(sc, firsti);
1217 return;
1218 }
1219
1220 /* send it off */
1221 RAY_DPRINTF(("%s: ray_start issueing %d \n", sc->sc_xname, firsti));
1222 SRAM_WRITE_1(sc, RAY_SCB_CCSI, firsti);
1223 RAY_ECF_START_CMD(sc);
1224
1225 RAY_DPRINTF_XMIT(("%s: sent packet: len %d\n", sc->sc_xname,
1226 pktlen));
1227 }
1228
1229 /*
1230 * recevice a packet from the card
1231 */
1232 static void
1233 ray_recv(sc, ccs)
1234 struct ray_softc *sc;
1235 bus_size_t ccs;
1236 {
1237 struct ieee80211_frame *frame;
1238 struct ether_header *eh;
1239 struct mbuf *m;
1240 size_t pktlen, len, lenread;
1241 bus_size_t bufp, ebufp, tmp;
1242 struct ifnet *ifp;
1243 u_int8_t *src, *d;
1244 u_int frag, nofrag, ni, i, issnap, first;
1245 u_int8_t fc0;
1246
1247 #ifdef RAY_DEBUG
1248 /* have a look if you want to see how the card rx works :) */
1249 if (ray_debug && ray_debug_dump_desc)
1250 hexdump((caddr_t)sc->sc_memh + RAY_RCS_BASE, 0x400,
1251 16, 4, 0);
1252 #endif
1253
1254 m = 0;
1255 ifp = &sc->sc_if;
1256
1257 /* it looks like at least with build 4 there is no CRC in length */
1258 first = RAY_GET_INDEX(ccs);
1259 pktlen = SRAM_READ_FIELD_2(sc, ccs, ray_cmd_rx, c_pktlen);
1260
1261 RAY_DPRINTF(("%s: recv pktlen %d nofrag %d\n", sc->sc_xname,
1262 pktlen, nofrag));
1263 RAY_DPRINTF_XMIT(("%s: received packet: len %d\n", sc->sc_xname,
1264 pktlen));
1265 if (pktlen > MCLBYTES
1266 || pktlen < (sizeof(*frame) + sizeof(struct llc))) {
1267 RAY_DPRINTF(("%s: PKTLEN TOO BIG OR TOO SMALL\n",
1268 sc->sc_xname));
1269 ifp->if_ierrors++;
1270 goto done;
1271 }
1272 MGETHDR(m, M_DONTWAIT, MT_DATA);
1273 if (!m) {
1274 RAY_DPRINTF(("%s: MGETHDR FAILED\n", sc->sc_xname));
1275 ifp->if_ierrors++;
1276 goto done;
1277 }
1278 if (pktlen > MHLEN) {
1279 /* XXX should allow chaining? */
1280 MCLGET(m, M_DONTWAIT);
1281 if ((m->m_flags & M_EXT) == 0) {
1282 RAY_DPRINTF(("%s: MCLGET FAILED\n", sc->sc_xname));
1283 ifp->if_ierrors++;
1284 m_freem(m);
1285 m = 0;
1286 goto done;
1287 }
1288 }
1289 m->m_pkthdr.rcvif = ifp;
1290 m->m_pkthdr.len = pktlen;
1291 m->m_len = pktlen;
1292 d = mtod(m, u_int8_t *);
1293
1294 RAY_DPRINTF(("%s: recv ccs index %d\n", sc->sc_xname, first));
1295 frag = 0;
1296 lenread = 0;
1297 i = ni = first;
1298 while ((i = ni) && i != RAY_CCS_LINK_NULL) {
1299 ccs = RAY_GET_CCS(i);
1300 bufp = SRAM_READ_FIELD_2(sc, ccs, ray_cmd_rx, c_bufp);
1301 len = SRAM_READ_FIELD_2(sc, ccs, ray_cmd_rx, c_len);
1302 /* remove the CRC */
1303 #if 0
1304 /* at least with build 4 no crc seems to be here */
1305 if (frag++ == 0)
1306 len -= 4;
1307 #endif
1308 ni = SRAM_READ_FIELD_1(sc, ccs, ray_cmd_rx, c_nextfrag);
1309 RAY_DPRINTF(("%s: recv frag index %d len %d bufp 0x%x ni %d\n",
1310 sc->sc_xname, i, len, (int)bufp, ni));
1311 if (len + lenread > pktlen) {
1312 RAY_DPRINTF(("%s: BAD LEN current 0x%x pktlen 0x%x\n",
1313 sc->sc_xname, len + lenread, pktlen));
1314 ifp->if_ierrors++;
1315 m_freem(m);
1316 m = 0;
1317 goto done;
1318 }
1319 if (i < RAY_RCCS_FIRST) {
1320 printf("ray_recv: bad ccs index 0x%x\n", i);
1321 m_freem(m);
1322 m = 0;
1323 goto done;
1324 }
1325
1326 ebufp = bufp + len;
1327 if (ebufp <= RAY_RX_END)
1328 ray_read_region(sc, bufp, d, len);
1329 else {
1330 /* wrapping */
1331 ray_read_region(sc, bufp, d, (tmp = RAY_RX_END - bufp));
1332 ray_read_region(sc, RAY_RX_BASE, d + tmp, ebufp - RAY_RX_END);
1333 }
1334 d += len;
1335 lenread += len;
1336 }
1337 done:
1338
1339 RAY_DPRINTF(("%s: recv frag count %d\n", sc->sc_xname, frag));
1340
1341 /* free the rcss */
1342 ni = first;
1343 while ((i = ni) && (i != RAY_CCS_LINK_NULL)) {
1344 ccs = RAY_GET_CCS(i);
1345 ni = SRAM_READ_FIELD_1(sc, ccs, ray_cmd_rx, c_nextfrag);
1346 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status,
1347 RAY_CCS_STATUS_FREE);
1348 }
1349
1350 if (!m)
1351 return;
1352
1353 RAY_DPRINTF(("%s: recv got packet pktlen %d actual %d\n",
1354 sc->sc_xname, pktlen, lenread));
1355 #ifdef RAY_DEBUG
1356 if (ray_debug && ray_debug_dump_rx)
1357 ray_dump_mbuf(sc, m);
1358 #endif
1359 /* receivce the packet */
1360 frame = mtod(m, struct ieee80211_frame *);
1361 fc0 = frame->i_fc[0]
1362 & (IEEE80211_FC0_VERSION_MASK|IEEE80211_FC0_TYPE_MASK);
1363 if ((fc0 & IEEE80211_FC0_VERSION_MASK) != IEEE80211_FC0_VERSION_0) {
1364 RAY_DPRINTF(("%s: pkt not version 0 fc 0x%x\n",
1365 sc->sc_xname, fc0));
1366 m_freem(m);
1367 return;
1368 }
1369 if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA) {
1370 RAY_DPRINTF(("%s: pkt not type data fc0 0x%x\n",
1371 sc->sc_xname, fc0));
1372 m_freem(m);
1373 return;
1374 }
1375
1376 if (!memcmp(frame + 1, llc_snapid, sizeof(llc_snapid)))
1377 issnap = 1;
1378 else {
1379 /*
1380 * if user has link0 flag set we allow the weird
1381 * Ethernet2 in 802.11 encapsulation produced by
1382 * the windows driver for the WebGear card
1383 */
1384 RAY_DPRINTF(("%s: pkt not snap 0\n", sc->sc_xname));
1385 if ((ifp->if_flags & IFF_LINK0) == 0) {
1386 m_freem(m);
1387 return;
1388 }
1389 issnap = 0;
1390 }
1391 switch (frame->i_fc[1] & IEEE80211_FC1_RCVFROM_MASK) {
1392 case IEEE80211_FC1_RCVFROM_TERMINAL:
1393 src = frame->i_addr2;
1394 break;
1395 case IEEE80211_FC1_RCVFROM_AP:
1396 src = frame->i_addr3;
1397 break;
1398 case IEEE80211_FC1_RCVFROM_AP2AP:
1399 RAY_DPRINTF(("%s: pkt ap2ap\n", sc->sc_xname));
1400 m_freem(m);
1401 return;
1402 default:
1403 RAY_DPRINTF(("%s: pkt type unknown\n", sc->sc_xname));
1404 m_freem(m);
1405 return;
1406 }
1407 /*
1408 * This is a mess.. we should support other LLC frame types
1409 */
1410 if (issnap) {
1411 /* create an ether_header over top of the 802.11+SNAP header */
1412 eh = (struct ether_header *)((caddr_t)(frame + 1) - 6);
1413 memcpy(eh->ether_shost, src, ETHER_ADDR_LEN);
1414 memcpy(eh->ether_dhost, frame->i_addr1, ETHER_ADDR_LEN);
1415 } else {
1416 /* this is the weird e2 in 802.11 encapsulation */
1417 eh = (struct ether_header *)(frame + 1);
1418 }
1419 m_adj(m, (caddr_t)eh - (caddr_t)frame);
1420 #if NBPFILTER > 0
1421 if (ifp->if_bpf)
1422 bpf_mtap(ifp->if_bpf, m);
1423 #endif
1424 /* XXX doesn't appear to be included m->m_flags |= M_HASFCS; */
1425 (*ifp->if_input)(ifp, m);
1426 }
1427
1428
1429 /*
1430 * scan for free buffers
1431 *
1432 * Note: do _not_ try to optimize this away, there is some kind of
1433 * horrible interaction with receiving tx interrupts and they
1434 * have to be done as fast as possible, which means zero processing.
1435 * this took ~ever to figure out, don't make someone do it again!
1436 */
1437 static u_int
1438 ray_find_free_tx_ccs(sc, hint)
1439 struct ray_softc *sc;
1440 u_int hint;
1441 {
1442 u_int i, stat;
1443
1444 for (i = hint; i <= RAY_CCS_TX_LAST; i++) {
1445 stat = SRAM_READ_FIELD_1(sc, RAY_GET_CCS(i), ray_cmd, c_status);
1446 if (stat == RAY_CCS_STATUS_FREE)
1447 return (i);
1448 }
1449
1450 if (hint == RAY_CCS_TX_FIRST)
1451 return (RAY_CCS_LINK_NULL);
1452
1453 for (i = RAY_CCS_TX_FIRST; i < hint; i++) {
1454 stat = SRAM_READ_FIELD_1(sc, RAY_GET_CCS(i), ray_cmd, c_status);
1455 if (stat == RAY_CCS_STATUS_FREE)
1456 return (i);
1457 }
1458 return (RAY_CCS_LINK_NULL);
1459 }
1460
1461 /*
1462 * allocate, initialize and link in a tx ccs for the given
1463 * page and the current chain values
1464 */
1465 static bus_size_t
1466 ray_fill_in_tx_ccs(sc, pktlen, i, pi)
1467 struct ray_softc *sc;
1468 size_t pktlen;
1469 u_int i, pi;
1470 {
1471 bus_size_t ccs, bufp;
1472
1473 /* pktlen += RAY_TX_PHY_SIZE; */
1474 bufp = RAY_TX_BASE + i * RAY_TX_BUF_SIZE;
1475 bufp += sc->sc_txpad;
1476 ccs = RAY_GET_CCS(i);
1477 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_status, RAY_CCS_STATUS_BUSY);
1478 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_cmd, RAY_CMD_TX_REQ);
1479 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_link, RAY_CCS_LINK_NULL);
1480 SRAM_WRITE_FIELD_2(sc, ccs, ray_cmd_tx, c_bufp, bufp);
1481 SRAM_WRITE_FIELD_2(sc, ccs, ray_cmd_tx, c_len, pktlen);
1482 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_tx_rate, sc->sc_deftxrate);
1483 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_apm_mode, 0);
1484 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_antenna, 0);
1485
1486 /* link us in */
1487 if (pi != RAY_CCS_LINK_NULL)
1488 SRAM_WRITE_FIELD_1(sc, RAY_GET_CCS(pi), ray_cmd_tx, c_link, i);
1489
1490 RAY_DPRINTF(("%s: ray_alloc_tx_ccs bufp 0x%lx idx %d pidx %d \n",
1491 sc->sc_xname, bufp, i, pi));
1492
1493 return (bufp + RAY_TX_PHY_SIZE);
1494 }
1495
1496 /*
1497 * an update params command has completed lookup which command and
1498 * the status
1499 */
1500 static ray_cmd_func_t
1501 ray_update_params_done(sc, ccs, stat)
1502 struct ray_softc *sc;
1503 bus_size_t ccs;
1504 u_int stat;
1505 {
1506 ray_cmd_func_t rcmd;
1507
1508 rcmd = 0;
1509
1510 RAY_DPRINTF(("%s: ray_update_params_done stat %d\n",
1511 sc->sc_xname, stat));
1512
1513 /* this will get more complex as we add commands */
1514 if (stat == RAY_CCS_STATUS_FAIL) {
1515 printf("%s: failed to update a promisc\n", sc->sc_xname);
1516 /* XXX should probably reset */
1517 /* rcmd = ray_reset; */
1518 }
1519
1520 if (sc->sc_running & SCP_UPD_PROMISC) {
1521 ray_cmd_done(sc, SCP_UPD_PROMISC);
1522 sc->sc_promisc = SRAM_READ_1(sc, RAY_HOST_TO_ECF_BASE);
1523 RAY_DPRINTF(("%s: new promisc value %d\n", sc->sc_xname,
1524 sc->sc_promisc));
1525 } else if (sc->sc_updreq) {
1526 ray_cmd_done(sc, SCP_UPD_UPDATEPARAMS);
1527 /* get the update parameter */
1528 sc->sc_updreq->r_failcause =
1529 SRAM_READ_FIELD_1(sc, ccs, ray_cmd_update, c_failcause);
1530 sc->sc_updreq = 0;
1531 wakeup(ray_update_params);
1532
1533 rcmd = ray_start_join_net;
1534 }
1535 return (rcmd);
1536 }
1537
1538 /*
1539 * check too see if we have any pending commands.
1540 */
1541 static void
1542 ray_check_scheduled(arg)
1543 void *arg;
1544 {
1545 struct ray_softc *sc;
1546 int s, i, mask;
1547
1548 s = splnet();
1549
1550 sc = arg;
1551 RAY_DPRINTF((
1552 "%s: ray_check_scheduled enter schd 0x%x running 0x%x ready %d\n",
1553 sc->sc_xname, sc->sc_scheduled, sc->sc_running, RAY_ECF_READY(sc)));
1554
1555 if (sc->sc_timoneed) {
1556 untimeout(ray_check_scheduled, sc);
1557 sc->sc_timoneed = 0;
1558 }
1559
1560 /* if update subcmd is running -- clear it in scheduled */
1561 if (sc->sc_running & SCP_UPDATESUBCMD)
1562 sc->sc_scheduled &= ~SCP_UPDATESUBCMD;
1563
1564 mask = SCP_FIRST;
1565 for (i = 0; i < ray_ncmdtab; mask <<= 1, i++) {
1566 if ((sc->sc_scheduled & ~SCP_UPD_MASK) == 0)
1567 break;
1568 if (!RAY_ECF_READY(sc))
1569 break;
1570 if (sc->sc_scheduled & mask)
1571 (*ray_cmdtab[i])(sc);
1572 }
1573
1574 RAY_DPRINTF((
1575 "%s: ray_check_scheduled exit sched 0x%x running 0x%x ready %d\n",
1576 sc->sc_xname, sc->sc_scheduled, sc->sc_running, RAY_ECF_READY(sc)));
1577
1578 if (sc->sc_scheduled & ~SCP_UPD_MASK)
1579 ray_set_pending(sc, sc->sc_scheduled);
1580
1581 splx(s);
1582 }
1583
1584 /*
1585 * check for unreported returns
1586 *
1587 * this routine is coded to only expect one outstanding request for the
1588 * timed out requests at a time, but thats all that can be outstanding
1589 * per hardware limitations
1590 */
1591 static void
1592 ray_check_ccs(arg)
1593 void *arg;
1594 {
1595 ray_cmd_func_t fp;
1596 struct ray_softc *sc;
1597 u_int i, cmd, stat;
1598 bus_size_t ccs;
1599 int s;
1600
1601 s = splnet();
1602 sc = arg;
1603
1604 RAY_DPRINTF(("%s: ray_check_ccs\n", sc->sc_xname));
1605
1606 sc->sc_timocheck = 0;
1607 for (i = RAY_CCS_CMD_FIRST; i <= RAY_CCS_CMD_LAST; i++) {
1608 if (!sc->sc_ccsinuse[i])
1609 continue;
1610 ccs = RAY_GET_CCS(i);
1611 cmd = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd);
1612 switch (cmd) {
1613 case RAY_CMD_START_PARAMS:
1614 case RAY_CMD_UPDATE_MCAST:
1615 case RAY_CMD_UPDATE_PARAMS:
1616 stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status);
1617 RAY_DPRINTF(("%s: check ccs idx %d ccs 0x%lx "
1618 "cmd 0x%x stat %d\n", sc->sc_xname, i,
1619 ccs, cmd, stat));
1620 goto breakout;
1621 }
1622 }
1623 breakout:
1624 /* see if we got one of the commands we are looking for */
1625 if (i > RAY_CCS_CMD_LAST)
1626 ; /* nothign */
1627 else if (stat == RAY_CCS_STATUS_FREE) {
1628 stat = RAY_CCS_STATUS_COMPLETE;
1629 if ((fp = ray_ccs_done(sc, ccs)))
1630 (*fp)(sc);
1631 } else if (stat != RAY_CCS_STATUS_BUSY) {
1632 if (sc->sc_ccsinuse[i] == 1) {
1633 /* give a chance for the interrupt to occur */
1634 sc->sc_ccsinuse[i] = 2;
1635 if (!sc->sc_timocheck) {
1636 timeout(ray_check_ccs, sc, 1);
1637 sc->sc_timocheck = 1;
1638 }
1639 } else if ((fp = ray_ccs_done(sc, ccs)))
1640 (*fp)(sc);
1641 } else {
1642 timeout(ray_check_ccs, sc, RAY_CHECK_CCS_TIMEOUT);
1643 sc->sc_timocheck = 1;
1644 }
1645 splx(s);
1646 }
1647
1648 /*
1649 * read the counters, the card implements the following protocol
1650 * to keep the values from being changed while read: It checks
1651 * the `own' bit and if zero writes the current internal counter
1652 * value, it then sets the `own' bit to 1. If the `own' bit was 1 it
1653 * incremenets its internal counter. The user thus reads the counter
1654 * if the `own' bit is one and then sets the own bit to 0.
1655 */
1656 static void
1657 ray_update_error_counters(sc)
1658 struct ray_softc *sc;
1659 {
1660 bus_size_t csc;
1661
1662 /* try and update the error counters */
1663 csc = RAY_STATUS_BASE;
1664 if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_mrxo_own)) {
1665 sc->sc_rxoverflow +=
1666 SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_mrx_overflow);
1667 SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_mrxo_own, 0);
1668 }
1669 if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_mrxc_own)) {
1670 sc->sc_rxcksum +=
1671 SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_mrx_overflow);
1672 SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_mrxc_own, 0);
1673 }
1674 if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_rxhc_own)) {
1675 sc->sc_rxhcksum +=
1676 SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_rx_hcksum);
1677 SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_rxhc_own, 0);
1678 }
1679 sc->sc_rxnoise = SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_rx_noise);
1680 }
1681
1682 /*
1683 * one of the commands we issued has completed, process.
1684 */
1685 static ray_cmd_func_t
1686 ray_ccs_done(sc, ccs)
1687 struct ray_softc *sc;
1688 bus_size_t ccs;
1689 {
1690 struct ifnet *ifp;
1691 ray_cmd_func_t rcmd;
1692 u_int cmd, stat;
1693
1694 ifp = &sc->sc_if;
1695 cmd = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd);
1696 stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status);
1697
1698 RAY_DPRINTF(("%s: ray_ccs_done idx %ld cmd 0x%x stat %d\n",
1699 sc->sc_xname, RAY_GET_INDEX(ccs), cmd, stat));
1700
1701 rcmd = 0;
1702 switch (cmd) {
1703 /*
1704 * solicited commands
1705 */
1706 case RAY_CMD_START_PARAMS:
1707 /* start network */
1708 ray_cmd_done(sc, SCP_UPD_STARTUP);
1709
1710 /* ok to start queueing packets */
1711 sc->sc_if.if_flags &= ~IFF_OACTIVE;
1712
1713 sc->sc_omode = sc->sc_mode;
1714 memcpy(sc->sc_cnwid, sc->sc_dnwid, sizeof(sc->sc_cnwid));
1715
1716 rcmd = ray_start_join_net;
1717 break;
1718 case RAY_CMD_UPDATE_PARAMS:
1719 rcmd = ray_update_params_done(sc, ccs, stat);
1720 break;
1721 case RAY_CMD_REPORT_PARAMS:
1722 /* get the reported parameters */
1723 ray_cmd_done(sc, SCP_REPORTPARAMS);
1724 if (!sc->sc_repreq)
1725 break;
1726 sc->sc_repreq->r_failcause =
1727 SRAM_READ_FIELD_1(sc, ccs, ray_cmd_report, c_failcause);
1728 sc->sc_repreq->r_len =
1729 SRAM_READ_FIELD_1(sc, ccs, ray_cmd_report, c_len);
1730 ray_read_region(sc, RAY_ECF_TO_HOST_BASE, sc->sc_repreq->r_data,
1731 sc->sc_repreq->r_len);
1732 sc->sc_repreq = 0;
1733 wakeup(ray_report_params);
1734 break;
1735 case RAY_CMD_UPDATE_MCAST:
1736 ray_cmd_done(sc, SCP_UPD_MCAST);
1737 if (stat == RAY_CCS_STATUS_FAIL)
1738 rcmd = ray_reset;
1739 break;
1740 case RAY_CMD_START_NET:
1741 case RAY_CMD_JOIN_NET:
1742 rcmd = ray_start_join_net_done(sc, cmd, ccs, stat);
1743 break;
1744 case RAY_CMD_TX_REQ:
1745 if (sc->sc_if.if_flags & IFF_OACTIVE) {
1746 sc->sc_if.if_flags &= ~IFF_OACTIVE;
1747 /* this may also be a problem */
1748 rcmd = ray_intr_start;
1749 }
1750 /* free it -- no tracking */
1751 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status,
1752 RAY_CCS_STATUS_FREE);
1753 goto done;
1754 case RAY_CMD_START_ASSOC:
1755 ray_cmd_done(sc, SCP_STARTASSOC);
1756 if (stat == RAY_CCS_STATUS_FAIL)
1757 rcmd = ray_start_join_net; /* XXX check */
1758 else
1759 rcmd = ray_intr_start;
1760 break;
1761 case RAY_CMD_UPDATE_APM:
1762 case RAY_CMD_TEST_MEM:
1763 case RAY_CMD_SHUTDOWN:
1764 case RAY_CMD_DUMP_MEM:
1765 case RAY_CMD_START_TIMER:
1766 break;
1767 default:
1768 printf("%s: intr: unknown command 0x%x\n",
1769 sc->sc_if.if_xname, cmd);
1770 break;
1771 }
1772 ray_free_ccs(sc, ccs);
1773 done:
1774 /*
1775 * see if needed things can be done now that a command
1776 * has completed
1777 */
1778 ray_check_scheduled(sc);
1779
1780 return (rcmd);
1781 }
1782
1783 /*
1784 * an unsolicted interrupt, i.e., the ECF is sending us a command
1785 */
1786 static ray_cmd_func_t
1787 ray_rccs_intr(sc, ccs)
1788 struct ray_softc *sc;
1789 bus_size_t ccs;
1790 {
1791 ray_cmd_func_t rcmd;
1792 u_int cmd, stat;
1793
1794 cmd = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd);
1795 stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status);
1796
1797 RAY_DPRINTF(("%s: ray_rccs_intr idx %ld cmd 0x%x stat %d\n",
1798 sc->sc_xname, RAY_GET_INDEX(ccs), cmd, stat));
1799
1800 rcmd = 0;
1801 switch (cmd) {
1802 /*
1803 * unsolicted commands
1804 */
1805 case RAY_ECMD_RX_DONE:
1806 ray_recv(sc, ccs);
1807 goto done;
1808 case RAY_ECMD_REJOIN_DONE:
1809 rcmd = ray_start_assoc;
1810 break;
1811 case RAY_ECMD_ROAM_START:
1812 break;
1813 case RAY_ECMD_JAPAN_CALL_SIGNAL:
1814 break;
1815 default:
1816 ray_update_error_counters(sc);
1817
1818 /* this is a bogus return from build 4 don't free 0x55 */
1819 if (sc->sc_version == SC_BUILD_4 && cmd == 0x55
1820 && RAY_GET_INDEX(ccs) == 0x55) {
1821 goto done;
1822 }
1823 printf("%s: intr: unknown command 0x%x\n",
1824 sc->sc_if.if_xname, cmd);
1825 break;
1826 }
1827 /* free the ccs */
1828 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_FREE);
1829 done:
1830 return (rcmd);
1831 }
1832
1833 /*
1834 * process an interrupt
1835 */
1836 static int
1837 ray_intr(arg)
1838 void *arg;
1839 {
1840 struct ray_softc *sc;
1841 ray_cmd_func_t rcmd;
1842 u_int i, count;
1843
1844 sc = arg;
1845
1846 RAY_DPRINTF(("%s: ray_intr\n", sc->sc_xname));
1847
1848 if ((++sc->sc_checkcounters % 32) == 0)
1849 ray_update_error_counters(sc);
1850
1851 count = 0;
1852 rcmd = 0;
1853 if (!REG_READ(sc, RAY_HCSIR))
1854 count = 0;
1855 else {
1856 count = 1;
1857 i = SRAM_READ_1(sc, RAY_SCB_RCCSI);
1858 if (i <= RAY_CCS_LAST)
1859 rcmd = ray_ccs_done(sc, RAY_GET_CCS(i));
1860 else if (i <= RAY_RCCS_LAST)
1861 rcmd = ray_rccs_intr(sc, RAY_GET_CCS(i));
1862 else
1863 printf("%s: intr: bad cmd index %d\n", sc->sc_xname, i);
1864 }
1865
1866 if (rcmd)
1867 (*rcmd)(sc);
1868
1869 if (count)
1870 REG_WRITE(sc, RAY_HCSIR, 0);
1871
1872 RAY_DPRINTF(("%s: interrupt handled %d\n", sc->sc_xname, count));
1873
1874 return (count ? 1 : 0);
1875 }
1876
1877
1878 /*
1879 * Generic CCS handling
1880 */
1881
1882 /*
1883 * free the chain of descriptors -- used for freeing allocated tx chains
1884 */
1885 static void
1886 ray_free_ccs_chain(sc, ni)
1887 struct ray_softc *sc;
1888 u_int ni;
1889 {
1890 u_int i;
1891
1892 while ((i = ni) != RAY_CCS_LINK_NULL) {
1893 ni = SRAM_READ_FIELD_1(sc, RAY_GET_CCS(i), ray_cmd, c_link);
1894 SRAM_WRITE_FIELD_1(sc, RAY_GET_CCS(i), ray_cmd, c_status,
1895 RAY_CCS_STATUS_FREE);
1896 }
1897 }
1898
1899 /*
1900 * free up a cmd and return the old status
1901 * this routine is only used for commands
1902 */
1903 static u_int8_t
1904 ray_free_ccs(sc, ccs)
1905 struct ray_softc *sc;
1906 bus_size_t ccs;
1907 {
1908 u_int8_t stat;
1909
1910 RAY_DPRINTF(("%s: free_ccs idx %ld\n", sc->sc_xname,
1911 RAY_GET_INDEX(ccs)));
1912
1913 stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status);
1914 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_FREE);
1915 if (ccs <= RAY_GET_CCS(RAY_CCS_LAST))
1916 sc->sc_ccsinuse[RAY_GET_INDEX(ccs)] = 0;
1917
1918 return (stat);
1919 }
1920
1921 /*
1922 * returns 1 and in `ccb' the bus offset of the free ccb
1923 * or 0 if none are free
1924 *
1925 * If `track' is not zero, handles tracking this command
1926 * possibly indicating a callback is needed and setting a timeout
1927 * also if ECF isn't ready we terminate earlier to avoid overhead.
1928 *
1929 * this routine is only used for commands
1930 */
1931 static int
1932 ray_alloc_ccs(sc, ccsp, cmd, track)
1933 struct ray_softc *sc;
1934 bus_size_t *ccsp;
1935 u_int cmd, track;
1936 {
1937 bus_size_t ccs;
1938 u_int i;
1939
1940 RAY_DPRINTF(("%s: alloc_ccs cmd %d\n", sc->sc_xname, cmd));
1941
1942 /* for tracked commands, if not ready just set pending */
1943 if (track && !RAY_ECF_READY(sc)) {
1944 ray_cmd_schedule(sc, track);
1945 return (0);
1946 }
1947
1948 /* first scan our inuse array */
1949 for (i = RAY_CCS_CMD_FIRST; i <= RAY_CCS_CMD_LAST; i++) {
1950 /* XXX wonder if we have to probe here to make the card go */
1951 (void)SRAM_READ_FIELD_1(sc, RAY_GET_CCS(i), ray_cmd, c_status);
1952 if (!sc->sc_ccsinuse[i])
1953 break;
1954 }
1955 if (i > RAY_CCS_CMD_LAST) {
1956 if (track)
1957 ray_cmd_schedule(sc, track);
1958 return (0);
1959 }
1960 sc->sc_ccsinuse[i] = 1;
1961 ccs = RAY_GET_CCS(i);
1962 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_BUSY);
1963 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_cmd, cmd);
1964 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_link, RAY_CCS_LINK_NULL);
1965
1966 *ccsp = ccs;
1967 return (1);
1968 }
1969
1970
1971 /*
1972 * this function sets the pending bit for the command given in 'need'
1973 * and schedules a timeout if none is scheduled already. Any command
1974 * that uses the `host to ecf' region must be serialized.
1975 */
1976 static void
1977 ray_set_pending(sc, cmdf)
1978 struct ray_softc *sc;
1979 u_int cmdf;
1980 {
1981 RAY_DPRINTF(("%s: ray_set_pending 0x%x\n", sc->sc_xname, cmdf));
1982
1983 sc->sc_scheduled |= cmdf;
1984 if (!sc->sc_timoneed) {
1985 RAY_DPRINTF(("%s: ray_set_pending new timo\n", sc->sc_xname));
1986 timeout(ray_check_scheduled, sc, RAY_CHECK_SCHED_TIMEOUT);
1987 sc->sc_timoneed = 1;
1988 }
1989 }
1990
1991 /*
1992 * schedule the `cmdf' for completion later
1993 */
1994 static void
1995 ray_cmd_schedule(sc, cmdf)
1996 struct ray_softc *sc;
1997 int cmdf;
1998 {
1999 int track;
2000
2001 RAY_DPRINTF(("%s: ray_cmd_schedule 0x%x\n", sc->sc_xname, cmdf));
2002
2003 track = cmdf;
2004 if ((cmdf & SCP_UPD_MASK) == 0)
2005 ray_set_pending(sc, track);
2006 else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) {
2007 /* don't do timeout mechaniscm if subcmd already going */
2008 sc->sc_scheduled |= cmdf;
2009 } else
2010 ray_set_pending(sc, cmdf | SCP_UPDATESUBCMD);
2011 }
2012
2013 /*
2014 * check to see if `cmdf' has been scheduled
2015 */
2016 static int
2017 ray_cmd_is_scheduled(sc, cmdf)
2018 struct ray_softc *sc;
2019 int cmdf;
2020 {
2021 RAY_DPRINTF(("%s: ray_cmd_is_scheduled 0x%x\n", sc->sc_xname, cmdf));
2022
2023 return ((sc->sc_scheduled & cmdf) ? 1 : 0);
2024 }
2025
2026 /*
2027 * cancel a scheduled command (not a running one though!)
2028 */
2029 static void
2030 ray_cmd_cancel(sc, cmdf)
2031 struct ray_softc *sc;
2032 int cmdf;
2033 {
2034 RAY_DPRINTF(("%s: ray_cmd_cancel 0x%x\n", sc->sc_xname, cmdf));
2035
2036 sc->sc_scheduled &= ~cmdf;
2037 if ((cmdf & SCP_UPD_MASK) && (sc->sc_scheduled & SCP_UPD_MASK) == 0)
2038 sc->sc_scheduled &= ~SCP_UPDATESUBCMD;
2039
2040 /* if nothing else needed cancel the timer */
2041 if (sc->sc_scheduled == 0 && sc->sc_timoneed) {
2042 untimeout(ray_check_scheduled, sc);
2043 sc->sc_timoneed = 0;
2044 }
2045 }
2046
2047 /*
2048 * called to indicate the 'cmdf' has been issued
2049 */
2050 static void
2051 ray_cmd_ran(sc, cmdf)
2052 struct ray_softc *sc;
2053 int cmdf;
2054 {
2055 RAY_DPRINTF(("%s: ray_cmd_ran 0x%x\n", sc->sc_xname, cmdf));
2056
2057 if (cmdf & SCP_UPD_MASK)
2058 sc->sc_running |= cmdf | SCP_UPDATESUBCMD;
2059 else
2060 sc->sc_running |= cmdf;
2061
2062 if ((cmdf & SCP_TIMOCHECK_CMD_MASK) && !sc->sc_timocheck) {
2063 timeout(ray_check_ccs, sc, RAY_CHECK_CCS_TIMEOUT);
2064 sc->sc_timocheck = 1;
2065 }
2066 }
2067
2068 /*
2069 * check to see if `cmdf' has been issued
2070 */
2071 static int
2072 ray_cmd_is_running(sc, cmdf)
2073 struct ray_softc *sc;
2074 int cmdf;
2075 {
2076 RAY_DPRINTF(("%s: ray_cmd_is_running 0x%x\n", sc->sc_xname, cmdf));
2077
2078 return ((sc->sc_running & cmdf) ? 1 : 0);
2079 }
2080
2081 /*
2082 * the given `cmdf' that was issued has completed
2083 */
2084 static void
2085 ray_cmd_done(sc, cmdf)
2086 struct ray_softc *sc;
2087 int cmdf;
2088 {
2089 RAY_DPRINTF(("%s: ray_cmd_done 0x%x\n", sc->sc_xname, cmdf));
2090
2091 sc->sc_running &= ~cmdf;
2092 if (cmdf & SCP_UPD_MASK) {
2093 sc->sc_running &= ~SCP_UPDATESUBCMD;
2094 if (sc->sc_scheduled & SCP_UPD_MASK)
2095 ray_cmd_schedule(sc, sc->sc_scheduled & SCP_UPD_MASK);
2096 }
2097 if ((sc->sc_running & SCP_TIMOCHECK_CMD_MASK) == 0 && sc->sc_timocheck){
2098 untimeout(ray_check_ccs, sc);
2099 sc->sc_timocheck = 0;
2100 }
2101 }
2102
2103 /*
2104 * issue the command
2105 * only used for commands not tx
2106 */
2107 static int
2108 ray_issue_cmd(sc, ccs, track)
2109 struct ray_softc *sc;
2110 bus_size_t ccs;
2111 u_int track;
2112 {
2113 u_int i;
2114
2115 RAY_DPRINTF(("%s: ray_cmd_issue 0x%x\n", sc->sc_xname, track));
2116
2117 /*
2118 * XXX other drivers did this, but I think
2119 * what we really want to do is just make sure we don't
2120 * get here or that spinning is ok
2121 */
2122 i = 0;
2123 while (!RAY_ECF_READY(sc))
2124 if (++i > 50) {
2125 ray_free_ccs(sc, ccs);
2126 if (track)
2127 ray_cmd_schedule(sc, track);
2128 return (0);
2129 }
2130
2131 SRAM_WRITE_1(sc, RAY_SCB_CCSI, RAY_GET_INDEX(ccs));
2132 RAY_ECF_START_CMD(sc);
2133 ray_cmd_ran(sc, track);
2134
2135 return (1);
2136 }
2137
2138 /*
2139 * send a simple command if we can
2140 */
2141 static int
2142 ray_simple_cmd(sc, cmd, track)
2143 struct ray_softc *sc;
2144 u_int cmd, track;
2145 {
2146 bus_size_t ccs;
2147
2148 return (ray_alloc_ccs(sc, &ccs, cmd, track) &&
2149 ray_issue_cmd(sc, ccs, track));
2150 }
2151
2152 /*
2153 * Functions based on CCS commands
2154 */
2155
2156 /*
2157 * run a update subcommand
2158 */
2159 static void
2160 ray_update_subcmd(sc)
2161 struct ray_softc *sc;
2162 {
2163 int submask, i;
2164
2165 RAY_DPRINTF(("%s: ray_update_subcmd\n", sc->sc_xname));
2166
2167 ray_cmd_cancel(sc, SCP_UPDATESUBCMD);
2168 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
2169 return;
2170 submask = SCP_UPD_FIRST;
2171 for (i = 0; i < ray_nsubcmdtab; submask <<= 1, i++) {
2172 if ((sc->sc_scheduled & SCP_UPD_MASK) == 0)
2173 break;
2174 /* when done the next command will be scheduled */
2175 if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD))
2176 break;
2177 if (!RAY_ECF_READY(sc))
2178 break;
2179 /*
2180 * give priority to LSB -- e.g., if previous loop reschuled
2181 * doing this command after calling the function won't catch
2182 * if a later command sets an earlier bit
2183 */
2184 if (sc->sc_scheduled & ((submask - 1) & SCP_UPD_MASK))
2185 break;
2186 if (sc->sc_scheduled & submask)
2187 (*ray_subcmdtab[i])(sc);
2188 }
2189 }
2190
2191 /*
2192 * report a parameter
2193 */
2194 static void
2195 ray_report_params(sc)
2196 struct ray_softc *sc;
2197 {
2198 bus_size_t ccs;
2199
2200 ray_cmd_cancel(sc, SCP_REPORTPARAMS);
2201
2202 if (!sc->sc_repreq)
2203 return;
2204
2205 /* do the issue check before equality check */
2206 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
2207 return;
2208 else if (ray_cmd_is_running(sc, SCP_REPORTPARAMS)) {
2209 ray_cmd_schedule(sc, SCP_REPORTPARAMS);
2210 return;
2211 } else if (!ray_alloc_ccs(sc, &ccs, RAY_CMD_REPORT_PARAMS,
2212 SCP_REPORTPARAMS))
2213 return;
2214
2215 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_report, c_paramid,
2216 sc->sc_repreq->r_paramid);
2217 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_report, c_nparam, 1);
2218 (void)ray_issue_cmd(sc, ccs, SCP_REPORTPARAMS);
2219 }
2220
2221 /*
2222 * start an association
2223 */
2224 static void
2225 ray_start_assoc(sc)
2226 struct ray_softc *sc;
2227 {
2228 ray_cmd_cancel(sc, SCP_STARTASSOC);
2229 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
2230 return;
2231 else if (ray_cmd_is_running(sc, SCP_STARTASSOC))
2232 return;
2233 (void)ray_simple_cmd(sc, RAY_CMD_START_ASSOC, SCP_STARTASSOC);
2234 }
2235
2236 /*
2237 * Subcommand functions that use the SCP_UPDATESUBCMD command
2238 * (and are serialized with respect to other update sub commands
2239 */
2240
2241 /*
2242 * download the startup parameters to the card
2243 * -- no outstanding commands expected
2244 */
2245 static void
2246 ray_download_params(sc)
2247 struct ray_softc *sc;
2248 {
2249 struct ray_startup_params_head *sp;
2250 struct ray_startup_params_tail_5 *sp5;
2251 struct ray_startup_params_tail_4 *sp4;
2252 bus_size_t off;
2253
2254 RAY_DPRINTF(("%s: init_startup_params\n", sc->sc_xname));
2255
2256 ray_cmd_cancel(sc, SCP_UPD_STARTUP);
2257
2258 #define PUT2(p, v) \
2259 do { (p)[0] = ((v >> 8) & 0xff); (p)[1] = (v & 0xff); } while(0)
2260
2261 sp = &sc->sc_startup;
2262 sp4 = &sc->sc_startup_4;
2263 sp5 = &sc->sc_startup_5;
2264 memset(sp, 0, sizeof(*sp));
2265 if (sc->sc_version == SC_BUILD_4)
2266 memset(sp4, 0, sizeof(*sp4));
2267 else
2268 memset(sp5, 0, sizeof(*sp5));
2269 memcpy(sp->sp_ssid, sc->sc_dnwid, sizeof(sp->sp_ssid));
2270 sp->sp_scan_mode = 0x1;
2271 memcpy(sp->sp_mac_addr, sc->sc_ecf_startup.e_station_addr,
2272 ETHER_ADDR_LEN);
2273 PUT2(sp->sp_frag_thresh, 0x7fff); /* disabled */
2274 if (sc->sc_version == SC_BUILD_4) {
2275 #if 1
2276 /* linux/fbsd */
2277 PUT2(sp->sp_dwell_time, 0x200);
2278 PUT2(sp->sp_beacon_period, 1);
2279 #else
2280 /* divined */
2281 PUT2(sp->sp_dwell_time, 0x400);
2282 PUT2(sp->sp_beacon_period, 0);
2283 #endif
2284 } else {
2285 PUT2(sp->sp_dwell_time, 128);
2286 PUT2(sp->sp_beacon_period, 256);
2287 }
2288 sp->sp_dtim_interval = 1;
2289 #if 0
2290 /* these are the documented defaults for build 5/6 */
2291 sp->sp_max_retry = 0x1f;
2292 sp->sp_ack_timo = 0x86;
2293 sp->sp_sifs = 0x1c;
2294 #elif 1
2295 /* these were scrounged from the linux driver */
2296 sp->sp_max_retry = 0x07;
2297
2298 sp->sp_ack_timo = 0xa3;
2299 sp->sp_sifs = 0x1d;
2300 #else
2301 /* these were divined */
2302 sp->sp_max_retry = 0x03;
2303
2304 sp->sp_ack_timo = 0xa3;
2305 sp->sp_sifs = 0x1d;
2306 #endif
2307 #if 0
2308 /* these are the documented defaults for build 5/6 */
2309 sp->sp_difs = 0x82;
2310 sp->sp_pifs = 0;
2311 #else
2312 /* linux/fbsd */
2313 sp->sp_difs = 0x82;
2314
2315 if (sc->sc_version == SC_BUILD_4)
2316 sp->sp_pifs = 0xce;
2317 else
2318 sp->sp_pifs = 0x4e;
2319 #endif
2320
2321 PUT2(sp->sp_rts_thresh, 0x7fff); /* disabled */
2322 if (sc->sc_version == SC_BUILD_4) {
2323 PUT2(sp->sp_scan_dwell, 0xfb1e);
2324 PUT2(sp->sp_scan_max_dwell, 0xc75c);
2325 } else {
2326 PUT2(sp->sp_scan_dwell, 0x4e2);
2327 PUT2(sp->sp_scan_max_dwell, 0x38a4);
2328 }
2329 sp->sp_assoc_timo = 0x5;
2330 if (sc->sc_version == SC_BUILD_4) {
2331 #if 0
2332 /* linux/fbsd */
2333 sp->sp_adhoc_scan_cycle = 0x4;
2334 sp->sp_infra_scan_cycle = 0x2;
2335 sp->sp_infra_super_scan_cycle = 0x4;
2336 #else
2337 /* divined */
2338 sp->sp_adhoc_scan_cycle = 0x8;
2339 sp->sp_infra_scan_cycle = 0x1;
2340 sp->sp_infra_super_scan_cycle = 0x18;
2341 #endif
2342 } else {
2343 sp->sp_adhoc_scan_cycle = 0x8;
2344 sp->sp_infra_scan_cycle = 0x2;
2345 sp->sp_infra_super_scan_cycle = 0x8;
2346 }
2347 sp->sp_promisc = sc->sc_promisc;
2348 PUT2(sp->sp_uniq_word, 0x0cbd);
2349 if (sc->sc_version == SC_BUILD_4) {
2350 /* XXX whats this value anyway.. the std says 50us */
2351 /* XXX sp->sp_slot_time = 0x4e; */
2352 sp->sp_slot_time = 0x4e;
2353 #if 1
2354 /*linux/fbsd*/
2355 sp->sp_roam_low_snr_thresh = 0xff;
2356 #else
2357 /*divined*/
2358 sp->sp_roam_low_snr_thresh = 0x30;
2359 #endif
2360 } else {
2361 sp->sp_slot_time = 0x32;
2362 sp->sp_roam_low_snr_thresh = 0xff; /* disabled */
2363 }
2364 #if 1
2365 sp->sp_low_snr_count = 0xff; /* disabled */
2366 #else
2367 /* divined -- check */
2368 sp->sp_low_snr_count = 0x07; /* disabled */
2369 #endif
2370 #if 0
2371 sp->sp_infra_missed_beacon_count = 0x2;
2372 #elif 1
2373 /* linux/fbsd */
2374 sp->sp_infra_missed_beacon_count = 0x5;
2375 #else
2376 /* divined -- check, looks fishy */
2377 sp->sp_infra_missed_beacon_count = 0x7;
2378 #endif
2379 sp->sp_adhoc_missed_beacon_count = 0xff;
2380 sp->sp_country_code = sc->sc_dcountrycode;
2381 sp->sp_hop_seq = 0x0b;
2382 if (sc->sc_version == SC_BUILD_4) {
2383 sp->sp_hop_seq_len = 0x4e;
2384 sp4->sp_cw_max = 0x3f; /* single byte on build 4 */
2385 sp4->sp_cw_min = 0x0f; /* single byte on build 4 */
2386 sp4->sp_noise_filter_gain = 0x4;
2387 sp4->sp_noise_limit_offset = 0x8;
2388 sp4->sp_rssi_thresh_offset = 0x28;
2389 sp4->sp_busy_thresh_offset = 0x28;
2390 sp4->sp_sync_thresh = 0x07;
2391 sp4->sp_test_mode = 0x0;
2392 sp4->sp_test_min_chan = 0x2;
2393 sp4->sp_test_max_chan = 0x2;
2394 } else {
2395 sp->sp_hop_seq_len = 0x4f;
2396 PUT2(sp5->sp_cw_max, 0x3f);
2397 PUT2(sp5->sp_cw_min, 0x0f);
2398 sp5->sp_noise_filter_gain = 0x4;
2399 sp5->sp_noise_limit_offset = 0x8;
2400 sp5->sp_rssi_thresh_offset = 0x28;
2401 sp5->sp_busy_thresh_offset = 0x28;
2402 sp5->sp_sync_thresh = 0x07;
2403 sp5->sp_test_mode = 0x0;
2404 sp5->sp_test_min_chan = 0x2;
2405 sp5->sp_test_max_chan = 0x2;
2406 #if 0
2407 sp5->sp_allow_probe_resp = 0x1;
2408 #else
2409 sp5->sp_allow_probe_resp = 0x0;
2410 #endif
2411 sp5->sp_privacy_must_start = 0x0;
2412 sp5->sp_privacy_can_join = 0x0;
2413 sp5->sp_basic_rate_set[0] = 0x2;
2414 /* 2 = 1Mbps, 3 = old 2Mbps 4 = 2Mbps */
2415 }
2416
2417 /* we shouldn't be called with some command pending */
2418 if (!RAY_ECF_READY(sc))
2419 panic("ray_download_params busy");
2420
2421 /* write the compatible part */
2422 off = RAY_HOST_TO_ECF_BASE;
2423 ray_write_region(sc, off, sp, sizeof(sc->sc_startup));
2424 off += sizeof(sc->sc_startup);
2425 if (sc->sc_version == SC_BUILD_4)
2426 ray_write_region(sc, off, sp4, sizeof(*sp4));
2427 else
2428 ray_write_region(sc, off, sp5, sizeof(*sp5));
2429 if (!ray_simple_cmd(sc, RAY_CMD_START_PARAMS, SCP_UPD_STARTUP))
2430 panic("ray_download_params issue");
2431 }
2432
2433 /*
2434 * start or join a network
2435 */
2436 static void
2437 ray_start_join_net(sc)
2438 struct ray_softc *sc;
2439 {
2440 struct ray_net_params np;
2441 bus_size_t ccs;
2442 int cmd;
2443
2444 ray_cmd_cancel(sc, SCP_UPD_STARTJOIN);
2445 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
2446 return;
2447
2448 /* XXX check we may not want to re-issue */
2449 if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) {
2450 ray_cmd_schedule(sc, SCP_UPD_STARTJOIN);
2451 return;
2452 }
2453
2454 if (sc->sc_mode == SC_MODE_ADHOC)
2455 cmd = RAY_CMD_START_NET;
2456 else
2457 cmd = RAY_CMD_JOIN_NET;
2458
2459 if (!ray_alloc_ccs(sc, &ccs, cmd, SCP_UPD_STARTJOIN))
2460 return;
2461 sc->sc_startccs = ccs;
2462 sc->sc_startcmd = cmd;
2463 if (!memcmp(sc->sc_cnwid, sc->sc_dnwid, sizeof(sc->sc_cnwid))
2464 && sc->sc_omode == sc->sc_mode)
2465 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_upd_param, 0);
2466 else {
2467 memset(&np, 0, sizeof(np));
2468 np.p_net_type = sc->sc_mode;
2469 memcpy(np.p_ssid, sc->sc_dnwid, sizeof(np.p_ssid));
2470 ray_write_region(sc, RAY_HOST_TO_ECF_BASE, &np, sizeof(np));
2471 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_upd_param, 1);
2472 }
2473 if (ray_issue_cmd(sc, ccs, SCP_UPD_STARTJOIN))
2474 timeout(ray_start_join_timo, sc, RAY_START_TIMEOUT);
2475 }
2476
2477 static void
2478 ray_start_join_timo(arg)
2479 void *arg;
2480 {
2481 struct ray_softc *sc;
2482 u_int stat;
2483
2484 sc = arg;
2485 stat = SRAM_READ_FIELD_1(sc, sc->sc_startccs, ray_cmd, c_status);
2486 ray_start_join_net_done(sc, sc->sc_startcmd, sc->sc_startccs, stat);
2487 }
2488
2489 /*
2490 * The start/join has completed. Note: we timeout the start
2491 * command because it seems to fail to work at least on the
2492 * build 4 firmware without reporting an error. This actually
2493 * may be a result of not putting the correct params in the
2494 * initial download. If this is a timeout `stat' will be
2495 * marked busy.
2496 */
2497 static ray_cmd_func_t
2498 ray_start_join_net_done(sc, cmd, ccs, stat)
2499 struct ray_softc *sc;
2500 u_int cmd;
2501 bus_size_t ccs;
2502 u_int stat;
2503 {
2504 struct ray_net_params np;
2505
2506 untimeout(ray_start_join_timo, sc);
2507 ray_cmd_done(sc, SCP_UPD_STARTJOIN);
2508
2509 if (stat == RAY_CCS_STATUS_FAIL) {
2510 /* XXX poke ifmedia when it supports this */
2511 sc->sc_havenet = 0;
2512 return (ray_start_join_net);
2513 }
2514 if (stat == RAY_CCS_STATUS_BUSY || stat == RAY_CCS_STATUS_FREE) {
2515 /* handle the timeout condition */
2516 timeout(ray_start_join_timo, sc, RAY_START_TIMEOUT);
2517
2518 /* be safe -- not a lot occurs with no net though */
2519 if (!RAY_ECF_READY(sc))
2520 return (0);
2521
2522 /* see if our nwid is up to date */
2523 if (!memcmp(sc->sc_cnwid, sc->sc_dnwid, sizeof(sc->sc_cnwid))
2524 && sc->sc_omode == sc->sc_mode)
2525 SRAM_WRITE_FIELD_1(sc,ccs, ray_cmd_net, c_upd_param, 0);
2526 else {
2527 memset(&np, 0, sizeof(np));
2528 np.p_net_type = sc->sc_mode;
2529 memcpy(np.p_ssid, sc->sc_dnwid, sizeof(np.p_ssid));
2530 ray_write_region(sc, RAY_HOST_TO_ECF_BASE, &np,
2531 sizeof(np));
2532 SRAM_WRITE_FIELD_1(sc,ccs, ray_cmd_net, c_upd_param, 1);
2533 }
2534
2535 if (sc->sc_mode == SC_MODE_ADHOC)
2536 cmd = RAY_CMD_START_NET;
2537 else
2538 cmd = RAY_CMD_JOIN_NET;
2539 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_cmd,
2540 RAY_CCS_STATUS_BUSY);
2541 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_status,
2542 RAY_CCS_STATUS_BUSY);
2543
2544 /* we simply poke the card again issuing the same ccs */
2545 SRAM_WRITE_1(sc, RAY_SCB_CCSI, RAY_GET_INDEX(ccs));
2546 RAY_ECF_START_CMD(sc);
2547 ray_cmd_ran(sc, SCP_UPD_STARTJOIN);
2548 return (0);
2549 }
2550 /* get the current ssid */
2551 SRAM_READ_FIELD_N(sc, ccs, ray_cmd_net, c_bss_id, sc->sc_bssid,
2552 sizeof(sc->sc_bssid));
2553
2554 sc->sc_deftxrate = SRAM_READ_FIELD_1(sc, ccs, ray_cmd_net,c_def_txrate);
2555 sc->sc_encrypt = SRAM_READ_FIELD_1(sc, ccs, ray_cmd_net, c_encrypt);
2556
2557 /* adjust values for buggy build 4 */
2558 if (sc->sc_deftxrate == 0x55)
2559 sc->sc_deftxrate = RAY_PID_BASIC_RATE_1500K;
2560 if (sc->sc_encrypt == 0x55)
2561 sc->sc_encrypt = 0;
2562
2563 if (SRAM_READ_FIELD_1(sc, ccs, ray_cmd_net, c_upd_param)) {
2564 ray_read_region(sc, RAY_HOST_TO_ECF_BASE, &np, sizeof(np));
2565 memcpy(sc->sc_cnwid, np.p_ssid, sizeof(sc->sc_cnwid));
2566 sc->sc_omode = sc->sc_mode;
2567 if (np.p_net_type != sc->sc_mode)
2568 return (ray_start_join_net);
2569 }
2570 RAY_DPRINTF(("%s: net start/join nwid %.32s bssid %s inited %d\n",
2571 sc->sc_xname, sc->sc_cnwid, ether_sprintf(sc->sc_bssid),
2572 SRAM_READ_FIELD_1(sc, ccs, ray_cmd_net, c_inited)));
2573
2574 /* network is now active */
2575 sc->sc_havenet = 1;
2576 ray_cmd_schedule(sc, SCP_UPD_MCAST|SCP_UPD_PROMISC);
2577 if (cmd == RAY_CMD_JOIN_NET)
2578 return (ray_start_assoc);
2579 else
2580 return (ray_intr_start);
2581 }
2582
2583 /*
2584 * set the card in/out of promiscuous mode
2585 */
2586 static void
2587 ray_update_promisc(sc)
2588 struct ray_softc *sc;
2589 {
2590 bus_size_t ccs;
2591 int promisc;
2592
2593 ray_cmd_cancel(sc, SCP_UPD_PROMISC);
2594
2595 /* do the issue check before equality check */
2596 promisc = !!(sc->sc_if.if_flags & (IFF_PROMISC | IFF_ALLMULTI));
2597 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
2598 return;
2599 else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) {
2600 ray_cmd_schedule(sc, SCP_UPD_PROMISC);
2601 return;
2602 } else if (promisc == sc->sc_promisc)
2603 return;
2604 else if (!ray_alloc_ccs(sc,&ccs,RAY_CMD_UPDATE_PARAMS, SCP_UPD_PROMISC))
2605 return;
2606 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_paramid, RAY_PID_PROMISC);
2607 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_nparam, 1);
2608 SRAM_WRITE_1(sc, RAY_HOST_TO_ECF_BASE, promisc);
2609 (void)ray_issue_cmd(sc, ccs, SCP_UPD_PROMISC);
2610 }
2611
2612 /*
2613 * update the parameter based on what the user passed in
2614 */
2615 static void
2616 ray_update_params(sc)
2617 struct ray_softc *sc;
2618 {
2619 bus_size_t ccs;
2620
2621 ray_cmd_cancel(sc, SCP_UPD_UPDATEPARAMS);
2622 if (!sc->sc_updreq) {
2623 /* XXX do we need to wakeup here? */
2624 return;
2625 }
2626
2627 /* do the issue check before equality check */
2628 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
2629 return;
2630 else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) {
2631 ray_cmd_schedule(sc, SCP_UPD_UPDATEPARAMS);
2632 return;
2633 } else if (!ray_alloc_ccs(sc, &ccs, RAY_CMD_UPDATE_PARAMS,
2634 SCP_UPD_UPDATEPARAMS))
2635 return;
2636
2637 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_paramid,
2638 sc->sc_updreq->r_paramid);
2639 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_nparam, 1);
2640 ray_write_region(sc, RAY_HOST_TO_ECF_BASE, sc->sc_updreq->r_data,
2641 sc->sc_updreq->r_len);
2642
2643 (void)ray_issue_cmd(sc, ccs, SCP_UPD_UPDATEPARAMS);
2644 }
2645
2646 /*
2647 * set the multicast filter list
2648 */
2649 static void
2650 ray_update_mcast(sc)
2651 struct ray_softc *sc;
2652 {
2653 bus_size_t ccs;
2654 struct ether_multistep step;
2655 struct ether_multi *enm;
2656 struct ethercom *ec;
2657 bus_size_t bufp;
2658 int count;
2659
2660 ec = &sc->sc_ec;
2661 ray_cmd_cancel(sc, SCP_UPD_MCAST);
2662
2663 /* see if we have any ranges */
2664 if ((count = sc->sc_ec.ec_multicnt) < 17) {
2665 ETHER_FIRST_MULTI(step, ec, enm);
2666 while (enm) {
2667 /* see if this is a range */
2668 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
2669 ETHER_ADDR_LEN)) {
2670 count = 17;
2671 break;
2672 }
2673 ETHER_NEXT_MULTI(step, enm);
2674 }
2675 }
2676
2677 /* track this stuff even when not running */
2678 if (count > 16) {
2679 sc->sc_if.if_flags |= IFF_ALLMULTI;
2680 ray_update_promisc(sc);
2681 return;
2682 } else if (sc->sc_if.if_flags & IFF_ALLMULTI) {
2683 sc->sc_if.if_flags &= ~IFF_ALLMULTI;
2684 ray_update_promisc(sc);
2685 }
2686
2687 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
2688 return;
2689 else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) {
2690 ray_cmd_schedule(sc, SCP_UPD_MCAST);
2691 return;
2692 } else if (!ray_alloc_ccs(sc,&ccs, RAY_CMD_UPDATE_MCAST, SCP_UPD_MCAST))
2693 return;
2694 SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update_mcast, c_nmcast, count);
2695 bufp = RAY_HOST_TO_ECF_BASE;
2696 ETHER_FIRST_MULTI(step, ec, enm);
2697 while (enm) {
2698 ray_write_region(sc, bufp, enm->enm_addrlo, ETHER_ADDR_LEN);
2699 bufp += ETHER_ADDR_LEN;
2700 ETHER_NEXT_MULTI(step, enm);
2701 }
2702 (void)ray_issue_cmd(sc, ccs, SCP_UPD_MCAST);
2703 }
2704
2705 /*
2706 * User issued commands
2707 */
2708
2709 /*
2710 * issue a update params
2711 *
2712 * expected to be called in sleapable context -- intended for user stuff
2713 */
2714 static int
2715 ray_user_update_params(sc, pr)
2716 struct ray_softc *sc;
2717 struct ray_param_req *pr;
2718 {
2719 int rv;
2720
2721 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
2722 pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP;
2723 return (EIO);
2724 }
2725
2726 /* wait to be able to issue the command */
2727 rv = 0;
2728 while (ray_cmd_is_running(sc, SCP_UPD_UPDATEPARAMS) ||
2729 ray_cmd_is_scheduled(sc, SCP_UPD_UPDATEPARAMS)) {
2730 rv = tsleep(ray_update_params, 0|PCATCH, "cmd in use", 0);
2731 if (rv)
2732 return (rv);
2733 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
2734 pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP;
2735 return (EIO);
2736 }
2737 }
2738
2739 pr->r_failcause = RAY_FAILCAUSE_WAITING;
2740 sc->sc_updreq = pr;
2741 ray_cmd_schedule(sc, SCP_UPD_UPDATEPARAMS);
2742 ray_check_scheduled(sc);
2743
2744 while (pr->r_failcause == RAY_FAILCAUSE_WAITING)
2745 (void)tsleep(ray_update_params, 0, "waiting cmd", 0);
2746 wakeup(ray_update_params);
2747
2748 return (0);
2749 }
2750
2751 /*
2752 * issue a report params
2753 *
2754 * expected to be called in sleapable context -- intended for user stuff
2755 */
2756 static int
2757 ray_user_report_params(sc, pr)
2758 struct ray_softc *sc;
2759 struct ray_param_req *pr;
2760 {
2761 int rv;
2762
2763 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
2764 pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP;
2765 return (EIO);
2766 }
2767
2768 /* wait to be able to issue the command */
2769 rv = 0;
2770 while (ray_cmd_is_running(sc, SCP_REPORTPARAMS)
2771 || ray_cmd_is_scheduled(sc, SCP_REPORTPARAMS)) {
2772 rv = tsleep(ray_report_params, 0|PCATCH, "cmd in use", 0);
2773 if (rv)
2774 return (rv);
2775 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
2776 pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP;
2777 return (EIO);
2778 }
2779 }
2780
2781 pr->r_failcause = RAY_FAILCAUSE_WAITING;
2782 sc->sc_repreq = pr;
2783 ray_cmd_schedule(sc, SCP_REPORTPARAMS);
2784 ray_check_scheduled(sc);
2785
2786 while (pr->r_failcause == RAY_FAILCAUSE_WAITING)
2787 (void)tsleep(ray_report_params, 0, "waiting cmd", 0);
2788 wakeup(ray_report_params);
2789
2790 return (0);
2791 }
2792
2793
2794 /*
2795 * this is a temporary wrapper around bus_space_read_region_1
2796 * as it seems to mess with gcc. the line numbers get offset
2797 * presumably this is related to the inline asm on i386.
2798 */
2799
2800 static void
2801 ray_read_region(sc, off, vp, c)
2802 struct ray_softc *sc;
2803 bus_size_t off;
2804 void *vp;
2805 size_t c;
2806 {
2807 u_int n2, n4, tmp;
2808 u_int8_t *p;
2809
2810 p = vp;
2811
2812 /* XXX we may be making poor assumptions here but lets hope */
2813 switch ((off|(bus_addr_t)p) & 0x03) {
2814 case 0:
2815 if ((n4 = c / 4)) {
2816 bus_space_read_region_4(sc->sc_memt, sc->sc_memh, off,
2817 p, n4);
2818 tmp = c & ~0x3;
2819 c &= 0x3;
2820 p += tmp;
2821 off += tmp;
2822 }
2823 switch (c) {
2824 case 3:
2825 *p = bus_space_read_1(sc->sc_memt,sc->sc_memh, off);
2826 p++, off++;
2827 case 2:
2828 *p = bus_space_read_1(sc->sc_memt,sc->sc_memh, off);
2829 p++, off++;
2830 case 1:
2831 *p = bus_space_read_1(sc->sc_memt,sc->sc_memh, off);
2832 }
2833 break;
2834 case 2:
2835 if ((n2 = (c >> 1)))
2836 bus_space_read_region_2(sc->sc_memt, sc->sc_memh, off,
2837 p, n2);
2838 if (c & 1) {
2839 c &= ~0x1;
2840 *(p + c) = bus_space_read_1(sc->sc_memt, sc->sc_memh,
2841 off + c);
2842 }
2843 break;
2844 case 1:
2845 case 3:
2846 bus_space_read_region_1(sc->sc_memt, sc->sc_memh, off, p, c);
2847 break;
2848 }
2849 }
2850
2851 /*
2852 * this is a temporary wrapper around bus_space_write_region_1
2853 * as it seems to mess with gcc. the line numbers get offset
2854 * presumably this is related to the inline asm on i386.
2855 */
2856 static void
2857 ray_write_region(sc, off, vp, c)
2858 struct ray_softc *sc;
2859 bus_size_t off;
2860 void *vp;
2861 size_t c;
2862 {
2863 size_t n2, n4, tmp;
2864 u_int8_t *p;
2865
2866 p = vp;
2867 /* XXX we may be making poor assumptions here but lets hope */
2868 switch ((off|(bus_addr_t)p) & 0x03) {
2869 case 0:
2870 if ((n4 = (c >> 2))) {
2871 bus_space_write_region_4(sc->sc_memt, sc->sc_memh, off,
2872 p, n4);
2873 tmp = c & ~0x3;
2874 c &= 0x3;
2875 p += tmp;
2876 off += tmp;
2877 }
2878 switch (c) {
2879 case 3:
2880 bus_space_write_1(sc->sc_memt,sc->sc_memh, off, *p);
2881 p++, off++;
2882 case 2:
2883 bus_space_write_1(sc->sc_memt,sc->sc_memh, off, *p);
2884 p++, off++;
2885 case 1:
2886 bus_space_write_1(sc->sc_memt,sc->sc_memh, off, *p);
2887 }
2888 break;
2889 case 2:
2890 if ((n2 = (c >> 1)))
2891 bus_space_write_region_2(sc->sc_memt, sc->sc_memh, off,
2892 p, n2);
2893 if (c & 0x1) {
2894 c &= ~0x1;
2895 bus_space_write_1(sc->sc_memt, sc->sc_memh,
2896 off + c, *(p + c));
2897 }
2898 break;
2899 case 1:
2900 case 3:
2901 bus_space_write_region_1(sc->sc_memt, sc->sc_memh, off, p, c);
2902 break;
2903 }
2904 }
2905
2906 #ifdef RAY_DEBUG
2907
2908 #define PRINTABLE(c) ((c) >= 0x20 && (c) <= 0x7f)
2909
2910 void
2911 hexdump(const u_int8_t *d, int len, int br, int div, int fl)
2912 {
2913 int i, j, offw, first, tlen, ni, nj, sp;
2914
2915 sp = br / div;
2916 offw = 0;
2917 if (len && (fl & HEXDF_NOOFFSET) == 0) {
2918 tlen = len;
2919 do {
2920 offw++;
2921 } while (tlen /= br);
2922 }
2923 if (offw)
2924 printf("%0*x: ", offw, 0);
2925 for (i = 0; i < len; i++, d++) {
2926 if (i && (i % br) == 0) {
2927 if ((fl & HEXDF_NOASCII) == 0) {
2928 printf(" ");
2929 d -= br;
2930 for (j = 0; j < br; d++, j++) {
2931 if (j && (j % sp) == 0)
2932 printf(" ");
2933 if (PRINTABLE(*d))
2934 printf("%c", (int)*d);
2935 else
2936 printf(".");
2937 }
2938 }
2939 if (offw)
2940 printf("\n%0*x: ", offw, i);
2941 else
2942 printf("\n");
2943 if ((fl & HEXDF_NOCOMPRESS) == 0) {
2944 first = 1;
2945 while (len - i >= br) {
2946 if (memcmp(d, d - br, br))
2947 break;
2948 d += br;
2949 i += br;
2950 if (first) {
2951 printf("*");
2952 first = 0;
2953 }
2954 }
2955 if (len == i) {
2956 printf("\n%0*x", offw, i);
2957 return;
2958 }
2959 }
2960 } else if (i && (i % sp) == 0)
2961 printf(" ");
2962 printf("%02x ", *d);
2963 }
2964 if (len && (((i - 1) % br) || i == 1)) {
2965 if ((fl & HEXDF_NOASCII) == 0) {
2966 i = i % br ? i % br : br;
2967 ni = (br - i) % br;
2968 j = (i - 1) / sp;
2969 nj = (div - j - 1) % div;
2970 j = 3 * ni + nj + 3;
2971 printf("%*s", j, "");
2972 d -= i;
2973 for (j = 0; j < i; d++, j++) {
2974 if (j && (j % sp) == 0)
2975 printf(" ");
2976 if (PRINTABLE(*d))
2977 printf("%c", (int)*d);
2978 else
2979 printf(".");
2980 }
2981 }
2982 printf("\n");
2983 }
2984 }
2985
2986
2987
2988 static void
2989 ray_dump_mbuf(sc, m)
2990 struct ray_softc *sc;
2991 struct mbuf *m;
2992 {
2993 u_int8_t *d, *ed;
2994 u_int i;
2995
2996 printf("%s: pkt dump:", sc->sc_xname);
2997 i = 0;
2998 for (; m; m = m->m_next) {
2999 d = mtod(m, u_int8_t *);
3000 ed = d + m->m_len;
3001
3002 for (; d < ed; i++, d++) {
3003 if ((i % 16) == 0)
3004 printf("\n\t");
3005 else if ((i % 8) == 0)
3006 printf(" ");
3007 printf(" %02x", *d);
3008 }
3009 }
3010 if ((i - 1) % 16)
3011 printf("\n");
3012 }
3013 #endif /* RAY_DEBUG */
3014