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