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