blob: 49739c36a449f53018a6fb115995e163e77f9087 [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
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200138static void p54u_tx_reuse_skb_cb(struct urb *urb)
139{
140 struct sk_buff *skb = urb->context;
141 struct p54u_priv *priv = (struct p54u_priv *)((struct ieee80211_hw *)
142 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)))->priv;
143
144 skb_pull(skb, priv->common.tx_hdr_len);
145 usb_free_urb(urb);
146}
147
Michael Wueff1a592007-09-25 18:11:01 -0700148static void p54u_tx_cb(struct urb *urb)
149{
150 usb_free_urb(urb);
151}
152
153static void p54u_tx_free_cb(struct urb *urb)
154{
155 kfree(urb->transfer_buffer);
156 usb_free_urb(urb);
157}
158
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200159static void p54u_tx_free_skb_cb(struct urb *urb)
160{
161 struct sk_buff *skb = urb->context;
162 struct ieee80211_hw *dev = (struct ieee80211_hw *)
163 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
164
165 p54_free_skb(dev, skb);
166 usb_free_urb(urb);
167}
168
Michael Wueff1a592007-09-25 18:11:01 -0700169static int p54u_init_urbs(struct ieee80211_hw *dev)
170{
171 struct p54u_priv *priv = dev->priv;
172 struct urb *entry;
173 struct sk_buff *skb;
174 struct p54u_rx_info *info;
175
176 while (skb_queue_len(&priv->rx_queue) < 32) {
Christian Lamparter4e416a62008-09-01 22:48:41 +0200177 skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL);
Michael Wueff1a592007-09-25 18:11:01 -0700178 if (!skb)
179 break;
180 entry = usb_alloc_urb(0, GFP_KERNEL);
181 if (!entry) {
182 kfree_skb(skb);
183 break;
184 }
Christian Lamparter4e416a62008-09-01 22:48:41 +0200185 usb_fill_bulk_urb(entry, priv->udev,
186 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
187 skb_tail_pointer(skb),
188 priv->common.rx_mtu + 32, p54u_rx_cb, skb);
Michael Wueff1a592007-09-25 18:11:01 -0700189 info = (struct p54u_rx_info *) skb->cb;
190 info->urb = entry;
191 info->dev = dev;
192 skb_queue_tail(&priv->rx_queue, skb);
193 usb_submit_urb(entry, GFP_KERNEL);
194 }
195
196 return 0;
197}
198
199static void p54u_free_urbs(struct ieee80211_hw *dev)
200{
201 struct p54u_priv *priv = dev->priv;
202 struct p54u_rx_info *info;
203 struct sk_buff *skb;
204
205 while ((skb = skb_dequeue(&priv->rx_queue))) {
206 info = (struct p54u_rx_info *) skb->cb;
207 if (!info->urb)
208 continue;
209
210 usb_kill_urb(info->urb);
211 kfree_skb(skb);
212 }
213}
214
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200215static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb,
216 int free_on_tx)
Michael Wueff1a592007-09-25 18:11:01 -0700217{
218 struct p54u_priv *priv = dev->priv;
219 struct urb *addr_urb, *data_urb;
220
221 addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
222 if (!addr_urb)
223 return;
224
225 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
226 if (!data_urb) {
227 usb_free_urb(addr_urb);
228 return;
229 }
230
231 usb_fill_bulk_urb(addr_urb, priv->udev,
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200232 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
John W. Linville27df6052008-10-22 16:41:55 -0400233 &((struct p54_hdr *)skb->data)->req_id, 4,
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200234 p54u_tx_cb, dev);
Michael Wueff1a592007-09-25 18:11:01 -0700235 usb_fill_bulk_urb(data_urb, priv->udev,
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200236 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
237 skb->data, skb->len,
238 free_on_tx ? p54u_tx_free_skb_cb :
239 p54u_tx_reuse_skb_cb, skb);
Michael Wueff1a592007-09-25 18:11:01 -0700240
241 usb_submit_urb(addr_urb, GFP_ATOMIC);
242 usb_submit_urb(data_urb, GFP_ATOMIC);
243}
244
Larry Finger1f1c0e32008-09-25 14:54:28 -0500245static __le32 p54u_lm87_chksum(const u32 *data, size_t length)
Christian Lamparter2b808482008-09-04 12:29:38 +0200246{
Larry Finger1f1c0e32008-09-25 14:54:28 -0500247 u32 chk = 0;
Christian Lamparter2b808482008-09-04 12:29:38 +0200248
249 length >>= 2;
250 while (length--) {
Larry Finger1f1c0e32008-09-25 14:54:28 -0500251 chk ^= *data++;
Christian Lamparter2b808482008-09-04 12:29:38 +0200252 chk = (chk >> 5) ^ (chk << 3);
253 }
254
Larry Finger1f1c0e32008-09-25 14:54:28 -0500255 return cpu_to_le32(chk);
Christian Lamparter2b808482008-09-04 12:29:38 +0200256}
257
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200258static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb,
259 int free_on_tx)
Christian Lamparter2b808482008-09-04 12:29:38 +0200260{
261 struct p54u_priv *priv = dev->priv;
262 struct urb *data_urb;
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200263 struct lm87_tx_hdr *hdr;
264 __le32 checksum;
John W. Linville27df6052008-10-22 16:41:55 -0400265 __le32 addr = ((struct p54_hdr *)skb->data)->req_id;
Christian Lamparter2b808482008-09-04 12:29:38 +0200266
267 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
268 if (!data_urb)
269 return;
270
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200271 checksum = p54u_lm87_chksum((u32 *)skb->data, skb->len);
272 hdr = (struct lm87_tx_hdr *)skb_push(skb, sizeof(*hdr));
273 hdr->chksum = checksum;
274 hdr->device_addr = addr;
Christian Lamparter2b808482008-09-04 12:29:38 +0200275
276 usb_fill_bulk_urb(data_urb, priv->udev,
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200277 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
278 skb->data, skb->len,
279 free_on_tx ? p54u_tx_free_skb_cb :
280 p54u_tx_reuse_skb_cb, skb);
Christian Lamparter2b808482008-09-04 12:29:38 +0200281
282 usb_submit_urb(data_urb, GFP_ATOMIC);
283}
284
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200285static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb,
286 int free_on_tx)
Michael Wueff1a592007-09-25 18:11:01 -0700287{
288 struct p54u_priv *priv = dev->priv;
289 struct urb *int_urb, *data_urb;
290 struct net2280_tx_hdr *hdr;
291 struct net2280_reg_write *reg;
292
293 reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
294 if (!reg)
295 return;
296
297 int_urb = usb_alloc_urb(0, GFP_ATOMIC);
298 if (!int_urb) {
299 kfree(reg);
300 return;
301 }
302
303 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
304 if (!data_urb) {
305 kfree(reg);
306 usb_free_urb(int_urb);
307 return;
308 }
309
310 reg->port = cpu_to_le16(NET2280_DEV_U32);
311 reg->addr = cpu_to_le32(P54U_DEV_BASE);
312 reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
313
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200314 hdr = (void *)skb_push(skb, sizeof(*hdr));
Michael Wueff1a592007-09-25 18:11:01 -0700315 memset(hdr, 0, sizeof(*hdr));
John W. Linville27df6052008-10-22 16:41:55 -0400316 hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id;
317 hdr->len = cpu_to_le16(skb->len + sizeof(struct p54_hdr));
Michael Wueff1a592007-09-25 18:11:01 -0700318
319 usb_fill_bulk_urb(int_urb, priv->udev,
320 usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
321 p54u_tx_free_cb, dev);
322 usb_submit_urb(int_urb, GFP_ATOMIC);
323
324 usb_fill_bulk_urb(data_urb, priv->udev,
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200325 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
326 skb->data, skb->len,
327 free_on_tx ? p54u_tx_free_skb_cb :
328 p54u_tx_reuse_skb_cb, skb);
Michael Wueff1a592007-09-25 18:11:01 -0700329 usb_submit_urb(data_urb, GFP_ATOMIC);
330}
331
332static int p54u_write(struct p54u_priv *priv,
333 struct net2280_reg_write *buf,
334 enum net2280_op_type type,
335 __le32 addr, __le32 val)
336{
337 unsigned int ep;
338 int alen;
339
340 if (type & 0x0800)
341 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
342 else
343 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
344
345 buf->port = cpu_to_le16(type);
346 buf->addr = addr;
347 buf->val = val;
348
349 return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
350}
351
352static int p54u_read(struct p54u_priv *priv, void *buf,
353 enum net2280_op_type type,
354 __le32 addr, __le32 *val)
355{
356 struct net2280_reg_read *read = buf;
357 __le32 *reg = buf;
358 unsigned int ep;
359 int alen, err;
360
361 if (type & 0x0800)
362 ep = P54U_PIPE_DEV;
363 else
364 ep = P54U_PIPE_BRG;
365
366 read->port = cpu_to_le16(type);
367 read->addr = addr;
368
369 err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
370 read, sizeof(*read), &alen, 1000);
371 if (err)
372 return err;
373
374 err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
375 reg, sizeof(*reg), &alen, 1000);
376 if (err)
377 return err;
378
379 *val = *reg;
380 return 0;
381}
382
383static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
384 void *data, size_t len)
385{
386 int alen;
387 return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
388 data, len, &alen, 2000);
389}
390
Michael Wueff1a592007-09-25 18:11:01 -0700391static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
392{
393 static char start_string[] = "~~~~<\r";
394 struct p54u_priv *priv = dev->priv;
395 const struct firmware *fw_entry = NULL;
396 int err, alen;
397 u8 carry = 0;
David Woodhouse8b72eb42008-05-24 00:08:55 +0100398 u8 *buf, *tmp;
399 const u8 *data;
Michael Wueff1a592007-09-25 18:11:01 -0700400 unsigned int left, remains, block_size;
401 struct x2_header *hdr;
402 unsigned long timeout;
403
404 tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
405 if (!buf) {
406 printk(KERN_ERR "p54usb: cannot allocate firmware upload buffer!\n");
407 err = -ENOMEM;
408 goto err_bufalloc;
409 }
410
411 memcpy(buf, start_string, 4);
412 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
413 if (err) {
414 printk(KERN_ERR "p54usb: reset failed! (%d)\n", err);
415 goto err_reset;
416 }
417
418 err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev);
419 if (err) {
420 printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n");
421 goto err_req_fw_failed;
422 }
423
Christian Lamparter4e416a62008-09-01 22:48:41 +0200424 err = p54_parse_firmware(dev, fw_entry);
425 if (err)
426 goto err_upload_failed;
Michael Wueff1a592007-09-25 18:11:01 -0700427
428 left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
429 strcpy(buf, start_string);
430 left -= strlen(start_string);
431 tmp += strlen(start_string);
432
433 data = fw_entry->data;
434 remains = fw_entry->size;
435
436 hdr = (struct x2_header *)(buf + strlen(start_string));
437 memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
438 hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
439 hdr->fw_length = cpu_to_le32(fw_entry->size);
440 hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
441 sizeof(u32)*2));
442 left -= sizeof(*hdr);
443 tmp += sizeof(*hdr);
444
445 while (remains) {
446 while (left--) {
447 if (carry) {
448 *tmp++ = carry;
449 carry = 0;
450 remains--;
451 continue;
452 }
453 switch (*data) {
454 case '~':
455 *tmp++ = '}';
456 carry = '^';
457 break;
458 case '}':
459 *tmp++ = '}';
460 carry = ']';
461 break;
462 default:
463 *tmp++ = *data;
464 remains--;
465 break;
466 }
467 data++;
468 }
469
470 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
471 if (err) {
Christian Lamparter32ddf072008-08-08 21:17:37 +0200472 printk(KERN_ERR "p54usb: firmware upload failed!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700473 goto err_upload_failed;
474 }
475
476 tmp = buf;
477 left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
478 }
479
480 *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
481 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
482 if (err) {
Christian Lamparter32ddf072008-08-08 21:17:37 +0200483 printk(KERN_ERR "p54usb: firmware upload failed!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700484 goto err_upload_failed;
485 }
486
487 timeout = jiffies + msecs_to_jiffies(1000);
488 while (!(err = usb_bulk_msg(priv->udev,
489 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
490 if (alen > 2 && !memcmp(buf, "OK", 2))
491 break;
492
493 if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
Christian Lamparter32ddf072008-08-08 21:17:37 +0200494 printk(KERN_INFO "p54usb: firmware upload failed!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700495 err = -EINVAL;
496 break;
497 }
498
499 if (time_after(jiffies, timeout)) {
Christian Lamparter32ddf072008-08-08 21:17:37 +0200500 printk(KERN_ERR "p54usb: firmware boot timed out!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700501 err = -ETIMEDOUT;
502 break;
503 }
504 }
505 if (err)
506 goto err_upload_failed;
507
508 buf[0] = 'g';
509 buf[1] = '\r';
510 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
511 if (err) {
Christian Lamparter32ddf072008-08-08 21:17:37 +0200512 printk(KERN_ERR "p54usb: firmware boot failed!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700513 goto err_upload_failed;
514 }
515
516 timeout = jiffies + msecs_to_jiffies(1000);
517 while (!(err = usb_bulk_msg(priv->udev,
518 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
519 if (alen > 0 && buf[0] == 'g')
520 break;
521
522 if (time_after(jiffies, timeout)) {
523 err = -ETIMEDOUT;
524 break;
525 }
526 }
527 if (err)
528 goto err_upload_failed;
529
530 err_upload_failed:
531 release_firmware(fw_entry);
532 err_req_fw_failed:
533 err_reset:
534 kfree(buf);
535 err_bufalloc:
536 return err;
537}
538
539static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
540{
541 struct p54u_priv *priv = dev->priv;
542 const struct firmware *fw_entry = NULL;
543 const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
544 int err, alen;
545 void *buf;
546 __le32 reg;
547 unsigned int remains, offset;
David Woodhouse8b72eb42008-05-24 00:08:55 +0100548 const u8 *data;
Michael Wueff1a592007-09-25 18:11:01 -0700549
550 buf = kmalloc(512, GFP_KERNEL);
551 if (!buf) {
552 printk(KERN_ERR "p54usb: firmware buffer alloc failed!\n");
553 return -ENOMEM;
554 }
555
556 err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev);
557 if (err) {
558 printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n");
559 kfree(buf);
560 return err;
561 }
562
Christian Lamparter4e416a62008-09-01 22:48:41 +0200563 err = p54_parse_firmware(dev, fw_entry);
564 if (err) {
565 kfree(buf);
566 release_firmware(fw_entry);
567 return err;
568 }
Michael Wueff1a592007-09-25 18:11:01 -0700569
570#define P54U_WRITE(type, addr, data) \
571 do {\
572 err = p54u_write(priv, buf, type,\
573 cpu_to_le32((u32)(unsigned long)addr), data);\
574 if (err) \
575 goto fail;\
576 } while (0)
577
578#define P54U_READ(type, addr) \
579 do {\
580 err = p54u_read(priv, buf, type,\
581 cpu_to_le32((u32)(unsigned long)addr), &reg);\
582 if (err)\
583 goto fail;\
584 } while (0)
585
586 /* power down net2280 bridge */
587 P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
588 reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
589 reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
590 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
591
592 mdelay(100);
593
594 /* power up bridge */
595 reg |= cpu_to_le32(P54U_BRG_POWER_UP);
596 reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
597 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
598
599 mdelay(100);
600
601 P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
602 cpu_to_le32(NET2280_CLK_30Mhz |
603 NET2280_PCI_ENABLE |
604 NET2280_PCI_SOFT_RESET));
605
606 mdelay(20);
607
608 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
609 cpu_to_le32(PCI_COMMAND_MEMORY |
610 PCI_COMMAND_MASTER));
611
612 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
613 cpu_to_le32(NET2280_BASE));
614
615 P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
616 reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
617 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
618
619 // TODO: we really need this?
620 P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
621
622 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
623 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
624 P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
625 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
626
627 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
628 cpu_to_le32(NET2280_BASE2));
629
630 /* finally done setting up the bridge */
631
632 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
633 cpu_to_le32(PCI_COMMAND_MEMORY |
634 PCI_COMMAND_MASTER));
635
636 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
637 P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
638 cpu_to_le32(P54U_DEV_BASE));
639
640 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
641 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
642 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
643
644 /* do romboot */
645 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
646
647 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
648 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
649 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
650 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
651 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
652
653 mdelay(20);
654
655 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
656 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
657
658 mdelay(20);
659
660 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
661 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
662
663 mdelay(100);
664
665 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
666 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
667
668 /* finally, we can upload firmware now! */
669 remains = fw_entry->size;
670 data = fw_entry->data;
671 offset = ISL38XX_DEV_FIRMWARE_ADDR;
672
673 while (remains) {
674 unsigned int block_len = min(remains, (unsigned int)512);
675 memcpy(buf, data, block_len);
676
677 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
678 if (err) {
Christian Lamparter32ddf072008-08-08 21:17:37 +0200679 printk(KERN_ERR "p54usb: firmware block upload "
Michael Wueff1a592007-09-25 18:11:01 -0700680 "failed\n");
681 goto fail;
682 }
683
684 P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
685 cpu_to_le32(0xc0000f00));
686
687 P54U_WRITE(NET2280_DEV_U32,
688 0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
689 P54U_WRITE(NET2280_DEV_U32,
690 0x0020 | (unsigned long)&devreg->direct_mem_win,
691 cpu_to_le32(1));
692
693 P54U_WRITE(NET2280_DEV_U32,
694 0x0024 | (unsigned long)&devreg->direct_mem_win,
695 cpu_to_le32(block_len));
696 P54U_WRITE(NET2280_DEV_U32,
697 0x0028 | (unsigned long)&devreg->direct_mem_win,
698 cpu_to_le32(offset));
699
700 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
701 cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
702 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
703 cpu_to_le32(block_len >> 2));
704 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
705 cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
706
707 mdelay(10);
708
709 P54U_READ(NET2280_DEV_U32,
710 0x002C | (unsigned long)&devreg->direct_mem_win);
711 if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
712 !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
Christian Lamparter32ddf072008-08-08 21:17:37 +0200713 printk(KERN_ERR "p54usb: firmware DMA transfer "
Michael Wueff1a592007-09-25 18:11:01 -0700714 "failed\n");
715 goto fail;
716 }
717
718 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
719 cpu_to_le32(NET2280_FIFO_FLUSH));
720
721 remains -= block_len;
722 data += block_len;
723 offset += block_len;
724 }
725
726 /* do ramboot */
727 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
728 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
729 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
730 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
731 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
732
733 mdelay(20);
734
735 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
736 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
737
738 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
739 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
740
741 mdelay(100);
742
743 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
744 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
745
746 /* start up the firmware */
747 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
748 cpu_to_le32(ISL38XX_INT_IDENT_INIT));
749
750 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
751 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
752
753 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
754 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
755 NET2280_USB_INTERRUPT_ENABLE));
756
757 P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
758 cpu_to_le32(ISL38XX_DEV_INT_RESET));
759
760 err = usb_interrupt_msg(priv->udev,
761 usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
762 buf, sizeof(__le32), &alen, 1000);
763 if (err || alen != sizeof(__le32))
764 goto fail;
765
766 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
767 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
768
769 if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
770 err = -EINVAL;
771
772 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
773 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
774 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
775
776#undef P54U_WRITE
777#undef P54U_READ
778
779 fail:
780 release_firmware(fw_entry);
781 kfree(buf);
782 return err;
783}
784
785static int p54u_open(struct ieee80211_hw *dev)
786{
787 struct p54u_priv *priv = dev->priv;
788 int err;
789
790 err = p54u_init_urbs(dev);
791 if (err) {
792 return err;
793 }
794
795 priv->common.open = p54u_init_urbs;
796
797 return 0;
798}
799
800static void p54u_stop(struct ieee80211_hw *dev)
801{
802 /* TODO: figure out how to reliably stop the 3887 and net2280 so
803 the hardware is still usable next time we want to start it.
804 until then, we just stop listening to the hardware.. */
805 p54u_free_urbs(dev);
806 return;
807}
808
809static int __devinit p54u_probe(struct usb_interface *intf,
810 const struct usb_device_id *id)
811{
812 struct usb_device *udev = interface_to_usbdev(intf);
813 struct ieee80211_hw *dev;
814 struct p54u_priv *priv;
815 int err;
816 unsigned int i, recognized_pipes;
Michael Wueff1a592007-09-25 18:11:01 -0700817
818 dev = p54_init_common(sizeof(*priv));
819 if (!dev) {
Christian Lamparter32ddf072008-08-08 21:17:37 +0200820 printk(KERN_ERR "p54usb: ieee80211 alloc failed\n");
Michael Wueff1a592007-09-25 18:11:01 -0700821 return -ENOMEM;
822 }
823
824 priv = dev->priv;
825
826 SET_IEEE80211_DEV(dev, &intf->dev);
827 usb_set_intfdata(intf, dev);
828 priv->udev = udev;
829
830 usb_get_dev(udev);
831
832 /* really lazy and simple way of figuring out if we're a 3887 */
833 /* TODO: should just stick the identification in the device table */
834 i = intf->altsetting->desc.bNumEndpoints;
835 recognized_pipes = 0;
836 while (i--) {
837 switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
838 case P54U_PIPE_DATA:
839 case P54U_PIPE_MGMT:
840 case P54U_PIPE_BRG:
841 case P54U_PIPE_DEV:
842 case P54U_PIPE_DATA | USB_DIR_IN:
843 case P54U_PIPE_MGMT | USB_DIR_IN:
844 case P54U_PIPE_BRG | USB_DIR_IN:
845 case P54U_PIPE_DEV | USB_DIR_IN:
846 case P54U_PIPE_INT | USB_DIR_IN:
847 recognized_pipes++;
848 }
849 }
850 priv->common.open = p54u_open;
Christian Lamparter2b808482008-09-04 12:29:38 +0200851 priv->common.stop = p54u_stop;
Michael Wueff1a592007-09-25 18:11:01 -0700852 if (recognized_pipes < P54U_PIPE_NUMBER) {
853 priv->hw_type = P54U_3887;
Christian Lamparter2b808482008-09-04 12:29:38 +0200854 err = p54u_upload_firmware_3887(dev);
855 if (priv->common.fw_interface == FW_LM87) {
856 dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
857 priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
858 priv->common.tx = p54u_tx_lm87;
859 } else
860 priv->common.tx = p54u_tx_3887;
Michael Wueff1a592007-09-25 18:11:01 -0700861 } else {
Christian Lamparter2b808482008-09-04 12:29:38 +0200862 priv->hw_type = P54U_NET2280;
Michael Wueff1a592007-09-25 18:11:01 -0700863 dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
864 priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
865 priv->common.tx = p54u_tx_net2280;
Michael Wueff1a592007-09-25 18:11:01 -0700866 err = p54u_upload_firmware_net2280(dev);
Christian Lamparter2b808482008-09-04 12:29:38 +0200867 }
Michael Wueff1a592007-09-25 18:11:01 -0700868 if (err)
869 goto err_free_dev;
870
Christian Lamparter7cb77072008-09-01 22:48:51 +0200871 skb_queue_head_init(&priv->rx_queue);
872
873 p54u_open(dev);
874 err = p54_read_eeprom(dev);
875 p54u_stop(dev);
Michael Wueff1a592007-09-25 18:11:01 -0700876 if (err)
877 goto err_free_dev;
878
Michael Wueff1a592007-09-25 18:11:01 -0700879 err = ieee80211_register_hw(dev);
880 if (err) {
Christian Lamparter32ddf072008-08-08 21:17:37 +0200881 printk(KERN_ERR "p54usb: Cannot register netdevice\n");
Michael Wueff1a592007-09-25 18:11:01 -0700882 goto err_free_dev;
883 }
884
Michael Wueff1a592007-09-25 18:11:01 -0700885 return 0;
886
887 err_free_dev:
888 ieee80211_free_hw(dev);
889 usb_set_intfdata(intf, NULL);
890 usb_put_dev(udev);
891 return err;
892}
893
894static void __devexit p54u_disconnect(struct usb_interface *intf)
895{
896 struct ieee80211_hw *dev = usb_get_intfdata(intf);
897 struct p54u_priv *priv;
898
899 if (!dev)
900 return;
901
902 ieee80211_unregister_hw(dev);
903
904 priv = dev->priv;
905 usb_put_dev(interface_to_usbdev(intf));
906 p54_free_common(dev);
907 ieee80211_free_hw(dev);
908}
909
910static struct usb_driver p54u_driver = {
Christian Lamparter32ddf072008-08-08 21:17:37 +0200911 .name = "p54usb",
Michael Wueff1a592007-09-25 18:11:01 -0700912 .id_table = p54u_table,
913 .probe = p54u_probe,
914 .disconnect = p54u_disconnect,
915};
916
917static int __init p54u_init(void)
918{
919 return usb_register(&p54u_driver);
920}
921
922static void __exit p54u_exit(void)
923{
924 usb_deregister(&p54u_driver);
925}
926
927module_init(p54u_init);
928module_exit(p54u_exit);