/*
* EEPROM parser code for mac80211 Prism54 drivers
*
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
* Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
*
* Based on:
* - the islsm (softmac prism54) driver, which is:
* Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
* - stlc45xx driver
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
*
* 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 <linux/sort.h>
#include <linux/slab.h>
#include <net/mac80211.h>
#include <linux/crc-ccitt.h>
#include <linux/export.h>
#include "p54.h"
#include "eeprom.h"
#include "lmac.h"
static struct ieee80211_rate p54_bgrates[] = {
{ .bitrate = 10, .hw_value = 0, },
{ .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 60, .hw_value = 4, },
{ .bitrate = 90, .hw_value = 5, },
{ .bitrate = 120, .hw_value = 6, },
{ .bitrate = 180, .hw_value = 7, },
{ .bitrate = 240, .hw_value = 8, },
{ .bitrate = 360, .hw_value = 9, },
{ .bitrate = 480, .hw_value = 10, },
{ .bitrate = 540, .hw_value = 11, },
};
static struct ieee80211_rate p54_arates[] = {
{ .bitrate = 60, .hw_value = 4, },
{ .bitrate = 90, .hw_value = 5, },
{ .bitrate = 120, .hw_value = 6, },
{ .bitrate = 180, .hw_value = 7, },
{ .bitrate = 240, .hw_value = 8, },
{ .bitrate = 360, .hw_value = 9, },
{ .bitrate = 480, .hw_value = 10, },
{ .bitrate = 540, .hw_value = 11, },
};
static struct p54_rssi_db_entry p54_rssi_default = {
/*
* The defaults are taken from usb-logs of the
* vendor driver. So, they should be safe to
* use in case we can't get a match from the
* rssi <-> dBm conversion database.
*/
.mul = 130,
.add = -398,
};
#define CHAN_HAS_CAL BIT(0)
#define CHAN_HAS_LIMIT BIT(1)
#define CHAN_HAS_CURVE BIT(2)
#define CHAN_HAS_ALL (CHAN_HAS_CAL | CHAN_HAS_LIMIT | CHAN_HAS_CURVE)
struct p54_channel_entry {
u16 freq;
u16 data;
int index;
enum ieee80211_band band;
};
struct p54_channel_list {
struct p54_channel_entry *channels;
size_t entries;
size_t max_entries;
size_t band_channel_num[IEEE80211_NUM_BANDS];
};
static int p54_get_band_from_freq(u16 freq)
{
/* FIXME: sync these values with the 802.11 spec */
if ((freq >= 2412) && (freq <= 2484))
return IEEE80211_BAND_2GHZ;
if ((freq >= 4920) && (freq <= 5825))
return IEEE80211_BAND_5GHZ;
return -1;
}
static int same_band(u16 freq, u16 freq2)
{
return p54_get_band_from_freq(freq) == p54_get_band_from_freq(freq2);
}
static int p54_compare_channels(const void *_a,
const void *_b)
{
const struct p54_channel_entry *a = _a;
const struct p54_channel_entry *b = _b;
return a->freq - b->freq;
}
static int p54_compare_rssichan(const void *_a,
const void *_b)
{
const struct p54_rssi_db_entry *a = _a;
const struct p54_rssi_db_entry *b = _b;
return a->freq - b->freq;
}
static int p54_fill_band_bitrates(struct ieee80211_hw *dev,
struct ieee80211_supported_band *band_entry,
enum ieee80211_band band)
{
/* TODO: generate rate array dynamically */
switch (band) {
case IEEE80211_BAND_2GHZ:
band_entry->bitrates = p54_bgrates;
band_entry->n_bitrates = ARRAY_SIZE(p54_bgrates);
break;
case IEEE80211_BAND_5GHZ:
band_entry->bitrates = p54_arates;
band_entry->n_bitrates = ARRAY_SIZE(p54_arates);
break;
default:
return -EINVAL;
}
return