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
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
|
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2008 by Ben Taylor <bentaylor.solx86@gmail.com>
* Copyright (c) 2007 by Lukas Turek <turek@ksvi.mff.cuni.cz>
* Copyright (c) 2007 by Jiri Svoboda <jirik.svoboda@seznam.cz>
* Copyright (c) 2007 by Martin Krulis <martin.krulis@matfyz.cz>
* Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef _ZYD_H
#define _ZYD_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/sysmacros.h>
#include <sys/net80211.h>
#define USBDRV_MAJOR_VER 2
#define USBDRV_MINOR_VER 0
#include <sys/usb/usba.h>
#include <sys/usb/usba/usba_types.h>
#define ZYD_DRV_NAME "zyd"
#define ZYD_DRV_DESC "Zydas ZD1211(B)"
#define ZYD_DRV_REV "V1.1"
/* Return the number of fields of an array */
#define ZYD_ARRAY_LENGTH(arr) (sizeof (arr) / sizeof ((arr)[0]))
/*
* Result type: all functions beginning with zyd_
* should use this to indicate success or failure.
* (except for public funcions, of course)
*
* Detecting error: always use (value != ZYD_SUCCESS)
* Indicating error: return ZYD_FAILURE
*/
typedef enum {
ZYD_SUCCESS,
ZYD_FAILURE
} zyd_res;
/*
* Chip revision ID
*/
typedef enum {
ZYD_UNKNOWN,
ZYD_ZD1211,
ZYD_ZD1211B
} zyd_mac_rev_t;
/*
* USB-safe mutual exclusion object.
*/
typedef struct {
boolean_t initialized; /* B_TRUE if properly initialized */
boolean_t held; /* B_TRUE if the object is held */
kmutex_t lock; /* serialize access */
kcondvar_t wait; /* for waiting on release */
} zyd_serial_t;
/*
* Holds an ioread request status.
*/
struct zyd_ioread {
volatile boolean_t pending; /* ioread is in progress */
volatile boolean_t done; /* response has been received */
volatile boolean_t exc; /* an exception has occured */
void *buffer; /* response buffer */
int buf_len; /* buffer size (bytes) */
};
/*
* USB state.
*/
struct zyd_usb {
/* Copy of sc->dip */
dev_info_t *dip;
/* Device configuration information */
usb_client_dev_data_t *cdata;
boolean_t connected;
/* Communication pipe handles */
usb_pipe_handle_t pipe_data_in;
usb_pipe_handle_t pipe_data_out;
usb_pipe_handle_t pipe_cmd_in;
usb_pipe_handle_t pipe_cmd_out;
/* Communication endpoint data (copied from descriptor tree) */
usb_ep_data_t ep_data_in;
usb_ep_data_t ep_data_out;
usb_ep_data_t ep_cmd_in;
usb_ep_data_t ep_cmd_out;
/* Current ioread request (if any) */
struct zyd_ioread io_read;
};
struct zyd_softc; /* forward declaration */
struct zyd_rf {
/* RF methods */
zyd_res (*init)(struct zyd_rf *);
zyd_res (*switch_radio)(struct zyd_rf *, boolean_t);
zyd_res (*set_channel)(struct zyd_rf *, uint8_t);
/* RF attributes */
struct zyd_softc *rf_sc; /* back-pointer */
int width;
};
/*
* per-instance soft-state structure
*/
struct zyd_softc {
/* Serialize access to the soft_state/device */
zyd_serial_t serial;
struct zyd_rf sc_rf;
dev_info_t *dip;
/* timeout for scanning */
timeout_id_t timeout_id;
/* USB-specific data */
struct zyd_usb usb;
/* Chip revision ZYD1211/ZYD1211B */
zyd_mac_rev_t mac_rev;
/* MAC address */
uint8_t macaddr[IEEE80211_ADDR_LEN];
/* net80211 data */
struct ieee80211com ic;
boolean_t running;
boolean_t suspended;
boolean_t resched;
uint8_t tx_queued;
/* Data from EEPROM */
uint16_t fwbase;
uint8_t regdomain;
uint16_t fw_rev;
uint8_t rf_rev;
uint8_t pa_rev;
uint8_t fix_cr47;
uint8_t fix_cr157;
uint8_t pwr_cal[14];
uint8_t pwr_int[14];
uint8_t ofdm36_cal[14];
uint8_t ofdm48_cal[14];
uint8_t ofdm54_cal[14];
/* kstats */
uint32_t tx_nobuf;
uint32_t rx_nobuf;
uint32_t tx_err;
uint32_t rx_err;
/* net80211 original state change handler */
int (*newstate)(ieee80211com_t *,
enum ieee80211_state, int);
};
/* RF-config request */
struct zyd_rfwrite {
uint16_t code;
uint16_t width;
uint16_t bit[32];
};
/* 16-bit I/O register write request */
struct zyd_iowrite16 {
uint16_t reg;
uint16_t value;
};
#pragma pack(1)
/* Generic usb command to the ZD chip */
struct zyd_cmd {
uint16_t cmd_code;
uint8_t data[64];
};
/* ZD prepends this header to an incoming frame. */
struct zyd_plcphdr {
uint8_t signal;
uint8_t reserved[2];
uint16_t service; /* unaligned! */
};
/* ZD appends this footer to an incoming frame. */
struct zyd_rx_stat {
uint8_t rssi;
uint8_t signal_cck;
uint8_t signal_ofdm;
uint8_t cipher;
uint8_t flags;
};
/* this structure may be unaligned */
struct zyd_rx_desc {
#define ZYD_MAX_RXFRAMECNT 3
uint16_t len[ZYD_MAX_RXFRAMECNT];
uint16_t tag;
#define ZYD_TAG_MULTIFRAME 0x697e
};
/*
* Prepended to the 802.11 frame when sending to data_out.
*/
struct zyd_tx_header {
uint8_t rate_mod_flags;
uint16_t frame_size;
uint8_t type_flags;
uint16_t packet_size;
uint16_t frame_duration;
uint8_t service;
uint16_t next_frame_duration;
};
#pragma pack()
/*
* Map USB id to 1211/1211B chip
*/
typedef struct zyd_usb_info {
uint16_t vendor_id;
uint16_t product_id;
zyd_mac_rev_t mac_rev;
} zyd_usb_info_t;
/*
* Simple lock for callback-waiting. This lock should be used in situations when
* one needs to wait for a callback function. It sipmply encapsulates one mutex
* and one conditional variable.
*/
struct zyd_cb_lock {
boolean_t done;
kmutex_t mutex;
kcondvar_t cv;
};
/* Bits for rate_mod_flags */
#define ZYD_TX_RMF_RATE(rmf) ((rmf) & 0x0f)
#define ZYD_TX_RMF_OFDM 0x10
#define ZYD_TX_RMF_SH_PREAMBLE 0x20 /* CCK */
#define ZYD_TX_RMF_5GHZ 0x40 /* OFDM */
/* Bits for type_flags */
#define ZYD_TX_FLAG_BACKOFF 0x01
#define ZYD_TX_FLAG_MULTICAST 0x02
#define ZYD_TX_FLAG_TYPE(t) (((t) & 0x3) << 2)
#define ZYD_TX_TYPE_DATA 0
#define ZYD_TX_TYPE_PS_POLL 1
#define ZYD_TX_TYPE_MGMT 2
#define ZYD_TX_TYPE_CTL 3
#define ZYD_TX_FLAG_WAKEUP 0x10
#define ZYD_TX_FLAG_RTS 0x20
#define ZYD_TX_FLAG_ENCRYPT 0x40
#define ZYD_TX_FLAG_CTS_TO_SELF 0x80
#define ZYD_TX_SERVICE_LENGTH_EXTENSION 0x80
#define ZYD_TX_LIST_COUNT 0x8
#define ZYD_RX_LIST_COUNT 0x8
#define ZYD_USB_REQ_COUNT 0x8
/*
* Time in miliseconds to stay on one channel during scan.
*/
#define ZYD_DWELL_TIME 200000
#define ZYD_SER_SIG B_TRUE
#define ZYD_NO_SIG B_FALSE
/* Location in the endpoint descriptor tree used by the device */
#define ZYD_USB_CONFIG_NUMBER 1
#define ZYD_USB_IFACE_INDEX 0
#define ZYD_USB_ALT_IF_INDEX 0
#define ZYD_DBG_HW (1<<0)
#define ZYD_DBG_FW (1<<1)
#define ZYD_DBG_USB (1<<2)
#define ZYD_DBG_TX (1<<3)
#define ZYD_DBG_RX (1<<4)
#define ZYD_DBG_SCAN (1<<5)
#define ZYD_DBG_GLD (1<<6)
#define ZYD_DBG_80211 (1<<7)
#define ZYD_DBG_RESUME (1<<8)
#define ZYD_RX_BUF_SIZE (sizeof (struct zyd_rx_desc) + \
((IEEE80211_MAX_LEN + 3) & ~3) * ZYD_MAX_RXFRAMECNT)
/* quickly determine if a given rate is CCK or OFDM */
#define ZYD_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)
/*
* Calculate the byte offset of a struct member
*/
#define ZYD_IC_TO_SOFTC(ic)\
(\
(struct zyd_softc *)(\
(uintptr_t)(ic) - offsetof(struct zyd_softc, ic)\
)\
)
/*
* The 'struct zyd_usb usb' is stored inside 'struct zyd_softc'.
* Using the knowledge of the usb member position,
* convert a pointer to 'usb' to a pointer to the zyd_softc.
*/
#define ZYD_USB_TO_SOFTC(usbp)\
(\
(struct zyd_softc *)(\
(uintptr_t)(usbp) - offsetof(struct zyd_softc, usb)\
)\
)
/* Debugging macros */
#ifdef DEBUG
#define ZYD_DEBUG(x) zyd_dbg x
#else
#define ZYD_DEBUG(x)
#endif
#define ZYD_WARN zyd_warn
extern void *zyd_ssp;
#ifdef DEBUG
extern uint32_t zyd_dbg_flags;
void zyd_dbg(uint32_t dbg_mask, const char *fmt, ...);
#endif
void zyd_warn(const char *fmt, ...);
/*
* Functions needed for initializing radios and switching channels
*/
extern zyd_res zyd_read32(struct zyd_softc *, uint16_t, uint32_t *);
extern zyd_res zyd_write32(struct zyd_softc *, uint16_t, uint32_t);
extern zyd_res zyd_read16(struct zyd_softc *, uint16_t, uint16_t *);
extern zyd_res zyd_write16a(struct zyd_softc *, const struct zyd_iowrite16 *,
int);
extern zyd_res zyd_write16(struct zyd_softc *, uint16_t, uint16_t);
/*
* Zydas's own USB-safe synchronization primitive. There are many USB API
* functions which forbids that caller holds a mutex. So we're avoiding that
* by using out own primitive (it consist of )
*/
void zyd_serial_init(struct zyd_softc *sc);
zyd_res zyd_serial_enter(struct zyd_softc *sc, boolean_t wait_sig);
void zyd_serial_exit(struct zyd_softc *sc);
void zyd_serial_deinit(struct zyd_softc *sc);
void zyd_cb_lock_init(struct zyd_cb_lock *lock);
void zyd_cb_lock_destroy(struct zyd_cb_lock *lock);
zyd_res zyd_cb_lock_wait(struct zyd_cb_lock *lock, clock_t timeout);
void zyd_cb_lock_signal(struct zyd_cb_lock *lock);
/* chipset specific routines */
void zyd_hw_set_channel(struct zyd_softc *sc, uint8_t chan);
zyd_res zyd_hw_init(struct zyd_softc *sc);
void zyd_hw_deinit(struct zyd_softc *sc);
zyd_res zyd_hw_start(struct zyd_softc *sc);
void zyd_hw_stop(struct zyd_softc *sc);
/* USB specific routines */
zyd_res zyd_usb_init(struct zyd_softc *sc);
void zyd_usb_deinit(struct zyd_softc *sc);
zyd_res zyd_usb_open_pipes(struct zyd_usb *uc);
void zyd_usb_close_pipes(struct zyd_usb *uc);
zyd_res zyd_usb_cmd_in_start_polling(struct zyd_usb *uc);
void zyd_usb_cmd_in_stop_polling(struct zyd_usb *uc);
zyd_res zyd_usb_data_in_enable(struct zyd_usb *uc);
void zyd_usb_data_in_disable(struct zyd_usb *uc);
zyd_res zyd_usb_cmd_send(struct zyd_usb *uc, uint16_t code,
const void *data, size_t len);
zyd_res zyd_usb_ioread_req(struct zyd_usb *uc, const void *in_data,
size_t in_len, void *out_data, size_t out_len);
zyd_res zyd_usb_send_packet(struct zyd_usb *uc, mblk_t *mp);
zyd_mac_rev_t zyd_usb_mac_rev(uint16_t vendor, uint16_t product);
zyd_res zyd_usb_loadfirmware(struct zyd_usb *uc, uint8_t *fw,
size_t size);
void zyd_receive(struct zyd_softc *sc, const uint8_t *buf, uint16_t len);
int zyd_resume(struct zyd_softc *sc);
int zyd_suspend(struct zyd_softc *sc);
extern uint8_t zd1211_firmware[];
extern size_t zd1211_firmware_size;
extern uint8_t zd1211b_firmware[];
extern size_t zd1211b_firmware_size;
#ifdef __cplusplus
}
#endif
#endif /* _ZYD_H */
|