📄 iwl-3945.c
字号:
iwl_write_restricted_reg(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); udelay(20); iwl_set_bits_restricted_reg(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); iwl_release_restricted_access(priv); spin_unlock_irqrestore(&priv->lock, flags); /* Determine HW type */ rc = pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); if (rc) return rc; IWL_DEBUG_INFO("HW Revision ID = 0x%X\n", rev_id); iwl3945_nic_set_pwr_src(priv, 1); spin_lock_irqsave(&priv->lock, flags); if (rev_id & PCI_CFG_REV_ID_BIT_RTP) IWL_DEBUG_INFO("RTP type \n"); else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { IWL_DEBUG_INFO("ALM-MB type\n"); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB); } else { IWL_DEBUG_INFO("ALM-MM type\n"); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM); } spin_unlock_irqrestore(&priv->lock, flags); /* Initialize the EEPROM */ rc = iwl_eeprom_init(priv); if (rc) return rc; spin_lock_irqsave(&priv->lock, flags); if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom.sku_cap) { IWL_DEBUG_INFO("SKU OP mode is mrc\n"); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC); } else IWL_DEBUG_INFO("SKU OP mode is basic\n"); if ((priv->eeprom.board_revision & 0xF0) == 0xD0) { IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", priv->eeprom.board_revision); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); } else { IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", priv->eeprom.board_revision); iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); } if (priv->eeprom.almgor_m_version <= 1) { iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A); IWL_DEBUG_INFO("Card M type A version is 0x%X\n", priv->eeprom.almgor_m_version); } else { IWL_DEBUG_INFO("Card M type B version is 0x%X\n", priv->eeprom.almgor_m_version); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B); } spin_unlock_irqrestore(&priv->lock, flags); if (priv->eeprom.sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE) IWL_DEBUG_RF_KILL("SW RF KILL supported in EEPROM.\n"); if (priv->eeprom.sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE) IWL_DEBUG_RF_KILL("HW RF KILL supported in EEPROM.\n"); /* Allocate the RX queue, or reset if it is already allocated */ if (!rxq->bd) { rc = iwl_rx_queue_alloc(priv); if (rc) { IWL_ERROR("Unable to initialize Rx queue\n"); return -ENOMEM; } } else iwl_rx_queue_reset(priv, rxq); iwl_rx_replenish(priv); iwl3945_rx_init(priv, rxq); spin_lock_irqsave(&priv->lock, flags); /* Look at using this instead: rxq->need_update = 1; iwl_rx_queue_update_write_ptr(priv, rxq); */ rc = iwl_grab_restricted_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } iwl_write_restricted(priv, FH_RCSR_WPTR(0), rxq->write & ~7); iwl_release_restricted_access(priv); spin_unlock_irqrestore(&priv->lock, flags); rc = iwl3945_txq_ctx_reset(priv); if (rc) return rc; set_bit(STATUS_INIT, &priv->status); return 0;}/** * iwl_hw_txq_ctx_free - Free TXQ Context * * Destroy all TX DMA queues and structures */void iwl_hw_txq_ctx_free(struct iwl_priv *priv){ int txq_id; /* Tx queues */ for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) iwl_tx_queue_free(priv, &priv->txq[txq_id]);}void iwl_hw_txq_ctx_stop(struct iwl_priv *priv){ int queue; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); if (iwl_grab_restricted_access(priv)) { spin_unlock_irqrestore(&priv->lock, flags); iwl_hw_txq_ctx_free(priv); return; } /* stop SCD */ iwl_write_restricted_reg(priv, SCD_MODE_REG, 0); /* reset TFD queues */ for (queue = TFD_QUEUE_MIN; queue < TFD_QUEUE_MAX; queue++) { iwl_write_restricted(priv, FH_TCSR_CONFIG(queue), 0x0); iwl_poll_restricted_bit(priv, FH_TSSR_TX_STATUS, ALM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(queue), 1000); } iwl_release_restricted_access(priv); spin_unlock_irqrestore(&priv->lock, flags); iwl_hw_txq_ctx_free(priv);}int iwl_hw_nic_stop_master(struct iwl_priv *priv){ int rc = 0; u32 reg_val; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); /* set stop master bit */ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); reg_val = iwl_read32(priv, CSR_GP_CNTRL); if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE == (reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE)) IWL_DEBUG_INFO("Card in power save, master is already " "stopped\n"); else { rc = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); if (rc < 0) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } } spin_unlock_irqrestore(&priv->lock, flags); IWL_DEBUG_INFO("stop master\n"); return rc;}int iwl_hw_nic_reset(struct iwl_priv *priv){ int rc; unsigned long flags; iwl_hw_nic_stop_master(priv); spin_lock_irqsave(&priv->lock, flags); iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); rc = iwl_poll_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); rc = iwl_grab_restricted_access(priv); if (!rc) { iwl_write_restricted_reg(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_BSM_CLK_RQT); udelay(10); iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); iwl_write_restricted_reg(priv, APMG_RTC_INT_MSK_REG, 0x0); iwl_write_restricted_reg(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF); /* enable DMA */ iwl_write_restricted_reg(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); udelay(10); iwl_set_bits_restricted_reg(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); udelay(5); iwl_clear_bits_restricted_reg(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); iwl_release_restricted_access(priv); } /* Clear the 'host command active' bit... */ clear_bit(STATUS_HCMD_ACTIVE, &priv->status); wake_up_interruptible(&priv->wait_command_queue); spin_unlock_irqrestore(&priv->lock, flags); return rc;}/** * iwl_hw_reg_adjust_power_by_temp - return index delta into power gain settings table */static int iwl_hw_reg_adjust_power_by_temp(int new_reading, int old_reading){ return (new_reading - old_reading) * (-11) / 100;}/** * iwl_hw_reg_temp_out_of_range - Keep temperature in sane range */static inline int iwl_hw_reg_temp_out_of_range(int temperature){ return (((temperature < -260) || (temperature > 25)) ? 1 : 0);}int iwl_hw_get_temperature(struct iwl_priv *priv){ return iwl_read32(priv, CSR_UCODE_DRV_GP2);}/** * iwl_hw_reg_txpower_get_temperature - get current temperature by reading from NIC */static int iwl_hw_reg_txpower_get_temperature(struct iwl_priv *priv){ int temperature; temperature = iwl_hw_get_temperature(priv); /* driver's okay range is -260 to +25. * human readable okay range is 0 to +285 */ IWL_DEBUG_INFO("Temperature: %d\n", temperature + IWL_TEMP_CONVERT); /* handle insane temp reading */ if (iwl_hw_reg_temp_out_of_range(temperature)) { IWL_ERROR("Error bad temperature value %d\n", temperature); /* if really really hot(?), * substitute the 3rd band/group's temp measured at factory */ if (priv->last_temperature > 100) temperature = priv->eeprom.groups[2].temperature; else /* else use most recent "sane" value from driver */ temperature = priv->last_temperature; } return temperature; /* raw, not "human readable" */}/* Adjust Txpower only if temperature variance is greater than threshold. * * Both are lower than older versions' 9 degrees */#define IWL_TEMPERATURE_LIMIT_TIMER 6/** * is_temp_calib_needed - determines if new calibration is needed * * records new temperature in tx_mgr->temperature. * replaces tx_mgr->last_temperature *only* if calib needed * (assumes caller will actually do the calibration!). */static int is_temp_calib_needed(struct iwl_priv *priv){ int temp_diff; priv->temperature = iwl_hw_reg_txpower_get_temperature(priv); temp_diff = priv->temperature - priv->last_temperature; /* get absolute value */ if (temp_diff < 0) { IWL_DEBUG_POWER("Getting cooler, delta %d,\n", temp_diff); temp_diff = -temp_diff; } else if (temp_diff == 0) IWL_DEBUG_POWER("Same temp,\n"); else IWL_DEBUG_POWER("Getting warmer, delta %d,\n", temp_diff); /* if we don't need calibration, *don't* update last_temperature */ if (temp_diff < IWL_TEMPERATURE_LIMIT_TIMER) { IWL_DEBUG_POWER("Timed thermal calib not needed\n"); return 0; } IWL_DEBUG_POWER("Timed thermal calib needed\n"); /* assume that caller will actually do calib ... * update the "last temperature" value */ priv->last_temperature = priv->temperature; return 1;}#define IWL_MAX_GAIN_ENTRIES 78#define IWL_CCK_FROM_OFDM_POWER_DIFF -5#define IWL_CCK_FROM_OFDM_INDEX_DIFF (10)/* radio and DSP power table, each step is 1/2 dB. * 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */static struct iwl_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = { { {251, 127}, /* 2.4 GHz, highest power */ {251, 127}, {251, 127}, {251, 127}, {251, 125}, {251, 110}, {251, 105}, {251, 98}, {187, 125}, {187, 115}, {187, 108}, {187, 99}, {243, 119}, {243, 111}, {243, 105}, {243, 97}, {243, 92}, {211, 106}, {211, 100}, {179, 120}, {179, 113}, {179, 107}, {147, 125}, {147, 119}, {147, 112}, {147, 106}, {147, 101}, {147, 97}, {147, 91}, {115, 107}, {235, 121}, {235, 115}, {235, 109}, {203, 127}, {203, 121}, {203, 115}, {203, 108}, {203, 102}, {203, 96}, {203, 92}, {171, 110}, {171, 104}, {171, 98}, {139, 116}, {227, 125}, {227, 119}, {227, 113}, {227, 107}, {227, 101}, {227, 96}, {195, 113}, {195, 106}, {195, 102}, {195, 95}, {163, 113}, {163, 106}, {163, 102}, {163, 95}, {131, 113}, {131, 106}, {131, 102}, {131, 95}, {99, 113}, {99, 106}, {99, 102}, {99, 95}, {67, 113}, {67, 106}, {67, 102}, {67, 95}, {35, 113}, {35, 106}, {35, 102}, {35, 95}, {3, 113}, {3, 106}, {3, 102}, {3, 95} }, /* 2.4 GHz, lowest power */ { {251, 127}, /* 5.x GHz, highest power */ {251, 120}, {251, 114}, {219, 119}, {219, 101}, {187, 113}, {187, 102}, {155, 114}, {155, 103}, {123, 117}, {123, 107}, {123, 99}, {123, 92}, {91, 108}, {59, 125}, {59, 118}, {59, 109}, {59, 102}, {59, 96}, {59, 90}, {27, 104}, {27, 98}, {27, 92}, {115, 118}, {115, 111}, {115, 104}, {83, 126}, {83, 121}, {83, 113}, {83, 105}, {83, 99},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -