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