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