static void rt2800usb_stop_queue(struct data_queue *queue) { struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; u32 reg; switch (queue->qid) { case QID_RX: rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); break; case QID_BEACON: rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); break; default: break; } }
/* * Watchdog handlers */ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev) { unsigned int i; u32 reg; rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) { WARNING(rt2x00dev, "TX HW queue 0 timed out," " invoke forced kick\n"); rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012); for (i = 0; i < 10; i++) { udelay(10); if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) break; } rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); } rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) { WARNING(rt2x00dev, "TX HW queue 1 timed out," " invoke forced kick\n"); rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a); for (i = 0; i < 10; i++) { udelay(10); if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) break; } rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); } rt2x00usb_watchdog(rt2x00dev); }
static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) { unsigned int i; u32 reg; for (i = 0; i < 200; i++) { rt2800_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"); rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); }
static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom) { struct rt2x00_dev *rt2x00dev = eeprom->data; u32 reg = 0; rt2x00_set_field32(®, E2PROM_CSR_DATA_IN, !!eeprom->reg_data_in); rt2x00_set_field32(®, E2PROM_CSR_DATA_OUT, !!eeprom->reg_data_out); rt2x00_set_field32(®, E2PROM_CSR_DATA_CLOCK, !!eeprom->reg_data_clock); rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, !!eeprom->reg_chip_select); rt2800_register_write(rt2x00dev, E2PROM_CSR, reg); }
/* * Device state switch handlers. */ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, enum dev_state state) { int mask = (state == STATE_RADIO_IRQ_ON) || (state == STATE_RADIO_IRQ_ON_ISR); 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) { rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); } rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, 0); rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, 0); rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, mask); rt2x00_set_field32(®, INT_MASK_CSR_AC0_DMA_DONE, 0); rt2x00_set_field32(®, INT_MASK_CSR_AC1_DMA_DONE, 0); rt2x00_set_field32(®, INT_MASK_CSR_AC2_DMA_DONE, 0); rt2x00_set_field32(®, INT_MASK_CSR_AC3_DMA_DONE, 0); rt2x00_set_field32(®, INT_MASK_CSR_HCCA_DMA_DONE, 0); rt2x00_set_field32(®, INT_MASK_CSR_MGMT_DMA_DONE, 0); rt2x00_set_field32(®, INT_MASK_CSR_MCU_COMMAND, 0); rt2x00_set_field32(®, INT_MASK_CSR_RXTX_COHERENT, 0); rt2x00_set_field32(®, INT_MASK_CSR_TBTT, mask); rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, mask); rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, mask); rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, mask); rt2x00_set_field32(®, INT_MASK_CSR_GPTIMER, 0); rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, 0); rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, 0); rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); }
static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; int i; /* * Wait until BBP and RF are ready. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, MAC_CSR0, ®); if (reg && reg != ~0) break; msleep(1); } if (i == REGISTER_BUSY_COUNT) { ERROR(rt2x00dev, "Unstable hardware.\n"); return -EBUSY; } rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, USB_MODE_RESET, REGISTER_TIMEOUT); rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); return 0; }
static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { u32 reg; if (queue != QID_BEACON) { rt2x00usb_kick_tx_queue(rt2x00dev, queue); return; } 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); } }
static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev))) return -EIO; rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); /* * Total room for RX frames in kilobytes, PBF might still exceed * this limit so reduce the number to prevent errors. */ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg); return rt2800_enable_radio(rt2x00dev); }
/* * TX data initialization */ static void rt2800usb_write_beacon(struct queue_entry *entry) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); unsigned int beacon_base; u32 reg; /* * Add the descriptor in front of the skb. */ skb_push(entry->skb, entry->queue->desc_size); memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); skbdesc->desc = entry->skb->data; /* * Disable beaconing while we are reloading the beacon data, * otherwise we might be sending out invalid data. */ rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); /* * Write entire beacon with descriptor to register. */ beacon_base = HW_BEACON_OFFSET(entry->entry_idx); rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, beacon_base, entry->skb->data, entry->skb->len, REGISTER_TIMEOUT32(entry->skb->len)); /* * Clean up the beacon skb. */ dev_kfree_skb(entry->skb); entry->skb = NULL; }
/* * RX control handlers */ static void rt2800pci_fill_rxdone(struct queue_entry *entry, struct rxdone_entry_desc *rxdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); struct queue_entry_priv_pci *entry_priv = entry->priv_data; __le32 *rxd = entry_priv->desc; __le32 *rxwi = (__le32 *)entry->skb->data; u32 rxd3; u32 rxwi0; u32 rxwi1; u32 rxwi2; u32 rxwi3; rt2x00_desc_read(rxd, 3, &rxd3); rt2x00_desc_read(rxwi, 0, &rxwi0); rt2x00_desc_read(rxwi, 1, &rxwi1); rt2x00_desc_read(rxwi, 2, &rxwi2); rt2x00_desc_read(rxwi, 3, &rxwi3); if (rt2x00_get_field32(rxd3, RXD_W3_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { /* * Unfortunately we don't know the cipher type used during * decryption. This prevents us from correct providing * correct statistics through debugfs. */ rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); rxdesc->cipher_status = rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR); } if (rt2x00_get_field32(rxd3, 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; 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(rxd3, RXD_W3_MY_BSS)) rxdesc->dev_flags |= RXDONE_MY_BSS; if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) { rxdesc->dev_flags |= RXDONE_L2PAD; skbdesc->flags |= SKBDESC_L2_PADDED; } if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) rxdesc->flags |= RX_FLAG_SHORT_GI; if (rt2x00_get_field32(rxwi1, RXWI_W1_BW)) rxdesc->flags |= RX_FLAG_40MHZ; /* * Detect RX rate, always use MCS as signal type. */ rxdesc->dev_flags |= RXDONE_SIGNAL_MCS; rxdesc->rate_mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE); rxdesc->signal = rt2x00_get_field32(rxwi1, RXWI_W1_MCS); /* * Mask of 0x8 bit to remove the short preamble flag. */ if (rxdesc->rate_mode == RATE_MODE_CCK) rxdesc->signal &= ~0x8; rxdesc->rssi = (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; rxdesc->noise = (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2; rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); /* * Set RX IDX in register to inform hardware that we have handled * this entry and it is available for reuse again. */ rt2800_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx); /* * Remove TXWI descriptor from start of buffer. */ skb_pull(entry->skb, RXWI_DESC_SIZE); skb_trim(entry->skb, rxdesc->size); }
static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) { struct queue_entry_priv_pci *entry_priv; u32 reg; rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); /* * Initialize registers. */ entry_priv = rt2x00dev->tx[0].entries[0].priv_data; rt2800_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); rt2800_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit); rt2800_register_write(rt2x00dev, TX_CTX_IDX0, 0); rt2800_register_write(rt2x00dev, TX_DTX_IDX0, 0); entry_priv = rt2x00dev->tx[1].entries[0].priv_data; rt2800_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); rt2800_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit); rt2800_register_write(rt2x00dev, TX_CTX_IDX1, 0); rt2800_register_write(rt2x00dev, TX_DTX_IDX1, 0); entry_priv = rt2x00dev->tx[2].entries[0].priv_data; rt2800_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); rt2800_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit); rt2800_register_write(rt2x00dev, TX_CTX_IDX2, 0); rt2800_register_write(rt2x00dev, TX_DTX_IDX2, 0); entry_priv = rt2x00dev->tx[3].entries[0].priv_data; rt2800_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); rt2800_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit); rt2800_register_write(rt2x00dev, TX_CTX_IDX3, 0); rt2800_register_write(rt2x00dev, TX_DTX_IDX3, 0); entry_priv = rt2x00dev->rx->entries[0].priv_data; rt2800_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); rt2800_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit); rt2800_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1); rt2800_register_write(rt2x00dev, RX_DRX_IDX, 0); /* * Enable global DMA configuration */ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); rt2800_register_write(rt2x00dev, DELAY_INT_CFG, 0); return 0; }
static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len) { unsigned int i; u32 reg; /* * Wait for stable hardware. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, MAC_CSR0, ®); if (reg && reg != ~0) break; msleep(1); } if (i == REGISTER_BUSY_COUNT) { ERROR(rt2x00dev, "Unstable hardware.\n"); return -EBUSY; } rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000); /* * Disable DMA, will be reenabled later when enabling * the radio. */ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); /* * enable Host program ram write selection */ reg = 0; rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg); /* * Write firmware to device. */ rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, data, len); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); /* * Wait for device to stabilize. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) break; msleep(1); } if (i == REGISTER_BUSY_COUNT) { ERROR(rt2x00dev, "PBF system register not ready.\n"); return -EBUSY; } /* * Disable interrupts */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF); /* * Initialize BBP R/W access agent */ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); return 0; }
static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; u16 word; /* * Initialize all registers. */ if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || rt2800_init_registers(rt2x00dev) || rt2800_init_bbp(rt2x00dev) || rt2800_init_rfcsr(rt2x00dev))) return -EIO; rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); udelay(50); rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); /* * Total room for RX frames in kilobytes, PBF might still exceed * this limit so reduce the number to prevent errors. */ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg); rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); /* * Initialize LED control */ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff, word & 0xff, (word >> 8) & 0xff); rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff, word & 0xff, (word >> 8) & 0xff); rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff, word & 0xff, (word >> 8) & 0xff); return 0; }
static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len) { unsigned int i; int status; u32 reg; u32 offset; u32 length; /* * Check which section of the firmware we need. */ if (rt2x00_rt(rt2x00dev, RT2860) || rt2x00_rt(rt2x00dev, RT2872) || rt2x00_rt(rt2x00dev, RT3070)) { offset = 0; length = 4096; } else { offset = 4096; length = 4096; } /* * Wait for stable hardware. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, MAC_CSR0, ®); if (reg && reg != ~0) break; msleep(1); } if (i == REGISTER_BUSY_COUNT) { ERROR(rt2x00dev, "Unstable hardware.\n"); return -EBUSY; } /* * Write firmware to device. */ rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, FIRMWARE_IMAGE_BASE, data + offset, length, REGISTER_TIMEOUT32(length)); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); /* * Send firmware request to device to load firmware, * we need to specify a long timeout time. */ status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, USB_MODE_FIRMWARE, REGISTER_TIMEOUT_FIRMWARE); if (status < 0) { ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); return status; } msleep(10); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); /* * Send signal to firmware during boot time. */ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071) || rt2x00_rt(rt2x00dev, RT3572)) { udelay(200); rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); udelay(10); } /* * Wait for device to stabilize. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) break; msleep(1); } if (i == REGISTER_BUSY_COUNT) { ERROR(rt2x00dev, "PBF system register not ready.\n"); return -EBUSY; } /* * Initialize firmware. */ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); msleep(1); return 0; }
/* * Interrupt functions. */ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) { struct ieee80211_conf conf = { .flags = 0 }; struct rt2x00lib_conf libconf = { .conf = &conf }; rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); } static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; struct queue_entry *entry; u32 status; u8 qid; while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); if (qid >= QID_RX) { /* * Unknown queue, this shouldn't happen. Just drop * this tx status. */ WARNING(rt2x00dev, "Got TX status report with " "unexpected pid %u, dropping\n", qid); break; } queue = rt2x00queue_get_queue(rt2x00dev, qid); if (unlikely(queue == NULL)) { /* * The queue is NULL, this shouldn't happen. Stop * processing here and drop the tx status */ WARNING(rt2x00dev, "Got TX status for an unavailable " "queue %u, dropping\n", qid); break; } if (rt2x00queue_empty(queue)) { /* * The queue is empty. Stop processing here * and drop the tx status. */ WARNING(rt2x00dev, "Got TX status for an empty " "queue %u, dropping\n", qid); break; } entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); rt2800_txdone_entry(entry, status); } } static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, struct rt2x00_field32 irq_field) { unsigned long flags; u32 reg; /* * Enable a single interrupt. The interrupt mask register * access needs locking. */ spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); rt2x00_set_field32(®, irq_field, 1); rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); }