aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54/p54usb.c
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2008-04-08 15:38:00 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-08 16:44:45 -0400
commitfb26971058845868f7c45b720636180d14c058e4 (patch)
treedd1463cfdad7b837b592a888847edb4200034ebd /drivers/net/wireless/p54/p54usb.c
parent2c8dccc77420fb7433da5674818959d3499d35be (diff)
p54: move to separate directory
Signed-off-by: Christian Lamparter <chunkeey@web.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54/p54usb.c')
-rw-r--r--drivers/net/wireless/p54/p54usb.c910
1 files changed, 910 insertions, 0 deletions
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
new file mode 100644
index 000000000000..98ddbb3b3273
--- /dev/null
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -0,0 +1,910 @@
1
2/*
3 * Linux device driver for USB based Prism54
4 *
5 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
6 *
7 * Based on the islsm (softmac prism54) driver, which is:
8 * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/init.h>
16#include <linux/usb.h>
17#include <linux/pci.h>
18#include <linux/firmware.h>
19#include <linux/etherdevice.h>
20#include <linux/delay.h>
21#include <linux/crc32.h>
22#include <net/mac80211.h>
23
24#include "p54.h"
25#include "p54usb.h"
26
27MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
28MODULE_DESCRIPTION("Prism54 USB wireless driver");
29MODULE_LICENSE("GPL");
30MODULE_ALIAS("prism54usb");
31
32static struct usb_device_id p54u_table[] __devinitdata = {
33 /* Version 1 devices (pci chip + net2280) */
34 {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
35 {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
36 {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
37 {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
38 {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
39 {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */
40 {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */
41 {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
42 {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
43 {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
44 {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */
45 {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */
46 {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */
47 {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */
48 {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */
49 {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */
50
51 /* Version 2 devices (3887) */
52 {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
53 {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
54 {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
55 {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
56 {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
57 {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
58 {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
59 {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
60 {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/
61 {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/
62 {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */
63 {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
64 {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
65 {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
66 {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
67 {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */
68 {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
69 {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
70 {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
71 {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
72 {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
73 {}
74};
75
76MODULE_DEVICE_TABLE(usb, p54u_table);
77
78static void p54u_rx_cb(struct urb *urb)
79{
80 struct sk_buff *skb = (struct sk_buff *) urb->context;
81 struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
82 struct ieee80211_hw *dev = info->dev;
83 struct p54u_priv *priv = dev->priv;
84
85 if (unlikely(urb->status)) {
86 info->urb = NULL;
87 usb_free_urb(urb);
88 return;
89 }
90
91 skb_unlink(skb, &priv->rx_queue);
92 skb_put(skb, urb->actual_length);
93 if (!priv->hw_type)
94 skb_pull(skb, sizeof(struct net2280_tx_hdr));
95
96 if (p54_rx(dev, skb)) {
97 skb = dev_alloc_skb(MAX_RX_SIZE);
98 if (unlikely(!skb)) {
99 usb_free_urb(urb);
100 /* TODO check rx queue length and refill *somewhere* */
101 return;
102 }
103
104 info = (struct p54u_rx_info *) skb->cb;
105 info->urb = urb;
106 info->dev = dev;
107 urb->transfer_buffer = skb_tail_pointer(skb);
108 urb->context = skb;
109 skb_queue_tail(&priv->rx_queue, skb);
110 } else {
111 skb_trim(skb, 0);
112 skb_queue_tail(&priv->rx_queue, skb);
113 }
114
115 usb_submit_urb(urb, GFP_ATOMIC);
116}
117
118static void p54u_tx_cb(struct urb *urb)
119{
120 usb_free_urb(urb);
121}
122
123static void p54u_tx_free_cb(struct urb *urb)
124{
125 kfree(urb->transfer_buffer);
126 usb_free_urb(urb);
127}
128
129static int p54u_init_urbs(struct ieee80211_hw *dev)
130{
131 struct p54u_priv *priv = dev->priv;
132 struct urb *entry;
133 struct sk_buff *skb;
134 struct p54u_rx_info *info;
135
136 while (skb_queue_len(&priv->rx_queue) < 32) {
137 skb = __dev_alloc_skb(MAX_RX_SIZE, GFP_KERNEL);
138 if (!skb)
139 break;
140 entry = usb_alloc_urb(0, GFP_KERNEL);
141 if (!entry) {
142 kfree_skb(skb);
143 break;
144 }
145 usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), skb_tail_pointer(skb), MAX_RX_SIZE, p54u_rx_cb, skb);
146 info = (struct p54u_rx_info *) skb->cb;
147 info->urb = entry;
148 info->dev = dev;
149 skb_queue_tail(&priv->rx_queue, skb);
150 usb_submit_urb(entry, GFP_KERNEL);
151 }
152
153 return 0;
154}
155
156static void p54u_free_urbs(struct ieee80211_hw *dev)
157{
158 struct p54u_priv *priv = dev->priv;
159 struct p54u_rx_info *info;
160 struct sk_buff *skb;
161
162 while ((skb = skb_dequeue(&priv->rx_queue))) {
163 info = (struct p54u_rx_info *) skb->cb;
164 if (!info->urb)
165 continue;
166
167 usb_kill_urb(info->urb);
168 kfree_skb(skb);
169 }
170}
171
172static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
173 size_t len, int free_on_tx)
174{
175 struct p54u_priv *priv = dev->priv;
176 struct urb *addr_urb, *data_urb;
177
178 addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
179 if (!addr_urb)
180 return;
181
182 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
183 if (!data_urb) {
184 usb_free_urb(addr_urb);
185 return;
186 }
187
188 usb_fill_bulk_urb(addr_urb, priv->udev,
189 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id,
190 sizeof(data->req_id), p54u_tx_cb, dev);
191 usb_fill_bulk_urb(data_urb, priv->udev,
192 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len,
193 free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
194
195 usb_submit_urb(addr_urb, GFP_ATOMIC);
196 usb_submit_urb(data_urb, GFP_ATOMIC);
197}
198
199static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
200 size_t len, int free_on_tx)
201{
202 struct p54u_priv *priv = dev->priv;
203 struct urb *int_urb, *data_urb;
204 struct net2280_tx_hdr *hdr;
205 struct net2280_reg_write *reg;
206
207 reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
208 if (!reg)
209 return;
210
211 int_urb = usb_alloc_urb(0, GFP_ATOMIC);
212 if (!int_urb) {
213 kfree(reg);
214 return;
215 }
216
217 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
218 if (!data_urb) {
219 kfree(reg);
220 usb_free_urb(int_urb);
221 return;
222 }
223
224 reg->port = cpu_to_le16(NET2280_DEV_U32);
225 reg->addr = cpu_to_le32(P54U_DEV_BASE);
226 reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
227
228 len += sizeof(*data);
229 hdr = (void *)data - sizeof(*hdr);
230 memset(hdr, 0, sizeof(*hdr));
231 hdr->device_addr = data->req_id;
232 hdr->len = cpu_to_le16(len);
233
234 usb_fill_bulk_urb(int_urb, priv->udev,
235 usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
236 p54u_tx_free_cb, dev);
237 usb_submit_urb(int_urb, GFP_ATOMIC);
238
239 usb_fill_bulk_urb(data_urb, priv->udev,
240 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr),
241 free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
242 usb_submit_urb(data_urb, GFP_ATOMIC);
243}
244
245static int p54u_write(struct p54u_priv *priv,
246 struct net2280_reg_write *buf,
247 enum net2280_op_type type,
248 __le32 addr, __le32 val)
249{
250 unsigned int ep;
251 int alen;
252
253 if (type & 0x0800)
254 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
255 else
256 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
257
258 buf->port = cpu_to_le16(type);
259 buf->addr = addr;
260 buf->val = val;
261
262 return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
263}
264
265static int p54u_read(struct p54u_priv *priv, void *buf,
266 enum net2280_op_type type,
267 __le32 addr, __le32 *val)
268{
269 struct net2280_reg_read *read = buf;
270 __le32 *reg = buf;
271 unsigned int ep;
272 int alen, err;
273
274 if (type & 0x0800)
275 ep = P54U_PIPE_DEV;
276 else
277 ep = P54U_PIPE_BRG;
278
279 read->port = cpu_to_le16(type);
280 read->addr = addr;
281
282 err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
283 read, sizeof(*read), &alen, 1000);
284 if (err)
285 return err;
286
287 err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
288 reg, sizeof(*reg), &alen, 1000);
289 if (err)
290 return err;
291
292 *val = *reg;
293 return 0;
294}
295
296static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
297 void *data, size_t len)
298{
299 int alen;
300 return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
301 data, len, &alen, 2000);
302}
303
304static int p54u_read_eeprom(struct ieee80211_hw *dev)
305{
306 struct p54u_priv *priv = dev->priv;
307 void *buf;
308 struct p54_control_hdr *hdr;
309 int err, alen;
310 size_t offset = priv->hw_type ? 0x10 : 0x20;
311
312 buf = kmalloc(0x2020, GFP_KERNEL);
313 if (!buf) {
314 printk(KERN_ERR "prism54usb: cannot allocate memory for "
315 "eeprom readback!\n");
316 return -ENOMEM;
317 }
318
319 if (priv->hw_type) {
320 *((u32 *) buf) = priv->common.rx_start;
321 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
322 if (err) {
323 printk(KERN_ERR "prism54usb: addr send failed\n");
324 goto fail;
325 }
326 } else {
327 struct net2280_reg_write *reg = buf;
328 reg->port = cpu_to_le16(NET2280_DEV_U32);
329 reg->addr = cpu_to_le32(P54U_DEV_BASE);
330 reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
331 err = p54u_bulk_msg(priv, P54U_PIPE_DEV, buf, sizeof(*reg));
332 if (err) {
333 printk(KERN_ERR "prism54usb: dev_int send failed\n");
334 goto fail;
335 }
336 }
337
338 hdr = buf + priv->common.tx_hdr_len;
339 p54_fill_eeprom_readback(hdr);
340 hdr->req_id = cpu_to_le32(priv->common.rx_start);
341 if (priv->common.tx_hdr_len) {
342 struct net2280_tx_hdr *tx_hdr = buf;
343 tx_hdr->device_addr = hdr->req_id;
344 tx_hdr->len = cpu_to_le16(EEPROM_READBACK_LEN);
345 }
346
347 /* we can just pretend to send 0x2000 bytes of nothing in the headers */
348 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf,
349 EEPROM_READBACK_LEN + priv->common.tx_hdr_len);
350 if (err) {
351 printk(KERN_ERR "prism54usb: eeprom req send failed\n");
352 goto fail;
353 }
354
355 err = usb_bulk_msg(priv->udev,
356 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
357 buf, 0x2020, &alen, 1000);
358 if (!err && alen > offset) {
359 p54_parse_eeprom(dev, (u8 *)buf + offset, alen - offset);
360 } else {
361 printk(KERN_ERR "prism54usb: eeprom read failed!\n");
362 err = -EINVAL;
363 goto fail;
364 }
365
366 fail:
367 kfree(buf);
368 return err;
369}
370
371static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
372{
373 static char start_string[] = "~~~~<\r";
374 struct p54u_priv *priv = dev->priv;
375 const struct firmware *fw_entry = NULL;
376 int err, alen;
377 u8 carry = 0;
378 u8 *buf, *tmp, *data;
379 unsigned int left, remains, block_size;
380 struct x2_header *hdr;
381 unsigned long timeout;
382
383 tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
384 if (!buf) {
385 printk(KERN_ERR "p54usb: cannot allocate firmware upload buffer!\n");
386 err = -ENOMEM;
387 goto err_bufalloc;
388 }
389
390 memcpy(buf, start_string, 4);
391 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
392 if (err) {
393 printk(KERN_ERR "p54usb: reset failed! (%d)\n", err);
394 goto err_reset;
395 }
396
397 err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev);
398 if (err) {
399 printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n");
400 goto err_req_fw_failed;
401 }
402
403 p54_parse_firmware(dev, fw_entry);
404
405 left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
406 strcpy(buf, start_string);
407 left -= strlen(start_string);
408 tmp += strlen(start_string);
409
410 data = fw_entry->data;
411 remains = fw_entry->size;
412
413 hdr = (struct x2_header *)(buf + strlen(start_string));
414 memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
415 hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
416 hdr->fw_length = cpu_to_le32(fw_entry->size);
417 hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
418 sizeof(u32)*2));
419 left -= sizeof(*hdr);
420 tmp += sizeof(*hdr);
421
422 while (remains) {
423 while (left--) {
424 if (carry) {
425 *tmp++ = carry;
426 carry = 0;
427 remains--;
428 continue;
429 }
430 switch (*data) {
431 case '~':
432 *tmp++ = '}';
433 carry = '^';
434 break;
435 case '}':
436 *tmp++ = '}';
437 carry = ']';
438 break;
439 default:
440 *tmp++ = *data;
441 remains--;
442 break;
443 }
444 data++;
445 }
446
447 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
448 if (err) {
449 printk(KERN_ERR "prism54usb: firmware upload failed!\n");
450 goto err_upload_failed;
451 }
452
453 tmp = buf;
454 left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
455 }
456
457 *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
458 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
459 if (err) {
460 printk(KERN_ERR "prism54usb: firmware upload failed!\n");
461 goto err_upload_failed;
462 }
463
464 timeout = jiffies + msecs_to_jiffies(1000);
465 while (!(err = usb_bulk_msg(priv->udev,
466 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
467 if (alen > 2 && !memcmp(buf, "OK", 2))
468 break;
469
470 if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
471 printk(KERN_INFO "prism54usb: firmware upload failed!\n");
472 err = -EINVAL;
473 break;
474 }
475
476 if (time_after(jiffies, timeout)) {
477 printk(KERN_ERR "prism54usb: firmware boot timed out!\n");
478 err = -ETIMEDOUT;
479 break;
480 }
481 }
482 if (err)
483 goto err_upload_failed;
484
485 buf[0] = 'g';
486 buf[1] = '\r';
487 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
488 if (err) {
489 printk(KERN_ERR "prism54usb: firmware boot failed!\n");
490 goto err_upload_failed;
491 }
492
493 timeout = jiffies + msecs_to_jiffies(1000);
494 while (!(err = usb_bulk_msg(priv->udev,
495 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
496 if (alen > 0 && buf[0] == 'g')
497 break;
498
499 if (time_after(jiffies, timeout)) {
500 err = -ETIMEDOUT;
501 break;
502 }
503 }
504 if (err)
505 goto err_upload_failed;
506
507 err_upload_failed:
508 release_firmware(fw_entry);
509 err_req_fw_failed:
510 err_reset:
511 kfree(buf);
512 err_bufalloc:
513 return err;
514}
515
516static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
517{
518 struct p54u_priv *priv = dev->priv;
519 const struct firmware *fw_entry = NULL;
520 const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
521 int err, alen;
522 void *buf;
523 __le32 reg;
524 unsigned int remains, offset;
525 u8 *data;
526
527 buf = kmalloc(512, GFP_KERNEL);
528 if (!buf) {
529 printk(KERN_ERR "p54usb: firmware buffer alloc failed!\n");
530 return -ENOMEM;
531 }
532
533 err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev);
534 if (err) {
535 printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n");
536 kfree(buf);
537 return err;
538 }
539
540 p54_parse_firmware(dev, fw_entry);
541
542#define P54U_WRITE(type, addr, data) \
543 do {\
544 err = p54u_write(priv, buf, type,\
545 cpu_to_le32((u32)(unsigned long)addr), data);\
546 if (err) \
547 goto fail;\
548 } while (0)
549
550#define P54U_READ(type, addr) \
551 do {\
552 err = p54u_read(priv, buf, type,\
553 cpu_to_le32((u32)(unsigned long)addr), &reg);\
554 if (err)\
555 goto fail;\
556 } while (0)
557
558 /* power down net2280 bridge */
559 P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
560 reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
561 reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
562 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
563
564 mdelay(100);
565
566 /* power up bridge */
567 reg |= cpu_to_le32(P54U_BRG_POWER_UP);
568 reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
569 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
570
571 mdelay(100);
572
573 P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
574 cpu_to_le32(NET2280_CLK_30Mhz |
575 NET2280_PCI_ENABLE |
576 NET2280_PCI_SOFT_RESET));
577
578 mdelay(20);
579
580 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
581 cpu_to_le32(PCI_COMMAND_MEMORY |
582 PCI_COMMAND_MASTER));
583
584 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
585 cpu_to_le32(NET2280_BASE));
586
587 P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
588 reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
589 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
590
591 // TODO: we really need this?
592 P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
593
594 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
595 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
596 P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
597 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
598
599 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
600 cpu_to_le32(NET2280_BASE2));
601
602 /* finally done setting up the bridge */
603
604 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
605 cpu_to_le32(PCI_COMMAND_MEMORY |
606 PCI_COMMAND_MASTER));
607
608 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
609 P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
610 cpu_to_le32(P54U_DEV_BASE));
611
612 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
613 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
614 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
615
616 /* do romboot */
617 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
618
619 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
620 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
621 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
622 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
623 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
624
625 mdelay(20);
626
627 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
628 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
629
630 mdelay(20);
631
632 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
633 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
634
635 mdelay(100);
636
637 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
638 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
639
640 /* finally, we can upload firmware now! */
641 remains = fw_entry->size;
642 data = fw_entry->data;
643 offset = ISL38XX_DEV_FIRMWARE_ADDR;
644
645 while (remains) {
646 unsigned int block_len = min(remains, (unsigned int)512);
647 memcpy(buf, data, block_len);
648
649 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
650 if (err) {
651 printk(KERN_ERR "prism54usb: firmware block upload "
652 "failed\n");
653 goto fail;
654 }
655
656 P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
657 cpu_to_le32(0xc0000f00));
658
659 P54U_WRITE(NET2280_DEV_U32,
660 0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
661 P54U_WRITE(NET2280_DEV_U32,
662 0x0020 | (unsigned long)&devreg->direct_mem_win,
663 cpu_to_le32(1));
664
665 P54U_WRITE(NET2280_DEV_U32,
666 0x0024 | (unsigned long)&devreg->direct_mem_win,
667 cpu_to_le32(block_len));
668 P54U_WRITE(NET2280_DEV_U32,
669 0x0028 | (unsigned long)&devreg->direct_mem_win,
670 cpu_to_le32(offset));
671
672 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
673 cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
674 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
675 cpu_to_le32(block_len >> 2));
676 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
677 cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
678
679 mdelay(10);
680
681 P54U_READ(NET2280_DEV_U32,
682 0x002C | (unsigned long)&devreg->direct_mem_win);
683 if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
684 !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
685 printk(KERN_ERR "prism54usb: firmware DMA transfer "
686 "failed\n");
687 goto fail;
688 }
689
690 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
691 cpu_to_le32(NET2280_FIFO_FLUSH));
692
693 remains -= block_len;
694 data += block_len;
695 offset += block_len;
696 }
697
698 /* do ramboot */
699 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
700 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
701 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
702 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
703 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
704
705 mdelay(20);
706
707 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
708 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
709
710 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
711 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
712
713 mdelay(100);
714
715 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
716 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
717
718 /* start up the firmware */
719 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
720 cpu_to_le32(ISL38XX_INT_IDENT_INIT));
721
722 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
723 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
724
725 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
726 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
727 NET2280_USB_INTERRUPT_ENABLE));
728
729 P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
730 cpu_to_le32(ISL38XX_DEV_INT_RESET));
731
732 err = usb_interrupt_msg(priv->udev,
733 usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
734 buf, sizeof(__le32), &alen, 1000);
735 if (err || alen != sizeof(__le32))
736 goto fail;
737
738 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
739 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
740
741 if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
742 err = -EINVAL;
743
744 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
745 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
746 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
747
748#undef P54U_WRITE
749#undef P54U_READ
750
751 fail:
752 release_firmware(fw_entry);
753 kfree(buf);
754 return err;
755}
756
757static int p54u_open(struct ieee80211_hw *dev)
758{
759 struct p54u_priv *priv = dev->priv;
760 int err;
761
762 err = p54u_init_urbs(dev);
763 if (err) {
764 return err;
765 }
766
767 priv->common.open = p54u_init_urbs;
768
769 return 0;
770}
771
772static void p54u_stop(struct ieee80211_hw *dev)
773{
774 /* TODO: figure out how to reliably stop the 3887 and net2280 so
775 the hardware is still usable next time we want to start it.
776 until then, we just stop listening to the hardware.. */
777 p54u_free_urbs(dev);
778 return;
779}
780
781static int __devinit p54u_probe(struct usb_interface *intf,
782 const struct usb_device_id *id)
783{
784 struct usb_device *udev = interface_to_usbdev(intf);
785 struct ieee80211_hw *dev;
786 struct p54u_priv *priv;
787 int err;
788 unsigned int i, recognized_pipes;
789 DECLARE_MAC_BUF(mac);
790
791 dev = p54_init_common(sizeof(*priv));
792 if (!dev) {
793 printk(KERN_ERR "prism54usb: ieee80211 alloc failed\n");
794 return -ENOMEM;
795 }
796
797 priv = dev->priv;
798
799 SET_IEEE80211_DEV(dev, &intf->dev);
800 usb_set_intfdata(intf, dev);
801 priv->udev = udev;
802
803 usb_get_dev(udev);
804
805 /* really lazy and simple way of figuring out if we're a 3887 */
806 /* TODO: should just stick the identification in the device table */
807 i = intf->altsetting->desc.bNumEndpoints;
808 recognized_pipes = 0;
809 while (i--) {
810 switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
811 case P54U_PIPE_DATA:
812 case P54U_PIPE_MGMT:
813 case P54U_PIPE_BRG:
814 case P54U_PIPE_DEV:
815 case P54U_PIPE_DATA | USB_DIR_IN:
816 case P54U_PIPE_MGMT | USB_DIR_IN:
817 case P54U_PIPE_BRG | USB_DIR_IN:
818 case P54U_PIPE_DEV | USB_DIR_IN:
819 case P54U_PIPE_INT | USB_DIR_IN:
820 recognized_pipes++;
821 }
822 }
823 priv->common.open = p54u_open;
824
825 if (recognized_pipes < P54U_PIPE_NUMBER) {
826 priv->hw_type = P54U_3887;
827 priv->common.tx = p54u_tx_3887;
828 } else {
829 dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
830 priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
831 priv->common.tx = p54u_tx_net2280;
832 }
833 priv->common.stop = p54u_stop;
834
835 if (priv->hw_type)
836 err = p54u_upload_firmware_3887(dev);
837 else
838 err = p54u_upload_firmware_net2280(dev);
839 if (err)
840 goto err_free_dev;
841
842 err = p54u_read_eeprom(dev);
843 if (err)
844 goto err_free_dev;
845
846 if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
847 u8 perm_addr[ETH_ALEN];
848
849 printk(KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n");
850 random_ether_addr(perm_addr);
851 SET_IEEE80211_PERM_ADDR(dev, perm_addr);
852 }
853
854 skb_queue_head_init(&priv->rx_queue);
855
856 err = ieee80211_register_hw(dev);
857 if (err) {
858 printk(KERN_ERR "prism54usb: Cannot register netdevice\n");
859 goto err_free_dev;
860 }
861
862 printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
863 wiphy_name(dev->wiphy),
864 print_mac(mac, dev->wiphy->perm_addr),
865 priv->common.version);
866
867 return 0;
868
869 err_free_dev:
870 ieee80211_free_hw(dev);
871 usb_set_intfdata(intf, NULL);
872 usb_put_dev(udev);
873 return err;
874}
875
876static void __devexit p54u_disconnect(struct usb_interface *intf)
877{
878 struct ieee80211_hw *dev = usb_get_intfdata(intf);
879 struct p54u_priv *priv;
880
881 if (!dev)
882 return;
883
884 ieee80211_unregister_hw(dev);
885
886 priv = dev->priv;
887 usb_put_dev(interface_to_usbdev(intf));
888 p54_free_common(dev);
889 ieee80211_free_hw(dev);
890}
891
892static struct usb_driver p54u_driver = {
893 .name = "prism54usb",
894 .id_table = p54u_table,
895 .probe = p54u_probe,
896 .disconnect = p54u_disconnect,
897};
898
899static int __init p54u_init(void)
900{
901 return usb_register(&p54u_driver);
902}
903
904static void __exit p54u_exit(void)
905{
906 usb_deregister(&p54u_driver);
907}
908
909module_init(p54u_init);
910module_exit(p54u_exit);