/**
* 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 "phy.h"
#include "table.h"
#include "sta.h"
#include "xmit.h"
u8 read_from_eeprom(struct agnx_priv *priv, u16 address)
{
void __iomem *ctl = priv->ctl;
struct agnx_eeprom cmd;
u32 reg;
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = EEPROM_CMD_READ << AGNX_EEPROM_COMMAND_SHIFT;
cmd.address = address;
/* Verify that the Status bit is clear */
/* Read Command and Address are written to the Serial Interface */
iowrite32(*(__le32 *)&cmd, ctl + AGNX_CIR_SERIALITF);
/* Wait for the Status bit to clear again */
eeprom_delay();
/* Read from Data */
reg = ioread32(ctl + AGNX_CIR_SERIALITF);
cmd = *(struct agnx_eeprom *)®
return cmd.data;
}
static int card_full_reset(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
u32 reg;
AGNX_TRACE;
reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x80);
reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
return 0;
}
inline void enable_power_saving(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
u32 reg;
reg = agnx_read32(ctl, AGNX_PM_PMCTL);
reg &= ~0x8;
agnx_write32(ctl, AGNX_PM_PMCTL, reg);
}
inline void disable_power_saving(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
u32 reg;
reg = agnx_read32(ctl, AGNX_PM_PMCTL);
reg |= 0x8;
agnx_write32(ctl, AGNX_PM_PMCTL, reg);
}
void disable_receiver(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
AGNX_TRACE;
/* FIXME Disable the receiver */
agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x0);
/* Set gain control reset */
agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
/* Reset gain control reset */
agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
}
/* Fixme this shoule be disable RX, above is enable RX */
void enable_receiver(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
AGNX_TRACE;
/* Set adaptive gain control discovery mode */
agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
/* Set gain control reset */
agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
/* Clear gain control reset */
agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
}
static void mac_address_set(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
u8 *mac_addr = priv->mac_addr;
u32 reg;
/* FIXME */
reg = (mac_addr[0] << 24) | (mac_addr[1] << 16) | mac_addr[2] << 8 | mac_addr[3];
iowrite32(reg, ctl + AGNX_RXM_MACHI);
reg = (mac_addr[4] << 8) | mac_addr[5];
iowrite32(reg, ctl + AGNX_RXM_MACLO);
}
static void receiver_bssid_set(struct agnx_priv *priv, const u8 *bssid)
{
void __iomem *ctl = priv->ctl;
u32 reg;
disable_receiver(priv);
/* FIXME */
reg = bssid[0] << 24 | (bssid[1] << 16) | (bssid[2] << 8) | bssid[3];
iowrite32(reg, ctl + AGNX_RXM_BSSIDHI);
reg = (bssid[4] << 8) | bssid[5];
iowrite32(reg, ctl + AGNX_RXM_BSSIDLO);
/* Enable the receiver */
enable_receiver(priv);
/* Clear the TSF */
/* agnx_write32(ctl, AGNX_TXM_TSFLO, 0x0); */
/* agnx_write32(ctl, AGNX_TXM_TSFHI, 0x0); */
/* Clear the TBTT */
agnx_write32(ctl, AGNX_TXM_TBTTLO, 0x0);
agnx_write32(ctl, AGNX_TXM_TBTTHI, 0x0);
disable_receiver(priv);
} /* receiver_bssid_set */
static void band_management_init(struct agnx_priv *priv)
{
void __iomem *ctl = priv->ctl;
void __iomem *data = priv->data