]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/net/wireless/p54/p54usb.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[net-next-2.6.git] / drivers / net / wireless / p54 / p54usb.c
CommitLineData
eff1a59c
MW
1
2/*
3 * Linux device driver for USB based Prism54
4 *
5 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
6 *
7 * Based on the islsm (softmac prism54) driver, which is:
8 * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/init.h>
16#include <linux/usb.h>
17#include <linux/pci.h>
5a0e3ad6 18#include <linux/slab.h>
eff1a59c
MW
19#include <linux/firmware.h>
20#include <linux/etherdevice.h>
21#include <linux/delay.h>
22#include <linux/crc32.h>
23#include <net/mac80211.h>
24
25#include "p54.h"
d8c92107 26#include "lmac.h"
eff1a59c
MW
27#include "p54usb.h"
28
29MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
30MODULE_DESCRIPTION("Prism54 USB wireless driver");
31MODULE_LICENSE("GPL");
32MODULE_ALIAS("prism54usb");
9a8675d7
CL
33MODULE_FIRMWARE("isl3886usb");
34MODULE_FIRMWARE("isl3887usb");
eff1a59c
MW
35
36static struct usb_device_id p54u_table[] __devinitdata = {
37 /* Version 1 devices (pci chip + net2280) */
38 {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
05a9a161 39 {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */
eff1a59c 40 {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
15a69a81 41 {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */
eff1a59c
MW
42 {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
43 {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
1a17582e 44 {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
eff1a59c
MW
45 {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */
46 {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */
47 {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
ec366eba 48 {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
eff1a59c
MW
49 {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
50 {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
51 {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */
52 {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */
53 {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */
54 {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */
55 {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */
56 {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */
57
58 /* Version 2 devices (3887) */
4546002c 59 {USB_DEVICE(0x0471, 0x1230)}, /* Philips CPWUA054/00 */
eff1a59c
MW
60 {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
61 {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
62 {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
878e6a43 63 {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
eff1a59c
MW
64 {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
65 {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
5b9a919a 66 {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */
eff1a59c
MW
67 {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
68 {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
69 {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
70 {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/
71 {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/
7484bdc0
LO
72 /* {USB_DEVICE(0x0cde, 0x0006)}, * Medion MD40900 already listed above,
73 * just noting it here for clarity */
eff1a59c 74 {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
f7f71173 75 {USB_DEVICE(0x0cde, 0x0015)}, /* Zcomax XG-705A */
eff1a59c 76 {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
43557e15 77 {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
ec366eba 78 {USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */
387e100a 79 {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */
c1098103 80 {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
e3062403 81 {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */
eff1a59c
MW
82 {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
83 {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
0f666a08 84 {USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */
eff1a59c
MW
85 {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
86 {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
87 {}
88};
89
90MODULE_DEVICE_TABLE(usb, p54u_table);
91
1ca5f2e9
CL
92static const struct {
93 u32 intf;
94 enum p54u_hw_type type;
328d84fb
SO
95 const char *fw;
96 const char *fw_legacy;
1ca5f2e9
CL
97 char hw[20];
98} p54u_fwlist[__NUM_P54U_HWTYPES] = {
99 {
100 .type = P54U_NET2280,
101 .intf = FW_LM86,
102 .fw = "isl3886usb",
103 .fw_legacy = "isl3890usb",
104 .hw = "ISL3886 + net2280",
105 },
106 {
107 .type = P54U_3887,
108 .intf = FW_LM87,
109 .fw = "isl3887usb",
110 .fw_legacy = "isl3887usb_bare",
111 .hw = "ISL3887",
112 },
113};
114
eff1a59c
MW
115static void p54u_rx_cb(struct urb *urb)
116{
117 struct sk_buff *skb = (struct sk_buff *) urb->context;
118 struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
119 struct ieee80211_hw *dev = info->dev;
120 struct p54u_priv *priv = dev->priv;
121
dd397dc9
CL
122 skb_unlink(skb, &priv->rx_queue);
123
eff1a59c 124 if (unlikely(urb->status)) {
dd397dc9 125 dev_kfree_skb_irq(skb);
eff1a59c
MW
126 return;
127 }
128
eff1a59c 129 skb_put(skb, urb->actual_length);
2b80848e
CL
130
131 if (priv->hw_type == P54U_NET2280)
132 skb_pull(skb, priv->common.tx_hdr_len);
133 if (priv->common.fw_interface == FW_LM87) {
134 skb_pull(skb, 4);
135 skb_put(skb, 4);
136 }
eff1a59c
MW
137
138 if (p54_rx(dev, skb)) {
4e416a6f 139 skb = dev_alloc_skb(priv->common.rx_mtu + 32);
eff1a59c 140 if (unlikely(!skb)) {
eff1a59c
MW
141 /* TODO check rx queue length and refill *somewhere* */
142 return;
143 }
144
145 info = (struct p54u_rx_info *) skb->cb;
146 info->urb = urb;
147 info->dev = dev;
148 urb->transfer_buffer = skb_tail_pointer(skb);
149 urb->context = skb;
eff1a59c 150 } else {
2b80848e
CL
151 if (priv->hw_type == P54U_NET2280)
152 skb_push(skb, priv->common.tx_hdr_len);
153 if (priv->common.fw_interface == FW_LM87) {
154 skb_push(skb, 4);
155 skb_put(skb, 4);
156 }
d47c3ceb 157 skb_reset_tail_pointer(skb);
eff1a59c 158 skb_trim(skb, 0);
1ca5f2e9 159 urb->transfer_buffer = skb_tail_pointer(skb);
eff1a59c 160 }
dd397dc9
CL
161 skb_queue_tail(&priv->rx_queue, skb);
162 usb_anchor_urb(urb, &priv->submitted);
163 if (usb_submit_urb(urb, GFP_ATOMIC)) {
164 skb_unlink(skb, &priv->rx_queue);
165 usb_unanchor_urb(urb);
166 dev_kfree_skb_irq(skb);
167 }
eff1a59c
MW
168}
169
0a5ec96a 170static void p54u_tx_cb(struct urb *urb)
b92f30d6
CL
171{
172 struct sk_buff *skb = urb->context;
173 struct ieee80211_hw *dev = (struct ieee80211_hw *)
174 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
175
e2fe154e 176 p54_free_skb(dev, skb);
dd397dc9
CL
177}
178
179static void p54u_tx_dummy_cb(struct urb *urb) { }
180
181static void p54u_free_urbs(struct ieee80211_hw *dev)
182{
183 struct p54u_priv *priv = dev->priv;
184 usb_kill_anchored_urbs(&priv->submitted);
b92f30d6
CL
185}
186
eff1a59c
MW
187static int p54u_init_urbs(struct ieee80211_hw *dev)
188{
189 struct p54u_priv *priv = dev->priv;
dd397dc9 190 struct urb *entry = NULL;
eff1a59c
MW
191 struct sk_buff *skb;
192 struct p54u_rx_info *info;
dd397dc9 193 int ret = 0;
eff1a59c
MW
194
195 while (skb_queue_len(&priv->rx_queue) < 32) {
4e416a6f 196 skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL);
dd397dc9
CL
197 if (!skb) {
198 ret = -ENOMEM;
199 goto err;
200 }
eff1a59c
MW
201 entry = usb_alloc_urb(0, GFP_KERNEL);
202 if (!entry) {
dd397dc9
CL
203 ret = -ENOMEM;
204 goto err;
eff1a59c 205 }
dd397dc9 206
4e416a6f
CL
207 usb_fill_bulk_urb(entry, priv->udev,
208 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
209 skb_tail_pointer(skb),
210 priv->common.rx_mtu + 32, p54u_rx_cb, skb);
eff1a59c
MW
211 info = (struct p54u_rx_info *) skb->cb;
212 info->urb = entry;
213 info->dev = dev;
214 skb_queue_tail(&priv->rx_queue, skb);
dd397dc9
CL
215
216 usb_anchor_urb(entry, &priv->submitted);
217 ret = usb_submit_urb(entry, GFP_KERNEL);
218 if (ret) {
219 skb_unlink(skb, &priv->rx_queue);
220 usb_unanchor_urb(entry);
221 goto err;
222 }
223 usb_free_urb(entry);
224 entry = NULL;
eff1a59c
MW
225 }
226
227 return 0;
eff1a59c 228
dd397dc9
CL
229 err:
230 usb_free_urb(entry);
231 kfree_skb(skb);
232 p54u_free_urbs(dev);
233 return ret;
eff1a59c
MW
234}
235
c9127659 236static __le32 p54u_lm87_chksum(const __le32 *data, size_t length)
2b80848e 237{
1f1c0e33 238 u32 chk = 0;
2b80848e
CL
239
240 length >>= 2;
241 while (length--) {
c9127659 242 chk ^= le32_to_cpu(*data++);
2b80848e
CL
243 chk = (chk >> 5) ^ (chk << 3);
244 }
245
1f1c0e33 246 return cpu_to_le32(chk);
2b80848e
CL
247}
248
0a5ec96a 249static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
2b80848e
CL
250{
251 struct p54u_priv *priv = dev->priv;
252 struct urb *data_urb;
e2fe154e 253 struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
2b80848e
CL
254
255 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
6d541a68
CL
256 if (!data_urb) {
257 p54_free_skb(dev, skb);
2b80848e 258 return;
6d541a68 259 }
2b80848e 260
e2fe154e
CL
261 hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
262 hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id;
2b80848e
CL
263
264 usb_fill_bulk_urb(data_urb, priv->udev,
b92f30d6 265 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
e2fe154e
CL
266 hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ?
267 p54u_tx_cb : p54u_tx_dummy_cb, skb);
00627f22 268 data_urb->transfer_flags |= URB_ZERO_PACKET;
2b80848e 269
dd397dc9
CL
270 usb_anchor_urb(data_urb, &priv->submitted);
271 if (usb_submit_urb(data_urb, GFP_ATOMIC)) {
272 usb_unanchor_urb(data_urb);
dd397dc9
CL
273 p54_free_skb(dev, skb);
274 }
275 usb_free_urb(data_urb);
2b80848e
CL
276}
277
0a5ec96a 278static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
eff1a59c
MW
279{
280 struct p54u_priv *priv = dev->priv;
6d541a68 281 struct urb *int_urb = NULL, *data_urb = NULL;
e2fe154e 282 struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
6d541a68
CL
283 struct net2280_reg_write *reg = NULL;
284 int err = -ENOMEM;
eff1a59c
MW
285
286 reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
287 if (!reg)
6d541a68 288 goto out;
eff1a59c
MW
289
290 int_urb = usb_alloc_urb(0, GFP_ATOMIC);
6d541a68
CL
291 if (!int_urb)
292 goto out;
eff1a59c
MW
293
294 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
6d541a68
CL
295 if (!data_urb)
296 goto out;
eff1a59c
MW
297
298 reg->port = cpu_to_le16(NET2280_DEV_U32);
299 reg->addr = cpu_to_le32(P54U_DEV_BASE);
300 reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
301
eff1a59c 302 memset(hdr, 0, sizeof(*hdr));
e2fe154e
CL
303 hdr->len = cpu_to_le16(skb->len);
304 hdr->device_addr = ((struct p54_hdr *) skb->data)->req_id;
eff1a59c
MW
305
306 usb_fill_bulk_urb(int_urb, priv->udev,
307 usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
dd397dc9
CL
308 p54u_tx_dummy_cb, dev);
309
310 /*
6d541a68
CL
311 * URB_FREE_BUFFER triggers a code path in the USB subsystem that will
312 * free what is inside the transfer_buffer after the last reference to
313 * the int_urb is dropped.
dd397dc9 314 */
b4068a80 315 int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET;
6d541a68 316 reg = NULL;
eff1a59c
MW
317
318 usb_fill_bulk_urb(data_urb, priv->udev,
b92f30d6 319 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
e2fe154e
CL
320 hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ?
321 p54u_tx_cb : p54u_tx_dummy_cb, skb);
b4068a80 322 data_urb->transfer_flags |= URB_ZERO_PACKET;
dd397dc9
CL
323
324 usb_anchor_urb(int_urb, &priv->submitted);
325 err = usb_submit_urb(int_urb, GFP_ATOMIC);
326 if (err) {
327 usb_unanchor_urb(int_urb);
328 goto out;
329 }
330
331 usb_anchor_urb(data_urb, &priv->submitted);
332 err = usb_submit_urb(data_urb, GFP_ATOMIC);
333 if (err) {
334 usb_unanchor_urb(data_urb);
335 goto out;
336 }
6d541a68 337out:
dd397dc9
CL
338 usb_free_urb(int_urb);
339 usb_free_urb(data_urb);
340
341 if (err) {
6d541a68 342 kfree(reg);
dd397dc9
CL
343 p54_free_skb(dev, skb);
344 }
eff1a59c
MW
345}
346
347static int p54u_write(struct p54u_priv *priv,
348 struct net2280_reg_write *buf,
349 enum net2280_op_type type,
350 __le32 addr, __le32 val)
351{
352 unsigned int ep;
353 int alen;
354
355 if (type & 0x0800)
356 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
357 else
358 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
359
360 buf->port = cpu_to_le16(type);
361 buf->addr = addr;
362 buf->val = val;
363
364 return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
365}
366
367static int p54u_read(struct p54u_priv *priv, void *buf,
368 enum net2280_op_type type,
369 __le32 addr, __le32 *val)
370{
371 struct net2280_reg_read *read = buf;
372 __le32 *reg = buf;
373 unsigned int ep;
374 int alen, err;
375
376 if (type & 0x0800)
377 ep = P54U_PIPE_DEV;
378 else
379 ep = P54U_PIPE_BRG;
380
381 read->port = cpu_to_le16(type);
382 read->addr = addr;
383
384 err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
385 read, sizeof(*read), &alen, 1000);
386 if (err)
387 return err;
388
389 err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
390 reg, sizeof(*reg), &alen, 1000);
391 if (err)
392 return err;
393
394 *val = *reg;
395 return 0;
396}
397
398static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
399 void *data, size_t len)
400{
401 int alen;
402 return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
403 data, len, &alen, 2000);
404}
405
1ca5f2e9 406static int p54u_device_reset(struct ieee80211_hw *dev)
6982869d
CL
407{
408 struct p54u_priv *priv = dev->priv;
c88a768d 409 int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING);
6982869d 410
c88a768d
CL
411 if (lock) {
412 ret = usb_lock_device_for_reset(priv->udev, priv->intf);
413 if (ret < 0) {
414 dev_err(&priv->udev->dev, "(p54usb) unable to lock "
1ca5f2e9 415 "device for reset (%d)!\n", ret);
c88a768d
CL
416 return ret;
417 }
6982869d
CL
418 }
419
420 ret = usb_reset_device(priv->udev);
421 if (lock)
422 usb_unlock_device(priv->udev);
423
1ca5f2e9 424 if (ret)
6982869d 425 dev_err(&priv->udev->dev, "(p54usb) unable to reset "
1ca5f2e9
CL
426 "device (%d)!\n", ret);
427
428 return ret;
429}
430
431static const char p54u_romboot_3887[] = "~~~~";
432static int p54u_firmware_reset_3887(struct ieee80211_hw *dev)
433{
434 struct p54u_priv *priv = dev->priv;
21d6c270 435 u8 *buf;
1ca5f2e9 436 int ret;
6982869d 437
27b81bbe 438 buf = kmemdup(p54u_romboot_3887, 4, GFP_KERNEL);
21d6c270
LF
439 if (!buf)
440 return -ENOMEM;
6982869d 441 ret = p54u_bulk_msg(priv, P54U_PIPE_DATA,
21d6c270
LF
442 buf, 4);
443 kfree(buf);
6982869d
CL
444 if (ret)
445 dev_err(&priv->udev->dev, "(p54usb) unable to jump to "
1ca5f2e9 446 "boot ROM (%d)!\n", ret);
6982869d
CL
447
448 return ret;
449}
450
1ca5f2e9 451static const char p54u_firmware_upload_3887[] = "<\r";
eff1a59c
MW
452static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
453{
eff1a59c 454 struct p54u_priv *priv = dev->priv;
eff1a59c
MW
455 int err, alen;
456 u8 carry = 0;
8b72eb43
DW
457 u8 *buf, *tmp;
458 const u8 *data;
eff1a59c
MW
459 unsigned int left, remains, block_size;
460 struct x2_header *hdr;
461 unsigned long timeout;
462
1ca5f2e9
CL
463 err = p54u_firmware_reset_3887(dev);
464 if (err)
465 return err;
466
eff1a59c
MW
467 tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
468 if (!buf) {
02e37ba1
CL
469 dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware"
470 "upload buffer!\n");
1ca5f2e9 471 return -ENOMEM;
e365f160
CL
472 }
473
1ca5f2e9 474 left = block_size = min((size_t)P54U_FW_BLOCK, priv->fw->size);
6982869d
CL
475 strcpy(buf, p54u_firmware_upload_3887);
476 left -= strlen(p54u_firmware_upload_3887);
477 tmp += strlen(p54u_firmware_upload_3887);
eff1a59c 478
1ca5f2e9
CL
479 data = priv->fw->data;
480 remains = priv->fw->size;
eff1a59c 481
6982869d 482 hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887));
eff1a59c
MW
483 memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
484 hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
1ca5f2e9 485 hdr->fw_length = cpu_to_le32(priv->fw->size);
eff1a59c
MW
486 hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
487 sizeof(u32)*2));
488 left -= sizeof(*hdr);
489 tmp += sizeof(*hdr);
490
491 while (remains) {
492 while (left--) {
493 if (carry) {
494 *tmp++ = carry;
495 carry = 0;
496 remains--;
497 continue;
498 }
499 switch (*data) {
500 case '~':
501 *tmp++ = '}';
502 carry = '^';
503 break;
504 case '}':
505 *tmp++ = '}';
506 carry = ']';
507 break;
508 default:
509 *tmp++ = *data;
510 remains--;
511 break;
512 }
513 data++;
514 }
515
516 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
517 if (err) {
02e37ba1
CL
518 dev_err(&priv->udev->dev, "(p54usb) firmware "
519 "upload failed!\n");
eff1a59c
MW
520 goto err_upload_failed;
521 }
522
523 tmp = buf;
524 left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
525 }
526
1ca5f2e9
CL
527 *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, priv->fw->data,
528 priv->fw->size));
eff1a59c
MW
529 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
530 if (err) {
02e37ba1 531 dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
eff1a59c
MW
532 goto err_upload_failed;
533 }
eff1a59c
MW
534 timeout = jiffies + msecs_to_jiffies(1000);
535 while (!(err = usb_bulk_msg(priv->udev,
536 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
537 if (alen > 2 && !memcmp(buf, "OK", 2))
538 break;
539
540 if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
eff1a59c
MW
541 err = -EINVAL;
542 break;
543 }
544
545 if (time_after(jiffies, timeout)) {
02e37ba1
CL
546 dev_err(&priv->udev->dev, "(p54usb) firmware boot "
547 "timed out!\n");
eff1a59c
MW
548 err = -ETIMEDOUT;
549 break;
550 }
551 }
02e37ba1
CL
552 if (err) {
553 dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
eff1a59c 554 goto err_upload_failed;
02e37ba1 555 }
eff1a59c
MW
556
557 buf[0] = 'g';
558 buf[1] = '\r';
559 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
560 if (err) {
02e37ba1 561 dev_err(&priv->udev->dev, "(p54usb) firmware boot failed!\n");
eff1a59c
MW
562 goto err_upload_failed;
563 }
564
565 timeout = jiffies + msecs_to_jiffies(1000);
566 while (!(err = usb_bulk_msg(priv->udev,
567 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
568 if (alen > 0 && buf[0] == 'g')
569 break;
570
571 if (time_after(jiffies, timeout)) {
572 err = -ETIMEDOUT;
573 break;
574 }
575 }
576 if (err)
577 goto err_upload_failed;
578
1ca5f2e9 579err_upload_failed:
eff1a59c 580 kfree(buf);
eff1a59c
MW
581 return err;
582}
583
584static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
585{
586 struct p54u_priv *priv = dev->priv;
eff1a59c
MW
587 const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
588 int err, alen;
589 void *buf;
590 __le32 reg;
591 unsigned int remains, offset;
8b72eb43 592 const u8 *data;
eff1a59c
MW
593
594 buf = kmalloc(512, GFP_KERNEL);
595 if (!buf) {
02e37ba1
CL
596 dev_err(&priv->udev->dev, "(p54usb) firmware buffer "
597 "alloc failed!\n");
eff1a59c
MW
598 return -ENOMEM;
599 }
600
eff1a59c
MW
601#define P54U_WRITE(type, addr, data) \
602 do {\
603 err = p54u_write(priv, buf, type,\
604 cpu_to_le32((u32)(unsigned long)addr), data);\
605 if (err) \
606 goto fail;\
607 } while (0)
608
609#define P54U_READ(type, addr) \
610 do {\
611 err = p54u_read(priv, buf, type,\
612 cpu_to_le32((u32)(unsigned long)addr), &reg);\
613 if (err)\
614 goto fail;\
615 } while (0)
616
617 /* power down net2280 bridge */
618 P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
619 reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
620 reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
621 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
622
623 mdelay(100);
624
625 /* power up bridge */
626 reg |= cpu_to_le32(P54U_BRG_POWER_UP);
627 reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
628 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
629
630 mdelay(100);
631
632 P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
633 cpu_to_le32(NET2280_CLK_30Mhz |
634 NET2280_PCI_ENABLE |
635 NET2280_PCI_SOFT_RESET));
636
637 mdelay(20);
638
639 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
640 cpu_to_le32(PCI_COMMAND_MEMORY |
641 PCI_COMMAND_MASTER));
642
643 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
644 cpu_to_le32(NET2280_BASE));
645
646 P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
647 reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
648 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
649
650 // TODO: we really need this?
651 P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
652
653 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
654 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
655 P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
656 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
657
658 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
659 cpu_to_le32(NET2280_BASE2));
660
661 /* finally done setting up the bridge */
662
663 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
664 cpu_to_le32(PCI_COMMAND_MEMORY |
665 PCI_COMMAND_MASTER));
666
667 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
668 P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
669 cpu_to_le32(P54U_DEV_BASE));
670
671 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
672 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
673 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
674
675 /* do romboot */
676 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
677
678 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
679 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
680 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
681 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
682 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
683
684 mdelay(20);
685
686 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
687 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
688
689 mdelay(20);
690
691 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
692 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
693
694 mdelay(100);
695
696 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
697 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
698
699 /* finally, we can upload firmware now! */
1ca5f2e9
CL
700 remains = priv->fw->size;
701 data = priv->fw->data;
eff1a59c
MW
702 offset = ISL38XX_DEV_FIRMWARE_ADDR;
703
704 while (remains) {
705 unsigned int block_len = min(remains, (unsigned int)512);
706 memcpy(buf, data, block_len);
707
708 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
709 if (err) {
02e37ba1
CL
710 dev_err(&priv->udev->dev, "(p54usb) firmware block "
711 "upload failed\n");
eff1a59c
MW
712 goto fail;
713 }
714
715 P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
716 cpu_to_le32(0xc0000f00));
717
718 P54U_WRITE(NET2280_DEV_U32,
719 0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
720 P54U_WRITE(NET2280_DEV_U32,
721 0x0020 | (unsigned long)&devreg->direct_mem_win,
722 cpu_to_le32(1));
723
724 P54U_WRITE(NET2280_DEV_U32,
725 0x0024 | (unsigned long)&devreg->direct_mem_win,
726 cpu_to_le32(block_len));
727 P54U_WRITE(NET2280_DEV_U32,
728 0x0028 | (unsigned long)&devreg->direct_mem_win,
729 cpu_to_le32(offset));
730
731 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
732 cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
733 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
734 cpu_to_le32(block_len >> 2));
735 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
736 cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
737
738 mdelay(10);
739
740 P54U_READ(NET2280_DEV_U32,
741 0x002C | (unsigned long)&devreg->direct_mem_win);
742 if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
743 !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
02e37ba1
CL
744 dev_err(&priv->udev->dev, "(p54usb) firmware DMA "
745 "transfer failed\n");
eff1a59c
MW
746 goto fail;
747 }
748
749 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
750 cpu_to_le32(NET2280_FIFO_FLUSH));
751
752 remains -= block_len;
753 data += block_len;
754 offset += block_len;
755 }
756
757 /* do ramboot */
758 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
759 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
760 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
761 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
762 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
763
764 mdelay(20);
765
766 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
767 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
768
769 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
770 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
771
772 mdelay(100);
773
774 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
775 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
776
777 /* start up the firmware */
778 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
779 cpu_to_le32(ISL38XX_INT_IDENT_INIT));
780
781 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
782 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
783
784 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
785 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
786 NET2280_USB_INTERRUPT_ENABLE));
787
788 P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
789 cpu_to_le32(ISL38XX_DEV_INT_RESET));
790
791 err = usb_interrupt_msg(priv->udev,
792 usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
793 buf, sizeof(__le32), &alen, 1000);
794 if (err || alen != sizeof(__le32))
795 goto fail;
796
797 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
798 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
799
800 if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
801 err = -EINVAL;
802
803 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
804 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
805 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
806
807#undef P54U_WRITE
808#undef P54U_READ
809
1ca5f2e9 810fail:
eff1a59c
MW
811 kfree(buf);
812 return err;
813}
814
1ca5f2e9
CL
815static int p54u_load_firmware(struct ieee80211_hw *dev)
816{
817 struct p54u_priv *priv = dev->priv;
818 int err, i;
819
820 BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES);
821
822 for (i = 0; i < __NUM_P54U_HWTYPES; i++)
823 if (p54u_fwlist[i].type == priv->hw_type)
824 break;
825
826 if (i == __NUM_P54U_HWTYPES)
827 return -EOPNOTSUPP;
828
829 err = request_firmware(&priv->fw, p54u_fwlist[i].fw, &priv->udev->dev);
830 if (err) {
831 dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "
832 "(%d)!\n", p54u_fwlist[i].fw, err);
833
834 err = request_firmware(&priv->fw, p54u_fwlist[i].fw_legacy,
835 &priv->udev->dev);
836 if (err)
837 return err;
838 }
839
840 err = p54_parse_firmware(dev, priv->fw);
841 if (err)
842 goto out;
843
844 if (priv->common.fw_interface != p54u_fwlist[i].intf) {
845 dev_err(&priv->udev->dev, "wrong firmware, please get "
846 "a firmware for \"%s\" and try again.\n",
847 p54u_fwlist[i].hw);
848 err = -EINVAL;
849 }
850
851out:
852 if (err)
853 release_firmware(priv->fw);
854
855 return err;
856}
857
eff1a59c
MW
858static int p54u_open(struct ieee80211_hw *dev)
859{
860 struct p54u_priv *priv = dev->priv;
861 int err;
862
863 err = p54u_init_urbs(dev);
864 if (err) {
865 return err;
866 }
867
868 priv->common.open = p54u_init_urbs;
869
870 return 0;
871}
872
873static void p54u_stop(struct ieee80211_hw *dev)
874{
875 /* TODO: figure out how to reliably stop the 3887 and net2280 so
876 the hardware is still usable next time we want to start it.
877 until then, we just stop listening to the hardware.. */
878 p54u_free_urbs(dev);
eff1a59c
MW
879}
880
881static int __devinit p54u_probe(struct usb_interface *intf,
882 const struct usb_device_id *id)
883{
884 struct usb_device *udev = interface_to_usbdev(intf);
885 struct ieee80211_hw *dev;
886 struct p54u_priv *priv;
887 int err;
888 unsigned int i, recognized_pipes;
eff1a59c
MW
889
890 dev = p54_init_common(sizeof(*priv));
02e37ba1 891
eff1a59c 892 if (!dev) {
02e37ba1 893 dev_err(&udev->dev, "(p54usb) ieee80211 alloc failed\n");
eff1a59c
MW
894 return -ENOMEM;
895 }
896
897 priv = dev->priv;
1ca5f2e9 898 priv->hw_type = P54U_INVALID_HW;
eff1a59c
MW
899
900 SET_IEEE80211_DEV(dev, &intf->dev);
901 usb_set_intfdata(intf, dev);
902 priv->udev = udev;
6982869d
CL
903 priv->intf = intf;
904 skb_queue_head_init(&priv->rx_queue);
905 init_usb_anchor(&priv->submitted);
eff1a59c
MW
906
907 usb_get_dev(udev);
908
909 /* really lazy and simple way of figuring out if we're a 3887 */
910 /* TODO: should just stick the identification in the device table */
911 i = intf->altsetting->desc.bNumEndpoints;
912 recognized_pipes = 0;
913 while (i--) {
914 switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
915 case P54U_PIPE_DATA:
916 case P54U_PIPE_MGMT:
917 case P54U_PIPE_BRG:
918 case P54U_PIPE_DEV:
919 case P54U_PIPE_DATA | USB_DIR_IN:
920 case P54U_PIPE_MGMT | USB_DIR_IN:
921 case P54U_PIPE_BRG | USB_DIR_IN:
922 case P54U_PIPE_DEV | USB_DIR_IN:
923 case P54U_PIPE_INT | USB_DIR_IN:
924 recognized_pipes++;
925 }
926 }
927 priv->common.open = p54u_open;
2b80848e 928 priv->common.stop = p54u_stop;
eff1a59c 929 if (recognized_pipes < P54U_PIPE_NUMBER) {
13792578 930#ifdef CONFIG_PM
1ca5f2e9
CL
931 /* ISL3887 needs a full reset on resume */
932 udev->reset_resume = 1;
11791a6f 933#endif /* CONFIG_PM */
1ca5f2e9
CL
934 err = p54u_device_reset(dev);
935
eff1a59c 936 priv->hw_type = P54U_3887;
a406ac0d
CL
937 dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
938 priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
939 priv->common.tx = p54u_tx_lm87;
1ca5f2e9 940 priv->upload_fw = p54u_upload_firmware_3887;
eff1a59c 941 } else {
2b80848e 942 priv->hw_type = P54U_NET2280;
eff1a59c
MW
943 dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
944 priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
945 priv->common.tx = p54u_tx_net2280;
1ca5f2e9 946 priv->upload_fw = p54u_upload_firmware_net2280;
2b80848e 947 }
1ca5f2e9 948 err = p54u_load_firmware(dev);
eff1a59c
MW
949 if (err)
950 goto err_free_dev;
951
1ca5f2e9
CL
952 err = priv->upload_fw(dev);
953 if (err)
954 goto err_free_fw;
955
7cb77072
CL
956 p54u_open(dev);
957 err = p54_read_eeprom(dev);
958 p54u_stop(dev);
eff1a59c 959 if (err)
1ca5f2e9 960 goto err_free_fw;
eff1a59c 961
2ac71072
CL
962 err = p54_register_common(dev, &udev->dev);
963 if (err)
1ca5f2e9 964 goto err_free_fw;
eff1a59c 965
eff1a59c
MW
966 return 0;
967
1ca5f2e9
CL
968err_free_fw:
969 release_firmware(priv->fw);
970
971err_free_dev:
d8c92107 972 p54_free_common(dev);
eff1a59c
MW
973 usb_set_intfdata(intf, NULL);
974 usb_put_dev(udev);
975 return err;
976}
977
978static void __devexit p54u_disconnect(struct usb_interface *intf)
979{
980 struct ieee80211_hw *dev = usb_get_intfdata(intf);
981 struct p54u_priv *priv;
982
983 if (!dev)
984 return;
985
d8c92107 986 p54_unregister_common(dev);
eff1a59c
MW
987
988 priv = dev->priv;
989 usb_put_dev(interface_to_usbdev(intf));
1ca5f2e9 990 release_firmware(priv->fw);
eff1a59c 991 p54_free_common(dev);
eff1a59c
MW
992}
993
6982869d
CL
994static int p54u_pre_reset(struct usb_interface *intf)
995{
1ca5f2e9
CL
996 struct ieee80211_hw *dev = usb_get_intfdata(intf);
997
998 if (!dev)
999 return -ENODEV;
1000
1001 p54u_stop(dev);
6982869d
CL
1002 return 0;
1003}
1004
1ca5f2e9
CL
1005static int p54u_resume(struct usb_interface *intf)
1006{
1007 struct ieee80211_hw *dev = usb_get_intfdata(intf);
1008 struct p54u_priv *priv;
1009
1010 if (!dev)
1011 return -ENODEV;
1012
1013 priv = dev->priv;
1014 if (unlikely(!(priv->upload_fw && priv->fw)))
1015 return 0;
1016
1017 return priv->upload_fw(dev);
1018}
1019
6982869d
CL
1020static int p54u_post_reset(struct usb_interface *intf)
1021{
1ca5f2e9
CL
1022 struct ieee80211_hw *dev = usb_get_intfdata(intf);
1023 struct p54u_priv *priv;
1024 int err;
1025
1026 err = p54u_resume(intf);
1027 if (err)
1028 return err;
1029
1030 /* reinitialize old device state */
1031 priv = dev->priv;
1032 if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED)
1033 ieee80211_restart_hw(dev);
1034
6982869d
CL
1035 return 0;
1036}
1037
1ca5f2e9
CL
1038#ifdef CONFIG_PM
1039
1040static int p54u_suspend(struct usb_interface *intf, pm_message_t message)
1041{
1042 return p54u_pre_reset(intf);
1043}
1044
1045#endif /* CONFIG_PM */
1046
eff1a59c 1047static struct usb_driver p54u_driver = {
32ddf071 1048 .name = "p54usb",
eff1a59c
MW
1049 .id_table = p54u_table,
1050 .probe = p54u_probe,
1051 .disconnect = p54u_disconnect,
6982869d
CL
1052 .pre_reset = p54u_pre_reset,
1053 .post_reset = p54u_post_reset,
1ca5f2e9
CL
1054#ifdef CONFIG_PM
1055 .suspend = p54u_suspend,
1056 .resume = p54u_resume,
1057 .reset_resume = p54u_resume,
1058#endif /* CONFIG_PM */
fbf95296 1059 .soft_unbind = 1,
eff1a59c
MW
1060};
1061
1062static int __init p54u_init(void)
1063{
1064 return usb_register(&p54u_driver);
1065}
1066
1067static void __exit p54u_exit(void)
1068{
1069 usb_deregister(&p54u_driver);
1070}
1071
1072module_init(p54u_init);
1073module_exit(p54u_exit);