dev_info(zd_chip_dev(chip), "%s\n", buffer);
}
+static zd_addr_t inc_addr(zd_addr_t addr)
+{
+ u16 a = (u16)addr;
+ /* Control registers use byte addressing, but everything else uses word
+ * addressing. */
+ if ((a & 0xf000) == CR_START)
+ a += 2;
+ else
+ a += 1;
+ return (zd_addr_t)a;
+}
+
/* Read a variable number of 32-bit values. Parameter count is not allowed to
* exceed USB_MAX_IOREAD32_COUNT.
*/
/* Allocate a single memory block for values and addresses. */
count16 = 2*count;
- a16 = (zd_addr_t *)kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
+ a16 = kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
GFP_NOFS);
if (!a16) {
dev_dbg_f(zd_chip_dev(chip),
for (i = 0; i < count; i++) {
int j = 2*i;
/* We read the high word always first. */
- a16[j] = zd_inc_word(addr[i]);
+ a16[j] = inc_addr(addr[i]);
a16[j+1] = addr[i];
}
j = 2*i;
/* We write the high word always first. */
ioreqs16[j].value = ioreqs[i].value >> 16;
- ioreqs16[j].addr = zd_inc_word(ioreqs[i].addr);
+ ioreqs16[j].addr = inc_addr(ioreqs[i].addr);
ioreqs16[j+1].value = ioreqs[i].value;
ioreqs16[j+1].addr = ioreqs[i].addr;
}
chip->patch_cr157 = (value >> 13) & 0x1;
chip->patch_6m_band_edge = (value >> 21) & 0x1;
chip->new_phy_layout = (value >> 31) & 0x1;
+ chip->link_led = ((value >> 4) & 1) ? LED1 : LED2;
+ chip->supports_tx_led = 1;
+ if (value & (1 << 24)) { /* LED scenario */
+ if (value & (1 << 29))
+ chip->supports_tx_led = 0;
+ }
dev_dbg_f(zd_chip_dev(chip),
"RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d "
- "patch 6M %d new PHY %d\n",
+ "patch 6M %d new PHY %d link LED%d tx led %d\n",
zd_rf_name(*rf_type), *rf_type,
chip->pa_type, chip->patch_cck_gain,
- chip->patch_cr157, chip->patch_6m_band_edge, chip->new_phy_layout);
+ chip->patch_cr157, chip->patch_6m_band_edge,
+ chip->new_phy_layout,
+ chip->link_led == LED1 ? 1 : 2,
+ chip->supports_tx_led);
return 0;
error:
*rf_type = 0;
ZD_ASSERT(mutex_is_locked(&chip->mutex));
for (i = 0;;) {
- r = zd_ioread32_locked(chip, &v, e2p_addr+i/2);
+ r = zd_ioread32_locked(chip, &v,
+ (zd_addr_t)((u16)e2p_addr+i/2));
if (r)
return r;
v -= guard;
static int zd1211_hw_init_hmac(struct zd_chip *chip)
{
static const struct zd_ioreq32 ioreqs[] = {
- { CR_ACK_TIMEOUT_EXT, 0x20 },
- { CR_ADDA_MBIAS_WARMTIME, 0x30000808 },
{ CR_ZD1211_RETRY_MAX, 0x2 },
- { CR_SNIFFER_ON, 0 },
- { CR_RX_FILTER, STA_RX_FILTER },
- { CR_GROUP_HASH_P1, 0x00 },
- { CR_GROUP_HASH_P2, 0x80000000 },
- { CR_REG1, 0xa4 },
- { CR_ADDA_PWR_DWN, 0x7f },
- { CR_BCN_PLCP_CFG, 0x00f00401 },
- { CR_PHY_DELAY, 0x00 },
- { CR_ACK_TIMEOUT_EXT, 0x80 },
- { CR_ADDA_PWR_DWN, 0x00 },
- { CR_ACK_TIME_80211, 0x100 },
- { CR_RX_PE_DELAY, 0x70 },
- { CR_PS_CTRL, 0x10000000 },
- { CR_RTS_CTS_RATE, 0x02030203 },
{ CR_RX_THRESHOLD, 0x000c0640 },
- { CR_AFTER_PNP, 0x1 },
- { CR_WEP_PROTECT, 0x114 },
};
- int r;
-
dev_dbg_f(zd_chip_dev(chip), "\n");
ZD_ASSERT(mutex_is_locked(&chip->mutex));
- r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-#ifdef DEBUG
- if (r) {
- dev_err(zd_chip_dev(chip),
- "error in zd_iowrite32a_locked. Error number %d\n", r);
- }
-#endif /* DEBUG */
- return r;
+ return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
}
static int zd1211b_hw_init_hmac(struct zd_chip *chip)
{
static const struct zd_ioreq32 ioreqs[] = {
- { CR_ACK_TIMEOUT_EXT, 0x20 },
- { CR_ADDA_MBIAS_WARMTIME, 0x30000808 },
{ CR_ZD1211B_RETRY_MAX, 0x02020202 },
{ CR_ZD1211B_TX_PWR_CTL4, 0x007f003f },
{ CR_ZD1211B_TX_PWR_CTL3, 0x007f003f },
{ CR_ZD1211B_AIFS_CTL1, 0x00280028 },
{ CR_ZD1211B_AIFS_CTL2, 0x008C003C },
{ CR_ZD1211B_TXOP, 0x01800824 },
+ { CR_RX_THRESHOLD, 0x000c0eff, },
+ };
+
+ dev_dbg_f(zd_chip_dev(chip), "\n");
+ ZD_ASSERT(mutex_is_locked(&chip->mutex));
+ return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int hw_init_hmac(struct zd_chip *chip)
+{
+ int r;
+ static const struct zd_ioreq32 ioreqs[] = {
+ { CR_ACK_TIMEOUT_EXT, 0x20 },
+ { CR_ADDA_MBIAS_WARMTIME, 0x30000808 },
{ CR_SNIFFER_ON, 0 },
{ CR_RX_FILTER, STA_RX_FILTER },
{ CR_GROUP_HASH_P1, 0x00 },
{ CR_RX_PE_DELAY, 0x70 },
{ CR_PS_CTRL, 0x10000000 },
{ CR_RTS_CTS_RATE, 0x02030203 },
- { CR_RX_THRESHOLD, 0x000c0eff, },
{ CR_AFTER_PNP, 0x1 },
{ CR_WEP_PROTECT, 0x114 },
+ { CR_IFS_VALUE, IFS_VALUE_DEFAULT },
};
- int r;
-
- dev_dbg_f(zd_chip_dev(chip), "\n");
ZD_ASSERT(mutex_is_locked(&chip->mutex));
r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
- if (r) {
- dev_dbg_f(zd_chip_dev(chip),
- "error in zd_iowrite32a_locked. Error number %d\n", r);
- }
- return r;
-}
+ if (r)
+ return r;
-static int hw_init_hmac(struct zd_chip *chip)
-{
return chip->is_zd1211b ?
zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip);
}
if (r)
return r;
- /* Although the vendor driver defaults to a different value during
- * init, it overwrites the IFS value with the following every time
- * the channel changes. We should aim to be more intelligent... */
- r = zd_iowrite32_locked(chip, IFS_VALUE_DEFAULT, CR_IFS_VALUE);
- if (r)
- return r;
-
return set_beacon_interval(chip, 100);
}
+static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset)
+{
+ return (zd_addr_t)((u16)chip->fw_regs_base + offset);
+}
+
#ifdef DEBUG
static int dump_cr(struct zd_chip *chip, const zd_addr_t addr,
const char *addr_string)
static void dump_fw_registers(struct zd_chip *chip)
{
- static const zd_addr_t addr[4] = {
- FW_FIRMWARE_VER, FW_USB_SPEED, FW_FIX_TX_RATE,
- FW_LINK_STATUS
+ const zd_addr_t addr[4] = {
+ fw_reg_addr(chip, FW_REG_FIRMWARE_VER),
+ fw_reg_addr(chip, FW_REG_USB_SPEED),
+ fw_reg_addr(chip, FW_REG_FIX_TX_RATE),
+ fw_reg_addr(chip, FW_REG_LED_LINK_STATUS),
};
int r;
int r;
u16 version;
- r = zd_ioread16_locked(chip, &version, FW_FIRMWARE_VER);
+ r = zd_ioread16_locked(chip, &version,
+ fw_reg_addr(chip, FW_REG_FIRMWARE_VER));
if (r)
return r;
return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL);
}
+int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip,
+ u8 rts_rate, int preamble)
+{
+ int rts_mod = ZD_RX_CCK;
+ u32 value = 0;
+
+ /* Modulation bit */
+ if (ZD_CS_TYPE(rts_rate) == ZD_CS_OFDM)
+ rts_mod = ZD_RX_OFDM;
+
+ dev_dbg_f(zd_chip_dev(chip), "rts_rate=%x preamble=%x\n",
+ rts_rate, preamble);
+
+ value |= rts_rate << RTSCTS_SH_RTS_RATE;
+ value |= rts_mod << RTSCTS_SH_RTS_MOD_TYPE;
+ value |= preamble << RTSCTS_SH_RTS_PMB_TYPE;
+ value |= preamble << RTSCTS_SH_CTS_PMB_TYPE;
+
+ /* We always send 11M self-CTS messages, like the vendor driver. */
+ value |= ZD_CCK_RATE_11M << RTSCTS_SH_CTS_RATE;
+ value |= ZD_RX_CCK << RTSCTS_SH_CTS_MOD_TYPE;
+
+ return zd_iowrite32_locked(chip, value, CR_RTS_CTS_RATE);
+}
+
int zd_chip_enable_hwint(struct zd_chip *chip)
{
int r;
return r;
}
+static int read_fw_regs_offset(struct zd_chip *chip)
+{
+ int r;
+
+ ZD_ASSERT(mutex_is_locked(&chip->mutex));
+ r = zd_ioread16_locked(chip, (u16*)&chip->fw_regs_base,
+ FWRAW_REGS_ADDR);
+ if (r)
+ return r;
+ dev_dbg_f(zd_chip_dev(chip), "fw_regs_base: %#06hx\n",
+ (u16)chip->fw_regs_base);
+
+ return 0;
+}
+
+
int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
{
int r;
if (r)
goto out;
- r = zd_usb_init_hw(&chip->usb);
+ r = read_fw_regs_offset(chip);
if (r)
goto out;
return channel;
}
-static u16 led_mask(int led)
-{
- switch (led) {
- case 1:
- return LED1;
- case 2:
- return LED2;
- default:
- return 0;
- }
-}
-
-static int read_led_reg(struct zd_chip *chip, u16 *status)
-{
- ZD_ASSERT(mutex_is_locked(&chip->mutex));
- return zd_ioread16_locked(chip, status, CR_LED);
-}
-
-static int write_led_reg(struct zd_chip *chip, u16 status)
+int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
{
- ZD_ASSERT(mutex_is_locked(&chip->mutex));
- return zd_iowrite16_locked(chip, status, CR_LED);
-}
+ const zd_addr_t a[] = {
+ fw_reg_addr(chip, FW_REG_LED_LINK_STATUS),
+ CR_LED,
+ };
-int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status)
-{
- int r, ret;
- u16 mask = led_mask(led);
- u16 reg;
+ int r;
+ u16 v[ARRAY_SIZE(a)];
+ struct zd_ioreq16 ioreqs[ARRAY_SIZE(a)] = {
+ [0] = { fw_reg_addr(chip, FW_REG_LED_LINK_STATUS) },
+ [1] = { CR_LED },
+ };
+ u16 other_led;
- if (!mask)
- return -EINVAL;
mutex_lock(&chip->mutex);
- r = read_led_reg(chip, ®);
+ r = zd_ioread16v_locked(chip, v, (const zd_addr_t *)a, ARRAY_SIZE(a));
if (r)
- return r;
+ goto out;
+
+ other_led = chip->link_led == LED1 ? LED2 : LED1;
+
switch (status) {
- case LED_STATUS:
- return (reg & mask) ? LED_ON : LED_OFF;
case LED_OFF:
- reg &= ~mask;
- ret = LED_OFF;
+ ioreqs[0].value = FW_LINK_OFF;
+ ioreqs[1].value = v[1] & ~(LED1|LED2);
break;
- case LED_FLIP:
- reg ^= mask;
- ret = (reg&mask) ? LED_ON : LED_OFF;
+ case LED_SCANNING:
+ ioreqs[0].value = FW_LINK_OFF;
+ ioreqs[1].value = v[1] & ~other_led;
+ if (get_seconds() % 3 == 0) {
+ ioreqs[1].value &= ~chip->link_led;
+ } else {
+ ioreqs[1].value |= chip->link_led;
+ }
break;
- case LED_ON:
- reg |= mask;
- ret = LED_ON;
+ case LED_ASSOCIATED:
+ ioreqs[0].value = FW_LINK_TX;
+ ioreqs[1].value = v[1] & ~other_led;
+ ioreqs[1].value |= chip->link_led;
break;
default:
- return -EINVAL;
- }
- r = write_led_reg(chip, reg);
- if (r) {
- ret = r;
+ r = -EINVAL;
goto out;
}
-out:
- mutex_unlock(&chip->mutex);
- return r;
-}
-
-int zd_chip_led_flip(struct zd_chip *chip, int led,
- const unsigned int *phases_msecs, unsigned int count)
-{
- int i, r;
- enum led_status status;
- r = zd_chip_led_status(chip, led, LED_STATUS);
- if (r)
- return r;
- status = r;
- for (i = 0; i < count; i++) {
- r = zd_chip_led_status(chip, led, LED_FLIP);
- if (r < 0)
+ if (v[0] != ioreqs[0].value || v[1] != ioreqs[1].value) {
+ r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+ if (r)
goto out;
- msleep(phases_msecs[i]);
}
-
+ r = 0;
out:
- zd_chip_led_status(chip, led, status);
+ mutex_unlock(&chip->mutex);
return r;
}
-int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
+int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates)
{
- int r;
-
- if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G))
- return -EINVAL;
+ ZD_ASSERT((cr_rates & ~(CR_RATES_80211B | CR_RATES_80211G)) == 0);
+ dev_dbg_f(zd_chip_dev(chip), "%x\n", cr_rates);
- mutex_lock(&chip->mutex);
- r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);
- mutex_unlock(&chip->mutex);
- return r;
+ return zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);
}
static int ofdm_qual_db(u8 status_quality, u8 rate, unsigned int size)
return 0;
}
+int zd_chip_set_multicast_hash(struct zd_chip *chip,
+ struct zd_mc_hash *hash)
+{
+ struct zd_ioreq32 ioreqs[] = {
+ { CR_GROUP_HASH_P1, hash->low },
+ { CR_GROUP_HASH_P2, hash->high },
+ };
+
+ dev_dbg_f(zd_chip_dev(chip), "hash l 0x%08x h 0x%08x\n",
+ ioreqs[0].value, ioreqs[1].value);
+ return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}