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