1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
|
/*-
* Copyright (C) 2000
* Dr. Duncan McLennan Barclay, dmlb@ragnet.demon.co.uk.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY DUNCAN BARCLAY AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL DUNCAN BARCLAY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*
*/
/*
* Network parameters, used twice in softc to store what we want and what
* we have.
*
* The current parameters are ONLY valid in a function called from the runq
* and should not be accessed directly from ioctls.
*/
struct ray_nw_param {
struct ray_cmd_net p_1;
struct ray_net_params \
p_2;
u_int8_t np_ap_status;
int np_promisc; /* Promiscious mode status */
int np_framing; /* Packet framing types */
int np_auth; /* Authentication status */
int np_havenet; /* True if we have a network */
};
#define np_upd_param p_1.c_upd_param
#define np_bss_id p_1.c_bss_id
#define np_inited p_1.c_inited
#define np_def_txrate p_1.c_def_txrate
#define np_encrypt p_1.c_encrypt
#define np_net_type p_2.p_net_type
#define np_ssid p_2.p_ssid
#define np_priv_start p_2.p_privacy_must_start
#define np_priv_join p_2.p_privacy_can_join
/*
* One of these structures per allocated device
*/
struct ray_softc {
device_t dev; /* Device */
struct ifnet *ifp; /* Ethernet common */
struct callout_handle
tx_timerh; /* Handle for tx timer */
struct callout_handle
com_timerh; /* Handle for command timer */
bus_space_tag_t am_bst; /* Bus space tag for attribute memory */
bus_space_handle_t am_bsh; /* Bus space handle for attribute mem */
int am_rid; /* Resource id for attribute memory */
struct resource* am_res; /* Resource for attribute memory */
bus_space_tag_t cm_bst; /* Bus space tag for common memory */
bus_space_handle_t cm_bsh; /* Bus space handle for common memory */
int cm_rid; /* Resource id for common memory */
struct resource* cm_res; /* Resource for common memory */
int irq_rid; /* Resource id for irq */
struct resource* irq_res; /* Resource for irq */
void * irq_handle; /* Handle for irq handler */
u_int8_t sc_ccsinuse[64];/* ccss' in use -- not for tx */
u_char sc_gone; /* 1 = Card bailed out */
struct ray_ecf_startup_v5
sc_ecf_startup; /* Startup info from card */
TAILQ_HEAD(ray_comq, ray_comq_entry)
sc_comq; /* Command queue */
struct ray_nw_param sc_c; /* current network params */
struct ray_nw_param sc_d; /* desired network params */
int sc_checkcounters;
u_int64_t sc_rxoverflow; /* Number of rx overflows */
u_int64_t sc_rxcksum; /* Number of checksum errors */
u_int64_t sc_rxhcksum; /* Number of header checksum errors */
u_int8_t sc_rxnoise; /* Average receiver level */
struct ray_siglev sc_siglevs[RAY_NSIGLEVRECS]; /* Antenna/levels */
};
#define sc_station_addr sc_ecf_startup.e_station_addr
#define sc_version sc_ecf_startup.e_fw_build_string
#define sc_tibsize sc_ecf_startup.e_tibsize
/*
* Command queue definitions
*/
typedef void (*ray_comqfn_t)(struct ray_softc *sc, struct ray_comq_entry *com);
struct ray_comq_entry {
TAILQ_ENTRY(ray_comq_entry) c_chain; /* Tail queue. */
ray_comqfn_t c_function; /* Function to call */
int c_flags; /* Flags */
u_int8_t c_retval; /* Return value */
void *c_wakeup; /* Sleeping on this */
size_t c_ccs; /* CCS structure */
struct ray_nw_param
c_desired; /* network settings */
struct ray_param_req
*c_pr; /* MIB report/update */
char *c_mesg;
};
/*
* Macro's and constants
*/
static int mib_info[RAY_MIB_MAX+1][3] = RAY_MIB_INFO;
/* Indirections for reading/writing memory - from NetBSD/if_ray.c */
#ifndef offsetof
#define offsetof(type, member) \
((size_t)(&((type *)0)->member))
#endif /* offsetof */
#define ATTR_READ_1(sc, off) \
((u_int8_t)bus_space_read_1((sc)->am_bst, (sc)->am_bsh, (off)))
#define ATTR_WRITE_1(sc, off, val) \
bus_space_write_1((sc)->am_bst, (sc)->am_bsh, (off), (val))
#define SRAM_READ_1(sc, off) \
((u_int8_t)bus_space_read_1((sc)->cm_bst, (sc)->cm_bsh, (off)))
#define SRAM_READ_REGION(sc, off, p, n) \
bus_space_read_region_1((sc)->cm_bst, (sc)->cm_bsh, (off), (void *)(p), (n))
#define SRAM_READ_FIELD_1(sc, off, s, f) \
SRAM_READ_1((sc), (off) + offsetof(struct s, f))
#define SRAM_READ_FIELD_2(sc, off, s, f) \
((((u_int16_t)SRAM_READ_1((sc), (off) + offsetof(struct s, f)) << 8) \
|(SRAM_READ_1((sc), (off) + 1 + offsetof(struct s, f)))))
#define SRAM_READ_FIELD_N(sc, off, s, f, p, n) \
SRAM_READ_REGION((sc), (off) + offsetof(struct s, f), (p), (n))
#define SRAM_WRITE_1(sc, off, val) \
bus_space_write_1((sc)->cm_bst, (sc)->cm_bsh, (off), (val))
#define SRAM_WRITE_REGION(sc, off, p, n) \
bus_space_write_region_1((sc)->cm_bst, (sc)->cm_bsh, (off), (void *)(p), (n))
#define SRAM_WRITE_FIELD_1(sc, off, s, f, v) \
SRAM_WRITE_1((sc), (off) + offsetof(struct s, f), (v))
#define SRAM_WRITE_FIELD_2(sc, off, s, f, v) do { \
SRAM_WRITE_1((sc), (off) + offsetof(struct s, f), (((v) >> 8 ) & 0xff)); \
SRAM_WRITE_1((sc), (off) + 1 + offsetof(struct s, f), ((v) & 0xff)); \
} while (0)
#define SRAM_WRITE_FIELD_N(sc, off, s, f, p, n) \
SRAM_WRITE_REGION((sc), (off) + offsetof(struct s, f), (p), (n))
/* Framing types */
/* XXX maybe better as part of the if structure? */
#define RAY_FRAMING_ENCAPSULATION 0
#define RAY_FRAMING_TRANSLATION 1
/* Authentication states */
#define RAY_AUTH_UNAUTH 0
#define RAY_AUTH_WAITING 1
#define RAY_AUTH_AUTH 2
#define RAY_AUTH_NEEDED 3
/* Flags for runq entries */
#define RAY_COM_FWOK 0x0001 /* Wakeup on completion */
#define RAY_COM_FRUNNING 0x0002 /* This one running */
#define RAY_COM_FCOMPLETED 0x0004 /* This one completed */
#define RAY_COM_FWAIT 0x0008 /* Do not run the queue */
#define RAY_COM_FCHKRUNNING 0x0010 /* Check IFF_DRV_RUNNING*/
#define RAY_COM_FDETACHED 0x0020 /* Card is gone */
#define RAY_COM_FWOKEN 0x0040 /* Woken by detach */
#define RAY_COM_FLAGS_PRINTFB \
"\020" \
"\001WOK" \
"\002RUNNING" \
"\003COMPLETED" \
"\004WAIT" \
"\005CHKRUNNING" \
"\006DETACHED"
#define RAY_COM_NEEDS_TIMO(cmd) ( \
(cmd == RAY_CMD_DOWNLOAD_PARAMS) || \
(cmd == RAY_CMD_UPDATE_PARAMS) || \
(cmd == RAY_CMD_UPDATE_MCAST) \
)
#ifndef RAY_COM_TIMEOUT
#define RAY_COM_TIMEOUT (hz / 2)
#endif
#ifndef RAY_RESET_TIMEOUT
#define RAY_RESET_TIMEOUT (10 * hz)
#endif
#ifndef RAY_TX_TIMEOUT
#define RAY_TX_TIMEOUT (hz / 2)
#endif
#define RAY_CCS_FREE(sc, ccs) \
SRAM_WRITE_FIELD_1((sc), (ccs), ray_cmd, c_status, RAY_CCS_STATUS_FREE)
#define RAY_ECF_READY(sc) \
(!(ATTR_READ_1((sc), RAY_ECFIR) & RAY_ECFIR_IRQ))
#define RAY_ECF_START_CMD(sc) ATTR_WRITE_1((sc), RAY_ECFIR, RAY_ECFIR_IRQ)
#define RAY_HCS_CLEAR_INTR(sc) ATTR_WRITE_1((sc), RAY_HCSIR, 0)
#define RAY_HCS_INTR(sc) (ATTR_READ_1((sc), RAY_HCSIR) & RAY_HCSIR_IRQ)
#define RAY_PANIC(sc, fmt, args...) do { \
panic("ray%d: %s(%d) " fmt "\n", device_get_unit((sc)->dev), \
__func__ , __LINE__ , ##args); \
} while (0)
#define RAY_PRINTF(sc, fmt, args...) do { \
device_printf((sc)->dev, "%s(%d) " fmt "\n", \
__func__ , __LINE__ , ##args); \
} while (0)
#define RAY_COM_MALLOC(function, flags) \
ray_com_malloc((function), (flags), __STRING(function));
#define RAY_COM_FREE(com, ncom) do { \
int i; \
for (i = 0; i < ncom; i++) \
FREE(com[i], M_RAYCOM); \
} while (0)
/*
* This macro handles adding commands to the runq and quickly
* getting away when the card is detached. The macro returns
* from the current function with ENXIO.
*/
#define RAY_COM_RUNQ(sc, com, ncom, mesg, error) do { \
(error) = ray_com_runq_add((sc), (com), (ncom), (mesg)); \
if ((error) == ENXIO) { \
RAY_COM_FREE((com), (ncom)); \
return (error); \
} else if ((error) && ((error) != ENXIO)) \
RAY_PRINTF(sc, "got error from runq 0x%x", (error)); \
} while (0)
/*
* There are a number of entry points into the ray_init_xxx routines.
* These can be classed into two types: a) those that happen as a result
* of a change to the cards operating parameters (e.g. BSSID change), and
* b) those that happen as a result of a change to the interface parameters
* (e.g. a change to the IP address). The second set of entries need not
* send a command to the card when the card is IFF_DRV_RUNNING. The
* RAY_COM_FCHKRUNNING flags indicates when the RUNNING flag should be
* checked, and this macro does the necessary check and command abort.
*/
#define RAY_COM_CHKRUNNING(sc, com, ifp) do { \
if (((com)->c_flags & RAY_COM_FCHKRUNNING) && \
((ifp)->if_drv_flags & IFF_DRV_RUNNING)) { \
ray_com_runq_done(sc); \
return; \
} } while (0)
#define RAY_COM_INIT(com, function, flags) \
ray_com_init((com), (function), (flags), __STRING(function));
#ifndef RAY_COM_CHECK
#define RAY_COM_CHECK(sc, com)
#endif /* RAY_COM_CHECK */
#ifndef RAY_MBUF_DUMP
#define RAY_MBUF_DUMP(sc, mask, m, s)
#endif /* RAY_MBUF_DUMP */
#ifndef RAY_RECERR
#define RAY_RECERR(sc, fmt, args...) do { \
struct ifnet *ifp = (sc)->ifp; \
if (ifp->if_flags & IFF_DEBUG) { \
device_printf((sc)->dev, "%s(%d) " fmt "\n", \
__func__ , __LINE__ , ##args); \
} } while (0)
#endif /* RAY_RECERR */
/* XXX this should be in CCSERR but don't work - probably need to use ##ifp->(iferrcounter)++; \*/
#ifndef RAY_CCSERR
#define RAY_CCSERR(sc, status, iferrcounter) do { \
struct ifnet *ifp = (sc)->ifp; \
char *ss[] = RAY_CCS_STATUS_STRINGS; \
if ((status) != RAY_CCS_STATUS_COMPLETE) { \
if (ifp->if_flags & IFF_DEBUG) { \
device_printf((sc)->dev, \
"%s(%d) ECF command completed with status %s\n", \
__func__ , __LINE__ , ss[(status)]); \
} } } while (0)
#endif /* RAY_CCSERR */
#ifndef RAY_MAP_CM
#define RAY_MAP_CM(sc)
#endif /* RAY_MAP_CM */
/*
* Management information element payloads
*/
union ieee80211_information {
char ssid[IEEE80211_NWID_LEN+1];
struct rates {
u_int8_t *p;
} rates;
struct fh {
u_int16_t dwell;
u_int8_t set;
u_int8_t pattern;
u_int8_t index;
} fh;
struct ds {
u_int8_t channel;
} ds;
struct cf {
u_int8_t count;
u_int8_t period;
u_int8_t maxdur[2];
u_int8_t dur[2];
} cf;
struct tim {
u_int8_t count;
u_int8_t period;
u_int8_t bitctl;
/* u_int8_t pvt[251]; The driver needs to use this. */
} tim;
struct ibss {
u_int16_t atim;
} ibss;
struct challenge {
u_int8_t *p;
u_int8_t len;
} challenge;
};
|