]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/zd1211rw/zd_chip.c
[PATCH] zd1211rw: Remove addressing abstraction
[linux-2.6] / drivers / net / wireless / zd1211rw / zd_chip.c
index c213a2e56e5511e26dd9c62bc797237a163ad097..12dfc0b6efe6796b2f371b53a357e23dc1a558f6 100644 (file)
@@ -84,6 +84,18 @@ static void print_id(struct zd_chip *chip)
        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.
  */
@@ -101,7 +113,7 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr
 
        /* 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),
@@ -114,7 +126,7 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr
        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];
        }
 
@@ -163,7 +175,7 @@ int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
                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;
        }
@@ -325,13 +337,22 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type)
        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;
@@ -457,7 +478,8 @@ static int read_values(struct zd_chip *chip, u8 *values, size_t count,
 
        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;
@@ -789,47 +811,18 @@ static int hw_reset_phy(struct zd_chip *chip)
 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 },
@@ -838,6 +831,20 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip)
                { 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 },
@@ -852,25 +859,16 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip)
                { 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);
 }
@@ -965,16 +963,14 @@ static int hw_init(struct zd_chip *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)
@@ -1009,9 +1005,11 @@ static int test_init(struct zd_chip *chip)
 
 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;
@@ -1037,7 +1035,8 @@ static int print_fw_version(struct zd_chip *chip)
        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;
 
@@ -1067,6 +1066,31 @@ static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std)
        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;
@@ -1092,6 +1116,22 @@ int zd_chip_disable_hwint(struct zd_chip *chip)
        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;
@@ -1111,7 +1151,7 @@ int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
        if (r)
                goto out;
 
-       r = zd_usb_init_hw(&chip->usb);
+       r = read_fw_regs_offset(chip);
        if (r)
                goto out;
 
@@ -1289,103 +1329,69 @@ u8 zd_chip_get_channel(struct zd_chip *chip)
        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, &reg);
+       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)
@@ -1674,3 +1680,15 @@ int zd_rfwritev_cr_locked(struct zd_chip *chip,
        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));
+}