📄 zd_chip.c
字号:
u8 rf_type; dev_dbg_f(zd_chip_dev(chip), "\n"); mutex_lock(&chip->mutex); chip->is_zd1211b = (device_type == DEVICE_ZD1211B) != 0;#ifdef DEBUG r = test_init(chip); if (r) goto out;#endif r = zd_iowrite32_locked(chip, 1, CR_AFTER_PNP); if (r) goto out; r = zd_usb_init_hw(&chip->usb); 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_e2p_mac_addr(chip); if (r) goto out; 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]; dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_int %#04x\n", channel, value); return zd_iowrite32_locked(chip, value, CR31);}static int update_pwr_cal(struct zd_chip *chip, u8 channel){ u8 value = chip->pwr_cal_values[channel-1]; dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_cal %#04x\n", channel, value); return zd_iowrite32_locked(chip, value, CR68);}static int update_ofdm_cal(struct zd_chip *chip, u8 channel){ struct zd_ioreq32 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]; dev_dbg_f(zd_chip_dev(chip), "channel %d ofdm_cal 36M %#04x 48M %#04x 54M %#04x\n", channel, ioreqs[0].value, ioreqs[1].value, ioreqs[2].value); return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));}static int update_channel_integration_and_calibration(struct zd_chip *chip, u8 channel){ int r; r = update_pwr_int(chip, channel); if (r) return r; if (chip->is_zd1211b) { static const struct zd_ioreq32 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_iowrite32a_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) 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_iowrite32_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;}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){ ZD_ASSERT(mutex_is_locked(&chip->mutex)); return zd_iowrite16_locked(chip, 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; if (!mask) return -EINVAL; mutex_lock(&chip->mutex); r = read_led_reg(chip, ®); if (r) return r; switch (status) { case LED_STATUS: return (reg & mask) ? LED_ON : LED_OFF; case LED_OFF: reg &= ~mask; ret = LED_OFF; break; case LED_FLIP: reg ^= mask; ret = (reg&mask) ? LED_ON : LED_OFF; break; case LED_ON: reg |= mask; ret = LED_ON; break; default: return -EINVAL; } r = write_led_reg(chip, reg); if (r) { ret = r; 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) goto out; msleep(phases_msecs[i]); }out: zd_chip_led_status(chip, led, status); return r;}int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates){ int r; if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G)) return -EINVAL; mutex_lock(&chip->mutex); r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL); mutex_unlock(&chip->mutex); return r;}static int ofdm_qual_db(u8 status_quality, u8 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 (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 (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 rate, unsigned int size){ int r; r = ofdm_qual_db(status_quality, 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;}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_ofdm_plcp_header_rate(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_RATE_6M] = 60, [ZD_OFDM_RATE_9M] = 90, [ZD_OFDM_RATE_12M] = 120, [ZD_OFDM_RATE_18M] = 180, [ZD_OFDM_RATE_24M] = 240, [ZD_OFDM_RATE_36M] = 360, [ZD_OFDM_RATE_48M] = 480, [ZD_OFDM_RATE_54M] = 540, }; u16 rate; if (status->frame_status & ZD_RX_OFDM) { u8 ofdm_rate = zd_ofdm_plcp_header_rate(rx_frame); rate = ofdm_rates[ofdm_rate & 0xf]; } else { u8 cck_rate = zd_cck_plcp_header_rate(rx_frame); switch (cck_rate) { case ZD_CCK_SIGNAL_1M: rate = 10; break; case ZD_CCK_SIGNAL_2M: rate = 20; break; case ZD_CCK_SIGNAL_5M5: rate = 55; break; case ZD_CCK_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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -