diff options
Diffstat (limited to 'drivers/net')
22 files changed, 6911 insertions, 0 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 30ec235e6935..fa9d2c4edc93 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -550,6 +550,7 @@ config USB_ZD1201 | |||
550 | 550 | ||
551 | source "drivers/net/wireless/hostap/Kconfig" | 551 | source "drivers/net/wireless/hostap/Kconfig" |
552 | source "drivers/net/wireless/bcm43xx/Kconfig" | 552 | source "drivers/net/wireless/bcm43xx/Kconfig" |
553 | source "drivers/net/wireless/zd1211rw/Kconfig" | ||
553 | 554 | ||
554 | # yes, this works even when no drivers are selected | 555 | # yes, this works even when no drivers are selected |
555 | config NET_WIRELESS | 556 | config NET_WIRELESS |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 512603de309a..c613af17a159 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
@@ -36,6 +36,7 @@ obj-$(CONFIG_PRISM54) += prism54/ | |||
36 | 36 | ||
37 | obj-$(CONFIG_HOSTAP) += hostap/ | 37 | obj-$(CONFIG_HOSTAP) += hostap/ |
38 | obj-$(CONFIG_BCM43XX) += bcm43xx/ | 38 | obj-$(CONFIG_BCM43XX) += bcm43xx/ |
39 | obj-$(CONFIG_ZD1211RW) += zd1211rw/ | ||
39 | 40 | ||
40 | # 16-bit wireless PCMCIA client drivers | 41 | # 16-bit wireless PCMCIA client drivers |
41 | obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o | 42 | obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o |
diff --git a/drivers/net/wireless/zd1211rw/Kconfig b/drivers/net/wireless/zd1211rw/Kconfig new file mode 100644 index 000000000000..66ed55bc5460 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/Kconfig | |||
@@ -0,0 +1,19 @@ | |||
1 | config ZD1211RW | ||
2 | tristate "ZyDAS ZD1211/ZD1211B USB-wireless support" | ||
3 | depends on USB && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL | ||
4 | select FW_LOADER | ||
5 | ---help--- | ||
6 | This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless | ||
7 | chip, present in many USB-wireless adapters. | ||
8 | |||
9 | Device firmware is required alongside this driver. You can download the | ||
10 | firmware distribution from http://zd1211.ath.cx/get-firmware | ||
11 | |||
12 | config ZD1211RW_DEBUG | ||
13 | bool "ZyDAS ZD1211 debugging" | ||
14 | depends on ZD1211RW | ||
15 | ---help--- | ||
16 | ZD1211 debugging messages. Choosing Y will result in additional debug | ||
17 | messages being saved to your kernel logs, which may help debug any | ||
18 | problems. | ||
19 | |||
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile new file mode 100644 index 000000000000..500314fc74d2 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | obj-$(CONFIG_ZD1211RW) += zd1211rw.o | ||
2 | |||
3 | zd1211rw-objs := zd_chip.o zd_ieee80211.o \ | ||
4 | zd_mac.o zd_netdev.o \ | ||
5 | zd_rf_al2230.o zd_rf_rf2959.o \ | ||
6 | zd_rf.o zd_usb.o zd_util.o | ||
7 | |||
8 | ifeq ($(CONFIG_ZD1211RW_DEBUG),y) | ||
9 | EXTRA_CFLAGS += -DDEBUG | ||
10 | endif | ||
11 | |||
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c new file mode 100644 index 000000000000..efc9c4bd826f --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -0,0 +1,1615 @@ | |||
1 | /* zd_chip.c | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | /* This file implements all the hardware specific functions for the ZD1211 | ||
19 | * and ZD1211B chips. Support for the ZD1211B was possible after Timothy | ||
20 | * Legge sent me a ZD1211B device. Thank you Tim. -- Uli | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/errno.h> | ||
25 | |||
26 | #include "zd_def.h" | ||
27 | #include "zd_chip.h" | ||
28 | #include "zd_ieee80211.h" | ||
29 | #include "zd_mac.h" | ||
30 | #include "zd_rf.h" | ||
31 | #include "zd_util.h" | ||
32 | |||
33 | void zd_chip_init(struct zd_chip *chip, | ||
34 | struct net_device *netdev, | ||
35 | struct usb_interface *intf) | ||
36 | { | ||
37 | memset(chip, 0, sizeof(*chip)); | ||
38 | mutex_init(&chip->mutex); | ||
39 | zd_usb_init(&chip->usb, netdev, intf); | ||
40 | zd_rf_init(&chip->rf); | ||
41 | } | ||
42 | |||
43 | void zd_chip_clear(struct zd_chip *chip) | ||
44 | { | ||
45 | mutex_lock(&chip->mutex); | ||
46 | zd_usb_clear(&chip->usb); | ||
47 | zd_rf_clear(&chip->rf); | ||
48 | mutex_unlock(&chip->mutex); | ||
49 | mutex_destroy(&chip->mutex); | ||
50 | memset(chip, 0, sizeof(*chip)); | ||
51 | } | ||
52 | |||
53 | static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size) | ||
54 | { | ||
55 | return scnprintf(buffer, size, "%02x-%02x-%02x", | ||
56 | addr[0], addr[1], addr[2]); | ||
57 | } | ||
58 | |||
59 | /* Prints an identifier line, which will support debugging. */ | ||
60 | static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size) | ||
61 | { | ||
62 | int i = 0; | ||
63 | |||
64 | i = scnprintf(buffer, size, "zd1211%s chip ", | ||
65 | chip->is_zd1211b ? "b" : ""); | ||
66 | i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i); | ||
67 | i += scnprintf(buffer+i, size-i, " "); | ||
68 | i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i); | ||
69 | i += scnprintf(buffer+i, size-i, " "); | ||
70 | i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i); | ||
71 | i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c", chip->pa_type, | ||
72 | chip->patch_cck_gain ? 'g' : '-', | ||
73 | chip->patch_cr157 ? '7' : '-', | ||
74 | chip->patch_6m_band_edge ? '6' : '-'); | ||
75 | return i; | ||
76 | } | ||
77 | |||
78 | static void print_id(struct zd_chip *chip) | ||
79 | { | ||
80 | char buffer[80]; | ||
81 | |||
82 | scnprint_id(chip, buffer, sizeof(buffer)); | ||
83 | buffer[sizeof(buffer)-1] = 0; | ||
84 | dev_info(zd_chip_dev(chip), "%s\n", buffer); | ||
85 | } | ||
86 | |||
87 | /* Read a variable number of 32-bit values. Parameter count is not allowed to | ||
88 | * exceed USB_MAX_IOREAD32_COUNT. | ||
89 | */ | ||
90 | int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr, | ||
91 | unsigned int count) | ||
92 | { | ||
93 | int r; | ||
94 | int i; | ||
95 | zd_addr_t *a16 = (zd_addr_t *)NULL; | ||
96 | u16 *v16; | ||
97 | unsigned int count16; | ||
98 | |||
99 | if (count > USB_MAX_IOREAD32_COUNT) | ||
100 | return -EINVAL; | ||
101 | |||
102 | /* Allocate a single memory block for values and addresses. */ | ||
103 | count16 = 2*count; | ||
104 | a16 = (zd_addr_t *)kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)), | ||
105 | GFP_NOFS); | ||
106 | if (!a16) { | ||
107 | dev_dbg_f(zd_chip_dev(chip), | ||
108 | "error ENOMEM in allocation of a16\n"); | ||
109 | r = -ENOMEM; | ||
110 | goto out; | ||
111 | } | ||
112 | v16 = (u16 *)(a16 + count16); | ||
113 | |||
114 | for (i = 0; i < count; i++) { | ||
115 | int j = 2*i; | ||
116 | /* We read the high word always first. */ | ||
117 | a16[j] = zd_inc_word(addr[i]); | ||
118 | a16[j+1] = addr[i]; | ||
119 | } | ||
120 | |||
121 | r = zd_ioread16v_locked(chip, v16, a16, count16); | ||
122 | if (r) { | ||
123 | dev_dbg_f(zd_chip_dev(chip), | ||
124 | "error: zd_ioread16v_locked. Error number %d\n", r); | ||
125 | goto out; | ||
126 | } | ||
127 | |||
128 | for (i = 0; i < count; i++) { | ||
129 | int j = 2*i; | ||
130 | values[i] = (v16[j] << 16) | v16[j+1]; | ||
131 | } | ||
132 | |||
133 | out: | ||
134 | kfree((void *)a16); | ||
135 | return r; | ||
136 | } | ||
137 | |||
138 | int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, | ||
139 | unsigned int count) | ||
140 | { | ||
141 | int i, j, r; | ||
142 | struct zd_ioreq16 *ioreqs16; | ||
143 | unsigned int count16; | ||
144 | |||
145 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
146 | |||
147 | if (count == 0) | ||
148 | return 0; | ||
149 | if (count > USB_MAX_IOWRITE32_COUNT) | ||
150 | return -EINVAL; | ||
151 | |||
152 | /* Allocate a single memory block for values and addresses. */ | ||
153 | count16 = 2*count; | ||
154 | ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_NOFS); | ||
155 | if (!ioreqs16) { | ||
156 | r = -ENOMEM; | ||
157 | dev_dbg_f(zd_chip_dev(chip), | ||
158 | "error %d in ioreqs16 allocation\n", r); | ||
159 | goto out; | ||
160 | } | ||
161 | |||
162 | for (i = 0; i < count; i++) { | ||
163 | j = 2*i; | ||
164 | /* We write the high word always first. */ | ||
165 | ioreqs16[j].value = ioreqs[i].value >> 16; | ||
166 | ioreqs16[j].addr = zd_inc_word(ioreqs[i].addr); | ||
167 | ioreqs16[j+1].value = ioreqs[i].value; | ||
168 | ioreqs16[j+1].addr = ioreqs[i].addr; | ||
169 | } | ||
170 | |||
171 | r = zd_usb_iowrite16v(&chip->usb, ioreqs16, count16); | ||
172 | #ifdef DEBUG | ||
173 | if (r) { | ||
174 | dev_dbg_f(zd_chip_dev(chip), | ||
175 | "error %d in zd_usb_write16v\n", r); | ||
176 | } | ||
177 | #endif /* DEBUG */ | ||
178 | out: | ||
179 | kfree(ioreqs16); | ||
180 | return r; | ||
181 | } | ||
182 | |||
183 | int zd_iowrite16a_locked(struct zd_chip *chip, | ||
184 | const struct zd_ioreq16 *ioreqs, unsigned int count) | ||
185 | { | ||
186 | int r; | ||
187 | unsigned int i, j, t, max; | ||
188 | |||
189 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
190 | for (i = 0; i < count; i += j + t) { | ||
191 | t = 0; | ||
192 | max = count-i; | ||
193 | if (max > USB_MAX_IOWRITE16_COUNT) | ||
194 | max = USB_MAX_IOWRITE16_COUNT; | ||
195 | for (j = 0; j < max; j++) { | ||
196 | if (!ioreqs[i+j].addr) { | ||
197 | t = 1; | ||
198 | break; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | r = zd_usb_iowrite16v(&chip->usb, &ioreqs[i], j); | ||
203 | if (r) { | ||
204 | dev_dbg_f(zd_chip_dev(chip), | ||
205 | "error zd_usb_iowrite16v. Error number %d\n", | ||
206 | r); | ||
207 | return r; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | /* Writes a variable number of 32 bit registers. The functions will split | ||
215 | * that in several USB requests. A split can be forced by inserting an IO | ||
216 | * request with an zero address field. | ||
217 | */ | ||
218 | int zd_iowrite32a_locked(struct zd_chip *chip, | ||
219 | const struct zd_ioreq32 *ioreqs, unsigned int count) | ||
220 | { | ||
221 | int r; | ||
222 | unsigned int i, j, t, max; | ||
223 | |||
224 | for (i = 0; i < count; i += j + t) { | ||
225 | t = 0; | ||
226 | max = count-i; | ||
227 | if (max > USB_MAX_IOWRITE32_COUNT) | ||
228 | max = USB_MAX_IOWRITE32_COUNT; | ||
229 | for (j = 0; j < max; j++) { | ||
230 | if (!ioreqs[i+j].addr) { | ||
231 | t = 1; | ||
232 | break; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | r = _zd_iowrite32v_locked(chip, &ioreqs[i], j); | ||
237 | if (r) { | ||
238 | dev_dbg_f(zd_chip_dev(chip), | ||
239 | "error _zd_iowrite32v_locked." | ||
240 | " Error number %d\n", r); | ||
241 | return r; | ||
242 | } | ||
243 | } | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value) | ||
249 | { | ||
250 | int r; | ||
251 | |||
252 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
253 | mutex_lock(&chip->mutex); | ||
254 | r = zd_ioread16_locked(chip, value, addr); | ||
255 | mutex_unlock(&chip->mutex); | ||
256 | return r; | ||
257 | } | ||
258 | |||
259 | int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value) | ||
260 | { | ||
261 | int r; | ||
262 | |||
263 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
264 | mutex_lock(&chip->mutex); | ||
265 | r = zd_ioread32_locked(chip, value, addr); | ||
266 | mutex_unlock(&chip->mutex); | ||
267 | return r; | ||
268 | } | ||
269 | |||
270 | int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value) | ||
271 | { | ||
272 | int r; | ||
273 | |||
274 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
275 | mutex_lock(&chip->mutex); | ||
276 | r = zd_iowrite16_locked(chip, value, addr); | ||
277 | mutex_unlock(&chip->mutex); | ||
278 | return r; | ||
279 | } | ||
280 | |||
281 | int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value) | ||
282 | { | ||
283 | int r; | ||
284 | |||
285 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
286 | mutex_lock(&chip->mutex); | ||
287 | r = zd_iowrite32_locked(chip, value, addr); | ||
288 | mutex_unlock(&chip->mutex); | ||
289 | return r; | ||
290 | } | ||
291 | |||
292 | int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses, | ||
293 | u32 *values, unsigned int count) | ||
294 | { | ||
295 | int r; | ||
296 | |||
297 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
298 | mutex_lock(&chip->mutex); | ||
299 | r = zd_ioread32v_locked(chip, values, addresses, count); | ||
300 | mutex_unlock(&chip->mutex); | ||
301 | return r; | ||
302 | } | ||
303 | |||
304 | int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, | ||
305 | unsigned int count) | ||
306 | { | ||
307 | int r; | ||
308 | |||
309 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
310 | mutex_lock(&chip->mutex); | ||
311 | r = zd_iowrite32a_locked(chip, ioreqs, count); | ||
312 | mutex_unlock(&chip->mutex); | ||
313 | return r; | ||
314 | } | ||
315 | |||
316 | static int read_pod(struct zd_chip *chip, u8 *rf_type) | ||
317 | { | ||
318 | int r; | ||
319 | u32 value; | ||
320 | |||
321 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
322 | r = zd_ioread32_locked(chip, &value, E2P_POD); | ||
323 | if (r) | ||
324 | goto error; | ||
325 | dev_dbg_f(zd_chip_dev(chip), "E2P_POD %#010x\n", value); | ||
326 | |||
327 | /* FIXME: AL2230 handling (Bit 7 in POD) */ | ||
328 | *rf_type = value & 0x0f; | ||
329 | chip->pa_type = (value >> 16) & 0x0f; | ||
330 | chip->patch_cck_gain = (value >> 8) & 0x1; | ||
331 | chip->patch_cr157 = (value >> 13) & 0x1; | ||
332 | chip->patch_6m_band_edge = (value >> 21) & 0x1; | ||
333 | |||
334 | dev_dbg_f(zd_chip_dev(chip), | ||
335 | "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " | ||
336 | "patch 6M %d\n", | ||
337 | zd_rf_name(*rf_type), *rf_type, | ||
338 | chip->pa_type, chip->patch_cck_gain, | ||
339 | chip->patch_cr157, chip->patch_6m_band_edge); | ||
340 | return 0; | ||
341 | error: | ||
342 | *rf_type = 0; | ||
343 | chip->pa_type = 0; | ||
344 | chip->patch_cck_gain = 0; | ||
345 | chip->patch_cr157 = 0; | ||
346 | chip->patch_6m_band_edge = 0; | ||
347 | return r; | ||
348 | } | ||
349 | |||
350 | static int _read_mac_addr(struct zd_chip *chip, u8 *mac_addr, | ||
351 | const zd_addr_t *addr) | ||
352 | { | ||
353 | int r; | ||
354 | u32 parts[2]; | ||
355 | |||
356 | r = zd_ioread32v_locked(chip, parts, (const zd_addr_t *)addr, 2); | ||
357 | if (r) { | ||
358 | dev_dbg_f(zd_chip_dev(chip), | ||
359 | "error: couldn't read e2p macs. Error number %d\n", r); | ||
360 | return r; | ||
361 | } | ||
362 | |||
363 | mac_addr[0] = parts[0]; | ||
364 | mac_addr[1] = parts[0] >> 8; | ||
365 | mac_addr[2] = parts[0] >> 16; | ||
366 | mac_addr[3] = parts[0] >> 24; | ||
367 | mac_addr[4] = parts[1]; | ||
368 | mac_addr[5] = parts[1] >> 8; | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int read_e2p_mac_addr(struct zd_chip *chip) | ||
374 | { | ||
375 | static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 }; | ||
376 | |||
377 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
378 | return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr); | ||
379 | } | ||
380 | |||
381 | /* MAC address: if custom mac addresses are to to be used CR_MAC_ADDR_P1 and | ||
382 | * CR_MAC_ADDR_P2 must be overwritten | ||
383 | */ | ||
384 | void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr) | ||
385 | { | ||
386 | mutex_lock(&chip->mutex); | ||
387 | memcpy(mac_addr, chip->e2p_mac, ETH_ALEN); | ||
388 | mutex_unlock(&chip->mutex); | ||
389 | } | ||
390 | |||
391 | static int read_mac_addr(struct zd_chip *chip, u8 *mac_addr) | ||
392 | { | ||
393 | static const zd_addr_t addr[2] = { CR_MAC_ADDR_P1, CR_MAC_ADDR_P2 }; | ||
394 | return _read_mac_addr(chip, mac_addr, (const zd_addr_t *)addr); | ||
395 | } | ||
396 | |||
397 | int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr) | ||
398 | { | ||
399 | int r; | ||
400 | |||
401 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
402 | mutex_lock(&chip->mutex); | ||
403 | r = read_mac_addr(chip, mac_addr); | ||
404 | mutex_unlock(&chip->mutex); | ||
405 | return r; | ||
406 | } | ||
407 | |||
408 | int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) | ||
409 | { | ||
410 | int r; | ||
411 | struct zd_ioreq32 reqs[2] = { | ||
412 | [0] = { .addr = CR_MAC_ADDR_P1 }, | ||
413 | [1] = { .addr = CR_MAC_ADDR_P2 }, | ||
414 | }; | ||
415 | |||
416 | reqs[0].value = (mac_addr[3] << 24) | ||
417 | | (mac_addr[2] << 16) | ||
418 | | (mac_addr[1] << 8) | ||
419 | | mac_addr[0]; | ||
420 | reqs[1].value = (mac_addr[5] << 8) | ||
421 | | mac_addr[4]; | ||
422 | |||
423 | dev_dbg_f(zd_chip_dev(chip), | ||
424 | "mac addr " MAC_FMT "\n", MAC_ARG(mac_addr)); | ||
425 | |||
426 | mutex_lock(&chip->mutex); | ||
427 | r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); | ||
428 | #ifdef DEBUG | ||
429 | { | ||
430 | u8 tmp[ETH_ALEN]; | ||
431 | read_mac_addr(chip, tmp); | ||
432 | } | ||
433 | #endif /* DEBUG */ | ||
434 | mutex_unlock(&chip->mutex); | ||
435 | return r; | ||
436 | } | ||
437 | |||
438 | int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain) | ||
439 | { | ||
440 | int r; | ||
441 | u32 value; | ||
442 | |||
443 | mutex_lock(&chip->mutex); | ||
444 | r = zd_ioread32_locked(chip, &value, E2P_SUBID); | ||
445 | mutex_unlock(&chip->mutex); | ||
446 | if (r) | ||
447 | return r; | ||
448 | |||
449 | *regdomain = value >> 16; | ||
450 | dev_dbg_f(zd_chip_dev(chip), "regdomain: %#04x\n", *regdomain); | ||
451 | |||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static int read_values(struct zd_chip *chip, u8 *values, size_t count, | ||
456 | zd_addr_t e2p_addr, u32 guard) | ||
457 | { | ||
458 | int r; | ||
459 | int i; | ||
460 | u32 v; | ||
461 | |||
462 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
463 | for (i = 0;;) { | ||
464 | r = zd_ioread32_locked(chip, &v, e2p_addr+i/2); | ||
465 | if (r) | ||
466 | return r; | ||
467 | v -= guard; | ||
468 | if (i+4 < count) { | ||
469 | values[i++] = v; | ||
470 | values[i++] = v >> 8; | ||
471 | values[i++] = v >> 16; | ||
472 | values[i++] = v >> 24; | ||
473 | continue; | ||
474 | } | ||
475 | for (;i < count; i++) | ||
476 | values[i] = v >> (8*(i%3)); | ||
477 | return 0; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | static int read_pwr_cal_values(struct zd_chip *chip) | ||
482 | { | ||
483 | return read_values(chip, chip->pwr_cal_values, | ||
484 | E2P_CHANNEL_COUNT, E2P_PWR_CAL_VALUE1, | ||
485 | 0); | ||
486 | } | ||
487 | |||
488 | static int read_pwr_int_values(struct zd_chip *chip) | ||
489 | { | ||
490 | return read_values(chip, chip->pwr_int_values, | ||
491 | E2P_CHANNEL_COUNT, E2P_PWR_INT_VALUE1, | ||
492 | E2P_PWR_INT_GUARD); | ||
493 | } | ||
494 | |||
495 | static int read_ofdm_cal_values(struct zd_chip *chip) | ||
496 | { | ||
497 | int r; | ||
498 | int i; | ||
499 | static const zd_addr_t addresses[] = { | ||
500 | E2P_36M_CAL_VALUE1, | ||
501 | E2P_48M_CAL_VALUE1, | ||
502 | E2P_54M_CAL_VALUE1, | ||
503 | }; | ||
504 | |||
505 | for (i = 0; i < 3; i++) { | ||
506 | r = read_values(chip, chip->ofdm_cal_values[i], | ||
507 | E2P_CHANNEL_COUNT, addresses[i], 0); | ||
508 | if (r) | ||
509 | return r; | ||
510 | } | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static int read_cal_int_tables(struct zd_chip *chip) | ||
515 | { | ||
516 | int r; | ||
517 | |||
518 | r = read_pwr_cal_values(chip); | ||
519 | if (r) | ||
520 | return r; | ||
521 | r = read_pwr_int_values(chip); | ||
522 | if (r) | ||
523 | return r; | ||
524 | r = read_ofdm_cal_values(chip); | ||
525 | if (r) | ||
526 | return r; | ||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | /* phy means physical registers */ | ||
531 | int zd_chip_lock_phy_regs(struct zd_chip *chip) | ||
532 | { | ||
533 | int r; | ||
534 | u32 tmp; | ||
535 | |||
536 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
537 | r = zd_ioread32_locked(chip, &tmp, CR_REG1); | ||
538 | if (r) { | ||
539 | dev_err(zd_chip_dev(chip), "error ioread32(CR_REG1): %d\n", r); | ||
540 | return r; | ||
541 | } | ||
542 | |||
543 | dev_dbg_f(zd_chip_dev(chip), | ||
544 | "CR_REG1: 0x%02x -> 0x%02x\n", tmp, tmp & ~UNLOCK_PHY_REGS); | ||
545 | tmp &= ~UNLOCK_PHY_REGS; | ||
546 | |||
547 | r = zd_iowrite32_locked(chip, tmp, CR_REG1); | ||
548 | if (r) | ||
549 | dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r); | ||
550 | return r; | ||
551 | } | ||
552 | |||
553 | int zd_chip_unlock_phy_regs(struct zd_chip *chip) | ||
554 | { | ||
555 | int r; | ||
556 | u32 tmp; | ||
557 | |||
558 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
559 | r = zd_ioread32_locked(chip, &tmp, CR_REG1); | ||
560 | if (r) { | ||
561 | dev_err(zd_chip_dev(chip), | ||
562 | "error ioread32(CR_REG1): %d\n", r); | ||
563 | return r; | ||
564 | } | ||
565 | |||
566 | dev_dbg_f(zd_chip_dev(chip), | ||
567 | "CR_REG1: 0x%02x -> 0x%02x\n", tmp, tmp | UNLOCK_PHY_REGS); | ||
568 | tmp |= UNLOCK_PHY_REGS; | ||
569 | |||
570 | r = zd_iowrite32_locked(chip, tmp, CR_REG1); | ||
571 | if (r) | ||
572 | dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r); | ||
573 | return r; | ||
574 | } | ||
575 | |||
576 | /* CR157 can be optionally patched by the EEPROM */ | ||
577 | static int patch_cr157(struct zd_chip *chip) | ||
578 | { | ||
579 | int r; | ||
580 | u32 value; | ||
581 | |||
582 | if (!chip->patch_cr157) | ||
583 | return 0; | ||
584 | |||
585 | r = zd_ioread32_locked(chip, &value, E2P_PHY_REG); | ||
586 | if (r) | ||
587 | return r; | ||
588 | |||
589 | dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value >> 8); | ||
590 | return zd_iowrite32_locked(chip, value >> 8, CR157); | ||
591 | } | ||
592 | |||
593 | /* | ||
594 | * 6M band edge can be optionally overwritten for certain RF's | ||
595 | * Vendor driver says: for FCC regulation, enabled per HWFeature 6M band edge | ||
596 | * bit (for AL2230, AL2230S) | ||
597 | */ | ||
598 | static int patch_6m_band_edge(struct zd_chip *chip, int channel) | ||
599 | { | ||
600 | struct zd_ioreq16 ioreqs[] = { | ||
601 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, | ||
602 | { CR47, 0x1e }, | ||
603 | }; | ||
604 | |||
605 | if (!chip->patch_6m_band_edge || !chip->rf.patch_6m_band_edge) | ||
606 | return 0; | ||
607 | |||
608 | /* FIXME: Channel 11 is not the edge for all regulatory domains. */ | ||
609 | if (channel == 1 || channel == 11) | ||
610 | ioreqs[0].value = 0x12; | ||
611 | |||
612 | dev_dbg_f(zd_chip_dev(chip), "patching for channel %d\n", channel); | ||
613 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
614 | } | ||
615 | |||
616 | static int zd1211_hw_reset_phy(struct zd_chip *chip) | ||
617 | { | ||
618 | static const struct zd_ioreq16 ioreqs[] = { | ||
619 | { CR0, 0x0a }, { CR1, 0x06 }, { CR2, 0x26 }, | ||
620 | { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xa0 }, | ||
621 | { CR10, 0x81 }, { CR11, 0x00 }, { CR12, 0x7f }, | ||
622 | { CR13, 0x8c }, { CR14, 0x80 }, { CR15, 0x3d }, | ||
623 | { CR16, 0x20 }, { CR17, 0x1e }, { CR18, 0x0a }, | ||
624 | { CR19, 0x48 }, { CR20, 0x0c }, { CR21, 0x0c }, | ||
625 | { CR22, 0x23 }, { CR23, 0x90 }, { CR24, 0x14 }, | ||
626 | { CR25, 0x40 }, { CR26, 0x10 }, { CR27, 0x19 }, | ||
627 | { CR28, 0x7f }, { CR29, 0x80 }, { CR30, 0x4b }, | ||
628 | { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, | ||
629 | { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, | ||
630 | { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, | ||
631 | { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, | ||
632 | { CR43, 0x10 }, { CR44, 0x12 }, { CR46, 0xff }, | ||
633 | { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, | ||
634 | { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, | ||
635 | { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, | ||
636 | { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, | ||
637 | { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, | ||
638 | { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, | ||
639 | { CR79, 0x68 }, { CR80, 0x64 }, { CR81, 0x64 }, | ||
640 | { CR82, 0x00 }, { CR83, 0x00 }, { CR84, 0x00 }, | ||
641 | { CR85, 0x02 }, { CR86, 0x00 }, { CR87, 0x00 }, | ||
642 | { CR88, 0xff }, { CR89, 0xfc }, { CR90, 0x00 }, | ||
643 | { CR91, 0x00 }, { CR92, 0x00 }, { CR93, 0x08 }, | ||
644 | { CR94, 0x00 }, { CR95, 0x00 }, { CR96, 0xff }, | ||
645 | { CR97, 0xe7 }, { CR98, 0x00 }, { CR99, 0x00 }, | ||
646 | { CR100, 0x00 }, { CR101, 0xae }, { CR102, 0x02 }, | ||
647 | { CR103, 0x00 }, { CR104, 0x03 }, { CR105, 0x65 }, | ||
648 | { CR106, 0x04 }, { CR107, 0x00 }, { CR108, 0x0a }, | ||
649 | { CR109, 0xaa }, { CR110, 0xaa }, { CR111, 0x25 }, | ||
650 | { CR112, 0x25 }, { CR113, 0x00 }, { CR119, 0x1e }, | ||
651 | { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, | ||
652 | { }, | ||
653 | { CR5, 0x00 }, { CR6, 0x00 }, { CR7, 0x00 }, | ||
654 | { CR8, 0x00 }, { CR9, 0x20 }, { CR12, 0xf0 }, | ||
655 | { CR20, 0x0e }, { CR21, 0x0e }, { CR27, 0x10 }, | ||
656 | { CR44, 0x33 }, { CR47, 0x1E }, { CR83, 0x24 }, | ||
657 | { CR84, 0x04 }, { CR85, 0x00 }, { CR86, 0x0C }, | ||
658 | { CR87, 0x12 }, { CR88, 0x0C }, { CR89, 0x00 }, | ||
659 | { CR90, 0x10 }, { CR91, 0x08 }, { CR93, 0x00 }, | ||
660 | { CR94, 0x01 }, { CR95, 0x00 }, { CR96, 0x50 }, | ||
661 | { CR97, 0x37 }, { CR98, 0x35 }, { CR101, 0x13 }, | ||
662 | { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, | ||
663 | { CR105, 0x12 }, { CR109, 0x27 }, { CR110, 0x27 }, | ||
664 | { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, | ||
665 | { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, | ||
666 | { CR117, 0xfc }, { CR118, 0xfa }, { CR120, 0x4f }, | ||
667 | { CR123, 0x27 }, { CR125, 0xaa }, { CR127, 0x03 }, | ||
668 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, | ||
669 | { CR131, 0x0C }, { CR136, 0xdf }, { CR137, 0x40 }, | ||
670 | { CR138, 0xa0 }, { CR139, 0xb0 }, { CR140, 0x99 }, | ||
671 | { CR141, 0x82 }, { CR142, 0x54 }, { CR143, 0x1c }, | ||
672 | { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x4c }, | ||
673 | { CR149, 0x50 }, { CR150, 0x0e }, { CR151, 0x18 }, | ||
674 | { CR160, 0xfe }, { CR161, 0xee }, { CR162, 0xaa }, | ||
675 | { CR163, 0xfa }, { CR164, 0xfa }, { CR165, 0xea }, | ||
676 | { CR166, 0xbe }, { CR167, 0xbe }, { CR168, 0x6a }, | ||
677 | { CR169, 0xba }, { CR170, 0xba }, { CR171, 0xba }, | ||
678 | /* Note: CR204 must lead the CR203 */ | ||
679 | { CR204, 0x7d }, | ||
680 | { }, | ||
681 | { CR203, 0x30 }, | ||
682 | }; | ||
683 | |||
684 | int r, t; | ||
685 | |||
686 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
687 | |||
688 | r = zd_chip_lock_phy_regs(chip); | ||
689 | if (r) | ||
690 | goto out; | ||
691 | |||
692 | r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
693 | if (r) | ||
694 | goto unlock; | ||
695 | |||
696 | r = patch_cr157(chip); | ||
697 | unlock: | ||
698 | t = zd_chip_unlock_phy_regs(chip); | ||
699 | if (t && !r) | ||
700 | r = t; | ||
701 | out: | ||
702 | return r; | ||
703 | } | ||
704 | |||
705 | static int zd1211b_hw_reset_phy(struct zd_chip *chip) | ||
706 | { | ||
707 | static const struct zd_ioreq16 ioreqs[] = { | ||
708 | { CR0, 0x14 }, { CR1, 0x06 }, { CR2, 0x26 }, | ||
709 | { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xe0 }, | ||
710 | { CR10, 0x81 }, | ||
711 | /* power control { { CR11, 1 << 6 }, */ | ||
712 | { CR11, 0x00 }, | ||
713 | { CR12, 0xf0 }, { CR13, 0x8c }, { CR14, 0x80 }, | ||
714 | { CR15, 0x3d }, { CR16, 0x20 }, { CR17, 0x1e }, | ||
715 | { CR18, 0x0a }, { CR19, 0x48 }, | ||
716 | { CR20, 0x10 }, /* Org:0x0E, ComTrend:RalLink AP */ | ||
717 | { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, | ||
718 | { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, | ||
719 | { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, | ||
720 | { CR30, 0x49 }, /* jointly decoder, no ASIC */ | ||
721 | { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, | ||
722 | { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, | ||
723 | { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, | ||
724 | { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, | ||
725 | { CR43, 0x10 }, { CR44, 0x33 }, { CR46, 0xff }, | ||
726 | { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, | ||
727 | { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, | ||
728 | { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, | ||
729 | { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, | ||
730 | { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, | ||
731 | { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, | ||
732 | { CR79, 0xf0 }, { CR80, 0x64 }, { CR81, 0x64 }, | ||
733 | { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, | ||
734 | { CR85, 0x00 }, { CR86, 0x0c }, { CR87, 0x12 }, | ||
735 | { CR88, 0x0c }, { CR89, 0x00 }, { CR90, 0x58 }, | ||
736 | { CR91, 0x04 }, { CR92, 0x00 }, { CR93, 0x00 }, | ||
737 | { CR94, 0x01 }, | ||
738 | { CR95, 0x20 }, /* ZD1211B */ | ||
739 | { CR96, 0x50 }, { CR97, 0x37 }, { CR98, 0x35 }, | ||
740 | { CR99, 0x00 }, { CR100, 0x01 }, { CR101, 0x13 }, | ||
741 | { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, | ||
742 | { CR105, 0x12 }, { CR106, 0x04 }, { CR107, 0x00 }, | ||
743 | { CR108, 0x0a }, { CR109, 0x27 }, { CR110, 0x27 }, | ||
744 | { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, | ||
745 | { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, | ||
746 | { CR117, 0xfc }, { CR118, 0xfa }, { CR119, 0x1e }, | ||
747 | { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, | ||
748 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, | ||
749 | { CR131, 0x0c }, { CR136, 0xdf }, { CR137, 0xa0 }, | ||
750 | { CR138, 0xa8 }, { CR139, 0xb4 }, { CR140, 0x98 }, | ||
751 | { CR141, 0x82 }, { CR142, 0x53 }, { CR143, 0x1c }, | ||
752 | { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x40 }, | ||
753 | { CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */ | ||
754 | { CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */ | ||
755 | { CR151, 0x18 }, { CR159, 0x70 }, { CR160, 0xfe }, | ||
756 | { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa }, | ||
757 | { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe }, | ||
758 | { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba }, | ||
759 | { CR170, 0xba }, { CR171, 0xba }, | ||
760 | /* Note: CR204 must lead the CR203 */ | ||
761 | { CR204, 0x7d }, | ||
762 | {}, | ||
763 | { CR203, 0x30 }, | ||
764 | }; | ||
765 | |||
766 | int r, t; | ||
767 | |||
768 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
769 | |||
770 | r = zd_chip_lock_phy_regs(chip); | ||
771 | if (r) | ||
772 | goto out; | ||
773 | |||
774 | r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
775 | if (r) | ||
776 | goto unlock; | ||
777 | |||
778 | r = patch_cr157(chip); | ||
779 | unlock: | ||
780 | t = zd_chip_unlock_phy_regs(chip); | ||
781 | if (t && !r) | ||
782 | r = t; | ||
783 | out: | ||
784 | return r; | ||
785 | } | ||
786 | |||
787 | static int hw_reset_phy(struct zd_chip *chip) | ||
788 | { | ||
789 | return chip->is_zd1211b ? zd1211b_hw_reset_phy(chip) : | ||
790 | zd1211_hw_reset_phy(chip); | ||
791 | } | ||
792 | |||
793 | static int zd1211_hw_init_hmac(struct zd_chip *chip) | ||
794 | { | ||
795 | static const struct zd_ioreq32 ioreqs[] = { | ||
796 | { CR_ACK_TIMEOUT_EXT, 0x20 }, | ||
797 | { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, | ||
798 | { CR_ZD1211_RETRY_MAX, 0x2 }, | ||
799 | { CR_SNIFFER_ON, 0 }, | ||
800 | { CR_RX_FILTER, AP_RX_FILTER }, | ||
801 | { CR_GROUP_HASH_P1, 0x00 }, | ||
802 | { CR_GROUP_HASH_P2, 0x80000000 }, | ||
803 | { CR_REG1, 0xa4 }, | ||
804 | { CR_ADDA_PWR_DWN, 0x7f }, | ||
805 | { CR_BCN_PLCP_CFG, 0x00f00401 }, | ||
806 | { CR_PHY_DELAY, 0x00 }, | ||
807 | { CR_ACK_TIMEOUT_EXT, 0x80 }, | ||
808 | { CR_ADDA_PWR_DWN, 0x00 }, | ||
809 | { CR_ACK_TIME_80211, 0x100 }, | ||
810 | { CR_IFS_VALUE, 0x547c032 }, | ||
811 | { CR_RX_PE_DELAY, 0x70 }, | ||
812 | { CR_PS_CTRL, 0x10000000 }, | ||
813 | { CR_RTS_CTS_RATE, 0x02030203 }, | ||
814 | { CR_RX_THRESHOLD, 0x000c0640 }, | ||
815 | { CR_AFTER_PNP, 0x1 }, | ||
816 | { CR_WEP_PROTECT, 0x114 }, | ||
817 | }; | ||
818 | |||
819 | int r; | ||
820 | |||
821 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
822 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
823 | r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
824 | #ifdef DEBUG | ||
825 | if (r) { | ||
826 | dev_err(zd_chip_dev(chip), | ||
827 | "error in zd_iowrite32a_locked. Error number %d\n", r); | ||
828 | } | ||
829 | #endif /* DEBUG */ | ||
830 | return r; | ||
831 | } | ||
832 | |||
833 | static int zd1211b_hw_init_hmac(struct zd_chip *chip) | ||
834 | { | ||
835 | static const struct zd_ioreq32 ioreqs[] = { | ||
836 | { CR_ACK_TIMEOUT_EXT, 0x20 }, | ||
837 | { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, | ||
838 | { CR_ZD1211B_RETRY_MAX, 0x02020202 }, | ||
839 | { CR_ZD1211B_TX_PWR_CTL4, 0x007f003f }, | ||
840 | { CR_ZD1211B_TX_PWR_CTL3, 0x007f003f }, | ||
841 | { CR_ZD1211B_TX_PWR_CTL2, 0x003f001f }, | ||
842 | { CR_ZD1211B_TX_PWR_CTL1, 0x001f000f }, | ||
843 | { CR_ZD1211B_AIFS_CTL1, 0x00280028 }, | ||
844 | { CR_ZD1211B_AIFS_CTL2, 0x008C003C }, | ||
845 | { CR_ZD1211B_TXOP, 0x01800824 }, | ||
846 | { CR_SNIFFER_ON, 0 }, | ||
847 | { CR_RX_FILTER, AP_RX_FILTER }, | ||
848 | { CR_GROUP_HASH_P1, 0x00 }, | ||
849 | { CR_GROUP_HASH_P2, 0x80000000 }, | ||
850 | { CR_REG1, 0xa4 }, | ||
851 | { CR_ADDA_PWR_DWN, 0x7f }, | ||
852 | { CR_BCN_PLCP_CFG, 0x00f00401 }, | ||
853 | { CR_PHY_DELAY, 0x00 }, | ||
854 | { CR_ACK_TIMEOUT_EXT, 0x80 }, | ||
855 | { CR_ADDA_PWR_DWN, 0x00 }, | ||
856 | { CR_ACK_TIME_80211, 0x100 }, | ||
857 | { CR_IFS_VALUE, 0x547c032 }, | ||
858 | { CR_RX_PE_DELAY, 0x70 }, | ||
859 | { CR_PS_CTRL, 0x10000000 }, | ||
860 | { CR_RTS_CTS_RATE, 0x02030203 }, | ||
861 | { CR_RX_THRESHOLD, 0x000c0640 }, | ||
862 | { CR_AFTER_PNP, 0x1 }, | ||
863 | { CR_WEP_PROTECT, 0x114 }, | ||
864 | }; | ||
865 | |||
866 | int r; | ||
867 | |||
868 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
869 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
870 | r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
871 | if (r) { | ||
872 | dev_dbg_f(zd_chip_dev(chip), | ||
873 | "error in zd_iowrite32a_locked. Error number %d\n", r); | ||
874 | } | ||
875 | return r; | ||
876 | } | ||
877 | |||
878 | static int hw_init_hmac(struct zd_chip *chip) | ||
879 | { | ||
880 | return chip->is_zd1211b ? | ||
881 | zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip); | ||
882 | } | ||
883 | |||
884 | struct aw_pt_bi { | ||
885 | u32 atim_wnd_period; | ||
886 | u32 pre_tbtt; | ||
887 | u32 beacon_interval; | ||
888 | }; | ||
889 | |||
890 | static int get_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) | ||
891 | { | ||
892 | int r; | ||
893 | static const zd_addr_t aw_pt_bi_addr[] = | ||
894 | { CR_ATIM_WND_PERIOD, CR_PRE_TBTT, CR_BCN_INTERVAL }; | ||
895 | u32 values[3]; | ||
896 | |||
897 | r = zd_ioread32v_locked(chip, values, (const zd_addr_t *)aw_pt_bi_addr, | ||
898 | ARRAY_SIZE(aw_pt_bi_addr)); | ||
899 | if (r) { | ||
900 | memset(s, 0, sizeof(*s)); | ||
901 | return r; | ||
902 | } | ||
903 | |||
904 | s->atim_wnd_period = values[0]; | ||
905 | s->pre_tbtt = values[1]; | ||
906 | s->beacon_interval = values[2]; | ||
907 | dev_dbg_f(zd_chip_dev(chip), "aw %u pt %u bi %u\n", | ||
908 | s->atim_wnd_period, s->pre_tbtt, s->beacon_interval); | ||
909 | return 0; | ||
910 | } | ||
911 | |||
912 | static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) | ||
913 | { | ||
914 | struct zd_ioreq32 reqs[3]; | ||
915 | |||
916 | if (s->beacon_interval <= 5) | ||
917 | s->beacon_interval = 5; | ||
918 | if (s->pre_tbtt < 4 || s->pre_tbtt >= s->beacon_interval) | ||
919 | s->pre_tbtt = s->beacon_interval - 1; | ||
920 | if (s->atim_wnd_period >= s->pre_tbtt) | ||
921 | s->atim_wnd_period = s->pre_tbtt - 1; | ||
922 | |||
923 | reqs[0].addr = CR_ATIM_WND_PERIOD; | ||
924 | reqs[0].value = s->atim_wnd_period; | ||
925 | reqs[1].addr = CR_PRE_TBTT; | ||
926 | reqs[1].value = s->pre_tbtt; | ||
927 | reqs[2].addr = CR_BCN_INTERVAL; | ||
928 | reqs[2].value = s->beacon_interval; | ||
929 | |||
930 | dev_dbg_f(zd_chip_dev(chip), | ||
931 | "aw %u pt %u bi %u\n", s->atim_wnd_period, s->pre_tbtt, | ||
932 | s->beacon_interval); | ||
933 | return zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); | ||
934 | } | ||
935 | |||
936 | |||
937 | static int set_beacon_interval(struct zd_chip *chip, u32 interval) | ||
938 | { | ||
939 | int r; | ||
940 | struct aw_pt_bi s; | ||
941 | |||
942 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
943 | r = get_aw_pt_bi(chip, &s); | ||
944 | if (r) | ||
945 | return r; | ||
946 | s.beacon_interval = interval; | ||
947 | return set_aw_pt_bi(chip, &s); | ||
948 | } | ||
949 | |||
950 | int zd_set_beacon_interval(struct zd_chip *chip, u32 interval) | ||
951 | { | ||
952 | int r; | ||
953 | |||
954 | mutex_lock(&chip->mutex); | ||
955 | r = set_beacon_interval(chip, interval); | ||
956 | mutex_unlock(&chip->mutex); | ||
957 | return r; | ||
958 | } | ||
959 | |||
960 | static int hw_init(struct zd_chip *chip) | ||
961 | { | ||
962 | int r; | ||
963 | |||
964 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
965 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
966 | r = hw_reset_phy(chip); | ||
967 | if (r) | ||
968 | return r; | ||
969 | |||
970 | r = hw_init_hmac(chip); | ||
971 | if (r) | ||
972 | return r; | ||
973 | r = set_beacon_interval(chip, 100); | ||
974 | if (r) | ||
975 | return r; | ||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | #ifdef DEBUG | ||
980 | static int dump_cr(struct zd_chip *chip, const zd_addr_t addr, | ||
981 | const char *addr_string) | ||
982 | { | ||
983 | int r; | ||
984 | u32 value; | ||
985 | |||
986 | r = zd_ioread32_locked(chip, &value, addr); | ||
987 | if (r) { | ||
988 | dev_dbg_f(zd_chip_dev(chip), | ||
989 | "error reading %s. Error number %d\n", addr_string, r); | ||
990 | return r; | ||
991 | } | ||
992 | |||
993 | dev_dbg_f(zd_chip_dev(chip), "%s %#010x\n", | ||
994 | addr_string, (unsigned int)value); | ||
995 | return 0; | ||
996 | } | ||
997 | |||
998 | static int test_init(struct zd_chip *chip) | ||
999 | { | ||
1000 | int r; | ||
1001 | |||
1002 | r = dump_cr(chip, CR_AFTER_PNP, "CR_AFTER_PNP"); | ||
1003 | if (r) | ||
1004 | return r; | ||
1005 | r = dump_cr(chip, CR_GPI_EN, "CR_GPI_EN"); | ||
1006 | if (r) | ||
1007 | return r; | ||
1008 | return dump_cr(chip, CR_INTERRUPT, "CR_INTERRUPT"); | ||
1009 | } | ||
1010 | |||
1011 | static void dump_fw_registers(struct zd_chip *chip) | ||
1012 | { | ||
1013 | static const zd_addr_t addr[4] = { | ||
1014 | FW_FIRMWARE_VER, FW_USB_SPEED, FW_FIX_TX_RATE, | ||
1015 | FW_LINK_STATUS | ||
1016 | }; | ||
1017 | |||
1018 | int r; | ||
1019 | u16 values[4]; | ||
1020 | |||
1021 | r = zd_ioread16v_locked(chip, values, (const zd_addr_t*)addr, | ||
1022 | ARRAY_SIZE(addr)); | ||
1023 | if (r) { | ||
1024 | dev_dbg_f(zd_chip_dev(chip), "error %d zd_ioread16v_locked\n", | ||
1025 | r); | ||
1026 | return; | ||
1027 | } | ||
1028 | |||
1029 | dev_dbg_f(zd_chip_dev(chip), "FW_FIRMWARE_VER %#06hx\n", values[0]); | ||
1030 | dev_dbg_f(zd_chip_dev(chip), "FW_USB_SPEED %#06hx\n", values[1]); | ||
1031 | dev_dbg_f(zd_chip_dev(chip), "FW_FIX_TX_RATE %#06hx\n", values[2]); | ||
1032 | dev_dbg_f(zd_chip_dev(chip), "FW_LINK_STATUS %#06hx\n", values[3]); | ||
1033 | } | ||
1034 | #endif /* DEBUG */ | ||
1035 | |||
1036 | static int print_fw_version(struct zd_chip *chip) | ||
1037 | { | ||
1038 | int r; | ||
1039 | u16 version; | ||
1040 | |||
1041 | r = zd_ioread16_locked(chip, &version, FW_FIRMWARE_VER); | ||
1042 | if (r) | ||
1043 | return r; | ||
1044 | |||
1045 | dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version); | ||
1046 | return 0; | ||
1047 | } | ||
1048 | |||
1049 | static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std) | ||
1050 | { | ||
1051 | u32 rates; | ||
1052 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
1053 | /* This sets the mandatory rates, which only depend from the standard | ||
1054 | * that the device is supporting. Until further notice we should try | ||
1055 | * to support 802.11g also for full speed USB. | ||
1056 | */ | ||
1057 | switch (std) { | ||
1058 | case IEEE80211B: | ||
1059 | rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M; | ||
1060 | break; | ||
1061 | case IEEE80211G: | ||
1062 | rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M| | ||
1063 | CR_RATE_6M|CR_RATE_12M|CR_RATE_24M; | ||
1064 | break; | ||
1065 | default: | ||
1066 | return -EINVAL; | ||
1067 | } | ||
1068 | return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL); | ||
1069 | } | ||
1070 | |||
1071 | int zd_chip_enable_hwint(struct zd_chip *chip) | ||
1072 | { | ||
1073 | int r; | ||
1074 | |||
1075 | mutex_lock(&chip->mutex); | ||
1076 | r = zd_iowrite32_locked(chip, HWINT_ENABLED, CR_INTERRUPT); | ||
1077 | mutex_unlock(&chip->mutex); | ||
1078 | return r; | ||
1079 | } | ||
1080 | |||
1081 | static int disable_hwint(struct zd_chip *chip) | ||
1082 | { | ||
1083 | return zd_iowrite32_locked(chip, HWINT_DISABLED, CR_INTERRUPT); | ||
1084 | } | ||
1085 | |||
1086 | int zd_chip_disable_hwint(struct zd_chip *chip) | ||
1087 | { | ||
1088 | int r; | ||
1089 | |||
1090 | mutex_lock(&chip->mutex); | ||
1091 | r = disable_hwint(chip); | ||
1092 | mutex_unlock(&chip->mutex); | ||
1093 | return r; | ||
1094 | } | ||
1095 | |||
1096 | int zd_chip_init_hw(struct zd_chip *chip, u8 device_type) | ||
1097 | { | ||
1098 | int r; | ||
1099 | u8 rf_type; | ||
1100 | |||
1101 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
1102 | |||
1103 | mutex_lock(&chip->mutex); | ||
1104 | chip->is_zd1211b = (device_type == DEVICE_ZD1211B) != 0; | ||
1105 | |||
1106 | #ifdef DEBUG | ||
1107 | r = test_init(chip); | ||
1108 | if (r) | ||
1109 | goto out; | ||
1110 | #endif | ||
1111 | r = zd_iowrite32_locked(chip, 1, CR_AFTER_PNP); | ||
1112 | if (r) | ||
1113 | goto out; | ||
1114 | |||
1115 | r = zd_usb_init_hw(&chip->usb); | ||
1116 | if (r) | ||
1117 | goto out; | ||
1118 | |||
1119 | /* GPI is always disabled, also in the other driver. | ||
1120 | */ | ||
1121 | r = zd_iowrite32_locked(chip, 0, CR_GPI_EN); | ||
1122 | if (r) | ||
1123 | goto out; | ||
1124 | r = zd_iowrite32_locked(chip, CWIN_SIZE, CR_CWMIN_CWMAX); | ||
1125 | if (r) | ||
1126 | goto out; | ||
1127 | /* Currently we support IEEE 802.11g for full and high speed USB. | ||
1128 | * It might be discussed, whether we should suppport pure b mode for | ||
1129 | * full speed USB. | ||
1130 | */ | ||
1131 | r = set_mandatory_rates(chip, IEEE80211G); | ||
1132 | if (r) | ||
1133 | goto out; | ||
1134 | /* Disabling interrupts is certainly a smart thing here. | ||
1135 | */ | ||
1136 | r = disable_hwint(chip); | ||
1137 | if (r) | ||
1138 | goto out; | ||
1139 | r = read_pod(chip, &rf_type); | ||
1140 | if (r) | ||
1141 | goto out; | ||
1142 | r = hw_init(chip); | ||
1143 | if (r) | ||
1144 | goto out; | ||
1145 | r = zd_rf_init_hw(&chip->rf, rf_type); | ||
1146 | if (r) | ||
1147 | goto out; | ||
1148 | |||
1149 | r = print_fw_version(chip); | ||
1150 | if (r) | ||
1151 | goto out; | ||
1152 | |||
1153 | #ifdef DEBUG | ||
1154 | dump_fw_registers(chip); | ||
1155 | r = test_init(chip); | ||
1156 | if (r) | ||
1157 | goto out; | ||
1158 | #endif /* DEBUG */ | ||
1159 | |||
1160 | r = read_e2p_mac_addr(chip); | ||
1161 | if (r) | ||
1162 | goto out; | ||
1163 | |||
1164 | r = read_cal_int_tables(chip); | ||
1165 | if (r) | ||
1166 | goto out; | ||
1167 | |||
1168 | print_id(chip); | ||
1169 | out: | ||
1170 | mutex_unlock(&chip->mutex); | ||
1171 | return r; | ||
1172 | } | ||
1173 | |||
1174 | static int update_pwr_int(struct zd_chip *chip, u8 channel) | ||
1175 | { | ||
1176 | u8 value = chip->pwr_int_values[channel - 1]; | ||
1177 | dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_int %#04x\n", | ||
1178 | channel, value); | ||
1179 | return zd_iowrite32_locked(chip, value, CR31); | ||
1180 | } | ||
1181 | |||
1182 | static int update_pwr_cal(struct zd_chip *chip, u8 channel) | ||
1183 | { | ||
1184 | u8 value = chip->pwr_cal_values[channel-1]; | ||
1185 | dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_cal %#04x\n", | ||
1186 | channel, value); | ||
1187 | return zd_iowrite32_locked(chip, value, CR68); | ||
1188 | } | ||
1189 | |||
1190 | static int update_ofdm_cal(struct zd_chip *chip, u8 channel) | ||
1191 | { | ||
1192 | struct zd_ioreq32 ioreqs[3]; | ||
1193 | |||
1194 | ioreqs[0].addr = CR67; | ||
1195 | ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1]; | ||
1196 | ioreqs[1].addr = CR66; | ||
1197 | ioreqs[1].value = chip->ofdm_cal_values[OFDM_48M_INDEX][channel-1]; | ||
1198 | ioreqs[2].addr = CR65; | ||
1199 | ioreqs[2].value = chip->ofdm_cal_values[OFDM_54M_INDEX][channel-1]; | ||
1200 | |||
1201 | dev_dbg_f(zd_chip_dev(chip), | ||
1202 | "channel %d ofdm_cal 36M %#04x 48M %#04x 54M %#04x\n", | ||
1203 | channel, ioreqs[0].value, ioreqs[1].value, ioreqs[2].value); | ||
1204 | return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
1205 | } | ||
1206 | |||
1207 | static int update_channel_integration_and_calibration(struct zd_chip *chip, | ||
1208 | u8 channel) | ||
1209 | { | ||
1210 | int r; | ||
1211 | |||
1212 | r = update_pwr_int(chip, channel); | ||
1213 | if (r) | ||
1214 | return r; | ||
1215 | if (chip->is_zd1211b) { | ||
1216 | static const struct zd_ioreq32 ioreqs[] = { | ||
1217 | { CR69, 0x28 }, | ||
1218 | {}, | ||
1219 | { CR69, 0x2a }, | ||
1220 | }; | ||
1221 | |||
1222 | r = update_ofdm_cal(chip, channel); | ||
1223 | if (r) | ||
1224 | return r; | ||
1225 | r = update_pwr_cal(chip, channel); | ||
1226 | if (r) | ||
1227 | return r; | ||
1228 | r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
1229 | if (r) | ||
1230 | return r; | ||
1231 | } | ||
1232 | |||
1233 | return 0; | ||
1234 | } | ||
1235 | |||
1236 | /* The CCK baseband gain can be optionally patched by the EEPROM */ | ||
1237 | static int patch_cck_gain(struct zd_chip *chip) | ||
1238 | { | ||
1239 | int r; | ||
1240 | u32 value; | ||
1241 | |||
1242 | if (!chip->patch_cck_gain) | ||
1243 | return 0; | ||
1244 | |||
1245 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
1246 | r = zd_ioread32_locked(chip, &value, E2P_PHY_REG); | ||
1247 | if (r) | ||
1248 | return r; | ||
1249 | dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff); | ||
1250 | return zd_iowrite32_locked(chip, value & 0xff, CR47); | ||
1251 | } | ||
1252 | |||
1253 | int zd_chip_set_channel(struct zd_chip *chip, u8 channel) | ||
1254 | { | ||
1255 | int r, t; | ||
1256 | |||
1257 | mutex_lock(&chip->mutex); | ||
1258 | r = zd_chip_lock_phy_regs(chip); | ||
1259 | if (r) | ||
1260 | goto out; | ||
1261 | r = zd_rf_set_channel(&chip->rf, channel); | ||
1262 | if (r) | ||
1263 | goto unlock; | ||
1264 | r = update_channel_integration_and_calibration(chip, channel); | ||
1265 | if (r) | ||
1266 | goto unlock; | ||
1267 | r = patch_cck_gain(chip); | ||
1268 | if (r) | ||
1269 | goto unlock; | ||
1270 | r = patch_6m_band_edge(chip, channel); | ||
1271 | if (r) | ||
1272 | goto unlock; | ||
1273 | r = zd_iowrite32_locked(chip, 0, CR_CONFIG_PHILIPS); | ||
1274 | unlock: | ||
1275 | t = zd_chip_unlock_phy_regs(chip); | ||
1276 | if (t && !r) | ||
1277 | r = t; | ||
1278 | out: | ||
1279 | mutex_unlock(&chip->mutex); | ||
1280 | return r; | ||
1281 | } | ||
1282 | |||
1283 | u8 zd_chip_get_channel(struct zd_chip *chip) | ||
1284 | { | ||
1285 | u8 channel; | ||
1286 | |||
1287 | mutex_lock(&chip->mutex); | ||
1288 | channel = chip->rf.channel; | ||
1289 | mutex_unlock(&chip->mutex); | ||
1290 | return channel; | ||
1291 | } | ||
1292 | |||
1293 | static u16 led_mask(int led) | ||
1294 | { | ||
1295 | switch (led) { | ||
1296 | case 1: | ||
1297 | return LED1; | ||
1298 | case 2: | ||
1299 | return LED2; | ||
1300 | default: | ||
1301 | return 0; | ||
1302 | } | ||
1303 | } | ||
1304 | |||
1305 | static int read_led_reg(struct zd_chip *chip, u16 *status) | ||
1306 | { | ||
1307 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
1308 | return zd_ioread16_locked(chip, status, CR_LED); | ||
1309 | } | ||
1310 | |||
1311 | static int write_led_reg(struct zd_chip *chip, u16 status) | ||
1312 | { | ||
1313 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
1314 | return zd_iowrite16_locked(chip, status, CR_LED); | ||
1315 | } | ||
1316 | |||
1317 | int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status) | ||
1318 | { | ||
1319 | int r, ret; | ||
1320 | u16 mask = led_mask(led); | ||
1321 | u16 reg; | ||
1322 | |||
1323 | if (!mask) | ||
1324 | return -EINVAL; | ||
1325 | mutex_lock(&chip->mutex); | ||
1326 | r = read_led_reg(chip, ®); | ||
1327 | if (r) | ||
1328 | return r; | ||
1329 | switch (status) { | ||
1330 | case LED_STATUS: | ||
1331 | return (reg & mask) ? LED_ON : LED_OFF; | ||
1332 | case LED_OFF: | ||
1333 | reg &= ~mask; | ||
1334 | ret = LED_OFF; | ||
1335 | break; | ||
1336 | case LED_FLIP: | ||
1337 | reg ^= mask; | ||
1338 | ret = (reg&mask) ? LED_ON : LED_OFF; | ||
1339 | break; | ||
1340 | case LED_ON: | ||
1341 | reg |= mask; | ||
1342 | ret = LED_ON; | ||
1343 | break; | ||
1344 | default: | ||
1345 | return -EINVAL; | ||
1346 | } | ||
1347 | r = write_led_reg(chip, reg); | ||
1348 | if (r) { | ||
1349 | ret = r; | ||
1350 | goto out; | ||
1351 | } | ||
1352 | out: | ||
1353 | mutex_unlock(&chip->mutex); | ||
1354 | return r; | ||
1355 | } | ||
1356 | |||
1357 | int zd_chip_led_flip(struct zd_chip *chip, int led, | ||
1358 | const unsigned int *phases_msecs, unsigned int count) | ||
1359 | { | ||
1360 | int i, r; | ||
1361 | enum led_status status; | ||
1362 | |||
1363 | r = zd_chip_led_status(chip, led, LED_STATUS); | ||
1364 | if (r) | ||
1365 | return r; | ||
1366 | status = r; | ||
1367 | for (i = 0; i < count; i++) { | ||
1368 | r = zd_chip_led_status(chip, led, LED_FLIP); | ||
1369 | if (r < 0) | ||
1370 | goto out; | ||
1371 | msleep(phases_msecs[i]); | ||
1372 | } | ||
1373 | |||
1374 | out: | ||
1375 | zd_chip_led_status(chip, led, status); | ||
1376 | return r; | ||
1377 | } | ||
1378 | |||
1379 | int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) | ||
1380 | { | ||
1381 | int r; | ||
1382 | |||
1383 | if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G)) | ||
1384 | return -EINVAL; | ||
1385 | |||
1386 | mutex_lock(&chip->mutex); | ||
1387 | r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL); | ||
1388 | mutex_unlock(&chip->mutex); | ||
1389 | return r; | ||
1390 | } | ||
1391 | |||
1392 | static int ofdm_qual_db(u8 status_quality, u8 rate, unsigned int size) | ||
1393 | { | ||
1394 | static const u16 constants[] = { | ||
1395 | 715, 655, 585, 540, 470, 410, 360, 315, | ||
1396 | 270, 235, 205, 175, 150, 125, 105, 85, | ||
1397 | 65, 50, 40, 25, 15 | ||
1398 | }; | ||
1399 | |||
1400 | int i; | ||
1401 | u32 x; | ||
1402 | |||
1403 | /* It seems that their quality parameter is somehow per signal | ||
1404 | * and is now transferred per bit. | ||
1405 | */ | ||
1406 | switch (rate) { | ||
1407 | case ZD_OFDM_RATE_6M: | ||
1408 | case ZD_OFDM_RATE_12M: | ||
1409 | case ZD_OFDM_RATE_24M: | ||
1410 | size *= 2; | ||
1411 | break; | ||
1412 | case ZD_OFDM_RATE_9M: | ||
1413 | case ZD_OFDM_RATE_18M: | ||
1414 | case ZD_OFDM_RATE_36M: | ||
1415 | case ZD_OFDM_RATE_54M: | ||
1416 | size *= 4; | ||
1417 | size /= 3; | ||
1418 | break; | ||
1419 | case ZD_OFDM_RATE_48M: | ||
1420 | size *= 3; | ||
1421 | size /= 2; | ||
1422 | break; | ||
1423 | default: | ||
1424 | return -EINVAL; | ||
1425 | } | ||
1426 | |||
1427 | x = (10000 * status_quality)/size; | ||
1428 | for (i = 0; i < ARRAY_SIZE(constants); i++) { | ||
1429 | if (x > constants[i]) | ||
1430 | break; | ||
1431 | } | ||
1432 | |||
1433 | return i; | ||
1434 | } | ||
1435 | |||
1436 | static unsigned int log10times100(unsigned int x) | ||
1437 | { | ||
1438 | static const u8 log10[] = { | ||
1439 | 0, | ||
1440 | 0, 30, 47, 60, 69, 77, 84, 90, 95, 100, | ||
1441 | 104, 107, 111, 114, 117, 120, 123, 125, 127, 130, | ||
1442 | 132, 134, 136, 138, 139, 141, 143, 144, 146, 147, | ||
1443 | 149, 150, 151, 153, 154, 155, 156, 157, 159, 160, | ||
1444 | 161, 162, 163, 164, 165, 166, 167, 168, 169, 169, | ||
1445 | 170, 171, 172, 173, 174, 174, 175, 176, 177, 177, | ||
1446 | 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, | ||
1447 | 185, 185, 186, 186, 187, 188, 188, 189, 189, 190, | ||
1448 | 190, 191, 191, 192, 192, 193, 193, 194, 194, 195, | ||
1449 | 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, | ||
1450 | 200, 200, 201, 201, 202, 202, 202, 203, 203, 204, | ||
1451 | 204, 204, 205, 205, 206, 206, 206, 207, 207, 207, | ||
1452 | 208, 208, 208, 209, 209, 210, 210, 210, 211, 211, | ||
1453 | 211, 212, 212, 212, 213, 213, 213, 213, 214, 214, | ||
1454 | 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, | ||
1455 | 217, 218, 218, 218, 219, 219, 219, 219, 220, 220, | ||
1456 | 220, 220, 221, 221, 221, 222, 222, 222, 222, 223, | ||
1457 | 223, 223, 223, 224, 224, 224, 224, | ||
1458 | }; | ||
1459 | |||
1460 | return x < ARRAY_SIZE(log10) ? log10[x] : 225; | ||
1461 | } | ||
1462 | |||
1463 | enum { | ||
1464 | MAX_CCK_EVM_DB = 45, | ||
1465 | }; | ||
1466 | |||
1467 | static int cck_evm_db(u8 status_quality) | ||
1468 | { | ||
1469 | return (20 * log10times100(status_quality)) / 100; | ||
1470 | } | ||
1471 | |||
1472 | static int cck_snr_db(u8 status_quality) | ||
1473 | { | ||
1474 | int r = MAX_CCK_EVM_DB - cck_evm_db(status_quality); | ||
1475 | ZD_ASSERT(r >= 0); | ||
1476 | return r; | ||
1477 | } | ||
1478 | |||
1479 | static int rx_qual_db(const void *rx_frame, unsigned int size, | ||
1480 | const struct rx_status *status) | ||
1481 | { | ||
1482 | return (status->frame_status&ZD_RX_OFDM) ? | ||
1483 | ofdm_qual_db(status->signal_quality_ofdm, | ||
1484 | zd_ofdm_plcp_header_rate(rx_frame), | ||
1485 | size) : | ||
1486 | cck_snr_db(status->signal_quality_cck); | ||
1487 | } | ||
1488 | |||
1489 | u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, | ||
1490 | const struct rx_status *status) | ||
1491 | { | ||
1492 | int r = rx_qual_db(rx_frame, size, status); | ||
1493 | if (r < 0) | ||
1494 | r = 0; | ||
1495 | r = (r * 100) / 14; | ||
1496 | if (r > 100) | ||
1497 | r = 100; | ||
1498 | return r; | ||
1499 | } | ||
1500 | |||
1501 | u8 zd_rx_strength_percent(u8 rssi) | ||
1502 | { | ||
1503 | int r = (rssi*100) / 30; | ||
1504 | if (r > 100) | ||
1505 | r = 100; | ||
1506 | return (u8) r; | ||
1507 | } | ||
1508 | |||
1509 | u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status) | ||
1510 | { | ||
1511 | static const u16 ofdm_rates[] = { | ||
1512 | [ZD_OFDM_RATE_6M] = 60, | ||
1513 | [ZD_OFDM_RATE_9M] = 90, | ||
1514 | [ZD_OFDM_RATE_12M] = 120, | ||
1515 | [ZD_OFDM_RATE_18M] = 180, | ||
1516 | [ZD_OFDM_RATE_24M] = 240, | ||
1517 | [ZD_OFDM_RATE_36M] = 360, | ||
1518 | [ZD_OFDM_RATE_48M] = 480, | ||
1519 | [ZD_OFDM_RATE_54M] = 540, | ||
1520 | }; | ||
1521 | u16 rate; | ||
1522 | if (status->frame_status & ZD_RX_OFDM) { | ||
1523 | u8 ofdm_rate = zd_ofdm_plcp_header_rate(rx_frame); | ||
1524 | rate = ofdm_rates[ofdm_rate & 0xf]; | ||
1525 | } else { | ||
1526 | u8 cck_rate = zd_cck_plcp_header_rate(rx_frame); | ||
1527 | switch (cck_rate) { | ||
1528 | case ZD_CCK_SIGNAL_1M: | ||
1529 | rate = 10; | ||
1530 | break; | ||
1531 | case ZD_CCK_SIGNAL_2M: | ||
1532 | rate = 20; | ||
1533 | break; | ||
1534 | case ZD_CCK_SIGNAL_5M5: | ||
1535 | rate = 55; | ||
1536 | break; | ||
1537 | case ZD_CCK_SIGNAL_11M: | ||
1538 | rate = 110; | ||
1539 | break; | ||
1540 | default: | ||
1541 | rate = 0; | ||
1542 | } | ||
1543 | } | ||
1544 | |||
1545 | return rate; | ||
1546 | } | ||
1547 | |||
1548 | int zd_chip_switch_radio_on(struct zd_chip *chip) | ||
1549 | { | ||
1550 | int r; | ||
1551 | |||
1552 | mutex_lock(&chip->mutex); | ||
1553 | r = zd_switch_radio_on(&chip->rf); | ||
1554 | mutex_unlock(&chip->mutex); | ||
1555 | return r; | ||
1556 | } | ||
1557 | |||
1558 | int zd_chip_switch_radio_off(struct zd_chip *chip) | ||
1559 | { | ||
1560 | int r; | ||
1561 | |||
1562 | mutex_lock(&chip->mutex); | ||
1563 | r = zd_switch_radio_off(&chip->rf); | ||
1564 | mutex_unlock(&chip->mutex); | ||
1565 | return r; | ||
1566 | } | ||
1567 | |||
1568 | int zd_chip_enable_int(struct zd_chip *chip) | ||
1569 | { | ||
1570 | int r; | ||
1571 | |||
1572 | mutex_lock(&chip->mutex); | ||
1573 | r = zd_usb_enable_int(&chip->usb); | ||
1574 | mutex_unlock(&chip->mutex); | ||
1575 | return r; | ||
1576 | } | ||
1577 | |||
1578 | void zd_chip_disable_int(struct zd_chip *chip) | ||
1579 | { | ||
1580 | mutex_lock(&chip->mutex); | ||
1581 | zd_usb_disable_int(&chip->usb); | ||
1582 | mutex_unlock(&chip->mutex); | ||
1583 | } | ||
1584 | |||
1585 | int zd_chip_enable_rx(struct zd_chip *chip) | ||
1586 | { | ||
1587 | int r; | ||
1588 | |||
1589 | mutex_lock(&chip->mutex); | ||
1590 | r = zd_usb_enable_rx(&chip->usb); | ||
1591 | mutex_unlock(&chip->mutex); | ||
1592 | return r; | ||
1593 | } | ||
1594 | |||
1595 | void zd_chip_disable_rx(struct zd_chip *chip) | ||
1596 | { | ||
1597 | mutex_lock(&chip->mutex); | ||
1598 | zd_usb_disable_rx(&chip->usb); | ||
1599 | mutex_unlock(&chip->mutex); | ||
1600 | } | ||
1601 | |||
1602 | int zd_rfwritev_locked(struct zd_chip *chip, | ||
1603 | const u32* values, unsigned int count, u8 bits) | ||
1604 | { | ||
1605 | int r; | ||
1606 | unsigned int i; | ||
1607 | |||
1608 | for (i = 0; i < count; i++) { | ||
1609 | r = zd_rfwrite_locked(chip, values[i], bits); | ||
1610 | if (r) | ||
1611 | return r; | ||
1612 | } | ||
1613 | |||
1614 | return 0; | ||
1615 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h new file mode 100644 index 000000000000..805121093ab5 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_chip.h | |||
@@ -0,0 +1,825 @@ | |||
1 | /* zd_chip.h | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef _ZD_CHIP_H | ||
19 | #define _ZD_CHIP_H | ||
20 | |||
21 | #include "zd_types.h" | ||
22 | #include "zd_rf.h" | ||
23 | #include "zd_usb.h" | ||
24 | |||
25 | /* Header for the Media Access Controller (MAC) and the Baseband Processor | ||
26 | * (BBP). It appears that the ZD1211 wraps the old ZD1205 with USB glue and | ||
27 | * adds a processor for handling the USB protocol. | ||
28 | */ | ||
29 | |||
30 | /* 8-bit hardware registers */ | ||
31 | #define CR0 CTL_REG(0x0000) | ||
32 | #define CR1 CTL_REG(0x0004) | ||
33 | #define CR2 CTL_REG(0x0008) | ||
34 | #define CR3 CTL_REG(0x000C) | ||
35 | |||
36 | #define CR5 CTL_REG(0x0010) | ||
37 | /* bit 5: if set short preamble used | ||
38 | * bit 6: filter band - Japan channel 14 on, else off | ||
39 | */ | ||
40 | #define CR6 CTL_REG(0x0014) | ||
41 | #define CR7 CTL_REG(0x0018) | ||
42 | #define CR8 CTL_REG(0x001C) | ||
43 | |||
44 | #define CR4 CTL_REG(0x0020) | ||
45 | |||
46 | #define CR9 CTL_REG(0x0024) | ||
47 | /* bit 2: antenna switch (together with CR10) */ | ||
48 | #define CR10 CTL_REG(0x0028) | ||
49 | /* bit 1: antenna switch (together with CR9) | ||
50 | * RF2959 controls with CR11 radion on and off | ||
51 | */ | ||
52 | #define CR11 CTL_REG(0x002C) | ||
53 | /* bit 6: TX power control for OFDM | ||
54 | * RF2959 controls with CR10 radio on and off | ||
55 | */ | ||
56 | #define CR12 CTL_REG(0x0030) | ||
57 | #define CR13 CTL_REG(0x0034) | ||
58 | #define CR14 CTL_REG(0x0038) | ||
59 | #define CR15 CTL_REG(0x003C) | ||
60 | #define CR16 CTL_REG(0x0040) | ||
61 | #define CR17 CTL_REG(0x0044) | ||
62 | #define CR18 CTL_REG(0x0048) | ||
63 | #define CR19 CTL_REG(0x004C) | ||
64 | #define CR20 CTL_REG(0x0050) | ||
65 | #define CR21 CTL_REG(0x0054) | ||
66 | #define CR22 CTL_REG(0x0058) | ||
67 | #define CR23 CTL_REG(0x005C) | ||
68 | #define CR24 CTL_REG(0x0060) /* CCA threshold */ | ||
69 | #define CR25 CTL_REG(0x0064) | ||
70 | #define CR26 CTL_REG(0x0068) | ||
71 | #define CR27 CTL_REG(0x006C) | ||
72 | #define CR28 CTL_REG(0x0070) | ||
73 | #define CR29 CTL_REG(0x0074) | ||
74 | #define CR30 CTL_REG(0x0078) | ||
75 | #define CR31 CTL_REG(0x007C) /* TX power control for RF in CCK mode */ | ||
76 | #define CR32 CTL_REG(0x0080) | ||
77 | #define CR33 CTL_REG(0x0084) | ||
78 | #define CR34 CTL_REG(0x0088) | ||
79 | #define CR35 CTL_REG(0x008C) | ||
80 | #define CR36 CTL_REG(0x0090) | ||
81 | #define CR37 CTL_REG(0x0094) | ||
82 | #define CR38 CTL_REG(0x0098) | ||
83 | #define CR39 CTL_REG(0x009C) | ||
84 | #define CR40 CTL_REG(0x00A0) | ||
85 | #define CR41 CTL_REG(0x00A4) | ||
86 | #define CR42 CTL_REG(0x00A8) | ||
87 | #define CR43 CTL_REG(0x00AC) | ||
88 | #define CR44 CTL_REG(0x00B0) | ||
89 | #define CR45 CTL_REG(0x00B4) | ||
90 | #define CR46 CTL_REG(0x00B8) | ||
91 | #define CR47 CTL_REG(0x00BC) /* CCK baseband gain | ||
92 | * (patch value might be in EEPROM) | ||
93 | */ | ||
94 | #define CR48 CTL_REG(0x00C0) | ||
95 | #define CR49 CTL_REG(0x00C4) | ||
96 | #define CR50 CTL_REG(0x00C8) | ||
97 | #define CR51 CTL_REG(0x00CC) /* TX power control for RF in 6-36M modes */ | ||
98 | #define CR52 CTL_REG(0x00D0) /* TX power control for RF in 48M mode */ | ||
99 | #define CR53 CTL_REG(0x00D4) /* TX power control for RF in 54M mode */ | ||
100 | #define CR54 CTL_REG(0x00D8) | ||
101 | #define CR55 CTL_REG(0x00DC) | ||
102 | #define CR56 CTL_REG(0x00E0) | ||
103 | #define CR57 CTL_REG(0x00E4) | ||
104 | #define CR58 CTL_REG(0x00E8) | ||
105 | #define CR59 CTL_REG(0x00EC) | ||
106 | #define CR60 CTL_REG(0x00F0) | ||
107 | #define CR61 CTL_REG(0x00F4) | ||
108 | #define CR62 CTL_REG(0x00F8) | ||
109 | #define CR63 CTL_REG(0x00FC) | ||
110 | #define CR64 CTL_REG(0x0100) | ||
111 | #define CR65 CTL_REG(0x0104) /* OFDM 54M calibration */ | ||
112 | #define CR66 CTL_REG(0x0108) /* OFDM 48M calibration */ | ||
113 | #define CR67 CTL_REG(0x010C) /* OFDM 36M calibration */ | ||
114 | #define CR68 CTL_REG(0x0110) /* CCK calibration */ | ||
115 | #define CR69 CTL_REG(0x0114) | ||
116 | #define CR70 CTL_REG(0x0118) | ||
117 | #define CR71 CTL_REG(0x011C) | ||
118 | #define CR72 CTL_REG(0x0120) | ||
119 | #define CR73 CTL_REG(0x0124) | ||
120 | #define CR74 CTL_REG(0x0128) | ||
121 | #define CR75 CTL_REG(0x012C) | ||
122 | #define CR76 CTL_REG(0x0130) | ||
123 | #define CR77 CTL_REG(0x0134) | ||
124 | #define CR78 CTL_REG(0x0138) | ||
125 | #define CR79 CTL_REG(0x013C) | ||
126 | #define CR80 CTL_REG(0x0140) | ||
127 | #define CR81 CTL_REG(0x0144) | ||
128 | #define CR82 CTL_REG(0x0148) | ||
129 | #define CR83 CTL_REG(0x014C) | ||
130 | #define CR84 CTL_REG(0x0150) | ||
131 | #define CR85 CTL_REG(0x0154) | ||
132 | #define CR86 CTL_REG(0x0158) | ||
133 | #define CR87 CTL_REG(0x015C) | ||
134 | #define CR88 CTL_REG(0x0160) | ||
135 | #define CR89 CTL_REG(0x0164) | ||
136 | #define CR90 CTL_REG(0x0168) | ||
137 | #define CR91 CTL_REG(0x016C) | ||
138 | #define CR92 CTL_REG(0x0170) | ||
139 | #define CR93 CTL_REG(0x0174) | ||
140 | #define CR94 CTL_REG(0x0178) | ||
141 | #define CR95 CTL_REG(0x017C) | ||
142 | #define CR96 CTL_REG(0x0180) | ||
143 | #define CR97 CTL_REG(0x0184) | ||
144 | #define CR98 CTL_REG(0x0188) | ||
145 | #define CR99 CTL_REG(0x018C) | ||
146 | #define CR100 CTL_REG(0x0190) | ||
147 | #define CR101 CTL_REG(0x0194) | ||
148 | #define CR102 CTL_REG(0x0198) | ||
149 | #define CR103 CTL_REG(0x019C) | ||
150 | #define CR104 CTL_REG(0x01A0) | ||
151 | #define CR105 CTL_REG(0x01A4) | ||
152 | #define CR106 CTL_REG(0x01A8) | ||
153 | #define CR107 CTL_REG(0x01AC) | ||
154 | #define CR108 CTL_REG(0x01B0) | ||
155 | #define CR109 CTL_REG(0x01B4) | ||
156 | #define CR110 CTL_REG(0x01B8) | ||
157 | #define CR111 CTL_REG(0x01BC) | ||
158 | #define CR112 CTL_REG(0x01C0) | ||
159 | #define CR113 CTL_REG(0x01C4) | ||
160 | #define CR114 CTL_REG(0x01C8) | ||
161 | #define CR115 CTL_REG(0x01CC) | ||
162 | #define CR116 CTL_REG(0x01D0) | ||
163 | #define CR117 CTL_REG(0x01D4) | ||
164 | #define CR118 CTL_REG(0x01D8) | ||
165 | #define CR119 CTL_REG(0x01DC) | ||
166 | #define CR120 CTL_REG(0x01E0) | ||
167 | #define CR121 CTL_REG(0x01E4) | ||
168 | #define CR122 CTL_REG(0x01E8) | ||
169 | #define CR123 CTL_REG(0x01EC) | ||
170 | #define CR124 CTL_REG(0x01F0) | ||
171 | #define CR125 CTL_REG(0x01F4) | ||
172 | #define CR126 CTL_REG(0x01F8) | ||
173 | #define CR127 CTL_REG(0x01FC) | ||
174 | #define CR128 CTL_REG(0x0200) | ||
175 | #define CR129 CTL_REG(0x0204) | ||
176 | #define CR130 CTL_REG(0x0208) | ||
177 | #define CR131 CTL_REG(0x020C) | ||
178 | #define CR132 CTL_REG(0x0210) | ||
179 | #define CR133 CTL_REG(0x0214) | ||
180 | #define CR134 CTL_REG(0x0218) | ||
181 | #define CR135 CTL_REG(0x021C) | ||
182 | #define CR136 CTL_REG(0x0220) | ||
183 | #define CR137 CTL_REG(0x0224) | ||
184 | #define CR138 CTL_REG(0x0228) | ||
185 | #define CR139 CTL_REG(0x022C) | ||
186 | #define CR140 CTL_REG(0x0230) | ||
187 | #define CR141 CTL_REG(0x0234) | ||
188 | #define CR142 CTL_REG(0x0238) | ||
189 | #define CR143 CTL_REG(0x023C) | ||
190 | #define CR144 CTL_REG(0x0240) | ||
191 | #define CR145 CTL_REG(0x0244) | ||
192 | #define CR146 CTL_REG(0x0248) | ||
193 | #define CR147 CTL_REG(0x024C) | ||
194 | #define CR148 CTL_REG(0x0250) | ||
195 | #define CR149 CTL_REG(0x0254) | ||
196 | #define CR150 CTL_REG(0x0258) | ||
197 | #define CR151 CTL_REG(0x025C) | ||
198 | #define CR152 CTL_REG(0x0260) | ||
199 | #define CR153 CTL_REG(0x0264) | ||
200 | #define CR154 CTL_REG(0x0268) | ||
201 | #define CR155 CTL_REG(0x026C) | ||
202 | #define CR156 CTL_REG(0x0270) | ||
203 | #define CR157 CTL_REG(0x0274) | ||
204 | #define CR158 CTL_REG(0x0278) | ||
205 | #define CR159 CTL_REG(0x027C) | ||
206 | #define CR160 CTL_REG(0x0280) | ||
207 | #define CR161 CTL_REG(0x0284) | ||
208 | #define CR162 CTL_REG(0x0288) | ||
209 | #define CR163 CTL_REG(0x028C) | ||
210 | #define CR164 CTL_REG(0x0290) | ||
211 | #define CR165 CTL_REG(0x0294) | ||
212 | #define CR166 CTL_REG(0x0298) | ||
213 | #define CR167 CTL_REG(0x029C) | ||
214 | #define CR168 CTL_REG(0x02A0) | ||
215 | #define CR169 CTL_REG(0x02A4) | ||
216 | #define CR170 CTL_REG(0x02A8) | ||
217 | #define CR171 CTL_REG(0x02AC) | ||
218 | #define CR172 CTL_REG(0x02B0) | ||
219 | #define CR173 CTL_REG(0x02B4) | ||
220 | #define CR174 CTL_REG(0x02B8) | ||
221 | #define CR175 CTL_REG(0x02BC) | ||
222 | #define CR176 CTL_REG(0x02C0) | ||
223 | #define CR177 CTL_REG(0x02C4) | ||
224 | #define CR178 CTL_REG(0x02C8) | ||
225 | #define CR179 CTL_REG(0x02CC) | ||
226 | #define CR180 CTL_REG(0x02D0) | ||
227 | #define CR181 CTL_REG(0x02D4) | ||
228 | #define CR182 CTL_REG(0x02D8) | ||
229 | #define CR183 CTL_REG(0x02DC) | ||
230 | #define CR184 CTL_REG(0x02E0) | ||
231 | #define CR185 CTL_REG(0x02E4) | ||
232 | #define CR186 CTL_REG(0x02E8) | ||
233 | #define CR187 CTL_REG(0x02EC) | ||
234 | #define CR188 CTL_REG(0x02F0) | ||
235 | #define CR189 CTL_REG(0x02F4) | ||
236 | #define CR190 CTL_REG(0x02F8) | ||
237 | #define CR191 CTL_REG(0x02FC) | ||
238 | #define CR192 CTL_REG(0x0300) | ||
239 | #define CR193 CTL_REG(0x0304) | ||
240 | #define CR194 CTL_REG(0x0308) | ||
241 | #define CR195 CTL_REG(0x030C) | ||
242 | #define CR196 CTL_REG(0x0310) | ||
243 | #define CR197 CTL_REG(0x0314) | ||
244 | #define CR198 CTL_REG(0x0318) | ||
245 | #define CR199 CTL_REG(0x031C) | ||
246 | #define CR200 CTL_REG(0x0320) | ||
247 | #define CR201 CTL_REG(0x0324) | ||
248 | #define CR202 CTL_REG(0x0328) | ||
249 | #define CR203 CTL_REG(0x032C) /* I2C bus template value & flash control */ | ||
250 | #define CR204 CTL_REG(0x0330) | ||
251 | #define CR205 CTL_REG(0x0334) | ||
252 | #define CR206 CTL_REG(0x0338) | ||
253 | #define CR207 CTL_REG(0x033C) | ||
254 | #define CR208 CTL_REG(0x0340) | ||
255 | #define CR209 CTL_REG(0x0344) | ||
256 | #define CR210 CTL_REG(0x0348) | ||
257 | #define CR211 CTL_REG(0x034C) | ||
258 | #define CR212 CTL_REG(0x0350) | ||
259 | #define CR213 CTL_REG(0x0354) | ||
260 | #define CR214 CTL_REG(0x0358) | ||
261 | #define CR215 CTL_REG(0x035C) | ||
262 | #define CR216 CTL_REG(0x0360) | ||
263 | #define CR217 CTL_REG(0x0364) | ||
264 | #define CR218 CTL_REG(0x0368) | ||
265 | #define CR219 CTL_REG(0x036C) | ||
266 | #define CR220 CTL_REG(0x0370) | ||
267 | #define CR221 CTL_REG(0x0374) | ||
268 | #define CR222 CTL_REG(0x0378) | ||
269 | #define CR223 CTL_REG(0x037C) | ||
270 | #define CR224 CTL_REG(0x0380) | ||
271 | #define CR225 CTL_REG(0x0384) | ||
272 | #define CR226 CTL_REG(0x0388) | ||
273 | #define CR227 CTL_REG(0x038C) | ||
274 | #define CR228 CTL_REG(0x0390) | ||
275 | #define CR229 CTL_REG(0x0394) | ||
276 | #define CR230 CTL_REG(0x0398) | ||
277 | #define CR231 CTL_REG(0x039C) | ||
278 | #define CR232 CTL_REG(0x03A0) | ||
279 | #define CR233 CTL_REG(0x03A4) | ||
280 | #define CR234 CTL_REG(0x03A8) | ||
281 | #define CR235 CTL_REG(0x03AC) | ||
282 | #define CR236 CTL_REG(0x03B0) | ||
283 | |||
284 | #define CR240 CTL_REG(0x03C0) | ||
285 | /* bit 7: host-controlled RF register writes | ||
286 | * CR241-CR245: for hardware controlled writing of RF bits, not needed for | ||
287 | * USB | ||
288 | */ | ||
289 | #define CR241 CTL_REG(0x03C4) | ||
290 | #define CR242 CTL_REG(0x03C8) | ||
291 | #define CR243 CTL_REG(0x03CC) | ||
292 | #define CR244 CTL_REG(0x03D0) | ||
293 | #define CR245 CTL_REG(0x03D4) | ||
294 | |||
295 | #define CR251 CTL_REG(0x03EC) /* only used for activation and deactivation of | ||
296 | * Airoha RFs AL2230 and AL7230B | ||
297 | */ | ||
298 | #define CR252 CTL_REG(0x03F0) | ||
299 | #define CR253 CTL_REG(0x03F4) | ||
300 | #define CR254 CTL_REG(0x03F8) | ||
301 | #define CR255 CTL_REG(0x03FC) | ||
302 | |||
303 | #define CR_MAX_PHY_REG 255 | ||
304 | |||
305 | /* Taken from the ZYDAS driver, not all of them are relevant for the ZSD1211 | ||
306 | * driver. | ||
307 | */ | ||
308 | |||
309 | #define CR_RF_IF_CLK CTL_REG(0x0400) | ||
310 | #define CR_RF_IF_DATA CTL_REG(0x0404) | ||
311 | #define CR_PE1_PE2 CTL_REG(0x0408) | ||
312 | #define CR_PE2_DLY CTL_REG(0x040C) | ||
313 | #define CR_LE1 CTL_REG(0x0410) | ||
314 | #define CR_LE2 CTL_REG(0x0414) | ||
315 | /* Seems to enable/disable GPI (General Purpose IO?) */ | ||
316 | #define CR_GPI_EN CTL_REG(0x0418) | ||
317 | #define CR_RADIO_PD CTL_REG(0x042C) | ||
318 | #define CR_RF2948_PD CTL_REG(0x042C) | ||
319 | #define CR_ENABLE_PS_MANUAL_AGC CTL_REG(0x043C) | ||
320 | #define CR_CONFIG_PHILIPS CTL_REG(0x0440) | ||
321 | #define CR_SA2400_SER_AP CTL_REG(0x0444) | ||
322 | #define CR_I2C_WRITE CTL_REG(0x0444) | ||
323 | #define CR_SA2400_SER_RP CTL_REG(0x0448) | ||
324 | #define CR_RADIO_PE CTL_REG(0x0458) | ||
325 | #define CR_RST_BUS_MASTER CTL_REG(0x045C) | ||
326 | #define CR_RFCFG CTL_REG(0x0464) | ||
327 | #define CR_HSTSCHG CTL_REG(0x046C) | ||
328 | #define CR_PHY_ON CTL_REG(0x0474) | ||
329 | #define CR_RX_DELAY CTL_REG(0x0478) | ||
330 | #define CR_RX_PE_DELAY CTL_REG(0x047C) | ||
331 | #define CR_GPIO_1 CTL_REG(0x0490) | ||
332 | #define CR_GPIO_2 CTL_REG(0x0494) | ||
333 | #define CR_EncryBufMux CTL_REG(0x04A8) | ||
334 | #define CR_PS_CTRL CTL_REG(0x0500) | ||
335 | #define CR_ADDA_PWR_DWN CTL_REG(0x0504) | ||
336 | #define CR_ADDA_MBIAS_WARMTIME CTL_REG(0x0508) | ||
337 | #define CR_MAC_PS_STATE CTL_REG(0x050C) | ||
338 | |||
339 | #define CR_INTERRUPT CTL_REG(0x0510) | ||
340 | #define INT_TX_COMPLETE 0x00000001 | ||
341 | #define INT_RX_COMPLETE 0x00000002 | ||
342 | #define INT_RETRY_FAIL 0x00000004 | ||
343 | #define INT_WAKEUP 0x00000008 | ||
344 | #define INT_DTIM_NOTIFY 0x00000020 | ||
345 | #define INT_CFG_NEXT_BCN 0x00000040 | ||
346 | #define INT_BUS_ABORT 0x00000080 | ||
347 | #define INT_TX_FIFO_READY 0x00000100 | ||
348 | #define INT_UART 0x00000200 | ||
349 | #define INT_TX_COMPLETE_EN 0x00010000 | ||
350 | #define INT_RX_COMPLETE_EN 0x00020000 | ||
351 | #define INT_RETRY_FAIL_EN 0x00040000 | ||
352 | #define INT_WAKEUP_EN 0x00080000 | ||
353 | #define INT_DTIM_NOTIFY_EN 0x00200000 | ||
354 | #define INT_CFG_NEXT_BCN_EN 0x00400000 | ||
355 | #define INT_BUS_ABORT_EN 0x00800000 | ||
356 | #define INT_TX_FIFO_READY_EN 0x01000000 | ||
357 | #define INT_UART_EN 0x02000000 | ||
358 | |||
359 | #define CR_TSF_LOW_PART CTL_REG(0x0514) | ||
360 | #define CR_TSF_HIGH_PART CTL_REG(0x0518) | ||
361 | |||
362 | /* Following three values are in time units (1024us) | ||
363 | * Following condition must be met: | ||
364 | * atim < tbtt < bcn | ||
365 | */ | ||
366 | #define CR_ATIM_WND_PERIOD CTL_REG(0x051C) | ||
367 | #define CR_BCN_INTERVAL CTL_REG(0x0520) | ||
368 | #define CR_PRE_TBTT CTL_REG(0x0524) | ||
369 | /* in units of TU(1024us) */ | ||
370 | |||
371 | /* for UART support */ | ||
372 | #define CR_UART_RBR_THR_DLL CTL_REG(0x0540) | ||
373 | #define CR_UART_DLM_IER CTL_REG(0x0544) | ||
374 | #define CR_UART_IIR_FCR CTL_REG(0x0548) | ||
375 | #define CR_UART_LCR CTL_REG(0x054c) | ||
376 | #define CR_UART_MCR CTL_REG(0x0550) | ||
377 | #define CR_UART_LSR CTL_REG(0x0554) | ||
378 | #define CR_UART_MSR CTL_REG(0x0558) | ||
379 | #define CR_UART_ECR CTL_REG(0x055c) | ||
380 | #define CR_UART_STATUS CTL_REG(0x0560) | ||
381 | |||
382 | #define CR_PCI_TX_ADDR_P1 CTL_REG(0x0600) | ||
383 | #define CR_PCI_TX_AddR_P2 CTL_REG(0x0604) | ||
384 | #define CR_PCI_RX_AddR_P1 CTL_REG(0x0608) | ||
385 | #define CR_PCI_RX_AddR_P2 CTL_REG(0x060C) | ||
386 | |||
387 | /* must be overwritten if custom MAC address will be used */ | ||
388 | #define CR_MAC_ADDR_P1 CTL_REG(0x0610) | ||
389 | #define CR_MAC_ADDR_P2 CTL_REG(0x0614) | ||
390 | #define CR_BSSID_P1 CTL_REG(0x0618) | ||
391 | #define CR_BSSID_P2 CTL_REG(0x061C) | ||
392 | #define CR_BCN_PLCP_CFG CTL_REG(0x0620) | ||
393 | #define CR_GROUP_HASH_P1 CTL_REG(0x0624) | ||
394 | #define CR_GROUP_HASH_P2 CTL_REG(0x0628) | ||
395 | #define CR_RX_TIMEOUT CTL_REG(0x062C) | ||
396 | |||
397 | /* Basic rates supported by the BSS. When producing ACK or CTS messages, the | ||
398 | * device will use a rate in this table that is less than or equal to the rate | ||
399 | * of the incoming frame which prompted the response */ | ||
400 | #define CR_BASIC_RATE_TBL CTL_REG(0x0630) | ||
401 | #define CR_RATE_1M 0x0001 /* 802.11b */ | ||
402 | #define CR_RATE_2M 0x0002 /* 802.11b */ | ||
403 | #define CR_RATE_5_5M 0x0004 /* 802.11b */ | ||
404 | #define CR_RATE_11M 0x0008 /* 802.11b */ | ||
405 | #define CR_RATE_6M 0x0100 /* 802.11g */ | ||
406 | #define CR_RATE_9M 0x0200 /* 802.11g */ | ||
407 | #define CR_RATE_12M 0x0400 /* 802.11g */ | ||
408 | #define CR_RATE_18M 0x0800 /* 802.11g */ | ||
409 | #define CR_RATE_24M 0x1000 /* 802.11g */ | ||
410 | #define CR_RATE_36M 0x2000 /* 802.11g */ | ||
411 | #define CR_RATE_48M 0x4000 /* 802.11g */ | ||
412 | #define CR_RATE_54M 0x8000 /* 802.11g */ | ||
413 | #define CR_RATES_80211G 0xff00 | ||
414 | #define CR_RATES_80211B 0x000f | ||
415 | |||
416 | /* Mandatory rates required in the BSS. When producing ACK or CTS messages, if | ||
417 | * the device could not find an appropriate rate in CR_BASIC_RATE_TBL, it will | ||
418 | * look for a rate in this table that is less than or equal to the rate of | ||
419 | * the incoming frame. */ | ||
420 | #define CR_MANDATORY_RATE_TBL CTL_REG(0x0634) | ||
421 | #define CR_RTS_CTS_RATE CTL_REG(0x0638) | ||
422 | |||
423 | #define CR_WEP_PROTECT CTL_REG(0x063C) | ||
424 | #define CR_RX_THRESHOLD CTL_REG(0x0640) | ||
425 | |||
426 | /* register for controlling the LEDS */ | ||
427 | #define CR_LED CTL_REG(0x0644) | ||
428 | /* masks for controlling LEDs */ | ||
429 | #define LED1 0x0100 | ||
430 | #define LED2 0x0200 | ||
431 | |||
432 | /* Seems to indicate that the configuration is over. | ||
433 | */ | ||
434 | #define CR_AFTER_PNP CTL_REG(0x0648) | ||
435 | #define CR_ACK_TIME_80211 CTL_REG(0x0658) | ||
436 | |||
437 | #define CR_RX_OFFSET CTL_REG(0x065c) | ||
438 | |||
439 | #define CR_PHY_DELAY CTL_REG(0x066C) | ||
440 | #define CR_BCN_FIFO CTL_REG(0x0670) | ||
441 | #define CR_SNIFFER_ON CTL_REG(0x0674) | ||
442 | |||
443 | #define CR_ENCRYPTION_TYPE CTL_REG(0x0678) | ||
444 | #define NO_WEP 0 | ||
445 | #define WEP64 1 | ||
446 | #define WEP128 5 | ||
447 | #define WEP256 6 | ||
448 | #define ENC_SNIFFER 8 | ||
449 | |||
450 | #define CR_ZD1211_RETRY_MAX CTL_REG(0x067C) | ||
451 | |||
452 | #define CR_REG1 CTL_REG(0x0680) | ||
453 | /* Setting the bit UNLOCK_PHY_REGS disallows the write access to physical | ||
454 | * registers, so one could argue it is a LOCK bit. But calling it | ||
455 | * LOCK_PHY_REGS makes it confusing. | ||
456 | */ | ||
457 | #define UNLOCK_PHY_REGS 0x0080 | ||
458 | |||
459 | #define CR_DEVICE_STATE CTL_REG(0x0684) | ||
460 | #define CR_UNDERRUN_CNT CTL_REG(0x0688) | ||
461 | |||
462 | #define CR_RX_FILTER CTL_REG(0x068c) | ||
463 | #define RX_FILTER_ASSOC_RESPONSE 0x0002 | ||
464 | #define RX_FILTER_PROBE_RESPONSE 0x0020 | ||
465 | #define RX_FILTER_BEACON 0x0100 | ||
466 | #define RX_FILTER_AUTH 0x0800 | ||
467 | /* Sniff modus sets filter to 0xfffff */ | ||
468 | |||
469 | #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) | ||
470 | #define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694) | ||
471 | #define CR_IFS_VALUE CTL_REG(0x0698) | ||
472 | #define CR_RX_TIME_OUT CTL_REG(0x069C) | ||
473 | #define CR_TOTAL_RX_FRM CTL_REG(0x06A0) | ||
474 | #define CR_CRC32_CNT CTL_REG(0x06A4) | ||
475 | #define CR_CRC16_CNT CTL_REG(0x06A8) | ||
476 | #define CR_DECRYPTION_ERR_UNI CTL_REG(0x06AC) | ||
477 | #define CR_RX_FIFO_OVERRUN CTL_REG(0x06B0) | ||
478 | |||
479 | #define CR_DECRYPTION_ERR_MUL CTL_REG(0x06BC) | ||
480 | |||
481 | #define CR_NAV_CNT CTL_REG(0x06C4) | ||
482 | #define CR_NAV_CCA CTL_REG(0x06C8) | ||
483 | #define CR_RETRY_CNT CTL_REG(0x06CC) | ||
484 | |||
485 | #define CR_READ_TCB_ADDR CTL_REG(0x06E8) | ||
486 | #define CR_READ_RFD_ADDR CTL_REG(0x06EC) | ||
487 | #define CR_CWMIN_CWMAX CTL_REG(0x06F0) | ||
488 | #define CR_TOTAL_TX_FRM CTL_REG(0x06F4) | ||
489 | |||
490 | /* CAM: Continuous Access Mode (power management) */ | ||
491 | #define CR_CAM_MODE CTL_REG(0x0700) | ||
492 | #define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704) | ||
493 | #define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708) | ||
494 | #define CR_CAM_ADDRESS CTL_REG(0x070C) | ||
495 | #define CR_CAM_DATA CTL_REG(0x0710) | ||
496 | |||
497 | #define CR_ROMDIR CTL_REG(0x0714) | ||
498 | |||
499 | #define CR_DECRY_ERR_FLG_LOW CTL_REG(0x0714) | ||
500 | #define CR_DECRY_ERR_FLG_HIGH CTL_REG(0x0718) | ||
501 | |||
502 | #define CR_WEPKEY0 CTL_REG(0x0720) | ||
503 | #define CR_WEPKEY1 CTL_REG(0x0724) | ||
504 | #define CR_WEPKEY2 CTL_REG(0x0728) | ||
505 | #define CR_WEPKEY3 CTL_REG(0x072C) | ||
506 | #define CR_WEPKEY4 CTL_REG(0x0730) | ||
507 | #define CR_WEPKEY5 CTL_REG(0x0734) | ||
508 | #define CR_WEPKEY6 CTL_REG(0x0738) | ||
509 | #define CR_WEPKEY7 CTL_REG(0x073C) | ||
510 | #define CR_WEPKEY8 CTL_REG(0x0740) | ||
511 | #define CR_WEPKEY9 CTL_REG(0x0744) | ||
512 | #define CR_WEPKEY10 CTL_REG(0x0748) | ||
513 | #define CR_WEPKEY11 CTL_REG(0x074C) | ||
514 | #define CR_WEPKEY12 CTL_REG(0x0750) | ||
515 | #define CR_WEPKEY13 CTL_REG(0x0754) | ||
516 | #define CR_WEPKEY14 CTL_REG(0x0758) | ||
517 | #define CR_WEPKEY15 CTL_REG(0x075c) | ||
518 | #define CR_TKIP_MODE CTL_REG(0x0760) | ||
519 | |||
520 | #define CR_EEPROM_PROTECT0 CTL_REG(0x0758) | ||
521 | #define CR_EEPROM_PROTECT1 CTL_REG(0x075C) | ||
522 | |||
523 | #define CR_DBG_FIFO_RD CTL_REG(0x0800) | ||
524 | #define CR_DBG_SELECT CTL_REG(0x0804) | ||
525 | #define CR_FIFO_Length CTL_REG(0x0808) | ||
526 | |||
527 | |||
528 | #define CR_RSSI_MGC CTL_REG(0x0810) | ||
529 | |||
530 | #define CR_PON CTL_REG(0x0818) | ||
531 | #define CR_RX_ON CTL_REG(0x081C) | ||
532 | #define CR_TX_ON CTL_REG(0x0820) | ||
533 | #define CR_CHIP_EN CTL_REG(0x0824) | ||
534 | #define CR_LO_SW CTL_REG(0x0828) | ||
535 | #define CR_TXRX_SW CTL_REG(0x082C) | ||
536 | #define CR_S_MD CTL_REG(0x0830) | ||
537 | |||
538 | #define CR_USB_DEBUG_PORT CTL_REG(0x0888) | ||
539 | |||
540 | #define CR_ZD1211B_TX_PWR_CTL1 CTL_REG(0x0b00) | ||
541 | #define CR_ZD1211B_TX_PWR_CTL2 CTL_REG(0x0b04) | ||
542 | #define CR_ZD1211B_TX_PWR_CTL3 CTL_REG(0x0b08) | ||
543 | #define CR_ZD1211B_TX_PWR_CTL4 CTL_REG(0x0b0c) | ||
544 | #define CR_ZD1211B_AIFS_CTL1 CTL_REG(0x0b10) | ||
545 | #define CR_ZD1211B_AIFS_CTL2 CTL_REG(0x0b14) | ||
546 | #define CR_ZD1211B_TXOP CTL_REG(0x0b20) | ||
547 | #define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) | ||
548 | |||
549 | #define AP_RX_FILTER 0x0400feff | ||
550 | #define STA_RX_FILTER 0x0000ffff | ||
551 | |||
552 | #define CWIN_SIZE 0x007f043f | ||
553 | |||
554 | |||
555 | #define HWINT_ENABLED 0x004f0000 | ||
556 | #define HWINT_DISABLED 0 | ||
557 | |||
558 | #define E2P_PWR_INT_GUARD 8 | ||
559 | #define E2P_CHANNEL_COUNT 14 | ||
560 | |||
561 | /* If you compare this addresses with the ZYDAS orignal driver, please notify | ||
562 | * that we use word mapping for the EEPROM. | ||
563 | */ | ||
564 | |||
565 | /* | ||
566 | * Upper 16 bit contains the regulatory domain. | ||
567 | */ | ||
568 | #define E2P_SUBID E2P_REG(0x00) | ||
569 | #define E2P_POD E2P_REG(0x02) | ||
570 | #define E2P_MAC_ADDR_P1 E2P_REG(0x04) | ||
571 | #define E2P_MAC_ADDR_P2 E2P_REG(0x06) | ||
572 | #define E2P_PWR_CAL_VALUE1 E2P_REG(0x08) | ||
573 | #define E2P_PWR_CAL_VALUE2 E2P_REG(0x0a) | ||
574 | #define E2P_PWR_CAL_VALUE3 E2P_REG(0x0c) | ||
575 | #define E2P_PWR_CAL_VALUE4 E2P_REG(0x0e) | ||
576 | #define E2P_PWR_INT_VALUE1 E2P_REG(0x10) | ||
577 | #define E2P_PWR_INT_VALUE2 E2P_REG(0x12) | ||
578 | #define E2P_PWR_INT_VALUE3 E2P_REG(0x14) | ||
579 | #define E2P_PWR_INT_VALUE4 E2P_REG(0x16) | ||
580 | |||
581 | /* Contains a bit for each allowed channel. It gives for Europe (ETSI 0x30) | ||
582 | * also only 11 channels. */ | ||
583 | #define E2P_ALLOWED_CHANNEL E2P_REG(0x18) | ||
584 | |||
585 | #define E2P_PHY_REG E2P_REG(0x1a) | ||
586 | #define E2P_DEVICE_VER E2P_REG(0x20) | ||
587 | #define E2P_36M_CAL_VALUE1 E2P_REG(0x28) | ||
588 | #define E2P_36M_CAL_VALUE2 E2P_REG(0x2a) | ||
589 | #define E2P_36M_CAL_VALUE3 E2P_REG(0x2c) | ||
590 | #define E2P_36M_CAL_VALUE4 E2P_REG(0x2e) | ||
591 | #define E2P_11A_INT_VALUE1 E2P_REG(0x30) | ||
592 | #define E2P_11A_INT_VALUE2 E2P_REG(0x32) | ||
593 | #define E2P_11A_INT_VALUE3 E2P_REG(0x34) | ||
594 | #define E2P_11A_INT_VALUE4 E2P_REG(0x36) | ||
595 | #define E2P_48M_CAL_VALUE1 E2P_REG(0x38) | ||
596 | #define E2P_48M_CAL_VALUE2 E2P_REG(0x3a) | ||
597 | #define E2P_48M_CAL_VALUE3 E2P_REG(0x3c) | ||
598 | #define E2P_48M_CAL_VALUE4 E2P_REG(0x3e) | ||
599 | #define E2P_48M_INT_VALUE1 E2P_REG(0x40) | ||
600 | #define E2P_48M_INT_VALUE2 E2P_REG(0x42) | ||
601 | #define E2P_48M_INT_VALUE3 E2P_REG(0x44) | ||
602 | #define E2P_48M_INT_VALUE4 E2P_REG(0x46) | ||
603 | #define E2P_54M_CAL_VALUE1 E2P_REG(0x48) /* ??? */ | ||
604 | #define E2P_54M_CAL_VALUE2 E2P_REG(0x4a) | ||
605 | #define E2P_54M_CAL_VALUE3 E2P_REG(0x4c) | ||
606 | #define E2P_54M_CAL_VALUE4 E2P_REG(0x4e) | ||
607 | #define E2P_54M_INT_VALUE1 E2P_REG(0x50) | ||
608 | #define E2P_54M_INT_VALUE2 E2P_REG(0x52) | ||
609 | #define E2P_54M_INT_VALUE3 E2P_REG(0x54) | ||
610 | #define E2P_54M_INT_VALUE4 E2P_REG(0x56) | ||
611 | |||
612 | /* All 16 bit values */ | ||
613 | #define FW_FIRMWARE_VER FW_REG(0) | ||
614 | /* non-zero if USB high speed connection */ | ||
615 | #define FW_USB_SPEED FW_REG(1) | ||
616 | #define FW_FIX_TX_RATE FW_REG(2) | ||
617 | /* Seems to be able to control LEDs over the firmware */ | ||
618 | #define FW_LINK_STATUS FW_REG(3) | ||
619 | #define FW_SOFT_RESET FW_REG(4) | ||
620 | #define FW_FLASH_CHK FW_REG(5) | ||
621 | |||
622 | enum { | ||
623 | CR_BASE_OFFSET = 0x9000, | ||
624 | FW_START_OFFSET = 0xee00, | ||
625 | FW_BASE_ADDR_OFFSET = FW_START_OFFSET + 0x1d, | ||
626 | EEPROM_START_OFFSET = 0xf800, | ||
627 | EEPROM_SIZE = 0x800, /* words */ | ||
628 | LOAD_CODE_SIZE = 0xe, /* words */ | ||
629 | LOAD_VECT_SIZE = 0x10000 - 0xfff7, /* words */ | ||
630 | EEPROM_REGS_OFFSET = LOAD_CODE_SIZE + LOAD_VECT_SIZE, | ||
631 | E2P_BASE_OFFSET = EEPROM_START_OFFSET + | ||
632 | EEPROM_REGS_OFFSET, | ||
633 | }; | ||
634 | |||
635 | #define FW_REG_TABLE_ADDR USB_ADDR(FW_START_OFFSET + 0x1d) | ||
636 | |||
637 | enum { | ||
638 | /* indices for ofdm_cal_values */ | ||
639 | OFDM_36M_INDEX = 0, | ||
640 | OFDM_48M_INDEX = 1, | ||
641 | OFDM_54M_INDEX = 2, | ||
642 | }; | ||
643 | |||
644 | struct zd_chip { | ||
645 | struct zd_usb usb; | ||
646 | struct zd_rf rf; | ||
647 | struct mutex mutex; | ||
648 | u8 e2p_mac[ETH_ALEN]; | ||
649 | /* EepSetPoint in the vendor driver */ | ||
650 | u8 pwr_cal_values[E2P_CHANNEL_COUNT]; | ||
651 | /* integration values in the vendor driver */ | ||
652 | u8 pwr_int_values[E2P_CHANNEL_COUNT]; | ||
653 | /* SetPointOFDM in the vendor driver */ | ||
654 | u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT]; | ||
655 | u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, | ||
656 | is_zd1211b:1; | ||
657 | }; | ||
658 | |||
659 | static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb) | ||
660 | { | ||
661 | return container_of(usb, struct zd_chip, usb); | ||
662 | } | ||
663 | |||
664 | static inline struct zd_chip *zd_rf_to_chip(struct zd_rf *rf) | ||
665 | { | ||
666 | return container_of(rf, struct zd_chip, rf); | ||
667 | } | ||
668 | |||
669 | #define zd_chip_dev(chip) (&(chip)->usb.intf->dev) | ||
670 | |||
671 | void zd_chip_init(struct zd_chip *chip, | ||
672 | struct net_device *netdev, | ||
673 | struct usb_interface *intf); | ||
674 | void zd_chip_clear(struct zd_chip *chip); | ||
675 | int zd_chip_init_hw(struct zd_chip *chip, u8 device_type); | ||
676 | int zd_chip_reset(struct zd_chip *chip); | ||
677 | |||
678 | static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values, | ||
679 | const zd_addr_t *addresses, | ||
680 | unsigned int count) | ||
681 | { | ||
682 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
683 | return zd_usb_ioread16v(&chip->usb, values, addresses, count); | ||
684 | } | ||
685 | |||
686 | static inline int zd_ioread16_locked(struct zd_chip *chip, u16 *value, | ||
687 | const zd_addr_t addr) | ||
688 | { | ||
689 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
690 | return zd_usb_ioread16(&chip->usb, value, addr); | ||
691 | } | ||
692 | |||
693 | int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, | ||
694 | const zd_addr_t *addresses, unsigned int count); | ||
695 | |||
696 | static inline int zd_ioread32_locked(struct zd_chip *chip, u32 *value, | ||
697 | const zd_addr_t addr) | ||
698 | { | ||
699 | return zd_ioread32v_locked(chip, value, (const zd_addr_t *)&addr, 1); | ||
700 | } | ||
701 | |||
702 | static inline int zd_iowrite16_locked(struct zd_chip *chip, u16 value, | ||
703 | zd_addr_t addr) | ||
704 | { | ||
705 | struct zd_ioreq16 ioreq; | ||
706 | |||
707 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
708 | ioreq.addr = addr; | ||
709 | ioreq.value = value; | ||
710 | |||
711 | return zd_usb_iowrite16v(&chip->usb, &ioreq, 1); | ||
712 | } | ||
713 | |||
714 | int zd_iowrite16a_locked(struct zd_chip *chip, | ||
715 | const struct zd_ioreq16 *ioreqs, unsigned int count); | ||
716 | |||
717 | int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, | ||
718 | unsigned int count); | ||
719 | |||
720 | static inline int zd_iowrite32_locked(struct zd_chip *chip, u32 value, | ||
721 | zd_addr_t addr) | ||
722 | { | ||
723 | struct zd_ioreq32 ioreq; | ||
724 | |||
725 | ioreq.addr = addr; | ||
726 | ioreq.value = value; | ||
727 | |||
728 | return _zd_iowrite32v_locked(chip, &ioreq, 1); | ||
729 | } | ||
730 | |||
731 | int zd_iowrite32a_locked(struct zd_chip *chip, | ||
732 | const struct zd_ioreq32 *ioreqs, unsigned int count); | ||
733 | |||
734 | static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits) | ||
735 | { | ||
736 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
737 | return zd_usb_rfwrite(&chip->usb, value, bits); | ||
738 | } | ||
739 | |||
740 | int zd_rfwritev_locked(struct zd_chip *chip, | ||
741 | const u32* values, unsigned int count, u8 bits); | ||
742 | |||
743 | /* Locking functions for reading and writing registers. | ||
744 | * The different parameters are intentional. | ||
745 | */ | ||
746 | int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value); | ||
747 | int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value); | ||
748 | int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value); | ||
749 | int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value); | ||
750 | int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses, | ||
751 | u32 *values, unsigned int count); | ||
752 | int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, | ||
753 | unsigned int count); | ||
754 | |||
755 | int zd_chip_set_channel(struct zd_chip *chip, u8 channel); | ||
756 | static inline u8 _zd_chip_get_channel(struct zd_chip *chip) | ||
757 | { | ||
758 | return chip->rf.channel; | ||
759 | } | ||
760 | u8 zd_chip_get_channel(struct zd_chip *chip); | ||
761 | int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain); | ||
762 | void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr); | ||
763 | int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr); | ||
764 | int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr); | ||
765 | int zd_chip_switch_radio_on(struct zd_chip *chip); | ||
766 | int zd_chip_switch_radio_off(struct zd_chip *chip); | ||
767 | int zd_chip_enable_int(struct zd_chip *chip); | ||
768 | void zd_chip_disable_int(struct zd_chip *chip); | ||
769 | int zd_chip_enable_rx(struct zd_chip *chip); | ||
770 | void zd_chip_disable_rx(struct zd_chip *chip); | ||
771 | int zd_chip_enable_hwint(struct zd_chip *chip); | ||
772 | int zd_chip_disable_hwint(struct zd_chip *chip); | ||
773 | |||
774 | static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type) | ||
775 | { | ||
776 | return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type); | ||
777 | } | ||
778 | |||
779 | static inline int zd_set_encryption_type(struct zd_chip *chip, u32 type) | ||
780 | { | ||
781 | return zd_iowrite32(chip, CR_ENCRYPTION_TYPE, type); | ||
782 | } | ||
783 | |||
784 | static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates) | ||
785 | { | ||
786 | return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates); | ||
787 | } | ||
788 | |||
789 | int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates); | ||
790 | |||
791 | static inline int zd_chip_set_rx_filter(struct zd_chip *chip, u32 filter) | ||
792 | { | ||
793 | return zd_iowrite32(chip, CR_RX_FILTER, filter); | ||
794 | } | ||
795 | |||
796 | int zd_chip_lock_phy_regs(struct zd_chip *chip); | ||
797 | int zd_chip_unlock_phy_regs(struct zd_chip *chip); | ||
798 | |||
799 | enum led_status { | ||
800 | LED_OFF = 0, | ||
801 | LED_ON = 1, | ||
802 | LED_FLIP = 2, | ||
803 | LED_STATUS = 3, | ||
804 | }; | ||
805 | |||
806 | int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status); | ||
807 | int zd_chip_led_flip(struct zd_chip *chip, int led, | ||
808 | const unsigned int *phases_msecs, unsigned int count); | ||
809 | |||
810 | int zd_set_beacon_interval(struct zd_chip *chip, u32 interval); | ||
811 | |||
812 | static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval) | ||
813 | { | ||
814 | return zd_ioread32(chip, CR_BCN_INTERVAL, interval); | ||
815 | } | ||
816 | |||
817 | struct rx_status; | ||
818 | |||
819 | u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, | ||
820 | const struct rx_status *status); | ||
821 | u8 zd_rx_strength_percent(u8 rssi); | ||
822 | |||
823 | u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status); | ||
824 | |||
825 | #endif /* _ZD_CHIP_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h new file mode 100644 index 000000000000..465906812fc4 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_def.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* zd_def.h | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef _ZD_DEF_H | ||
19 | #define _ZD_DEF_H | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/stringify.h> | ||
23 | #include <linux/device.h> | ||
24 | #include <linux/kernel.h> | ||
25 | |||
26 | #define dev_printk_f(level, dev, fmt, args...) \ | ||
27 | dev_printk(level, dev, "%s() " fmt, __func__, ##args) | ||
28 | |||
29 | #ifdef DEBUG | ||
30 | # define dev_dbg_f(dev, fmt, args...) \ | ||
31 | dev_printk_f(KERN_DEBUG, dev, fmt, ## args) | ||
32 | #else | ||
33 | # define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0) | ||
34 | #endif /* DEBUG */ | ||
35 | |||
36 | #ifdef DEBUG | ||
37 | # define ZD_ASSERT(x) \ | ||
38 | do { \ | ||
39 | if (!(x)) { \ | ||
40 | pr_debug("%s:%d ASSERT %s VIOLATED!\n", \ | ||
41 | __FILE__, __LINE__, __stringify(x)); \ | ||
42 | } \ | ||
43 | } while (0) | ||
44 | #else | ||
45 | # define ZD_ASSERT(x) do { } while (0) | ||
46 | #endif | ||
47 | |||
48 | #endif /* _ZD_DEF_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c new file mode 100644 index 000000000000..66905f7b61ff --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c | |||
@@ -0,0 +1,191 @@ | |||
1 | /* zd_ieee80211.c | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | /* | ||
19 | * A lot of this code is generic and should be moved into the upper layers | ||
20 | * at some point. | ||
21 | */ | ||
22 | |||
23 | #include <linux/errno.h> | ||
24 | #include <linux/wireless.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <net/ieee80211.h> | ||
27 | |||
28 | #include "zd_def.h" | ||
29 | #include "zd_ieee80211.h" | ||
30 | #include "zd_mac.h" | ||
31 | |||
32 | static const struct channel_range channel_ranges[] = { | ||
33 | [0] = { 0, 0}, | ||
34 | [ZD_REGDOMAIN_FCC] = { 1, 12}, | ||
35 | [ZD_REGDOMAIN_IC] = { 1, 12}, | ||
36 | [ZD_REGDOMAIN_ETSI] = { 1, 14}, | ||
37 | [ZD_REGDOMAIN_JAPAN] = { 1, 14}, | ||
38 | [ZD_REGDOMAIN_SPAIN] = { 1, 14}, | ||
39 | [ZD_REGDOMAIN_FRANCE] = { 1, 14}, | ||
40 | [ZD_REGDOMAIN_JAPAN_ADD] = {14, 15}, | ||
41 | }; | ||
42 | |||
43 | const struct channel_range *zd_channel_range(u8 regdomain) | ||
44 | { | ||
45 | if (regdomain >= ARRAY_SIZE(channel_ranges)) | ||
46 | regdomain = 0; | ||
47 | return &channel_ranges[regdomain]; | ||
48 | } | ||
49 | |||
50 | int zd_regdomain_supports_channel(u8 regdomain, u8 channel) | ||
51 | { | ||
52 | const struct channel_range *range = zd_channel_range(regdomain); | ||
53 | return range->start <= channel && channel < range->end; | ||
54 | } | ||
55 | |||
56 | int zd_regdomain_supported(u8 regdomain) | ||
57 | { | ||
58 | const struct channel_range *range = zd_channel_range(regdomain); | ||
59 | return range->start != 0; | ||
60 | } | ||
61 | |||
62 | /* Stores channel frequencies in MHz. */ | ||
63 | static const u16 channel_frequencies[] = { | ||
64 | 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, | ||
65 | 2452, 2457, 2462, 2467, 2472, 2484, | ||
66 | }; | ||
67 | |||
68 | #define NUM_CHANNELS ARRAY_SIZE(channel_frequencies) | ||
69 | |||
70 | static int compute_freq(struct iw_freq *freq, u32 mhz, u32 hz) | ||
71 | { | ||
72 | u32 factor; | ||
73 | |||
74 | freq->e = 0; | ||
75 | if (mhz >= 1000000000U) { | ||
76 | pr_debug("zd1211 mhz %u to large\n", mhz); | ||
77 | freq->m = 0; | ||
78 | return -EINVAL; | ||
79 | } | ||
80 | |||
81 | factor = 1000; | ||
82 | while (mhz >= factor) { | ||
83 | |||
84 | freq->e += 1; | ||
85 | factor *= 10; | ||
86 | } | ||
87 | |||
88 | factor /= 1000U; | ||
89 | freq->m = mhz * (1000000U/factor) + hz/factor; | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | int zd_channel_to_freq(struct iw_freq *freq, u8 channel) | ||
95 | { | ||
96 | if (channel > NUM_CHANNELS) { | ||
97 | freq->m = 0; | ||
98 | freq->e = 0; | ||
99 | return -EINVAL; | ||
100 | } | ||
101 | if (!channel) { | ||
102 | freq->m = 0; | ||
103 | freq->e = 0; | ||
104 | return -EINVAL; | ||
105 | } | ||
106 | return compute_freq(freq, channel_frequencies[channel-1], 0); | ||
107 | } | ||
108 | |||
109 | static int freq_to_mhz(const struct iw_freq *freq) | ||
110 | { | ||
111 | u32 factor; | ||
112 | int e; | ||
113 | |||
114 | /* Such high frequencies are not supported. */ | ||
115 | if (freq->e > 6) | ||
116 | return -EINVAL; | ||
117 | |||
118 | factor = 1; | ||
119 | for (e = freq->e; e > 0; --e) { | ||
120 | factor *= 10; | ||
121 | } | ||
122 | factor = 1000000U / factor; | ||
123 | |||
124 | if (freq->m % factor) { | ||
125 | return -EINVAL; | ||
126 | } | ||
127 | |||
128 | return freq->m / factor; | ||
129 | } | ||
130 | |||
131 | int zd_find_channel(u8 *channel, const struct iw_freq *freq) | ||
132 | { | ||
133 | int i, r; | ||
134 | u32 mhz; | ||
135 | |||
136 | if (!(freq->flags & IW_FREQ_FIXED)) | ||
137 | return 0; | ||
138 | |||
139 | if (freq->m < 1000) { | ||
140 | if (freq->m > NUM_CHANNELS || freq->m == 0) | ||
141 | return -EINVAL; | ||
142 | *channel = freq->m; | ||
143 | return 1; | ||
144 | } | ||
145 | |||
146 | r = freq_to_mhz(freq); | ||
147 | if (r < 0) | ||
148 | return r; | ||
149 | mhz = r; | ||
150 | |||
151 | for (i = 0; i < NUM_CHANNELS; i++) { | ||
152 | if (mhz == channel_frequencies[i]) { | ||
153 | *channel = i+1; | ||
154 | return 1; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | return -EINVAL; | ||
159 | } | ||
160 | |||
161 | int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain) | ||
162 | { | ||
163 | struct ieee80211_geo geo; | ||
164 | const struct channel_range *range; | ||
165 | int i; | ||
166 | u8 channel; | ||
167 | |||
168 | dev_dbg(zd_mac_dev(zd_netdev_mac(ieee->dev)), | ||
169 | "regdomain %#04x\n", regdomain); | ||
170 | |||
171 | range = zd_channel_range(regdomain); | ||
172 | if (range->start == 0) { | ||
173 | dev_err(zd_mac_dev(zd_netdev_mac(ieee->dev)), | ||
174 | "zd1211 regdomain %#04x not supported\n", | ||
175 | regdomain); | ||
176 | return -EINVAL; | ||
177 | } | ||
178 | |||
179 | memset(&geo, 0, sizeof(geo)); | ||
180 | |||
181 | for (i = 0, channel = range->start; channel < range->end; channel++) { | ||
182 | struct ieee80211_channel *chan = &geo.bg[i++]; | ||
183 | chan->freq = channel_frequencies[channel - 1]; | ||
184 | chan->channel = channel; | ||
185 | } | ||
186 | |||
187 | geo.bg_channels = i; | ||
188 | memcpy(geo.name, "XX ", 4); | ||
189 | ieee80211_set_geo(ieee, &geo); | ||
190 | return 0; | ||
191 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h new file mode 100644 index 000000000000..36329890dfec --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.h | |||
@@ -0,0 +1,85 @@ | |||
1 | #ifndef _ZD_IEEE80211_H | ||
2 | #define _ZD_IEEE80211_H | ||
3 | |||
4 | #include <net/ieee80211.h> | ||
5 | #include "zd_types.h" | ||
6 | |||
7 | /* Additional definitions from the standards. | ||
8 | */ | ||
9 | |||
10 | #define ZD_REGDOMAIN_FCC 0x10 | ||
11 | #define ZD_REGDOMAIN_IC 0x20 | ||
12 | #define ZD_REGDOMAIN_ETSI 0x30 | ||
13 | #define ZD_REGDOMAIN_SPAIN 0x31 | ||
14 | #define ZD_REGDOMAIN_FRANCE 0x32 | ||
15 | #define ZD_REGDOMAIN_JAPAN_ADD 0x40 | ||
16 | #define ZD_REGDOMAIN_JAPAN 0x41 | ||
17 | |||
18 | enum { | ||
19 | MIN_CHANNEL24 = 1, | ||
20 | MAX_CHANNEL24 = 14, | ||
21 | }; | ||
22 | |||
23 | struct channel_range { | ||
24 | u8 start; | ||
25 | u8 end; /* exclusive (channel must be less than end) */ | ||
26 | }; | ||
27 | |||
28 | struct iw_freq; | ||
29 | |||
30 | int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain); | ||
31 | |||
32 | const struct channel_range *zd_channel_range(u8 regdomain); | ||
33 | int zd_regdomain_supports_channel(u8 regdomain, u8 channel); | ||
34 | int zd_regdomain_supported(u8 regdomain); | ||
35 | |||
36 | /* for 2.4 GHz band */ | ||
37 | int zd_channel_to_freq(struct iw_freq *freq, u8 channel); | ||
38 | int zd_find_channel(u8 *channel, const struct iw_freq *freq); | ||
39 | |||
40 | #define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80 | ||
41 | |||
42 | struct ofdm_plcp_header { | ||
43 | u8 prefix[3]; | ||
44 | __le16 service; | ||
45 | } __attribute__((packed)); | ||
46 | |||
47 | static inline u8 zd_ofdm_plcp_header_rate( | ||
48 | const struct ofdm_plcp_header *header) | ||
49 | { | ||
50 | return header->prefix[0] & 0xf; | ||
51 | } | ||
52 | |||
53 | #define ZD_OFDM_RATE_6M 0xb | ||
54 | #define ZD_OFDM_RATE_9M 0xf | ||
55 | #define ZD_OFDM_RATE_12M 0xa | ||
56 | #define ZD_OFDM_RATE_18M 0xe | ||
57 | #define ZD_OFDM_RATE_24M 0x9 | ||
58 | #define ZD_OFDM_RATE_36M 0xd | ||
59 | #define ZD_OFDM_RATE_48M 0x8 | ||
60 | #define ZD_OFDM_RATE_54M 0xc | ||
61 | |||
62 | struct cck_plcp_header { | ||
63 | u8 signal; | ||
64 | u8 service; | ||
65 | __le16 length; | ||
66 | __le16 crc16; | ||
67 | } __attribute__((packed)); | ||
68 | |||
69 | static inline u8 zd_cck_plcp_header_rate(const struct cck_plcp_header *header) | ||
70 | { | ||
71 | return header->signal; | ||
72 | } | ||
73 | |||
74 | #define ZD_CCK_SIGNAL_1M 0x0a | ||
75 | #define ZD_CCK_SIGNAL_2M 0x14 | ||
76 | #define ZD_CCK_SIGNAL_5M5 0x37 | ||
77 | #define ZD_CCK_SIGNAL_11M 0x6e | ||
78 | |||
79 | enum ieee80211_std { | ||
80 | IEEE80211B = 0x01, | ||
81 | IEEE80211A = 0x02, | ||
82 | IEEE80211G = 0x04, | ||
83 | }; | ||
84 | |||
85 | #endif /* _ZD_IEEE80211_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c new file mode 100644 index 000000000000..bbe067ec7de1 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -0,0 +1,1055 @@ | |||
1 | /* zd_mac.c | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/etherdevice.h> | ||
20 | #include <linux/wireless.h> | ||
21 | #include <linux/usb.h> | ||
22 | #include <linux/jiffies.h> | ||
23 | #include <net/ieee80211_radiotap.h> | ||
24 | |||
25 | #include "zd_def.h" | ||
26 | #include "zd_chip.h" | ||
27 | #include "zd_mac.h" | ||
28 | #include "zd_ieee80211.h" | ||
29 | #include "zd_netdev.h" | ||
30 | #include "zd_rf.h" | ||
31 | #include "zd_util.h" | ||
32 | |||
33 | static void ieee_init(struct ieee80211_device *ieee); | ||
34 | static void softmac_init(struct ieee80211softmac_device *sm); | ||
35 | |||
36 | int zd_mac_init(struct zd_mac *mac, | ||
37 | struct net_device *netdev, | ||
38 | struct usb_interface *intf) | ||
39 | { | ||
40 | struct ieee80211_device *ieee = zd_netdev_ieee80211(netdev); | ||
41 | |||
42 | memset(mac, 0, sizeof(*mac)); | ||
43 | spin_lock_init(&mac->lock); | ||
44 | mac->netdev = netdev; | ||
45 | |||
46 | ieee_init(ieee); | ||
47 | softmac_init(ieee80211_priv(netdev)); | ||
48 | zd_chip_init(&mac->chip, netdev, intf); | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static int reset_channel(struct zd_mac *mac) | ||
53 | { | ||
54 | int r; | ||
55 | unsigned long flags; | ||
56 | const struct channel_range *range; | ||
57 | |||
58 | spin_lock_irqsave(&mac->lock, flags); | ||
59 | range = zd_channel_range(mac->regdomain); | ||
60 | if (!range->start) { | ||
61 | r = -EINVAL; | ||
62 | goto out; | ||
63 | } | ||
64 | mac->requested_channel = range->start; | ||
65 | r = 0; | ||
66 | out: | ||
67 | spin_unlock_irqrestore(&mac->lock, flags); | ||
68 | return r; | ||
69 | } | ||
70 | |||
71 | int zd_mac_init_hw(struct zd_mac *mac, u8 device_type) | ||
72 | { | ||
73 | int r; | ||
74 | struct zd_chip *chip = &mac->chip; | ||
75 | u8 addr[ETH_ALEN]; | ||
76 | u8 default_regdomain; | ||
77 | |||
78 | r = zd_chip_enable_int(chip); | ||
79 | if (r) | ||
80 | goto out; | ||
81 | r = zd_chip_init_hw(chip, device_type); | ||
82 | if (r) | ||
83 | goto disable_int; | ||
84 | |||
85 | zd_get_e2p_mac_addr(chip, addr); | ||
86 | r = zd_write_mac_addr(chip, addr); | ||
87 | if (r) | ||
88 | goto disable_int; | ||
89 | ZD_ASSERT(!irqs_disabled()); | ||
90 | spin_lock_irq(&mac->lock); | ||
91 | memcpy(mac->netdev->dev_addr, addr, ETH_ALEN); | ||
92 | spin_unlock_irq(&mac->lock); | ||
93 | |||
94 | r = zd_read_regdomain(chip, &default_regdomain); | ||
95 | if (r) | ||
96 | goto disable_int; | ||
97 | if (!zd_regdomain_supported(default_regdomain)) { | ||
98 | dev_dbg_f(zd_mac_dev(mac), | ||
99 | "Regulatory Domain %#04x is not supported.\n", | ||
100 | default_regdomain); | ||
101 | r = -EINVAL; | ||
102 | goto disable_int; | ||
103 | } | ||
104 | spin_lock_irq(&mac->lock); | ||
105 | mac->regdomain = mac->default_regdomain = default_regdomain; | ||
106 | spin_unlock_irq(&mac->lock); | ||
107 | r = reset_channel(mac); | ||
108 | if (r) | ||
109 | goto disable_int; | ||
110 | |||
111 | r = zd_set_encryption_type(chip, NO_WEP); | ||
112 | if (r) | ||
113 | goto disable_int; | ||
114 | |||
115 | r = zd_geo_init(zd_mac_to_ieee80211(mac), mac->regdomain); | ||
116 | if (r) | ||
117 | goto disable_int; | ||
118 | |||
119 | r = 0; | ||
120 | disable_int: | ||
121 | zd_chip_disable_int(chip); | ||
122 | out: | ||
123 | return r; | ||
124 | } | ||
125 | |||
126 | void zd_mac_clear(struct zd_mac *mac) | ||
127 | { | ||
128 | /* Aquire the lock. */ | ||
129 | spin_lock(&mac->lock); | ||
130 | spin_unlock(&mac->lock); | ||
131 | zd_chip_clear(&mac->chip); | ||
132 | memset(mac, 0, sizeof(*mac)); | ||
133 | } | ||
134 | |||
135 | static int reset_mode(struct zd_mac *mac) | ||
136 | { | ||
137 | struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); | ||
138 | struct zd_ioreq32 ioreqs[3] = { | ||
139 | { CR_RX_FILTER, RX_FILTER_BEACON|RX_FILTER_PROBE_RESPONSE| | ||
140 | RX_FILTER_AUTH|RX_FILTER_ASSOC_RESPONSE }, | ||
141 | { CR_SNIFFER_ON, 0U }, | ||
142 | { CR_ENCRYPTION_TYPE, NO_WEP }, | ||
143 | }; | ||
144 | |||
145 | if (ieee->iw_mode == IW_MODE_MONITOR) { | ||
146 | ioreqs[0].value = 0xffffffff; | ||
147 | ioreqs[1].value = 0x1; | ||
148 | ioreqs[2].value = ENC_SNIFFER; | ||
149 | } | ||
150 | |||
151 | return zd_iowrite32a(&mac->chip, ioreqs, 3); | ||
152 | } | ||
153 | |||
154 | int zd_mac_open(struct net_device *netdev) | ||
155 | { | ||
156 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
157 | struct zd_chip *chip = &mac->chip; | ||
158 | int r; | ||
159 | |||
160 | r = zd_chip_enable_int(chip); | ||
161 | if (r < 0) | ||
162 | goto out; | ||
163 | |||
164 | r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G); | ||
165 | if (r < 0) | ||
166 | goto disable_int; | ||
167 | r = reset_mode(mac); | ||
168 | if (r) | ||
169 | goto disable_int; | ||
170 | r = zd_chip_switch_radio_on(chip); | ||
171 | if (r < 0) | ||
172 | goto disable_int; | ||
173 | r = zd_chip_set_channel(chip, mac->requested_channel); | ||
174 | if (r < 0) | ||
175 | goto disable_radio; | ||
176 | r = zd_chip_enable_rx(chip); | ||
177 | if (r < 0) | ||
178 | goto disable_radio; | ||
179 | r = zd_chip_enable_hwint(chip); | ||
180 | if (r < 0) | ||
181 | goto disable_rx; | ||
182 | |||
183 | ieee80211softmac_start(netdev); | ||
184 | return 0; | ||
185 | disable_rx: | ||
186 | zd_chip_disable_rx(chip); | ||
187 | disable_radio: | ||
188 | zd_chip_switch_radio_off(chip); | ||
189 | disable_int: | ||
190 | zd_chip_disable_int(chip); | ||
191 | out: | ||
192 | return r; | ||
193 | } | ||
194 | |||
195 | int zd_mac_stop(struct net_device *netdev) | ||
196 | { | ||
197 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
198 | struct zd_chip *chip = &mac->chip; | ||
199 | |||
200 | /* | ||
201 | * The order here deliberately is a little different from the open() | ||
202 | * method, since we need to make sure there is no opportunity for RX | ||
203 | * frames to be processed by softmac after we have stopped it. | ||
204 | */ | ||
205 | |||
206 | zd_chip_disable_rx(chip); | ||
207 | ieee80211softmac_stop(netdev); | ||
208 | |||
209 | zd_chip_disable_hwint(chip); | ||
210 | zd_chip_switch_radio_off(chip); | ||
211 | zd_chip_disable_int(chip); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | int zd_mac_set_mac_address(struct net_device *netdev, void *p) | ||
217 | { | ||
218 | int r; | ||
219 | unsigned long flags; | ||
220 | struct sockaddr *addr = p; | ||
221 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
222 | struct zd_chip *chip = &mac->chip; | ||
223 | |||
224 | if (!is_valid_ether_addr(addr->sa_data)) | ||
225 | return -EADDRNOTAVAIL; | ||
226 | |||
227 | dev_dbg_f(zd_mac_dev(mac), | ||
228 | "Setting MAC to " MAC_FMT "\n", MAC_ARG(addr->sa_data)); | ||
229 | |||
230 | r = zd_write_mac_addr(chip, addr->sa_data); | ||
231 | if (r) | ||
232 | return r; | ||
233 | |||
234 | spin_lock_irqsave(&mac->lock, flags); | ||
235 | memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN); | ||
236 | spin_unlock_irqrestore(&mac->lock, flags); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | int zd_mac_set_regdomain(struct zd_mac *mac, u8 regdomain) | ||
242 | { | ||
243 | int r; | ||
244 | u8 channel; | ||
245 | |||
246 | ZD_ASSERT(!irqs_disabled()); | ||
247 | spin_lock_irq(&mac->lock); | ||
248 | if (regdomain == 0) { | ||
249 | regdomain = mac->default_regdomain; | ||
250 | } | ||
251 | if (!zd_regdomain_supported(regdomain)) { | ||
252 | spin_unlock_irq(&mac->lock); | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | mac->regdomain = regdomain; | ||
256 | channel = mac->requested_channel; | ||
257 | spin_unlock_irq(&mac->lock); | ||
258 | |||
259 | r = zd_geo_init(zd_mac_to_ieee80211(mac), regdomain); | ||
260 | if (r) | ||
261 | return r; | ||
262 | if (!zd_regdomain_supports_channel(regdomain, channel)) { | ||
263 | r = reset_channel(mac); | ||
264 | if (r) | ||
265 | return r; | ||
266 | } | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | u8 zd_mac_get_regdomain(struct zd_mac *mac) | ||
272 | { | ||
273 | unsigned long flags; | ||
274 | u8 regdomain; | ||
275 | |||
276 | spin_lock_irqsave(&mac->lock, flags); | ||
277 | regdomain = mac->regdomain; | ||
278 | spin_unlock_irqrestore(&mac->lock, flags); | ||
279 | return regdomain; | ||
280 | } | ||
281 | |||
282 | static void set_channel(struct net_device *netdev, u8 channel) | ||
283 | { | ||
284 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
285 | |||
286 | dev_dbg_f(zd_mac_dev(mac), "channel %d\n", channel); | ||
287 | |||
288 | zd_chip_set_channel(&mac->chip, channel); | ||
289 | } | ||
290 | |||
291 | /* TODO: Should not work in Managed mode. */ | ||
292 | int zd_mac_request_channel(struct zd_mac *mac, u8 channel) | ||
293 | { | ||
294 | unsigned long lock_flags; | ||
295 | struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); | ||
296 | |||
297 | if (ieee->iw_mode == IW_MODE_INFRA) | ||
298 | return -EPERM; | ||
299 | |||
300 | spin_lock_irqsave(&mac->lock, lock_flags); | ||
301 | if (!zd_regdomain_supports_channel(mac->regdomain, channel)) { | ||
302 | spin_unlock_irqrestore(&mac->lock, lock_flags); | ||
303 | return -EINVAL; | ||
304 | } | ||
305 | mac->requested_channel = channel; | ||
306 | spin_unlock_irqrestore(&mac->lock, lock_flags); | ||
307 | if (netif_running(mac->netdev)) | ||
308 | return zd_chip_set_channel(&mac->chip, channel); | ||
309 | else | ||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags) | ||
314 | { | ||
315 | struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); | ||
316 | |||
317 | *channel = zd_chip_get_channel(&mac->chip); | ||
318 | if (ieee->iw_mode != IW_MODE_INFRA) { | ||
319 | spin_lock_irq(&mac->lock); | ||
320 | *flags = *channel == mac->requested_channel ? | ||
321 | MAC_FIXED_CHANNEL : 0; | ||
322 | spin_unlock(&mac->lock); | ||
323 | } else { | ||
324 | *flags = 0; | ||
325 | } | ||
326 | dev_dbg_f(zd_mac_dev(mac), "channel %u flags %u\n", *channel, *flags); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | /* If wrong rate is given, we are falling back to the slowest rate: 1MBit/s */ | ||
331 | static u8 cs_typed_rate(u8 cs_rate) | ||
332 | { | ||
333 | static const u8 typed_rates[16] = { | ||
334 | [ZD_CS_CCK_RATE_1M] = ZD_CS_CCK|ZD_CS_CCK_RATE_1M, | ||
335 | [ZD_CS_CCK_RATE_2M] = ZD_CS_CCK|ZD_CS_CCK_RATE_2M, | ||
336 | [ZD_CS_CCK_RATE_5_5M] = ZD_CS_CCK|ZD_CS_CCK_RATE_5_5M, | ||
337 | [ZD_CS_CCK_RATE_11M] = ZD_CS_CCK|ZD_CS_CCK_RATE_11M, | ||
338 | [ZD_OFDM_RATE_6M] = ZD_CS_OFDM|ZD_OFDM_RATE_6M, | ||
339 | [ZD_OFDM_RATE_9M] = ZD_CS_OFDM|ZD_OFDM_RATE_9M, | ||
340 | [ZD_OFDM_RATE_12M] = ZD_CS_OFDM|ZD_OFDM_RATE_12M, | ||
341 | [ZD_OFDM_RATE_18M] = ZD_CS_OFDM|ZD_OFDM_RATE_18M, | ||
342 | [ZD_OFDM_RATE_24M] = ZD_CS_OFDM|ZD_OFDM_RATE_24M, | ||
343 | [ZD_OFDM_RATE_36M] = ZD_CS_OFDM|ZD_OFDM_RATE_36M, | ||
344 | [ZD_OFDM_RATE_48M] = ZD_CS_OFDM|ZD_OFDM_RATE_48M, | ||
345 | [ZD_OFDM_RATE_54M] = ZD_CS_OFDM|ZD_OFDM_RATE_54M, | ||
346 | }; | ||
347 | |||
348 | ZD_ASSERT(ZD_CS_RATE_MASK == 0x0f); | ||
349 | return typed_rates[cs_rate & ZD_CS_RATE_MASK]; | ||
350 | } | ||
351 | |||
352 | /* Fallback to lowest rate, if rate is unknown. */ | ||
353 | static u8 rate_to_cs_rate(u8 rate) | ||
354 | { | ||
355 | switch (rate) { | ||
356 | case IEEE80211_CCK_RATE_2MB: | ||
357 | return ZD_CS_CCK_RATE_2M; | ||
358 | case IEEE80211_CCK_RATE_5MB: | ||
359 | return ZD_CS_CCK_RATE_5_5M; | ||
360 | case IEEE80211_CCK_RATE_11MB: | ||
361 | return ZD_CS_CCK_RATE_11M; | ||
362 | case IEEE80211_OFDM_RATE_6MB: | ||
363 | return ZD_OFDM_RATE_6M; | ||
364 | case IEEE80211_OFDM_RATE_9MB: | ||
365 | return ZD_OFDM_RATE_9M; | ||
366 | case IEEE80211_OFDM_RATE_12MB: | ||
367 | return ZD_OFDM_RATE_12M; | ||
368 | case IEEE80211_OFDM_RATE_18MB: | ||
369 | return ZD_OFDM_RATE_18M; | ||
370 | case IEEE80211_OFDM_RATE_24MB: | ||
371 | return ZD_OFDM_RATE_24M; | ||
372 | case IEEE80211_OFDM_RATE_36MB: | ||
373 | return ZD_OFDM_RATE_36M; | ||
374 | case IEEE80211_OFDM_RATE_48MB: | ||
375 | return ZD_OFDM_RATE_48M; | ||
376 | case IEEE80211_OFDM_RATE_54MB: | ||
377 | return ZD_OFDM_RATE_54M; | ||
378 | } | ||
379 | return ZD_CS_CCK_RATE_1M; | ||
380 | } | ||
381 | |||
382 | int zd_mac_set_mode(struct zd_mac *mac, u32 mode) | ||
383 | { | ||
384 | struct ieee80211_device *ieee; | ||
385 | |||
386 | switch (mode) { | ||
387 | case IW_MODE_AUTO: | ||
388 | case IW_MODE_ADHOC: | ||
389 | case IW_MODE_INFRA: | ||
390 | mac->netdev->type = ARPHRD_ETHER; | ||
391 | break; | ||
392 | case IW_MODE_MONITOR: | ||
393 | mac->netdev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
394 | break; | ||
395 | default: | ||
396 | dev_dbg_f(zd_mac_dev(mac), "wrong mode %u\n", mode); | ||
397 | return -EINVAL; | ||
398 | } | ||
399 | |||
400 | ieee = zd_mac_to_ieee80211(mac); | ||
401 | ZD_ASSERT(!irqs_disabled()); | ||
402 | spin_lock_irq(&ieee->lock); | ||
403 | ieee->iw_mode = mode; | ||
404 | spin_unlock_irq(&ieee->lock); | ||
405 | |||
406 | if (netif_running(mac->netdev)) | ||
407 | return reset_mode(mac); | ||
408 | |||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | int zd_mac_get_mode(struct zd_mac *mac, u32 *mode) | ||
413 | { | ||
414 | unsigned long flags; | ||
415 | struct ieee80211_device *ieee; | ||
416 | |||
417 | ieee = zd_mac_to_ieee80211(mac); | ||
418 | spin_lock_irqsave(&ieee->lock, flags); | ||
419 | *mode = ieee->iw_mode; | ||
420 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range) | ||
425 | { | ||
426 | int i; | ||
427 | const struct channel_range *channel_range; | ||
428 | u8 regdomain; | ||
429 | |||
430 | memset(range, 0, sizeof(*range)); | ||
431 | |||
432 | /* FIXME: Not so important and depends on the mode. For 802.11g | ||
433 | * usually this value is used. It seems to be that Bit/s number is | ||
434 | * given here. | ||
435 | */ | ||
436 | range->throughput = 27 * 1000 * 1000; | ||
437 | |||
438 | range->max_qual.qual = 100; | ||
439 | range->max_qual.level = 100; | ||
440 | |||
441 | /* FIXME: Needs still to be tuned. */ | ||
442 | range->avg_qual.qual = 71; | ||
443 | range->avg_qual.level = 80; | ||
444 | |||
445 | /* FIXME: depends on standard? */ | ||
446 | range->min_rts = 256; | ||
447 | range->max_rts = 2346; | ||
448 | |||
449 | range->min_frag = MIN_FRAG_THRESHOLD; | ||
450 | range->max_frag = MAX_FRAG_THRESHOLD; | ||
451 | |||
452 | range->max_encoding_tokens = WEP_KEYS; | ||
453 | range->num_encoding_sizes = 2; | ||
454 | range->encoding_size[0] = 5; | ||
455 | range->encoding_size[1] = WEP_KEY_LEN; | ||
456 | |||
457 | range->we_version_compiled = WIRELESS_EXT; | ||
458 | range->we_version_source = 20; | ||
459 | |||
460 | ZD_ASSERT(!irqs_disabled()); | ||
461 | spin_lock_irq(&mac->lock); | ||
462 | regdomain = mac->regdomain; | ||
463 | spin_unlock_irq(&mac->lock); | ||
464 | channel_range = zd_channel_range(regdomain); | ||
465 | |||
466 | range->num_channels = channel_range->end - channel_range->start; | ||
467 | range->old_num_channels = range->num_channels; | ||
468 | range->num_frequency = range->num_channels; | ||
469 | range->old_num_frequency = range->num_frequency; | ||
470 | |||
471 | for (i = 0; i < range->num_frequency; i++) { | ||
472 | struct iw_freq *freq = &range->freq[i]; | ||
473 | freq->i = channel_range->start + i; | ||
474 | zd_channel_to_freq(freq, freq->i); | ||
475 | } | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int zd_calc_tx_length_us(u8 *service, u8 cs_rate, u16 tx_length) | ||
481 | { | ||
482 | static const u8 rate_divisor[] = { | ||
483 | [ZD_CS_CCK_RATE_1M] = 1, | ||
484 | [ZD_CS_CCK_RATE_2M] = 2, | ||
485 | [ZD_CS_CCK_RATE_5_5M] = 11, /* bits must be doubled */ | ||
486 | [ZD_CS_CCK_RATE_11M] = 11, | ||
487 | [ZD_OFDM_RATE_6M] = 6, | ||
488 | [ZD_OFDM_RATE_9M] = 9, | ||
489 | [ZD_OFDM_RATE_12M] = 12, | ||
490 | [ZD_OFDM_RATE_18M] = 18, | ||
491 | [ZD_OFDM_RATE_24M] = 24, | ||
492 | [ZD_OFDM_RATE_36M] = 36, | ||
493 | [ZD_OFDM_RATE_48M] = 48, | ||
494 | [ZD_OFDM_RATE_54M] = 54, | ||
495 | }; | ||
496 | |||
497 | u32 bits = (u32)tx_length * 8; | ||
498 | u32 divisor; | ||
499 | |||
500 | divisor = rate_divisor[cs_rate]; | ||
501 | if (divisor == 0) | ||
502 | return -EINVAL; | ||
503 | |||
504 | switch (cs_rate) { | ||
505 | case ZD_CS_CCK_RATE_5_5M: | ||
506 | bits = (2*bits) + 10; /* round up to the next integer */ | ||
507 | break; | ||
508 | case ZD_CS_CCK_RATE_11M: | ||
509 | if (service) { | ||
510 | u32 t = bits % 11; | ||
511 | *service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION; | ||
512 | if (0 < t && t <= 3) { | ||
513 | *service |= ZD_PLCP_SERVICE_LENGTH_EXTENSION; | ||
514 | } | ||
515 | } | ||
516 | bits += 10; /* round up to the next integer */ | ||
517 | break; | ||
518 | } | ||
519 | |||
520 | return bits/divisor; | ||
521 | } | ||
522 | |||
523 | enum { | ||
524 | R2M_SHORT_PREAMBLE = 0x01, | ||
525 | R2M_11A = 0x02, | ||
526 | }; | ||
527 | |||
528 | static u8 cs_rate_to_modulation(u8 cs_rate, int flags) | ||
529 | { | ||
530 | u8 modulation; | ||
531 | |||
532 | modulation = cs_typed_rate(cs_rate); | ||
533 | if (flags & R2M_SHORT_PREAMBLE) { | ||
534 | switch (ZD_CS_RATE(modulation)) { | ||
535 | case ZD_CS_CCK_RATE_2M: | ||
536 | case ZD_CS_CCK_RATE_5_5M: | ||
537 | case ZD_CS_CCK_RATE_11M: | ||
538 | modulation |= ZD_CS_CCK_PREA_SHORT; | ||
539 | return modulation; | ||
540 | } | ||
541 | } | ||
542 | if (flags & R2M_11A) { | ||
543 | if (ZD_CS_TYPE(modulation) == ZD_CS_OFDM) | ||
544 | modulation |= ZD_CS_OFDM_MODE_11A; | ||
545 | } | ||
546 | return modulation; | ||
547 | } | ||
548 | |||
549 | static void cs_set_modulation(struct zd_mac *mac, struct zd_ctrlset *cs, | ||
550 | struct ieee80211_hdr_4addr *hdr) | ||
551 | { | ||
552 | struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); | ||
553 | u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl)); | ||
554 | u8 rate, cs_rate; | ||
555 | int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0; | ||
556 | |||
557 | /* FIXME: 802.11a? short preamble? */ | ||
558 | rate = ieee80211softmac_suggest_txrate(softmac, | ||
559 | is_multicast_ether_addr(hdr->addr1), is_mgt); | ||
560 | |||
561 | cs_rate = rate_to_cs_rate(rate); | ||
562 | cs->modulation = cs_rate_to_modulation(cs_rate, 0); | ||
563 | } | ||
564 | |||
565 | static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | ||
566 | struct ieee80211_hdr_4addr *header) | ||
567 | { | ||
568 | unsigned int tx_length = le16_to_cpu(cs->tx_length); | ||
569 | u16 fctl = le16_to_cpu(header->frame_ctl); | ||
570 | u16 ftype = WLAN_FC_GET_TYPE(fctl); | ||
571 | u16 stype = WLAN_FC_GET_STYPE(fctl); | ||
572 | |||
573 | /* | ||
574 | * CONTROL: | ||
575 | * - start at 0x00 | ||
576 | * - if fragment 0, enable bit 0 | ||
577 | * - if backoff needed, enable bit 0 | ||
578 | * - if burst (backoff not needed) disable bit 0 | ||
579 | * - if multicast, enable bit 1 | ||
580 | * - if PS-POLL frame, enable bit 2 | ||
581 | * - if in INDEPENDENT_BSS mode and zd1205_DestPowerSave, then enable | ||
582 | * bit 4 (FIXME: wtf) | ||
583 | * - if frag_len > RTS threshold, set bit 5 as long if it isnt | ||
584 | * multicast or mgt | ||
585 | * - if bit 5 is set, and we are in OFDM mode, unset bit 5 and set bit | ||
586 | * 7 | ||
587 | */ | ||
588 | |||
589 | cs->control = 0; | ||
590 | |||
591 | /* First fragment */ | ||
592 | if (WLAN_GET_SEQ_FRAG(le16_to_cpu(header->seq_ctl)) == 0) | ||
593 | cs->control |= ZD_CS_NEED_RANDOM_BACKOFF; | ||
594 | |||
595 | /* Multicast */ | ||
596 | if (is_multicast_ether_addr(header->addr1)) | ||
597 | cs->control |= ZD_CS_MULTICAST; | ||
598 | |||
599 | /* PS-POLL */ | ||
600 | if (stype == IEEE80211_STYPE_PSPOLL) | ||
601 | cs->control |= ZD_CS_PS_POLL_FRAME; | ||
602 | |||
603 | if (!is_multicast_ether_addr(header->addr1) && | ||
604 | ftype != IEEE80211_FTYPE_MGMT && | ||
605 | tx_length > zd_netdev_ieee80211(mac->netdev)->rts) | ||
606 | { | ||
607 | /* FIXME: check the logic */ | ||
608 | if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM) { | ||
609 | /* 802.11g */ | ||
610 | cs->control |= ZD_CS_SELF_CTS; | ||
611 | } else { /* 802.11b */ | ||
612 | cs->control |= ZD_CS_RTS; | ||
613 | } | ||
614 | } | ||
615 | |||
616 | /* FIXME: Management frame? */ | ||
617 | } | ||
618 | |||
619 | static int fill_ctrlset(struct zd_mac *mac, | ||
620 | struct ieee80211_txb *txb, | ||
621 | int frag_num) | ||
622 | { | ||
623 | int r; | ||
624 | struct sk_buff *skb = txb->fragments[frag_num]; | ||
625 | struct ieee80211_hdr_4addr *hdr = | ||
626 | (struct ieee80211_hdr_4addr *) skb->data; | ||
627 | unsigned int frag_len = skb->len + IEEE80211_FCS_LEN; | ||
628 | unsigned int next_frag_len; | ||
629 | unsigned int packet_length; | ||
630 | struct zd_ctrlset *cs = (struct zd_ctrlset *) | ||
631 | skb_push(skb, sizeof(struct zd_ctrlset)); | ||
632 | |||
633 | if (frag_num+1 < txb->nr_frags) { | ||
634 | next_frag_len = txb->fragments[frag_num+1]->len + | ||
635 | IEEE80211_FCS_LEN; | ||
636 | } else { | ||
637 | next_frag_len = 0; | ||
638 | } | ||
639 | ZD_ASSERT(frag_len <= 0xffff); | ||
640 | ZD_ASSERT(next_frag_len <= 0xffff); | ||
641 | |||
642 | cs_set_modulation(mac, cs, hdr); | ||
643 | |||
644 | cs->tx_length = cpu_to_le16(frag_len); | ||
645 | |||
646 | cs_set_control(mac, cs, hdr); | ||
647 | |||
648 | packet_length = frag_len + sizeof(struct zd_ctrlset) + 10; | ||
649 | ZD_ASSERT(packet_length <= 0xffff); | ||
650 | /* ZD1211B: Computing the length difference this way, gives us | ||
651 | * flexibility to compute the packet length. | ||
652 | */ | ||
653 | cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ? | ||
654 | packet_length - frag_len : packet_length); | ||
655 | |||
656 | /* | ||
657 | * CURRENT LENGTH: | ||
658 | * - transmit frame length in microseconds | ||
659 | * - seems to be derived from frame length | ||
660 | * - see Cal_Us_Service() in zdinlinef.h | ||
661 | * - if macp->bTxBurstEnable is enabled, then multiply by 4 | ||
662 | * - bTxBurstEnable is never set in the vendor driver | ||
663 | * | ||
664 | * SERVICE: | ||
665 | * - "for PLCP configuration" | ||
666 | * - always 0 except in some situations at 802.11b 11M | ||
667 | * - see line 53 of zdinlinef.h | ||
668 | */ | ||
669 | cs->service = 0; | ||
670 | r = zd_calc_tx_length_us(&cs->service, ZD_CS_RATE(cs->modulation), | ||
671 | le16_to_cpu(cs->tx_length)); | ||
672 | if (r < 0) | ||
673 | return r; | ||
674 | cs->current_length = cpu_to_le16(r); | ||
675 | |||
676 | if (next_frag_len == 0) { | ||
677 | cs->next_frame_length = 0; | ||
678 | } else { | ||
679 | r = zd_calc_tx_length_us(NULL, ZD_CS_RATE(cs->modulation), | ||
680 | next_frag_len); | ||
681 | if (r < 0) | ||
682 | return r; | ||
683 | cs->next_frame_length = cpu_to_le16(r); | ||
684 | } | ||
685 | |||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri) | ||
690 | { | ||
691 | int i, r; | ||
692 | |||
693 | for (i = 0; i < txb->nr_frags; i++) { | ||
694 | struct sk_buff *skb = txb->fragments[i]; | ||
695 | |||
696 | r = fill_ctrlset(mac, txb, i); | ||
697 | if (r) | ||
698 | return r; | ||
699 | r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len); | ||
700 | if (r) | ||
701 | return r; | ||
702 | } | ||
703 | |||
704 | /* FIXME: shouldn't this be handled by the upper layers? */ | ||
705 | mac->netdev->trans_start = jiffies; | ||
706 | |||
707 | ieee80211_txb_free(txb); | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | struct zd_rt_hdr { | ||
712 | struct ieee80211_radiotap_header rt_hdr; | ||
713 | u8 rt_flags; | ||
714 | u16 rt_channel; | ||
715 | u16 rt_chbitmask; | ||
716 | u16 rt_rate; | ||
717 | }; | ||
718 | |||
719 | static void fill_rt_header(void *buffer, struct zd_mac *mac, | ||
720 | const struct ieee80211_rx_stats *stats, | ||
721 | const struct rx_status *status) | ||
722 | { | ||
723 | struct zd_rt_hdr *hdr = buffer; | ||
724 | |||
725 | hdr->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; | ||
726 | hdr->rt_hdr.it_pad = 0; | ||
727 | hdr->rt_hdr.it_len = cpu_to_le16(sizeof(struct zd_rt_hdr)); | ||
728 | hdr->rt_hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | ||
729 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
730 | (1 << IEEE80211_RADIOTAP_RATE)); | ||
731 | |||
732 | hdr->rt_flags = 0; | ||
733 | if (status->decryption_type & (ZD_RX_WEP64|ZD_RX_WEP128|ZD_RX_WEP256)) | ||
734 | hdr->rt_flags |= IEEE80211_RADIOTAP_F_WEP; | ||
735 | |||
736 | /* FIXME: 802.11a */ | ||
737 | hdr->rt_channel = cpu_to_le16(ieee80211chan2mhz( | ||
738 | _zd_chip_get_channel(&mac->chip))); | ||
739 | hdr->rt_chbitmask = cpu_to_le16(IEEE80211_CHAN_2GHZ | | ||
740 | ((status->frame_status & ZD_RX_FRAME_MODULATION_MASK) == | ||
741 | ZD_RX_OFDM ? IEEE80211_CHAN_OFDM : IEEE80211_CHAN_CCK)); | ||
742 | |||
743 | hdr->rt_rate = stats->rate / 5; | ||
744 | } | ||
745 | |||
746 | /* Returns 1 if the data packet is for us and 0 otherwise. */ | ||
747 | static int is_data_packet_for_us(struct ieee80211_device *ieee, | ||
748 | struct ieee80211_hdr_4addr *hdr) | ||
749 | { | ||
750 | struct net_device *netdev = ieee->dev; | ||
751 | u16 fc = le16_to_cpu(hdr->frame_ctl); | ||
752 | |||
753 | ZD_ASSERT(WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA); | ||
754 | |||
755 | switch (ieee->iw_mode) { | ||
756 | case IW_MODE_ADHOC: | ||
757 | if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != 0 || | ||
758 | memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) != 0) | ||
759 | return 0; | ||
760 | break; | ||
761 | case IW_MODE_AUTO: | ||
762 | case IW_MODE_INFRA: | ||
763 | if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != | ||
764 | IEEE80211_FCTL_FROMDS || | ||
765 | memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) != 0) | ||
766 | return 0; | ||
767 | break; | ||
768 | default: | ||
769 | ZD_ASSERT(ieee->iw_mode != IW_MODE_MONITOR); | ||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 || | ||
774 | is_multicast_ether_addr(hdr->addr1) || | ||
775 | (netdev->flags & IFF_PROMISC); | ||
776 | } | ||
777 | |||
778 | /* Filters receiving packets. If it returns 1 send it to ieee80211_rx, if 0 | ||
779 | * return. If an error is detected -EINVAL is returned. ieee80211_rx_mgt() is | ||
780 | * called here. | ||
781 | * | ||
782 | * It has been based on ieee80211_rx_any. | ||
783 | */ | ||
784 | static int filter_rx(struct ieee80211_device *ieee, | ||
785 | const u8 *buffer, unsigned int length, | ||
786 | struct ieee80211_rx_stats *stats) | ||
787 | { | ||
788 | struct ieee80211_hdr_4addr *hdr; | ||
789 | u16 fc; | ||
790 | |||
791 | if (ieee->iw_mode == IW_MODE_MONITOR) | ||
792 | return 1; | ||
793 | |||
794 | hdr = (struct ieee80211_hdr_4addr *)buffer; | ||
795 | fc = le16_to_cpu(hdr->frame_ctl); | ||
796 | if ((fc & IEEE80211_FCTL_VERS) != 0) | ||
797 | return -EINVAL; | ||
798 | |||
799 | switch (WLAN_FC_GET_TYPE(fc)) { | ||
800 | case IEEE80211_FTYPE_MGMT: | ||
801 | if (length < sizeof(struct ieee80211_hdr_3addr)) | ||
802 | return -EINVAL; | ||
803 | ieee80211_rx_mgt(ieee, hdr, stats); | ||
804 | return 0; | ||
805 | case IEEE80211_FTYPE_CTL: | ||
806 | /* Ignore invalid short buffers */ | ||
807 | return 0; | ||
808 | case IEEE80211_FTYPE_DATA: | ||
809 | if (length < sizeof(struct ieee80211_hdr_3addr)) | ||
810 | return -EINVAL; | ||
811 | return is_data_packet_for_us(ieee, hdr); | ||
812 | } | ||
813 | |||
814 | return -EINVAL; | ||
815 | } | ||
816 | |||
817 | static void update_qual_rssi(struct zd_mac *mac, u8 qual_percent, u8 rssi) | ||
818 | { | ||
819 | unsigned long flags; | ||
820 | |||
821 | spin_lock_irqsave(&mac->lock, flags); | ||
822 | mac->qual_average = (7 * mac->qual_average + qual_percent) / 8; | ||
823 | mac->rssi_average = (7 * mac->rssi_average + rssi) / 8; | ||
824 | spin_unlock_irqrestore(&mac->lock, flags); | ||
825 | } | ||
826 | |||
827 | static int fill_rx_stats(struct ieee80211_rx_stats *stats, | ||
828 | const struct rx_status **pstatus, | ||
829 | struct zd_mac *mac, | ||
830 | const u8 *buffer, unsigned int length) | ||
831 | { | ||
832 | const struct rx_status *status; | ||
833 | |||
834 | *pstatus = status = zd_tail(buffer, length, sizeof(struct rx_status)); | ||
835 | if (status->frame_status & ZD_RX_ERROR) { | ||
836 | /* FIXME: update? */ | ||
837 | return -EINVAL; | ||
838 | } | ||
839 | memset(stats, 0, sizeof(struct ieee80211_rx_stats)); | ||
840 | stats->len = length - (ZD_PLCP_HEADER_SIZE + IEEE80211_FCS_LEN + | ||
841 | + sizeof(struct rx_status)); | ||
842 | /* FIXME: 802.11a */ | ||
843 | stats->freq = IEEE80211_24GHZ_BAND; | ||
844 | stats->received_channel = _zd_chip_get_channel(&mac->chip); | ||
845 | stats->rssi = zd_rx_strength_percent(status->signal_strength); | ||
846 | stats->signal = zd_rx_qual_percent(buffer, | ||
847 | length - sizeof(struct rx_status), | ||
848 | status); | ||
849 | stats->mask = IEEE80211_STATMASK_RSSI | IEEE80211_STATMASK_SIGNAL; | ||
850 | stats->rate = zd_rx_rate(buffer, status); | ||
851 | if (stats->rate) | ||
852 | stats->mask |= IEEE80211_STATMASK_RATE; | ||
853 | |||
854 | update_qual_rssi(mac, stats->signal, stats->rssi); | ||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length) | ||
859 | { | ||
860 | int r; | ||
861 | struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); | ||
862 | struct ieee80211_rx_stats stats; | ||
863 | const struct rx_status *status; | ||
864 | struct sk_buff *skb; | ||
865 | |||
866 | if (length < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN + | ||
867 | IEEE80211_FCS_LEN + sizeof(struct rx_status)) | ||
868 | return -EINVAL; | ||
869 | |||
870 | r = fill_rx_stats(&stats, &status, mac, buffer, length); | ||
871 | if (r) | ||
872 | return r; | ||
873 | |||
874 | length -= ZD_PLCP_HEADER_SIZE+IEEE80211_FCS_LEN+ | ||
875 | sizeof(struct rx_status); | ||
876 | buffer += ZD_PLCP_HEADER_SIZE; | ||
877 | |||
878 | r = filter_rx(ieee, buffer, length, &stats); | ||
879 | if (r <= 0) | ||
880 | return r; | ||
881 | |||
882 | skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length); | ||
883 | if (!skb) | ||
884 | return -ENOMEM; | ||
885 | if (ieee->iw_mode == IW_MODE_MONITOR) | ||
886 | fill_rt_header(skb_put(skb, sizeof(struct zd_rt_hdr)), mac, | ||
887 | &stats, status); | ||
888 | memcpy(skb_put(skb, length), buffer, length); | ||
889 | |||
890 | r = ieee80211_rx(ieee, skb, &stats); | ||
891 | if (!r) { | ||
892 | ZD_ASSERT(in_irq()); | ||
893 | dev_kfree_skb_irq(skb); | ||
894 | } | ||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | static int netdev_tx(struct ieee80211_txb *txb, struct net_device *netdev, | ||
899 | int pri) | ||
900 | { | ||
901 | return zd_mac_tx(zd_netdev_mac(netdev), txb, pri); | ||
902 | } | ||
903 | |||
904 | static void set_security(struct net_device *netdev, | ||
905 | struct ieee80211_security *sec) | ||
906 | { | ||
907 | struct ieee80211_device *ieee = zd_netdev_ieee80211(netdev); | ||
908 | struct ieee80211_security *secinfo = &ieee->sec; | ||
909 | int keyidx; | ||
910 | |||
911 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n"); | ||
912 | |||
913 | for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) | ||
914 | if (sec->flags & (1<<keyidx)) { | ||
915 | secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx]; | ||
916 | secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx]; | ||
917 | memcpy(secinfo->keys[keyidx], sec->keys[keyidx], | ||
918 | SCM_KEY_LEN); | ||
919 | } | ||
920 | |||
921 | if (sec->flags & SEC_ACTIVE_KEY) { | ||
922 | secinfo->active_key = sec->active_key; | ||
923 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
924 | " .active_key = %d\n", sec->active_key); | ||
925 | } | ||
926 | if (sec->flags & SEC_UNICAST_GROUP) { | ||
927 | secinfo->unicast_uses_group = sec->unicast_uses_group; | ||
928 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
929 | " .unicast_uses_group = %d\n", | ||
930 | sec->unicast_uses_group); | ||
931 | } | ||
932 | if (sec->flags & SEC_LEVEL) { | ||
933 | secinfo->level = sec->level; | ||
934 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
935 | " .level = %d\n", sec->level); | ||
936 | } | ||
937 | if (sec->flags & SEC_ENABLED) { | ||
938 | secinfo->enabled = sec->enabled; | ||
939 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
940 | " .enabled = %d\n", sec->enabled); | ||
941 | } | ||
942 | if (sec->flags & SEC_ENCRYPT) { | ||
943 | secinfo->encrypt = sec->encrypt; | ||
944 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
945 | " .encrypt = %d\n", sec->encrypt); | ||
946 | } | ||
947 | if (sec->flags & SEC_AUTH_MODE) { | ||
948 | secinfo->auth_mode = sec->auth_mode; | ||
949 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
950 | " .auth_mode = %d\n", sec->auth_mode); | ||
951 | } | ||
952 | } | ||
953 | |||
954 | static void ieee_init(struct ieee80211_device *ieee) | ||
955 | { | ||
956 | ieee->mode = IEEE_B | IEEE_G; | ||
957 | ieee->freq_band = IEEE80211_24GHZ_BAND; | ||
958 | ieee->modulation = IEEE80211_OFDM_MODULATION | IEEE80211_CCK_MODULATION; | ||
959 | ieee->tx_headroom = sizeof(struct zd_ctrlset); | ||
960 | ieee->set_security = set_security; | ||
961 | ieee->hard_start_xmit = netdev_tx; | ||
962 | |||
963 | /* Software encryption/decryption for now */ | ||
964 | ieee->host_build_iv = 0; | ||
965 | ieee->host_encrypt = 1; | ||
966 | ieee->host_decrypt = 1; | ||
967 | |||
968 | /* FIXME: default to managed mode, until ieee80211 and zd1211rw can | ||
969 | * correctly support AUTO */ | ||
970 | ieee->iw_mode = IW_MODE_INFRA; | ||
971 | } | ||
972 | |||
973 | static void softmac_init(struct ieee80211softmac_device *sm) | ||
974 | { | ||
975 | sm->set_channel = set_channel; | ||
976 | } | ||
977 | |||
978 | struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) | ||
979 | { | ||
980 | struct zd_mac *mac = zd_netdev_mac(ndev); | ||
981 | struct iw_statistics *iw_stats = &mac->iw_stats; | ||
982 | |||
983 | memset(iw_stats, 0, sizeof(struct iw_statistics)); | ||
984 | /* We are not setting the status, because ieee->state is not updated | ||
985 | * at all and this driver doesn't track authentication state. | ||
986 | */ | ||
987 | spin_lock_irq(&mac->lock); | ||
988 | iw_stats->qual.qual = mac->qual_average; | ||
989 | iw_stats->qual.level = mac->rssi_average; | ||
990 | iw_stats->qual.updated = IW_QUAL_QUAL_UPDATED|IW_QUAL_LEVEL_UPDATED| | ||
991 | IW_QUAL_NOISE_INVALID; | ||
992 | spin_unlock_irq(&mac->lock); | ||
993 | /* TODO: update counter */ | ||
994 | return iw_stats; | ||
995 | } | ||
996 | |||
997 | #ifdef DEBUG | ||
998 | static const char* decryption_types[] = { | ||
999 | [ZD_RX_NO_WEP] = "none", | ||
1000 | [ZD_RX_WEP64] = "WEP64", | ||
1001 | [ZD_RX_TKIP] = "TKIP", | ||
1002 | [ZD_RX_AES] = "AES", | ||
1003 | [ZD_RX_WEP128] = "WEP128", | ||
1004 | [ZD_RX_WEP256] = "WEP256", | ||
1005 | }; | ||
1006 | |||
1007 | static const char *decryption_type_string(u8 type) | ||
1008 | { | ||
1009 | const char *s; | ||
1010 | |||
1011 | if (type < ARRAY_SIZE(decryption_types)) { | ||
1012 | s = decryption_types[type]; | ||
1013 | } else { | ||
1014 | s = NULL; | ||
1015 | } | ||
1016 | return s ? s : "unknown"; | ||
1017 | } | ||
1018 | |||
1019 | static int is_ofdm(u8 frame_status) | ||
1020 | { | ||
1021 | return (frame_status & ZD_RX_OFDM); | ||
1022 | } | ||
1023 | |||
1024 | void zd_dump_rx_status(const struct rx_status *status) | ||
1025 | { | ||
1026 | const char* modulation; | ||
1027 | u8 quality; | ||
1028 | |||
1029 | if (is_ofdm(status->frame_status)) { | ||
1030 | modulation = "ofdm"; | ||
1031 | quality = status->signal_quality_ofdm; | ||
1032 | } else { | ||
1033 | modulation = "cck"; | ||
1034 | quality = status->signal_quality_cck; | ||
1035 | } | ||
1036 | pr_debug("rx status %s strength %#04x qual %#04x decryption %s\n", | ||
1037 | modulation, status->signal_strength, quality, | ||
1038 | decryption_type_string(status->decryption_type)); | ||
1039 | if (status->frame_status & ZD_RX_ERROR) { | ||
1040 | pr_debug("rx error %s%s%s%s%s%s\n", | ||
1041 | (status->frame_status & ZD_RX_TIMEOUT_ERROR) ? | ||
1042 | "timeout " : "", | ||
1043 | (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR) ? | ||
1044 | "fifo " : "", | ||
1045 | (status->frame_status & ZD_RX_DECRYPTION_ERROR) ? | ||
1046 | "decryption " : "", | ||
1047 | (status->frame_status & ZD_RX_CRC32_ERROR) ? | ||
1048 | "crc32 " : "", | ||
1049 | (status->frame_status & ZD_RX_NO_ADDR1_MATCH_ERROR) ? | ||
1050 | "addr1 " : "", | ||
1051 | (status->frame_status & ZD_RX_CRC16_ERROR) ? | ||
1052 | "crc16" : ""); | ||
1053 | } | ||
1054 | } | ||
1055 | #endif /* DEBUG */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h new file mode 100644 index 000000000000..71e382c589ee --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
@@ -0,0 +1,190 @@ | |||
1 | /* zd_mac.c | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef _ZD_MAC_H | ||
19 | #define _ZD_MAC_H | ||
20 | |||
21 | #include <linux/wireless.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <net/ieee80211.h> | ||
24 | #include <net/ieee80211softmac.h> | ||
25 | |||
26 | #include "zd_chip.h" | ||
27 | #include "zd_netdev.h" | ||
28 | |||
29 | struct zd_ctrlset { | ||
30 | u8 modulation; | ||
31 | __le16 tx_length; | ||
32 | u8 control; | ||
33 | /* stores only the difference to tx_length on ZD1211B */ | ||
34 | __le16 packet_length; | ||
35 | __le16 current_length; | ||
36 | u8 service; | ||
37 | __le16 next_frame_length; | ||
38 | } __attribute__((packed)); | ||
39 | |||
40 | #define ZD_CS_RESERVED_SIZE 25 | ||
41 | |||
42 | /* zd_crtlset field modulation */ | ||
43 | #define ZD_CS_RATE_MASK 0x0f | ||
44 | #define ZD_CS_TYPE_MASK 0x10 | ||
45 | #define ZD_CS_RATE(modulation) ((modulation) & ZD_CS_RATE_MASK) | ||
46 | #define ZD_CS_TYPE(modulation) ((modulation) & ZD_CS_TYPE_MASK) | ||
47 | |||
48 | #define ZD_CS_CCK 0x00 | ||
49 | #define ZD_CS_OFDM 0x10 | ||
50 | |||
51 | #define ZD_CS_CCK_RATE_1M 0x00 | ||
52 | #define ZD_CS_CCK_RATE_2M 0x01 | ||
53 | #define ZD_CS_CCK_RATE_5_5M 0x02 | ||
54 | #define ZD_CS_CCK_RATE_11M 0x03 | ||
55 | /* The rates for OFDM are encoded as in the PLCP header. Use ZD_OFDM_RATE_*. | ||
56 | */ | ||
57 | |||
58 | /* bit 5 is preamble (when in CCK mode), or a/g selection (when in OFDM mode) */ | ||
59 | #define ZD_CS_CCK_PREA_LONG 0x00 | ||
60 | #define ZD_CS_CCK_PREA_SHORT 0x20 | ||
61 | #define ZD_CS_OFDM_MODE_11G 0x00 | ||
62 | #define ZD_CS_OFDM_MODE_11A 0x20 | ||
63 | |||
64 | /* zd_ctrlset control field */ | ||
65 | #define ZD_CS_NEED_RANDOM_BACKOFF 0x01 | ||
66 | #define ZD_CS_MULTICAST 0x02 | ||
67 | |||
68 | #define ZD_CS_FRAME_TYPE_MASK 0x0c | ||
69 | #define ZD_CS_DATA_FRAME 0x00 | ||
70 | #define ZD_CS_PS_POLL_FRAME 0x04 | ||
71 | #define ZD_CS_MANAGEMENT_FRAME 0x08 | ||
72 | #define ZD_CS_NO_SEQUENCE_CTL_FRAME 0x0c | ||
73 | |||
74 | #define ZD_CS_WAKE_DESTINATION 0x10 | ||
75 | #define ZD_CS_RTS 0x20 | ||
76 | #define ZD_CS_ENCRYPT 0x40 | ||
77 | #define ZD_CS_SELF_CTS 0x80 | ||
78 | |||
79 | /* Incoming frames are prepended by a PLCP header */ | ||
80 | #define ZD_PLCP_HEADER_SIZE 5 | ||
81 | |||
82 | struct rx_length_info { | ||
83 | __le16 length[3]; | ||
84 | __le16 tag; | ||
85 | } __attribute__((packed)); | ||
86 | |||
87 | #define RX_LENGTH_INFO_TAG 0x697e | ||
88 | |||
89 | struct rx_status { | ||
90 | /* rssi */ | ||
91 | u8 signal_strength; | ||
92 | u8 signal_quality_cck; | ||
93 | u8 signal_quality_ofdm; | ||
94 | u8 decryption_type; | ||
95 | u8 frame_status; | ||
96 | } __attribute__((packed)); | ||
97 | |||
98 | /* rx_status field decryption_type */ | ||
99 | #define ZD_RX_NO_WEP 0 | ||
100 | #define ZD_RX_WEP64 1 | ||
101 | #define ZD_RX_TKIP 2 | ||
102 | #define ZD_RX_AES 4 | ||
103 | #define ZD_RX_WEP128 5 | ||
104 | #define ZD_RX_WEP256 6 | ||
105 | |||
106 | /* rx_status field frame_status */ | ||
107 | #define ZD_RX_FRAME_MODULATION_MASK 0x01 | ||
108 | #define ZD_RX_CCK 0x00 | ||
109 | #define ZD_RX_OFDM 0x01 | ||
110 | |||
111 | #define ZD_RX_TIMEOUT_ERROR 0x02 | ||
112 | #define ZD_RX_FIFO_OVERRUN_ERROR 0x04 | ||
113 | #define ZD_RX_DECRYPTION_ERROR 0x08 | ||
114 | #define ZD_RX_CRC32_ERROR 0x10 | ||
115 | #define ZD_RX_NO_ADDR1_MATCH_ERROR 0x20 | ||
116 | #define ZD_RX_CRC16_ERROR 0x40 | ||
117 | #define ZD_RX_ERROR 0x80 | ||
118 | |||
119 | enum mac_flags { | ||
120 | MAC_FIXED_CHANNEL = 0x01, | ||
121 | }; | ||
122 | |||
123 | struct zd_mac { | ||
124 | struct net_device *netdev; | ||
125 | struct zd_chip chip; | ||
126 | spinlock_t lock; | ||
127 | /* Unlocked reading possible */ | ||
128 | struct iw_statistics iw_stats; | ||
129 | u8 qual_average; | ||
130 | u8 rssi_average; | ||
131 | u8 regdomain; | ||
132 | u8 default_regdomain; | ||
133 | u8 requested_channel; | ||
134 | }; | ||
135 | |||
136 | static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac) | ||
137 | { | ||
138 | return zd_netdev_ieee80211(mac->netdev); | ||
139 | } | ||
140 | |||
141 | static inline struct zd_mac *zd_netdev_mac(struct net_device *netdev) | ||
142 | { | ||
143 | return ieee80211softmac_priv(netdev); | ||
144 | } | ||
145 | |||
146 | static inline struct zd_mac *zd_chip_to_mac(struct zd_chip *chip) | ||
147 | { | ||
148 | return container_of(chip, struct zd_mac, chip); | ||
149 | } | ||
150 | |||
151 | static inline struct zd_mac *zd_usb_to_mac(struct zd_usb *usb) | ||
152 | { | ||
153 | return zd_chip_to_mac(zd_usb_to_chip(usb)); | ||
154 | } | ||
155 | |||
156 | #define zd_mac_dev(mac) (zd_chip_dev(&(mac)->chip)) | ||
157 | |||
158 | int zd_mac_init(struct zd_mac *mac, | ||
159 | struct net_device *netdev, | ||
160 | struct usb_interface *intf); | ||
161 | void zd_mac_clear(struct zd_mac *mac); | ||
162 | |||
163 | int zd_mac_init_hw(struct zd_mac *mac, u8 device_type); | ||
164 | |||
165 | int zd_mac_open(struct net_device *netdev); | ||
166 | int zd_mac_stop(struct net_device *netdev); | ||
167 | int zd_mac_set_mac_address(struct net_device *dev, void *p); | ||
168 | |||
169 | int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length); | ||
170 | |||
171 | int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain); | ||
172 | u8 zd_mac_get_regdomain(struct zd_mac *zd_mac); | ||
173 | |||
174 | int zd_mac_request_channel(struct zd_mac *mac, u8 channel); | ||
175 | int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags); | ||
176 | |||
177 | int zd_mac_set_mode(struct zd_mac *mac, u32 mode); | ||
178 | int zd_mac_get_mode(struct zd_mac *mac, u32 *mode); | ||
179 | |||
180 | int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range); | ||
181 | |||
182 | struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev); | ||
183 | |||
184 | #ifdef DEBUG | ||
185 | void zd_dump_rx_status(const struct rx_status *status); | ||
186 | #else | ||
187 | #define zd_dump_rx_status(status) | ||
188 | #endif /* DEBUG */ | ||
189 | |||
190 | #endif /* _ZD_MAC_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c new file mode 100644 index 000000000000..9df232c2c863 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_netdev.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* zd_netdev.c | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/etherdevice.h> | ||
20 | #include <linux/skbuff.h> | ||
21 | #include <net/ieee80211.h> | ||
22 | #include <net/ieee80211softmac.h> | ||
23 | #include <net/ieee80211softmac_wx.h> | ||
24 | #include <net/iw_handler.h> | ||
25 | |||
26 | #include "zd_def.h" | ||
27 | #include "zd_netdev.h" | ||
28 | #include "zd_mac.h" | ||
29 | #include "zd_ieee80211.h" | ||
30 | |||
31 | /* Region 0 means reset regdomain to default. */ | ||
32 | static int zd_set_regdomain(struct net_device *netdev, | ||
33 | struct iw_request_info *info, | ||
34 | union iwreq_data *req, char *extra) | ||
35 | { | ||
36 | const u8 *regdomain = (u8 *)req; | ||
37 | return zd_mac_set_regdomain(zd_netdev_mac(netdev), *regdomain); | ||
38 | } | ||
39 | |||
40 | static int zd_get_regdomain(struct net_device *netdev, | ||
41 | struct iw_request_info *info, | ||
42 | union iwreq_data *req, char *extra) | ||
43 | { | ||
44 | u8 *regdomain = (u8 *)req; | ||
45 | if (!regdomain) | ||
46 | return -EINVAL; | ||
47 | *regdomain = zd_mac_get_regdomain(zd_netdev_mac(netdev)); | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static const struct iw_priv_args zd_priv_args[] = { | ||
52 | { | ||
53 | .cmd = ZD_PRIV_SET_REGDOMAIN, | ||
54 | .set_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, | ||
55 | .name = "set_regdomain", | ||
56 | }, | ||
57 | { | ||
58 | .cmd = ZD_PRIV_GET_REGDOMAIN, | ||
59 | .get_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, | ||
60 | .name = "get_regdomain", | ||
61 | }, | ||
62 | }; | ||
63 | |||
64 | #define PRIV_OFFSET(x) [(x)-SIOCIWFIRSTPRIV] | ||
65 | |||
66 | static const iw_handler zd_priv_handler[] = { | ||
67 | PRIV_OFFSET(ZD_PRIV_SET_REGDOMAIN) = zd_set_regdomain, | ||
68 | PRIV_OFFSET(ZD_PRIV_GET_REGDOMAIN) = zd_get_regdomain, | ||
69 | }; | ||
70 | |||
71 | static int iw_get_name(struct net_device *netdev, | ||
72 | struct iw_request_info *info, | ||
73 | union iwreq_data *req, char *extra) | ||
74 | { | ||
75 | /* FIXME: check whether 802.11a will also supported, add also | ||
76 | * zd1211B, if we support it. | ||
77 | */ | ||
78 | strlcpy(req->name, "802.11g zd1211", IFNAMSIZ); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int iw_set_freq(struct net_device *netdev, | ||
83 | struct iw_request_info *info, | ||
84 | union iwreq_data *req, char *extra) | ||
85 | { | ||
86 | int r; | ||
87 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
88 | struct iw_freq *freq = &req->freq; | ||
89 | u8 channel; | ||
90 | |||
91 | r = zd_find_channel(&channel, freq); | ||
92 | if (r < 0) | ||
93 | return r; | ||
94 | r = zd_mac_request_channel(mac, channel); | ||
95 | return r; | ||
96 | } | ||
97 | |||
98 | static int iw_get_freq(struct net_device *netdev, | ||
99 | struct iw_request_info *info, | ||
100 | union iwreq_data *req, char *extra) | ||
101 | { | ||
102 | int r; | ||
103 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
104 | struct iw_freq *freq = &req->freq; | ||
105 | u8 channel; | ||
106 | u8 flags; | ||
107 | |||
108 | r = zd_mac_get_channel(mac, &channel, &flags); | ||
109 | if (r) | ||
110 | return r; | ||
111 | |||
112 | freq->flags = (flags & MAC_FIXED_CHANNEL) ? | ||
113 | IW_FREQ_FIXED : IW_FREQ_AUTO; | ||
114 | dev_dbg_f(zd_mac_dev(mac), "channel %s\n", | ||
115 | (flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto"); | ||
116 | return zd_channel_to_freq(freq, channel); | ||
117 | } | ||
118 | |||
119 | static int iw_set_mode(struct net_device *netdev, | ||
120 | struct iw_request_info *info, | ||
121 | union iwreq_data *req, char *extra) | ||
122 | { | ||
123 | return zd_mac_set_mode(zd_netdev_mac(netdev), req->mode); | ||
124 | } | ||
125 | |||
126 | static int iw_get_mode(struct net_device *netdev, | ||
127 | struct iw_request_info *info, | ||
128 | union iwreq_data *req, char *extra) | ||
129 | { | ||
130 | return zd_mac_get_mode(zd_netdev_mac(netdev), &req->mode); | ||
131 | } | ||
132 | |||
133 | static int iw_get_range(struct net_device *netdev, | ||
134 | struct iw_request_info *info, | ||
135 | union iwreq_data *req, char *extra) | ||
136 | { | ||
137 | struct iw_range *range = (struct iw_range *)extra; | ||
138 | |||
139 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n"); | ||
140 | req->data.length = sizeof(*range); | ||
141 | return zd_mac_get_range(zd_netdev_mac(netdev), range); | ||
142 | } | ||
143 | |||
144 | static int iw_set_encode(struct net_device *netdev, | ||
145 | struct iw_request_info *info, | ||
146 | union iwreq_data *data, | ||
147 | char *extra) | ||
148 | { | ||
149 | return ieee80211_wx_set_encode(zd_netdev_ieee80211(netdev), info, | ||
150 | data, extra); | ||
151 | } | ||
152 | |||
153 | static int iw_get_encode(struct net_device *netdev, | ||
154 | struct iw_request_info *info, | ||
155 | union iwreq_data *data, | ||
156 | char *extra) | ||
157 | { | ||
158 | return ieee80211_wx_get_encode(zd_netdev_ieee80211(netdev), info, | ||
159 | data, extra); | ||
160 | } | ||
161 | |||
162 | static int iw_set_encodeext(struct net_device *netdev, | ||
163 | struct iw_request_info *info, | ||
164 | union iwreq_data *data, | ||
165 | char *extra) | ||
166 | { | ||
167 | return ieee80211_wx_set_encodeext(zd_netdev_ieee80211(netdev), info, | ||
168 | data, extra); | ||
169 | } | ||
170 | |||
171 | static int iw_get_encodeext(struct net_device *netdev, | ||
172 | struct iw_request_info *info, | ||
173 | union iwreq_data *data, | ||
174 | char *extra) | ||
175 | { | ||
176 | return ieee80211_wx_get_encodeext(zd_netdev_ieee80211(netdev), info, | ||
177 | data, extra); | ||
178 | } | ||
179 | |||
180 | #define WX(x) [(x)-SIOCIWFIRST] | ||
181 | |||
182 | static const iw_handler zd_standard_iw_handlers[] = { | ||
183 | WX(SIOCGIWNAME) = iw_get_name, | ||
184 | WX(SIOCSIWFREQ) = iw_set_freq, | ||
185 | WX(SIOCGIWFREQ) = iw_get_freq, | ||
186 | WX(SIOCSIWMODE) = iw_set_mode, | ||
187 | WX(SIOCGIWMODE) = iw_get_mode, | ||
188 | WX(SIOCGIWRANGE) = iw_get_range, | ||
189 | WX(SIOCSIWENCODE) = iw_set_encode, | ||
190 | WX(SIOCGIWENCODE) = iw_get_encode, | ||
191 | WX(SIOCSIWENCODEEXT) = iw_set_encodeext, | ||
192 | WX(SIOCGIWENCODEEXT) = iw_get_encodeext, | ||
193 | WX(SIOCSIWAUTH) = ieee80211_wx_set_auth, | ||
194 | WX(SIOCGIWAUTH) = ieee80211_wx_get_auth, | ||
195 | WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan, | ||
196 | WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results, | ||
197 | WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid, | ||
198 | WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid, | ||
199 | WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap, | ||
200 | WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap, | ||
201 | WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate, | ||
202 | WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate, | ||
203 | WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie, | ||
204 | WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie, | ||
205 | WX(SIOCSIWMLME) = ieee80211softmac_wx_set_mlme, | ||
206 | }; | ||
207 | |||
208 | static const struct iw_handler_def iw_handler_def = { | ||
209 | .standard = zd_standard_iw_handlers, | ||
210 | .num_standard = ARRAY_SIZE(zd_standard_iw_handlers), | ||
211 | .private = zd_priv_handler, | ||
212 | .num_private = ARRAY_SIZE(zd_priv_handler), | ||
213 | .private_args = zd_priv_args, | ||
214 | .num_private_args = ARRAY_SIZE(zd_priv_args), | ||
215 | .get_wireless_stats = zd_mac_get_wireless_stats, | ||
216 | }; | ||
217 | |||
218 | struct net_device *zd_netdev_alloc(struct usb_interface *intf) | ||
219 | { | ||
220 | int r; | ||
221 | struct net_device *netdev; | ||
222 | struct zd_mac *mac; | ||
223 | |||
224 | netdev = alloc_ieee80211softmac(sizeof(struct zd_mac)); | ||
225 | if (!netdev) { | ||
226 | dev_dbg_f(&intf->dev, "out of memory\n"); | ||
227 | return NULL; | ||
228 | } | ||
229 | |||
230 | mac = zd_netdev_mac(netdev); | ||
231 | r = zd_mac_init(mac, netdev, intf); | ||
232 | if (r) { | ||
233 | usb_set_intfdata(intf, NULL); | ||
234 | free_ieee80211(netdev); | ||
235 | return NULL; | ||
236 | } | ||
237 | |||
238 | SET_MODULE_OWNER(netdev); | ||
239 | SET_NETDEV_DEV(netdev, &intf->dev); | ||
240 | |||
241 | dev_dbg_f(&intf->dev, "netdev->flags %#06hx\n", netdev->flags); | ||
242 | dev_dbg_f(&intf->dev, "netdev->features %#010lx\n", netdev->features); | ||
243 | |||
244 | netdev->open = zd_mac_open; | ||
245 | netdev->stop = zd_mac_stop; | ||
246 | /* netdev->get_stats = */ | ||
247 | /* netdev->set_multicast_list = */ | ||
248 | netdev->set_mac_address = zd_mac_set_mac_address; | ||
249 | netdev->wireless_handlers = &iw_handler_def; | ||
250 | /* netdev->ethtool_ops = */ | ||
251 | |||
252 | return netdev; | ||
253 | } | ||
254 | |||
255 | void zd_netdev_free(struct net_device *netdev) | ||
256 | { | ||
257 | if (!netdev) | ||
258 | return; | ||
259 | |||
260 | zd_mac_clear(zd_netdev_mac(netdev)); | ||
261 | free_ieee80211(netdev); | ||
262 | } | ||
263 | |||
264 | void zd_netdev_disconnect(struct net_device *netdev) | ||
265 | { | ||
266 | unregister_netdev(netdev); | ||
267 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.h b/drivers/net/wireless/zd1211rw/zd_netdev.h new file mode 100644 index 000000000000..374a957073c1 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_netdev.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* zd_netdev.h: Header for net device related functions. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef _ZD_NETDEV_H | ||
19 | #define _ZD_NETDEV_H | ||
20 | |||
21 | #include <linux/usb.h> | ||
22 | #include <linux/netdevice.h> | ||
23 | #include <net/ieee80211.h> | ||
24 | |||
25 | #define ZD_PRIV_SET_REGDOMAIN (SIOCIWFIRSTPRIV) | ||
26 | #define ZD_PRIV_GET_REGDOMAIN (SIOCIWFIRSTPRIV+1) | ||
27 | |||
28 | static inline struct ieee80211_device *zd_netdev_ieee80211( | ||
29 | struct net_device *ndev) | ||
30 | { | ||
31 | return netdev_priv(ndev); | ||
32 | } | ||
33 | |||
34 | static inline struct net_device *zd_ieee80211_to_netdev( | ||
35 | struct ieee80211_device *ieee) | ||
36 | { | ||
37 | return ieee->dev; | ||
38 | } | ||
39 | |||
40 | struct net_device *zd_netdev_alloc(struct usb_interface *intf); | ||
41 | void zd_netdev_free(struct net_device *netdev); | ||
42 | |||
43 | void zd_netdev_disconnect(struct net_device *netdev); | ||
44 | |||
45 | #endif /* _ZD_NETDEV_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c new file mode 100644 index 000000000000..d3770d2c61bc --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* zd_rf.c | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #include <linux/errno.h> | ||
19 | #include <linux/string.h> | ||
20 | |||
21 | #include "zd_def.h" | ||
22 | #include "zd_rf.h" | ||
23 | #include "zd_ieee80211.h" | ||
24 | #include "zd_chip.h" | ||
25 | |||
26 | static const char *rfs[] = { | ||
27 | [0] = "unknown RF0", | ||
28 | [1] = "unknown RF1", | ||
29 | [UW2451_RF] = "UW2451_RF", | ||
30 | [UCHIP_RF] = "UCHIP_RF", | ||
31 | [AL2230_RF] = "AL2230_RF", | ||
32 | [AL7230B_RF] = "AL7230B_RF", | ||
33 | [THETA_RF] = "THETA_RF", | ||
34 | [AL2210_RF] = "AL2210_RF", | ||
35 | [MAXIM_NEW_RF] = "MAXIM_NEW_RF", | ||
36 | [UW2453_RF] = "UW2453_RF", | ||
37 | [AL2230S_RF] = "AL2230S_RF", | ||
38 | [RALINK_RF] = "RALINK_RF", | ||
39 | [INTERSIL_RF] = "INTERSIL_RF", | ||
40 | [RF2959_RF] = "RF2959_RF", | ||
41 | [MAXIM_NEW2_RF] = "MAXIM_NEW2_RF", | ||
42 | [PHILIPS_RF] = "PHILIPS_RF", | ||
43 | }; | ||
44 | |||
45 | const char *zd_rf_name(u8 type) | ||
46 | { | ||
47 | if (type & 0xf0) | ||
48 | type = 0; | ||
49 | return rfs[type]; | ||
50 | } | ||
51 | |||
52 | void zd_rf_init(struct zd_rf *rf) | ||
53 | { | ||
54 | memset(rf, 0, sizeof(*rf)); | ||
55 | } | ||
56 | |||
57 | void zd_rf_clear(struct zd_rf *rf) | ||
58 | { | ||
59 | memset(rf, 0, sizeof(*rf)); | ||
60 | } | ||
61 | |||
62 | int zd_rf_init_hw(struct zd_rf *rf, u8 type) | ||
63 | { | ||
64 | int r, t; | ||
65 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
66 | |||
67 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
68 | switch (type) { | ||
69 | case RF2959_RF: | ||
70 | r = zd_rf_init_rf2959(rf); | ||
71 | if (r) | ||
72 | return r; | ||
73 | break; | ||
74 | case AL2230_RF: | ||
75 | r = zd_rf_init_al2230(rf); | ||
76 | if (r) | ||
77 | return r; | ||
78 | break; | ||
79 | default: | ||
80 | dev_err(zd_chip_dev(chip), | ||
81 | "RF %s %#x is not supported\n", zd_rf_name(type), type); | ||
82 | rf->type = 0; | ||
83 | return -ENODEV; | ||
84 | } | ||
85 | |||
86 | rf->type = type; | ||
87 | |||
88 | r = zd_chip_lock_phy_regs(chip); | ||
89 | if (r) | ||
90 | return r; | ||
91 | t = rf->init_hw(rf); | ||
92 | r = zd_chip_unlock_phy_regs(chip); | ||
93 | if (t) | ||
94 | r = t; | ||
95 | return r; | ||
96 | } | ||
97 | |||
98 | int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size) | ||
99 | { | ||
100 | return scnprintf(buffer, size, "%s", zd_rf_name(rf->type)); | ||
101 | } | ||
102 | |||
103 | int zd_rf_set_channel(struct zd_rf *rf, u8 channel) | ||
104 | { | ||
105 | int r; | ||
106 | |||
107 | ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex)); | ||
108 | if (channel < MIN_CHANNEL24) | ||
109 | return -EINVAL; | ||
110 | if (channel > MAX_CHANNEL24) | ||
111 | return -EINVAL; | ||
112 | dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel); | ||
113 | |||
114 | r = rf->set_channel(rf, channel); | ||
115 | if (r >= 0) | ||
116 | rf->channel = channel; | ||
117 | return r; | ||
118 | } | ||
119 | |||
120 | int zd_switch_radio_on(struct zd_rf *rf) | ||
121 | { | ||
122 | int r, t; | ||
123 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
124 | |||
125 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
126 | r = zd_chip_lock_phy_regs(chip); | ||
127 | if (r) | ||
128 | return r; | ||
129 | t = rf->switch_radio_on(rf); | ||
130 | r = zd_chip_unlock_phy_regs(chip); | ||
131 | if (t) | ||
132 | r = t; | ||
133 | return r; | ||
134 | } | ||
135 | |||
136 | int zd_switch_radio_off(struct zd_rf *rf) | ||
137 | { | ||
138 | int r, t; | ||
139 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
140 | |||
141 | /* TODO: move phy regs handling to zd_chip */ | ||
142 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
143 | r = zd_chip_lock_phy_regs(chip); | ||
144 | if (r) | ||
145 | return r; | ||
146 | t = rf->switch_radio_off(rf); | ||
147 | r = zd_chip_unlock_phy_regs(chip); | ||
148 | if (t) | ||
149 | r = t; | ||
150 | return r; | ||
151 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h new file mode 100644 index 000000000000..ea30f693fcc8 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* zd_rf.h | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef _ZD_RF_H | ||
19 | #define _ZD_RF_H | ||
20 | |||
21 | #include "zd_types.h" | ||
22 | |||
23 | #define UW2451_RF 0x2 | ||
24 | #define UCHIP_RF 0x3 | ||
25 | #define AL2230_RF 0x4 | ||
26 | #define AL7230B_RF 0x5 /* a,b,g */ | ||
27 | #define THETA_RF 0x6 | ||
28 | #define AL2210_RF 0x7 | ||
29 | #define MAXIM_NEW_RF 0x8 | ||
30 | #define UW2453_RF 0x9 | ||
31 | #define AL2230S_RF 0xa | ||
32 | #define RALINK_RF 0xb | ||
33 | #define INTERSIL_RF 0xc | ||
34 | #define RF2959_RF 0xd | ||
35 | #define MAXIM_NEW2_RF 0xe | ||
36 | #define PHILIPS_RF 0xf | ||
37 | |||
38 | #define RF_CHANNEL(ch) [(ch)-1] | ||
39 | |||
40 | /* Provides functions of the RF transceiver. */ | ||
41 | |||
42 | enum { | ||
43 | RF_REG_BITS = 6, | ||
44 | RF_VALUE_BITS = 18, | ||
45 | RF_RV_BITS = RF_REG_BITS + RF_VALUE_BITS, | ||
46 | }; | ||
47 | |||
48 | struct zd_rf { | ||
49 | u8 type; | ||
50 | |||
51 | u8 channel; | ||
52 | /* | ||
53 | * Whether this RF should patch the 6M band edge | ||
54 | * (assuming E2P_POD agrees) | ||
55 | */ | ||
56 | u8 patch_6m_band_edge:1; | ||
57 | |||
58 | /* RF-specific functions */ | ||
59 | int (*init_hw)(struct zd_rf *rf); | ||
60 | int (*set_channel)(struct zd_rf *rf, u8 channel); | ||
61 | int (*switch_radio_on)(struct zd_rf *rf); | ||
62 | int (*switch_radio_off)(struct zd_rf *rf); | ||
63 | }; | ||
64 | |||
65 | const char *zd_rf_name(u8 type); | ||
66 | void zd_rf_init(struct zd_rf *rf); | ||
67 | void zd_rf_clear(struct zd_rf *rf); | ||
68 | int zd_rf_init_hw(struct zd_rf *rf, u8 type); | ||
69 | |||
70 | int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size); | ||
71 | |||
72 | int zd_rf_set_channel(struct zd_rf *rf, u8 channel); | ||
73 | |||
74 | int zd_switch_radio_on(struct zd_rf *rf); | ||
75 | int zd_switch_radio_off(struct zd_rf *rf); | ||
76 | |||
77 | /* Functions for individual RF chips */ | ||
78 | |||
79 | int zd_rf_init_rf2959(struct zd_rf *rf); | ||
80 | int zd_rf_init_al2230(struct zd_rf *rf); | ||
81 | |||
82 | #endif /* _ZD_RF_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c new file mode 100644 index 000000000000..0948b25f660d --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c | |||
@@ -0,0 +1,308 @@ | |||
1 | /* zd_rf_al2230.c: Functions for the AL2230 RF controller | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | |||
20 | #include "zd_rf.h" | ||
21 | #include "zd_usb.h" | ||
22 | #include "zd_chip.h" | ||
23 | |||
24 | static const u32 al2230_table[][3] = { | ||
25 | RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, }, | ||
26 | RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, }, | ||
27 | RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, }, | ||
28 | RF_CHANNEL( 4) = { 0x03e790, 0x0b3331, 0x00000d, }, | ||
29 | RF_CHANNEL( 5) = { 0x03f7a0, 0x033331, 0x00000d, }, | ||
30 | RF_CHANNEL( 6) = { 0x03f7a0, 0x0b3331, 0x00000d, }, | ||
31 | RF_CHANNEL( 7) = { 0x03e7a0, 0x033331, 0x00000d, }, | ||
32 | RF_CHANNEL( 8) = { 0x03e7a0, 0x0b3331, 0x00000d, }, | ||
33 | RF_CHANNEL( 9) = { 0x03f7b0, 0x033331, 0x00000d, }, | ||
34 | RF_CHANNEL(10) = { 0x03f7b0, 0x0b3331, 0x00000d, }, | ||
35 | RF_CHANNEL(11) = { 0x03e7b0, 0x033331, 0x00000d, }, | ||
36 | RF_CHANNEL(12) = { 0x03e7b0, 0x0b3331, 0x00000d, }, | ||
37 | RF_CHANNEL(13) = { 0x03f7c0, 0x033331, 0x00000d, }, | ||
38 | RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, }, | ||
39 | }; | ||
40 | |||
41 | static int zd1211_al2230_init_hw(struct zd_rf *rf) | ||
42 | { | ||
43 | int r; | ||
44 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
45 | |||
46 | static const struct zd_ioreq16 ioreqs[] = { | ||
47 | { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, | ||
48 | { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, | ||
49 | { CR44, 0x33 }, { CR106, 0x2a }, { CR107, 0x1a }, | ||
50 | { CR109, 0x09 }, { CR110, 0x27 }, { CR111, 0x2b }, | ||
51 | { CR112, 0x2b }, { CR119, 0x0a }, { CR10, 0x89 }, | ||
52 | /* for newest (3rd cut) AL2300 */ | ||
53 | { CR17, 0x28 }, | ||
54 | { CR26, 0x93 }, { CR34, 0x30 }, | ||
55 | /* for newest (3rd cut) AL2300 */ | ||
56 | { CR35, 0x3e }, | ||
57 | { CR41, 0x24 }, { CR44, 0x32 }, | ||
58 | /* for newest (3rd cut) AL2300 */ | ||
59 | { CR46, 0x96 }, | ||
60 | { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, | ||
61 | { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, | ||
62 | { CR92, 0x0a }, { CR99, 0x28 }, { CR100, 0x00 }, | ||
63 | { CR101, 0x13 }, { CR102, 0x27 }, { CR106, 0x24 }, | ||
64 | { CR107, 0x2a }, { CR109, 0x09 }, { CR110, 0x13 }, | ||
65 | { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, | ||
66 | { CR114, 0x27 }, | ||
67 | /* for newest (3rd cut) AL2300 */ | ||
68 | { CR115, 0x24 }, | ||
69 | { CR116, 0x24 }, { CR117, 0xf4 }, { CR118, 0xfc }, | ||
70 | { CR119, 0x10 }, { CR120, 0x4f }, { CR121, 0x77 }, | ||
71 | { CR122, 0xe0 }, { CR137, 0x88 }, { CR252, 0xff }, | ||
72 | { CR253, 0xff }, | ||
73 | |||
74 | /* These following happen separately in the vendor driver */ | ||
75 | { }, | ||
76 | |||
77 | /* shdnb(PLL_ON)=0 */ | ||
78 | { CR251, 0x2f }, | ||
79 | /* shdnb(PLL_ON)=1 */ | ||
80 | { CR251, 0x3f }, | ||
81 | { CR138, 0x28 }, { CR203, 0x06 }, | ||
82 | }; | ||
83 | |||
84 | static const u32 rv[] = { | ||
85 | /* Channel 1 */ | ||
86 | 0x03f790, | ||
87 | 0x033331, | ||
88 | 0x00000d, | ||
89 | |||
90 | 0x0b3331, | ||
91 | 0x03b812, | ||
92 | 0x00fff3, | ||
93 | 0x000da4, | ||
94 | 0x0f4dc5, /* fix freq shift, 0x04edc5 */ | ||
95 | 0x0805b6, | ||
96 | 0x011687, | ||
97 | 0x000688, | ||
98 | 0x0403b9, /* external control TX power (CR31) */ | ||
99 | 0x00dbba, | ||
100 | 0x00099b, | ||
101 | 0x0bdffc, | ||
102 | 0x00000d, | ||
103 | 0x00500f, | ||
104 | |||
105 | /* These writes happen separately in the vendor driver */ | ||
106 | 0x00d00f, | ||
107 | 0x004c0f, | ||
108 | 0x00540f, | ||
109 | 0x00700f, | ||
110 | 0x00500f, | ||
111 | }; | ||
112 | |||
113 | r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
114 | if (r) | ||
115 | return r; | ||
116 | |||
117 | r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); | ||
118 | if (r) | ||
119 | return r; | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static int zd1211b_al2230_init_hw(struct zd_rf *rf) | ||
125 | { | ||
126 | int r; | ||
127 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
128 | |||
129 | static const struct zd_ioreq16 ioreqs1[] = { | ||
130 | { CR10, 0x89 }, { CR15, 0x20 }, | ||
131 | { CR17, 0x2B }, /* for newest(3rd cut) AL2230 */ | ||
132 | { CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 }, | ||
133 | { CR28, 0x3e }, { CR29, 0x00 }, | ||
134 | { CR33, 0x28 }, /* 5621 */ | ||
135 | { CR34, 0x30 }, | ||
136 | { CR35, 0x3e }, /* for newest(3rd cut) AL2230 */ | ||
137 | { CR41, 0x24 }, { CR44, 0x32 }, | ||
138 | { CR46, 0x99 }, /* for newest(3rd cut) AL2230 */ | ||
139 | { CR47, 0x1e }, | ||
140 | |||
141 | /* ZD1211B 05.06.10 */ | ||
142 | { CR48, 0x00 }, { CR49, 0x00 }, { CR51, 0x01 }, | ||
143 | { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, | ||
144 | { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, | ||
145 | { CR69, 0x28 }, | ||
146 | |||
147 | { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, | ||
148 | { CR87, 0x0a }, { CR89, 0x04 }, | ||
149 | { CR91, 0x00 }, /* 5621 */ | ||
150 | { CR92, 0x0a }, | ||
151 | { CR98, 0x8d }, /* 4804, for 1212 new algorithm */ | ||
152 | { CR99, 0x00 }, /* 5621 */ | ||
153 | { CR101, 0x13 }, { CR102, 0x27 }, | ||
154 | { CR106, 0x24 }, /* for newest(3rd cut) AL2230 */ | ||
155 | { CR107, 0x2a }, | ||
156 | { CR109, 0x13 }, /* 4804, for 1212 new algorithm */ | ||
157 | { CR110, 0x1f }, /* 4804, for 1212 new algorithm */ | ||
158 | { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, | ||
159 | { CR114, 0x27 }, | ||
160 | { CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) AL2230 */ | ||
161 | { CR116, 0x24 }, | ||
162 | { CR117, 0xfa }, /* for 1211b */ | ||
163 | { CR118, 0xfa }, /* for 1211b */ | ||
164 | { CR119, 0x10 }, | ||
165 | { CR120, 0x4f }, | ||
166 | { CR121, 0x6c }, /* for 1211b */ | ||
167 | { CR122, 0xfc }, /* E0->FC at 4902 */ | ||
168 | { CR123, 0x57 }, /* 5623 */ | ||
169 | { CR125, 0xad }, /* 4804, for 1212 new algorithm */ | ||
170 | { CR126, 0x6c }, /* 5614 */ | ||
171 | { CR127, 0x03 }, /* 4804, for 1212 new algorithm */ | ||
172 | { CR137, 0x50 }, /* 5614 */ | ||
173 | { CR138, 0xa8 }, | ||
174 | { CR144, 0xac }, /* 5621 */ | ||
175 | { CR150, 0x0d }, { CR252, 0x00 }, { CR253, 0x00 }, | ||
176 | }; | ||
177 | |||
178 | static const u32 rv1[] = { | ||
179 | /* channel 1 */ | ||
180 | 0x03f790, | ||
181 | 0x033331, | ||
182 | 0x00000d, | ||
183 | |||
184 | 0x0b3331, | ||
185 | 0x03b812, | ||
186 | 0x00fff3, | ||
187 | 0x0005a4, | ||
188 | 0x0f4dc5, /* fix freq shift 0x044dc5 */ | ||
189 | 0x0805b6, | ||
190 | 0x0146c7, | ||
191 | 0x000688, | ||
192 | 0x0403b9, /* External control TX power (CR31) */ | ||
193 | 0x00dbba, | ||
194 | 0x00099b, | ||
195 | 0x0bdffc, | ||
196 | 0x00000d, | ||
197 | 0x00580f, | ||
198 | }; | ||
199 | |||
200 | static const struct zd_ioreq16 ioreqs2[] = { | ||
201 | { CR47, 0x1e }, { CR_RFCFG, 0x03 }, | ||
202 | }; | ||
203 | |||
204 | static const u32 rv2[] = { | ||
205 | 0x00880f, | ||
206 | 0x00080f, | ||
207 | }; | ||
208 | |||
209 | static const struct zd_ioreq16 ioreqs3[] = { | ||
210 | { CR_RFCFG, 0x00 }, { CR47, 0x1e }, { CR251, 0x7f }, | ||
211 | }; | ||
212 | |||
213 | static const u32 rv3[] = { | ||
214 | 0x00d80f, | ||
215 | 0x00780f, | ||
216 | 0x00580f, | ||
217 | }; | ||
218 | |||
219 | static const struct zd_ioreq16 ioreqs4[] = { | ||
220 | { CR138, 0x28 }, { CR203, 0x06 }, | ||
221 | }; | ||
222 | |||
223 | r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1)); | ||
224 | if (r) | ||
225 | return r; | ||
226 | r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS); | ||
227 | if (r) | ||
228 | return r; | ||
229 | r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2)); | ||
230 | if (r) | ||
231 | return r; | ||
232 | r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS); | ||
233 | if (r) | ||
234 | return r; | ||
235 | r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3)); | ||
236 | if (r) | ||
237 | return r; | ||
238 | r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS); | ||
239 | if (r) | ||
240 | return r; | ||
241 | return zd_iowrite16a_locked(chip, ioreqs4, ARRAY_SIZE(ioreqs4)); | ||
242 | } | ||
243 | |||
244 | static int al2230_set_channel(struct zd_rf *rf, u8 channel) | ||
245 | { | ||
246 | int r; | ||
247 | const u32 *rv = al2230_table[channel-1]; | ||
248 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
249 | static const struct zd_ioreq16 ioreqs[] = { | ||
250 | { CR138, 0x28 }, | ||
251 | { CR203, 0x06 }, | ||
252 | }; | ||
253 | |||
254 | r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS); | ||
255 | if (r) | ||
256 | return r; | ||
257 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
258 | } | ||
259 | |||
260 | static int zd1211_al2230_switch_radio_on(struct zd_rf *rf) | ||
261 | { | ||
262 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
263 | static const struct zd_ioreq16 ioreqs[] = { | ||
264 | { CR11, 0x00 }, | ||
265 | { CR251, 0x3f }, | ||
266 | }; | ||
267 | |||
268 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
269 | } | ||
270 | |||
271 | static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf) | ||
272 | { | ||
273 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
274 | static const struct zd_ioreq16 ioreqs[] = { | ||
275 | { CR11, 0x00 }, | ||
276 | { CR251, 0x7f }, | ||
277 | }; | ||
278 | |||
279 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
280 | } | ||
281 | |||
282 | static int al2230_switch_radio_off(struct zd_rf *rf) | ||
283 | { | ||
284 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
285 | static const struct zd_ioreq16 ioreqs[] = { | ||
286 | { CR11, 0x04 }, | ||
287 | { CR251, 0x2f }, | ||
288 | }; | ||
289 | |||
290 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
291 | } | ||
292 | |||
293 | int zd_rf_init_al2230(struct zd_rf *rf) | ||
294 | { | ||
295 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
296 | |||
297 | rf->set_channel = al2230_set_channel; | ||
298 | rf->switch_radio_off = al2230_switch_radio_off; | ||
299 | if (chip->is_zd1211b) { | ||
300 | rf->init_hw = zd1211b_al2230_init_hw; | ||
301 | rf->switch_radio_on = zd1211b_al2230_switch_radio_on; | ||
302 | } else { | ||
303 | rf->init_hw = zd1211_al2230_init_hw; | ||
304 | rf->switch_radio_on = zd1211_al2230_switch_radio_on; | ||
305 | } | ||
306 | rf->patch_6m_band_edge = 1; | ||
307 | return 0; | ||
308 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c new file mode 100644 index 000000000000..58247271cc24 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c | |||
@@ -0,0 +1,279 @@ | |||
1 | /* zd_rf_rfmd.c: Functions for the RFMD RF controller | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | |||
20 | #include "zd_rf.h" | ||
21 | #include "zd_usb.h" | ||
22 | #include "zd_chip.h" | ||
23 | |||
24 | static u32 rf2959_table[][2] = { | ||
25 | RF_CHANNEL( 1) = { 0x181979, 0x1e6666 }, | ||
26 | RF_CHANNEL( 2) = { 0x181989, 0x1e6666 }, | ||
27 | RF_CHANNEL( 3) = { 0x181999, 0x1e6666 }, | ||
28 | RF_CHANNEL( 4) = { 0x1819a9, 0x1e6666 }, | ||
29 | RF_CHANNEL( 5) = { 0x1819b9, 0x1e6666 }, | ||
30 | RF_CHANNEL( 6) = { 0x1819c9, 0x1e6666 }, | ||
31 | RF_CHANNEL( 7) = { 0x1819d9, 0x1e6666 }, | ||
32 | RF_CHANNEL( 8) = { 0x1819e9, 0x1e6666 }, | ||
33 | RF_CHANNEL( 9) = { 0x1819f9, 0x1e6666 }, | ||
34 | RF_CHANNEL(10) = { 0x181a09, 0x1e6666 }, | ||
35 | RF_CHANNEL(11) = { 0x181a19, 0x1e6666 }, | ||
36 | RF_CHANNEL(12) = { 0x181a29, 0x1e6666 }, | ||
37 | RF_CHANNEL(13) = { 0x181a39, 0x1e6666 }, | ||
38 | RF_CHANNEL(14) = { 0x181a60, 0x1c0000 }, | ||
39 | }; | ||
40 | |||
41 | #if 0 | ||
42 | static int bits(u32 rw, int from, int to) | ||
43 | { | ||
44 | rw &= ~(0xffffffffU << (to+1)); | ||
45 | rw >>= from; | ||
46 | return rw; | ||
47 | } | ||
48 | |||
49 | static int bit(u32 rw, int bit) | ||
50 | { | ||
51 | return bits(rw, bit, bit); | ||
52 | } | ||
53 | |||
54 | static void dump_regwrite(u32 rw) | ||
55 | { | ||
56 | int reg = bits(rw, 18, 22); | ||
57 | int rw_flag = bits(rw, 23, 23); | ||
58 | PDEBUG("rf2959 %#010x reg %d rw %d", rw, reg, rw_flag); | ||
59 | |||
60 | switch (reg) { | ||
61 | case 0: | ||
62 | PDEBUG("reg0 CFG1 ref_sel %d hybernate %d rf_vco_reg_en %d" | ||
63 | " if_vco_reg_en %d if_vga_en %d", | ||
64 | bits(rw, 14, 15), bit(rw, 3), bit(rw, 2), bit(rw, 1), | ||
65 | bit(rw, 0)); | ||
66 | break; | ||
67 | case 1: | ||
68 | PDEBUG("reg1 IFPLL1 pll_en1 %d kv_en1 %d vtc_en1 %d lpf1 %d" | ||
69 | " cpl1 %d pdp1 %d autocal_en1 %d ld_en1 %d ifloopr %d" | ||
70 | " ifloopc %d dac1 %d", | ||
71 | bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14), | ||
72 | bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10), | ||
73 | bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0, 3)); | ||
74 | break; | ||
75 | case 2: | ||
76 | PDEBUG("reg2 IFPLL2 n1 %d num1 %d", | ||
77 | bits(rw, 6, 17), bits(rw, 0, 5)); | ||
78 | break; | ||
79 | case 3: | ||
80 | PDEBUG("reg3 IFPLL3 num %d", bits(rw, 0, 17)); | ||
81 | break; | ||
82 | case 4: | ||
83 | PDEBUG("reg4 IFPLL4 dn1 %#04x ct_def1 %d kv_def1 %d", | ||
84 | bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3)); | ||
85 | break; | ||
86 | case 5: | ||
87 | PDEBUG("reg5 RFPLL1 pll_en %d kv_en %d vtc_en %d lpf %d cpl %d" | ||
88 | " pdp %d autocal_en %d ld_en %d rfloopr %d rfloopc %d" | ||
89 | " dac %d", | ||
90 | bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14), | ||
91 | bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10), | ||
92 | bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0,3)); | ||
93 | break; | ||
94 | case 6: | ||
95 | PDEBUG("reg6 RFPLL2 n %d num %d", | ||
96 | bits(rw, 6, 17), bits(rw, 0, 5)); | ||
97 | break; | ||
98 | case 7: | ||
99 | PDEBUG("reg7 RFPLL3 num2 %d", bits(rw, 0, 17)); | ||
100 | break; | ||
101 | case 8: | ||
102 | PDEBUG("reg8 RFPLL4 dn %#06x ct_def %d kv_def %d", | ||
103 | bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3)); | ||
104 | break; | ||
105 | case 9: | ||
106 | PDEBUG("reg9 CAL1 tvco %d tlock %d m_ct_value %d ld_window %d", | ||
107 | bits(rw, 13, 17), bits(rw, 8, 12), bits(rw, 3, 7), | ||
108 | bits(rw, 0, 2)); | ||
109 | break; | ||
110 | case 10: | ||
111 | PDEBUG("reg10 TXRX1 rxdcfbbyps %d pcontrol %d txvgc %d" | ||
112 | " rxlpfbw %d txlpfbw %d txdiffmode %d txenmode %d" | ||
113 | " intbiasen %d tybypass %d", | ||
114 | bit(rw, 17), bits(rw, 15, 16), bits(rw, 10, 14), | ||
115 | bits(rw, 7, 9), bits(rw, 4, 6), bit(rw, 3), bit(rw, 2), | ||
116 | bit(rw, 1), bit(rw, 0)); | ||
117 | break; | ||
118 | case 11: | ||
119 | PDEBUG("reg11 PCNT1 mid_bias %d p_desired %d pc_offset %d" | ||
120 | " tx_delay %d", | ||
121 | bits(rw, 15, 17), bits(rw, 9, 14), bits(rw, 3, 8), | ||
122 | bits(rw, 0, 2)); | ||
123 | break; | ||
124 | case 12: | ||
125 | PDEBUG("reg12 PCNT2 max_power %d mid_power %d min_power %d", | ||
126 | bits(rw, 12, 17), bits(rw, 6, 11), bits(rw, 0, 5)); | ||
127 | break; | ||
128 | case 13: | ||
129 | PDEBUG("reg13 VCOT1 rfpll vco comp %d ifpll vco comp %d" | ||
130 | " lobias %d if_biasbuf %d if_biasvco %d rf_biasbuf %d" | ||
131 | " rf_biasvco %d", | ||
132 | bit(rw, 17), bit(rw, 16), bit(rw, 15), | ||
133 | bits(rw, 8, 9), bits(rw, 5, 7), bits(rw, 3, 4), | ||
134 | bits(rw, 0, 2)); | ||
135 | break; | ||
136 | case 14: | ||
137 | PDEBUG("reg14 IQCAL rx_acal %d rx_pcal %d" | ||
138 | " tx_acal %d tx_pcal %d", | ||
139 | bits(rw, 13, 17), bits(rw, 9, 12), bits(rw, 4, 8), | ||
140 | bits(rw, 0, 3)); | ||
141 | break; | ||
142 | } | ||
143 | } | ||
144 | #endif /* 0 */ | ||
145 | |||
146 | static int rf2959_init_hw(struct zd_rf *rf) | ||
147 | { | ||
148 | int r; | ||
149 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
150 | |||
151 | static const struct zd_ioreq16 ioreqs[] = { | ||
152 | { CR2, 0x1E }, { CR9, 0x20 }, { CR10, 0x89 }, | ||
153 | { CR11, 0x00 }, { CR15, 0xD0 }, { CR17, 0x68 }, | ||
154 | { CR19, 0x4a }, { CR20, 0x0c }, { CR21, 0x0E }, | ||
155 | { CR23, 0x48 }, | ||
156 | /* normal size for cca threshold */ | ||
157 | { CR24, 0x14 }, | ||
158 | /* { CR24, 0x20 }, */ | ||
159 | { CR26, 0x90 }, { CR27, 0x30 }, { CR29, 0x20 }, | ||
160 | { CR31, 0xb2 }, { CR32, 0x43 }, { CR33, 0x28 }, | ||
161 | { CR38, 0x30 }, { CR34, 0x0f }, { CR35, 0xF0 }, | ||
162 | { CR41, 0x2a }, { CR46, 0x7F }, { CR47, 0x1E }, | ||
163 | { CR51, 0xc5 }, { CR52, 0xc5 }, { CR53, 0xc5 }, | ||
164 | { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, | ||
165 | { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, | ||
166 | { CR85, 0x00 }, { CR86, 0x10 }, { CR87, 0x2A }, | ||
167 | { CR88, 0x10 }, { CR89, 0x24 }, { CR90, 0x18 }, | ||
168 | /* { CR91, 0x18 }, */ | ||
169 | /* should solve continous CTS frame problems */ | ||
170 | { CR91, 0x00 }, | ||
171 | { CR92, 0x0a }, { CR93, 0x00 }, { CR94, 0x01 }, | ||
172 | { CR95, 0x00 }, { CR96, 0x40 }, { CR97, 0x37 }, | ||
173 | { CR98, 0x05 }, { CR99, 0x28 }, { CR100, 0x00 }, | ||
174 | { CR101, 0x13 }, { CR102, 0x27 }, { CR103, 0x27 }, | ||
175 | { CR104, 0x18 }, { CR105, 0x12 }, | ||
176 | /* normal size */ | ||
177 | { CR106, 0x1a }, | ||
178 | /* { CR106, 0x22 }, */ | ||
179 | { CR107, 0x24 }, { CR108, 0x0a }, { CR109, 0x13 }, | ||
180 | { CR110, 0x2F }, { CR111, 0x27 }, { CR112, 0x27 }, | ||
181 | { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x40 }, | ||
182 | { CR116, 0x40 }, { CR117, 0xF0 }, { CR118, 0xF0 }, | ||
183 | { CR119, 0x16 }, | ||
184 | /* no TX continuation */ | ||
185 | { CR122, 0x00 }, | ||
186 | /* { CR122, 0xff }, */ | ||
187 | { CR127, 0x03 }, { CR131, 0x08 }, { CR138, 0x28 }, | ||
188 | { CR148, 0x44 }, { CR150, 0x10 }, { CR169, 0xBB }, | ||
189 | { CR170, 0xBB }, | ||
190 | }; | ||
191 | |||
192 | static const u32 rv[] = { | ||
193 | 0x000007, /* REG0(CFG1) */ | ||
194 | 0x07dd43, /* REG1(IFPLL1) */ | ||
195 | 0x080959, /* REG2(IFPLL2) */ | ||
196 | 0x0e6666, | ||
197 | 0x116a57, /* REG4 */ | ||
198 | 0x17dd43, /* REG5 */ | ||
199 | 0x1819f9, /* REG6 */ | ||
200 | 0x1e6666, | ||
201 | 0x214554, | ||
202 | 0x25e7fa, | ||
203 | 0x27fffa, | ||
204 | /* The Zydas driver somehow forgets to set this value. It's | ||
205 | * only set for Japan. We are using internal power control | ||
206 | * for now. | ||
207 | */ | ||
208 | 0x294128, /* internal power */ | ||
209 | /* 0x28252c, */ /* External control TX power */ | ||
210 | /* CR31_CCK, CR51_6-36M, CR52_48M, CR53_54M */ | ||
211 | 0x2c0000, | ||
212 | 0x300000, | ||
213 | 0x340000, /* REG13(0xD) */ | ||
214 | 0x381e0f, /* REG14(0xE) */ | ||
215 | /* Bogus, RF2959's data sheet doesn't know register 27, which is | ||
216 | * actually referenced here. The commented 0x11 is 17. | ||
217 | */ | ||
218 | 0x6c180f, /* REG27(0x11) */ | ||
219 | }; | ||
220 | |||
221 | r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
222 | if (r) | ||
223 | return r; | ||
224 | |||
225 | return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); | ||
226 | } | ||
227 | |||
228 | static int rf2959_set_channel(struct zd_rf *rf, u8 channel) | ||
229 | { | ||
230 | int i, r; | ||
231 | u32 *rv = rf2959_table[channel-1]; | ||
232 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
233 | |||
234 | for (i = 0; i < 2; i++) { | ||
235 | r = zd_rfwrite_locked(chip, rv[i], RF_RV_BITS); | ||
236 | if (r) | ||
237 | return r; | ||
238 | } | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static int rf2959_switch_radio_on(struct zd_rf *rf) | ||
243 | { | ||
244 | static const struct zd_ioreq16 ioreqs[] = { | ||
245 | { CR10, 0x89 }, | ||
246 | { CR11, 0x00 }, | ||
247 | }; | ||
248 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
249 | |||
250 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
251 | } | ||
252 | |||
253 | static int rf2959_switch_radio_off(struct zd_rf *rf) | ||
254 | { | ||
255 | static const struct zd_ioreq16 ioreqs[] = { | ||
256 | { CR10, 0x15 }, | ||
257 | { CR11, 0x81 }, | ||
258 | }; | ||
259 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
260 | |||
261 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
262 | } | ||
263 | |||
264 | int zd_rf_init_rf2959(struct zd_rf *rf) | ||
265 | { | ||
266 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
267 | |||
268 | if (chip->is_zd1211b) { | ||
269 | dev_err(zd_chip_dev(chip), | ||
270 | "RF2959 is currently not supported for ZD1211B" | ||
271 | " devices\n"); | ||
272 | return -ENODEV; | ||
273 | } | ||
274 | rf->init_hw = rf2959_init_hw; | ||
275 | rf->set_channel = rf2959_set_channel; | ||
276 | rf->switch_radio_on = rf2959_switch_radio_on; | ||
277 | rf->switch_radio_off = rf2959_switch_radio_off; | ||
278 | return 0; | ||
279 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_types.h b/drivers/net/wireless/zd1211rw/zd_types.h new file mode 100644 index 000000000000..0155a1584ed3 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_types.h | |||
@@ -0,0 +1,71 @@ | |||
1 | /* zd_types.h | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef _ZD_TYPES_H | ||
19 | #define _ZD_TYPES_H | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | |||
23 | /* We have three register spaces mapped into the overall USB address space of | ||
24 | * 64K words (16-bit values). There is the control register space of | ||
25 | * double-word registers, the eeprom register space and the firmware register | ||
26 | * space. The control register space is byte mapped, the others are word | ||
27 | * mapped. | ||
28 | * | ||
29 | * For that reason, we are using byte offsets for control registers and word | ||
30 | * offsets for everything else. | ||
31 | */ | ||
32 | |||
33 | typedef u32 __nocast zd_addr_t; | ||
34 | |||
35 | enum { | ||
36 | ADDR_BASE_MASK = 0xff000000, | ||
37 | ADDR_OFFSET_MASK = 0x0000ffff, | ||
38 | ADDR_ZERO_MASK = 0x00ff0000, | ||
39 | NULL_BASE = 0x00000000, | ||
40 | USB_BASE = 0x01000000, | ||
41 | CR_BASE = 0x02000000, | ||
42 | CR_MAX_OFFSET = 0x0b30, | ||
43 | E2P_BASE = 0x03000000, | ||
44 | E2P_MAX_OFFSET = 0x007e, | ||
45 | FW_BASE = 0x04000000, | ||
46 | FW_MAX_OFFSET = 0x0005, | ||
47 | }; | ||
48 | |||
49 | #define ZD_ADDR_BASE(addr) ((u32)(addr) & ADDR_BASE_MASK) | ||
50 | #define ZD_OFFSET(addr) ((u32)(addr) & ADDR_OFFSET_MASK) | ||
51 | |||
52 | #define ZD_ADDR(base, offset) \ | ||
53 | ((zd_addr_t)(((base) & ADDR_BASE_MASK) | ((offset) & ADDR_OFFSET_MASK))) | ||
54 | |||
55 | #define ZD_NULL_ADDR ((zd_addr_t)0) | ||
56 | #define USB_REG(offset) ZD_ADDR(USB_BASE, offset) /* word addressing */ | ||
57 | #define CTL_REG(offset) ZD_ADDR(CR_BASE, offset) /* byte addressing */ | ||
58 | #define E2P_REG(offset) ZD_ADDR(E2P_BASE, offset) /* word addressing */ | ||
59 | #define FW_REG(offset) ZD_ADDR(FW_BASE, offset) /* word addressing */ | ||
60 | |||
61 | static inline zd_addr_t zd_inc_word(zd_addr_t addr) | ||
62 | { | ||
63 | u32 base = ZD_ADDR_BASE(addr); | ||
64 | u32 offset = ZD_OFFSET(addr); | ||
65 | |||
66 | offset += base == CR_BASE ? 2 : 1; | ||
67 | |||
68 | return base | offset; | ||
69 | } | ||
70 | |||
71 | #endif /* _ZD_TYPES_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c new file mode 100644 index 000000000000..ce1cb2c6aa8d --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -0,0 +1,1316 @@ | |||
1 | /* zd_usb.c | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #include <asm/unaligned.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/firmware.h> | ||
22 | #include <linux/device.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/skbuff.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <net/ieee80211.h> | ||
27 | |||
28 | #include "zd_def.h" | ||
29 | #include "zd_netdev.h" | ||
30 | #include "zd_mac.h" | ||
31 | #include "zd_usb.h" | ||
32 | #include "zd_util.h" | ||
33 | |||
34 | static struct usb_device_id usb_ids[] = { | ||
35 | /* ZD1211 */ | ||
36 | { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 }, | ||
37 | { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 }, | ||
38 | { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, | ||
39 | { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, | ||
40 | { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, | ||
41 | { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, | ||
42 | /* ZD1211B */ | ||
43 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, | ||
44 | { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, | ||
45 | {} | ||
46 | }; | ||
47 | |||
48 | MODULE_LICENSE("GPL"); | ||
49 | MODULE_DESCRIPTION("USB driver for devices with the ZD1211 chip."); | ||
50 | MODULE_AUTHOR("Ulrich Kunitz"); | ||
51 | MODULE_AUTHOR("Daniel Drake"); | ||
52 | MODULE_VERSION("1.0"); | ||
53 | MODULE_DEVICE_TABLE(usb, usb_ids); | ||
54 | |||
55 | #define FW_ZD1211_PREFIX "zd1211/zd1211_" | ||
56 | #define FW_ZD1211B_PREFIX "zd1211/zd1211b_" | ||
57 | |||
58 | /* register address handling */ | ||
59 | |||
60 | #ifdef DEBUG | ||
61 | static int check_addr(struct zd_usb *usb, zd_addr_t addr) | ||
62 | { | ||
63 | u32 base = ZD_ADDR_BASE(addr); | ||
64 | u32 offset = ZD_OFFSET(addr); | ||
65 | |||
66 | if ((u32)addr & ADDR_ZERO_MASK) | ||
67 | goto invalid_address; | ||
68 | switch (base) { | ||
69 | case USB_BASE: | ||
70 | break; | ||
71 | case CR_BASE: | ||
72 | if (offset > CR_MAX_OFFSET) { | ||
73 | dev_dbg(zd_usb_dev(usb), | ||
74 | "CR offset %#010x larger than" | ||
75 | " CR_MAX_OFFSET %#10x\n", | ||
76 | offset, CR_MAX_OFFSET); | ||
77 | goto invalid_address; | ||
78 | } | ||
79 | if (offset & 1) { | ||
80 | dev_dbg(zd_usb_dev(usb), | ||
81 | "CR offset %#010x is not a multiple of 2\n", | ||
82 | offset); | ||
83 | goto invalid_address; | ||
84 | } | ||
85 | break; | ||
86 | case E2P_BASE: | ||
87 | if (offset > E2P_MAX_OFFSET) { | ||
88 | dev_dbg(zd_usb_dev(usb), | ||
89 | "E2P offset %#010x larger than" | ||
90 | " E2P_MAX_OFFSET %#010x\n", | ||
91 | offset, E2P_MAX_OFFSET); | ||
92 | goto invalid_address; | ||
93 | } | ||
94 | break; | ||
95 | case FW_BASE: | ||
96 | if (!usb->fw_base_offset) { | ||
97 | dev_dbg(zd_usb_dev(usb), | ||
98 | "ERROR: fw base offset has not been set\n"); | ||
99 | return -EAGAIN; | ||
100 | } | ||
101 | if (offset > FW_MAX_OFFSET) { | ||
102 | dev_dbg(zd_usb_dev(usb), | ||
103 | "FW offset %#10x is larger than" | ||
104 | " FW_MAX_OFFSET %#010x\n", | ||
105 | offset, FW_MAX_OFFSET); | ||
106 | goto invalid_address; | ||
107 | } | ||
108 | break; | ||
109 | default: | ||
110 | dev_dbg(zd_usb_dev(usb), | ||
111 | "address has unsupported base %#010x\n", addr); | ||
112 | goto invalid_address; | ||
113 | } | ||
114 | |||
115 | return 0; | ||
116 | invalid_address: | ||
117 | dev_dbg(zd_usb_dev(usb), | ||
118 | "ERROR: invalid address: %#010x\n", addr); | ||
119 | return -EINVAL; | ||
120 | } | ||
121 | #endif /* DEBUG */ | ||
122 | |||
123 | static u16 usb_addr(struct zd_usb *usb, zd_addr_t addr) | ||
124 | { | ||
125 | u32 base; | ||
126 | u16 offset; | ||
127 | |||
128 | base = ZD_ADDR_BASE(addr); | ||
129 | offset = ZD_OFFSET(addr); | ||
130 | |||
131 | ZD_ASSERT(check_addr(usb, addr) == 0); | ||
132 | |||
133 | switch (base) { | ||
134 | case CR_BASE: | ||
135 | offset += CR_BASE_OFFSET; | ||
136 | break; | ||
137 | case E2P_BASE: | ||
138 | offset += E2P_BASE_OFFSET; | ||
139 | break; | ||
140 | case FW_BASE: | ||
141 | offset += usb->fw_base_offset; | ||
142 | break; | ||
143 | } | ||
144 | |||
145 | return offset; | ||
146 | } | ||
147 | |||
148 | /* USB device initialization */ | ||
149 | |||
150 | static int request_fw_file( | ||
151 | const struct firmware **fw, const char *name, struct device *device) | ||
152 | { | ||
153 | int r; | ||
154 | |||
155 | dev_dbg_f(device, "fw name %s\n", name); | ||
156 | |||
157 | r = request_firmware(fw, name, device); | ||
158 | if (r) | ||
159 | dev_err(device, | ||
160 | "Could not load firmware file %s. Error number %d\n", | ||
161 | name, r); | ||
162 | return r; | ||
163 | } | ||
164 | |||
165 | static inline u16 get_bcdDevice(const struct usb_device *udev) | ||
166 | { | ||
167 | return le16_to_cpu(udev->descriptor.bcdDevice); | ||
168 | } | ||
169 | |||
170 | enum upload_code_flags { | ||
171 | REBOOT = 1, | ||
172 | }; | ||
173 | |||
174 | /* Ensures that MAX_TRANSFER_SIZE is even. */ | ||
175 | #define MAX_TRANSFER_SIZE (USB_MAX_TRANSFER_SIZE & ~1) | ||
176 | |||
177 | static int upload_code(struct usb_device *udev, | ||
178 | const u8 *data, size_t size, u16 code_offset, int flags) | ||
179 | { | ||
180 | u8 *p; | ||
181 | int r; | ||
182 | |||
183 | /* USB request blocks need "kmalloced" buffers. | ||
184 | */ | ||
185 | p = kmalloc(MAX_TRANSFER_SIZE, GFP_KERNEL); | ||
186 | if (!p) { | ||
187 | dev_err(&udev->dev, "out of memory\n"); | ||
188 | r = -ENOMEM; | ||
189 | goto error; | ||
190 | } | ||
191 | |||
192 | size &= ~1; | ||
193 | while (size > 0) { | ||
194 | size_t transfer_size = size <= MAX_TRANSFER_SIZE ? | ||
195 | size : MAX_TRANSFER_SIZE; | ||
196 | |||
197 | dev_dbg_f(&udev->dev, "transfer size %zu\n", transfer_size); | ||
198 | |||
199 | memcpy(p, data, transfer_size); | ||
200 | r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
201 | USB_REQ_FIRMWARE_DOWNLOAD, | ||
202 | USB_DIR_OUT | USB_TYPE_VENDOR, | ||
203 | code_offset, 0, p, transfer_size, 1000 /* ms */); | ||
204 | if (r < 0) { | ||
205 | dev_err(&udev->dev, | ||
206 | "USB control request for firmware upload" | ||
207 | " failed. Error number %d\n", r); | ||
208 | goto error; | ||
209 | } | ||
210 | transfer_size = r & ~1; | ||
211 | |||
212 | size -= transfer_size; | ||
213 | data += transfer_size; | ||
214 | code_offset += transfer_size/sizeof(u16); | ||
215 | } | ||
216 | |||
217 | if (flags & REBOOT) { | ||
218 | u8 ret; | ||
219 | |||
220 | r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
221 | USB_REQ_FIRMWARE_CONFIRM, | ||
222 | USB_DIR_IN | USB_TYPE_VENDOR, | ||
223 | 0, 0, &ret, sizeof(ret), 5000 /* ms */); | ||
224 | if (r != sizeof(ret)) { | ||
225 | dev_err(&udev->dev, | ||
226 | "control request firmeware confirmation failed." | ||
227 | " Return value %d\n", r); | ||
228 | if (r >= 0) | ||
229 | r = -ENODEV; | ||
230 | goto error; | ||
231 | } | ||
232 | if (ret & 0x80) { | ||
233 | dev_err(&udev->dev, | ||
234 | "Internal error while downloading." | ||
235 | " Firmware confirm return value %#04x\n", | ||
236 | (unsigned int)ret); | ||
237 | r = -ENODEV; | ||
238 | goto error; | ||
239 | } | ||
240 | dev_dbg_f(&udev->dev, "firmware confirm return value %#04x\n", | ||
241 | (unsigned int)ret); | ||
242 | } | ||
243 | |||
244 | r = 0; | ||
245 | error: | ||
246 | kfree(p); | ||
247 | return r; | ||
248 | } | ||
249 | |||
250 | static u16 get_word(const void *data, u16 offset) | ||
251 | { | ||
252 | const __le16 *p = data; | ||
253 | return le16_to_cpu(p[offset]); | ||
254 | } | ||
255 | |||
256 | static char *get_fw_name(char *buffer, size_t size, u8 device_type, | ||
257 | const char* postfix) | ||
258 | { | ||
259 | scnprintf(buffer, size, "%s%s", | ||
260 | device_type == DEVICE_ZD1211B ? | ||
261 | FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX, | ||
262 | postfix); | ||
263 | return buffer; | ||
264 | } | ||
265 | |||
266 | static int upload_firmware(struct usb_device *udev, u8 device_type) | ||
267 | { | ||
268 | int r; | ||
269 | u16 fw_bcdDevice; | ||
270 | u16 bcdDevice; | ||
271 | const struct firmware *ub_fw = NULL; | ||
272 | const struct firmware *uph_fw = NULL; | ||
273 | char fw_name[128]; | ||
274 | |||
275 | bcdDevice = get_bcdDevice(udev); | ||
276 | |||
277 | r = request_fw_file(&ub_fw, | ||
278 | get_fw_name(fw_name, sizeof(fw_name), device_type, "ub"), | ||
279 | &udev->dev); | ||
280 | if (r) | ||
281 | goto error; | ||
282 | |||
283 | fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET); | ||
284 | |||
285 | /* FIXME: do we have any reason to perform the kludge that the vendor | ||
286 | * driver does when there is a version mismatch? (their driver uploads | ||
287 | * different firmwares and stuff) | ||
288 | */ | ||
289 | if (fw_bcdDevice != bcdDevice) { | ||
290 | dev_info(&udev->dev, | ||
291 | "firmware device id %#06x and actual device id " | ||
292 | "%#06x differ, continuing anyway\n", | ||
293 | fw_bcdDevice, bcdDevice); | ||
294 | } else { | ||
295 | dev_dbg_f(&udev->dev, | ||
296 | "firmware device id %#06x is equal to the " | ||
297 | "actual device id\n", fw_bcdDevice); | ||
298 | } | ||
299 | |||
300 | |||
301 | r = request_fw_file(&uph_fw, | ||
302 | get_fw_name(fw_name, sizeof(fw_name), device_type, "uphr"), | ||
303 | &udev->dev); | ||
304 | if (r) | ||
305 | goto error; | ||
306 | |||
307 | r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START_OFFSET, | ||
308 | REBOOT); | ||
309 | if (r) { | ||
310 | dev_err(&udev->dev, | ||
311 | "Could not upload firmware code uph. Error number %d\n", | ||
312 | r); | ||
313 | } | ||
314 | |||
315 | /* FALL-THROUGH */ | ||
316 | error: | ||
317 | release_firmware(ub_fw); | ||
318 | release_firmware(uph_fw); | ||
319 | return r; | ||
320 | } | ||
321 | |||
322 | static void disable_read_regs_int(struct zd_usb *usb) | ||
323 | { | ||
324 | struct zd_usb_interrupt *intr = &usb->intr; | ||
325 | |||
326 | ZD_ASSERT(in_interrupt()); | ||
327 | spin_lock(&intr->lock); | ||
328 | intr->read_regs_enabled = 0; | ||
329 | spin_unlock(&intr->lock); | ||
330 | } | ||
331 | |||
332 | #define urb_dev(urb) (&(urb)->dev->dev) | ||
333 | |||
334 | static inline void handle_regs_int(struct urb *urb) | ||
335 | { | ||
336 | struct zd_usb *usb = urb->context; | ||
337 | struct zd_usb_interrupt *intr = &usb->intr; | ||
338 | int len; | ||
339 | |||
340 | ZD_ASSERT(in_interrupt()); | ||
341 | spin_lock(&intr->lock); | ||
342 | |||
343 | if (intr->read_regs_enabled) { | ||
344 | intr->read_regs.length = len = urb->actual_length; | ||
345 | |||
346 | if (len > sizeof(intr->read_regs.buffer)) | ||
347 | len = sizeof(intr->read_regs.buffer); | ||
348 | memcpy(intr->read_regs.buffer, urb->transfer_buffer, len); | ||
349 | intr->read_regs_enabled = 0; | ||
350 | complete(&intr->read_regs.completion); | ||
351 | goto out; | ||
352 | } | ||
353 | |||
354 | dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n"); | ||
355 | out: | ||
356 | spin_unlock(&intr->lock); | ||
357 | } | ||
358 | |||
359 | static inline void handle_retry_failed_int(struct urb *urb) | ||
360 | { | ||
361 | dev_dbg_f(urb_dev(urb), "retry failed interrupt\n"); | ||
362 | } | ||
363 | |||
364 | |||
365 | static void int_urb_complete(struct urb *urb, struct pt_regs *pt_regs) | ||
366 | { | ||
367 | int r; | ||
368 | struct usb_int_header *hdr; | ||
369 | |||
370 | switch (urb->status) { | ||
371 | case 0: | ||
372 | break; | ||
373 | case -ESHUTDOWN: | ||
374 | case -EINVAL: | ||
375 | case -ENODEV: | ||
376 | case -ENOENT: | ||
377 | case -ECONNRESET: | ||
378 | goto kfree; | ||
379 | case -EPIPE: | ||
380 | usb_clear_halt(urb->dev, EP_INT_IN); | ||
381 | /* FALL-THROUGH */ | ||
382 | default: | ||
383 | goto resubmit; | ||
384 | } | ||
385 | |||
386 | if (urb->actual_length < sizeof(hdr)) { | ||
387 | dev_dbg_f(urb_dev(urb), "error: urb %p to small\n", urb); | ||
388 | goto resubmit; | ||
389 | } | ||
390 | |||
391 | hdr = urb->transfer_buffer; | ||
392 | if (hdr->type != USB_INT_TYPE) { | ||
393 | dev_dbg_f(urb_dev(urb), "error: urb %p wrong type\n", urb); | ||
394 | goto resubmit; | ||
395 | } | ||
396 | |||
397 | switch (hdr->id) { | ||
398 | case USB_INT_ID_REGS: | ||
399 | handle_regs_int(urb); | ||
400 | break; | ||
401 | case USB_INT_ID_RETRY_FAILED: | ||
402 | handle_retry_failed_int(urb); | ||
403 | break; | ||
404 | default: | ||
405 | dev_dbg_f(urb_dev(urb), "error: urb %p unknown id %x\n", urb, | ||
406 | (unsigned int)hdr->id); | ||
407 | goto resubmit; | ||
408 | } | ||
409 | |||
410 | resubmit: | ||
411 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
412 | if (r) { | ||
413 | dev_dbg_f(urb_dev(urb), "resubmit urb %p\n", urb); | ||
414 | goto kfree; | ||
415 | } | ||
416 | return; | ||
417 | kfree: | ||
418 | kfree(urb->transfer_buffer); | ||
419 | } | ||
420 | |||
421 | static inline int int_urb_interval(struct usb_device *udev) | ||
422 | { | ||
423 | switch (udev->speed) { | ||
424 | case USB_SPEED_HIGH: | ||
425 | return 4; | ||
426 | case USB_SPEED_LOW: | ||
427 | return 10; | ||
428 | case USB_SPEED_FULL: | ||
429 | default: | ||
430 | return 1; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | static inline int usb_int_enabled(struct zd_usb *usb) | ||
435 | { | ||
436 | unsigned long flags; | ||
437 | struct zd_usb_interrupt *intr = &usb->intr; | ||
438 | struct urb *urb; | ||
439 | |||
440 | spin_lock_irqsave(&intr->lock, flags); | ||
441 | urb = intr->urb; | ||
442 | spin_unlock_irqrestore(&intr->lock, flags); | ||
443 | return urb != NULL; | ||
444 | } | ||
445 | |||
446 | int zd_usb_enable_int(struct zd_usb *usb) | ||
447 | { | ||
448 | int r; | ||
449 | struct usb_device *udev; | ||
450 | struct zd_usb_interrupt *intr = &usb->intr; | ||
451 | void *transfer_buffer = NULL; | ||
452 | struct urb *urb; | ||
453 | |||
454 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
455 | |||
456 | urb = usb_alloc_urb(0, GFP_NOFS); | ||
457 | if (!urb) { | ||
458 | r = -ENOMEM; | ||
459 | goto out; | ||
460 | } | ||
461 | |||
462 | ZD_ASSERT(!irqs_disabled()); | ||
463 | spin_lock_irq(&intr->lock); | ||
464 | if (intr->urb) { | ||
465 | spin_unlock_irq(&intr->lock); | ||
466 | r = 0; | ||
467 | goto error_free_urb; | ||
468 | } | ||
469 | intr->urb = urb; | ||
470 | spin_unlock_irq(&intr->lock); | ||
471 | |||
472 | /* TODO: make it a DMA buffer */ | ||
473 | r = -ENOMEM; | ||
474 | transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_NOFS); | ||
475 | if (!transfer_buffer) { | ||
476 | dev_dbg_f(zd_usb_dev(usb), | ||
477 | "couldn't allocate transfer_buffer\n"); | ||
478 | goto error_set_urb_null; | ||
479 | } | ||
480 | |||
481 | udev = zd_usb_to_usbdev(usb); | ||
482 | usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN), | ||
483 | transfer_buffer, USB_MAX_EP_INT_BUFFER, | ||
484 | int_urb_complete, usb, | ||
485 | intr->interval); | ||
486 | |||
487 | dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb); | ||
488 | r = usb_submit_urb(urb, GFP_NOFS); | ||
489 | if (r) { | ||
490 | dev_dbg_f(zd_usb_dev(usb), | ||
491 | "Couldn't submit urb. Error number %d\n", r); | ||
492 | goto error; | ||
493 | } | ||
494 | |||
495 | return 0; | ||
496 | error: | ||
497 | kfree(transfer_buffer); | ||
498 | error_set_urb_null: | ||
499 | spin_lock_irq(&intr->lock); | ||
500 | intr->urb = NULL; | ||
501 | spin_unlock_irq(&intr->lock); | ||
502 | error_free_urb: | ||
503 | usb_free_urb(urb); | ||
504 | out: | ||
505 | return r; | ||
506 | } | ||
507 | |||
508 | void zd_usb_disable_int(struct zd_usb *usb) | ||
509 | { | ||
510 | unsigned long flags; | ||
511 | struct zd_usb_interrupt *intr = &usb->intr; | ||
512 | struct urb *urb; | ||
513 | |||
514 | spin_lock_irqsave(&intr->lock, flags); | ||
515 | urb = intr->urb; | ||
516 | if (!urb) { | ||
517 | spin_unlock_irqrestore(&intr->lock, flags); | ||
518 | return; | ||
519 | } | ||
520 | intr->urb = NULL; | ||
521 | spin_unlock_irqrestore(&intr->lock, flags); | ||
522 | |||
523 | usb_kill_urb(urb); | ||
524 | dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb); | ||
525 | usb_free_urb(urb); | ||
526 | } | ||
527 | |||
528 | static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, | ||
529 | unsigned int length) | ||
530 | { | ||
531 | int i; | ||
532 | struct zd_mac *mac = zd_usb_to_mac(usb); | ||
533 | const struct rx_length_info *length_info; | ||
534 | |||
535 | if (length < sizeof(struct rx_length_info)) { | ||
536 | /* It's not a complete packet anyhow. */ | ||
537 | return; | ||
538 | } | ||
539 | length_info = (struct rx_length_info *) | ||
540 | (buffer + length - sizeof(struct rx_length_info)); | ||
541 | |||
542 | /* It might be that three frames are merged into a single URB | ||
543 | * transaction. We have to check for the length info tag. | ||
544 | * | ||
545 | * While testing we discovered that length_info might be unaligned, | ||
546 | * because if USB transactions are merged, the last packet will not | ||
547 | * be padded. Unaligned access might also happen if the length_info | ||
548 | * structure is not present. | ||
549 | */ | ||
550 | if (get_unaligned(&length_info->tag) == RX_LENGTH_INFO_TAG) { | ||
551 | unsigned int l, k, n; | ||
552 | for (i = 0, l = 0;; i++) { | ||
553 | k = le16_to_cpu(get_unaligned( | ||
554 | &length_info->length[i])); | ||
555 | n = l+k; | ||
556 | if (n > length) | ||
557 | return; | ||
558 | zd_mac_rx(mac, buffer+l, k); | ||
559 | if (i >= 2) | ||
560 | return; | ||
561 | l = (n+3) & ~3; | ||
562 | } | ||
563 | } else { | ||
564 | zd_mac_rx(mac, buffer, length); | ||
565 | } | ||
566 | } | ||
567 | |||
568 | static void rx_urb_complete(struct urb *urb, struct pt_regs *pt_regs) | ||
569 | { | ||
570 | struct zd_usb *usb; | ||
571 | struct zd_usb_rx *rx; | ||
572 | const u8 *buffer; | ||
573 | unsigned int length; | ||
574 | |||
575 | switch (urb->status) { | ||
576 | case 0: | ||
577 | break; | ||
578 | case -ESHUTDOWN: | ||
579 | case -EINVAL: | ||
580 | case -ENODEV: | ||
581 | case -ENOENT: | ||
582 | case -ECONNRESET: | ||
583 | return; | ||
584 | case -EPIPE: | ||
585 | usb_clear_halt(urb->dev, EP_DATA_IN); | ||
586 | /* FALL-THROUGH */ | ||
587 | default: | ||
588 | dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); | ||
589 | goto resubmit; | ||
590 | } | ||
591 | |||
592 | buffer = urb->transfer_buffer; | ||
593 | length = urb->actual_length; | ||
594 | usb = urb->context; | ||
595 | rx = &usb->rx; | ||
596 | |||
597 | if (length%rx->usb_packet_size > rx->usb_packet_size-4) { | ||
598 | /* If there is an old first fragment, we don't care. */ | ||
599 | dev_dbg_f(urb_dev(urb), "*** first fragment ***\n"); | ||
600 | ZD_ASSERT(length <= ARRAY_SIZE(rx->fragment)); | ||
601 | spin_lock(&rx->lock); | ||
602 | memcpy(rx->fragment, buffer, length); | ||
603 | rx->fragment_length = length; | ||
604 | spin_unlock(&rx->lock); | ||
605 | goto resubmit; | ||
606 | } | ||
607 | |||
608 | spin_lock(&rx->lock); | ||
609 | if (rx->fragment_length > 0) { | ||
610 | /* We are on a second fragment, we believe */ | ||
611 | ZD_ASSERT(length + rx->fragment_length <= | ||
612 | ARRAY_SIZE(rx->fragment)); | ||
613 | dev_dbg_f(urb_dev(urb), "*** second fragment ***\n"); | ||
614 | memcpy(rx->fragment+rx->fragment_length, buffer, length); | ||
615 | handle_rx_packet(usb, rx->fragment, | ||
616 | rx->fragment_length + length); | ||
617 | rx->fragment_length = 0; | ||
618 | spin_unlock(&rx->lock); | ||
619 | } else { | ||
620 | spin_unlock(&rx->lock); | ||
621 | handle_rx_packet(usb, buffer, length); | ||
622 | } | ||
623 | |||
624 | resubmit: | ||
625 | usb_submit_urb(urb, GFP_ATOMIC); | ||
626 | } | ||
627 | |||
628 | struct urb *alloc_urb(struct zd_usb *usb) | ||
629 | { | ||
630 | struct usb_device *udev = zd_usb_to_usbdev(usb); | ||
631 | struct urb *urb; | ||
632 | void *buffer; | ||
633 | |||
634 | urb = usb_alloc_urb(0, GFP_NOFS); | ||
635 | if (!urb) | ||
636 | return NULL; | ||
637 | buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_NOFS, | ||
638 | &urb->transfer_dma); | ||
639 | if (!buffer) { | ||
640 | usb_free_urb(urb); | ||
641 | return NULL; | ||
642 | } | ||
643 | |||
644 | usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN), | ||
645 | buffer, USB_MAX_RX_SIZE, | ||
646 | rx_urb_complete, usb); | ||
647 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
648 | |||
649 | return urb; | ||
650 | } | ||
651 | |||
652 | void free_urb(struct urb *urb) | ||
653 | { | ||
654 | if (!urb) | ||
655 | return; | ||
656 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, | ||
657 | urb->transfer_buffer, urb->transfer_dma); | ||
658 | usb_free_urb(urb); | ||
659 | } | ||
660 | |||
661 | int zd_usb_enable_rx(struct zd_usb *usb) | ||
662 | { | ||
663 | int i, r; | ||
664 | struct zd_usb_rx *rx = &usb->rx; | ||
665 | struct urb **urbs; | ||
666 | |||
667 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
668 | |||
669 | r = -ENOMEM; | ||
670 | urbs = kcalloc(URBS_COUNT, sizeof(struct urb *), GFP_NOFS); | ||
671 | if (!urbs) | ||
672 | goto error; | ||
673 | for (i = 0; i < URBS_COUNT; i++) { | ||
674 | urbs[i] = alloc_urb(usb); | ||
675 | if (!urbs[i]) | ||
676 | goto error; | ||
677 | } | ||
678 | |||
679 | ZD_ASSERT(!irqs_disabled()); | ||
680 | spin_lock_irq(&rx->lock); | ||
681 | if (rx->urbs) { | ||
682 | spin_unlock_irq(&rx->lock); | ||
683 | r = 0; | ||
684 | goto error; | ||
685 | } | ||
686 | rx->urbs = urbs; | ||
687 | rx->urbs_count = URBS_COUNT; | ||
688 | spin_unlock_irq(&rx->lock); | ||
689 | |||
690 | for (i = 0; i < URBS_COUNT; i++) { | ||
691 | r = usb_submit_urb(urbs[i], GFP_NOFS); | ||
692 | if (r) | ||
693 | goto error_submit; | ||
694 | } | ||
695 | |||
696 | return 0; | ||
697 | error_submit: | ||
698 | for (i = 0; i < URBS_COUNT; i++) { | ||
699 | usb_kill_urb(urbs[i]); | ||
700 | } | ||
701 | spin_lock_irq(&rx->lock); | ||
702 | rx->urbs = NULL; | ||
703 | rx->urbs_count = 0; | ||
704 | spin_unlock_irq(&rx->lock); | ||
705 | error: | ||
706 | if (urbs) { | ||
707 | for (i = 0; i < URBS_COUNT; i++) | ||
708 | free_urb(urbs[i]); | ||
709 | } | ||
710 | return r; | ||
711 | } | ||
712 | |||
713 | void zd_usb_disable_rx(struct zd_usb *usb) | ||
714 | { | ||
715 | int i; | ||
716 | unsigned long flags; | ||
717 | struct urb **urbs; | ||
718 | unsigned int count; | ||
719 | struct zd_usb_rx *rx = &usb->rx; | ||
720 | |||
721 | spin_lock_irqsave(&rx->lock, flags); | ||
722 | urbs = rx->urbs; | ||
723 | count = rx->urbs_count; | ||
724 | spin_unlock_irqrestore(&rx->lock, flags); | ||
725 | if (!urbs) | ||
726 | return; | ||
727 | |||
728 | for (i = 0; i < count; i++) { | ||
729 | usb_kill_urb(urbs[i]); | ||
730 | free_urb(urbs[i]); | ||
731 | } | ||
732 | kfree(urbs); | ||
733 | |||
734 | spin_lock_irqsave(&rx->lock, flags); | ||
735 | rx->urbs = NULL; | ||
736 | rx->urbs_count = 0; | ||
737 | spin_unlock_irqrestore(&rx->lock, flags); | ||
738 | } | ||
739 | |||
740 | static void tx_urb_complete(struct urb *urb, struct pt_regs *pt_regs) | ||
741 | { | ||
742 | int r; | ||
743 | |||
744 | switch (urb->status) { | ||
745 | case 0: | ||
746 | break; | ||
747 | case -ESHUTDOWN: | ||
748 | case -EINVAL: | ||
749 | case -ENODEV: | ||
750 | case -ENOENT: | ||
751 | case -ECONNRESET: | ||
752 | dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); | ||
753 | break; | ||
754 | case -EPIPE: | ||
755 | usb_clear_halt(urb->dev, EP_DATA_OUT); | ||
756 | /* FALL-THROUGH */ | ||
757 | default: | ||
758 | dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); | ||
759 | goto resubmit; | ||
760 | } | ||
761 | free_urb: | ||
762 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, | ||
763 | urb->transfer_buffer, urb->transfer_dma); | ||
764 | usb_free_urb(urb); | ||
765 | return; | ||
766 | resubmit: | ||
767 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
768 | if (r) { | ||
769 | dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r); | ||
770 | goto free_urb; | ||
771 | } | ||
772 | } | ||
773 | |||
774 | /* Puts the frame on the USB endpoint. It doesn't wait for | ||
775 | * completion. The frame must contain the control set. | ||
776 | */ | ||
777 | int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length) | ||
778 | { | ||
779 | int r; | ||
780 | struct usb_device *udev = zd_usb_to_usbdev(usb); | ||
781 | struct urb *urb; | ||
782 | void *buffer; | ||
783 | |||
784 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
785 | if (!urb) { | ||
786 | r = -ENOMEM; | ||
787 | goto out; | ||
788 | } | ||
789 | |||
790 | buffer = usb_buffer_alloc(zd_usb_to_usbdev(usb), length, GFP_ATOMIC, | ||
791 | &urb->transfer_dma); | ||
792 | if (!buffer) { | ||
793 | r = -ENOMEM; | ||
794 | goto error_free_urb; | ||
795 | } | ||
796 | memcpy(buffer, frame, length); | ||
797 | |||
798 | usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT), | ||
799 | buffer, length, tx_urb_complete, NULL); | ||
800 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
801 | |||
802 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
803 | if (r) | ||
804 | goto error; | ||
805 | return 0; | ||
806 | error: | ||
807 | usb_buffer_free(zd_usb_to_usbdev(usb), length, buffer, | ||
808 | urb->transfer_dma); | ||
809 | error_free_urb: | ||
810 | usb_free_urb(urb); | ||
811 | out: | ||
812 | return r; | ||
813 | } | ||
814 | |||
815 | static inline void init_usb_interrupt(struct zd_usb *usb) | ||
816 | { | ||
817 | struct zd_usb_interrupt *intr = &usb->intr; | ||
818 | |||
819 | spin_lock_init(&intr->lock); | ||
820 | intr->interval = int_urb_interval(zd_usb_to_usbdev(usb)); | ||
821 | init_completion(&intr->read_regs.completion); | ||
822 | intr->read_regs.cr_int_addr = cpu_to_le16(usb_addr(usb, CR_INTERRUPT)); | ||
823 | } | ||
824 | |||
825 | static inline void init_usb_rx(struct zd_usb *usb) | ||
826 | { | ||
827 | struct zd_usb_rx *rx = &usb->rx; | ||
828 | spin_lock_init(&rx->lock); | ||
829 | if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) { | ||
830 | rx->usb_packet_size = 512; | ||
831 | } else { | ||
832 | rx->usb_packet_size = 64; | ||
833 | } | ||
834 | ZD_ASSERT(rx->fragment_length == 0); | ||
835 | } | ||
836 | |||
837 | static inline void init_usb_tx(struct zd_usb *usb) | ||
838 | { | ||
839 | /* FIXME: at this point we will allocate a fixed number of urb's for | ||
840 | * use in a cyclic scheme */ | ||
841 | } | ||
842 | |||
843 | void zd_usb_init(struct zd_usb *usb, struct net_device *netdev, | ||
844 | struct usb_interface *intf) | ||
845 | { | ||
846 | memset(usb, 0, sizeof(*usb)); | ||
847 | usb->intf = usb_get_intf(intf); | ||
848 | usb_set_intfdata(usb->intf, netdev); | ||
849 | init_usb_interrupt(usb); | ||
850 | init_usb_tx(usb); | ||
851 | init_usb_rx(usb); | ||
852 | } | ||
853 | |||
854 | int zd_usb_init_hw(struct zd_usb *usb) | ||
855 | { | ||
856 | int r; | ||
857 | struct zd_chip *chip = zd_usb_to_chip(usb); | ||
858 | |||
859 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
860 | r = zd_ioread16_locked(chip, &usb->fw_base_offset, | ||
861 | USB_REG((u16)FW_BASE_ADDR_OFFSET)); | ||
862 | if (r) | ||
863 | return r; | ||
864 | dev_dbg_f(zd_usb_dev(usb), "fw_base_offset: %#06hx\n", | ||
865 | usb->fw_base_offset); | ||
866 | |||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | void zd_usb_clear(struct zd_usb *usb) | ||
871 | { | ||
872 | usb_set_intfdata(usb->intf, NULL); | ||
873 | usb_put_intf(usb->intf); | ||
874 | memset(usb, 0, sizeof(*usb)); | ||
875 | /* FIXME: usb_interrupt, usb_tx, usb_rx? */ | ||
876 | } | ||
877 | |||
878 | static const char *speed(enum usb_device_speed speed) | ||
879 | { | ||
880 | switch (speed) { | ||
881 | case USB_SPEED_LOW: | ||
882 | return "low"; | ||
883 | case USB_SPEED_FULL: | ||
884 | return "full"; | ||
885 | case USB_SPEED_HIGH: | ||
886 | return "high"; | ||
887 | default: | ||
888 | return "unknown speed"; | ||
889 | } | ||
890 | } | ||
891 | |||
892 | static int scnprint_id(struct usb_device *udev, char *buffer, size_t size) | ||
893 | { | ||
894 | return scnprintf(buffer, size, "%04hx:%04hx v%04hx %s", | ||
895 | le16_to_cpu(udev->descriptor.idVendor), | ||
896 | le16_to_cpu(udev->descriptor.idProduct), | ||
897 | get_bcdDevice(udev), | ||
898 | speed(udev->speed)); | ||
899 | } | ||
900 | |||
901 | int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size) | ||
902 | { | ||
903 | struct usb_device *udev = interface_to_usbdev(usb->intf); | ||
904 | return scnprint_id(udev, buffer, size); | ||
905 | } | ||
906 | |||
907 | #ifdef DEBUG | ||
908 | static void print_id(struct usb_device *udev) | ||
909 | { | ||
910 | char buffer[40]; | ||
911 | |||
912 | scnprint_id(udev, buffer, sizeof(buffer)); | ||
913 | buffer[sizeof(buffer)-1] = 0; | ||
914 | dev_dbg_f(&udev->dev, "%s\n", buffer); | ||
915 | } | ||
916 | #else | ||
917 | #define print_id(udev) do { } while (0) | ||
918 | #endif | ||
919 | |||
920 | static int probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
921 | { | ||
922 | int r; | ||
923 | struct usb_device *udev = interface_to_usbdev(intf); | ||
924 | struct net_device *netdev = NULL; | ||
925 | |||
926 | print_id(udev); | ||
927 | |||
928 | switch (udev->speed) { | ||
929 | case USB_SPEED_LOW: | ||
930 | case USB_SPEED_FULL: | ||
931 | case USB_SPEED_HIGH: | ||
932 | break; | ||
933 | default: | ||
934 | dev_dbg_f(&intf->dev, "Unknown USB speed\n"); | ||
935 | r = -ENODEV; | ||
936 | goto error; | ||
937 | } | ||
938 | |||
939 | netdev = zd_netdev_alloc(intf); | ||
940 | if (netdev == NULL) { | ||
941 | r = -ENOMEM; | ||
942 | goto error; | ||
943 | } | ||
944 | |||
945 | r = upload_firmware(udev, id->driver_info); | ||
946 | if (r) { | ||
947 | dev_err(&intf->dev, | ||
948 | "couldn't load firmware. Error number %d\n", r); | ||
949 | goto error; | ||
950 | } | ||
951 | |||
952 | r = usb_reset_configuration(udev); | ||
953 | if (r) { | ||
954 | dev_dbg_f(&intf->dev, | ||
955 | "couldn't reset configuration. Error number %d\n", r); | ||
956 | goto error; | ||
957 | } | ||
958 | |||
959 | /* At this point the interrupt endpoint is not generally enabled. We | ||
960 | * save the USB bandwidth until the network device is opened. But | ||
961 | * notify that the initialization of the MAC will require the | ||
962 | * interrupts to be temporary enabled. | ||
963 | */ | ||
964 | r = zd_mac_init_hw(zd_netdev_mac(netdev), id->driver_info); | ||
965 | if (r) { | ||
966 | dev_dbg_f(&intf->dev, | ||
967 | "couldn't initialize mac. Error number %d\n", r); | ||
968 | goto error; | ||
969 | } | ||
970 | |||
971 | r = register_netdev(netdev); | ||
972 | if (r) { | ||
973 | dev_dbg_f(&intf->dev, | ||
974 | "couldn't register netdev. Error number %d\n", r); | ||
975 | goto error; | ||
976 | } | ||
977 | |||
978 | dev_dbg_f(&intf->dev, "successful\n"); | ||
979 | dev_info(&intf->dev,"%s\n", netdev->name); | ||
980 | return 0; | ||
981 | error: | ||
982 | usb_reset_device(interface_to_usbdev(intf)); | ||
983 | zd_netdev_free(netdev); | ||
984 | return r; | ||
985 | } | ||
986 | |||
987 | static void disconnect(struct usb_interface *intf) | ||
988 | { | ||
989 | struct net_device *netdev = zd_intf_to_netdev(intf); | ||
990 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
991 | struct zd_usb *usb = &mac->chip.usb; | ||
992 | |||
993 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
994 | |||
995 | zd_netdev_disconnect(netdev); | ||
996 | |||
997 | /* Just in case something has gone wrong! */ | ||
998 | zd_usb_disable_rx(usb); | ||
999 | zd_usb_disable_int(usb); | ||
1000 | |||
1001 | /* If the disconnect has been caused by a removal of the | ||
1002 | * driver module, the reset allows reloading of the driver. If the | ||
1003 | * reset will not be executed here, the upload of the firmware in the | ||
1004 | * probe function caused by the reloading of the driver will fail. | ||
1005 | */ | ||
1006 | usb_reset_device(interface_to_usbdev(intf)); | ||
1007 | |||
1008 | /* If somebody still waits on this lock now, this is an error. */ | ||
1009 | zd_netdev_free(netdev); | ||
1010 | dev_dbg(&intf->dev, "disconnected\n"); | ||
1011 | } | ||
1012 | |||
1013 | static struct usb_driver driver = { | ||
1014 | .name = "zd1211rw", | ||
1015 | .id_table = usb_ids, | ||
1016 | .probe = probe, | ||
1017 | .disconnect = disconnect, | ||
1018 | }; | ||
1019 | |||
1020 | static int __init usb_init(void) | ||
1021 | { | ||
1022 | int r; | ||
1023 | |||
1024 | pr_debug("usb_init()\n"); | ||
1025 | |||
1026 | r = usb_register(&driver); | ||
1027 | if (r) { | ||
1028 | printk(KERN_ERR "usb_register() failed. Error number %d\n", r); | ||
1029 | return r; | ||
1030 | } | ||
1031 | |||
1032 | pr_debug("zd1211rw initialized\n"); | ||
1033 | return 0; | ||
1034 | } | ||
1035 | |||
1036 | static void __exit usb_exit(void) | ||
1037 | { | ||
1038 | pr_debug("usb_exit()\n"); | ||
1039 | usb_deregister(&driver); | ||
1040 | } | ||
1041 | |||
1042 | module_init(usb_init); | ||
1043 | module_exit(usb_exit); | ||
1044 | |||
1045 | static int usb_int_regs_length(unsigned int count) | ||
1046 | { | ||
1047 | return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data); | ||
1048 | } | ||
1049 | |||
1050 | static void prepare_read_regs_int(struct zd_usb *usb) | ||
1051 | { | ||
1052 | struct zd_usb_interrupt *intr = &usb->intr; | ||
1053 | |||
1054 | spin_lock(&intr->lock); | ||
1055 | intr->read_regs_enabled = 1; | ||
1056 | INIT_COMPLETION(intr->read_regs.completion); | ||
1057 | spin_unlock(&intr->lock); | ||
1058 | } | ||
1059 | |||
1060 | static int get_results(struct zd_usb *usb, u16 *values, | ||
1061 | struct usb_req_read_regs *req, unsigned int count) | ||
1062 | { | ||
1063 | int r; | ||
1064 | int i; | ||
1065 | struct zd_usb_interrupt *intr = &usb->intr; | ||
1066 | struct read_regs_int *rr = &intr->read_regs; | ||
1067 | struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer; | ||
1068 | |||
1069 | spin_lock(&intr->lock); | ||
1070 | |||
1071 | r = -EIO; | ||
1072 | /* The created block size seems to be larger than expected. | ||
1073 | * However results appear to be correct. | ||
1074 | */ | ||
1075 | if (rr->length < usb_int_regs_length(count)) { | ||
1076 | dev_dbg_f(zd_usb_dev(usb), | ||
1077 | "error: actual length %d less than expected %d\n", | ||
1078 | rr->length, usb_int_regs_length(count)); | ||
1079 | goto error_unlock; | ||
1080 | } | ||
1081 | if (rr->length > sizeof(rr->buffer)) { | ||
1082 | dev_dbg_f(zd_usb_dev(usb), | ||
1083 | "error: actual length %d exceeds buffer size %zu\n", | ||
1084 | rr->length, sizeof(rr->buffer)); | ||
1085 | goto error_unlock; | ||
1086 | } | ||
1087 | |||
1088 | for (i = 0; i < count; i++) { | ||
1089 | struct reg_data *rd = ®s->regs[i]; | ||
1090 | if (rd->addr != req->addr[i]) { | ||
1091 | dev_dbg_f(zd_usb_dev(usb), | ||
1092 | "rd[%d] addr %#06hx expected %#06hx\n", i, | ||
1093 | le16_to_cpu(rd->addr), | ||
1094 | le16_to_cpu(req->addr[i])); | ||
1095 | goto error_unlock; | ||
1096 | } | ||
1097 | values[i] = le16_to_cpu(rd->value); | ||
1098 | } | ||
1099 | |||
1100 | r = 0; | ||
1101 | error_unlock: | ||
1102 | spin_unlock(&intr->lock); | ||
1103 | return r; | ||
1104 | } | ||
1105 | |||
1106 | int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, | ||
1107 | const zd_addr_t *addresses, unsigned int count) | ||
1108 | { | ||
1109 | int r; | ||
1110 | int i, req_len, actual_req_len; | ||
1111 | struct usb_device *udev; | ||
1112 | struct usb_req_read_regs *req = NULL; | ||
1113 | unsigned long timeout; | ||
1114 | |||
1115 | if (count < 1) { | ||
1116 | dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n"); | ||
1117 | return -EINVAL; | ||
1118 | } | ||
1119 | if (count > USB_MAX_IOREAD16_COUNT) { | ||
1120 | dev_dbg_f(zd_usb_dev(usb), | ||
1121 | "error: count %u exceeds possible max %u\n", | ||
1122 | count, USB_MAX_IOREAD16_COUNT); | ||
1123 | return -EINVAL; | ||
1124 | } | ||
1125 | if (in_atomic()) { | ||
1126 | dev_dbg_f(zd_usb_dev(usb), | ||
1127 | "error: io in atomic context not supported\n"); | ||
1128 | return -EWOULDBLOCK; | ||
1129 | } | ||
1130 | if (!usb_int_enabled(usb)) { | ||
1131 | dev_dbg_f(zd_usb_dev(usb), | ||
1132 | "error: usb interrupt not enabled\n"); | ||
1133 | return -EWOULDBLOCK; | ||
1134 | } | ||
1135 | |||
1136 | req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16); | ||
1137 | req = kmalloc(req_len, GFP_NOFS); | ||
1138 | if (!req) | ||
1139 | return -ENOMEM; | ||
1140 | req->id = cpu_to_le16(USB_REQ_READ_REGS); | ||
1141 | for (i = 0; i < count; i++) | ||
1142 | req->addr[i] = cpu_to_le16(usb_addr(usb, addresses[i])); | ||
1143 | |||
1144 | udev = zd_usb_to_usbdev(usb); | ||
1145 | prepare_read_regs_int(usb); | ||
1146 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | ||
1147 | req, req_len, &actual_req_len, 1000 /* ms */); | ||
1148 | if (r) { | ||
1149 | dev_dbg_f(zd_usb_dev(usb), | ||
1150 | "error in usb_bulk_msg(). Error number %d\n", r); | ||
1151 | goto error; | ||
1152 | } | ||
1153 | if (req_len != actual_req_len) { | ||
1154 | dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()\n" | ||
1155 | " req_len %d != actual_req_len %d\n", | ||
1156 | req_len, actual_req_len); | ||
1157 | r = -EIO; | ||
1158 | goto error; | ||
1159 | } | ||
1160 | |||
1161 | timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion, | ||
1162 | msecs_to_jiffies(1000)); | ||
1163 | if (!timeout) { | ||
1164 | disable_read_regs_int(usb); | ||
1165 | dev_dbg_f(zd_usb_dev(usb), "read timed out\n"); | ||
1166 | r = -ETIMEDOUT; | ||
1167 | goto error; | ||
1168 | } | ||
1169 | |||
1170 | r = get_results(usb, values, req, count); | ||
1171 | error: | ||
1172 | kfree(req); | ||
1173 | return r; | ||
1174 | } | ||
1175 | |||
1176 | int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | ||
1177 | unsigned int count) | ||
1178 | { | ||
1179 | int r; | ||
1180 | struct usb_device *udev; | ||
1181 | struct usb_req_write_regs *req = NULL; | ||
1182 | int i, req_len, actual_req_len; | ||
1183 | |||
1184 | if (count == 0) | ||
1185 | return 0; | ||
1186 | if (count > USB_MAX_IOWRITE16_COUNT) { | ||
1187 | dev_dbg_f(zd_usb_dev(usb), | ||
1188 | "error: count %u exceeds possible max %u\n", | ||
1189 | count, USB_MAX_IOWRITE16_COUNT); | ||
1190 | return -EINVAL; | ||
1191 | } | ||
1192 | if (in_atomic()) { | ||
1193 | dev_dbg_f(zd_usb_dev(usb), | ||
1194 | "error: io in atomic context not supported\n"); | ||
1195 | return -EWOULDBLOCK; | ||
1196 | } | ||
1197 | |||
1198 | req_len = sizeof(struct usb_req_write_regs) + | ||
1199 | count * sizeof(struct reg_data); | ||
1200 | req = kmalloc(req_len, GFP_NOFS); | ||
1201 | if (!req) | ||
1202 | return -ENOMEM; | ||
1203 | |||
1204 | req->id = cpu_to_le16(USB_REQ_WRITE_REGS); | ||
1205 | for (i = 0; i < count; i++) { | ||
1206 | struct reg_data *rw = &req->reg_writes[i]; | ||
1207 | rw->addr = cpu_to_le16(usb_addr(usb, ioreqs[i].addr)); | ||
1208 | rw->value = cpu_to_le16(ioreqs[i].value); | ||
1209 | } | ||
1210 | |||
1211 | udev = zd_usb_to_usbdev(usb); | ||
1212 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | ||
1213 | req, req_len, &actual_req_len, 1000 /* ms */); | ||
1214 | if (r) { | ||
1215 | dev_dbg_f(zd_usb_dev(usb), | ||
1216 | "error in usb_bulk_msg(). Error number %d\n", r); | ||
1217 | goto error; | ||
1218 | } | ||
1219 | if (req_len != actual_req_len) { | ||
1220 | dev_dbg_f(zd_usb_dev(usb), | ||
1221 | "error in usb_bulk_msg()" | ||
1222 | " req_len %d != actual_req_len %d\n", | ||
1223 | req_len, actual_req_len); | ||
1224 | r = -EIO; | ||
1225 | goto error; | ||
1226 | } | ||
1227 | |||
1228 | /* FALL-THROUGH with r == 0 */ | ||
1229 | error: | ||
1230 | kfree(req); | ||
1231 | return r; | ||
1232 | } | ||
1233 | |||
1234 | int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) | ||
1235 | { | ||
1236 | int r; | ||
1237 | struct usb_device *udev; | ||
1238 | struct usb_req_rfwrite *req = NULL; | ||
1239 | int i, req_len, actual_req_len; | ||
1240 | u16 bit_value_template; | ||
1241 | |||
1242 | if (in_atomic()) { | ||
1243 | dev_dbg_f(zd_usb_dev(usb), | ||
1244 | "error: io in atomic context not supported\n"); | ||
1245 | return -EWOULDBLOCK; | ||
1246 | } | ||
1247 | if (bits < USB_MIN_RFWRITE_BIT_COUNT) { | ||
1248 | dev_dbg_f(zd_usb_dev(usb), | ||
1249 | "error: bits %d are smaller than" | ||
1250 | " USB_MIN_RFWRITE_BIT_COUNT %d\n", | ||
1251 | bits, USB_MIN_RFWRITE_BIT_COUNT); | ||
1252 | return -EINVAL; | ||
1253 | } | ||
1254 | if (bits > USB_MAX_RFWRITE_BIT_COUNT) { | ||
1255 | dev_dbg_f(zd_usb_dev(usb), | ||
1256 | "error: bits %d exceed USB_MAX_RFWRITE_BIT_COUNT %d\n", | ||
1257 | bits, USB_MAX_RFWRITE_BIT_COUNT); | ||
1258 | return -EINVAL; | ||
1259 | } | ||
1260 | #ifdef DEBUG | ||
1261 | if (value & (~0UL << bits)) { | ||
1262 | dev_dbg_f(zd_usb_dev(usb), | ||
1263 | "error: value %#09x has bits >= %d set\n", | ||
1264 | value, bits); | ||
1265 | return -EINVAL; | ||
1266 | } | ||
1267 | #endif /* DEBUG */ | ||
1268 | |||
1269 | dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits); | ||
1270 | |||
1271 | r = zd_usb_ioread16(usb, &bit_value_template, CR203); | ||
1272 | if (r) { | ||
1273 | dev_dbg_f(zd_usb_dev(usb), | ||
1274 | "error %d: Couldn't read CR203\n", r); | ||
1275 | goto out; | ||
1276 | } | ||
1277 | bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA); | ||
1278 | |||
1279 | req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16); | ||
1280 | req = kmalloc(req_len, GFP_NOFS); | ||
1281 | if (!req) | ||
1282 | return -ENOMEM; | ||
1283 | |||
1284 | req->id = cpu_to_le16(USB_REQ_WRITE_RF); | ||
1285 | /* 1: 3683a, but not used in ZYDAS driver */ | ||
1286 | req->value = cpu_to_le16(2); | ||
1287 | req->bits = cpu_to_le16(bits); | ||
1288 | |||
1289 | for (i = 0; i < bits; i++) { | ||
1290 | u16 bv = bit_value_template; | ||
1291 | if (value & (1 << (bits-1-i))) | ||
1292 | bv |= RF_DATA; | ||
1293 | req->bit_values[i] = cpu_to_le16(bv); | ||
1294 | } | ||
1295 | |||
1296 | udev = zd_usb_to_usbdev(usb); | ||
1297 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | ||
1298 | req, req_len, &actual_req_len, 1000 /* ms */); | ||
1299 | if (r) { | ||
1300 | dev_dbg_f(zd_usb_dev(usb), | ||
1301 | "error in usb_bulk_msg(). Error number %d\n", r); | ||
1302 | goto out; | ||
1303 | } | ||
1304 | if (req_len != actual_req_len) { | ||
1305 | dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()" | ||
1306 | " req_len %d != actual_req_len %d\n", | ||
1307 | req_len, actual_req_len); | ||
1308 | r = -EIO; | ||
1309 | goto out; | ||
1310 | } | ||
1311 | |||
1312 | /* FALL-THROUGH with r == 0 */ | ||
1313 | out: | ||
1314 | kfree(req); | ||
1315 | return r; | ||
1316 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h new file mode 100644 index 000000000000..d6420283bd5a --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_usb.h | |||
@@ -0,0 +1,240 @@ | |||
1 | /* zd_usb.h: Header for USB interface implemented by ZD1211 chip | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef _ZD_USB_H | ||
19 | #define _ZD_USB_H | ||
20 | |||
21 | #include <linux/completion.h> | ||
22 | #include <linux/netdevice.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/skbuff.h> | ||
25 | #include <linux/usb.h> | ||
26 | |||
27 | #include "zd_def.h" | ||
28 | #include "zd_types.h" | ||
29 | |||
30 | enum devicetype { | ||
31 | DEVICE_ZD1211 = 0, | ||
32 | DEVICE_ZD1211B = 1, | ||
33 | }; | ||
34 | |||
35 | enum endpoints { | ||
36 | EP_CTRL = 0, | ||
37 | EP_DATA_OUT = 1, | ||
38 | EP_DATA_IN = 2, | ||
39 | EP_INT_IN = 3, | ||
40 | EP_REGS_OUT = 4, | ||
41 | }; | ||
42 | |||
43 | enum { | ||
44 | USB_MAX_TRANSFER_SIZE = 4096, /* bytes */ | ||
45 | /* FIXME: The original driver uses this value. We have to check, | ||
46 | * whether the MAX_TRANSFER_SIZE is sufficient and this needs only be | ||
47 | * used if one combined frame is split over two USB transactions. | ||
48 | */ | ||
49 | USB_MAX_RX_SIZE = 4800, /* bytes */ | ||
50 | USB_MAX_IOWRITE16_COUNT = 15, | ||
51 | USB_MAX_IOWRITE32_COUNT = USB_MAX_IOWRITE16_COUNT/2, | ||
52 | USB_MAX_IOREAD16_COUNT = 15, | ||
53 | USB_MAX_IOREAD32_COUNT = USB_MAX_IOREAD16_COUNT/2, | ||
54 | USB_MIN_RFWRITE_BIT_COUNT = 16, | ||
55 | USB_MAX_RFWRITE_BIT_COUNT = 28, | ||
56 | USB_MAX_EP_INT_BUFFER = 64, | ||
57 | USB_ZD1211B_BCD_DEVICE = 0x4810, | ||
58 | }; | ||
59 | |||
60 | enum control_requests { | ||
61 | USB_REQ_WRITE_REGS = 0x21, | ||
62 | USB_REQ_READ_REGS = 0x22, | ||
63 | USB_REQ_WRITE_RF = 0x23, | ||
64 | USB_REQ_PROG_FLASH = 0x24, | ||
65 | USB_REQ_EEPROM_START = 0x0128, /* ? request is a byte */ | ||
66 | USB_REQ_EEPROM_MID = 0x28, | ||
67 | USB_REQ_EEPROM_END = 0x0228, /* ? request is a byte */ | ||
68 | USB_REQ_FIRMWARE_DOWNLOAD = 0x30, | ||
69 | USB_REQ_FIRMWARE_CONFIRM = 0x31, | ||
70 | USB_REQ_FIRMWARE_READ_DATA = 0x32, | ||
71 | }; | ||
72 | |||
73 | struct usb_req_read_regs { | ||
74 | __le16 id; | ||
75 | __le16 addr[0]; | ||
76 | } __attribute__((packed)); | ||
77 | |||
78 | struct reg_data { | ||
79 | __le16 addr; | ||
80 | __le16 value; | ||
81 | } __attribute__((packed)); | ||
82 | |||
83 | struct usb_req_write_regs { | ||
84 | __le16 id; | ||
85 | struct reg_data reg_writes[0]; | ||
86 | } __attribute__((packed)); | ||
87 | |||
88 | enum { | ||
89 | RF_IF_LE = 0x02, | ||
90 | RF_CLK = 0x04, | ||
91 | RF_DATA = 0x08, | ||
92 | }; | ||
93 | |||
94 | struct usb_req_rfwrite { | ||
95 | __le16 id; | ||
96 | __le16 value; | ||
97 | /* 1: 3683a */ | ||
98 | /* 2: other (default) */ | ||
99 | __le16 bits; | ||
100 | /* RF2595: 24 */ | ||
101 | __le16 bit_values[0]; | ||
102 | /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ | ||
103 | } __attribute__((packed)); | ||
104 | |||
105 | /* USB interrupt */ | ||
106 | |||
107 | enum usb_int_id { | ||
108 | USB_INT_TYPE = 0x01, | ||
109 | USB_INT_ID_REGS = 0x90, | ||
110 | USB_INT_ID_RETRY_FAILED = 0xa0, | ||
111 | }; | ||
112 | |||
113 | enum usb_int_flags { | ||
114 | USB_INT_READ_REGS_EN = 0x01, | ||
115 | }; | ||
116 | |||
117 | struct usb_int_header { | ||
118 | u8 type; /* must always be 1 */ | ||
119 | u8 id; | ||
120 | } __attribute__((packed)); | ||
121 | |||
122 | struct usb_int_regs { | ||
123 | struct usb_int_header hdr; | ||
124 | struct reg_data regs[0]; | ||
125 | } __attribute__((packed)); | ||
126 | |||
127 | struct usb_int_retry_fail { | ||
128 | struct usb_int_header hdr; | ||
129 | u8 new_rate; | ||
130 | u8 _dummy; | ||
131 | u8 addr[ETH_ALEN]; | ||
132 | u8 ibss_wakeup_dest; | ||
133 | } __attribute__((packed)); | ||
134 | |||
135 | struct read_regs_int { | ||
136 | struct completion completion; | ||
137 | /* Stores the USB int structure and contains the USB address of the | ||
138 | * first requested register before request. | ||
139 | */ | ||
140 | u8 buffer[USB_MAX_EP_INT_BUFFER]; | ||
141 | int length; | ||
142 | __le16 cr_int_addr; | ||
143 | }; | ||
144 | |||
145 | struct zd_ioreq16 { | ||
146 | zd_addr_t addr; | ||
147 | u16 value; | ||
148 | }; | ||
149 | |||
150 | struct zd_ioreq32 { | ||
151 | zd_addr_t addr; | ||
152 | u32 value; | ||
153 | }; | ||
154 | |||
155 | struct zd_usb_interrupt { | ||
156 | struct read_regs_int read_regs; | ||
157 | spinlock_t lock; | ||
158 | struct urb *urb; | ||
159 | int interval; | ||
160 | u8 read_regs_enabled:1; | ||
161 | }; | ||
162 | |||
163 | static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr) | ||
164 | { | ||
165 | return (struct usb_int_regs *)intr->read_regs.buffer; | ||
166 | } | ||
167 | |||
168 | #define URBS_COUNT 5 | ||
169 | |||
170 | struct zd_usb_rx { | ||
171 | spinlock_t lock; | ||
172 | u8 fragment[2*USB_MAX_RX_SIZE]; | ||
173 | unsigned int fragment_length; | ||
174 | unsigned int usb_packet_size; | ||
175 | struct urb **urbs; | ||
176 | int urbs_count; | ||
177 | }; | ||
178 | |||
179 | struct zd_usb_tx { | ||
180 | spinlock_t lock; | ||
181 | }; | ||
182 | |||
183 | /* Contains the usb parts. The structure doesn't require a lock, because intf | ||
184 | * and fw_base_offset, will not be changed after initialization. | ||
185 | */ | ||
186 | struct zd_usb { | ||
187 | struct zd_usb_interrupt intr; | ||
188 | struct zd_usb_rx rx; | ||
189 | struct zd_usb_tx tx; | ||
190 | struct usb_interface *intf; | ||
191 | u16 fw_base_offset; | ||
192 | }; | ||
193 | |||
194 | #define zd_usb_dev(usb) (&usb->intf->dev) | ||
195 | |||
196 | static inline struct usb_device *zd_usb_to_usbdev(struct zd_usb *usb) | ||
197 | { | ||
198 | return interface_to_usbdev(usb->intf); | ||
199 | } | ||
200 | |||
201 | static inline struct net_device *zd_intf_to_netdev(struct usb_interface *intf) | ||
202 | { | ||
203 | return usb_get_intfdata(intf); | ||
204 | } | ||
205 | |||
206 | static inline struct net_device *zd_usb_to_netdev(struct zd_usb *usb) | ||
207 | { | ||
208 | return zd_intf_to_netdev(usb->intf); | ||
209 | } | ||
210 | |||
211 | void zd_usb_init(struct zd_usb *usb, struct net_device *netdev, | ||
212 | struct usb_interface *intf); | ||
213 | int zd_usb_init_hw(struct zd_usb *usb); | ||
214 | void zd_usb_clear(struct zd_usb *usb); | ||
215 | |||
216 | int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size); | ||
217 | |||
218 | int zd_usb_enable_int(struct zd_usb *usb); | ||
219 | void zd_usb_disable_int(struct zd_usb *usb); | ||
220 | |||
221 | int zd_usb_enable_rx(struct zd_usb *usb); | ||
222 | void zd_usb_disable_rx(struct zd_usb *usb); | ||
223 | |||
224 | int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length); | ||
225 | |||
226 | int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, | ||
227 | const zd_addr_t *addresses, unsigned int count); | ||
228 | |||
229 | static inline int zd_usb_ioread16(struct zd_usb *usb, u16 *value, | ||
230 | const zd_addr_t addr) | ||
231 | { | ||
232 | return zd_usb_ioread16v(usb, value, (const zd_addr_t *)&addr, 1); | ||
233 | } | ||
234 | |||
235 | int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | ||
236 | unsigned int count); | ||
237 | |||
238 | int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits); | ||
239 | |||
240 | #endif /* _ZD_USB_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_util.c b/drivers/net/wireless/zd1211rw/zd_util.c new file mode 100644 index 000000000000..d20036c15d11 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_util.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* zd_util.c | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | * | ||
17 | * Utility program | ||
18 | */ | ||
19 | |||
20 | #include "zd_def.h" | ||
21 | #include "zd_util.h" | ||
22 | |||
23 | #ifdef DEBUG | ||
24 | static char hex(u8 v) | ||
25 | { | ||
26 | v &= 0xf; | ||
27 | return (v < 10 ? '0' : 'a' - 10) + v; | ||
28 | } | ||
29 | |||
30 | static char hex_print(u8 c) | ||
31 | { | ||
32 | return (0x20 <= c && c < 0x7f) ? c : '.'; | ||
33 | } | ||
34 | |||
35 | static void dump_line(const u8 *bytes, size_t size) | ||
36 | { | ||
37 | char c; | ||
38 | size_t i; | ||
39 | |||
40 | size = size <= 8 ? size : 8; | ||
41 | printk(KERN_DEBUG "zd1211 %p ", bytes); | ||
42 | for (i = 0; i < 8; i++) { | ||
43 | switch (i) { | ||
44 | case 1: | ||
45 | case 5: | ||
46 | c = '.'; | ||
47 | break; | ||
48 | case 3: | ||
49 | c = ':'; | ||
50 | break; | ||
51 | default: | ||
52 | c = ' '; | ||
53 | } | ||
54 | if (i < size) { | ||
55 | printk("%c%c%c", hex(bytes[i] >> 4), hex(bytes[i]), c); | ||
56 | } else { | ||
57 | printk(" %c", c); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | for (i = 0; i < size; i++) | ||
62 | printk("%c", hex_print(bytes[i])); | ||
63 | printk("\n"); | ||
64 | } | ||
65 | |||
66 | void zd_hexdump(const void *bytes, size_t size) | ||
67 | { | ||
68 | size_t i = 0; | ||
69 | |||
70 | do { | ||
71 | dump_line((u8 *)bytes + i, size-i); | ||
72 | i += 8; | ||
73 | } while (i < size); | ||
74 | } | ||
75 | #endif /* DEBUG */ | ||
76 | |||
77 | void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size) | ||
78 | { | ||
79 | if (buffer_size < tail_size) | ||
80 | return NULL; | ||
81 | return (u8 *)buffer + (buffer_size - tail_size); | ||
82 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_util.h b/drivers/net/wireless/zd1211rw/zd_util.h new file mode 100644 index 000000000000..ce26f7adea92 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_util.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* zd_util.h | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef _ZD_UTIL_H | ||
19 | #define _ZD_UTIL_H | ||
20 | |||
21 | void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size); | ||
22 | |||
23 | #ifdef DEBUG | ||
24 | void zd_hexdump(const void *bytes, size_t size); | ||
25 | #else | ||
26 | #define zd_hexdump(bytes, size) | ||
27 | #endif /* DEBUG */ | ||
28 | |||
29 | #endif /* _ZD_UTIL_H */ | ||