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>
This commit is contained in:
committed by
John W. Linville
parent
d203b8ef8e
commit
2b80848e38
@@ -42,6 +42,11 @@ struct p54_control_hdr {
|
|||||||
|
|
||||||
#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
|
#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
|
||||||
|
|
||||||
|
#define FW_FMAC 0x464d4143
|
||||||
|
#define FW_LM86 0x4c4d3836
|
||||||
|
#define FW_LM87 0x4c4d3837
|
||||||
|
#define FW_LM20 0x4c4d3230
|
||||||
|
|
||||||
struct p54_common {
|
struct p54_common {
|
||||||
u32 rx_start;
|
u32 rx_start;
|
||||||
u32 rx_end;
|
u32 rx_end;
|
||||||
@@ -68,6 +73,7 @@ struct p54_common {
|
|||||||
unsigned int tx_hdr_len;
|
unsigned int tx_hdr_len;
|
||||||
void *cached_vdcf;
|
void *cached_vdcf;
|
||||||
unsigned int fw_var;
|
unsigned int fw_var;
|
||||||
|
unsigned int fw_interface;
|
||||||
struct ieee80211_tx_queue_stats tx_stats[8];
|
struct ieee80211_tx_queue_stats tx_stats[8];
|
||||||
void *eeprom;
|
void *eeprom;
|
||||||
struct completion eeprom_comp;
|
struct completion eeprom_comp;
|
||||||
|
@@ -93,7 +93,8 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
|
|||||||
u32 code = le32_to_cpu(bootrec->code);
|
u32 code = le32_to_cpu(bootrec->code);
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case BR_CODE_COMPONENT_ID:
|
case BR_CODE_COMPONENT_ID:
|
||||||
switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
|
priv->fw_interface = be32_to_cpup(bootrec->data);
|
||||||
|
switch (priv->fw_interface) {
|
||||||
case FW_FMAC:
|
case FW_FMAC:
|
||||||
printk(KERN_INFO "p54: FreeMAC firmware\n");
|
printk(KERN_INFO "p54: FreeMAC firmware\n");
|
||||||
break;
|
break;
|
||||||
@@ -104,7 +105,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
|
|||||||
printk(KERN_INFO "p54: LM86 firmware\n");
|
printk(KERN_INFO "p54: LM86 firmware\n");
|
||||||
break;
|
break;
|
||||||
case FW_LM87:
|
case FW_LM87:
|
||||||
printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n");
|
printk(KERN_INFO "p54: LM87 firmware\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_INFO "p54: unknown firmware\n");
|
printk(KERN_INFO "p54: unknown firmware\n");
|
||||||
|
@@ -50,11 +50,6 @@ struct bootrec_desc {
|
|||||||
#define BR_CODE_END_OF_BRA 0xFF0000FF
|
#define BR_CODE_END_OF_BRA 0xFF0000FF
|
||||||
#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF
|
#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF
|
||||||
|
|
||||||
#define FW_FMAC 0x464d4143
|
|
||||||
#define FW_LM86 0x4c4d3836
|
|
||||||
#define FW_LM87 0x4c4d3837
|
|
||||||
#define FW_LM20 0x4c4d3230
|
|
||||||
|
|
||||||
/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
|
/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
|
||||||
|
|
||||||
struct pda_entry {
|
struct pda_entry {
|
||||||
|
@@ -91,8 +91,13 @@ static void p54u_rx_cb(struct urb *urb)
|
|||||||
|
|
||||||
skb_unlink(skb, &priv->rx_queue);
|
skb_unlink(skb, &priv->rx_queue);
|
||||||
skb_put(skb, urb->actual_length);
|
skb_put(skb, urb->actual_length);
|
||||||
if (!priv->hw_type)
|
|
||||||
skb_pull(skb, sizeof(struct net2280_tx_hdr));
|
if (priv->hw_type == P54U_NET2280)
|
||||||
|
skb_pull(skb, priv->common.tx_hdr_len);
|
||||||
|
if (priv->common.fw_interface == FW_LM87) {
|
||||||
|
skb_pull(skb, 4);
|
||||||
|
skb_put(skb, 4);
|
||||||
|
}
|
||||||
|
|
||||||
if (p54_rx(dev, skb)) {
|
if (p54_rx(dev, skb)) {
|
||||||
skb = dev_alloc_skb(priv->common.rx_mtu + 32);
|
skb = dev_alloc_skb(priv->common.rx_mtu + 32);
|
||||||
@@ -109,9 +114,12 @@ static void p54u_rx_cb(struct urb *urb)
|
|||||||
urb->context = skb;
|
urb->context = skb;
|
||||||
skb_queue_tail(&priv->rx_queue, skb);
|
skb_queue_tail(&priv->rx_queue, skb);
|
||||||
} else {
|
} else {
|
||||||
if (!priv->hw_type)
|
if (priv->hw_type == P54U_NET2280)
|
||||||
skb_push(skb, sizeof(struct net2280_tx_hdr));
|
skb_push(skb, priv->common.tx_hdr_len);
|
||||||
|
if (priv->common.fw_interface == FW_LM87) {
|
||||||
|
skb_push(skb, 4);
|
||||||
|
skb_put(skb, 4);
|
||||||
|
}
|
||||||
skb_reset_tail_pointer(skb);
|
skb_reset_tail_pointer(skb);
|
||||||
skb_trim(skb, 0);
|
skb_trim(skb, 0);
|
||||||
if (urb->transfer_buffer != skb_tail_pointer(skb)) {
|
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,
|
|||||||
usb_submit_urb(data_urb, GFP_ATOMIC);
|
usb_submit_urb(data_urb, GFP_ATOMIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__le32 p54u_lm87_chksum(const u32 *data, size_t length)
|
||||||
|
{
|
||||||
|
__le32 chk = 0;
|
||||||
|
|
||||||
|
length >>= 2;
|
||||||
|
while (length--) {
|
||||||
|
chk ^= cpu_to_le32(*data++);
|
||||||
|
chk = (chk >> 5) ^ (chk << 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void p54u_tx_lm87(struct ieee80211_hw *dev,
|
||||||
|
struct p54_control_hdr *data,
|
||||||
|
size_t len, int free_on_tx)
|
||||||
|
{
|
||||||
|
struct p54u_priv *priv = dev->priv;
|
||||||
|
struct urb *data_urb;
|
||||||
|
struct lm87_tx_hdr *hdr = (void *)data - sizeof(*hdr);
|
||||||
|
|
||||||
|
data_urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||||
|
if (!data_urb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hdr->chksum = p54u_lm87_chksum((u32 *)data, len);
|
||||||
|
hdr->device_addr = data->req_id;
|
||||||
|
|
||||||
|
usb_fill_bulk_urb(data_urb, priv->udev,
|
||||||
|
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr,
|
||||||
|
len + sizeof(*hdr), free_on_tx ? p54u_tx_free_cb : p54u_tx_cb,
|
||||||
|
dev);
|
||||||
|
|
||||||
|
usb_submit_urb(data_urb, GFP_ATOMIC);
|
||||||
|
}
|
||||||
|
|
||||||
static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
|
static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
|
||||||
size_t len, int free_on_tx)
|
size_t len, int free_on_tx)
|
||||||
{
|
{
|
||||||
@@ -776,21 +820,23 @@ static int __devinit p54u_probe(struct usb_interface *intf,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
priv->common.open = p54u_open;
|
priv->common.open = p54u_open;
|
||||||
|
priv->common.stop = p54u_stop;
|
||||||
if (recognized_pipes < P54U_PIPE_NUMBER) {
|
if (recognized_pipes < P54U_PIPE_NUMBER) {
|
||||||
priv->hw_type = P54U_3887;
|
priv->hw_type = P54U_3887;
|
||||||
|
err = p54u_upload_firmware_3887(dev);
|
||||||
|
if (priv->common.fw_interface == FW_LM87) {
|
||||||
|
dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
|
||||||
|
priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
|
||||||
|
priv->common.tx = p54u_tx_lm87;
|
||||||
|
} else
|
||||||
priv->common.tx = p54u_tx_3887;
|
priv->common.tx = p54u_tx_3887;
|
||||||
} else {
|
} else {
|
||||||
|
priv->hw_type = P54U_NET2280;
|
||||||
dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
|
dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
|
||||||
priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
|
priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
|
||||||
priv->common.tx = p54u_tx_net2280;
|
priv->common.tx = p54u_tx_net2280;
|
||||||
}
|
|
||||||
priv->common.stop = p54u_stop;
|
|
||||||
|
|
||||||
if (priv->hw_type)
|
|
||||||
err = p54u_upload_firmware_3887(dev);
|
|
||||||
else
|
|
||||||
err = p54u_upload_firmware_net2280(dev);
|
err = p54u_upload_firmware_net2280(dev);
|
||||||
|
}
|
||||||
if (err)
|
if (err)
|
||||||
goto err_free_dev;
|
goto err_free_dev;
|
||||||
|
|
||||||
|
@@ -72,6 +72,11 @@ struct net2280_tx_hdr {
|
|||||||
u8 padding[8];
|
u8 padding[8];
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct lm87_tx_hdr {
|
||||||
|
__le32 device_addr;
|
||||||
|
__le32 chksum;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
/* Some flags for the isl hardware registers controlling DMA inside the
|
/* Some flags for the isl hardware registers controlling DMA inside the
|
||||||
* chip */
|
* chip */
|
||||||
#define ISL38XX_DMA_STATUS_DONE 0x00000001
|
#define ISL38XX_DMA_STATUS_DONE 0x00000001
|
||||||
|
Reference in New Issue
Block a user