static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) { unsigned int i; u32 reg; /* * SOC devices don't support MCU requests. */ if (rt2x00_is_soc(rt2x00dev)) return; for (i = 0; i < 200; i++) { rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD2) == token) || (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD3) == token)) break; udelay(REGISTER_BUSY_DELAY); } if (i == 200) ERROR(rt2x00dev, "MCU request failed, no response from hardware\n"); rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); }
/* * Interrupt functions. */ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const enum ieee80211_tx_queue queue_idx) { struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); struct queue_entry_priv_pci_tx *priv_tx; struct queue_entry *entry; struct txdone_entry_desc txdesc; u32 word; while (!rt2x00queue_empty(queue)) { entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); priv_tx = entry->priv_data; rt2x00_desc_read(priv_tx->desc, 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. */ txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT); txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); rt2x00pci_txdone(rt2x00dev, entry, &txdesc); } }
static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) { struct rt2x00_dev *rt2x00dev = dev_instance; u32 reg = rt2x00dev->irqvalue[0]; /* * 1 - Pre TBTT interrupt. */ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) rt2x00lib_pretbtt(rt2x00dev); /* * 2 - Beacondone interrupt. */ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) rt2x00lib_beacondone(rt2x00dev); /* * 3 - Rx ring done interrupt. */ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) rt2x00pci_rxdone(rt2x00dev); /* * 4 - Auto wakeup interrupt. */ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) rt2800pci_wakeup(rt2x00dev); /* Enable interrupts again. */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_ON_ISR); return IRQ_HANDLED; }
/* * RX control handlers */ void rt2800mmio_fill_rxdone(struct queue_entry *entry, struct rxdone_entry_desc *rxdesc) { struct queue_entry_priv_mmio *entry_priv = entry->priv_data; __le32 *rxd = entry_priv->desc; u32 word; word = rt2x00_desc_read(rxd, 3); if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; /* * Unfortunately we don't know the cipher type used during * decryption. This prevents us from correct providing * correct statistics through debugfs. */ rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR); if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) { /* * Hardware has stripped IV/EIV data from 802.11 frame during * decryption. Unfortunately the descriptor doesn't contain * any fields with the EIV/IV data either, so they can't * be restored by rt2x00lib. */ rxdesc->flags |= RX_FLAG_IV_STRIPPED; /* * The hardware has already checked the Michael Mic and has * stripped it from the frame. Signal this to mac80211. */ rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) { rxdesc->flags |= RX_FLAG_DECRYPTED; } else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) { /* * In order to check the Michael Mic, the packet must have * been decrypted. Mac80211 doesnt check the MMIC failure * flag to initiate MMIC countermeasures if the decoded flag * has not been set. */ rxdesc->flags |= RX_FLAG_DECRYPTED; rxdesc->flags |= RX_FLAG_MMIC_ERROR; } } if (rt2x00_get_field32(word, RXD_W3_MY_BSS)) rxdesc->dev_flags |= RXDONE_MY_BSS; if (rt2x00_get_field32(word, RXD_W3_L2PAD)) rxdesc->dev_flags |= RXDONE_L2PAD; /* * Process the RXWI structure that is at the start of the buffer. */ rt2800_process_rxwi(entry, rxdesc); }
static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) { u32 reg, reg2; unsigned int i; char put_to_sleep; char bbp_state; char rf_state; put_to_sleep = (state != STATE_AWAKE); rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1); rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state); rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state); rt2x00_set_field32(®, 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, ®2); bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE); rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE); if (bbp_state == state && rf_state == state) return 0; rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); msleep(10); } return -EBUSY; }
static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) { u32 reg, reg2; unsigned int i; char put_to_sleep; char bbp_state; char rf_state; put_to_sleep = (state != STATE_AWAKE); rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1); rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state); rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state); rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep); rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®2); bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE); rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE); if (bbp_state == state && rf_state == state) return 0; rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); msleep(10); } return -EBUSY; }
static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue_idx) { struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx); struct queue_entry_priv_pci *entry_priv; struct queue_entry *entry; struct txdone_entry_desc txdesc; u32 word; while (!rt2x00queue_empty(queue)) { entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); entry_priv = entry->priv_data; rt2x00_desc_read(entry_priv->desc, 0, &word); if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || !rt2x00_get_field32(word, TXD_W0_VALID)) break; txdesc.flags = 0; switch (rt2x00_get_field32(word, TXD_W0_RESULT)) { case 0: case 1: __set_bit(TXDONE_SUCCESS, &txdesc.flags); break; case 2: __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags); default: __set_bit(TXDONE_FAILURE, &txdesc.flags); } txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); rt2x00lib_txdone(entry, &txdesc); } }
static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) { struct rt2x00_dev *rt2x00dev = dev_instance; u32 reg; /* Read status and ACK all interrupts */ rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); if (!reg) return IRQ_NONE; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; /* * 1 - Rx ring done interrupt. */ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) rt2x00pci_rxdone(rt2x00dev); if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) rt2800pci_txdone(rt2x00dev); return IRQ_HANDLED; }
/* * RX control handlers */ static void rt2400pci_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; /* * Obtain the status about this packet. */ 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 = 0; desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); }
static irqreturn_t rt2400pci_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, ®); rt2x00pci_register_write(rt2x00dev, CSR7, reg); if (!reg) return IRQ_NONE; if (!test_bit(DEVICE_STATE_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)) rt2400pci_txdone(rt2x00dev, QID_ATIM); /* * 4 - Priority ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) rt2400pci_txdone(rt2x00dev, QID_AC_BE); /* * 5 - Tx ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) rt2400pci_txdone(rt2x00dev, QID_AC_BK); return IRQ_HANDLED; }
/* * RX control handlers */ static void rt2800pci_fill_rxdone(struct queue_entry *entry, struct rxdone_entry_desc *rxdesc) { struct queue_entry_priv_pci *entry_priv = entry->priv_data; __le32 *rxd = entry_priv->desc; u32 word; rt2x00_desc_read(rxd, 3, &word); if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; /* * Unfortunately we don't know the cipher type used during * decryption. This prevents us from correct providing * correct statistics through debugfs. */ rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR); if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) { /* * Hardware has stripped IV/EIV data from 802.11 frame during * decryption. Unfortunately the descriptor doesn't contain * any fields with the EIV/IV data either, so they can't * be restored by rt2x00lib. */ rxdesc->flags |= RX_FLAG_IV_STRIPPED; /* * The hardware has already checked the Michael Mic and has * stripped it from the frame. Signal this to mac80211. */ rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) rxdesc->flags |= RX_FLAG_DECRYPTED; else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) rxdesc->flags |= RX_FLAG_MMIC_ERROR; } if (rt2x00_get_field32(word, RXD_W3_MY_BSS)) rxdesc->dev_flags |= RXDONE_MY_BSS; if (rt2x00_get_field32(word, RXD_W3_L2PAD)) rxdesc->dev_flags |= RXDONE_L2PAD; /* * Process the RXWI structure that is at the start of the buffer. */ rt2800_process_rxwi(entry, rxdesc); /* * Remove RXWI descriptor from start of buffer. */ skb_pull(entry->skb, RXWI_DESC_SIZE); }
static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) { struct rt2x00_dev *rt2x00dev = dev_instance; u32 reg, mask; unsigned long flags; /* Read status and ACK all interrupts */ rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); if (!reg) return IRQ_NONE; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; /* * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits * for interrupts and interrupt masks we can just use the value of * INT_SOURCE_CSR to create the interrupt mask. */ mask = ~reg; if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { rt2800pci_txstatus_interrupt(rt2x00dev); /* * Never disable the TX_FIFO_STATUS interrupt. */ rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1); } if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet); if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) tasklet_schedule(&rt2x00dev->rxdone_tasklet); if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) tasklet_schedule(&rt2x00dev->autowake_tasklet); /* * Disable all interrupts for which a tasklet was scheduled right now, * the tasklet will reenable the appropriate interrupts. */ spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); reg &= mask; rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); return IRQ_HANDLED; }
static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; u64 tsf; u32 reg; rt2x00pci_register_read(rt2x00dev, CSR17, ®); tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; rt2x00pci_register_read(rt2x00dev, CSR16, ®); tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER); return tsf; }
static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) { struct rt2x00_dev *rt2x00dev = eeprom->data; u32 reg; rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); eeprom->reg_data_clock = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_CLOCK); eeprom->reg_chip_select = !!rt2x00_get_field32(reg, E2PROM_CSR_CHIP_SELECT); }
static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) { struct rt2x00_dev *rt2x00dev = dev_instance; u32 reg; irqreturn_t ret = IRQ_HANDLED; /* Read status and ACK all interrupts */ rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); if (!reg) return IRQ_NONE; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) rt2800pci_txstatus_interrupt(rt2x00dev); if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT) || rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT) || rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE) || rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) { /* * All other interrupts are handled in the interrupt thread. * Store irqvalue for use in the interrupt thread. */ rt2x00dev->irqvalue[0] = reg; /* * Disable interrupts, will be enabled again in the * interrupt thread. */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF_ISR); /* * Leave the TX_FIFO_STATUS interrupt enabled to not lose any * tx status reports. */ rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); ret = IRQ_WAKE_THREAD; } return ret; }
/* * Initialization functions. */ static bool rt2800pci_get_entry_state(struct queue_entry *entry) { struct queue_entry_priv_pci *entry_priv = entry->priv_data; u32 word; if (entry->queue->qid == QID_RX) { rt2x00_desc_read(entry_priv->desc, 1, &word); return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE)); } else { rt2x00_desc_read(entry_priv->desc, 1, &word); return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE)); } }
/* * Initialization functions. */ static bool rt2400pci_get_entry_state(struct queue_entry *entry) { struct queue_entry_priv_pci *entry_priv = entry->priv_data; u32 word; if (entry->queue->qid == QID_RX) { rt2x00_desc_read(entry_priv->desc, 0, &word); return rt2x00_get_field32(word, RXD_W0_OWNER_NIC); } else { rt2x00_desc_read(entry_priv->desc, 0, &word); return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || rt2x00_get_field32(word, TXD_W0_VALID)); } }
static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) { u32 reg; rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); return rt2x00_get_field32(reg, GPIOCSR_BIT0); }
/* * TX data initialization */ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const unsigned int queue) { u32 reg; if (queue == RT2X00_BCN_QUEUE_BEACON) { rt2x00pci_register_read(rt2x00dev, CSR14, ®); if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) { rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); rt2x00_set_field32(®, CSR14_TBCN, 1); rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); rt2x00pci_register_write(rt2x00dev, CSR14, reg); } return; } rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue == IEEE80211_TX_QUEUE_DATA0)); rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue == IEEE80211_TX_QUEUE_DATA1)); rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue == RT2X00_BCN_QUEUE_ATIM)); rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); }
static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u32 value) { u32 reg; unsigned int i; if (!word) return; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2x00pci_register_read(rt2x00dev, RFCSR, ®); if (!rt2x00_get_field32(reg, RFCSR_BUSY)) goto rf_write; udelay(REGISTER_BUSY_DELAY); } ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n"); return; rf_write: reg = 0; rt2x00_set_field32(®, RFCSR_VALUE, value); rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); rt2x00_set_field32(®, RFCSR_BUSY, 1); rt2x00pci_register_write(rt2x00dev, RFCSR, reg); rt2x00_rf_write(rt2x00dev, word, value); }
static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) { u32 reg; /* * Wait until the BBP becomes ready. */ reg = rt2400pci_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n"); return; } /* * Write the data into the BBP. */ reg = 0; rt2x00_set_field32(®, BBPCSR_VALUE, value); rt2x00_set_field32(®, BBPCSR_REGNUM, word); rt2x00_set_field32(®, BBPCSR_BUSY, 1); rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); }
static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, const unsigned int word, u8 *value) { u32 reg; mutex_lock(&rt2x00dev->csr_mutex); /* * Wait until the BBP becomes available, afterwards we * can safely write the read request into the register. * After the data has been written, we wait until hardware * returns the correct value, if at any time the register * doesn't become available in time, reg will be 0xffffffff * which means we return 0xff to the caller. */ if (WAIT_FOR_BBP(rt2x00dev, ®)) { reg = 0; rt2x00_set_field32(®, BBPCSR_REGNUM, word); rt2x00_set_field32(®, BBPCSR_BUSY, 1); rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); WAIT_FOR_BBP(rt2x00dev, ®); } *value = rt2x00_get_field32(reg, BBPCSR_VALUE); mutex_unlock(&rt2x00dev->csr_mutex); }
static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) { struct eeprom_93cx6 eeprom; u32 reg; rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); eeprom.data = rt2x00dev; eeprom.register_read = rt2800pci_eepromregister_read; eeprom.register_write = rt2800pci_eepromregister_write; switch (rt2x00_get_field32(reg, E2PROM_CSR_TYPE)) { case 0: eeprom.width = PCI_EEPROM_WIDTH_93C46; break; case 1: eeprom.width = PCI_EEPROM_WIDTH_93C66; break; default: eeprom.width = PCI_EEPROM_WIDTH_93C86; break; } 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)); }
static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue_idx) { struct data_queue *queue; unsigned int idx, qidx = 0; u32 reg; if (queue_idx == QID_BEACON) { rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) { rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); } return; } if (queue_idx > QID_HCCA && queue_idx != QID_MGMT) return; queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); idx = queue->index[Q_INDEX]; if (queue_idx == QID_MGMT) qidx = 5; else qidx = queue_idx; rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx); }
static void rt2x00_interrupt_rxdone(struct _data_ring * ring, nanosecs_t *time_stamp) { struct _rt2x00_pci * rt2x00pci = rt2x00_priv(ring->device); struct rtnet_device * rtnet_dev = ring->device->rtnet_dev; struct rtwlan_device * rtwlan = rtnetdev_priv(rtnet_dev); struct _rxd * rxd = NULL; struct rtskb * rtskb; void * data = NULL; u16 size = 0x0000; /* u16 rssi = 0x0000; */ while(1){ rxd = DESC_ADDR(ring); data = DATA_ADDR(ring); if(rt2x00_get_field32(rxd->word0, RXD_W0_OWNER_NIC)) break; size = rt2x00_get_field32(rxd->word0, RXD_W0_DATABYTE_COUNT); /* rssi = rt2x00_get_field32(rxd->word2, RXD_W2_RSSI); */ /* prepare rtskb */ rtskb = dev_alloc_rtskb(size + NET_IP_ALIGN, &rtwlan->skb_pool); if(!rtskb){ ERROR("Couldn't allocate rtskb, packet dropped.\n"); break; } rtskb->rtdev = rtnet_dev; rtskb->time_stamp = *time_stamp; rtskb_reserve(rtskb, NET_IP_ALIGN); memcpy(rtskb->data, data, size); rtskb_put(rtskb, size); /* give incoming frame to rtwlan stack */ rtwlan_rx(rtskb, rtnet_dev); /* forward rtskb to rtnet */ rtnetif_rx(rtskb); rtwlan->stats.rx_packets++; rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1); rt2x00_ring_index_inc(&rt2x00pci->rx); } }
static int rt2800pci_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) { unsigned int i; u32 reg; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) return 0; msleep(1); } ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); return -EACCES; }
static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance) { struct rt2x00_dev *rt2x00dev = dev_instance; u32 reg = rt2x00dev->irqvalue[0]; /* * 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)) rt2400pci_txdone(rt2x00dev, QID_ATIM); /* * 4 - Priority ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) rt2400pci_txdone(rt2x00dev, QID_AC_BE); /* * 5 - Tx ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) rt2400pci_txdone(rt2x00dev, QID_AC_BK); /* Enable interrupts again. */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_ON_ISR); return IRQ_HANDLED; }
static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; u32 reg; rt2x00pci_register_read(rt2x00dev, CSR15, ®); return rt2x00_get_field32(reg, CSR15_BEACON_SENT); }
/* * Interrupt routines. * rt2x00_interrupt_txdone processes all transmitted packetss results. * rt2x00_interrupt_rxdone processes all received rx packets. */ static void rt2x00_interrupt_txdone(struct _data_ring * ring) { struct rtwlan_device * rtwlan = rtnetdev_priv(ring->device->rtnet_dev); struct _txd *txd = NULL; u8 tx_result = 0x00; /* u8 retry_count = 0x00; */ do{ txd = DESC_ADDR_DONE(ring); if(rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) || !rt2x00_get_field32(txd->word0, TXD_W0_VALID)) break; if(ring->ring_type == RING_TX){ tx_result = rt2x00_get_field32(txd->word0, TXD_W0_RESULT); /* retry_count = rt2x00_get_field32(txd->word0, TXD_W0_RETRY_COUNT); */ switch(tx_result) { case TX_SUCCESS: rtwlan->stats.tx_packets++; break; case TX_SUCCESS_RETRY: rtwlan->stats.tx_retry++; break; case TX_FAIL_RETRY: DEBUG("TX_FAIL_RETRY.\n"); break; case TX_FAIL_INVALID: DEBUG("TX_FAIL_INVALID.\n"); break; case TX_FAIL_OTHER: DEBUG("TX_FAIL_OTHER.\n"); break; default: DEBUG("Unknown tx result.\n"); } } rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0); rt2x00_ring_index_done_inc(ring); }while(!rt2x00_ring_empty(ring)); }
/* * Interrupt functions. */ static void rt2400pci_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); }