⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rt2500pci.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");	for (i = 0; i < EEPROM_BBP_SIZE; i++) {		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);		if (eeprom != 0xffff && eeprom != 0x0000) {			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);			value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);			DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",			      reg_id, value);			rt2500pci_bbp_write(rt2x00dev, reg_id, value);		}	}	DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");	return 0;}/* * Device state switch handlers. */static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev,				enum dev_state state){	u32 reg;	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);	rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX,			   state == STATE_RADIO_RX_OFF);	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);}static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,				 enum dev_state state){	int mask = (state == STATE_RADIO_IRQ_OFF);	u32 reg;	/*	 * When interrupts are being enabled, the interrupt registers	 * should clear the register to assure a clean state.	 */	if (state == STATE_RADIO_IRQ_ON) {		rt2x00pci_register_read(rt2x00dev, CSR7, &reg);		rt2x00pci_register_write(rt2x00dev, CSR7, reg);	}	/*	 * Only toggle the interrupts bits we are going to use.	 * Non-checked interrupt bits are disabled by default.	 */	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);	rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);	rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);	rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);	rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);	rt2x00_set_field32(&reg, CSR8_RXDONE, mask);	rt2x00pci_register_write(rt2x00dev, CSR8, reg);}static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev){	/*	 * Initialize all registers.	 */	if (rt2500pci_init_rings(rt2x00dev) ||	    rt2500pci_init_registers(rt2x00dev) ||	    rt2500pci_init_bbp(rt2x00dev)) {		ERROR(rt2x00dev, "Register initialization failed.\n");		return -EIO;	}	/*	 * Enable interrupts.	 */	rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);	/*	 * Enable LED	 */	rt2500pci_enable_led(rt2x00dev);	return 0;}static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev){	u32 reg;	/*	 * Disable LED	 */	rt2500pci_disable_led(rt2x00dev);	rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);	/*	 * Disable synchronisation.	 */	rt2x00pci_register_write(rt2x00dev, CSR14, 0);	/*	 * Cancel RX and TX.	 */	rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);	rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);	rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);	/*	 * Disable interrupts.	 */	rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF);}static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,			       enum dev_state state){	u32 reg;	unsigned int i;	char put_to_sleep;	char bbp_state;	char rf_state;	put_to_sleep = (state != STATE_AWAKE);	rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg);	rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);	rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);	rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);	rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);	rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);	/*	 * Device is not guaranteed to be in the requested state yet.	 * We must wait until the register indicates that the	 * device has entered the correct state.	 */	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {		rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg);		bbp_state = rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE);		rf_state = rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE);		if (bbp_state == state && rf_state == state)			return 0;		msleep(10);	}	NOTICE(rt2x00dev, "Device failed to enter state %d, "	       "current device state: bbp %d and rf %d.\n",	       state, bbp_state, rf_state);	return -EBUSY;}static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,				      enum dev_state state){	int retval = 0;	switch (state) {	case STATE_RADIO_ON:		retval = rt2500pci_enable_radio(rt2x00dev);		break;	case STATE_RADIO_OFF:		rt2500pci_disable_radio(rt2x00dev);		break;	case STATE_RADIO_RX_ON:	case STATE_RADIO_RX_OFF:		rt2500pci_toggle_rx(rt2x00dev, state);		break;	case STATE_DEEP_SLEEP:	case STATE_SLEEP:	case STATE_STANDBY:	case STATE_AWAKE:		retval = rt2500pci_set_state(rt2x00dev, state);		break;	default:		retval = -ENOTSUPP;		break;	}	return retval;}/* * TX descriptor initialization */static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,				    struct data_desc *txd,				    struct txdata_entry_desc *desc,				    struct ieee80211_hdr *ieee80211hdr,				    unsigned int length,				    struct ieee80211_tx_control *control){	u32 word;	/*	 * Start writing the descriptor words.	 */	rt2x00_desc_read(txd, 2, &word);	rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);	rt2x00_set_field32(&word, TXD_W2_AIFS, desc->aifs);	rt2x00_set_field32(&word, TXD_W2_CWMIN, desc->cw_min);	rt2x00_set_field32(&word, TXD_W2_CWMAX, desc->cw_max);	rt2x00_desc_write(txd, 2, word);	rt2x00_desc_read(txd, 3, &word);	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal);	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service);	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, desc->length_low);	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, desc->length_high);	rt2x00_desc_write(txd, 3, word);	rt2x00_desc_read(txd, 10, &word);	rt2x00_set_field32(&word, TXD_W10_RTS,			   test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags));	rt2x00_desc_write(txd, 10, word);	rt2x00_desc_read(txd, 0, &word);	rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);	rt2x00_set_field32(&word, TXD_W0_VALID, 1);	rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,			   test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));	rt2x00_set_field32(&word, TXD_W0_ACK,			   !(control->flags & IEEE80211_TXCTL_NO_ACK));	rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));	rt2x00_set_field32(&word, TXD_W0_OFDM,			   test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));	rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1);	rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,			   !!(control->flags &			      IEEE80211_TXCTL_LONG_RETRY_LIMIT));	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length);	rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);	rt2x00_desc_write(txd, 0, word);}/* * TX data initialization */static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,				    unsigned int queue){	u32 reg;	if (queue == IEEE80211_TX_QUEUE_BEACON) {		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);		if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {			rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);			rt2x00pci_register_write(rt2x00dev, CSR14, reg);		}		return;	}	rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);	if (queue == IEEE80211_TX_QUEUE_DATA0)		rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);	else if (queue == IEEE80211_TX_QUEUE_DATA1)		rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);	else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)		rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);	rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);}/* * RX control handlers */static void rt2500pci_fill_rxdone(struct data_entry *entry,				  struct rxdata_entry_desc *desc){	struct data_desc *rxd = entry->priv;	u32 word0;	u32 word2;	rt2x00_desc_read(rxd, 0, &word0);	rt2x00_desc_read(rxd, 2, &word2);	desc->flags = 0;	if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))		desc->flags |= RX_FLAG_FAILED_FCS_CRC;	if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))		desc->flags |= RX_FLAG_FAILED_PLCP_CRC;	desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);	desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -	    entry->ring->rt2x00dev->rssi_offset;	desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);	desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);}/* * Interrupt functions. */static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue){	struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);	struct data_entry *entry;	struct data_desc *txd;	u32 word;	int tx_status;	int retry;	while (!rt2x00_ring_empty(ring)) {		entry = rt2x00_get_data_entry_done(ring);		txd = entry->priv;		rt2x00_desc_read(txd, 0, &word);		if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||		    !rt2x00_get_field32(word, TXD_W0_VALID))			break;		/*		 * Obtain the status about this packet.		 */		tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);		retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);		rt2x00lib_txdone(entry, tx_status, retry);		/*		 * Make this entry available for reuse.		 */		entry->flags = 0;		rt2x00_set_field32(&word, TXD_W0_VALID, 0);		rt2x00_desc_write(txd, 0, word);		rt2x00_ring_index_done_inc(ring);	}	/*	 * If the data ring was full before the txdone handler	 * we must make sure the packet queue in the mac80211 stack	 * is reenabled when the txdone handler has finished.	 */	entry = ring->entry;	if (!rt2x00_ring_full(ring))		ieee80211_wake_queue(rt2x00dev->hw,				     entry->tx_status.control.queue);}static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance){	struct rt2x00_dev *rt2x00dev = dev_instance;	u32 reg;	/*	 * Get the interrupt sources & saved to local variable.	 * Write register value back to clear pending interrupts.	 */	rt2x00pci_register_read(rt2x00dev, CSR7, &reg);	rt2x00pci_register_write(rt2x00dev, CSR7, reg);	if (!reg)		return IRQ_NONE;	if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))		return IRQ_HANDLED;	/*	 * Handle interrupts, walk through all bits	 * and run the tasks, the bits are checked in order of	 * priority.	 */	/*	 * 1 - Beacon timer expired interrupt.	 */	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))		rt2x00lib_beacondone(rt2x00dev);	/*	 * 2 - Rx ring done interrupt.	 */	if (rt2x00_get_field32(reg, CSR7_RXDONE))		rt2x00pci_rxdone(rt2x00dev);	/*	 * 3 - Atim ring transmit done interrupt.	 */	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))		rt2500pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);	/*	 * 4 - Priority ring transmit done interrupt.	 */	if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))		rt2500pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);	/*	 * 5 - Tx ring transmit done interrupt.	 */	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))		rt2500pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);	return IRQ_HANDLED;}/* * Device probe functions. */static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev){	struct eeprom_93cx6 eeprom;	u32 reg;	u16 word;	u8 *mac;	rt2x00pci_register_read(rt2x00dev, CSR21, &reg);	eeprom.data = rt2x00dev;	eeprom.register_read = rt2500pci_eepromregister_read;	eeprom.register_write = rt2500pci_eepromregister_write;	eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ?	    PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66;	eeprom.reg_data_in = 0;	eeprom.reg_data_out = 0;	eeprom.reg_data_clock = 0;	eeprom.reg_chip_select = 0;	eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,			       EEPROM_SIZE / sizeof(u16));	/*	 * Start validation of the data that has been read.	 */	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);	if (!is_valid_ether_addr(mac)) {		DECLARE_MAC_BUF(macbuf);		random_ether_addr(mac);		EEPROM(rt2x00dev, "MAC: %s\n",		       print_mac(macbuf, mac));	}	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);	if (word == 0xffff) {		rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);		rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, 0);		rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, 0);		rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, 0);		rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);		rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);	}	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);	if (word == 0xffff) {		rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);		rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);		rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);	}	rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);	if (word == 0xffff) {		rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,				   DEFAULT_RSSI_OFFSET);		rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);		EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word);	}	return 0;}static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev){	u32 reg;	u16 value;	u16 eeprom;	/*	 * Read EEPROM word for configuration.	 */	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);	/*	 * Identify RF chipset.	 */	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);	rt2x00pci_register_read(rt2x00dev, CSR0, &reg);	rt2x00_set_chip(rt2x00dev, RT2560, value, reg);	if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&	    !rt2x00_rf(&rt2x00dev->chip, RF2523) &&	    !rt2x00_rf(&rt2x00dev->chip, RF2524) &&	    !rt2x00_rf(&rt2x00dev->chip, RF2525) &&	    !rt2x00_rf(&rt2x00dev->chip, RF2525E) &&	    !rt2x00_rf(&rt2x00dev->chip, RF5222)) {		ERROR(rt2x00dev, "Invalid RF chipset detected.\n");		return -ENODEV;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -