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