summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/zyd/zyd.h
blob: f280aca161873653d28d33e8546d09ebb464105a (plain)
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 */