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