xref: /titanic_52/usr/src/uts/common/io/zyd/zyd.h (revision 23a1ccea6aac035f084a7a4cdc968687d1b02daf)
1 /*
2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 2008 by  Ben Taylor <bentaylor.solx86@gmail.com>
8  * Copyright (c) 2007 by  Lukas Turek <turek@ksvi.mff.cuni.cz>
9  * Copyright (c) 2007 by  Jiri Svoboda <jirik.svoboda@seznam.cz>
10  * Copyright (c) 2007 by  Martin Krulis <martin.krulis@matfyz.cz>
11  * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
12  * Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de>
13  *
14  * Permission to use, copy, modify, and distribute this software for any
15  * purpose with or without fee is hereby granted, provided that the above
16  * copyright notice and this permission notice appear in all copies.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25  *
26  */
27 
28 #ifndef _ZYD_H
29 #define	_ZYD_H
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 #include <sys/sysmacros.h>
36 #include <sys/net80211.h>
37 
38 #define	USBDRV_MAJOR_VER 2
39 #define	USBDRV_MINOR_VER 0
40 #include <sys/usb/usba.h>
41 #include <sys/usb/usba/usba_types.h>
42 
43 #define	ZYD_DRV_NAME  "zyd"
44 #define	ZYD_DRV_DESC  "Zydas ZD1211(B)"
45 #define	ZYD_DRV_REV   "V1.1"
46 
47 /* Return the number of fields of an array */
48 #define	ZYD_ARRAY_LENGTH(arr) (sizeof (arr) / sizeof ((arr)[0]))
49 
50 /*
51  * Result type: all functions beginning with zyd_
52  * should use this to indicate success or failure.
53  * (except for public funcions, of course)
54  *
55  * Detecting error: always use (value != ZYD_SUCCESS)
56  * Indicating error: return ZYD_FAILURE
57  */
58 typedef enum {
59 	ZYD_SUCCESS,
60 	ZYD_FAILURE
61 } zyd_res;
62 
63 /*
64  * Chip revision ID
65  */
66 typedef enum {
67 	ZYD_UNKNOWN,
68 	ZYD_ZD1211,
69 	ZYD_ZD1211B
70 } zyd_mac_rev_t;
71 
72 /*
73  * USB-safe mutual exclusion object.
74  */
75 typedef struct {
76 	boolean_t initialized;	/* B_TRUE if properly initialized */
77 	boolean_t held;		/* B_TRUE if the object is held */
78 	kmutex_t lock;		/* serialize access */
79 	kcondvar_t wait;	/* for waiting on release */
80 } zyd_serial_t;
81 
82 /*
83  * Holds an ioread request status.
84  */
85 struct zyd_ioread {
86 	volatile boolean_t pending;	/* ioread is in progress */
87 	volatile boolean_t done;	/* response has been received */
88 	volatile boolean_t exc;		/* an exception has occured */
89 
90 	void *buffer;			/* response buffer */
91 	int buf_len;			/* buffer size (bytes) */
92 };
93 
94 /*
95  * USB state.
96  */
97 struct zyd_usb {
98 	/* Copy of sc->dip */
99 	dev_info_t 		*dip;
100 
101 	/* Device configuration information */
102 	usb_client_dev_data_t	*cdata;
103 
104 	boolean_t		connected;
105 
106 	/* Communication pipe handles */
107 	usb_pipe_handle_t	pipe_data_in;
108 	usb_pipe_handle_t	pipe_data_out;
109 	usb_pipe_handle_t	pipe_cmd_in;
110 	usb_pipe_handle_t	pipe_cmd_out;
111 
112 	/* Communication endpoint data (copied from descriptor tree) */
113 	usb_ep_data_t		ep_data_in;
114 	usb_ep_data_t		ep_data_out;
115 	usb_ep_data_t		ep_cmd_in;
116 	usb_ep_data_t		ep_cmd_out;
117 
118 	/* Current ioread request (if any) */
119 	struct zyd_ioread	io_read;
120 };
121 
122 struct zyd_softc;	/* forward declaration */
123 
124 struct zyd_rf {
125 	/* RF methods */
126 	zyd_res		(*init)(struct zyd_rf *);
127 	zyd_res		(*switch_radio)(struct zyd_rf *, boolean_t);
128 	zyd_res		(*set_channel)(struct zyd_rf *, uint8_t);
129 
130 	/* RF attributes */
131 	struct		zyd_softc *rf_sc;	/* back-pointer */
132 	int		width;
133 };
134 
135 /*
136  * per-instance soft-state structure
137  */
138 struct zyd_softc {
139 	/* Serialize access to the soft_state/device */
140 	zyd_serial_t		serial;
141 	struct zyd_rf		sc_rf;
142 
143 	dev_info_t		*dip;
144 
145 	/* timeout for scanning */
146 	timeout_id_t		timeout_id;
147 
148 	/* USB-specific data */
149 	struct zyd_usb		usb;
150 
151 	/* Chip revision ZYD1211/ZYD1211B */
152 	zyd_mac_rev_t		mac_rev;
153 
154 	/* MAC address */
155 	uint8_t			macaddr[IEEE80211_ADDR_LEN];
156 
157 	/* net80211 data */
158 	struct ieee80211com 	ic;
159 
160 	boolean_t		running;
161 	boolean_t		suspended;
162 	boolean_t		resched;
163 	uint8_t			tx_queued;
164 
165 	/* Data from EEPROM */
166 	uint16_t		fwbase;
167 	uint8_t			regdomain;
168 	uint16_t		fw_rev;
169 	uint8_t			rf_rev;
170 	uint8_t			pa_rev;
171 	uint8_t			fix_cr47;
172 	uint8_t			fix_cr157;
173 	uint8_t			pwr_cal[14];
174 	uint8_t			pwr_int[14];
175 	uint8_t			ofdm36_cal[14];
176 	uint8_t			ofdm48_cal[14];
177 	uint8_t			ofdm54_cal[14];
178 
179 	/* kstats */
180 	uint32_t		tx_nobuf;
181 	uint32_t		rx_nobuf;
182 	uint32_t		tx_err;
183 	uint32_t		rx_err;
184 
185 	/* net80211 original state change handler */
186 	int			(*newstate)(ieee80211com_t *,
187 					enum ieee80211_state, int);
188 };
189 
190 /* RF-config request */
191 struct zyd_rfwrite {
192 	uint16_t	code;
193 	uint16_t	width;
194 	uint16_t	bit[32];
195 };
196 
197 /* 16-bit I/O register write request */
198 struct zyd_iowrite16 {
199 	uint16_t	reg;
200 	uint16_t	value;
201 };
202 
203 #pragma pack(1)
204 
205 /* Generic usb command to the ZD chip */
206 struct zyd_cmd {
207 	uint16_t 	cmd_code;
208 	uint8_t		data[64];
209 };
210 
211 /* ZD prepends this header to an incoming frame. */
212 struct zyd_plcphdr {
213 	uint8_t		signal;
214 	uint8_t		reserved[2];
215 	uint16_t	service;	/* unaligned! */
216 };
217 
218 /* ZD appends this footer to an incoming frame. */
219 struct zyd_rx_stat {
220 	uint8_t rssi;
221 	uint8_t	signal_cck;
222 	uint8_t	signal_ofdm;
223 	uint8_t	cipher;
224 	uint8_t	flags;
225 };
226 
227 /* this structure may be unaligned */
228 struct zyd_rx_desc {
229 #define	ZYD_MAX_RXFRAMECNT 3
230 	uint16_t   len[ZYD_MAX_RXFRAMECNT];
231 	uint16_t   tag;
232 #define	ZYD_TAG_MULTIFRAME 0x697e
233 };
234 
235 /*
236  * Prepended to the 802.11 frame when sending to data_out.
237  */
238 struct zyd_tx_header {
239 	uint8_t rate_mod_flags;
240 	uint16_t frame_size;
241 	uint8_t type_flags;
242 	uint16_t packet_size;
243 	uint16_t frame_duration;
244 	uint8_t service;
245 	uint16_t next_frame_duration;
246 };
247 
248 #pragma pack()
249 
250 /*
251  * Map USB id to 1211/1211B chip
252  */
253 typedef struct zyd_usb_info {
254 	uint16_t	vendor_id;
255 	uint16_t	product_id;
256 	zyd_mac_rev_t	mac_rev;
257 } zyd_usb_info_t;
258 
259 /*
260  * Simple lock for callback-waiting. This lock should be used in situations when
261  * one needs to wait for a callback function. It sipmply encapsulates one mutex
262  * and one conditional variable.
263  */
264 struct zyd_cb_lock {
265 	boolean_t done;
266 	kmutex_t mutex;
267 	kcondvar_t cv;
268 };
269 
270 /* Bits for rate_mod_flags */
271 #define	ZYD_TX_RMF_RATE(rmf)	((rmf) & 0x0f)
272 #define	ZYD_TX_RMF_OFDM		0x10
273 #define	ZYD_TX_RMF_SH_PREAMBLE	0x20	/* CCK */
274 #define	ZYD_TX_RMF_5GHZ		0x40	/* OFDM */
275 
276 /* Bits for type_flags */
277 #define	ZYD_TX_FLAG_BACKOFF	0x01
278 #define	ZYD_TX_FLAG_MULTICAST	0x02
279 #define	ZYD_TX_FLAG_TYPE(t)	(((t) & 0x3) << 2)
280 #define	ZYD_TX_TYPE_DATA	0
281 #define	ZYD_TX_TYPE_PS_POLL	1
282 #define	ZYD_TX_TYPE_MGMT	2
283 #define	ZYD_TX_TYPE_CTL		3
284 
285 #define	ZYD_TX_FLAG_WAKEUP	0x10
286 #define	ZYD_TX_FLAG_RTS		0x20
287 #define	ZYD_TX_FLAG_ENCRYPT	0x40
288 #define	ZYD_TX_FLAG_CTS_TO_SELF	0x80
289 
290 #define	ZYD_TX_SERVICE_LENGTH_EXTENSION		0x80
291 
292 #define	ZYD_TX_LIST_COUNT	0x8
293 #define	ZYD_RX_LIST_COUNT	0x8
294 #define	ZYD_USB_REQ_COUNT	0x8
295 
296 /*
297  * Time in miliseconds to stay on one channel during scan.
298  */
299 #define	ZYD_DWELL_TIME 200000
300 
301 #define	ZYD_SER_SIG	B_TRUE
302 #define	ZYD_NO_SIG	B_FALSE
303 
304 /* Location in the endpoint descriptor tree used by the device */
305 #define	ZYD_USB_CONFIG_NUMBER  1
306 #define	ZYD_USB_IFACE_INDEX    0
307 #define	ZYD_USB_ALT_IF_INDEX   0
308 
309 #define	ZYD_DBG_HW	(1<<0)
310 #define	ZYD_DBG_FW	(1<<1)
311 #define	ZYD_DBG_USB	(1<<2)
312 #define	ZYD_DBG_TX	(1<<3)
313 #define	ZYD_DBG_RX	(1<<4)
314 #define	ZYD_DBG_SCAN	(1<<5)
315 #define	ZYD_DBG_GLD	(1<<6)
316 #define	ZYD_DBG_80211	(1<<7)
317 #define	ZYD_DBG_RESUME	(1<<8)
318 
319 #define	ZYD_RX_BUF_SIZE (sizeof (struct zyd_rx_desc) + \
320 	((IEEE80211_MAX_LEN + 3) & ~3) * ZYD_MAX_RXFRAMECNT)
321 
322 /* quickly determine if a given rate is CCK or OFDM */
323 #define	ZYD_RATE_IS_OFDM(rate)	((rate) >= 12 && (rate) != 22)
324 
325 /*
326  * Calculate the byte offset of a struct member
327  */
328 #define	ZYD_IC_TO_SOFTC(ic)\
329 (\
330 	(struct zyd_softc *)(\
331 		(uintptr_t)(ic) - offsetof(struct zyd_softc, ic)\
332 )\
333 )
334 
335 /*
336  * The 'struct zyd_usb usb' is stored inside 'struct zyd_softc'.
337  * Using the knowledge of the usb member position,
338  * convert a pointer to 'usb' to a pointer to the zyd_softc.
339  */
340 #define	ZYD_USB_TO_SOFTC(usbp)\
341 (\
342 	(struct zyd_softc *)(\
343 		(uintptr_t)(usbp) - offsetof(struct zyd_softc, usb)\
344 )\
345 )
346 
347 /* Debugging macros */
348 #ifdef DEBUG
349 #define	ZYD_DEBUG(x)	zyd_dbg x
350 #else
351 #define	ZYD_DEBUG(x)
352 #endif
353 #define	ZYD_WARN	zyd_warn
354 
355 extern void *zyd_ssp;
356 
357 #ifdef DEBUG
358 extern uint32_t zyd_dbg_flags;
359 void	zyd_dbg(uint32_t dbg_mask, const char *fmt, ...);
360 #endif
361 void	zyd_warn(const char *fmt, ...);
362 /*
363  * Functions needed for initializing radios and switching channels
364  */
365 extern zyd_res	zyd_read32(struct zyd_softc *, uint16_t, uint32_t *);
366 extern zyd_res	zyd_write32(struct zyd_softc *, uint16_t, uint32_t);
367 extern zyd_res	zyd_read16(struct zyd_softc *, uint16_t, uint16_t *);
368 extern zyd_res	zyd_write16a(struct zyd_softc *, const struct zyd_iowrite16 *,
369     int);
370 extern zyd_res	zyd_write16(struct zyd_softc *, uint16_t, uint16_t);
371 /*
372  * Zydas's own USB-safe synchronization primitive. There are many USB API
373  * functions which forbids that caller holds a mutex. So we're avoiding that
374  * by using out own primitive (it consist of )
375  */
376 void	zyd_serial_init(struct zyd_softc *sc);
377 zyd_res	zyd_serial_enter(struct zyd_softc *sc, boolean_t wait_sig);
378 void	zyd_serial_exit(struct zyd_softc *sc);
379 void	zyd_serial_deinit(struct zyd_softc *sc);
380 
381 void	zyd_cb_lock_init(struct zyd_cb_lock *lock);
382 void	zyd_cb_lock_destroy(struct zyd_cb_lock *lock);
383 zyd_res	zyd_cb_lock_wait(struct zyd_cb_lock *lock, clock_t timeout);
384 void	zyd_cb_lock_signal(struct zyd_cb_lock *lock);
385 
386 /* chipset specific routines */
387 void		zyd_hw_set_channel(struct zyd_softc *sc, uint8_t chan);
388 zyd_res		zyd_hw_init(struct zyd_softc *sc);
389 void		zyd_hw_deinit(struct zyd_softc *sc);
390 zyd_res		zyd_hw_start(struct zyd_softc *sc);
391 void		zyd_hw_stop(struct zyd_softc *sc);
392 
393 /* USB specific routines */
394 zyd_res		zyd_usb_init(struct zyd_softc *sc);
395 void		zyd_usb_deinit(struct zyd_softc *sc);
396 zyd_res		zyd_usb_open_pipes(struct zyd_usb *uc);
397 void		zyd_usb_close_pipes(struct zyd_usb *uc);
398 zyd_res		zyd_usb_cmd_in_start_polling(struct zyd_usb *uc);
399 void		zyd_usb_cmd_in_stop_polling(struct zyd_usb *uc);
400 zyd_res		zyd_usb_data_in_enable(struct zyd_usb *uc);
401 void		zyd_usb_data_in_disable(struct zyd_usb *uc);
402 zyd_res		zyd_usb_cmd_send(struct zyd_usb *uc, uint16_t code,
403 			const void *data, size_t len);
404 zyd_res		zyd_usb_ioread_req(struct zyd_usb *uc, const void *in_data,
405 			size_t in_len, void *out_data, size_t out_len);
406 zyd_res		zyd_usb_send_packet(struct zyd_usb *uc, mblk_t *mp);
407 zyd_mac_rev_t	zyd_usb_mac_rev(uint16_t vendor, uint16_t product);
408 zyd_res		zyd_usb_loadfirmware(struct zyd_usb *uc, uint8_t *fw,
409 			size_t size);
410 
411 void	zyd_receive(struct zyd_softc *sc, const uint8_t *buf, uint16_t len);
412 int	zyd_resume(struct zyd_softc *sc);
413 int	zyd_suspend(struct zyd_softc *sc);
414 
415 extern uint8_t	zd1211_firmware[];
416 extern size_t	zd1211_firmware_size;
417 extern uint8_t	zd1211b_firmware[];
418 extern size_t	zd1211b_firmware_size;
419 
420 #ifdef __cplusplus
421 }
422 #endif
423 
424 #endif /* _ZYD_H */
425