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