📄 zd_chip.c
字号:
if (r) goto out;#endif r = zd_iowrite32_locked(chip, 1, CR_AFTER_PNP); if (r) goto out; r = read_fw_regs_offset(chip); if (r) goto out; /* GPI is always disabled, also in the other driver. */ r = zd_iowrite32_locked(chip, 0, CR_GPI_EN); if (r) goto out; r = zd_iowrite32_locked(chip, CWIN_SIZE, CR_CWMIN_CWMAX); if (r) goto out; /* Currently we support IEEE 802.11g for full and high speed USB. * It might be discussed, whether we should suppport pure b mode for * full speed USB. */ r = set_mandatory_rates(chip, IEEE80211G); if (r) goto out; /* Disabling interrupts is certainly a smart thing here. */ r = disable_hwint(chip); if (r) goto out; r = read_pod(chip, &rf_type); if (r) goto out; r = hw_init(chip); if (r) goto out; r = zd_rf_init_hw(&chip->rf, rf_type); if (r) goto out; r = print_fw_version(chip); if (r) goto out;#ifdef DEBUG dump_fw_registers(chip); r = test_init(chip); if (r) goto out;#endif /* DEBUG */ r = read_cal_int_tables(chip); if (r) goto out; print_id(chip);out: mutex_unlock(&chip->mutex); return r;}static int update_pwr_int(struct zd_chip *chip, u8 channel){ u8 value = chip->pwr_int_values[channel - 1]; return zd_iowrite16_locked(chip, value, CR31);}static int update_pwr_cal(struct zd_chip *chip, u8 channel){ u8 value = chip->pwr_cal_values[channel-1]; return zd_iowrite16_locked(chip, value, CR68);}static int update_ofdm_cal(struct zd_chip *chip, u8 channel){ struct zd_ioreq16 ioreqs[3]; ioreqs[0].addr = CR67; ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1]; ioreqs[1].addr = CR66; ioreqs[1].value = chip->ofdm_cal_values[OFDM_48M_INDEX][channel-1]; ioreqs[2].addr = CR65; ioreqs[2].value = chip->ofdm_cal_values[OFDM_54M_INDEX][channel-1]; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));}static int update_channel_integration_and_calibration(struct zd_chip *chip, u8 channel){ int r; if (!zd_rf_should_update_pwr_int(&chip->rf)) return 0; r = update_pwr_int(chip, channel); if (r) return r; if (zd_chip_is_zd1211b(chip)) { static const struct zd_ioreq16 ioreqs[] = { { CR69, 0x28 }, {}, { CR69, 0x2a }, }; r = update_ofdm_cal(chip, channel); if (r) return r; r = update_pwr_cal(chip, channel); if (r) return r; r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); if (r) return r; } return 0;}/* The CCK baseband gain can be optionally patched by the EEPROM */static int patch_cck_gain(struct zd_chip *chip){ int r; u32 value; if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf)) return 0; ZD_ASSERT(mutex_is_locked(&chip->mutex)); r = zd_ioread32_locked(chip, &value, E2P_PHY_REG); if (r) return r; dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff); return zd_iowrite16_locked(chip, value & 0xff, CR47);}int zd_chip_set_channel(struct zd_chip *chip, u8 channel){ int r, t; mutex_lock(&chip->mutex); r = zd_chip_lock_phy_regs(chip); if (r) goto out; r = zd_rf_set_channel(&chip->rf, channel); if (r) goto unlock; r = update_channel_integration_and_calibration(chip, channel); if (r) goto unlock; r = patch_cck_gain(chip); if (r) goto unlock; r = patch_6m_band_edge(chip, channel); if (r) goto unlock; r = zd_iowrite32_locked(chip, 0, CR_CONFIG_PHILIPS);unlock: t = zd_chip_unlock_phy_regs(chip); if (t && !r) r = t;out: mutex_unlock(&chip->mutex); return r;}u8 zd_chip_get_channel(struct zd_chip *chip){ u8 channel; mutex_lock(&chip->mutex); channel = chip->rf.channel; mutex_unlock(&chip->mutex); return channel;}int zd_chip_control_leds(struct zd_chip *chip, enum led_status status){ const zd_addr_t a[] = { fw_reg_addr(chip, FW_REG_LED_LINK_STATUS), CR_LED, }; 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; mutex_lock(&chip->mutex); r = zd_ioread16v_locked(chip, v, (const zd_addr_t *)a, ARRAY_SIZE(a)); if (r) goto out; other_led = chip->link_led == LED1 ? LED2 : LED1; switch (status) { case LED_OFF: ioreqs[0].value = FW_LINK_OFF; ioreqs[1].value = v[1] & ~(LED1|LED2); break; 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_ASSOCIATED: ioreqs[0].value = FW_LINK_TX; ioreqs[1].value = v[1] & ~other_led; ioreqs[1].value |= chip->link_led; break; default: r = -EINVAL; goto out; } if (v[0] != ioreqs[0].value || v[1] != ioreqs[1].value) { r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); if (r) goto out; } r = 0;out: mutex_unlock(&chip->mutex); return r;}int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates){ ZD_ASSERT((cr_rates & ~(CR_RATES_80211B | CR_RATES_80211G)) == 0); dev_dbg_f(zd_chip_dev(chip), "%x\n", cr_rates); return zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);}static int ofdm_qual_db(u8 status_quality, u8 zd_rate, unsigned int size){ static const u16 constants[] = { 715, 655, 585, 540, 470, 410, 360, 315, 270, 235, 205, 175, 150, 125, 105, 85, 65, 50, 40, 25, 15 }; int i; u32 x; /* It seems that their quality parameter is somehow per signal * and is now transferred per bit. */ switch (zd_rate) { case ZD_OFDM_RATE_6M: case ZD_OFDM_RATE_12M: case ZD_OFDM_RATE_24M: size *= 2; break; case ZD_OFDM_RATE_9M: case ZD_OFDM_RATE_18M: case ZD_OFDM_RATE_36M: case ZD_OFDM_RATE_54M: size *= 4; size /= 3; break; case ZD_OFDM_RATE_48M: size *= 3; size /= 2; break; default: return -EINVAL; } x = (10000 * status_quality)/size; for (i = 0; i < ARRAY_SIZE(constants); i++) { if (x > constants[i]) break; } switch (zd_rate) { case ZD_OFDM_RATE_6M: case ZD_OFDM_RATE_9M: i += 3; break; case ZD_OFDM_RATE_12M: case ZD_OFDM_RATE_18M: i += 5; break; case ZD_OFDM_RATE_24M: case ZD_OFDM_RATE_36M: i += 9; break; case ZD_OFDM_RATE_48M: case ZD_OFDM_RATE_54M: i += 15; break; default: return -EINVAL; } return i;}static int ofdm_qual_percent(u8 status_quality, u8 zd_rate, unsigned int size){ int r; r = ofdm_qual_db(status_quality, zd_rate, size); ZD_ASSERT(r >= 0); if (r < 0) r = 0; r = (r * 100)/29; return r <= 100 ? r : 100;}static unsigned int log10times100(unsigned int x){ static const u8 log10[] = { 0, 0, 30, 47, 60, 69, 77, 84, 90, 95, 100, 104, 107, 111, 114, 117, 120, 123, 125, 127, 130, 132, 134, 136, 138, 139, 141, 143, 144, 146, 147, 149, 150, 151, 153, 154, 155, 156, 157, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 169, 170, 171, 172, 173, 174, 174, 175, 176, 177, 177, 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 186, 187, 188, 188, 189, 189, 190, 190, 191, 191, 192, 192, 193, 193, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 200, 201, 201, 202, 202, 202, 203, 203, 204, 204, 204, 205, 205, 206, 206, 206, 207, 207, 207, 208, 208, 208, 209, 209, 210, 210, 210, 211, 211, 211, 212, 212, 212, 213, 213, 213, 213, 214, 214, 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, 217, 218, 218, 218, 219, 219, 219, 219, 220, 220, 220, 220, 221, 221, 221, 222, 222, 222, 222, 223, 223, 223, 223, 224, 224, 224, 224, }; return x < ARRAY_SIZE(log10) ? log10[x] : 225;}enum { MAX_CCK_EVM_DB = 45,};static int cck_evm_db(u8 status_quality){ return (20 * log10times100(status_quality)) / 100;}static int cck_snr_db(u8 status_quality){ int r = MAX_CCK_EVM_DB - cck_evm_db(status_quality); ZD_ASSERT(r >= 0); return r;}static int cck_qual_percent(u8 status_quality){ int r; r = cck_snr_db(status_quality); r = (100*r)/17; return r <= 100 ? r : 100;}static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame){ return ZD_OFDM | zd_ofdm_plcp_header_rate(rx_frame);}u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, const struct rx_status *status){ return (status->frame_status&ZD_RX_OFDM) ? ofdm_qual_percent(status->signal_quality_ofdm, zd_rate_from_ofdm_plcp_header(rx_frame), size) : cck_qual_percent(status->signal_quality_cck);}u8 zd_rx_strength_percent(u8 rssi){ int r = (rssi*100) / 41; if (r > 100) r = 100; return (u8) r;}u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status){ static const u16 ofdm_rates[] = { [ZD_OFDM_PLCP_RATE_6M] = 60, [ZD_OFDM_PLCP_RATE_9M] = 90, [ZD_OFDM_PLCP_RATE_12M] = 120, [ZD_OFDM_PLCP_RATE_18M] = 180, [ZD_OFDM_PLCP_RATE_24M] = 240, [ZD_OFDM_PLCP_RATE_36M] = 360, [ZD_OFDM_PLCP_RATE_48M] = 480, [ZD_OFDM_PLCP_RATE_54M] = 540, }; u16 rate; if (status->frame_status & ZD_RX_OFDM) { /* Deals with PLCP OFDM rate (not zd_rates) */ u8 ofdm_rate = zd_ofdm_plcp_header_rate(rx_frame); rate = ofdm_rates[ofdm_rate & 0xf]; } else { switch (zd_cck_plcp_header_signal(rx_frame)) { case ZD_CCK_PLCP_SIGNAL_1M: rate = 10; break; case ZD_CCK_PLCP_SIGNAL_2M: rate = 20; break; case ZD_CCK_PLCP_SIGNAL_5M5: rate = 55; break; case ZD_CCK_PLCP_SIGNAL_11M: rate = 110; break; default: rate = 0; } } return rate;}int zd_chip_switch_radio_on(struct zd_chip *chip){ int r; mutex_lock(&chip->mutex); r = zd_switch_radio_on(&chip->rf); mutex_unlock(&chip->mutex); return r;}int zd_chip_switch_radio_off(struct zd_chip *chip){ int r; mutex_lock(&chip->mutex); r = zd_switch_radio_off(&chip->rf); mutex_unlock(&chip->mutex); return r;}int zd_chip_enable_int(struct zd_chip *chip){ int r; mutex_lock(&chip->mutex); r = zd_usb_enable_int(&chip->usb); mutex_unlock(&chip->mutex); return r;}void zd_chip_disable_int(struct zd_chip *chip){ mutex_lock(&chip->mutex); zd_usb_disable_int(&chip->usb); mutex_unlock(&chip->mutex);}int zd_chip_enable_rx(struct zd_chip *chip){ int r; mutex_lock(&chip->mutex); r = zd_usb_enable_rx(&chip->usb); mutex_unlock(&chip->mutex); return r;}void zd_chip_disable_rx(struct zd_chip *chip){ mutex_lock(&chip->mutex); zd_usb_disable_rx(&chip->usb); mutex_unlock(&chip->mutex);}int zd_rfwritev_locked(struct zd_chip *chip, const u32* values, unsigned int count, u8 bits){ int r; unsigned int i; for (i = 0; i < count; i++) { r = zd_rfwrite_locked(chip, values[i], bits); if (r) return r; } return 0;}/* * We can optionally program the RF directly through CR regs, if supported by * the hardware. This is much faster than the older method. */int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value){ struct zd_ioreq16 ioreqs[] = { { CR244, (value >> 16) & 0xff }, { CR243, (value >> 8) & 0xff }, { CR242, value & 0xff }, }; ZD_ASSERT(mutex_is_locked(&chip->mutex)); return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));}int zd_rfwritev_cr_locked(struct zd_chip *chip, const u32 *values, unsigned int count){ int r; unsigned int i; for (i = 0; i < count; i++) { r = zd_rfwrite_cr_locked(chip, values[i]); if (r) return r; } 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 }, }; return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -