/*
* Common code for mac80211 Prism54 drivers
*
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
* Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
*
* Based on the islsm (softmac prism54) driver, which is:
* Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <net/mac80211.h>
#include "p54.h"
#include "p54common.h"
MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
MODULE_DESCRIPTION("Softmac Prism54 common code");
MODULE_LICENSE("GPL");
MODULE_ALIAS("prism54common");
void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
{
struct p54_common *priv = dev->priv;
struct bootrec_exp_if *exp_if;
struct bootrec *bootrec;
u32 *data = (u32 *)fw->data;
u32 *end_data = (u32 *)fw->data + (fw->size >> 2);
u8 *fw_version = NULL;
size_t len;
int i;
if (priv->rx_start)
return;
while (data < end_data && *data)
data++;
while (data < end_data && !*data)
data++;
bootrec = (struct bootrec *) data;
while (bootrec->data <= end_data &&
(bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) {
u32 code = le32_to_cpu(bootrec->code);
switch (code) {
case BR_CODE_COMPONENT_ID:
switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
case FW_FMAC:
printk(KERN_INFO "p54: FreeMAC firmware\n");
break;
case FW_LM20:
printk(KERN_INFO "p54: LM20 firmware\n");
break;
case FW_LM86:
printk(KERN_INFO "p54: LM86 firmware\n");
break;
case FW_LM87:
printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n");
break;
default:
printk(KERN_INFO "p54: unknown firmware\n");
break;
}
break;
case BR_CODE_COMPONENT_VERSION:
/* 24 bytes should be enough for all firmwares */
if (strnlen((unsigned char*)bootrec->data, 24) < 24)
fw_version = (unsigned char*)bootrec->data;
break;
case BR_CODE_DESCR:
priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]);
/* FIXME add sanity checking */
priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500;
break;
case BR_CODE_EXPOSED_IF:
exp_if = (struct bootrec_exp_if *) bootrec->data;
for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
if (exp_if[i].if_id == cpu_to_le16(0x1a))
priv->fw_var = le16_to_cpu(exp_if[i].variant);
break;
case BR_CODE_DEPENDENT_IF:
break;
case BR_CODE_END_OF_BRA:
case LEGACY_BR_CODE_END_OF_BRA:
end_data = NULL;
break;
default:
break;
}
bootrec = (struct bootrec *)&bootrec->data[len];
}
if (fw_version)
printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n",
fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
if (priv->fw_var >= 0x300) {
/* Firmware supports QoS, use it! */
priv->tx_stats.data[0].limit = 3;
priv->tx_stats.data[1].limit = 4;
priv->tx_stats.data[2].limit = 3;
priv->tx_stats.data[3].limit = 1;
dev->queues = 4;
}
}
EXPORT_SYMBOL_GPL(p54_parse_firmware);
static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
struct pda_pa_curve_data *curve_data)
{
struct p54_common *priv