提交 7d230df3 编写于 作者: G Greg Kroah-Hartman

Staging: remove agnx driver

The agnx driver in the staging tree is broken, does not work, and
development is dead.  The developers have asked for it to be removed
so it now is.
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 02921484
......@@ -59,8 +59,6 @@ source "drivers/staging/echo/Kconfig"
source "drivers/staging/poch/Kconfig"
source "drivers/staging/agnx/Kconfig"
source "drivers/staging/otus/Kconfig"
source "drivers/staging/rt2860/Kconfig"
......
......@@ -12,7 +12,6 @@ obj-$(CONFIG_W35UND) += winbond/
obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_POCH) += poch/
obj-$(CONFIG_AGNX) += agnx/
obj-$(CONFIG_OTUS) += otus/
obj-$(CONFIG_RT2860) += rt2860/
obj-$(CONFIG_RT2870) += rt2870/
......
config AGNX
tristate "Wireless Airgo AGNX support"
depends on WLAN_80211 && MAC80211
---help---
This is an experimental driver for Airgo AGNX00 wireless chip.
obj-$(CONFIG_AGNX) += agnx.o
agnx-objs := rf.o \
pci.o \
xmit.o \
table.o \
sta.o \
phy.o
2008 7/18
The RX has can't receive OFDM packet correctly,
Guess it need be do RX calibrate.
before 2008 3/1
1: The RX get too much "CRC failed" pakets, it make the card work very unstable,
2: After running a while, the card will get infinity "RX Frame" and "Error"
interrupt, not know the root reason so far, try to fix it
3: Using two tx queue txd and txm but not only txm.
4: Set the hdr correctly.
5: Try to do recalibrate correvtly
6: To support G mode in future
7: Fix the mac address can't be readed and set correctly in BE machine.
8: Fix include and exclude FCS in promisous mode and manage mode
9: Using sta_notify to notice sta change
10: Turn on frame reception at the end of start
11: Guess the card support HW_MULTICAST_FILTER
12: The tx process should be implment atomic?
13: Using mac80211 function to control the TX&RX LED.
#ifndef AGNX_H_
#define AGNX_H_
#include <linux/io.h>
#include "xmit.h"
#define PFX KBUILD_MODNAME ": "
static inline u32 agnx_read32(void __iomem *mem_region, u32 offset)
{
return ioread32(mem_region + offset);
}
static inline void agnx_write32(void __iomem *mem_region, u32 offset, u32 val)
{
iowrite32(val, mem_region + offset);
}
/* static const struct ieee80211_rate agnx_rates_80211b[] = { */
/* { .rate = 10, */
/* .val = 0xa, */
/* .flags = IEEE80211_RATE_CCK }, */
/* { .rate = 20, */
/* .val = 0x14, */
/* .hw_value = -0x14, */
/* .flags = IEEE80211_RATE_CCK_2 }, */
/* { .rate = 55, */
/* .val = 0x37, */
/* .val2 = -0x37, */
/* .flags = IEEE80211_RATE_CCK_2 }, */
/* { .rate = 110, */
/* .val = 0x6e, */
/* .val2 = -0x6e, */
/* .flags = IEEE80211_RATE_CCK_2 } */
/* }; */
static const struct ieee80211_rate agnx_rates_80211g[] = {
/* { .bitrate = 10, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
/* { .bitrate = 20, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
/* { .bitrate = 55, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
/* { .bitrate = 110, .hw_value = 4, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
{ .bitrate = 10, .hw_value = 1, },
{ .bitrate = 20, .hw_value = 2, },
{ .bitrate = 55, .hw_value = 3, },
{ .bitrate = 110, .hw_value = 4,},
{ .bitrate = 60, .hw_value = 0xB, },
{ .bitrate = 90, .hw_value = 0xF, },
{ .bitrate = 120, .hw_value = 0xA },
{ .bitrate = 180, .hw_value = 0xE, },
/* { .bitrate = 240, .hw_value = 0xd, }, */
{ .bitrate = 360, .hw_value = 0xD, },
{ .bitrate = 480, .hw_value = 0x8, },
{ .bitrate = 540, .hw_value = 0xC, },
};
static const struct ieee80211_channel agnx_channels[] = {
{ .center_freq = 2412, .hw_value = 1, },
{ .center_freq = 2417, .hw_value = 2, },
{ .center_freq = 2422, .hw_value = 3, },
{ .center_freq = 2427, .hw_value = 4, },
{ .center_freq = 2432, .hw_value = 5, },
{ .center_freq = 2437, .hw_value = 6, },
{ .center_freq = 2442, .hw_value = 7, },
{ .center_freq = 2447, .hw_value = 8, },
{ .center_freq = 2452, .hw_value = 9, },
{ .center_freq = 2457, .hw_value = 10, },
{ .center_freq = 2462, .hw_value = 11, },
{ .center_freq = 2467, .hw_value = 12, },
{ .center_freq = 2472, .hw_value = 13, },
{ .center_freq = 2484, .hw_value = 14, },
};
#define NUM_DRIVE_MODES 2
/* Agnx operate mode */
enum {
AGNX_MODE_80211A,
AGNX_MODE_80211A_OOB,
AGNX_MODE_80211A_MIMO,
AGNX_MODE_80211B_SHORT,
AGNX_MODE_80211B_LONG,
AGNX_MODE_80211G,
AGNX_MODE_80211G_OOB,
AGNX_MODE_80211G_MIMO,
};
enum {
AGNX_UNINIT,
AGNX_START,
AGNX_STOP,
};
struct agnx_priv {
struct pci_dev *pdev;
struct ieee80211_hw *hw;
spinlock_t lock;
struct mutex mutex;
unsigned int init_status;
void __iomem *ctl; /* pointer to base ram address */
void __iomem *data; /* pointer to mem region #2 */
struct agnx_ring rx;
struct agnx_ring txm;
struct agnx_ring txd;
/* Need volatile? */
u32 irq_status;
struct delayed_work periodic_work; /* Periodic tasks like recalibrate */
struct ieee80211_low_level_stats stats;
/* unsigned int phymode; */
int mode;
int channel;
u8 bssid[ETH_ALEN];
u8 mac_addr[ETH_ALEN];
u8 revid;
struct ieee80211_supported_band band;
};
#define AGNX_CHAINS_MAX 6
#define AGNX_PERIODIC_DELAY 60000 /* unit: ms */
#define LOCAL_STAID 0 /* the station entry for the card itself */
#define BSSID_STAID 1 /* the station entry for the bsssid AP */
#define spi_delay() udelay(40)
#define eeprom_delay() udelay(40)
#define routing_table_delay() udelay(50)
/* PDU pool MEM region #2 */
#define AGNX_PDUPOOL 0x40000 /* PDU pool */
#define AGNX_PDUPOOL_SIZE 0x8000 /* PDU pool size*/
#define AGNX_PDU_TX_WQ 0x41000 /* PDU list TX workqueue */
#define AGNX_PDU_FREE 0x41800 /* Free Pool */
#define PDU_SIZE 0x80 /* Free Pool node size */
#define PDU_FREE_CNT 0xd0 /* Free pool node count */
/* RF stuffs */
extern void rf_chips_init(struct agnx_priv *priv);
extern void spi_rc_write(void __iomem *mem_region, u32 chip_ids, u32 sw);
extern void calibrate_oscillator(struct agnx_priv *priv);
extern void do_calibration(struct agnx_priv *priv);
extern void antenna_calibrate(struct agnx_priv *priv);
extern void __antenna_calibrate(struct agnx_priv *priv);
extern void print_offsets(struct agnx_priv *priv);
extern int agnx_set_channel(struct agnx_priv *priv, unsigned int channel);
#endif /* AGNX_H_ */
#ifndef AGNX_DEBUG_H_
#define AGNX_DEBUG_H_
#include "agnx.h"
#include "phy.h"
#include "sta.h"
#include "xmit.h"
#define AGNX_TRACE printk(KERN_ERR PFX "function:%s line:%d\n", __func__, __LINE__)
#define PRINTK_LE16(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.4x\n", le16_to_cpu(var))
#define PRINTK_LE32(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.8x\n", le32_to_cpu(var))
#define PRINTK_U8(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.2x\n", var)
#define PRINTK_BE16(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.4x\n", be16_to_cpu(var))
#define PRINTK_BE32(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.8x\n", be32_to_cpu(var))
#define PRINTK_BITS(prefix, field) printk(KERN_DEBUG PFX #prefix ": " #field ": 0x%x\n", (reg & field) >> field##_SHIFT)
static inline void agnx_bug(char *reason)
{
printk(KERN_ERR PFX "%s\n", reason);
BUG();
}
static inline void agnx_print_desc(struct agnx_desc *desc)
{
u32 reg = be32_to_cpu(desc->frag);
PRINTK_BITS(DESC, PACKET_LEN);
if (reg & FIRST_FRAG) {
PRINTK_BITS(DESC, FIRST_PACKET_MASK);
PRINTK_BITS(DESC, FIRST_RESERV2);
PRINTK_BITS(DESC, FIRST_TKIP_ERROR);
PRINTK_BITS(DESC, FIRST_TKIP_PACKET);
PRINTK_BITS(DESC, FIRST_RESERV1);
PRINTK_BITS(DESC, FIRST_FRAG_LEN);
} else {
PRINTK_BITS(DESC, SUB_RESERV2);
PRINTK_BITS(DESC, SUB_TKIP_ERROR);
PRINTK_BITS(DESC, SUB_TKIP_PACKET);
PRINTK_BITS(DESC, SUB_RESERV1);
PRINTK_BITS(DESC, SUB_FRAG_LEN);
}
PRINTK_BITS(DESC, FIRST_FRAG);
PRINTK_BITS(DESC, LAST_FRAG);
PRINTK_BITS(DESC, OWNER);
}
static inline void dump_ieee80211b_phy_hdr(__be32 _11b0, __be32 _11b1)
{
}
static inline void agnx_print_hdr(struct agnx_hdr *hdr)
{
u32 reg;
int i;
reg = be32_to_cpu(hdr->reg0);
PRINTK_BITS(HDR, RTS);
PRINTK_BITS(HDR, MULTICAST);
PRINTK_BITS(HDR, ACK);
PRINTK_BITS(HDR, TM);
PRINTK_BITS(HDR, RELAY);
PRINTK_BITS(HDR, REVISED_FCS);
PRINTK_BITS(HDR, NEXT_BUFFER_ADDR);
reg = be32_to_cpu(hdr->reg1);
PRINTK_BITS(HDR, MAC_HDR_LEN);
PRINTK_BITS(HDR, DURATION_OVERIDE);
PRINTK_BITS(HDR, PHY_HDR_OVERIDE);
PRINTK_BITS(HDR, CRC_FAIL);
PRINTK_BITS(HDR, SEQUENCE_NUMBER);
PRINTK_BITS(HDR, BUFF_HEAD_ADDR);
reg = be32_to_cpu(hdr->reg2);
PRINTK_BITS(HDR, PDU_COUNT);
PRINTK_BITS(HDR, WEP_KEY);
PRINTK_BITS(HDR, USES_WEP_KEY);
PRINTK_BITS(HDR, KEEP_ALIVE);
PRINTK_BITS(HDR, BUFF_TAIL_ADDR);
reg = be32_to_cpu(hdr->reg3);
PRINTK_BITS(HDR, CTS_11G);
PRINTK_BITS(HDR, RTS_11G);
PRINTK_BITS(HDR, FRAG_SIZE);
PRINTK_BITS(HDR, PAYLOAD_LEN);
PRINTK_BITS(HDR, FRAG_NUM);
reg = be32_to_cpu(hdr->reg4);
PRINTK_BITS(HDR, RELAY_STAID);
PRINTK_BITS(HDR, STATION_ID);
PRINTK_BITS(HDR, WORKQUEUE_ID);
reg = be32_to_cpu(hdr->reg5);
/* printf the route flag */
PRINTK_BITS(HDR, ROUTE_HOST);
PRINTK_BITS(HDR, ROUTE_CARD_CPU);
PRINTK_BITS(HDR, ROUTE_ENCRYPTION);
PRINTK_BITS(HDR, ROUTE_TX);
PRINTK_BITS(HDR, ROUTE_RX1);
PRINTK_BITS(HDR, ROUTE_RX2);
PRINTK_BITS(HDR, ROUTE_COMPRESSION);
PRINTK_BE32(HDR, hdr->_11g0);
PRINTK_BE32(HDR, hdr->_11g1);
PRINTK_BE32(HDR, hdr->_11b0);
PRINTK_BE32(HDR, hdr->_11b1);
dump_ieee80211b_phy_hdr(hdr->_11b0, hdr->_11b1);
/* Fixme */
for (i = 0; i < ARRAY_SIZE(hdr->mac_hdr); i++) {
if (i == 0)
printk(KERN_DEBUG PFX "IEEE80211 HDR: ");
printk("%.2x ", hdr->mac_hdr[i]);
if (i + 1 == ARRAY_SIZE(hdr->mac_hdr))
printk("\n");
}
PRINTK_BE16(HDR, hdr->rts_duration);
PRINTK_BE16(HDR, hdr->last_duration);
PRINTK_BE16(HDR, hdr->sec_last_duration);
PRINTK_BE16(HDR, hdr->other_duration);
PRINTK_BE16(HDR, hdr->tx_other_duration);
PRINTK_BE16(HDR, hdr->last_11g_len);
PRINTK_BE16(HDR, hdr->other_11g_len);
PRINTK_BE16(HDR, hdr->last_11b_len);
PRINTK_BE16(HDR, hdr->other_11b_len);
/* FIXME */
reg = be16_to_cpu(hdr->reg6);
PRINTK_BITS(HDR, MBF);
PRINTK_BITS(HDR, RSVD4);
PRINTK_BE16(HDR, hdr->rx_frag_stat);
PRINTK_BE32(HDR, hdr->time_stamp);
PRINTK_BE32(HDR, hdr->phy_stats_hi);
PRINTK_BE32(HDR, hdr->phy_stats_lo);
PRINTK_BE32(HDR, hdr->mic_key0);
PRINTK_BE32(HDR, hdr->mic_key1);
} /* agnx_print_hdr */
static inline void agnx_print_rx_hdr(struct agnx_hdr *hdr)
{
agnx_print_hdr(hdr);
PRINTK_BE16(HDR, hdr->rx.rx_packet_duration);
PRINTK_BE16(HDR, hdr->rx.replay_cnt);
PRINTK_U8(HDR, hdr->rx_channel);
}
static inline void agnx_print_tx_hdr(struct agnx_hdr *hdr)
{
agnx_print_hdr(hdr);
PRINTK_U8(HDR, hdr->tx.long_retry_limit);
PRINTK_U8(HDR, hdr->tx.short_retry_limit);
PRINTK_U8(HDR, hdr->tx.long_retry_cnt);
PRINTK_U8(HDR, hdr->tx.short_retry_cnt);
PRINTK_U8(HDR, hdr->rx_channel);
}
static inline void
agnx_print_sta_power(struct agnx_priv *priv, unsigned int sta_idx)
{
struct agnx_sta_power power;
u32 reg;
get_sta_power(priv, &power, sta_idx);
reg = le32_to_cpu(power.reg);
PRINTK_BITS(STA_POWER, SIGNAL);
PRINTK_BITS(STA_POWER, RATE);
PRINTK_BITS(STA_POWER, TIFS);
PRINTK_BITS(STA_POWER, EDCF);
PRINTK_BITS(STA_POWER, CHANNEL_BOND);
PRINTK_BITS(STA_POWER, PHY_MODE);
PRINTK_BITS(STA_POWER, POWER_LEVEL);
PRINTK_BITS(STA_POWER, NUM_TRANSMITTERS);
}
static inline void
agnx_print_sta_tx_wq(struct agnx_priv *priv, unsigned int sta_idx, unsigned int wq_idx)
{
struct agnx_sta_tx_wq tx_wq;
u32 reg;
get_sta_tx_wq(priv, &tx_wq, sta_idx, wq_idx);
reg = le32_to_cpu(tx_wq.reg0);
PRINTK_BITS(STA_TX_WQ, TAIL_POINTER);
PRINTK_BITS(STA_TX_WQ, HEAD_POINTER_LOW);
reg = le32_to_cpu(tx_wq.reg3);
PRINTK_BITS(STA_TX_WQ, HEAD_POINTER_HIGH);
PRINTK_BITS(STA_TX_WQ, ACK_POINTER_LOW);
reg = le32_to_cpu(tx_wq.reg1);
PRINTK_BITS(STA_TX_WQ, ACK_POINTER_HIGH);
PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_TAIL_PACK_CNT);
PRINTK_BITS(STA_TX_WQ, ACK_TIMOUT_TAIL_PACK_CNT);
reg = le32_to_cpu(tx_wq.reg2);
PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_WIN_LIM_BYTE_CNT);
PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_WIN_LIM_FRAG_CNT);
PRINTK_BITS(STA_TX_WQ, WORK_QUEUE_ACK_TYPE);
PRINTK_BITS(STA_TX_WQ, WORK_QUEUE_VALID);
}
static inline void agnx_print_sta_traffic(struct agnx_sta_traffic *traffic)
{
u32 reg;
reg = le32_to_cpu(traffic->reg0);
PRINTK_BITS(STA_TRAFFIC, ACK_TIMOUT_CNT);
PRINTK_BITS(STA_TRAFFIC, TRAFFIC_ACK_TYPE);
PRINTK_BITS(STA_TRAFFIC, NEW_PACKET);
PRINTK_BITS(STA_TRAFFIC, TRAFFIC_VALID);
PRINTK_BITS(STA_TRAFFIC, RX_HDR_DESC_POINTER);
reg = le32_to_cpu(traffic->reg1);
PRINTK_BITS(STA_TRAFFIC, RX_PACKET_TIMESTAMP);
PRINTK_BITS(STA_TRAFFIC, TRAFFIC_RESERVED);
PRINTK_BITS(STA_TRAFFIC, SV);
PRINTK_BITS(STA_TRAFFIC, RX_SEQUENCE_NUM);
PRINTK_LE32(STA_TRAFFIC, traffic->tx_replay_cnt_low);
PRINTK_LE16(STA_TRAFFIC, traffic->tx_replay_cnt_high);
PRINTK_LE16(STA_TRAFFIC, traffic->rx_replay_cnt_high);
PRINTK_LE32(STA_TRAFFIC, traffic->rx_replay_cnt_low);
}
static inline void agnx_print_sta(struct agnx_priv *priv, unsigned int sta_idx)
{
struct agnx_sta station;
struct agnx_sta *sta = &station;
u32 reg;
unsigned int i;
get_sta(priv, sta, sta_idx);
for (i = 0; i < 4; i++)
PRINTK_LE32(STA, sta->tx_session_keys[i]);
for (i = 0; i < 4; i++)
PRINTK_LE32(STA, sta->rx_session_keys[i]);
reg = le32_to_cpu(sta->reg);
PRINTK_BITS(STA, ID_1);
PRINTK_BITS(STA, ID_0);
PRINTK_BITS(STA, ENABLE_CONCATENATION);
PRINTK_BITS(STA, ENABLE_DECOMPRESSION);
PRINTK_BITS(STA, STA_RESERVED);
PRINTK_BITS(STA, EAP);
PRINTK_BITS(STA, ED_NULL);
PRINTK_BITS(STA, ENCRYPTION_POLICY);
PRINTK_BITS(STA, DEFINED_KEY_ID);
PRINTK_BITS(STA, FIXED_KEY);
PRINTK_BITS(STA, KEY_VALID);
PRINTK_BITS(STA, STATION_VALID);
PRINTK_LE32(STA, sta->tx_aes_blks_unicast);
PRINTK_LE32(STA, sta->rx_aes_blks_unicast);
PRINTK_LE16(STA, sta->aes_format_err_unicast_cnt);
PRINTK_LE16(STA, sta->aes_replay_unicast);
PRINTK_LE16(STA, sta->aes_decrypt_err_unicast);
PRINTK_LE16(STA, sta->aes_decrypt_err_default);
PRINTK_LE16(STA, sta->single_retry_packets);
PRINTK_LE16(STA, sta->failed_tx_packets);
PRINTK_LE16(STA, sta->muti_retry_packets);
PRINTK_LE16(STA, sta->ack_timeouts);
PRINTK_LE16(STA, sta->frag_tx_cnt);
PRINTK_LE16(STA, sta->rts_brq_sent);
PRINTK_LE16(STA, sta->tx_packets);
PRINTK_LE16(STA, sta->cts_back_timeout);
PRINTK_LE32(STA, sta->phy_stats_high);
PRINTK_LE32(STA, sta->phy_stats_low);
/* for (i = 0; i < 8; i++) */
agnx_print_sta_traffic(sta->traffic + 0);
PRINTK_LE16(STA, sta->traffic_class0_frag_success);
PRINTK_LE16(STA, sta->traffic_class1_frag_success);
PRINTK_LE16(STA, sta->traffic_class2_frag_success);
PRINTK_LE16(STA, sta->traffic_class3_frag_success);
PRINTK_LE16(STA, sta->traffic_class4_frag_success);
PRINTK_LE16(STA, sta->traffic_class5_frag_success);
PRINTK_LE16(STA, sta->traffic_class6_frag_success);
PRINTK_LE16(STA, sta->traffic_class7_frag_success);
PRINTK_LE16(STA, sta->num_frag_non_prime_rates);
PRINTK_LE16(STA, sta->ack_timeout_non_prime_rates);
}
static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
{
u16 fctl;
int hdrlen;
fctl = le16_to_cpu(hdr->frame_control);
switch (fctl & IEEE80211_FCTL_FTYPE) {
case IEEE80211_FTYPE_DATA:
printk(PFX "%s DATA ", tag);
break;
case IEEE80211_FTYPE_CTL:
printk(PFX "%s CTL ", tag);
break;
case IEEE80211_FTYPE_MGMT:
printk(PFX "%s MGMT ", tag);
switch (fctl & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_ASSOC_REQ:
printk("SubType: ASSOC_REQ ");
break;
case IEEE80211_STYPE_ASSOC_RESP:
printk("SubType: ASSOC_RESP ");
break;
case IEEE80211_STYPE_REASSOC_REQ:
printk("SubType: REASSOC_REQ ");
break;
case IEEE80211_STYPE_REASSOC_RESP:
printk("SubType: REASSOC_RESP ");
break;
case IEEE80211_STYPE_PROBE_REQ:
printk("SubType: PROBE_REQ ");
break;
case IEEE80211_STYPE_PROBE_RESP:
printk("SubType: PROBE_RESP ");
break;
case IEEE80211_STYPE_BEACON:
printk("SubType: BEACON ");
break;
case IEEE80211_STYPE_ATIM:
printk("SubType: ATIM ");
break;
case IEEE80211_STYPE_DISASSOC:
printk("SubType: DISASSOC ");
break;
case IEEE80211_STYPE_AUTH:
printk("SubType: AUTH ");
break;
case IEEE80211_STYPE_DEAUTH:
printk("SubType: DEAUTH ");
break;
case IEEE80211_STYPE_ACTION:
printk("SubType: ACTION ");
break;
default:
printk("SubType: Unknow\n");
}
break;
default:
printk(PFX "%s Packet type: Unknow\n", tag);
}
hdrlen = ieee80211_hdrlen(fctl);
if (hdrlen >= 4)
printk("FC=0x%04x DUR=0x%04x",
fctl, le16_to_cpu(hdr->duration_id));
if (hdrlen >= 10)
printk(" A1=%pM", hdr->addr1);
if (hdrlen >= 16)
printk(" A2=%pM", hdr->addr2);
if (hdrlen >= 24)
printk(" A3=%pM", hdr->addr3);
if (hdrlen >= 30)
printk(" A4=%pM", hdr->addr4);
printk("\n");
}
static inline void dump_txm_registers(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
int i;
for (i = 0; i <= 0x1e8; i += 4)
printk(KERN_DEBUG PFX "TXM: %x---> 0x%.8x\n", i, ioread32(ctl + i));
}
static inline void dump_rxm_registers(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
int i;
for (i = 0; i <= 0x108; i += 4)
printk(KERN_DEBUG PFX "RXM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2000 + i));
}
static inline void dump_bm_registers(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
int i;
for (i = 0; i <= 0x90; i += 4)
printk(KERN_DEBUG PFX "BM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2c00 + i));
}
static inline void dump_cir_registers(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
int i;
for (i = 0; i <= 0xb8; i += 4)
printk(KERN_DEBUG PFX "CIR: %x---> 0x%.8x\n", i, ioread32(ctl + 0x3000 + i));
}
#endif /* AGNX_DEBUG_H_ */
/**
* Airgo MIMO wireless driver
*
* Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
* Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
* works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
* 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/etherdevice.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include "agnx.h"
#include "debug.h"
#include "xmit.h"
#include "phy.h"
MODULE_AUTHOR("Li YanBo <dreamfly281@gmail.com>");
MODULE_DESCRIPTION("Airgo MIMO PCI wireless driver");
MODULE_LICENSE("GPL");
static struct pci_device_id agnx_pci_id_tbl[] __devinitdata = {
{ PCI_DEVICE(0x17cb, 0x0001) }, /* Beklin F5d8010, Netgear WGM511 etc */
{ PCI_DEVICE(0x17cb, 0x0002) }, /* Netgear Wpnt511 */
{ 0 }
};
MODULE_DEVICE_TABLE(pci, agnx_pci_id_tbl);
static inline void agnx_interrupt_ack(struct agnx_priv *priv, u32 *reason)
{
void __iomem *ctl = priv->ctl;
u32 reg;
if (*reason & AGNX_STAT_RX) {
/* Mark complete RX */
reg = ioread32(ctl + AGNX_CIR_RXCTL);
reg |= 0x4;
iowrite32(reg, ctl + AGNX_CIR_RXCTL);
/* disable Rx interrupt */
}
if (*reason & AGNX_STAT_TX) {
reg = ioread32(ctl + AGNX_CIR_TXDCTL);
if (reg & 0x4) {
iowrite32(reg, ctl + AGNX_CIR_TXDCTL);
*reason |= AGNX_STAT_TXD;
}
reg = ioread32(ctl + AGNX_CIR_TXMCTL);
if (reg & 0x4) {
iowrite32(reg, ctl + AGNX_CIR_TXMCTL);
*reason |= AGNX_STAT_TXM;
}
}
#if 0
if (*reason & AGNX_STAT_X) {
reg = ioread32(ctl + AGNX_INT_STAT);
iowrite32(reg, ctl + AGNX_INT_STAT);
/* FIXME reinit interrupt mask */
reg = 0xc390bf9 & ~IRQ_TX_BEACON;
reg &= ~IRQ_TX_DISABLE;
iowrite32(reg, ctl + AGNX_INT_MASK);
iowrite32(0x800, ctl + AGNX_CIR_BLKCTL);
}
#endif
} /* agnx_interrupt_ack */
static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
{
struct ieee80211_hw *dev = dev_id;
struct agnx_priv *priv = dev->priv;
void __iomem *ctl = priv->ctl;
irqreturn_t ret = IRQ_NONE;
u32 irq_reason;
spin_lock(&priv->lock);
/* printk(KERN_ERR PFX "Get a interrupt %s\n", __func__); */
if (priv->init_status != AGNX_START)
goto out;
/* FiXME Here has no lock, Is this will lead to race? */
irq_reason = ioread32(ctl + AGNX_CIR_BLKCTL);
if (!(irq_reason & 0x7))
goto out;
ret = IRQ_HANDLED;
priv->irq_status = ioread32(ctl + AGNX_INT_STAT);
/* printk(PFX "Interrupt reason is 0x%x\n", irq_reason); */
/* Make sure the txm and txd flags don't conflict with other unknown
interrupt flag, maybe is not necessary */
irq_reason &= 0xF;
disable_rx_interrupt(priv);
/* TODO Make sure the card finished initialized */
agnx_interrupt_ack(priv, &irq_reason);
if (irq_reason & AGNX_STAT_RX)
handle_rx_irq(priv);
if (irq_reason & AGNX_STAT_TXD)
handle_txd_irq(priv);
if (irq_reason & AGNX_STAT_TXM)
handle_txm_irq(priv);
if (irq_reason & AGNX_STAT_X)
handle_other_irq(priv);
enable_rx_interrupt(priv);
out:
spin_unlock(&priv->lock);
return ret;
} /* agnx_interrupt_handler */
/* FIXME */
static int agnx_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
AGNX_TRACE;
return _agnx_tx(dev->priv, skb);
} /* agnx_tx */
static int agnx_get_mac_address(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
u32 reg;
AGNX_TRACE;
/* Attention! directly read the MAC or other date from EEPROM will
lead to cardbus(WGM511) lock up when write to PM PLL register */
reg = agnx_read32(ctl, 0x3544);
udelay(40);
reg = agnx_read32(ctl, 0x354c);
udelay(50);
/* Get the mac address */
reg = agnx_read32(ctl, 0x3544);
udelay(40);
/* HACK */
reg = cpu_to_le32(reg);
priv->mac_addr[0] = ((u8 *)&reg)[2];
priv->mac_addr[1] = ((u8 *)&reg)[3];
reg = agnx_read32(ctl, 0x3548);
udelay(50);
*((u32 *)(priv->mac_addr + 2)) = cpu_to_le32(reg);
if (!is_valid_ether_addr(priv->mac_addr)) {
printk(KERN_WARNING PFX "read mac %pM\n", priv->mac_addr);
printk(KERN_WARNING PFX "Invalid hwaddr! Using random hwaddr\n");
random_ether_addr(priv->mac_addr);
}
return 0;
} /* agnx_get_mac_address */
static int agnx_alloc_rings(struct agnx_priv *priv)
{
unsigned int len;
AGNX_TRACE;
/* Allocate RX/TXM/TXD rings info */
priv->rx.size = AGNX_RX_RING_SIZE;
priv->txm.size = AGNX_TXM_RING_SIZE;
priv->txd.size = AGNX_TXD_RING_SIZE;
len = priv->rx.size + priv->txm.size + priv->txd.size;
/* priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_KERNEL); */
priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_ATOMIC);
if (!priv->rx.info)
return -ENOMEM;
priv->txm.info = priv->rx.info + priv->rx.size;
priv->txd.info = priv->txm.info + priv->txm.size;
/* Allocate RX/TXM/TXD descriptors */
priv->rx.desc = pci_alloc_consistent(priv->pdev, sizeof(struct agnx_desc) * len,
&priv->rx.dma);
if (!priv->rx.desc) {
kfree(priv->rx.info);
return -ENOMEM;
}
priv->txm.desc = priv->rx.desc + priv->rx.size;
priv->txm.dma = priv->rx.dma + sizeof(struct agnx_desc) * priv->rx.size;
priv->txd.desc = priv->txm.desc + priv->txm.size;
priv->txd.dma = priv->txm.dma + sizeof(struct agnx_desc) * priv->txm.size;
return 0;
} /* agnx_alloc_rings */
static void rings_free(struct agnx_priv *priv)
{
unsigned int len = priv->rx.size + priv->txm.size + priv->txd.size;
unsigned long flags;
AGNX_TRACE;
spin_lock_irqsave(&priv->lock, flags);
kfree(priv->rx.info);
pci_free_consistent(priv->pdev, sizeof(struct agnx_desc) * len,
priv->rx.desc, priv->rx.dma);
spin_unlock_irqrestore(&priv->lock, flags);
}
#if 0
static void agnx_periodic_work_handler(struct work_struct *work)
{
struct agnx_priv *priv = container_of(work, struct agnx_priv, periodic_work.work);
/* unsigned long flags; */
unsigned long delay;
/* fixme: using mutex?? */
/* spin_lock_irqsave(&priv->lock, flags); */
/* TODO Recalibrate*/
/* calibrate_oscillator(priv); */
/* antenna_calibrate(priv); */
/* agnx_send_packet(priv, 997); */
/* FIXME */
/* if (debug == 3) */
/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
/* else */
delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY);
/* delay = round_jiffies(HZ * 15); */
queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay);
/* spin_unlock_irqrestore(&priv->lock, flags); */
}
#endif
static int agnx_start(struct ieee80211_hw *dev)
{
struct agnx_priv *priv = dev->priv;
/* unsigned long delay; */
int err = 0;
AGNX_TRACE;
err = agnx_alloc_rings(priv);
if (err) {
printk(KERN_ERR PFX "Can't alloc RX/TXM/TXD rings\n");
goto out;
}
err = request_irq(priv->pdev->irq, &agnx_interrupt_handler,
IRQF_SHARED, "agnx_pci", dev);
if (err) {
printk(KERN_ERR PFX "Failed to register IRQ handler\n");
rings_free(priv);
goto out;
}
/* mdelay(500); */
might_sleep();
agnx_hw_init(priv);
/* mdelay(500); */
might_sleep();
priv->init_status = AGNX_START;
/* INIT_DELAYED_WORK(&priv->periodic_work, agnx_periodic_work_handler); */
/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
/* queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay); */
out:
return err;
} /* agnx_start */
static void agnx_stop(struct ieee80211_hw *dev)
{
struct agnx_priv *priv = dev->priv;
AGNX_TRACE;
priv->init_status = AGNX_STOP;
/* make sure hardware will not generate irq */
agnx_hw_reset(priv);
free_irq(priv->pdev->irq, dev);
/* flush_workqueue(priv->hw->workqueue); */
/* cancel_delayed_work_sync(&priv->periodic_work); */
unfill_rings(priv);
rings_free(priv);
}
static int agnx_config(struct ieee80211_hw *dev, u32 changed)
{
struct agnx_priv *priv = dev->priv;
struct ieee80211_conf *conf = &dev->conf;
int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
AGNX_TRACE;
spin_lock(&priv->lock);
/* FIXME need priv lock? */
if (channel != priv->channel) {
priv->channel = channel;
agnx_set_channel(priv, priv->channel);
}
spin_unlock(&priv->lock);
return 0;
}
static void agnx_bss_info_changed(struct ieee80211_hw *dev,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf,
u32 changed)
{
struct agnx_priv *priv = dev->priv;
void __iomem *ctl = priv->ctl;
AGNX_TRACE;
if (!(changed & BSS_CHANGED_BSSID))
return;
spin_lock(&priv->lock);
if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {
agnx_set_bssid(priv, conf->bssid);
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
hash_write(priv, conf->bssid, BSSID_STAID);
sta_init(priv, BSSID_STAID);
/* FIXME needed? */
sta_power_init(priv, BSSID_STAID);
agnx_write32(ctl, AGNX_BM_MTSM, 0xff & ~0x1);
}
spin_unlock(&priv->lock);
} /* agnx_bss_info_changed */
static void agnx_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags,
unsigned int *total_flags,
int mc_count, struct dev_mc_list *mclist)
{
unsigned int new_flags = 0;
*total_flags = new_flags;
/* TODO */
}
static int agnx_add_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct agnx_priv *priv = dev->priv;
AGNX_TRACE;
spin_lock(&priv->lock);
/* FIXME */
if (priv->mode != NL80211_IFTYPE_MONITOR)
return -EOPNOTSUPP;
switch (conf->type) {
case NL80211_IFTYPE_STATION:
priv->mode = conf->type;
break;
default:
return -EOPNOTSUPP;
}
spin_unlock(&priv->lock);
return 0;
}
static void agnx_remove_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct agnx_priv *priv = dev->priv;
AGNX_TRACE;
/* TODO */
priv->mode = NL80211_IFTYPE_MONITOR;
}
static int agnx_get_stats(struct ieee80211_hw *dev,
struct ieee80211_low_level_stats *stats)
{
struct agnx_priv *priv = dev->priv;
AGNX_TRACE;
spin_lock(&priv->lock);
/* TODO !! */
memcpy(stats, &priv->stats, sizeof(*stats));
spin_unlock(&priv->lock);
return 0;
}
static u64 agnx_get_tsft(struct ieee80211_hw *dev)
{
void __iomem *ctl = ((struct agnx_priv *)dev->priv)->ctl;
u32 tsftl;
u64 tsft;
AGNX_TRACE;
/* FIXME */
tsftl = ioread32(ctl + AGNX_TXM_TIMESTAMPLO);
tsft = ioread32(ctl + AGNX_TXM_TIMESTAMPHI);
tsft <<= 32;
tsft |= tsftl;
return tsft;
}
static int agnx_get_tx_stats(struct ieee80211_hw *dev,
struct ieee80211_tx_queue_stats *stats)
{
struct agnx_priv *priv = dev->priv;
AGNX_TRACE;
/* FIXME now we just using txd queue, but should using txm queue too */
stats[0].len = (priv->txd.idx - priv->txd.idx_sent) / 2;
stats[0].limit = priv->txd.size - 2;
stats[0].count = priv->txd.idx / 2;
return 0;
}
static struct ieee80211_ops agnx_ops = {
.tx = agnx_tx,
.start = agnx_start,
.stop = agnx_stop,
.add_interface = agnx_add_interface,
.remove_interface = agnx_remove_interface,
.config = agnx_config,
.bss_info_changed = agnx_bss_info_changed,
.configure_filter = agnx_configure_filter,
.get_stats = agnx_get_stats,
.get_tx_stats = agnx_get_tx_stats,
.get_tsf = agnx_get_tsft
};
static void __devexit agnx_pci_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
struct agnx_priv *priv;
AGNX_TRACE;
if (!dev)
return;
priv = dev->priv;
ieee80211_unregister_hw(dev);
pci_iounmap(pdev, priv->ctl);
pci_iounmap(pdev, priv->data);
pci_release_regions(pdev);
pci_disable_device(pdev);
ieee80211_free_hw(dev);
}
static int __devinit agnx_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct ieee80211_hw *dev;
struct agnx_priv *priv;
int err;
err = pci_enable_device(pdev);
if (err) {
dev_err(&pdev->dev, "can't enable pci device\n");
return err;
}
err = pci_request_regions(pdev, "agnx-pci");
if (err) {
dev_err(&pdev->dev, "can't reserve PCI resources\n");
return err;
}
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) ||
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
dev_err(&pdev->dev, "no suitable DMA available\n");
err = -EIO;
goto err_free_reg;
}
pci_set_master(pdev);
dev = ieee80211_alloc_hw(sizeof(*priv), &agnx_ops);
if (!dev) {
dev_err(&pdev->dev, "ieee80211 alloc failed\n");
err = -ENOMEM;
goto err_free_reg;
}
priv = dev->priv;
memset(priv, 0, sizeof(*priv));
priv->mode = NL80211_IFTYPE_MONITOR;
priv->pdev = pdev;
priv->hw = dev;
spin_lock_init(&priv->lock);
priv->init_status = AGNX_UNINIT;
priv->ctl = pci_iomap(pdev, 0, 0);
/* dev_dbg(&pdev->dev, "MEM1 mapped address is 0x%p\n", priv->ctl); */
if (!priv->ctl) {
dev_err(&pdev->dev, "can't map device memory\n");
err = -ENOMEM;
goto err_free_dev;
}
priv->data = pci_iomap(pdev, 1, 0);
if (!priv->data) {
dev_err(&pdev->dev, "can't map device memory\n");
err = -ENOMEM;
goto err_iounmap2;
}
pci_read_config_byte(pdev, PCI_REVISION_ID, &priv->revid);
priv->band.channels = (struct ieee80211_channel *)agnx_channels;
priv->band.n_channels = ARRAY_SIZE(agnx_channels);
priv->band.bitrates = (struct ieee80211_rate *)agnx_rates_80211g;
priv->band.n_bitrates = ARRAY_SIZE(agnx_rates_80211g);
/* Init ieee802.11 dev */
SET_IEEE80211_DEV(dev, &pdev->dev);
pci_set_drvdata(pdev, dev);
dev->extra_tx_headroom = sizeof(struct agnx_hdr);
/* FIXME It only include FCS in promious mode but not manage mode */
/* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS; */
dev->channel_change_time = 5000;
dev->max_signal = 100;
/* FIXME */
dev->queues = 1;
agnx_get_mac_address(priv);
SET_IEEE80211_PERM_ADDR(dev, priv->mac_addr);
/* /\* FIXME *\/ */
/* for (i = 1; i < NUM_DRIVE_MODES; i++) { */
/* err = ieee80211_register_hwmode(dev, &priv->modes[i]); */
/* if (err) { */
/* printk(KERN_ERR PFX "Can't register hwmode\n"); */
/* goto err_iounmap; */
/* } */
/* } */
priv->channel = 1;
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
err = ieee80211_register_hw(dev);
if (err) {
dev_err(&pdev->dev, "can't register hardware\n");
goto err_iounmap;
}
agnx_hw_reset(priv);
dev_info(&pdev->dev, "%s: hwaddr %pM, Rev 0x%02x\n",
wiphy_name(dev->wiphy),
dev->wiphy->perm_addr, priv->revid);
return 0;
err_iounmap:
pci_iounmap(pdev, priv->data);
err_iounmap2:
pci_iounmap(pdev, priv->ctl);
err_free_dev:
pci_set_drvdata(pdev, NULL);
ieee80211_free_hw(dev);
err_free_reg:
pci_release_regions(pdev);
pci_disable_device(pdev);
return err;
} /* agnx_pci_probe*/
#ifdef CONFIG_PM
static int agnx_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
AGNX_TRACE;
ieee80211_stop_queues(dev);
agnx_stop(dev);
pci_save_state(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
}
static int agnx_pci_resume(struct pci_dev *pdev)
{
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
AGNX_TRACE;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
agnx_start(dev);
ieee80211_wake_queues(dev);
return 0;
}
#else
#define agnx_pci_suspend NULL
#define agnx_pci_resume NULL
#endif /* CONFIG_PM */
static struct pci_driver agnx_pci_driver = {
.name = "agnx-pci",
.id_table = agnx_pci_id_tbl,
.probe = agnx_pci_probe,
.remove = __devexit_p(agnx_pci_remove),
.suspend = agnx_pci_suspend,
.resume = agnx_pci_resume,
};
static int __init agnx_pci_init(void)
{
AGNX_TRACE;
return pci_register_driver(&agnx_pci_driver);
}
static void __exit agnx_pci_exit(void)
{
AGNX_TRACE;
pci_unregister_driver(&agnx_pci_driver);
}
module_init(agnx_pci_init);
module_exit(agnx_pci_exit);
此差异已折叠。
#ifndef AGNX_PHY_H_
#define AGNX_PHY_H_
#include "agnx.h"
/* Transmission Managment Registers */
#define AGNX_TXM_BASE 0x0000
#define AGNX_TXM_CTL 0x0000 /* control register */
#define AGNX_TXM_ETMF 0x0004 /* enable transmission management functions */
#define AGNX_TXM_TXTEMP 0x0008 /* transmission template */
#define AGNX_TXM_RETRYSTAID 0x000c /* Retry Station ID */
#define AGNX_TXM_TIMESTAMPLO 0x0010 /* Timestamp Lo */
#define AGNX_TXM_TIMESTAMPHI 0x0014 /* Timestamp Hi */
#define AGNX_TXM_TXDELAY 0x0018 /* tx delay */
#define AGNX_TXM_TBTTLO 0x0020 /* tbtt Lo */
#define AGNX_TXM_TBTTHI 0x0024 /* tbtt Hi */
#define AGNX_TXM_BEAINTER 0x0028 /* Beacon Interval */
#define AGNX_TXM_NAV 0x0030 /* NAV */
#define AGNX_TXM_CFPMDV 0x0034 /* CFP MDV */
#define AGNX_TXM_CFPERCNT 0x0038 /* CFP period count */
#define AGNX_TXM_PROBDELAY 0x003c /* probe delay */
#define AGNX_TXM_LISINTERCNT 0x0040 /* listen interval count */
#define AGNX_TXM_DTIMPERICNT 0x004c /* DTIM period count */
#define AGNX_TXM_BEACON_CTL 0x005c /* beacon control */
#define AGNX_TXM_SCHEMPCNT 0x007c /* schedule empty count */
#define AGNX_TXM_MAXTIMOUT 0x0084 /* max timeout exceed count */
#define AGNX_TXM_MAXCFPTIM 0x0088 /* max CF poll timeout count */
#define AGNX_TXM_MAXRXTIME 0x008c /* max RX timeout count */
#define AGNX_TXM_MAXACKTIM 0x0090 /* max ACK timeout count */
#define AGNX_TXM_DIF01 0x00a0 /* DIF 0-1 */
#define AGNX_TXM_DIF23 0x00a4 /* DIF 2-3 */
#define AGNX_TXM_DIF45 0x00a8 /* DIF 4-5 */
#define AGNX_TXM_DIF67 0x00ac /* DIF 6-7 */
#define AGNX_TXM_SIFSPIFS 0x00b0 /* SIFS/PIFS */
#define AGNX_TXM_TIFSEIFS 0x00b4 /* TIFS/EIFS */
#define AGNX_TXM_MAXCCACNTSLOT 0x00b8 /* max CCA count slot */
#define AGNX_TXM_SLOTLIMIT 0x00bc /* slot limit/1 msec limit */
#define AGNX_TXM_CFPOLLRXTIM 0x00f0 /* CF poll RX timeout count */
#define AGNX_TXM_CFACKT11B 0x00f4 /* CF ack timeout limit for 11b */
#define AGNX_TXM_CW0 0x0100 /* CW 0 */
#define AGNX_TXM_SLBEALIM0 0x0108 /* short/long beacon limit 0 */
#define AGNX_TXM_CW1 0x0120 /* CW 1 */
#define AGNX_TXM_SLBEALIM1 0x0128 /* short/long beacon limit 1 */
#define AGNX_TXM_CW2 0x0140 /* CW 2 */
#define AGNX_TXM_SLBEALIM2 0x0148 /* short/long beacon limit 2 */
#define AGNX_TXM_CW3 0x0160 /* CW 3 */
#define AGNX_TXM_SLBEALIM3 0x0168 /* short/long beacon limit 3 */
#define AGNX_TXM_CW4 0x0180 /* CW 4 */
#define AGNX_TXM_SLBEALIM4 0x0188 /* short/long beacon limit 4 */
#define AGNX_TXM_CW5 0x01a0 /* CW 5 */
#define AGNX_TXM_SLBEALIM5 0x01a8 /* short/long beacon limit 5 */
#define AGNX_TXM_CW6 0x01c0 /* CW 6 */
#define AGNX_TXM_SLBEALIM6 0x01c8 /* short/long beacon limit 6 */
#define AGNX_TXM_CW7 0x01e0 /* CW 7 */
#define AGNX_TXM_SLBEALIM7 0x01e8 /* short/long beacon limit 7 */
#define AGNX_TXM_BEACONTEMP 0x1000 /* beacon template */
#define AGNX_TXM_STAPOWTEMP 0x1a00 /* Station Power Template */
/* Receive Management Control Registers */
#define AGNX_RXM_BASE 0x2000
#define AGNX_RXM_REQRATE 0x2000 /* requested rate */
#define AGNX_RXM_MACHI 0x2004 /* first 4 bytes of mac address */
#define AGNX_RXM_MACLO 0x2008 /* last 2 bytes of mac address */
#define AGNX_RXM_BSSIDHI 0x200c /* bssid hi */
#define AGNX_RXM_BSSIDLO 0x2010 /* bssid lo */
#define AGNX_RXM_HASH_CMD_FLAG 0x2014 /* Flags for the RX Hash Command Default:0 */
#define AGNX_RXM_HASH_CMD_HIGH 0x2018 /* The High half of the Hash Command */
#define AGNX_RXM_HASH_CMD_LOW 0x201c /* The Low half of the Hash Command */
#define AGNX_RXM_ROUTAB 0x2020 /* routing table */
#define ROUTAB_SUBTYPE_SHIFT 24
#define ROUTAB_TYPE_SHIFT 28
#define ROUTAB_STATUS_SHIFT 30
#define ROUTAB_RW_SHIFT 31
#define ROUTAB_ROUTE_DROP 0xf00000 /* Drop */
#define ROUTAB_ROUTE_CPU 0x400000 /* CPU */
#define ROUTAB_ROUTE_ENCRY 0x500800 /* Encryption */
#define ROUTAB_ROUTE_RFP 0x800000 /* RFP */
#define ROUTAB_TYPE_MANAG 0x0 /* Management */
#define ROUTAB_TYPE_CTL 0x1 /* Control */
#define ROUTAB_TYPE_DATA 0x2 /* Data */
#define ROUTAB_SUBTYPE_DATA 0x0
#define ROUTAB_SUBTYPE_DATAACK 0x1
#define ROUTAB_SUBTYPE_DATAPOLL 0x2
#define ROUTAB_SUBTYPE_DATAPOLLACK 0x3
#define ROUTAB_SUBTYPE_NULL 0x4 /* NULL */
#define ROUTAB_SUBTYPE_NULLACK 0x5
#define ROUTAB_SUBTYPE_NULLPOLL 0x6
#define ROUTAB_SUBTYPE_NULLPOLLACK 0x7
#define ROUTAB_SUBTYPE_QOSDATA 0x8 /* QOS DATA */
#define ROUTAB_SUBTYPE_QOSDATAACK 0x9
#define ROUTAB_SUBTYPE_QOSDATAPOLL 0xa
#define ROUTAB_SUBTYPE_QOSDATAACKPOLL 0xb
#define ROUTAB_SUBTYPE_QOSNULL 0xc
#define ROUTAB_SUBTYPE_QOSNULLACK 0xd
#define ROUTAB_SUBTYPE_QOSNULLPOLL 0xe
#define ROUTAB_SUBTYPE_QOSNULLPOLLACK 0xf
#define AGNX_RXM_DELAY11 0x2024 /* delay 11(AB) */
#define AGNX_RXM_SOF_CNT 0x2028 /* SOF Count */
#define AGNX_RXM_FRAG_CNT 0x202c /* Fragment Count*/
#define AGNX_RXM_FCS_CNT 0x2030 /* FCS Count */
#define AGNX_RXM_BSSID_MISS_CNT 0x2034 /* BSSID Miss Count */
#define AGNX_RXM_PDU_ERR_CNT 0x2038 /* PDU Error Count */
#define AGNX_RXM_DEST_MISS_CNT 0x203C /* Destination Miss Count */
#define AGNX_RXM_DROP_CNT 0x2040 /* Drop Count */
#define AGNX_RXM_ABORT_CNT 0x2044 /* Abort Count */
#define AGNX_RXM_RELAY_CNT 0x2048 /* Relay Count */
#define AGNX_RXM_HASH_MISS_CNT 0x204c /* Hash Miss Count */
#define AGNX_RXM_SA_HI 0x2050 /* Address of received packet Hi */
#define AGNX_RXM_SA_LO 0x2054 /* Address of received packet Lo */
#define AGNX_RXM_HASH_DUMP_LST 0x2100 /* Contains Hash Data */
#define AGNX_RXM_HASH_DUMP_MST 0x2104 /* Contains Hash Data */
#define AGNX_RXM_HASH_DUMP_DATA 0x2108 /* The Station ID to dump */
/* Encryption Managment */
#define AGNX_ENCRY_BASE 0x2400
#define AGNX_ENCRY_WEPKEY0 0x2440 /* wep key #0 */
#define AGNX_ENCRY_WEPKEY1 0x2444 /* wep key #1 */
#define AGNX_ENCRY_WEPKEY2 0x2448 /* wep key #2 */
#define AGNX_ENCRY_WEPKEY3 0x244c /* wep key #3 */
#define AGNX_ENCRY_CCMRECTL 0x2460 /* ccm replay control */
/* Band Management Registers */
#define AGNX_BM_BASE 0x2c00
#define AGNX_BM_BMCTL 0x2c00 /* band management control */
#define AGNX_BM_TXWADDR 0x2c18 /* tx workqueue address start */
#define AGNX_BM_TXTOPEER 0x2c24 /* transmit to peers */
#define AGNX_BM_FPLHP 0x2c2c /* free pool list head pointer */
#define AGNX_BM_FPLTP 0x2c30 /* free pool list tail pointer */
#define AGNX_BM_FPCNT 0x2c34 /* free pool count */
#define AGNX_BM_CIPDUWCNT 0x2c38 /* card interface pdu workqueue count */
#define AGNX_BM_SPPDUWCNT 0x2c3c /* sp pdu workqueue count */
#define AGNX_BM_RFPPDUWCNT 0x2c40 /* rfp pdu workqueue count */
#define AGNX_BM_RHPPDUWCNT 0x2c44 /* rhp pdu workqueue count */
#define AGNX_BM_CIWQCTL 0x2c48 /* Card Interface WorkQueue Control */
#define AGNX_BM_CPUTXWCTL 0x2c50 /* cpu tx workqueue control */
#define AGNX_BM_CPURXWCTL 0x2c58 /* cpu rx workqueue control */
#define AGNX_BM_CPULWCTL 0x2c60 /* cpu low workqueue control */
#define AGNX_BM_CPUHWCTL 0x2c68 /* cpu high workqueue control */
#define AGNX_BM_SPTXWCTL 0x2c70 /* sp tx workqueue control */
#define AGNX_BM_SPRXWCTL 0x2c78 /* sp rx workqueue control */
#define AGNX_BM_RFPWCTL 0x2c80 /* RFP workqueue control */
#define AGNX_BM_MTSM 0x2c90 /* Multicast Transmit Station Mask */
/* Card Interface Registers (32bits) */
#define AGNX_CIR_BASE 0x3000
#define AGNX_CIR_BLKCTL 0x3000 /* block control*/
#define AGNX_STAT_TX 0x1
#define AGNX_STAT_RX 0x2
#define AGNX_STAT_X 0x4
/* Below two interrupt flags will be set by our but not CPU or the card */
#define AGNX_STAT_TXD 0x10
#define AGNX_STAT_TXM 0x20
#define AGNX_CIR_ADDRWIN 0x3004 /* Addressable Windows*/
#define AGNX_CIR_ENDIAN 0x3008 /* card endianness */
#define AGNX_CIR_SERIALITF 0x3020 /* serial interface */
#define AGNX_CIR_RXCFG 0x3040 /* receive config */
#define ENABLE_RX_INTERRUPT 0x20
#define RX_CACHE_LINE 0x8
/* the RX fragment length */
#define FRAG_LEN_256 0x0 /* 256B */
#define FRAG_LEN_512 0x1
#define FRAG_LEN_1024 0x2
#define FRAG_LEN_2048 0x3
#define FRAG_BE 0x10
#define AGNX_CIR_RXCTL 0x3050 /* receive control */
/* memory address, chipside */
#define AGNX_CIR_RXCMSTART 0x3054 /* receive client memory start */
#define AGNX_CIR_RXCMEND 0x3058 /* receive client memory end */
/* memory address, pci */
#define AGNX_CIR_RXHOSTADDR 0x3060 /* receive hostside address */
/* memory address, chipside */
#define AGNX_CIR_RXCLIADDR 0x3064 /* receive clientside address */
#define AGNX_CIR_RXDMACTL 0x3068 /* receive dma control */
#define AGNX_CIR_TXCFG 0x3080 /* transmit config */
#define AGNX_CIR_TXMCTL 0x3090 /* Transmit Management Control */
#define ENABLE_TX_INTERRUPT 0x20
#define TX_CACHE_LINE 0x8
#define AGNX_CIR_TXMSTART 0x3094 /* Transmit Management Start */
#define AGNX_CIR_TXMEND 0x3098 /* Transmit Management End */
#define AGNX_CIR_TXDCTL 0x30a0 /* transmit data control */
/* memeory address, chipset */
#define AGNX_CIR_TXDSTART 0x30a4 /* transmit data start */
#define AGNX_CIR_TXDEND 0x30a8 /* transmit data end */
#define AGNX_CIR_TXMHADDR 0x30b0 /* Transmit Management Hostside Address */
#define AGNX_CIR_TXMCADDR 0x30b4 /* Transmit Management Clientside Address */
#define AGNX_CIR_TXDMACTL 0x30b8 /* transmit dma control */
/* Power Managment Unit */
#define AGNX_PM_BASE 0x3c00
#define AGNX_PM_PMCTL 0x3c00 /* PM Control*/
#define AGNX_PM_MACMSW 0x3c08 /* MAC Manual Slow Work Enable */
#define AGNX_PM_RFCTL 0x3c0c /* RF Control */
#define AGNX_PM_PHYMW 0x3c14 /* Phy Mannal Work */
#define AGNX_PM_SOFTRST 0x3c18 /* PMU Soft Reset */
#define AGNX_PM_PLLCTL 0x3c1c /* PMU PLL control*/
#define AGNX_PM_TESTPHY 0x3c24 /* PMU Test Phy */
/* Interrupt Control interface */
#define AGNX_INT_BASE 0x4000
#define AGNX_INT_STAT 0x4000 /* interrupt status */
#define AGNX_INT_MASK 0x400c /* interrupt mask */
/* FIXME */
#define IRQ_TX_BEACON 0x1 /* TX Beacon */
#define IRQ_TX_RETRY 0x8 /* TX Retry Interrupt */
#define IRQ_TX_ACTIVITY 0x10 /* TX Activity */
#define IRQ_RX_ACTIVITY 0x20 /* RX Activity */
/* FIXME I guess that instead RX a none exist staion's packet or
the station hasn't been init */
#define IRQ_RX_X 0x40
#define IRQ_RX_Y 0x80 /* RX ? */
#define IRQ_RX_HASHHIT 0x100 /* RX Hash Hit */
#define IRQ_RX_FRAME 0x200 /* RX Frame */
#define IRQ_ERR_INT 0x400 /* Error Interrupt */
#define IRQ_TX_QUE_FULL 0x800 /* TX Workqueue Full */
#define IRQ_BANDMAN_ERR 0x10000 /* Bandwidth Management Error */
#define IRQ_TX_DISABLE 0x20000 /* TX Disable */
#define IRQ_RX_IVASESKEY 0x80000 /* RX Invalid Session Key */
#define IRQ_RX_KEYIDMIS 0x100000 /* RX key ID Mismatch */
#define IRQ_REP_THHIT 0x200000 /* Replay Threshold Hit */
#define IRQ_TIMER1 0x4000000 /* Timer1 */
#define IRQ_TIMER_CNT 0x10000000 /* Timer Count */
#define IRQ_PHY_FASTINT 0x20000000 /* Phy Fast Interrupt */
#define IRQ_PHY_SLOWINT 0x40000000 /* Phy Slow Interrupt */
#define IRQ_OTHER 0x80000000 /* Unknow interrupt */
#define AGNX_IRQ_ALL 0xffffffff
/* System Interface */
#define AGNX_SYSITF_BASE 0x4400
#define AGNX_SYSITF_SYSMODE 0x4400 /* system mode */
#define AGNX_SYSITF_GPIOIN 0x4410 /* GPIO In */
/* PIN lines for leds? */
#define AGNX_SYSITF_GPIOUT 0x4414 /* GPIO Out */
/* Timer Control */
#define AGNX_TIMCTL_TIMER1 0x4800 /* Timer 1 */
#define AGNX_TIMCTL_TIM1CTL 0x4808 /* Timer 1 Control */
/* Antenna Calibration Interface */
#define AGNX_ACI_BASE 0x5000
#define AGNX_ACI_MODE 0x5000 /* Mode */
#define AGNX_ACI_MEASURE 0x5004 /* Measure */
#define AGNX_ACI_SELCHAIN 0x5008 /* Select Chain */
#define AGNX_ACI_LEN 0x500c /* Length */
#define AGNX_ACI_TIMER1 0x5018 /* Timer 1 */
#define AGNX_ACI_TIMER2 0x501c /* Timer 2 */
#define AGNX_ACI_OFFSET 0x5020 /* Offset */
#define AGNX_ACI_STATUS 0x5030 /* Status */
#define CALI_IDLE 0x0
#define CALI_DONE 0x1
#define CALI_BUSY 0x2
#define CALI_ERR 0x3
#define AGNX_ACI_AICCHA0OVE 0x5034 /* AIC Channel 0 Override */
#define AGNX_ACI_AICCHA1OVE 0x5038 /* AIC Channel 1 Override */
/* Gain Control Registers */
#define AGNX_GCR_BASE 0x9000
/* threshold of primary antenna */
#define AGNX_GCR_THD0A 0x9000 /* threshold? D0 A */
/* low threshold of primary antenna */
#define AGNX_GCR_THD0AL 0x9004 /* threshold? D0 A low */
/* threshold of secondary antenna */
#define AGNX_GCR_THD0B 0x9008 /* threshold? D0_B */
#define AGNX_GCR_DUNSAT 0x900c /* d unsaturated */
#define AGNX_GCR_DSAT 0x9010 /* d saturated */
#define AGNX_GCR_DFIRCAL 0x9014 /* D Fir/Cal */
#define AGNX_GCR_DGCTL11A 0x9018 /* d gain control 11a */
#define AGNX_GCR_DGCTL11B 0x901c /* d gain control 11b */
/* strength of gain */
#define AGNX_GCR_GAININIT 0x9020 /* gain initialization */
#define AGNX_GCR_THNOSIG 0x9024 /* threhold no signal */
#define AGNX_GCR_COARSTEP 0x9028 /* coarse stepping */
#define AGNX_GCR_SIFST11A 0x902c /* sifx time 11a */
#define AGNX_GCR_SIFST11B 0x9030 /* sifx time 11b */
#define AGNX_GCR_CWDETEC 0x9034 /* cw detection */
#define AGNX_GCR_0X38 0x9038 /* ???? */
#define AGNX_GCR_BOACT 0x903c /* BO Active */
#define AGNX_GCR_BOINACT 0x9040 /* BO Inactive */
#define AGNX_GCR_BODYNA 0x9044 /* BO dynamic */
/* 802.11 mode(a,b,g) */
#define AGNX_GCR_DISCOVMOD 0x9048 /* discovery mode */
#define AGNX_GCR_NLISTANT 0x904c /* number of listening antenna */
#define AGNX_GCR_NACTIANT 0x9050 /* number of active antenna */
#define AGNX_GCR_NMEASANT 0x9054 /* number of measuring antenna */
#define AGNX_GCR_NCAPTANT 0x9058 /* number of capture antenna */
#define AGNX_GCR_THCAP11A 0x905c /* threshold capture 11a */
#define AGNX_GCR_THCAP11B 0x9060 /* threshold capture 11b */
#define AGNX_GCR_THCAPRX11A 0x9064 /* threshold capture rx 11a */
#define AGNX_GCR_THCAPRX11B 0x9068 /* threshold capture rx 11b */
#define AGNX_GCR_THLEVDRO 0x906c /* threshold level drop */
#define AGNX_GCR_GAINSET0 0x9070 /* Gainset 0 */
#define AGNX_GCR_GAINSET1 0x9074 /* Gainset 1 */
#define AGNX_GCR_GAINSET2 0x9078 /* Gainset 2 */
#define AGNX_GCR_MAXRXTIME11A 0x907c /* maximum rx time 11a */
#define AGNX_GCR_MAXRXTIME11B 0x9080 /* maximum rx time 11b */
#define AGNX_GCR_CORRTIME 0x9084 /* correction time */
/* reset the subsystem, 0 = disable, 1 = enable */
#define AGNX_GCR_RSTGCTL 0x9088 /* reset gain control */
/* channel receiving */
#define AGNX_GCR_RXCHANEL 0x908c /* receive channel */
#define AGNX_GCR_NOISE0 0x9090 /* Noise 0 */
#define AGNX_GCR_NOISE1 0x9094 /* Noise 1 */
#define AGNX_GCR_NOISE2 0x9098 /* Noise 2 */
#define AGNX_GCR_SIGHTH 0x909c /* Signal High Threshold */
#define AGNX_GCR_SIGLTH 0x90a0 /* Signal Low Threshold */
#define AGNX_GCR_CORRDROP 0x90a4 /* correction drop */
/* threshold of tertiay antenna */
#define AGNX_GCR_THCD 0x90a8 /* threshold? CD */
#define AGNX_GCR_THCS 0x90ac /* threshold? CS */
#define AGNX_GCR_MAXPOWDIFF 0x90b8 /* maximum power difference */
#define AGNX_GCR_TRACNT4 0x90ec /* Transition Count 4 */
#define AGNX_GCR_TRACNT5 0x90f0 /* transition count 5 */
#define AGNX_GCR_TRACNT6 0x90f4 /* transition count 6 */
#define AGNX_GCR_TRACNT7 0x90f8 /* transition coutn 7 */
#define AGNX_GCR_TESTBUS 0x911c /* test bus */
#define AGNX_GCR_CHAINNUM 0x9120 /* Number of Chains */
#define AGNX_GCR_ANTCFG 0x9124 /* Antenna Config */
#define AGNX_GCR_THJUMP 0x912c /* threhold jump */
#define AGNX_GCR_THPOWER 0x9130 /* threshold power */
#define AGNX_GCR_THPOWCLIP 0x9134 /* threshold power clip*/
#define AGNX_GCR_FORCECTLCLK 0x9138 /* Force Gain Control Clock */
#define AGNX_GCR_GAINSETWRITE 0x913c /* Gainset Write */
#define AGNX_GCR_THD0BTFEST 0x9140 /* threshold d0 b tf estimate */
#define AGNX_GCR_THRX11BPOWMIN 0x9144 /* threshold rx 11b power minimum */
#define AGNX_GCR_0X14c 0x914c /* ?? */
#define AGNX_GCR_0X150 0x9150 /* ?? */
#define AGNX_GCR_RXOVERIDE 0x9194 /* recieve override */
#define AGNX_GCR_WATCHDOG 0x91b0 /* watchdog timeout */
/* Spi Interface */
#define AGNX_SPI_BASE 0xdc00
#define AGNX_SPI_CFG 0xdc00 /* spi configuration */
/* Only accept 16 bits */
#define AGNX_SPI_WMSW 0xdc04 /* write most significant word */
/* Only accept 16 bits */
#define AGNX_SPI_WLSW 0xdc08 /* write least significant word */
#define AGNX_SPI_CTL 0xdc0c /* spi control */
#define AGNX_SPI_RMSW 0xdc10 /* read most significant word */
#define AGNX_SPI_RLSW 0xdc14 /* read least significant word */
/* SPI Control Mask */
#define SPI_READ_CTL 0x4000 /* read control */
#define SPI_BUSY_CTL 0x8000 /* busy control */
/* RF and synth chips in spi */
#define RF_CHIP0 0x400
#define RF_CHIP1 0x800
#define RF_CHIP2 0x1000
#define SYNTH_CHIP 0x2000
/* Unknown register */
#define AGNX_UNKNOWN_BASE 0x7800
/* FIXME MonitorGain */
#define AGNX_MONGCR_BASE 0x12000
/* Gain Table */
#define AGNX_GAIN_TABLE 0x12400
/* The initial FIR coefficient table */
#define AGNX_FIR_BASE 0x19804
#define AGNX_ENGINE_LOOKUP_TBL 0x800
/* eeprom commands */
#define EEPROM_CMD_NULL 0x0 /* NULL */
#define EEPROM_CMD_WRITE 0x2 /* write */
#define EEPROM_CMD_READ 0x3 /* read */
#define EEPROM_CMD_STATUSREAD 0x5 /* status register read */
#define EEPROM_CMD_WRITEENABLE 0x6 /* write enable */
#define EEPROM_CMD_CONFIGURE 0x7 /* configure */
#define EEPROM_DATAFORCOFIGURE 0x6 /* ??? */
/* eeprom address */
#define EEPROM_ADDR_SUBVID 0x0 /* Sub Vendor ID */
#define EEPROM_ADDR_SUBSID 0x2 /* Sub System ID */
#define EEPROM_ADDR_MACADDR 0x146 /* MAC Address */
#define EEPROM_ADDR_LOTYPE 0x14f /* LO type */
struct agnx_eeprom {
u8 data; /* date */
u16 address; /* address in EEPROM */
u8 cmd; /* command, unknown, status */
} __attribute__((__packed__));
#define AGNX_EEPROM_COMMAND_SHIFT 5
#define AGNX_EEPROM_COMMAND_STAT 0x01
void disable_receiver(struct agnx_priv *priv);
void enable_receiver(struct agnx_priv *priv);
u8 read_from_eeprom(struct agnx_priv *priv, u16 address);
void agnx_hw_init(struct agnx_priv *priv);
int agnx_hw_reset(struct agnx_priv *priv);
int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len);
void agnx_set_bssid(struct agnx_priv *priv, const u8 *bssid);
void enable_power_saving(struct agnx_priv *priv);
void disable_power_saving(struct agnx_priv *priv);
void calibrate_antenna_period(unsigned long data);
#endif /* AGNX_PHY_H_ */
此差异已折叠。
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include "phy.h"
#include "sta.h"
#include "debug.h"
void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
{
void __iomem *ctl = priv->ctl;
reglo &= 0xFFFF;
reglo |= 0x30000000;
reglo |= 0x40000000; /* Set status busy */
reglo |= sta_id << 16;
iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
}
void hash_write(struct agnx_priv *priv, const u8 *mac_addr, u8 sta_id)
{
void __iomem *ctl = priv->ctl;
u32 reghi, reglo;
if (!is_valid_ether_addr(mac_addr))
printk(KERN_WARNING PFX "Update hash table: Invalid hwaddr!\n");
reghi = mac_addr[0] << 24 | mac_addr[1] << 16 | mac_addr[2] << 8 | mac_addr[3];
reglo = mac_addr[4] << 8 | mac_addr[5];
reglo |= 0x10000000; /* Set hash commmand */
reglo |= 0x40000000; /* Set status busy */
reglo |= sta_id << 16;
iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
if (!(reglo & 0x80000000))
printk(KERN_WARNING PFX "Update hash table failed\n");
}
void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
{
void __iomem *ctl = priv->ctl;
reglo &= 0xFFFF;
reglo |= 0x20000000;
reglo |= 0x40000000; /* Set status busy */
reglo |= sta_id << 16;
iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
}
void hash_dump(struct agnx_priv *priv, u8 sta_id)
{
void __iomem *ctl = priv->ctl;
u32 reghi, reglo;
reglo = 0x40000000; /* status bit */
iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
iowrite32(sta_id << 16, ctl + AGNX_RXM_HASH_DUMP_DATA);
udelay(80);
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
printk(PFX "hash cmd are : %.8x%.8x\n", reghi, reglo);
reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_FLAG);
printk(PFX "hash flag is : %.8x\n", reghi);
reghi = ioread32(ctl + AGNX_RXM_HASH_DUMP_MST);
reglo = ioread32(ctl + AGNX_RXM_HASH_DUMP_LST);
printk(PFX "hash dump mst lst: %.8x%.8x\n", reghi, reglo);
reghi = ioread32(ctl + AGNX_RXM_HASH_DUMP_DATA);
printk(PFX "hash dump data: %.8x\n", reghi);
}
void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
{
void __iomem *ctl = priv->ctl;
memcpy_fromio(power, ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
sizeof(*power));
}
inline void
set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
{
void __iomem *ctl = priv->ctl;
/* FIXME 2. Write Template to offset + station number */
memcpy_toio(ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
power, sizeof(*power));
}
void get_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
unsigned int sta_idx, unsigned int wq_idx)
{
void __iomem *data = priv->data;
memcpy_fromio(tx_wq, data + AGNX_PDU_TX_WQ + sizeof(*tx_wq) * STA_TX_WQ_NUM * sta_idx +
sizeof(*tx_wq) * wq_idx, sizeof(*tx_wq));
}
inline void set_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
unsigned int sta_idx, unsigned int wq_idx)
{
void __iomem *data = priv->data;
memcpy_toio(data + AGNX_PDU_TX_WQ + sizeof(*tx_wq) * STA_TX_WQ_NUM * sta_idx +
sizeof(*tx_wq) * wq_idx, tx_wq, sizeof(*tx_wq));
}
void get_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx)
{
void __iomem *data = priv->data;
memcpy_fromio(sta, data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
sizeof(*sta));
}
inline void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx)
{
void __iomem *data = priv->data;
memcpy_toio(data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
sta, sizeof(*sta));
}
/* FIXME */
void sta_power_init(struct agnx_priv *priv, unsigned int sta_idx)
{
struct agnx_sta_power power;
u32 reg;
AGNX_TRACE;
memset(&power, 0, sizeof(power));
reg = agnx_set_bits(EDCF, EDCF_SHIFT, 0x1);
power.reg = cpu_to_le32(reg);
set_sta_power(priv, &power, sta_idx);
udelay(40);
} /* add_power_template */
/* @num: The #number of station that is visible to the card */
static void sta_tx_workqueue_init(struct agnx_priv *priv, unsigned int sta_idx)
{
struct agnx_sta_tx_wq tx_wq;
u32 reg;
unsigned int i;
memset(&tx_wq, 0, sizeof(tx_wq));
reg = agnx_set_bits(WORK_QUEUE_VALID, WORK_QUEUE_VALID_SHIFT, 1);
reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 1);
/* reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 0); */
tx_wq.reg2 |= cpu_to_le32(reg);
/* Suppose all 8 traffic class are used */
for (i = 0; i < STA_TX_WQ_NUM; i++)
set_sta_tx_wq(priv, &tx_wq, sta_idx, i);
} /* sta_tx_workqueue_init */
static void sta_traffic_init(struct agnx_sta_traffic *traffic)
{
u32 reg;
memset(traffic, 0, sizeof(*traffic));
reg = agnx_set_bits(NEW_PACKET, NEW_PACKET_SHIFT, 1);
reg |= agnx_set_bits(TRAFFIC_VALID, TRAFFIC_VALID_SHIFT, 1);
/* reg |= agnx_set_bits(TRAFFIC_ACK_TYPE, TRAFFIC_ACK_TYPE_SHIFT, 1); */
traffic->reg0 = cpu_to_le32(reg);
/* 3. setting RX Sequence Number to 4095 */
reg = agnx_set_bits(RX_SEQUENCE_NUM, RX_SEQUENCE_NUM_SHIFT, 4095);
traffic->reg1 = cpu_to_le32(reg);
}
/* @num: The #number of station that is visible to the card */
void sta_init(struct agnx_priv *priv, unsigned int sta_idx)
{
/* FIXME the length of sta is 256 bytes Is that
* dangerous to stack overflow? */
struct agnx_sta sta;
u32 reg;
int i;
memset(&sta, 0, sizeof(sta));
/* Set valid to 1 */
reg = agnx_set_bits(STATION_VALID, STATION_VALID_SHIFT, 1);
/* Set Enable Concatenation to 0 (?) */
reg |= agnx_set_bits(ENABLE_CONCATENATION, ENABLE_CONCATENATION_SHIFT, 0);
/* Set Enable Decompression to 0 (?) */
reg |= agnx_set_bits(ENABLE_DECOMPRESSION, ENABLE_DECOMPRESSION_SHIFT, 0);
sta.reg = cpu_to_le32(reg);
/* Initialize each of the Traffic Class Structures by: */
for (i = 0; i < 8; i++)
sta_traffic_init(sta.traffic + i);
set_sta(priv, &sta, sta_idx);
sta_tx_workqueue_init(priv, sta_idx);
} /* sta_descriptor_init */
#ifndef AGNX_STA_H_
#define AGNX_STA_H_
#define STA_TX_WQ_NUM 8 /* The number of TX workqueue one STA has */
struct agnx_hash_cmd {
__be32 cmdhi;
#define MACLO 0xFFFF0000
#define MACLO_SHIFT 16
#define STA_ID 0x0000FFF0
#define STA_ID_SHIFT 4
#define CMD 0x0000000C
#define CMD_SHIFT 2
#define STATUS 0x00000002
#define STATUS_SHIFT 1
#define PASS 0x00000001
#define PASS_SHIFT 1
__be32 cmdlo;
} __attribute__((__packed__));
/*
* Station Power Template
* FIXME Just for agn100 yet
*/
struct agnx_sta_power {
__le32 reg;
#define SIGNAL 0x000000FF /* signal */
#define SIGNAL_SHIFT 0
#define RATE 0x00000F00
#define RATE_SHIFT 8
#define TIFS 0x00001000
#define TIFS_SHIFT 12
#define EDCF 0x00002000
#define EDCF_SHIFT 13
#define CHANNEL_BOND 0x00004000
#define CHANNEL_BOND_SHIFT 14
#define PHY_MODE 0x00038000
#define PHY_MODE_SHIFT 15
#define POWER_LEVEL 0x007C0000
#define POWER_LEVEL_SHIFT 18
#define NUM_TRANSMITTERS 0x00800000
#define NUM_TRANSMITTERS_SHIFT 23
} __attribute__((__packed__));
/*
* TX Workqueue Descriptor
*/
struct agnx_sta_tx_wq {
__le32 reg0;
#define HEAD_POINTER_LOW 0xFF000000 /* Head pointer low */
#define HEAD_POINTER_LOW_SHIFT 24
#define TAIL_POINTER 0x00FFFFFF /* Tail pointer */
#define TAIL_POINTER_SHIFT 0
__le32 reg3;
#define ACK_POINTER_LOW 0xFFFF0000 /* ACK pointer low */
#define ACK_POINTER_LOW_SHIFT 16
#define HEAD_POINTER_HIGH 0x0000FFFF /* Head pointer high */
#define HEAD_POINTER_HIGH_SHIFT 0
__le32 reg1;
/* ACK timeout tail packet count */
#define ACK_TIMOUT_TAIL_PACK_CNT 0xFFF00000
#define ACK_TIMOUT_TAIL_PACK_CNT_SHIFT 20
/* Head timeout tail packet count */
#define HEAD_TIMOUT_TAIL_PACK_CNT 0x000FFF00
#define HEAD_TIMOUT_TAIL_PACK_CNT_SHIFT 8
#define ACK_POINTER_HIGH 0x000000FF /* ACK pointer high */
#define ACK_POINTER_HIGH_SHIFT 0
__le32 reg2;
#define WORK_QUEUE_VALID 0x80000000 /* valid */
#define WORK_QUEUE_VALID_SHIFT 31
#define WORK_QUEUE_ACK_TYPE 0x40000000 /* ACK type */
#define WORK_QUEUE_ACK_TYPE_SHIFT 30
/* Head timeout window limit fragmentation count */
#define HEAD_TIMOUT_WIN_LIM_FRAG_CNT 0x3FFF0000
#define HEAD_TIMOUT_WIN_LIM_FRAG_CNT_SHIFT 16
/* Head timeout window limit byte count */
#define HEAD_TIMOUT_WIN_LIM_BYTE_CNT 0x0000FFFF
#define HEAD_TIMOUT_WIN_LIM_BYTE_CNT_SHIFT 0
} __attribute__((__packed__));
/*
* Traffic Class Structure
*/
struct agnx_sta_traffic {
__le32 reg0;
#define ACK_TIMOUT_CNT 0xFF800000 /* ACK Timeout Counts */
#define ACK_TIMOUT_CNT_SHIFT 23
#define TRAFFIC_ACK_TYPE 0x00600000 /* ACK Type */
#define TRAFFIC_ACK_TYPE_SHIFT 21
#define NEW_PACKET 0x00100000 /* New Packet */
#define NEW_PACKET_SHIFT 20
#define TRAFFIC_VALID 0x00080000 /* Valid */
#define TRAFFIC_VALID_SHIFT 19
#define RX_HDR_DESC_POINTER 0x0007FFFF /* RX Header Descripter pointer */
#define RX_HDR_DESC_POINTER_SHIFT 0
__le32 reg1;
#define RX_PACKET_TIMESTAMP 0xFFFF0000 /* RX Packet Timestamp */
#define RX_PACKET_TIMESTAMP_SHIFT 16
#define TRAFFIC_RESERVED 0x0000E000 /* Reserved */
#define TRAFFIC_RESERVED_SHIFT 13
#define SV 0x00001000 /* sv */
#define SV_SHIFT 12
#define RX_SEQUENCE_NUM 0x00000FFF /* RX Sequence Number */
#define RX_SEQUENCE_NUM_SHIFT 0
__le32 tx_replay_cnt_low; /* TX Replay Counter Low */
__le16 tx_replay_cnt_high; /* TX Replay Counter High */
__le16 rx_replay_cnt_high; /* RX Replay Counter High */
__be32 rx_replay_cnt_low; /* RX Replay Counter Low */
} __attribute__((__packed__));
/*
* Station Descriptors
*/
struct agnx_sta {
__le32 tx_session_keys[4]; /* Transmit Session Key (0-3) */
__le32 rx_session_keys[4]; /* Receive Session Key (0-3) */
__le32 reg;
#define ID_1 0xC0000000 /* id 1 */
#define ID_1_SHIFT 30
#define ID_0 0x30000000 /* id 0 */
#define ID_0_SHIFT 28
#define ENABLE_CONCATENATION 0x0FF00000 /* Enable concatenation */
#define ENABLE_CONCATENATION_SHIFT 20
#define ENABLE_DECOMPRESSION 0x000FF000 /* Enable decompression */
#define ENABLE_DECOMPRESSION_SHIFT 12
#define STA_RESERVED 0x00000C00 /* Reserved */
#define STA_RESERVED_SHIFT 10
#define EAP 0x00000200 /* EAP */
#define EAP_SHIFT 9
#define ED_NULL 0x00000100 /* ED NULL */
#define ED_NULL_SHIFT 8
#define ENCRYPTION_POLICY 0x000000E0 /* Encryption Policy */
#define ENCRYPTION_POLICY_SHIFT 5
#define DEFINED_KEY_ID 0x00000018 /* Defined Key ID */
#define DEFINED_KEY_ID_SHIFT 3
#define FIXED_KEY 0x00000004 /* Fixed Key */
#define FIXED_KEY_SHIFT 2
#define KEY_VALID 0x00000002 /* Key Valid */
#define KEY_VALID_SHIFT 1
#define STATION_VALID 0x00000001 /* Station Valid */
#define STATION_VALID_SHIFT 0
__le32 tx_aes_blks_unicast; /* TX AES Blks Unicast */
__le32 rx_aes_blks_unicast; /* RX AES Blks Unicast */
__le16 aes_format_err_unicast_cnt; /* AES Format Error Unicast Counts */
__le16 aes_replay_unicast; /* AES Replay Unicast */
__le16 aes_decrypt_err_unicast; /* AES Decrypt Error Unicast */
__le16 aes_decrypt_err_default; /* AES Decrypt Error default */
__le16 single_retry_packets; /* Single Retry Packets */
__le16 failed_tx_packets; /* Failed Tx Packets */
__le16 muti_retry_packets; /* Multiple Retry Packets */
__le16 ack_timeouts; /* ACK Timeouts */
__le16 frag_tx_cnt; /* Fragment TX Counts */
__le16 rts_brq_sent; /* RTS Brq Sent */
__le16 tx_packets; /* TX Packets */
__le16 cts_back_timeout; /* CTS Back Timeout */
__le32 phy_stats_high; /* PHY Stats High */
__le32 phy_stats_low; /* PHY Stats Low */
struct agnx_sta_traffic traffic[8]; /* Traffic Class Structure (8) */
__le16 traffic_class0_frag_success; /* Traffic Class 0 Fragment Success */
__le16 traffic_class1_frag_success; /* Traffic Class 1 Fragment Success */
__le16 traffic_class2_frag_success; /* Traffic Class 2 Fragment Success */
__le16 traffic_class3_frag_success; /* Traffic Class 3 Fragment Success */
__le16 traffic_class4_frag_success; /* Traffic Class 4 Fragment Success */
__le16 traffic_class5_frag_success; /* Traffic Class 5 Fragment Success */
__le16 traffic_class6_frag_success; /* Traffic Class 6 Fragment Success */
__le16 traffic_class7_frag_success; /* Traffic Class 7 Fragment Success */
__le16 num_frag_non_prime_rates; /* number of Fragments for non-prime rates */
__le16 ack_timeout_non_prime_rates; /* ACK Timeout for non-prime rates */
} __attribute__((__packed__));
struct agnx_beacon_hdr {
struct agnx_sta_power power; /* Tx Station Power Template */
u8 phy_hdr[6]; /* PHY Hdr */
u8 frame_len_lo; /* Frame Length Lo */
u8 frame_len_hi; /* Frame Length Hi */
u8 mac_hdr[24]; /* MAC Header */
/* FIXME */
/* 802.11(abg) beacon */
} __attribute__((__packed__));
void hash_write(struct agnx_priv *priv, const u8 *mac_addr, u8 sta_id);
void hash_dump(struct agnx_priv *priv, u8 sta_id);
void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx);
void set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power,
unsigned int sta_idx);
void get_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
unsigned int sta_idx, unsigned int wq_idx);
void set_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
unsigned int sta_idx, unsigned int wq_idx);
void get_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx);
void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx);
void sta_power_init(struct agnx_priv *priv, unsigned int num);
void sta_init(struct agnx_priv *priv, unsigned int num);
#endif /* AGNX_STA_H_ */
#include <linux/pci.h>
#include <linux/delay.h>
#include "agnx.h"
#include "debug.h"
#include "phy.h"
static const u32
tx_fir_table[] = { 0x19, 0x5d, 0xce, 0x151, 0x1c3, 0x1ff, 0x1ea, 0x17c, 0xcf,
0x19, 0x38e, 0x350, 0x362, 0x3ad, 0x5, 0x44, 0x59, 0x49,
0x21, 0x3f7, 0x3e0, 0x3e3, 0x3f3, 0x0 };
void tx_fir_table_init(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
int i;
for (i = 0; i < ARRAY_SIZE(tx_fir_table); i++)
iowrite32(tx_fir_table[i], ctl + AGNX_FIR_BASE + i*4);
} /* fir_table_setup */
static const u32
gain_table[] = { 0x8, 0x8, 0xf, 0x13, 0x17, 0x1b, 0x1f, 0x23, 0x27, 0x2b,
0x2f, 0x33, 0x37, 0x3b, 0x3f, 0x43, 0x47, 0x4b, 0x4f,
0x53, 0x57, 0x5b, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
0x5f, 0x5f, 0x5f, 0x5f };
void gain_table_init(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
int i;
for (i = 0; i < ARRAY_SIZE(gain_table); i++) {
iowrite32(gain_table[i], ctl + AGNX_GAIN_TABLE + i*4);
iowrite32(gain_table[i], ctl + AGNX_GAIN_TABLE + i*4 + 0x80);
}
} /* gain_table_init */
void monitor_gain_table_init(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
unsigned int i;
for (i = 0; i < 0x44; i += 4) {
iowrite32(0x61, ctl + AGNX_MONGCR_BASE + i);
iowrite32(0x61, ctl + AGNX_MONGCR_BASE + 0x200 + i);
}
for (i = 0x44; i < 0x64; i += 4) {
iowrite32(0x6e, ctl + AGNX_MONGCR_BASE + i);
iowrite32(0x6e, ctl + AGNX_MONGCR_BASE + 0x200 + i);
}
for (i = 0x64; i < 0x94; i += 4) {
iowrite32(0x7a, ctl + AGNX_MONGCR_BASE + i);
iowrite32(0x7a, ctl + AGNX_MONGCR_BASE + 0x200 + i);
}
for (i = 0x94; i < 0xdc; i += 4) {
iowrite32(0x87, ctl + AGNX_MONGCR_BASE + i);
iowrite32(0x87, ctl + AGNX_MONGCR_BASE + 0x200 + i);
}
for (i = 0xdc; i < 0x148; i += 4) {
iowrite32(0x95, ctl + AGNX_MONGCR_BASE + i);
iowrite32(0x95, ctl + AGNX_MONGCR_BASE + 0x200 + i);
}
for (i = 0x148; i < 0x1e8; i += 4) {
iowrite32(0xa2, ctl + AGNX_MONGCR_BASE + i);
iowrite32(0xa2, ctl + AGNX_MONGCR_BASE + 0x200 + i);
}
for (i = 0x1e8; i <= 0x1fc; i += 4) {
iowrite32(0xb0, ctl + AGNX_MONGCR_BASE + i);
iowrite32(0xb0, ctl + AGNX_MONGCR_BASE + 0x200 + i);
}
} /* monitor_gain_table_init */
void routing_table_init(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
unsigned int type, subtype;
u32 reg;
disable_receiver(priv);
for (type = 0; type < 0x3; type++) {
for (subtype = 0; subtype < 0x10; subtype++) {
/* 1. Set Routing table to R/W and to Return status on Read */
reg = (type << ROUTAB_TYPE_SHIFT) |
(subtype << ROUTAB_SUBTYPE_SHIFT);
reg |= (1 << ROUTAB_RW_SHIFT) | (1 << ROUTAB_STATUS_SHIFT);
if (type == ROUTAB_TYPE_DATA) {
/* NULL goes to RFP */
if (subtype == ROUTAB_SUBTYPE_NULL)
/* reg |= ROUTAB_ROUTE_RFP; */
reg |= ROUTAB_ROUTE_CPU;
/* QOS NULL goes to CPU */
else if (subtype == ROUTAB_SUBTYPE_QOSNULL)
reg |= ROUTAB_ROUTE_CPU;
/* All Data and QOS data subtypes go to Encryption */
else if ((subtype == ROUTAB_SUBTYPE_DATA) ||
(subtype == ROUTAB_SUBTYPE_DATAACK) ||
(subtype == ROUTAB_SUBTYPE_DATAPOLL) ||
(subtype == ROUTAB_SUBTYPE_DATAPOLLACK) ||
(subtype == ROUTAB_SUBTYPE_QOSDATA) ||
(subtype == ROUTAB_SUBTYPE_QOSDATAACK) ||
(subtype == ROUTAB_SUBTYPE_QOSDATAPOLL) ||
(subtype == ROUTAB_SUBTYPE_QOSDATAACKPOLL))
reg |= ROUTAB_ROUTE_ENCRY;
/* reg |= ROUTAB_ROUTE_CPU; */
/*Drop NULL and QOS NULL ack, poll and poll ack*/
else if ((subtype == ROUTAB_SUBTYPE_NULLACK) ||
(subtype == ROUTAB_SUBTYPE_QOSNULLACK) ||
(subtype == ROUTAB_SUBTYPE_NULLPOLL) ||
(subtype == ROUTAB_SUBTYPE_QOSNULLPOLL) ||
(subtype == ROUTAB_SUBTYPE_NULLPOLLACK) ||
(subtype == ROUTAB_SUBTYPE_QOSNULLPOLLACK))
/* reg |= ROUTAB_ROUTE_DROP; */
reg |= ROUTAB_ROUTE_CPU;
} else {
reg |= (ROUTAB_ROUTE_CPU);
}
iowrite32(reg, ctl + AGNX_RXM_ROUTAB);
/* Check to verify that the status bit cleared */
routing_table_delay();
}
}
enable_receiver(priv);
} /* routing_table_init */
void tx_engine_lookup_tbl_init(struct agnx_priv *priv)
{
void __iomem *data = priv->data;
unsigned int i;
for (i = 0; i <= 28; i += 4)
iowrite32(0xb00c, data + AGNX_ENGINE_LOOKUP_TBL + i);
for (i = 32; i <= 120; i += 8) {
iowrite32(0x1e58, data + AGNX_ENGINE_LOOKUP_TBL + i);
iowrite32(0xb00c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
}
for (i = 128; i <= 156; i += 4)
iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i);
for (i = 160; i <= 248; i += 8) {
iowrite32(0x1858, data + AGNX_ENGINE_LOOKUP_TBL + i);
iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
}
for (i = 256; i <= 284; i += 4)
iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i);
for (i = 288; i <= 376; i += 8) {
iowrite32(0x1a58, data + AGNX_ENGINE_LOOKUP_TBL + i);
iowrite32(0x1858, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
}
for (i = 512; i <= 540; i += 4)
iowrite32(0xc00c, data + AGNX_ENGINE_LOOKUP_TBL + i);
for (i = 544; i <= 632; i += 8) {
iowrite32(0x2058, data + AGNX_ENGINE_LOOKUP_TBL + i);
iowrite32(0xc00c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
}
for (i = 640; i <= 668; i += 4)
iowrite32(0xc80c, data + AGNX_ENGINE_LOOKUP_TBL + i);
for (i = 672; i <= 764; i += 8) {
iowrite32(0x2258, data + AGNX_ENGINE_LOOKUP_TBL + i);
iowrite32(0xc80c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
}
}
#ifndef AGNX_TABLE_H_
#define AGNX_TABLE_H_
void tx_fir_table_init(struct agnx_priv *priv);
void gain_table_init(struct agnx_priv *priv);
void monitor_gain_table_init(struct agnx_priv *priv);
void routing_table_init(struct agnx_priv *priv);
void tx_engine_lookup_tbl_init(struct agnx_priv *priv);
#endif /* AGNX_TABLE_H_ */
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册