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