diff options
author | Christian Lamparter <chunkeey@web.de> | 2008-09-04 06:29:38 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-09-05 16:19:52 -0400 |
commit | 2b80848e3818fb1c8ccddc105b065a86c68afa9d (patch) | |
tree | 02a8d14e9af88e79668d2b0b5414cf8438997a84 /drivers/net | |
parent | d203b8ef8e5acf9dad5a53d7067ef146e6b2e837 (diff) |
p54usb: support LM87 firmwares
This patch adds the necessary changes to support LM87 firmwares.
Signed-off-by: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/p54/p54.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54common.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54usb.c | 72 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54usb.h | 5 |
5 files changed, 73 insertions, 20 deletions
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 3d44ab34ee69..cd2a39f544b1 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h | |||
@@ -42,6 +42,11 @@ struct p54_control_hdr { | |||
42 | 42 | ||
43 | #define ISL38XX_DEV_FIRMWARE_ADDR 0x20000 | 43 | #define ISL38XX_DEV_FIRMWARE_ADDR 0x20000 |
44 | 44 | ||
45 | #define FW_FMAC 0x464d4143 | ||
46 | #define FW_LM86 0x4c4d3836 | ||
47 | #define FW_LM87 0x4c4d3837 | ||
48 | #define FW_LM20 0x4c4d3230 | ||
49 | |||
45 | struct p54_common { | 50 | struct p54_common { |
46 | u32 rx_start; | 51 | u32 rx_start; |
47 | u32 rx_end; | 52 | u32 rx_end; |
@@ -68,6 +73,7 @@ struct p54_common { | |||
68 | unsigned int tx_hdr_len; | 73 | unsigned int tx_hdr_len; |
69 | void *cached_vdcf; | 74 | void *cached_vdcf; |
70 | unsigned int fw_var; | 75 | unsigned int fw_var; |
76 | unsigned int fw_interface; | ||
71 | struct ieee80211_tx_queue_stats tx_stats[8]; | 77 | struct ieee80211_tx_queue_stats tx_stats[8]; |
72 | void *eeprom; | 78 | void *eeprom; |
73 | struct completion eeprom_comp; | 79 | struct completion eeprom_comp; |
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 6d8248eac6e8..e96bf1a8f84c 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -93,7 +93,8 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) | |||
93 | u32 code = le32_to_cpu(bootrec->code); | 93 | u32 code = le32_to_cpu(bootrec->code); |
94 | switch (code) { | 94 | switch (code) { |
95 | case BR_CODE_COMPONENT_ID: | 95 | case BR_CODE_COMPONENT_ID: |
96 | switch (be32_to_cpu(*(__be32 *)bootrec->data)) { | 96 | priv->fw_interface = be32_to_cpup(bootrec->data); |
97 | switch (priv->fw_interface) { | ||
97 | case FW_FMAC: | 98 | case FW_FMAC: |
98 | printk(KERN_INFO "p54: FreeMAC firmware\n"); | 99 | printk(KERN_INFO "p54: FreeMAC firmware\n"); |
99 | break; | 100 | break; |
@@ -104,7 +105,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) | |||
104 | printk(KERN_INFO "p54: LM86 firmware\n"); | 105 | printk(KERN_INFO "p54: LM86 firmware\n"); |
105 | break; | 106 | break; |
106 | case FW_LM87: | 107 | case FW_LM87: |
107 | printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n"); | 108 | printk(KERN_INFO "p54: LM87 firmware\n"); |
108 | break; | 109 | break; |
109 | default: | 110 | default: |
110 | printk(KERN_INFO "p54: unknown firmware\n"); | 111 | printk(KERN_INFO "p54: unknown firmware\n"); |
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 5f2af5152505..c24b5cddf46b 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h | |||
@@ -50,11 +50,6 @@ struct bootrec_desc { | |||
50 | #define BR_CODE_END_OF_BRA 0xFF0000FF | 50 | #define BR_CODE_END_OF_BRA 0xFF0000FF |
51 | #define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF | 51 | #define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF |
52 | 52 | ||
53 | #define FW_FMAC 0x464d4143 | ||
54 | #define FW_LM86 0x4c4d3836 | ||
55 | #define FW_LM87 0x4c4d3837 | ||
56 | #define FW_LM20 0x4c4d3230 | ||
57 | |||
58 | /* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */ | 53 | /* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */ |
59 | 54 | ||
60 | struct pda_entry { | 55 | struct pda_entry { |
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index eca858c40b1f..7444f3729779 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -91,8 +91,13 @@ static void p54u_rx_cb(struct urb *urb) | |||
91 | 91 | ||
92 | skb_unlink(skb, &priv->rx_queue); | 92 | skb_unlink(skb, &priv->rx_queue); |
93 | skb_put(skb, urb->actual_length); | 93 | skb_put(skb, urb->actual_length); |
94 | if (!priv->hw_type) | 94 | |
95 | skb_pull(skb, sizeof(struct net2280_tx_hdr)); | 95 | if (priv->hw_type == P54U_NET2280) |
96 | skb_pull(skb, priv->common.tx_hdr_len); | ||
97 | if (priv->common.fw_interface == FW_LM87) { | ||
98 | skb_pull(skb, 4); | ||
99 | skb_put(skb, 4); | ||
100 | } | ||
96 | 101 | ||
97 | if (p54_rx(dev, skb)) { | 102 | if (p54_rx(dev, skb)) { |
98 | skb = dev_alloc_skb(priv->common.rx_mtu + 32); | 103 | skb = dev_alloc_skb(priv->common.rx_mtu + 32); |
@@ -109,9 +114,12 @@ static void p54u_rx_cb(struct urb *urb) | |||
109 | urb->context = skb; | 114 | urb->context = skb; |
110 | skb_queue_tail(&priv->rx_queue, skb); | 115 | skb_queue_tail(&priv->rx_queue, skb); |
111 | } else { | 116 | } else { |
112 | if (!priv->hw_type) | 117 | if (priv->hw_type == P54U_NET2280) |
113 | skb_push(skb, sizeof(struct net2280_tx_hdr)); | 118 | skb_push(skb, priv->common.tx_hdr_len); |
114 | 119 | if (priv->common.fw_interface == FW_LM87) { | |
120 | skb_push(skb, 4); | ||
121 | skb_put(skb, 4); | ||
122 | } | ||
115 | skb_reset_tail_pointer(skb); | 123 | skb_reset_tail_pointer(skb); |
116 | skb_trim(skb, 0); | 124 | skb_trim(skb, 0); |
117 | if (urb->transfer_buffer != skb_tail_pointer(skb)) { | 125 | if (urb->transfer_buffer != skb_tail_pointer(skb)) { |
@@ -210,6 +218,42 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data, | |||
210 | usb_submit_urb(data_urb, GFP_ATOMIC); | 218 | usb_submit_urb(data_urb, GFP_ATOMIC); |
211 | } | 219 | } |
212 | 220 | ||
221 | __le32 p54u_lm87_chksum(const u32 *data, size_t length) | ||
222 | { | ||
223 | __le32 chk = 0; | ||
224 | |||
225 | length >>= 2; | ||
226 | while (length--) { | ||
227 | chk ^= cpu_to_le32(*data++); | ||
228 | chk = (chk >> 5) ^ (chk << 3); | ||
229 | } | ||
230 | |||
231 | return chk; | ||
232 | } | ||
233 | |||
234 | static void p54u_tx_lm87(struct ieee80211_hw *dev, | ||
235 | struct p54_control_hdr *data, | ||
236 | size_t len, int free_on_tx) | ||
237 | { | ||
238 | struct p54u_priv *priv = dev->priv; | ||
239 | struct urb *data_urb; | ||
240 | struct lm87_tx_hdr *hdr = (void *)data - sizeof(*hdr); | ||
241 | |||
242 | data_urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
243 | if (!data_urb) | ||
244 | return; | ||
245 | |||
246 | hdr->chksum = p54u_lm87_chksum((u32 *)data, len); | ||
247 | hdr->device_addr = data->req_id; | ||
248 | |||
249 | usb_fill_bulk_urb(data_urb, priv->udev, | ||
250 | usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, | ||
251 | len + sizeof(*hdr), free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, | ||
252 | dev); | ||
253 | |||
254 | usb_submit_urb(data_urb, GFP_ATOMIC); | ||
255 | } | ||
256 | |||
213 | static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data, | 257 | static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data, |
214 | size_t len, int free_on_tx) | 258 | size_t len, int free_on_tx) |
215 | { | 259 | { |
@@ -776,21 +820,23 @@ static int __devinit p54u_probe(struct usb_interface *intf, | |||
776 | } | 820 | } |
777 | } | 821 | } |
778 | priv->common.open = p54u_open; | 822 | priv->common.open = p54u_open; |
779 | 823 | priv->common.stop = p54u_stop; | |
780 | if (recognized_pipes < P54U_PIPE_NUMBER) { | 824 | if (recognized_pipes < P54U_PIPE_NUMBER) { |
781 | priv->hw_type = P54U_3887; | 825 | priv->hw_type = P54U_3887; |
782 | priv->common.tx = p54u_tx_3887; | 826 | err = p54u_upload_firmware_3887(dev); |
827 | if (priv->common.fw_interface == FW_LM87) { | ||
828 | dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); | ||
829 | priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr); | ||
830 | priv->common.tx = p54u_tx_lm87; | ||
831 | } else | ||
832 | priv->common.tx = p54u_tx_3887; | ||
783 | } else { | 833 | } else { |
834 | priv->hw_type = P54U_NET2280; | ||
784 | dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); | 835 | dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); |
785 | priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); | 836 | priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); |
786 | priv->common.tx = p54u_tx_net2280; | 837 | priv->common.tx = p54u_tx_net2280; |
787 | } | ||
788 | priv->common.stop = p54u_stop; | ||
789 | |||
790 | if (priv->hw_type) | ||
791 | err = p54u_upload_firmware_3887(dev); | ||
792 | else | ||
793 | err = p54u_upload_firmware_net2280(dev); | 838 | err = p54u_upload_firmware_net2280(dev); |
839 | } | ||
794 | if (err) | 840 | if (err) |
795 | goto err_free_dev; | 841 | goto err_free_dev; |
796 | 842 | ||
diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h index 1baaff058c5a..5b8fe91379c3 100644 --- a/drivers/net/wireless/p54/p54usb.h +++ b/drivers/net/wireless/p54/p54usb.h | |||
@@ -72,6 +72,11 @@ struct net2280_tx_hdr { | |||
72 | u8 padding[8]; | 72 | u8 padding[8]; |
73 | } __attribute__((packed)); | 73 | } __attribute__((packed)); |
74 | 74 | ||
75 | struct lm87_tx_hdr { | ||
76 | __le32 device_addr; | ||
77 | __le32 chksum; | ||
78 | } __attribute__((packed)); | ||
79 | |||
75 | /* Some flags for the isl hardware registers controlling DMA inside the | 80 | /* Some flags for the isl hardware registers controlling DMA inside the |
76 | * chip */ | 81 | * chip */ |
77 | #define ISL38XX_DMA_STATUS_DONE 0x00000001 | 82 | #define ISL38XX_DMA_STATUS_DONE 0x00000001 |