Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1674 commits) qlcnic: adding co maintainer ixgbe: add support for active DA cables ixgbe: dcb, do not tag tc_prio_control frames ixgbe: fix ixgbe_tx_is_paused logic ixgbe: always enable vlan strip/insert when DCB is enabled ixgbe: remove some redundant code in setting FCoE FIP filter ixgbe: fix wrong offset to fc_frame_header in ixgbe_fcoe_ddp ixgbe: fix header len when unsplit packet overflows to data buffer ipv6: Never schedule DAD timer on dead address ipv6: Use POSTDAD state ipv6: Use state_lock to protect ifa state ipv6: Replace inet6_ifaddr->dead with state cxgb4: notify upper drivers if the device is already up when they load cxgb4: keep interrupts available when the ports are brought down cxgb4: fix initial addition of MAC address cnic: Return SPQ credit to bnx2x after ring setup and shutdown. cnic: Convert cnic_local_flags to atomic ops. can: Fix SJA1000 command register writes on SMP systems bridge: fix build for CONFIG_SYSFS disabled ARCNET: Limit com20020 PCI ID matches for SOHARD cards ... Fix up various conflicts with pcmcia tree drivers/net/ {pcmcia/3c589_cs.c, wireless/orinoco/orinoco_cs.c and wireless/orinoco/spectrum_cs.c} and feature removal (Documentation/feature-removal-schedule.txt). Also fix a non-content conflict due to pm_qos_requirement getting renamed in the PM tree (now pm_qos_request) in net/mac80211/scan.c
This commit is contained in:
@@ -27,6 +27,17 @@ config HERMES
|
||||
configure your card and that /etc/pcmcia/wireless.opts works :
|
||||
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
|
||||
|
||||
config HERMES_PRISM
|
||||
bool "Support Prism 2/2.5 chipset"
|
||||
depends on HERMES
|
||||
---help---
|
||||
|
||||
Say Y to enable support for Prism 2 and 2.5 chipsets. These
|
||||
chipsets are better handled by the hostap driver. This driver
|
||||
would not support WPA or firmware download for Prism chipset.
|
||||
|
||||
If you are not sure, say N.
|
||||
|
||||
config HERMES_CACHE_FW_ON_INIT
|
||||
bool "Cache Hermes firmware on driver initialisation"
|
||||
depends on HERMES
|
||||
@@ -86,7 +97,7 @@ config NORTEL_HERMES
|
||||
|
||||
config PCI_HERMES
|
||||
tristate "Prism 2.5 PCI 802.11b adaptor support"
|
||||
depends on PCI && HERMES
|
||||
depends on PCI && HERMES && HERMES_PRISM
|
||||
help
|
||||
Enable support for PCI and mini-PCI 802.11b wireless NICs based on
|
||||
the Prism 2.5 chipset. These are true PCI cards, not the 802.11b
|
||||
@@ -121,3 +132,10 @@ config PCMCIA_SPECTRUM
|
||||
This driver requires firmware download on startup. Utilities
|
||||
for downloading Symbol firmware are available at
|
||||
<http://sourceforge.net/projects/orinoco/>
|
||||
|
||||
config ORINOCO_USB
|
||||
tristate "Agere Orinoco USB support"
|
||||
depends on USB && HERMES
|
||||
select FW_LOADER
|
||||
---help---
|
||||
This driver is for USB versions of the Agere Orinoco card.
|
||||
|
@@ -11,3 +11,7 @@ obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
|
||||
obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
|
||||
obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
|
||||
obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
|
||||
obj-$(CONFIG_ORINOCO_USB) += orinoco_usb.o
|
||||
|
||||
# Orinoco should be endian clean.
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
@@ -77,9 +77,9 @@ airport_resume(struct macio_dev *mdev)
|
||||
|
||||
enable_irq(card->irq);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, &flags);
|
||||
err = orinoco_up(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -195,7 +195,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
|
||||
ssleep(1);
|
||||
|
||||
/* Reset it before we get the interrupt */
|
||||
hermes_init(hw);
|
||||
hw->ops->init(hw);
|
||||
|
||||
if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) {
|
||||
printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq);
|
||||
@@ -210,7 +210,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
|
||||
}
|
||||
|
||||
/* Register an interface with the stack */
|
||||
if (orinoco_if_add(priv, phys_addr, card->irq) != 0) {
|
||||
if (orinoco_if_add(priv, phys_addr, card->irq, NULL) != 0) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto failed;
|
||||
}
|
||||
|
@@ -88,7 +88,9 @@ int orinoco_wiphy_register(struct wiphy *wiphy)
|
||||
|
||||
wiphy->rts_threshold = priv->rts_thresh;
|
||||
if (!priv->has_mwo)
|
||||
wiphy->frag_threshold = priv->frag_thresh;
|
||||
wiphy->frag_threshold = priv->frag_thresh + 1;
|
||||
wiphy->retry_short = priv->short_retry_limit;
|
||||
wiphy->retry_long = priv->long_retry_limit;
|
||||
|
||||
return wiphy_register(wiphy);
|
||||
}
|
||||
@@ -157,6 +159,7 @@ static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev,
|
||||
}
|
||||
|
||||
static int orinoco_set_channel(struct wiphy *wiphy,
|
||||
struct net_device *netdev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type)
|
||||
{
|
||||
@@ -187,7 +190,7 @@ static int orinoco_set_channel(struct wiphy *wiphy,
|
||||
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
|
||||
/* Fast channel change - no commit if successful */
|
||||
hermes_t *hw = &priv->hw;
|
||||
err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
|
||||
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
|
||||
HERMES_TEST_SET_CHANNEL,
|
||||
channel, NULL);
|
||||
}
|
||||
@@ -196,8 +199,92 @@ static int orinoco_set_channel(struct wiphy *wiphy,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)
|
||||
{
|
||||
struct orinoco_private *priv = wiphy_priv(wiphy);
|
||||
int frag_value = -1;
|
||||
int rts_value = -1;
|
||||
int err = 0;
|
||||
|
||||
if (changed & WIPHY_PARAM_RETRY_SHORT) {
|
||||
/* Setting short retry not supported */
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
if (changed & WIPHY_PARAM_RETRY_LONG) {
|
||||
/* Setting long retry not supported */
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
|
||||
/* Set fragmentation */
|
||||
if (priv->has_mwo) {
|
||||
if (wiphy->frag_threshold < 0)
|
||||
frag_value = 0;
|
||||
else {
|
||||
printk(KERN_WARNING "%s: Fixed fragmentation "
|
||||
"is not supported on this firmware. "
|
||||
"Using MWO robust instead.\n",
|
||||
priv->ndev->name);
|
||||
frag_value = 1;
|
||||
}
|
||||
} else {
|
||||
if (wiphy->frag_threshold < 0)
|
||||
frag_value = 2346;
|
||||
else if ((wiphy->frag_threshold < 257) ||
|
||||
(wiphy->frag_threshold > 2347))
|
||||
err = -EINVAL;
|
||||
else
|
||||
/* cfg80211 value is 257-2347 (odd only)
|
||||
* orinoco rid has range 256-2346 (even only) */
|
||||
frag_value = wiphy->frag_threshold & ~0x1;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
|
||||
/* Set RTS.
|
||||
*
|
||||
* Prism documentation suggests default of 2432,
|
||||
* and a range of 0-3000.
|
||||
*
|
||||
* Current implementation uses 2347 as the default and
|
||||
* the upper limit.
|
||||
*/
|
||||
|
||||
if (wiphy->rts_threshold < 0)
|
||||
rts_value = 2347;
|
||||
else if (wiphy->rts_threshold > 2347)
|
||||
err = -EINVAL;
|
||||
else
|
||||
rts_value = wiphy->rts_threshold;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
unsigned long flags;
|
||||
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
if (frag_value >= 0) {
|
||||
if (priv->has_mwo)
|
||||
priv->mwo_robust = frag_value;
|
||||
else
|
||||
priv->frag_thresh = frag_value;
|
||||
}
|
||||
if (rts_value >= 0)
|
||||
priv->rts_thresh = rts_value;
|
||||
|
||||
err = orinoco_commit(priv);
|
||||
|
||||
orinoco_unlock(priv, &flags);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct cfg80211_ops orinoco_cfg_ops = {
|
||||
.change_virtual_intf = orinoco_change_vif,
|
||||
.set_channel = orinoco_set_channel,
|
||||
.scan = orinoco_scan,
|
||||
.set_wiphy_params = orinoco_set_wiphy_params,
|
||||
};
|
||||
|
@@ -122,7 +122,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
|
||||
dev_dbg(dev, "Attempting to download firmware %s\n", firmware);
|
||||
|
||||
/* Read current plug data */
|
||||
err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0);
|
||||
err = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
|
||||
dev_dbg(dev, "Read PDA returned %d\n", err);
|
||||
if (err)
|
||||
goto free;
|
||||
@@ -149,7 +149,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
|
||||
}
|
||||
|
||||
/* Enable aux port to allow programming */
|
||||
err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point));
|
||||
err = hw->ops->program_init(hw, le32_to_cpu(hdr->entry_point));
|
||||
dev_dbg(dev, "Program init returned %d\n", err);
|
||||
if (err != 0)
|
||||
goto abort;
|
||||
@@ -177,7 +177,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
|
||||
goto abort;
|
||||
|
||||
/* Tell card we've finished */
|
||||
err = hermesi_program_end(hw);
|
||||
err = hw->ops->program_end(hw);
|
||||
dev_dbg(dev, "Program end returned %d\n", err);
|
||||
if (err != 0)
|
||||
goto abort;
|
||||
@@ -224,7 +224,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
|
||||
if (!pda)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1);
|
||||
ret = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
|
||||
if (ret)
|
||||
goto free;
|
||||
}
|
||||
@@ -260,7 +260,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
|
||||
}
|
||||
|
||||
/* Reset hermes chip and make sure it responds */
|
||||
ret = hermes_init(hw);
|
||||
ret = hw->ops->init(hw);
|
||||
|
||||
/* hermes_reset() should return 0 with the secondary firmware */
|
||||
if (secondary && ret != 0)
|
||||
|
@@ -51,6 +51,26 @@
|
||||
#define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */
|
||||
#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
|
||||
|
||||
/*
|
||||
* AUX port access. To unlock the AUX port write the access keys to the
|
||||
* PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
|
||||
* register. Then read it and make sure it's HERMES_AUX_ENABLED.
|
||||
*/
|
||||
#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
|
||||
#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
|
||||
#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
|
||||
#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */
|
||||
|
||||
#define HERMES_AUX_PW0 0xFE01
|
||||
#define HERMES_AUX_PW1 0xDC23
|
||||
#define HERMES_AUX_PW2 0xBA45
|
||||
|
||||
/* HERMES_CMD_DOWNLD */
|
||||
#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD)
|
||||
|
||||
/*
|
||||
* Debugging helpers
|
||||
*/
|
||||
@@ -70,6 +90,7 @@
|
||||
|
||||
#endif /* ! HERMES_DEBUG */
|
||||
|
||||
static const struct hermes_ops hermes_ops_local;
|
||||
|
||||
/*
|
||||
* Internal functions
|
||||
@@ -111,9 +132,9 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
|
||||
*/
|
||||
|
||||
/* For doing cmds that wipe the magic constant in SWSUPPORT0 */
|
||||
int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
|
||||
u16 parm0, u16 parm1, u16 parm2,
|
||||
struct hermes_response *resp)
|
||||
static int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
|
||||
u16 parm0, u16 parm1, u16 parm2,
|
||||
struct hermes_response *resp)
|
||||
{
|
||||
int err = 0;
|
||||
int k;
|
||||
@@ -163,17 +184,18 @@ int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_doicmd_wait);
|
||||
|
||||
void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
|
||||
{
|
||||
hw->iobase = address;
|
||||
hw->reg_spacing = reg_spacing;
|
||||
hw->inten = 0x0;
|
||||
hw->eeprom_pda = false;
|
||||
hw->ops = &hermes_ops_local;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_struct_init);
|
||||
|
||||
int hermes_init(hermes_t *hw)
|
||||
static int hermes_init(hermes_t *hw)
|
||||
{
|
||||
u16 reg;
|
||||
int err = 0;
|
||||
@@ -217,7 +239,6 @@ int hermes_init(hermes_t *hw)
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_init);
|
||||
|
||||
/* Issue a command to the chip, and (busy!) wait for it to
|
||||
* complete.
|
||||
@@ -228,8 +249,8 @@ EXPORT_SYMBOL(hermes_init);
|
||||
* > 0 on error returned by the firmware
|
||||
*
|
||||
* Callable from any context, but locking is your problem. */
|
||||
int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
|
||||
struct hermes_response *resp)
|
||||
static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
|
||||
struct hermes_response *resp)
|
||||
{
|
||||
int err;
|
||||
int k;
|
||||
@@ -291,9 +312,8 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_docmd_wait);
|
||||
|
||||
int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
|
||||
static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
|
||||
{
|
||||
int err = 0;
|
||||
int k;
|
||||
@@ -333,7 +353,6 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_allocate);
|
||||
|
||||
/* Set up a BAP to read a particular chunk of data from card's internal buffer.
|
||||
*
|
||||
@@ -403,8 +422,8 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
|
||||
* 0 on success
|
||||
* > 0 on error from firmware
|
||||
*/
|
||||
int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
|
||||
u16 id, u16 offset)
|
||||
static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
|
||||
u16 id, u16 offset)
|
||||
{
|
||||
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
|
||||
int err = 0;
|
||||
@@ -422,7 +441,6 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_bap_pread);
|
||||
|
||||
/* Write a block of data to the chip's buffer, via the
|
||||
* BAP. Synchronization/serialization is the caller's problem.
|
||||
@@ -432,8 +450,8 @@ EXPORT_SYMBOL(hermes_bap_pread);
|
||||
* 0 on success
|
||||
* > 0 on error from firmware
|
||||
*/
|
||||
int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
|
||||
u16 id, u16 offset)
|
||||
static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
|
||||
u16 id, u16 offset)
|
||||
{
|
||||
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
|
||||
int err = 0;
|
||||
@@ -451,7 +469,6 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_bap_pwrite);
|
||||
|
||||
/* Read a Length-Type-Value record from the card.
|
||||
*
|
||||
@@ -461,8 +478,8 @@ EXPORT_SYMBOL(hermes_bap_pwrite);
|
||||
* practice.
|
||||
*
|
||||
* Callable from user or bh context. */
|
||||
int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
|
||||
u16 *length, void *buf)
|
||||
static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
|
||||
u16 *length, void *buf)
|
||||
{
|
||||
int err = 0;
|
||||
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
|
||||
@@ -505,10 +522,9 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_read_ltv);
|
||||
|
||||
int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
|
||||
u16 length, const void *value)
|
||||
static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
|
||||
u16 length, const void *value)
|
||||
{
|
||||
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
|
||||
int err = 0;
|
||||
@@ -533,4 +549,228 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_write_ltv);
|
||||
|
||||
/*** Hermes AUX control ***/
|
||||
|
||||
static inline void
|
||||
hermes_aux_setaddr(hermes_t *hw, u32 addr)
|
||||
{
|
||||
hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
|
||||
hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
|
||||
}
|
||||
|
||||
static inline int
|
||||
hermes_aux_control(hermes_t *hw, int enabled)
|
||||
{
|
||||
int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
|
||||
int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
|
||||
int i;
|
||||
|
||||
/* Already open? */
|
||||
if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
|
||||
return 0;
|
||||
|
||||
hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
|
||||
hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
|
||||
hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
|
||||
hermes_write_reg(hw, HERMES_CONTROL, action);
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
udelay(10);
|
||||
if (hermes_read_reg(hw, HERMES_CONTROL) ==
|
||||
desired_state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*** Hermes programming ***/
|
||||
|
||||
/* About to start programming data (Hermes I)
|
||||
* offset is the entry point
|
||||
*
|
||||
* Spectrum_cs' Symbol fw does not require this
|
||||
* wl_lkm Agere fw does
|
||||
* Don't know about intersil
|
||||
*/
|
||||
static int hermesi_program_init(hermes_t *hw, u32 offset)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Disable interrupts?*/
|
||||
/*hw->inten = 0x0;*/
|
||||
/*hermes_write_regn(hw, INTEN, 0);*/
|
||||
/*hermes_set_irqmask(hw, 0);*/
|
||||
|
||||
/* Acknowledge any outstanding command */
|
||||
hermes_write_regn(hw, EVACK, 0xFFFF);
|
||||
|
||||
/* Using init_cmd_wait rather than cmd_wait */
|
||||
err = hw->ops->init_cmd_wait(hw,
|
||||
0x0100 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = hw->ops->init_cmd_wait(hw,
|
||||
0x0000 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = hermes_aux_control(hw, 1);
|
||||
pr_debug("AUX enable returned %d\n", err);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pr_debug("Enabling volatile, EP 0x%08x\n", offset);
|
||||
err = hw->ops->init_cmd_wait(hw,
|
||||
HERMES_PROGRAM_ENABLE_VOLATILE,
|
||||
offset & 0xFFFFu,
|
||||
offset >> 16,
|
||||
0,
|
||||
NULL);
|
||||
pr_debug("PROGRAM_ENABLE returned %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Done programming data (Hermes I)
|
||||
*
|
||||
* Spectrum_cs' Symbol fw does not require this
|
||||
* wl_lkm Agere fw does
|
||||
* Don't know about intersil
|
||||
*/
|
||||
static int hermesi_program_end(hermes_t *hw)
|
||||
{
|
||||
struct hermes_response resp;
|
||||
int rc = 0;
|
||||
int err;
|
||||
|
||||
rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
|
||||
|
||||
pr_debug("PROGRAM_DISABLE returned %d, "
|
||||
"r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
|
||||
rc, resp.resp0, resp.resp1, resp.resp2);
|
||||
|
||||
if ((rc == 0) &&
|
||||
((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
|
||||
rc = -EIO;
|
||||
|
||||
err = hermes_aux_control(hw, 0);
|
||||
pr_debug("AUX disable returned %d\n", err);
|
||||
|
||||
/* Acknowledge any outstanding command */
|
||||
hermes_write_regn(hw, EVACK, 0xFFFF);
|
||||
|
||||
/* Reinitialise, ignoring return */
|
||||
(void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
|
||||
return rc ? rc : err;
|
||||
}
|
||||
|
||||
static int hermes_program_bytes(struct hermes *hw, const char *data,
|
||||
u32 addr, u32 len)
|
||||
{
|
||||
/* wl lkm splits the programming into chunks of 2000 bytes.
|
||||
* This restriction appears to come from USB. The PCMCIA
|
||||
* adapters can program the whole lot in one go */
|
||||
hermes_aux_setaddr(hw, addr);
|
||||
hermes_write_bytes(hw, HERMES_AUXDATA, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read PDA from the adapter */
|
||||
static int hermes_read_pda(hermes_t *hw, __le16 *pda, u32 pda_addr, u16 pda_len)
|
||||
{
|
||||
int ret;
|
||||
u16 pda_size;
|
||||
u16 data_len = pda_len;
|
||||
__le16 *data = pda;
|
||||
|
||||
if (hw->eeprom_pda) {
|
||||
/* PDA of spectrum symbol is in eeprom */
|
||||
|
||||
/* Issue command to read EEPROM */
|
||||
ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* wl_lkm does not include PDA size in the PDA area.
|
||||
* We will pad the information into pda, so other routines
|
||||
* don't have to be modified */
|
||||
pda[0] = cpu_to_le16(pda_len - 2);
|
||||
/* Includes CFG_PROD_DATA but not itself */
|
||||
pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
|
||||
data_len = pda_len - 4;
|
||||
data = pda + 2;
|
||||
}
|
||||
|
||||
/* Open auxiliary port */
|
||||
ret = hermes_aux_control(hw, 1);
|
||||
pr_debug("AUX enable returned %d\n", ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Read PDA */
|
||||
hermes_aux_setaddr(hw, pda_addr);
|
||||
hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
|
||||
|
||||
/* Close aux port */
|
||||
ret = hermes_aux_control(hw, 0);
|
||||
pr_debug("AUX disable returned %d\n", ret);
|
||||
|
||||
/* Check PDA length */
|
||||
pda_size = le16_to_cpu(pda[0]);
|
||||
pr_debug("Actual PDA length %d, Max allowed %d\n",
|
||||
pda_size, pda_len);
|
||||
if (pda_size > pda_len)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hermes_lock_irqsave(spinlock_t *lock,
|
||||
unsigned long *flags) __acquires(lock)
|
||||
{
|
||||
spin_lock_irqsave(lock, *flags);
|
||||
}
|
||||
|
||||
static void hermes_unlock_irqrestore(spinlock_t *lock,
|
||||
unsigned long *flags) __releases(lock)
|
||||
{
|
||||
spin_unlock_irqrestore(lock, *flags);
|
||||
}
|
||||
|
||||
static void hermes_lock_irq(spinlock_t *lock) __acquires(lock)
|
||||
{
|
||||
spin_lock_irq(lock);
|
||||
}
|
||||
|
||||
static void hermes_unlock_irq(spinlock_t *lock) __releases(lock)
|
||||
{
|
||||
spin_unlock_irq(lock);
|
||||
}
|
||||
|
||||
/* Hermes operations for local buses */
|
||||
static const struct hermes_ops hermes_ops_local = {
|
||||
.init = hermes_init,
|
||||
.cmd_wait = hermes_docmd_wait,
|
||||
.init_cmd_wait = hermes_doicmd_wait,
|
||||
.allocate = hermes_allocate,
|
||||
.read_ltv = hermes_read_ltv,
|
||||
.write_ltv = hermes_write_ltv,
|
||||
.bap_pread = hermes_bap_pread,
|
||||
.bap_pwrite = hermes_bap_pwrite,
|
||||
.read_pda = hermes_read_pda,
|
||||
.program_init = hermesi_program_init,
|
||||
.program_end = hermesi_program_end,
|
||||
.program = hermes_program_bytes,
|
||||
.lock_irqsave = hermes_lock_irqsave,
|
||||
.unlock_irqrestore = hermes_unlock_irqrestore,
|
||||
.lock_irq = hermes_lock_irq,
|
||||
.unlock_irq = hermes_unlock_irq,
|
||||
};
|
||||
|
@@ -374,6 +374,37 @@ struct hermes_multicast {
|
||||
/* Timeouts */
|
||||
#define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */
|
||||
|
||||
struct hermes;
|
||||
|
||||
/* Functions to access hardware */
|
||||
struct hermes_ops {
|
||||
int (*init)(struct hermes *hw);
|
||||
int (*cmd_wait)(struct hermes *hw, u16 cmd, u16 parm0,
|
||||
struct hermes_response *resp);
|
||||
int (*init_cmd_wait)(struct hermes *hw, u16 cmd,
|
||||
u16 parm0, u16 parm1, u16 parm2,
|
||||
struct hermes_response *resp);
|
||||
int (*allocate)(struct hermes *hw, u16 size, u16 *fid);
|
||||
int (*read_ltv)(struct hermes *hw, int bap, u16 rid, unsigned buflen,
|
||||
u16 *length, void *buf);
|
||||
int (*write_ltv)(struct hermes *hw, int bap, u16 rid,
|
||||
u16 length, const void *value);
|
||||
int (*bap_pread)(struct hermes *hw, int bap, void *buf, int len,
|
||||
u16 id, u16 offset);
|
||||
int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf,
|
||||
int len, u16 id, u16 offset);
|
||||
int (*read_pda)(struct hermes *hw, __le16 *pda,
|
||||
u32 pda_addr, u16 pda_len);
|
||||
int (*program_init)(struct hermes *hw, u32 entry_point);
|
||||
int (*program_end)(struct hermes *hw);
|
||||
int (*program)(struct hermes *hw, const char *buf,
|
||||
u32 addr, u32 len);
|
||||
void (*lock_irqsave)(spinlock_t *lock, unsigned long *flags);
|
||||
void (*unlock_irqrestore)(spinlock_t *lock, unsigned long *flags);
|
||||
void (*lock_irq)(spinlock_t *lock);
|
||||
void (*unlock_irq)(spinlock_t *lock);
|
||||
};
|
||||
|
||||
/* Basic control structure */
|
||||
typedef struct hermes {
|
||||
void __iomem *iobase;
|
||||
@@ -381,6 +412,9 @@ typedef struct hermes {
|
||||
#define HERMES_16BIT_REGSPACING 0
|
||||
#define HERMES_32BIT_REGSPACING 1
|
||||
u16 inten; /* Which interrupts should be enabled? */
|
||||
bool eeprom_pda;
|
||||
const struct hermes_ops *ops;
|
||||
void *priv;
|
||||
} hermes_t;
|
||||
|
||||
/* Register access convenience macros */
|
||||
@@ -394,22 +428,6 @@ typedef struct hermes {
|
||||
|
||||
/* Function prototypes */
|
||||
void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing);
|
||||
int hermes_init(hermes_t *hw);
|
||||
int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
|
||||
struct hermes_response *resp);
|
||||
int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
|
||||
u16 parm0, u16 parm1, u16 parm2,
|
||||
struct hermes_response *resp);
|
||||
int hermes_allocate(hermes_t *hw, u16 size, u16 *fid);
|
||||
|
||||
int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
|
||||
u16 id, u16 offset);
|
||||
int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
|
||||
u16 id, u16 offset);
|
||||
int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
|
||||
u16 *length, void *buf);
|
||||
int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
|
||||
u16 length, const void *value);
|
||||
|
||||
/* Inline functions */
|
||||
|
||||
@@ -426,13 +444,13 @@ static inline void hermes_set_irqmask(hermes_t *hw, u16 events)
|
||||
|
||||
static inline int hermes_enable_port(hermes_t *hw, int port)
|
||||
{
|
||||
return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
|
||||
return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
static inline int hermes_disable_port(hermes_t *hw, int port)
|
||||
{
|
||||
return hermes_docmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
|
||||
return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
@@ -440,7 +458,7 @@ static inline int hermes_disable_port(hermes_t *hw, int port)
|
||||
* information frame in __orinoco_ev_info() */
|
||||
static inline int hermes_inquire(hermes_t *hw, u16 rid)
|
||||
{
|
||||
return hermes_docmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
|
||||
return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
|
||||
}
|
||||
|
||||
#define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1)
|
||||
@@ -475,10 +493,10 @@ static inline void hermes_clear_words(struct hermes *hw, int off,
|
||||
}
|
||||
|
||||
#define HERMES_READ_RECORD(hw, bap, rid, buf) \
|
||||
(hermes_read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
|
||||
(hw->ops->read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
|
||||
#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
|
||||
(hermes_write_ltv((hw), (bap), (rid), \
|
||||
HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
|
||||
(hw->ops->write_ltv((hw), (bap), (rid), \
|
||||
HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
|
||||
|
||||
static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
|
||||
{
|
||||
|
@@ -46,37 +46,11 @@
|
||||
|
||||
#define PFX "hermes_dld: "
|
||||
|
||||
/*
|
||||
* AUX port access. To unlock the AUX port write the access keys to the
|
||||
* PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
|
||||
* register. Then read it and make sure it's HERMES_AUX_ENABLED.
|
||||
*/
|
||||
#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
|
||||
#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
|
||||
#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
|
||||
#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */
|
||||
|
||||
#define HERMES_AUX_PW0 0xFE01
|
||||
#define HERMES_AUX_PW1 0xDC23
|
||||
#define HERMES_AUX_PW2 0xBA45
|
||||
|
||||
/* HERMES_CMD_DOWNLD */
|
||||
#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD)
|
||||
|
||||
/* End markers used in dblocks */
|
||||
#define PDI_END 0x00000000 /* End of PDA */
|
||||
#define BLOCK_END 0xFFFFFFFF /* Last image block */
|
||||
#define TEXT_END 0x1A /* End of text header */
|
||||
|
||||
/* Limit the amout we try to download in a single shot.
|
||||
* Size is in bytes.
|
||||
*/
|
||||
#define MAX_DL_SIZE 1024
|
||||
#define LIMIT_PROGRAM_SIZE 0
|
||||
|
||||
/*
|
||||
* The following structures have little-endian fields denoted by
|
||||
* the leading underscore. Don't access them directly - use inline
|
||||
@@ -165,41 +139,6 @@ pdi_len(const struct pdi *pdi)
|
||||
return 2 * (le16_to_cpu(pdi->len) - 1);
|
||||
}
|
||||
|
||||
/*** Hermes AUX control ***/
|
||||
|
||||
static inline void
|
||||
hermes_aux_setaddr(hermes_t *hw, u32 addr)
|
||||
{
|
||||
hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
|
||||
hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
|
||||
}
|
||||
|
||||
static inline int
|
||||
hermes_aux_control(hermes_t *hw, int enabled)
|
||||
{
|
||||
int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
|
||||
int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
|
||||
int i;
|
||||
|
||||
/* Already open? */
|
||||
if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
|
||||
return 0;
|
||||
|
||||
hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
|
||||
hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
|
||||
hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
|
||||
hermes_write_reg(hw, HERMES_CONTROL, action);
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
udelay(10);
|
||||
if (hermes_read_reg(hw, HERMES_CONTROL) ==
|
||||
desired_state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*** Plug Data Functions ***/
|
||||
|
||||
/*
|
||||
@@ -271,62 +210,7 @@ hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,
|
||||
return -EINVAL;
|
||||
|
||||
/* do the actual plugging */
|
||||
hermes_aux_setaddr(hw, pdr_addr(pdr));
|
||||
hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read PDA from the adapter */
|
||||
int hermes_read_pda(hermes_t *hw,
|
||||
__le16 *pda,
|
||||
u32 pda_addr,
|
||||
u16 pda_len,
|
||||
int use_eeprom) /* can we get this into hw? */
|
||||
{
|
||||
int ret;
|
||||
u16 pda_size;
|
||||
u16 data_len = pda_len;
|
||||
__le16 *data = pda;
|
||||
|
||||
if (use_eeprom) {
|
||||
/* PDA of spectrum symbol is in eeprom */
|
||||
|
||||
/* Issue command to read EEPROM */
|
||||
ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* wl_lkm does not include PDA size in the PDA area.
|
||||
* We will pad the information into pda, so other routines
|
||||
* don't have to be modified */
|
||||
pda[0] = cpu_to_le16(pda_len - 2);
|
||||
/* Includes CFG_PROD_DATA but not itself */
|
||||
pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
|
||||
data_len = pda_len - 4;
|
||||
data = pda + 2;
|
||||
}
|
||||
|
||||
/* Open auxiliary port */
|
||||
ret = hermes_aux_control(hw, 1);
|
||||
pr_debug(PFX "AUX enable returned %d\n", ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* read PDA from EEPROM */
|
||||
hermes_aux_setaddr(hw, pda_addr);
|
||||
hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
|
||||
|
||||
/* Close aux port */
|
||||
ret = hermes_aux_control(hw, 0);
|
||||
pr_debug(PFX "AUX disable returned %d\n", ret);
|
||||
|
||||
/* Check PDA length */
|
||||
pda_size = le16_to_cpu(pda[0]);
|
||||
pr_debug(PFX "Actual PDA length %d, Max allowed %d\n",
|
||||
pda_size, pda_len);
|
||||
if (pda_size > pda_len)
|
||||
return -EINVAL;
|
||||
hw->ops->program(hw, pdi->data, pdr_addr(pdr), pdi_len(pdi));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -389,101 +273,13 @@ hermes_blocks_length(const char *first_block, const void *end)
|
||||
|
||||
/*** Hermes programming ***/
|
||||
|
||||
/* About to start programming data (Hermes I)
|
||||
* offset is the entry point
|
||||
*
|
||||
* Spectrum_cs' Symbol fw does not require this
|
||||
* wl_lkm Agere fw does
|
||||
* Don't know about intersil
|
||||
*/
|
||||
int hermesi_program_init(hermes_t *hw, u32 offset)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Disable interrupts?*/
|
||||
/*hw->inten = 0x0;*/
|
||||
/*hermes_write_regn(hw, INTEN, 0);*/
|
||||
/*hermes_set_irqmask(hw, 0);*/
|
||||
|
||||
/* Acknowledge any outstanding command */
|
||||
hermes_write_regn(hw, EVACK, 0xFFFF);
|
||||
|
||||
/* Using doicmd_wait rather than docmd_wait */
|
||||
err = hermes_doicmd_wait(hw,
|
||||
0x0100 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = hermes_doicmd_wait(hw,
|
||||
0x0000 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = hermes_aux_control(hw, 1);
|
||||
pr_debug(PFX "AUX enable returned %d\n", err);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pr_debug(PFX "Enabling volatile, EP 0x%08x\n", offset);
|
||||
err = hermes_doicmd_wait(hw,
|
||||
HERMES_PROGRAM_ENABLE_VOLATILE,
|
||||
offset & 0xFFFFu,
|
||||
offset >> 16,
|
||||
0,
|
||||
NULL);
|
||||
pr_debug(PFX "PROGRAM_ENABLE returned %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Done programming data (Hermes I)
|
||||
*
|
||||
* Spectrum_cs' Symbol fw does not require this
|
||||
* wl_lkm Agere fw does
|
||||
* Don't know about intersil
|
||||
*/
|
||||
int hermesi_program_end(hermes_t *hw)
|
||||
{
|
||||
struct hermes_response resp;
|
||||
int rc = 0;
|
||||
int err;
|
||||
|
||||
rc = hermes_docmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
|
||||
|
||||
pr_debug(PFX "PROGRAM_DISABLE returned %d, "
|
||||
"r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
|
||||
rc, resp.resp0, resp.resp1, resp.resp2);
|
||||
|
||||
if ((rc == 0) &&
|
||||
((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
|
||||
rc = -EIO;
|
||||
|
||||
err = hermes_aux_control(hw, 0);
|
||||
pr_debug(PFX "AUX disable returned %d\n", err);
|
||||
|
||||
/* Acknowledge any outstanding command */
|
||||
hermes_write_regn(hw, EVACK, 0xFFFF);
|
||||
|
||||
/* Reinitialise, ignoring return */
|
||||
(void) hermes_doicmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
|
||||
return rc ? rc : err;
|
||||
}
|
||||
|
||||
/* Program the data blocks */
|
||||
int hermes_program(hermes_t *hw, const char *first_block, const void *end)
|
||||
{
|
||||
const struct dblock *blk;
|
||||
u32 blkaddr;
|
||||
u32 blklen;
|
||||
#if LIMIT_PROGRAM_SIZE
|
||||
u32 addr;
|
||||
u32 len;
|
||||
#endif
|
||||
int err = 0;
|
||||
|
||||
blk = (const struct dblock *) first_block;
|
||||
|
||||
@@ -498,30 +294,10 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)
|
||||
pr_debug(PFX "Programming block of length %d "
|
||||
"to address 0x%08x\n", blklen, blkaddr);
|
||||
|
||||
#if !LIMIT_PROGRAM_SIZE
|
||||
/* wl_lkm driver splits this into writes of 2000 bytes */
|
||||
hermes_aux_setaddr(hw, blkaddr);
|
||||
hermes_write_bytes(hw, HERMES_AUXDATA, blk->data,
|
||||
blklen);
|
||||
#else
|
||||
len = (blklen < MAX_DL_SIZE) ? blklen : MAX_DL_SIZE;
|
||||
addr = blkaddr;
|
||||
err = hw->ops->program(hw, blk->data, blkaddr, blklen);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
while (addr < (blkaddr + blklen)) {
|
||||
pr_debug(PFX "Programming subblock of length %d "
|
||||
"to address 0x%08x. Data @ %p\n",
|
||||
len, addr, &blk->data[addr - blkaddr]);
|
||||
|
||||
hermes_aux_setaddr(hw, addr);
|
||||
hermes_write_bytes(hw, HERMES_AUXDATA,
|
||||
&blk->data[addr - blkaddr],
|
||||
len);
|
||||
|
||||
addr += len;
|
||||
len = ((blkaddr + blklen - addr) < MAX_DL_SIZE) ?
|
||||
(blkaddr + blklen - addr) : MAX_DL_SIZE;
|
||||
}
|
||||
#endif
|
||||
blk = (const struct dblock *) &blk->data[blklen];
|
||||
|
||||
if ((void *) blk > (end - sizeof(*blk)))
|
||||
@@ -530,7 +306,7 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)
|
||||
blkaddr = dblock_addr(blk);
|
||||
blklen = dblock_len(blk);
|
||||
}
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*** Default plugging data for Hermes I ***/
|
||||
@@ -690,9 +466,8 @@ int hermes_apply_pda_with_defaults(hermes_t *hw,
|
||||
if ((pdi_len(pdi) == pdr_len(pdr)) &&
|
||||
((void *) pdi->data + pdi_len(pdi) < pda_end)) {
|
||||
/* do the actual plugging */
|
||||
hermes_aux_setaddr(hw, pdr_addr(pdr));
|
||||
hermes_write_bytes(hw, HERMES_AUXDATA,
|
||||
pdi->data, pdi_len(pdi));
|
||||
hw->ops->program(hw, pdi->data, pdr_addr(pdr),
|
||||
pdi_len(pdi));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -177,9 +177,9 @@ int determine_fw_capabilities(struct orinoco_private *priv,
|
||||
/* 3Com MAC : 00:50:DA:* */
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
/* Get the Symbol firmware version */
|
||||
err = hermes_read_ltv(hw, USER_BAP,
|
||||
HERMES_RID_SECONDARYVERSION_SYMBOL,
|
||||
SYMBOL_MAX_VER_LEN, NULL, &tmp);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP,
|
||||
HERMES_RID_SECONDARYVERSION_SYMBOL,
|
||||
SYMBOL_MAX_VER_LEN, NULL, &tmp);
|
||||
if (err) {
|
||||
dev_warn(dev, "Error %d reading Symbol firmware info. "
|
||||
"Wildly guessing capabilities...\n", err);
|
||||
@@ -262,6 +262,13 @@ int determine_fw_capabilities(struct orinoco_private *priv,
|
||||
if (fw_name)
|
||||
dev_info(dev, "Firmware determined as %s\n", fw_name);
|
||||
|
||||
#ifndef CONFIG_HERMES_PRISM
|
||||
if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
|
||||
dev_err(dev, "Support for Prism chipset is not enabled\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -279,8 +286,8 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
|
||||
u16 reclen;
|
||||
|
||||
/* Get the MAC address */
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
|
||||
ETH_ALEN, NULL, dev_addr);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
|
||||
ETH_ALEN, NULL, dev_addr);
|
||||
if (err) {
|
||||
dev_warn(dev, "Failed to read MAC address!\n");
|
||||
goto out;
|
||||
@@ -289,8 +296,8 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
|
||||
dev_dbg(dev, "MAC address %pM\n", dev_addr);
|
||||
|
||||
/* Get the station name */
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
|
||||
sizeof(nickbuf), &reclen, &nickbuf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
|
||||
sizeof(nickbuf), &reclen, &nickbuf);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to read station name\n");
|
||||
goto out;
|
||||
@@ -367,6 +374,32 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
|
||||
err = hermes_read_wordrec(hw, USER_BAP,
|
||||
HERMES_RID_CNFPREAMBLE_SYMBOL,
|
||||
&priv->preamble);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to read preamble setup\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Retry settings */
|
||||
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
|
||||
&priv->short_retry_limit);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to read short retry limit\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
|
||||
&priv->long_retry_limit);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to read long retry limit\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
|
||||
&priv->retry_lifetime);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to read max retry lifetime\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -380,11 +413,11 @@ int orinoco_hw_allocate_fid(struct orinoco_private *priv)
|
||||
struct hermes *hw = &priv->hw;
|
||||
int err;
|
||||
|
||||
err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
|
||||
err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
|
||||
if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
|
||||
/* Try workaround for old Symbol firmware bug */
|
||||
priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
|
||||
err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
|
||||
err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
|
||||
|
||||
dev_warn(dev, "Firmware ALLOC bug detected "
|
||||
"(old Symbol firmware?). Work around %s\n",
|
||||
@@ -430,8 +463,9 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
|
||||
struct hermes_idstring idbuf;
|
||||
|
||||
/* Set the MAC address */
|
||||
err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
|
||||
HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
|
||||
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
|
||||
HERMES_BYTES_TO_RECLEN(ETH_ALEN),
|
||||
dev->dev_addr);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Error %d setting MAC address\n",
|
||||
dev->name, err);
|
||||
@@ -494,7 +528,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
|
||||
idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
|
||||
memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
|
||||
/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
|
||||
err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
|
||||
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
|
||||
HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
|
||||
&idbuf);
|
||||
if (err) {
|
||||
@@ -502,7 +536,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
|
||||
dev->name, err);
|
||||
return err;
|
||||
}
|
||||
err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
|
||||
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
|
||||
HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
|
||||
&idbuf);
|
||||
if (err) {
|
||||
@@ -514,9 +548,9 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
|
||||
/* Set the station name */
|
||||
idbuf.len = cpu_to_le16(strlen(priv->nick));
|
||||
memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
|
||||
err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
|
||||
HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
|
||||
&idbuf);
|
||||
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
|
||||
HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
|
||||
&idbuf);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Error %d setting nickname\n",
|
||||
dev->name, err);
|
||||
@@ -631,12 +665,12 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
|
||||
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
|
||||
/* Enable monitor mode */
|
||||
dev->type = ARPHRD_IEEE80211;
|
||||
err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
|
||||
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
|
||||
HERMES_TEST_MONITOR, 0, NULL);
|
||||
} else {
|
||||
/* Disable monitor mode */
|
||||
dev->type = ARPHRD_ETHER;
|
||||
err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
|
||||
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
|
||||
HERMES_TEST_STOP, 0, NULL);
|
||||
}
|
||||
if (err)
|
||||
@@ -662,8 +696,8 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
|
||||
if ((key < 0) || (key >= 4))
|
||||
return -EINVAL;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
|
||||
sizeof(tsc_arr), NULL, &tsc_arr);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
|
||||
sizeof(tsc_arr), NULL, &tsc_arr);
|
||||
if (!err)
|
||||
memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
|
||||
|
||||
@@ -842,7 +876,7 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
|
||||
memcpy(key, priv->keys[i].key,
|
||||
priv->keys[i].key_len);
|
||||
|
||||
err = hermes_write_ltv(hw, USER_BAP,
|
||||
err = hw->ops->write_ltv(hw, USER_BAP,
|
||||
HERMES_RID_CNFDEFAULTKEY0 + i,
|
||||
HERMES_BYTES_TO_RECLEN(keylen),
|
||||
key);
|
||||
@@ -1049,17 +1083,17 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
|
||||
* group address if either we want to multicast, or if we were
|
||||
* multicasting and want to stop */
|
||||
if (!promisc && (mc_count || priv->mc_count)) {
|
||||
struct dev_mc_list *p;
|
||||
struct netdev_hw_addr *ha;
|
||||
struct hermes_multicast mclist;
|
||||
int i = 0;
|
||||
|
||||
netdev_for_each_mc_addr(p, dev) {
|
||||
netdev_for_each_mc_addr(ha, dev) {
|
||||
if (i == mc_count)
|
||||
break;
|
||||
memcpy(mclist.addr[i++], p->dmi_addr, ETH_ALEN);
|
||||
memcpy(mclist.addr[i++], ha->addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
err = hermes_write_ltv(hw, USER_BAP,
|
||||
err = hw->ops->write_ltv(hw, USER_BAP,
|
||||
HERMES_RID_CNFGROUPADDRESSES,
|
||||
HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
|
||||
&mclist);
|
||||
@@ -1101,15 +1135,15 @@ int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
|
||||
rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
|
||||
HERMES_RID_CNFDESIREDSSID;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
|
||||
NULL, &essidbuf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
|
||||
NULL, &essidbuf);
|
||||
if (err)
|
||||
goto fail_unlock;
|
||||
} else {
|
||||
*active = 0;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
|
||||
sizeof(essidbuf), NULL, &essidbuf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
|
||||
sizeof(essidbuf), NULL, &essidbuf);
|
||||
if (err)
|
||||
goto fail_unlock;
|
||||
}
|
||||
@@ -1180,8 +1214,8 @@ int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
|
||||
sizeof(list), NULL, &list);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
|
||||
sizeof(list), NULL, &list);
|
||||
orinoco_unlock(priv, &flags);
|
||||
|
||||
if (err)
|
||||
@@ -1248,7 +1282,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
|
||||
idbuf.len = cpu_to_le16(len);
|
||||
memcpy(idbuf.val, ssid->ssid, len);
|
||||
|
||||
err = hermes_write_ltv(hw, USER_BAP,
|
||||
err = hw->ops->write_ltv(hw, USER_BAP,
|
||||
HERMES_RID_CNFSCANSSID_AGERE,
|
||||
HERMES_BYTES_TO_RECLEN(len + 2),
|
||||
&idbuf);
|
||||
@@ -1312,8 +1346,8 @@ int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
|
||||
hermes_t *hw = &priv->hw;
|
||||
int err;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
|
||||
ETH_ALEN, NULL, addr);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
|
||||
ETH_ALEN, NULL, addr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@@ -22,7 +22,6 @@
|
||||
|
||||
/* Forward declarations */
|
||||
struct orinoco_private;
|
||||
struct dev_addr_list;
|
||||
|
||||
int determine_fw_capabilities(struct orinoco_private *priv, char *fw_name,
|
||||
size_t fw_name_len, u32 *hw_ver);
|
||||
|
@@ -254,7 +254,7 @@ void set_port_type(struct orinoco_private *priv)
|
||||
/* Device methods */
|
||||
/********************************************************************/
|
||||
|
||||
static int orinoco_open(struct net_device *dev)
|
||||
int orinoco_open(struct net_device *dev)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
unsigned long flags;
|
||||
@@ -272,8 +272,9 @@ static int orinoco_open(struct net_device *dev)
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_open);
|
||||
|
||||
static int orinoco_stop(struct net_device *dev)
|
||||
int orinoco_stop(struct net_device *dev)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
int err = 0;
|
||||
@@ -281,25 +282,27 @@ static int orinoco_stop(struct net_device *dev)
|
||||
/* We mustn't use orinoco_lock() here, because we need to be
|
||||
able to close the interface even if hw_unavailable is set
|
||||
(e.g. as we're released after a PC Card removal) */
|
||||
spin_lock_irq(&priv->lock);
|
||||
orinoco_lock_irq(priv);
|
||||
|
||||
priv->open = 0;
|
||||
|
||||
err = __orinoco_down(priv);
|
||||
|
||||
spin_unlock_irq(&priv->lock);
|
||||
orinoco_unlock_irq(priv);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_stop);
|
||||
|
||||
static struct net_device_stats *orinoco_get_stats(struct net_device *dev)
|
||||
struct net_device_stats *orinoco_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
|
||||
return &priv->stats;
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_get_stats);
|
||||
|
||||
static void orinoco_set_multicast_list(struct net_device *dev)
|
||||
void orinoco_set_multicast_list(struct net_device *dev)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
unsigned long flags;
|
||||
@@ -313,8 +316,9 @@ static void orinoco_set_multicast_list(struct net_device *dev)
|
||||
__orinoco_set_multicast_list(dev);
|
||||
orinoco_unlock(priv, &flags);
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_set_multicast_list);
|
||||
|
||||
static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
|
||||
int orinoco_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
|
||||
@@ -330,23 +334,115 @@ static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_change_mtu);
|
||||
|
||||
/********************************************************************/
|
||||
/* Tx path */
|
||||
/********************************************************************/
|
||||
|
||||
/* Add encapsulation and MIC to the existing SKB.
|
||||
* The main xmit routine will then send the whole lot to the card.
|
||||
* Need 8 bytes headroom
|
||||
* Need 8 bytes tailroom
|
||||
*
|
||||
* With encapsulated ethernet II frame
|
||||
* --------
|
||||
* 803.3 header (14 bytes)
|
||||
* dst[6]
|
||||
* -------- src[6]
|
||||
* 803.3 header (14 bytes) len[2]
|
||||
* dst[6] 803.2 header (8 bytes)
|
||||
* src[6] encaps[6]
|
||||
* len[2] <- leave alone -> len[2]
|
||||
* -------- -------- <-- 0
|
||||
* Payload Payload
|
||||
* ... ...
|
||||
*
|
||||
* -------- --------
|
||||
* MIC (8 bytes)
|
||||
* --------
|
||||
*
|
||||
* returns 0 on success, -ENOMEM on error.
|
||||
*/
|
||||
int orinoco_process_xmit_skb(struct sk_buff *skb,
|
||||
struct net_device *dev,
|
||||
struct orinoco_private *priv,
|
||||
int *tx_control,
|
||||
u8 *mic_buf)
|
||||
{
|
||||
struct orinoco_tkip_key *key;
|
||||
struct ethhdr *eh;
|
||||
int do_mic;
|
||||
|
||||
key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key;
|
||||
|
||||
do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) &&
|
||||
(key != NULL));
|
||||
|
||||
if (do_mic)
|
||||
*tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
|
||||
HERMES_TXCTRL_MIC;
|
||||
|
||||
eh = (struct ethhdr *)skb->data;
|
||||
|
||||
/* Encapsulate Ethernet-II frames */
|
||||
if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
|
||||
struct header_struct {
|
||||
struct ethhdr eth; /* 802.3 header */
|
||||
u8 encap[6]; /* 802.2 header */
|
||||
} __attribute__ ((packed)) hdr;
|
||||
int len = skb->len + sizeof(encaps_hdr) - (2 * ETH_ALEN);
|
||||
|
||||
if (skb_headroom(skb) < ENCAPS_OVERHEAD) {
|
||||
if (net_ratelimit())
|
||||
printk(KERN_ERR
|
||||
"%s: Not enough headroom for 802.2 headers %d\n",
|
||||
dev->name, skb_headroom(skb));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Fill in new header */
|
||||
memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
|
||||
hdr.eth.h_proto = htons(len);
|
||||
memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
|
||||
|
||||
/* Make room for the new header, and copy it in */
|
||||
eh = (struct ethhdr *) skb_push(skb, ENCAPS_OVERHEAD);
|
||||
memcpy(eh, &hdr, sizeof(hdr));
|
||||
}
|
||||
|
||||
/* Calculate Michael MIC */
|
||||
if (do_mic) {
|
||||
size_t len = skb->len - ETH_HLEN;
|
||||
u8 *mic = &mic_buf[0];
|
||||
|
||||
/* Have to write to an even address, so copy the spare
|
||||
* byte across */
|
||||
if (skb->len % 2) {
|
||||
*mic = skb->data[skb->len - 1];
|
||||
mic++;
|
||||
}
|
||||
|
||||
orinoco_mic(priv->tx_tfm_mic, key->tx_mic,
|
||||
eh->h_dest, eh->h_source, 0 /* priority */,
|
||||
skb->data + ETH_HLEN,
|
||||
len, mic);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_process_xmit_skb);
|
||||
|
||||
static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
struct net_device_stats *stats = &priv->stats;
|
||||
struct orinoco_tkip_key *key;
|
||||
hermes_t *hw = &priv->hw;
|
||||
int err = 0;
|
||||
u16 txfid = priv->txfid;
|
||||
struct ethhdr *eh;
|
||||
int tx_control;
|
||||
unsigned long flags;
|
||||
int do_mic;
|
||||
u8 mic_buf[MICHAEL_MIC_LEN+1];
|
||||
|
||||
if (!netif_running(dev)) {
|
||||
printk(KERN_ERR "%s: Tx on stopped device!\n",
|
||||
@@ -378,16 +474,12 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
if (skb->len < ETH_HLEN)
|
||||
goto drop;
|
||||
|
||||
key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key;
|
||||
|
||||
do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) &&
|
||||
(key != NULL));
|
||||
|
||||
tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
|
||||
|
||||
if (do_mic)
|
||||
tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
|
||||
HERMES_TXCTRL_MIC;
|
||||
err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control,
|
||||
&mic_buf[0]);
|
||||
if (err)
|
||||
goto drop;
|
||||
|
||||
if (priv->has_alt_txcntl) {
|
||||
/* WPA enabled firmwares have tx_cntl at the end of
|
||||
@@ -400,8 +492,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
*txcntl = cpu_to_le16(tx_control);
|
||||
err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
|
||||
txfid, 0);
|
||||
err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
|
||||
txfid, 0);
|
||||
if (err) {
|
||||
if (net_ratelimit())
|
||||
printk(KERN_ERR "%s: Error %d writing Tx "
|
||||
@@ -414,8 +506,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
desc.tx_control = cpu_to_le16(tx_control);
|
||||
err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
|
||||
txfid, 0);
|
||||
err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
|
||||
txfid, 0);
|
||||
if (err) {
|
||||
if (net_ratelimit())
|
||||
printk(KERN_ERR "%s: Error %d writing Tx "
|
||||
@@ -430,68 +522,24 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
|
||||
}
|
||||
|
||||
eh = (struct ethhdr *)skb->data;
|
||||
|
||||
/* Encapsulate Ethernet-II frames */
|
||||
if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
|
||||
struct header_struct {
|
||||
struct ethhdr eth; /* 802.3 header */
|
||||
u8 encap[6]; /* 802.2 header */
|
||||
} __attribute__ ((packed)) hdr;
|
||||
|
||||
/* Strip destination and source from the data */
|
||||
skb_pull(skb, 2 * ETH_ALEN);
|
||||
|
||||
/* And move them to a separate header */
|
||||
memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
|
||||
hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);
|
||||
memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
|
||||
|
||||
/* Insert the SNAP header */
|
||||
if (skb_headroom(skb) < sizeof(hdr)) {
|
||||
printk(KERN_ERR
|
||||
"%s: Not enough headroom for 802.2 headers %d\n",
|
||||
dev->name, skb_headroom(skb));
|
||||
goto drop;
|
||||
}
|
||||
eh = (struct ethhdr *) skb_push(skb, sizeof(hdr));
|
||||
memcpy(eh, &hdr, sizeof(hdr));
|
||||
}
|
||||
|
||||
err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
|
||||
txfid, HERMES_802_3_OFFSET);
|
||||
err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len,
|
||||
txfid, HERMES_802_3_OFFSET);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
|
||||
dev->name, err);
|
||||
goto busy;
|
||||
}
|
||||
|
||||
/* Calculate Michael MIC */
|
||||
if (do_mic) {
|
||||
u8 mic_buf[MICHAEL_MIC_LEN + 1];
|
||||
u8 *mic;
|
||||
size_t offset;
|
||||
size_t len;
|
||||
if (tx_control & HERMES_TXCTRL_MIC) {
|
||||
size_t offset = HERMES_802_3_OFFSET + skb->len;
|
||||
size_t len = MICHAEL_MIC_LEN;
|
||||
|
||||
if (skb->len % 2) {
|
||||
/* MIC start is on an odd boundary */
|
||||
mic_buf[0] = skb->data[skb->len - 1];
|
||||
mic = &mic_buf[1];
|
||||
offset = skb->len - 1;
|
||||
len = MICHAEL_MIC_LEN + 1;
|
||||
} else {
|
||||
mic = &mic_buf[0];
|
||||
offset = skb->len;
|
||||
len = MICHAEL_MIC_LEN;
|
||||
if (offset % 2) {
|
||||
offset--;
|
||||
len++;
|
||||
}
|
||||
|
||||
orinoco_mic(priv->tx_tfm_mic, key->tx_mic,
|
||||
eh->h_dest, eh->h_source, 0 /* priority */,
|
||||
skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
|
||||
|
||||
/* Write the MIC */
|
||||
err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
|
||||
txfid, HERMES_802_3_OFFSET + offset);
|
||||
err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
|
||||
txfid, offset);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
|
||||
dev->name, err);
|
||||
@@ -502,7 +550,7 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
/* Finally, we actually initiate the send */
|
||||
netif_stop_queue(dev);
|
||||
|
||||
err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
|
||||
err = hw->ops->cmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
|
||||
txfid, NULL);
|
||||
if (err) {
|
||||
netif_start_queue(dev);
|
||||
@@ -512,7 +560,6 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
goto busy;
|
||||
}
|
||||
|
||||
dev->trans_start = jiffies;
|
||||
stats->tx_bytes += HERMES_802_3_OFFSET + skb->len;
|
||||
goto ok;
|
||||
|
||||
@@ -572,9 +619,9 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
|
||||
return; /* Nothing's really happened */
|
||||
|
||||
/* Read part of the frame header - we need status and addr1 */
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
|
||||
sizeof(struct hermes_txexc_data),
|
||||
fid, 0);
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, &hdr,
|
||||
sizeof(struct hermes_txexc_data),
|
||||
fid, 0);
|
||||
|
||||
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
|
||||
stats->tx_errors++;
|
||||
@@ -615,7 +662,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
static void orinoco_tx_timeout(struct net_device *dev)
|
||||
void orinoco_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
struct net_device_stats *stats = &priv->stats;
|
||||
@@ -630,6 +677,7 @@ static void orinoco_tx_timeout(struct net_device *dev)
|
||||
|
||||
schedule_work(&priv->reset_work);
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_tx_timeout);
|
||||
|
||||
/********************************************************************/
|
||||
/* Rx path (data frames) */
|
||||
@@ -764,9 +812,9 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
|
||||
|
||||
/* If any, copy the data from the card to the skb */
|
||||
if (datalen > 0) {
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
|
||||
ALIGN(datalen, 2), rxfid,
|
||||
HERMES_802_2_OFFSET);
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
|
||||
ALIGN(datalen, 2), rxfid,
|
||||
HERMES_802_2_OFFSET);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: error %d reading monitor frame\n",
|
||||
dev->name, err);
|
||||
@@ -792,7 +840,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
|
||||
stats->rx_dropped++;
|
||||
}
|
||||
|
||||
static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
|
||||
void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
struct net_device_stats *stats = &priv->stats;
|
||||
@@ -814,8 +862,8 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
|
||||
|
||||
rxfid = hermes_read_regn(hw, RXFID);
|
||||
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, desc, sizeof(*desc),
|
||||
rxfid, 0);
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, desc, sizeof(*desc),
|
||||
rxfid, 0);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: error %d reading Rx descriptor. "
|
||||
"Frame dropped.\n", dev->name, err);
|
||||
@@ -882,9 +930,9 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
|
||||
nothing is removed. 2 is for aligning the IP header. */
|
||||
skb_reserve(skb, ETH_HLEN + 2);
|
||||
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),
|
||||
ALIGN(length, 2), rxfid,
|
||||
HERMES_802_2_OFFSET);
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, length),
|
||||
ALIGN(length, 2), rxfid,
|
||||
HERMES_802_2_OFFSET);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: error %d reading frame. "
|
||||
"Frame dropped.\n", dev->name, err);
|
||||
@@ -913,6 +961,7 @@ update_stats:
|
||||
out:
|
||||
kfree(desc);
|
||||
}
|
||||
EXPORT_SYMBOL(__orinoco_ev_rx);
|
||||
|
||||
static void orinoco_rx(struct net_device *dev,
|
||||
struct hermes_rx_descriptor *desc,
|
||||
@@ -1145,9 +1194,9 @@ static void orinoco_join_ap(struct work_struct *work)
|
||||
goto out;
|
||||
|
||||
/* Read scan results from the firmware */
|
||||
err = hermes_read_ltv(hw, USER_BAP,
|
||||
HERMES_RID_SCANRESULTSTABLE,
|
||||
MAX_SCAN_LEN, &len, buf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP,
|
||||
HERMES_RID_SCANRESULTSTABLE,
|
||||
MAX_SCAN_LEN, &len, buf);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Cannot read scan results\n",
|
||||
dev->name);
|
||||
@@ -1194,8 +1243,8 @@ static void orinoco_send_bssid_wevent(struct orinoco_private *priv)
|
||||
union iwreq_data wrqu;
|
||||
int err;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
|
||||
ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
|
||||
ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
|
||||
if (err != 0)
|
||||
return;
|
||||
|
||||
@@ -1217,8 +1266,8 @@ static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)
|
||||
if (!priv->has_wpa)
|
||||
return;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
|
||||
sizeof(buf), NULL, &buf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
|
||||
sizeof(buf), NULL, &buf);
|
||||
if (err != 0)
|
||||
return;
|
||||
|
||||
@@ -1247,8 +1296,9 @@ static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)
|
||||
if (!priv->has_wpa)
|
||||
return;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO,
|
||||
sizeof(buf), NULL, &buf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP,
|
||||
HERMES_RID_CURRENT_ASSOC_RESP_INFO,
|
||||
sizeof(buf), NULL, &buf);
|
||||
if (err != 0)
|
||||
return;
|
||||
|
||||
@@ -1353,7 +1403,7 @@ static void orinoco_process_scan_results(struct work_struct *work)
|
||||
spin_unlock_irqrestore(&priv->scan_lock, flags);
|
||||
}
|
||||
|
||||
static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
u16 infofid;
|
||||
@@ -1371,8 +1421,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
infofid = hermes_read_regn(hw, INFOFID);
|
||||
|
||||
/* Read the info frame header - don't try too hard */
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
|
||||
infofid, 0);
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, &info, sizeof(info),
|
||||
infofid, 0);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: error %d reading info frame. "
|
||||
"Frame dropped.\n", dev->name, err);
|
||||
@@ -1393,8 +1443,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
len = sizeof(tallies);
|
||||
}
|
||||
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len,
|
||||
infofid, sizeof(info));
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, &tallies, len,
|
||||
infofid, sizeof(info));
|
||||
if (err)
|
||||
break;
|
||||
|
||||
@@ -1429,8 +1479,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
break;
|
||||
}
|
||||
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len,
|
||||
infofid, sizeof(info));
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, &linkstatus, len,
|
||||
infofid, sizeof(info));
|
||||
if (err)
|
||||
break;
|
||||
newstatus = le16_to_cpu(linkstatus.linkstatus);
|
||||
@@ -1494,8 +1544,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
}
|
||||
|
||||
/* Read scan data */
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
|
||||
infofid, sizeof(info));
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) buf, len,
|
||||
infofid, sizeof(info));
|
||||
if (err) {
|
||||
kfree(buf);
|
||||
qabort_scan(priv);
|
||||
@@ -1547,8 +1597,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
break;
|
||||
|
||||
/* Read scan data */
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len,
|
||||
infofid, sizeof(info));
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) bss, len,
|
||||
infofid, sizeof(info));
|
||||
if (err)
|
||||
kfree(bss);
|
||||
else
|
||||
@@ -1568,9 +1618,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
/* We don't actually do anything about it */
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(__orinoco_ev_info);
|
||||
|
||||
static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
|
||||
{
|
||||
@@ -1647,7 +1696,7 @@ static int orinoco_reinit_firmware(struct orinoco_private *priv)
|
||||
struct hermes *hw = &priv->hw;
|
||||
int err;
|
||||
|
||||
err = hermes_init(hw);
|
||||
err = hw->ops->init(hw);
|
||||
if (priv->do_fw_download && !err) {
|
||||
err = orinoco_download(priv);
|
||||
if (err)
|
||||
@@ -1735,7 +1784,7 @@ void orinoco_reset(struct work_struct *work)
|
||||
}
|
||||
|
||||
/* This has to be called from user context */
|
||||
spin_lock_irq(&priv->lock);
|
||||
orinoco_lock_irq(priv);
|
||||
|
||||
priv->hw_unavailable--;
|
||||
|
||||
@@ -1750,7 +1799,7 @@ void orinoco_reset(struct work_struct *work)
|
||||
dev->trans_start = jiffies;
|
||||
}
|
||||
|
||||
spin_unlock_irq(&priv->lock);
|
||||
orinoco_unlock_irq(priv);
|
||||
|
||||
return;
|
||||
disable:
|
||||
@@ -1984,7 +2033,7 @@ int orinoco_init(struct orinoco_private *priv)
|
||||
priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN;
|
||||
|
||||
/* Initialize the firmware */
|
||||
err = hermes_init(hw);
|
||||
err = hw->ops->init(hw);
|
||||
if (err != 0) {
|
||||
dev_err(dev, "Failed to initialize firmware (err = %d)\n",
|
||||
err);
|
||||
@@ -2067,9 +2116,9 @@ int orinoco_init(struct orinoco_private *priv)
|
||||
|
||||
/* Make the hardware available, as long as it hasn't been
|
||||
* removed elsewhere (e.g. by PCMCIA hot unplug) */
|
||||
spin_lock_irq(&priv->lock);
|
||||
orinoco_lock_irq(priv);
|
||||
priv->hw_unavailable--;
|
||||
spin_unlock_irq(&priv->lock);
|
||||
orinoco_unlock_irq(priv);
|
||||
|
||||
dev_dbg(dev, "Ready\n");
|
||||
|
||||
@@ -2192,7 +2241,8 @@ EXPORT_SYMBOL(alloc_orinocodev);
|
||||
*/
|
||||
int orinoco_if_add(struct orinoco_private *priv,
|
||||
unsigned long base_addr,
|
||||
unsigned int irq)
|
||||
unsigned int irq,
|
||||
const struct net_device_ops *ops)
|
||||
{
|
||||
struct wiphy *wiphy = priv_to_wiphy(priv);
|
||||
struct wireless_dev *wdev;
|
||||
@@ -2211,16 +2261,21 @@ int orinoco_if_add(struct orinoco_private *priv,
|
||||
|
||||
/* Setup / override net_device fields */
|
||||
dev->ieee80211_ptr = wdev;
|
||||
dev->netdev_ops = &orinoco_netdev_ops;
|
||||
dev->watchdog_timeo = HZ; /* 1 second timeout */
|
||||
dev->wireless_handlers = &orinoco_handler_def;
|
||||
#ifdef WIRELESS_SPY
|
||||
dev->wireless_data = &priv->wireless_data;
|
||||
#endif
|
||||
/* Default to standard ops if not set */
|
||||
if (ops)
|
||||
dev->netdev_ops = ops;
|
||||
else
|
||||
dev->netdev_ops = &orinoco_netdev_ops;
|
||||
|
||||
/* we use the default eth_mac_addr for setting the MAC addr */
|
||||
|
||||
/* Reserve space in skb for the SNAP header */
|
||||
dev->hard_header_len += ENCAPS_OVERHEAD;
|
||||
dev->needed_headroom = ENCAPS_OVERHEAD;
|
||||
|
||||
netif_carrier_off(dev);
|
||||
|
||||
@@ -2305,7 +2360,7 @@ int orinoco_up(struct orinoco_private *priv)
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, &flags);
|
||||
|
||||
err = orinoco_reinit_firmware(priv);
|
||||
if (err) {
|
||||
@@ -2325,7 +2380,7 @@ int orinoco_up(struct orinoco_private *priv)
|
||||
}
|
||||
|
||||
exit:
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2337,7 +2392,7 @@ void orinoco_down(struct orinoco_private *priv)
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, &flags);
|
||||
err = __orinoco_down(priv);
|
||||
if (err)
|
||||
printk(KERN_WARNING "%s: Error %d downing interface\n",
|
||||
@@ -2345,7 +2400,7 @@ void orinoco_down(struct orinoco_private *priv)
|
||||
|
||||
netif_device_detach(dev);
|
||||
priv->hw_unavailable++;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_down);
|
||||
|
||||
|
@@ -33,18 +33,6 @@ int orinoco_commit(struct orinoco_private *priv);
|
||||
void orinoco_reset(struct work_struct *work);
|
||||
|
||||
/* Information element helpers - find a home for these... */
|
||||
static inline u8 *orinoco_get_ie(u8 *data, size_t len,
|
||||
enum ieee80211_eid eid)
|
||||
{
|
||||
u8 *p = data;
|
||||
while ((p + 2) < (data + len)) {
|
||||
if (p[0] == eid)
|
||||
return p;
|
||||
p += p[1] + 2;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define WPA_OUI_TYPE "\x00\x50\xF2\x01"
|
||||
#define WPA_SELECTOR_LEN 4
|
||||
static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)
|
||||
|
@@ -131,6 +131,8 @@ struct orinoco_private {
|
||||
u16 ap_density, rts_thresh;
|
||||
u16 pm_on, pm_mcast, pm_period, pm_timeout;
|
||||
u16 preamble;
|
||||
u16 short_retry_limit, long_retry_limit;
|
||||
u16 retry_lifetime;
|
||||
#ifdef WIRELESS_SPY
|
||||
struct iw_spy_data spy_data; /* iwspy support */
|
||||
struct iw_public_data wireless_data;
|
||||
@@ -188,12 +190,30 @@ extern void free_orinocodev(struct orinoco_private *priv);
|
||||
extern int orinoco_init(struct orinoco_private *priv);
|
||||
extern int orinoco_if_add(struct orinoco_private *priv,
|
||||
unsigned long base_addr,
|
||||
unsigned int irq);
|
||||
unsigned int irq,
|
||||
const struct net_device_ops *ops);
|
||||
extern void orinoco_if_del(struct orinoco_private *priv);
|
||||
extern int orinoco_up(struct orinoco_private *priv);
|
||||
extern void orinoco_down(struct orinoco_private *priv);
|
||||
extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
|
||||
|
||||
extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);
|
||||
extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);
|
||||
|
||||
int orinoco_process_xmit_skb(struct sk_buff *skb,
|
||||
struct net_device *dev,
|
||||
struct orinoco_private *priv,
|
||||
int *tx_control,
|
||||
u8 *mic);
|
||||
|
||||
/* Common ndo functions exported for reuse by orinoco_usb */
|
||||
int orinoco_open(struct net_device *dev);
|
||||
int orinoco_stop(struct net_device *dev);
|
||||
struct net_device_stats *orinoco_get_stats(struct net_device *dev);
|
||||
void orinoco_set_multicast_list(struct net_device *dev);
|
||||
int orinoco_change_mtu(struct net_device *dev, int new_mtu);
|
||||
void orinoco_tx_timeout(struct net_device *dev);
|
||||
|
||||
/********************************************************************/
|
||||
/* Locking and synchronization functions */
|
||||
/********************************************************************/
|
||||
@@ -201,11 +221,11 @@ extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
|
||||
static inline int orinoco_lock(struct orinoco_private *priv,
|
||||
unsigned long *flags)
|
||||
{
|
||||
spin_lock_irqsave(&priv->lock, *flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, flags);
|
||||
if (priv->hw_unavailable) {
|
||||
DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n",
|
||||
priv->ndev);
|
||||
spin_unlock_irqrestore(&priv->lock, *flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
return 0;
|
||||
@@ -214,7 +234,17 @@ static inline int orinoco_lock(struct orinoco_private *priv,
|
||||
static inline void orinoco_unlock(struct orinoco_private *priv,
|
||||
unsigned long *flags)
|
||||
{
|
||||
spin_unlock_irqrestore(&priv->lock, *flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
static inline void orinoco_lock_irq(struct orinoco_private *priv)
|
||||
{
|
||||
priv->hw.ops->lock_irq(&priv->lock);
|
||||
}
|
||||
|
||||
static inline void orinoco_unlock_irq(struct orinoco_private *priv)
|
||||
{
|
||||
priv->hw.ops->unlock_irq(&priv->lock);
|
||||
}
|
||||
|
||||
/*** Navigate from net_device to orinoco_private ***/
|
||||
|
@@ -281,7 +281,7 @@ orinoco_cs_config(struct pcmcia_device *link)
|
||||
|
||||
/* Register an interface with the stack */
|
||||
if (orinoco_if_add(priv, link->io.BasePort1,
|
||||
link->irq) != 0) {
|
||||
link->irq, NULL) != 0) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto failed;
|
||||
}
|
||||
@@ -306,9 +306,9 @@ orinoco_cs_release(struct pcmcia_device *link)
|
||||
|
||||
/* We're committed to taking the device away now, so mark the
|
||||
* hardware as unavailable */
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, &flags);
|
||||
priv->hw_unavailable++;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
|
||||
|
||||
pcmcia_disable_device(link);
|
||||
if (priv->hw.iobase)
|
||||
@@ -353,87 +353,90 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
|
||||
"Pavel Roskin <proski@gnu.org>, et al)";
|
||||
|
||||
static struct pcmcia_device_id orinoco_cs_ids[] = {
|
||||
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
|
||||
PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
|
||||
PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
|
||||
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
|
||||
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
|
||||
PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
|
||||
PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
|
||||
PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
|
||||
PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
|
||||
PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
|
||||
PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
|
||||
PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
|
||||
PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
|
||||
PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
|
||||
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
|
||||
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
|
||||
PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
|
||||
PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
|
||||
PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
|
||||
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
|
||||
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
|
||||
PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
|
||||
PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
|
||||
#ifdef CONFIG_HERMES_PRISM
|
||||
/* Only entries that certainly identify Prism chipset */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
|
||||
PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
|
||||
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
|
||||
PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
|
||||
PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
|
||||
PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
|
||||
PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
|
||||
PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
|
||||
PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
|
||||
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
|
||||
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
|
||||
PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
|
||||
PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
|
||||
PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
|
||||
PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
|
||||
PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
|
||||
PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
|
||||
PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
|
||||
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
|
||||
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
|
||||
PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
|
||||
PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
|
||||
PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
|
||||
PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
|
||||
PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
|
||||
PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
|
||||
PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
|
||||
PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
|
||||
PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
|
||||
PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
|
||||
PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
|
||||
PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
|
||||
PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
|
||||
PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
|
||||
PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
|
||||
PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
|
||||
PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
|
||||
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
|
||||
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
|
||||
PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
|
||||
PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
|
||||
PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
|
||||
PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
|
||||
PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
|
||||
PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
|
||||
PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
|
||||
PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
|
||||
PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
|
||||
PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
|
||||
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
|
||||
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
|
||||
PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
|
||||
PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
|
||||
PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
|
||||
PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
|
||||
PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
|
||||
PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39),
|
||||
#endif
|
||||
PCMCIA_DEVICE_NULL,
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
|
||||
|
@@ -220,7 +220,7 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = orinoco_if_add(priv, 0, 0);
|
||||
err = orinoco_if_add(priv, 0, 0, NULL);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto fail;
|
||||
|
@@ -170,7 +170,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = orinoco_if_add(priv, 0, 0);
|
||||
err = orinoco_if_add(priv, 0, 0, NULL);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto fail;
|
||||
|
@@ -259,7 +259,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = orinoco_if_add(priv, 0, 0);
|
||||
err = orinoco_if_add(priv, 0, 0, NULL);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto fail;
|
||||
|
@@ -156,7 +156,7 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = orinoco_if_add(priv, 0, 0);
|
||||
err = orinoco_if_add(priv, 0, 0, NULL);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto fail;
|
||||
|
1795
drivers/net/wireless/orinoco/orinoco_usb.c
Normal file
1795
drivers/net/wireless/orinoco/orinoco_usb.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -127,7 +127,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,
|
||||
{
|
||||
struct wiphy *wiphy = priv_to_wiphy(priv);
|
||||
struct ieee80211_channel *channel;
|
||||
u8 *ie;
|
||||
const u8 *ie;
|
||||
u64 timestamp;
|
||||
s32 signal;
|
||||
u16 capability;
|
||||
@@ -136,7 +136,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,
|
||||
int chan, freq;
|
||||
|
||||
ie_len = len - sizeof(*bss);
|
||||
ie = orinoco_get_ie(bss->data, ie_len, WLAN_EID_DS_PARAMS);
|
||||
ie = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bss->data, ie_len);
|
||||
chan = ie ? ie[2] : 0;
|
||||
freq = ieee80211_dsss_chan_to_freq(chan);
|
||||
channel = ieee80211_get_channel(wiphy, freq);
|
||||
|
@@ -337,6 +337,7 @@ spectrum_cs_config(struct pcmcia_device *link)
|
||||
goto failed;
|
||||
|
||||
hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
|
||||
hw->eeprom_pda = true;
|
||||
|
||||
/*
|
||||
* This actually configures the PCMCIA socket -- setting up
|
||||
@@ -359,7 +360,7 @@ spectrum_cs_config(struct pcmcia_device *link)
|
||||
|
||||
/* Register an interface with the stack */
|
||||
if (orinoco_if_add(priv, link->io.BasePort1,
|
||||
link->irq) != 0) {
|
||||
link->irq, NULL) != 0) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto failed;
|
||||
}
|
||||
@@ -384,9 +385,9 @@ spectrum_cs_release(struct pcmcia_device *link)
|
||||
|
||||
/* We're committed to taking the device away now, so mark the
|
||||
* hardware as unavailable */
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, &flags);
|
||||
priv->hw_unavailable++;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
|
||||
|
||||
pcmcia_disable_device(link);
|
||||
if (priv->hw.iobase)
|
||||
|
@@ -458,7 +458,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
|
||||
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
|
||||
/* Fast channel change - no commit if successful */
|
||||
hermes_t *hw = &priv->hw;
|
||||
err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
|
||||
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
|
||||
HERMES_TEST_SET_CHANNEL,
|
||||
chan, NULL);
|
||||
}
|
||||
@@ -538,125 +538,6 @@ static int orinoco_ioctl_setsens(struct net_device *dev,
|
||||
return -EINPROGRESS; /* Call commit handler */
|
||||
}
|
||||
|
||||
static int orinoco_ioctl_setrts(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *rrq,
|
||||
char *extra)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
int val = rrq->value;
|
||||
unsigned long flags;
|
||||
|
||||
if (rrq->disabled)
|
||||
val = 2347;
|
||||
|
||||
if ((val < 0) || (val > 2347))
|
||||
return -EINVAL;
|
||||
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
priv->rts_thresh = val;
|
||||
orinoco_unlock(priv, &flags);
|
||||
|
||||
return -EINPROGRESS; /* Call commit handler */
|
||||
}
|
||||
|
||||
static int orinoco_ioctl_getrts(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *rrq,
|
||||
char *extra)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
|
||||
rrq->value = priv->rts_thresh;
|
||||
rrq->disabled = (rrq->value == 2347);
|
||||
rrq->fixed = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int orinoco_ioctl_setfrag(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *frq,
|
||||
char *extra)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
int err = -EINPROGRESS; /* Call commit handler */
|
||||
unsigned long flags;
|
||||
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
if (priv->has_mwo) {
|
||||
if (frq->disabled)
|
||||
priv->mwo_robust = 0;
|
||||
else {
|
||||
if (frq->fixed)
|
||||
printk(KERN_WARNING "%s: Fixed fragmentation "
|
||||
"is not supported on this firmware. "
|
||||
"Using MWO robust instead.\n",
|
||||
dev->name);
|
||||
priv->mwo_robust = 1;
|
||||
}
|
||||
} else {
|
||||
if (frq->disabled)
|
||||
priv->frag_thresh = 2346;
|
||||
else {
|
||||
if ((frq->value < 256) || (frq->value > 2346))
|
||||
err = -EINVAL;
|
||||
else
|
||||
/* must be even */
|
||||
priv->frag_thresh = frq->value & ~0x1;
|
||||
}
|
||||
}
|
||||
|
||||
orinoco_unlock(priv, &flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int orinoco_ioctl_getfrag(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *frq,
|
||||
char *extra)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
hermes_t *hw = &priv->hw;
|
||||
int err;
|
||||
u16 val;
|
||||
unsigned long flags;
|
||||
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
if (priv->has_mwo) {
|
||||
err = hermes_read_wordrec(hw, USER_BAP,
|
||||
HERMES_RID_CNFMWOROBUST_AGERE,
|
||||
&val);
|
||||
if (err)
|
||||
val = 0;
|
||||
|
||||
frq->value = val ? 2347 : 0;
|
||||
frq->disabled = !val;
|
||||
frq->fixed = 0;
|
||||
} else {
|
||||
err = hermes_read_wordrec(hw, USER_BAP,
|
||||
HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
|
||||
&val);
|
||||
if (err)
|
||||
val = 0;
|
||||
|
||||
frq->value = val;
|
||||
frq->disabled = (val >= 2346);
|
||||
frq->fixed = 1;
|
||||
}
|
||||
|
||||
orinoco_unlock(priv, &flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int orinoco_ioctl_setrate(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *rrq,
|
||||
@@ -1201,60 +1082,6 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int orinoco_ioctl_getretry(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *rrq,
|
||||
char *extra)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
hermes_t *hw = &priv->hw;
|
||||
int err = 0;
|
||||
u16 short_limit, long_limit, lifetime;
|
||||
unsigned long flags;
|
||||
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
|
||||
&short_limit);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
|
||||
&long_limit);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
|
||||
&lifetime);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
rrq->disabled = 0; /* Can't be disabled */
|
||||
|
||||
/* Note : by default, display the retry number */
|
||||
if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
|
||||
rrq->flags = IW_RETRY_LIFETIME;
|
||||
rrq->value = lifetime * 1000; /* ??? */
|
||||
} else {
|
||||
/* By default, display the min number */
|
||||
if ((rrq->flags & IW_RETRY_LONG)) {
|
||||
rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
|
||||
rrq->value = long_limit;
|
||||
} else {
|
||||
rrq->flags = IW_RETRY_LIMIT;
|
||||
rrq->value = short_limit;
|
||||
if (short_limit != long_limit)
|
||||
rrq->flags |= IW_RETRY_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
orinoco_unlock(priv, &flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int orinoco_ioctl_reset(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
void *wrqu,
|
||||
@@ -1446,8 +1273,8 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
|
||||
extra);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
|
||||
extra);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -1506,46 +1333,44 @@ static const struct iw_priv_args orinoco_privtab[] = {
|
||||
* Structures to export the Wireless Handlers
|
||||
*/
|
||||
|
||||
#define STD_IW_HANDLER(id, func) \
|
||||
[IW_IOCTL_IDX(id)] = (iw_handler) func
|
||||
static const iw_handler orinoco_handler[] = {
|
||||
STD_IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit),
|
||||
STD_IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname),
|
||||
STD_IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq),
|
||||
STD_IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq),
|
||||
STD_IW_HANDLER(SIOCSIWMODE, cfg80211_wext_siwmode),
|
||||
STD_IW_HANDLER(SIOCGIWMODE, cfg80211_wext_giwmode),
|
||||
STD_IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens),
|
||||
STD_IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens),
|
||||
STD_IW_HANDLER(SIOCGIWRANGE, cfg80211_wext_giwrange),
|
||||
STD_IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
|
||||
STD_IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
|
||||
STD_IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
|
||||
STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
|
||||
STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap),
|
||||
STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap),
|
||||
STD_IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan),
|
||||
STD_IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan),
|
||||
STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid),
|
||||
STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid),
|
||||
STD_IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate),
|
||||
STD_IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate),
|
||||
STD_IW_HANDLER(SIOCSIWRTS, orinoco_ioctl_setrts),
|
||||
STD_IW_HANDLER(SIOCGIWRTS, orinoco_ioctl_getrts),
|
||||
STD_IW_HANDLER(SIOCSIWFRAG, orinoco_ioctl_setfrag),
|
||||
STD_IW_HANDLER(SIOCGIWFRAG, orinoco_ioctl_getfrag),
|
||||
STD_IW_HANDLER(SIOCGIWRETRY, orinoco_ioctl_getretry),
|
||||
STD_IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode),
|
||||
STD_IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode),
|
||||
STD_IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower),
|
||||
STD_IW_HANDLER(SIOCGIWPOWER, orinoco_ioctl_getpower),
|
||||
STD_IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie),
|
||||
STD_IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie),
|
||||
STD_IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme),
|
||||
STD_IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth),
|
||||
STD_IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth),
|
||||
STD_IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext),
|
||||
STD_IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext),
|
||||
IW_HANDLER(SIOCSIWCOMMIT, (iw_handler)orinoco_ioctl_commit),
|
||||
IW_HANDLER(SIOCGIWNAME, (iw_handler)cfg80211_wext_giwname),
|
||||
IW_HANDLER(SIOCSIWFREQ, (iw_handler)orinoco_ioctl_setfreq),
|
||||
IW_HANDLER(SIOCGIWFREQ, (iw_handler)orinoco_ioctl_getfreq),
|
||||
IW_HANDLER(SIOCSIWMODE, (iw_handler)cfg80211_wext_siwmode),
|
||||
IW_HANDLER(SIOCGIWMODE, (iw_handler)cfg80211_wext_giwmode),
|
||||
IW_HANDLER(SIOCSIWSENS, (iw_handler)orinoco_ioctl_setsens),
|
||||
IW_HANDLER(SIOCGIWSENS, (iw_handler)orinoco_ioctl_getsens),
|
||||
IW_HANDLER(SIOCGIWRANGE, (iw_handler)cfg80211_wext_giwrange),
|
||||
IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
|
||||
IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
|
||||
IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
|
||||
IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
|
||||
IW_HANDLER(SIOCSIWAP, (iw_handler)orinoco_ioctl_setwap),
|
||||
IW_HANDLER(SIOCGIWAP, (iw_handler)orinoco_ioctl_getwap),
|
||||
IW_HANDLER(SIOCSIWSCAN, (iw_handler)cfg80211_wext_siwscan),
|
||||
IW_HANDLER(SIOCGIWSCAN, (iw_handler)cfg80211_wext_giwscan),
|
||||
IW_HANDLER(SIOCSIWESSID, (iw_handler)orinoco_ioctl_setessid),
|
||||
IW_HANDLER(SIOCGIWESSID, (iw_handler)orinoco_ioctl_getessid),
|
||||
IW_HANDLER(SIOCSIWRATE, (iw_handler)orinoco_ioctl_setrate),
|
||||
IW_HANDLER(SIOCGIWRATE, (iw_handler)orinoco_ioctl_getrate),
|
||||
IW_HANDLER(SIOCSIWRTS, (iw_handler)cfg80211_wext_siwrts),
|
||||
IW_HANDLER(SIOCGIWRTS, (iw_handler)cfg80211_wext_giwrts),
|
||||
IW_HANDLER(SIOCSIWFRAG, (iw_handler)cfg80211_wext_siwfrag),
|
||||
IW_HANDLER(SIOCGIWFRAG, (iw_handler)cfg80211_wext_giwfrag),
|
||||
IW_HANDLER(SIOCGIWRETRY, (iw_handler)cfg80211_wext_giwretry),
|
||||
IW_HANDLER(SIOCSIWENCODE, (iw_handler)orinoco_ioctl_setiwencode),
|
||||
IW_HANDLER(SIOCGIWENCODE, (iw_handler)orinoco_ioctl_getiwencode),
|
||||
IW_HANDLER(SIOCSIWPOWER, (iw_handler)orinoco_ioctl_setpower),
|
||||
IW_HANDLER(SIOCGIWPOWER, (iw_handler)orinoco_ioctl_getpower),
|
||||
IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie),
|
||||
IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie),
|
||||
IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme),
|
||||
IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth),
|
||||
IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth),
|
||||
IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext),
|
||||
IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext),
|
||||
};
|
||||
|
||||
|
||||
@@ -1553,15 +1378,15 @@ static const iw_handler orinoco_handler[] = {
|
||||
Added typecasting since we no longer use iwreq_data -- Moustafa
|
||||
*/
|
||||
static const iw_handler orinoco_private_handler[] = {
|
||||
[0] = (iw_handler) orinoco_ioctl_reset,
|
||||
[1] = (iw_handler) orinoco_ioctl_reset,
|
||||
[2] = (iw_handler) orinoco_ioctl_setport3,
|
||||
[3] = (iw_handler) orinoco_ioctl_getport3,
|
||||
[4] = (iw_handler) orinoco_ioctl_setpreamble,
|
||||
[5] = (iw_handler) orinoco_ioctl_getpreamble,
|
||||
[6] = (iw_handler) orinoco_ioctl_setibssport,
|
||||
[7] = (iw_handler) orinoco_ioctl_getibssport,
|
||||
[9] = (iw_handler) orinoco_ioctl_getrid,
|
||||
[0] = (iw_handler)orinoco_ioctl_reset,
|
||||
[1] = (iw_handler)orinoco_ioctl_reset,
|
||||
[2] = (iw_handler)orinoco_ioctl_setport3,
|
||||
[3] = (iw_handler)orinoco_ioctl_getport3,
|
||||
[4] = (iw_handler)orinoco_ioctl_setpreamble,
|
||||
[5] = (iw_handler)orinoco_ioctl_getpreamble,
|
||||
[6] = (iw_handler)orinoco_ioctl_setibssport,
|
||||
[7] = (iw_handler)orinoco_ioctl_getibssport,
|
||||
[9] = (iw_handler)orinoco_ioctl_getrid,
|
||||
};
|
||||
|
||||
const struct iw_handler_def orinoco_handler_def = {
|
||||
|
Reference in New Issue
Block a user