📄 rt73usb.c
字号:
rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); else rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); break; case ANTENNA_B: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); if (rt2x00dev->curr_hwmode == HWMODE_A) rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); else rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); break; } rt73usb_bbp_write(rt2x00dev, 77, r77); rt73usb_bbp_write(rt2x00dev, 3, r3); rt73usb_bbp_write(rt2x00dev, 4, r4);}static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev, const int antenna_tx, const int antenna_rx){ u8 r3; u8 r4; u8 r77; rt73usb_bbp_read(rt2x00dev, 3, &r3); rt73usb_bbp_read(rt2x00dev, 4, &r4); rt73usb_bbp_read(rt2x00dev, 77, &r77); rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); switch (antenna_rx) { case ANTENNA_SW_DIVERSITY: case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); break; case ANTENNA_A: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); break; case ANTENNA_B: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); break; } rt73usb_bbp_write(rt2x00dev, 77, r77); rt73usb_bbp_write(rt2x00dev, 3, r3); rt73usb_bbp_write(rt2x00dev, 4, r4);}struct antenna_sel { u8 word; /* * value[0] -> non-LNA * value[1] -> LNA */ u8 value[2];};static const struct antenna_sel antenna_sel_a[] = { { 96, { 0x58, 0x78 } }, { 104, { 0x38, 0x48 } }, { 75, { 0xfe, 0x80 } }, { 86, { 0xfe, 0x80 } }, { 88, { 0xfe, 0x80 } }, { 35, { 0x60, 0x60 } }, { 97, { 0x58, 0x58 } }, { 98, { 0x58, 0x58 } },};static const struct antenna_sel antenna_sel_bg[] = { { 96, { 0x48, 0x68 } }, { 104, { 0x2c, 0x3c } }, { 75, { 0xfe, 0x80 } }, { 86, { 0xfe, 0x80 } }, { 88, { 0xfe, 0x80 } }, { 35, { 0x50, 0x50 } }, { 97, { 0x48, 0x48 } }, { 98, { 0x48, 0x48 } },};static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev, const int antenna_tx, const int antenna_rx){ const struct antenna_sel *sel; unsigned int lna; unsigned int i; u32 reg; rt73usb_register_read(rt2x00dev, PHY_CSR0, ®); if (rt2x00dev->curr_hwmode == HWMODE_A) { sel = antenna_sel_a; lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, 0); rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, 1); } else { sel = antenna_sel_bg; lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, 1); rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, 0); } for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); rt73usb_register_write(rt2x00dev, PHY_CSR0, reg); if (rt2x00_rf(&rt2x00dev->chip, RF5226) || rt2x00_rf(&rt2x00dev->chip, RF5225)) rt73usb_config_antenna_5x(rt2x00dev, antenna_tx, antenna_rx); else if (rt2x00_rf(&rt2x00dev->chip, RF2528) || rt2x00_rf(&rt2x00dev->chip, RF2527)) rt73usb_config_antenna_2x(rt2x00dev, antenna_tx, antenna_rx);}static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf){ u32 reg; rt73usb_register_read(rt2x00dev, MAC_CSR9, ®); rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, libconf->slot_time); rt73usb_register_write(rt2x00dev, MAC_CSR9, reg); rt73usb_register_read(rt2x00dev, MAC_CSR8, ®); rt2x00_set_field32(®, MAC_CSR8_SIFS, libconf->sifs); rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); rt2x00_set_field32(®, MAC_CSR8_EIFS, libconf->eifs); rt73usb_register_write(rt2x00dev, MAC_CSR8, reg); rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®); rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, libconf->conf->beacon_int * 16); rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);}static void rt73usb_config(struct rt2x00_dev *rt2x00dev, const unsigned int flags, struct rt2x00lib_conf *libconf){ if (flags & CONFIG_UPDATE_PHYMODE) rt73usb_config_phymode(rt2x00dev, libconf->basic_rates); if (flags & CONFIG_UPDATE_CHANNEL) rt73usb_config_channel(rt2x00dev, &libconf->rf, libconf->conf->power_level); if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL)) rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level); if (flags & CONFIG_UPDATE_ANTENNA) rt73usb_config_antenna(rt2x00dev, libconf->conf->antenna_sel_tx, libconf->conf->antenna_sel_rx); if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) rt73usb_config_duration(rt2x00dev, libconf);}/* * LED functions. */static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev){ u32 reg; rt73usb_register_read(rt2x00dev, MAC_CSR14, ®); rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70); rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30); rt73usb_register_write(rt2x00dev, MAC_CSR14, reg); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1); if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 1); else rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 1); rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000, rt2x00dev->led_reg, REGISTER_TIMEOUT);}static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev){ rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 0); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 0); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 0); rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000, rt2x00dev->led_reg, REGISTER_TIMEOUT);}static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi){ u32 led; if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH) return; /* * Led handling requires a positive value for the rssi, * to do that correctly we need to add the correction. */ rssi += rt2x00dev->rssi_offset; if (rssi <= 30) led = 0; else if (rssi <= 39) led = 1; else if (rssi <= 49) led = 2; else if (rssi <= 53) led = 3; else if (rssi <= 63) led = 4; else led = 5; rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, led, rt2x00dev->led_reg, REGISTER_TIMEOUT);}/* * Link tuning */static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev){ u32 reg; /* * Update FCS error count from register. */ rt73usb_register_read(rt2x00dev, STA_CSR0, ®); rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); /* * Update False CCA count from register. */ rt73usb_register_read(rt2x00dev, STA_CSR1, ®); reg = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); rt2x00dev->link.false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);}static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev){ rt73usb_bbp_write(rt2x00dev, 17, 0x20); rt2x00dev->link.vgc_level = 0x20;}static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev){ int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); u8 r17; u8 up_bound; u8 low_bound; /* * Update Led strength */ rt73usb_activity_led(rt2x00dev, rssi); rt73usb_bbp_read(rt2x00dev, 17, &r17); /* * Determine r17 bounds. */ if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) { low_bound = 0x28; up_bound = 0x48; if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { low_bound += 0x10; up_bound += 0x10; } } else { if (rssi > -82) { low_bound = 0x1c; up_bound = 0x40; } else if (rssi > -84) { low_bound = 0x1c; up_bound = 0x20; } else { low_bound = 0x1c; up_bound = 0x1c; } if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { low_bound += 0x14; up_bound += 0x10; } } /* * Special big-R17 for very short distance */ if (rssi > -35) { if (r17 != 0x60) rt73usb_bbp_write(rt2x00dev, 17, 0x60); return; } /* * Special big-R17 for short distance */ if (rssi >= -58) { if (r17 != up_bound) rt73usb_bbp_write(rt2x00dev, 17, up_bound); return; } /* * Special big-R17 for middle-short distance */ if (rssi >= -66) { low_bound += 0x10; if (r17 != low_bound) rt73usb_bbp_write(rt2x00dev, 17, low_bound); return; } /* * Special mid-R17 for middle distance */ if (rssi >= -74) { if (r17 != (low_bound + 0x10)) rt73usb_bbp_write(rt2x00dev, 17, low_bound + 0x08); return; } /* * Special case: Change up_bound based on the rssi. * Lower up_bound when rssi is weaker then -74 dBm. */ up_bound -= 2 * (-74 - rssi); if (low_bound > up_bound) up_bound = low_bound; if (r17 > up_bound) { rt73usb_bbp_write(rt2x00dev, 17, up_bound); return; } /* * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. */ if (rt2x00dev->link.false_cca > 512 && r17 < up_bound) { r17 += 4; if (r17 > up_bound) r17 = up_bound; rt73usb_bbp_write(rt2x00dev, 17, r17); } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) { r17 -= 4; if (r17 < low_bound) r17 = low_bound; rt73usb_bbp_write(rt2x00dev, 17, r17); }}/* * Firmware name function. */static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev){ return FIRMWARE_RT2571;}/* * Initialization functions. */static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, const size_t len){ unsigned int i; int status; u32 reg; char *ptr = data; char *cache; int buflen; int timeout; /* * Wait for stable hardware. */ for (i = 0; i < 100; i++) { rt73usb_register_read(rt2x00dev, MAC_CSR0, ®); if (reg) break; msleep(1); } if (!reg) { ERROR(rt2x00dev, "Unstable hardware.\n"); return -EBUSY; } /* * Write firmware to device. * We setup a seperate cache for this action, * since we are going to write larger chunks of data * then normally used cache size. */ cache = kmalloc(CSR_CACHE_SIZE_FIRMWARE, GFP_KERNEL); if (!cache) { ERROR(rt2x00dev, "Failed to allocate firmware cache.\n"); return -ENOMEM; } for (i = 0; i < len; i += CSR_CACHE_SIZE_FIRMWARE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -