📄 rt_rt2500pci.c
字号:
u8 reg_rx; u8 reg_tx; rt2x00_register_read(rt2x00pci, BBPCSR1, ®); rt2x00_bbp_regread(rt2x00pci, 14, ®_rx); rt2x00_bbp_regread(rt2x00pci, 2, ®_tx); /* TX antenna select */ if(config->antenna_tx == 1) { /* Antenna A */ reg_tx = (reg_tx & 0xfc) | 0x00; reg = (reg & 0xfffcfffc) | 0x00; } else if(config->antenna_tx == 2) { /* Antenna B */ reg_tx = (reg_tx & 0xfc) | 0x02; reg = (reg & 0xfffcfffc) | 0x00020002; } else { /* Diversity */ reg_tx = (reg_tx & 0xfc) | 0x02; reg = (reg & 0xfffcfffc) | 0x00020002; } /* RX antenna select */ if(config->antenna_rx == 1) reg_rx = (reg_rx & 0xfc) | 0x00; else if(config->antenna_rx == 2) reg_rx = (reg_rx & 0xfc) | 0x02; else reg_rx = (reg_rx & 0xfc) | 0x02; /* * RT2525E and RT5222 need to flip I/Q */ if(rt2x00_rf(&rt2x00pci->chip, RF5222)){ reg |= 0x00040004; reg_tx |= 0x04; } else if(rt2x00_rf(&rt2x00pci->chip, RF2525E)) { reg |= 0x00040004; reg_tx |= 0x04; reg_rx |= 0xfb; } rt2x00_register_write(rt2x00pci, BBPCSR1, reg); rt2x00_bbp_regwrite(rt2x00pci, 14, reg_rx); rt2x00_bbp_regwrite(rt2x00pci, 2, reg_tx);}static voidrt2x00_dev_update_duration(struct _rt2x00_pci *rt2x00pci, struct _rt2x00_config *config) { u32 reg = 0x00000000; DEBUG("Start.\n"); rt2x00_register_read(rt2x00pci, CSR11, ®); rt2x00_set_field32(®, CSR11_CWMIN, 5); /* 2^5 = 32. */ rt2x00_set_field32(®, CSR11_CWMAX, 10); /* 2^10 = 1024. */ rt2x00_set_field32(®, CSR11_SLOT_TIME, config->slot_time); rt2x00_set_field32(®, CSR11_CW_SELECT, 1); rt2x00_register_write(rt2x00pci, CSR11, reg); rt2x00_register_read(rt2x00pci, CSR18, ®); rt2x00_set_field32(®, CSR18_SIFS, config->sifs); rt2x00_set_field32(®, CSR18_PIFS, config->sifs + config->slot_time); rt2x00_register_write(rt2x00pci, CSR18, reg); rt2x00_register_read(rt2x00pci, CSR19, ®); rt2x00_set_field32(®, CSR19_DIFS, config->sifs + (2 * config->slot_time)); rt2x00_set_field32(®, CSR19_EIFS, config->sifs + get_duration((IEEE80211_HEADER + ACK_SIZE), capabilities.bitrate[0])); rt2x00_register_write(rt2x00pci, CSR19, reg);}static voidrt2x00_dev_update_retry(struct _rt2x00_pci * rt2x00pci, struct _rt2x00_config * config) { u32 reg = 0x00000000; rt2x00_register_read(rt2x00pci, CSR11, ®); rt2x00_set_field32(®, CSR11_LONG_RETRY, config->long_retry); rt2x00_set_field32(®, CSR11_SHORT_RETRY, config->short_retry); rt2x00_register_write(rt2x00pci, CSR11, reg);}static voidrt2x00_dev_update_preamble(struct _rt2x00_pci *rt2x00pci, struct _rt2x00_config *config) { u32 reg[4]; u32 preamble = 0x00000000; memset(®, 0x00, sizeof(reg)); reg[0] = cpu_to_le32(0x00700400 | preamble); /* ARCSR2 */ reg[1] = cpu_to_le32(0x00380401 | preamble); /* ARCSR3 */ reg[2] = cpu_to_le32(0x00150402 | preamble); /* ARCSR4 */ reg[3] = cpu_to_le32(0x000b8403 | preamble); /* ARCSR5 */ rt2x00_register_multiwrite(rt2x00pci, ARCSR2, ®[0], sizeof(reg));}static voidrt2x00_dev_update_led(struct _rt2x00_pci *rt2x00pci, struct _rt2x00_config *config) { u32 reg = 0x00000000; rt2x00_register_read(rt2x00pci, LEDCSR, ®); rt2x00_set_field32(®, LEDCSR_LINK, config->led_status ? 1 : 0); rt2x00_register_write(rt2x00pci, LEDCSR, reg);}static intrt2x00_dev_update_config(struct _rt2x00_core *core, u16 update_flags) { struct _rt2x00_pci *rt2x00pci = rt2x00_priv(core); DEBUG("Start.\n"); if(update_flags & UPDATE_BSSID) rt2x00_dev_update_bssid(rt2x00pci, &core->config); if(update_flags & UPDATE_PACKET_FILTER) rt2x00_dev_update_packet_filter(rt2x00pci, &core->config); if(update_flags & UPDATE_CHANNEL) rt2x00_dev_update_channel(rt2x00pci, &core->config); if(update_flags & UPDATE_BITRATE) rt2x00_dev_update_rate(rt2x00pci, &core->config); if(update_flags & UPDATE_TXPOWER) rt2x00_dev_update_txpower(rt2x00pci, &core->config); if(update_flags & UPDATE_ANTENNA) rt2x00_dev_update_antenna(rt2x00pci, &core->config); if(update_flags & UPDATE_DURATION) rt2x00_dev_update_duration(rt2x00pci, &core->config); if(update_flags & UPDATE_RETRY) rt2x00_dev_update_retry(rt2x00pci, &core->config); if(update_flags & UPDATE_PREAMBLE) rt2x00_dev_update_preamble(rt2x00pci, &core->config); if(update_flags & UPDATE_LED_STATUS) rt2x00_dev_update_led(rt2x00pci, &core->config); if(update_flags & UPDATE_AUTORESP) rt2x00_dev_update_autoresp(rt2x00pci, &core->config); if(update_flags & UPDATE_BBPSENS) rt2x00_dev_update_bbpsens(rt2x00pci, &core->config); DEBUG("Exit.\n"); return 0;}/* * Transmission routines. * rt2x00_write_tx_desc will write the txd descriptor. * rt2x00_dev_xmit_packet will copy the packets to the appropriate DMA ring. *//* * PLCP_SIGNAL, PLCP_SERVICE, PLCP_LENGTH_LOW and PLCP_LENGTH_HIGH are BBP registers. * For RT2460 devices we need, besides the value we want to write, * also set the busy bit (0x8000) and the register number (0x0f00). * The value we want to write is stored in 0x00ff. * For PLCP_SIGNAL we can optionally enable SHORT_PREAMBLE. * For PLCP_SERVICE we can set the length extension bit according to * 802.11b standard 18.2.3.5. */static void rt2x00_write_tx_desc(struct _rt2x00_pci *rt2x00pci, struct _txd *txd, u32 packet_size, u16 rate, u16 xmit_flags) { u32 residual = 0x00000000; u32 duration = 0x00000000; u16 signal = 0x0000; u16 service = 0x0000; u16 length_low = 0x0000; u16 length_high = 0x0000; rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 1); rt2x00_set_field32(&txd->word0, TXD_W0_DATABYTE_COUNT, packet_size); rt2x00_set_field32(&txd->word0, TXD_W0_ACK, (xmit_flags & XMIT_ACK) ? 1 : 0); rt2x00_set_field32(&txd->word0, TXD_W0_RETRY_MODE, (xmit_flags & XMIT_LONG_RETRY) ? 1 : 0); rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, (xmit_flags & XMIT_TIMESTAMP) ? 1 : 0); rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, (xmit_flags & XMIT_MORE_FRAGS) ? 1 : 0); rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, (xmit_flags & XMIT_RTS) ? 1 : 0); rt2x00_set_field32(&txd->word10, TXD_W10_RTS, (xmit_flags & XMIT_RTS) ? 1 : 0); rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, (xmit_flags & XMIT_OFDM) ? 1 : 0); packet_size += 4; if(xmit_flags & XMIT_OFDM) { /* * convert length to microseconds. */ length_high = (packet_size >> 6) & 0x3f; length_low = (packet_size & 0x3f); } else { residual = get_duration_res(packet_size, rate); duration = get_duration(packet_size, rate); if(residual != 0) duration++; length_high = duration >> 8; length_low = duration & 0xff; } signal |= 0x8500 | rt2x00_get_plcp(rate); if(xmit_flags & XMIT_SHORT_PREAMBLE) signal |= 0x0008; service |= 0x0600 | 0x0004; if(residual <= (8 % 11)) service |= 0x0080; rt2x00_set_field32(&txd->word3, TXD_W3_PLCP_SIGNAL, signal); rt2x00_set_field32(&txd->word3, TXD_W3_PLCP_SERVICE, service); rt2x00_set_field32(&txd->word3, TXD_W3_PLCP_LENGTH_LOW, length_low); rt2x00_set_field32(&txd->word3, TXD_W3_PLCP_LENGTH_HIGH, length_high); /* set XMIT_IFS to XMIT_IFS_NONE */ rt2x00_set_field32(&txd->word0, TXD_W0_IFS, XMIT_IFS_NONE); /* highest priority */ rt2x00_set_field32(&txd->word2, TXD_W2_CWMIN, 1); rt2x00_set_field32(&txd->word2, TXD_W2_CWMAX, 2); rt2x00_set_field32(&txd->word2, TXD_W2_AIFS, 1); /* * set this last, after this the device can start transmitting the packet. */ rt2x00_set_field32(&txd->word0, TXD_W0_OWNER_NIC, 1);}static int rt2x00_dev_xmit_packet(struct _rt2x00_core * core, struct rtskb *rtskb, u16 rate, u16 xmit_flags) { struct _rt2x00_pci *rt2x00pci = rt2x00_priv(core); struct _data_ring *ring = NULL; struct _txd *txd = NULL; void *data = NULL; u32 reg = 0x00000000; rtdm_lockctx_t context; rtdm_lock_get_irqsave(&rt2x00pci->lock, context); /* load tx-control register */ rt2x00_register_read(rt2x00pci, TXCSR0, ®); /* select tx-descriptor ring and prepare xmit */ ring = &rt2x00pci->tx; rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); txd = DESC_ADDR(ring); data = DATA_ADDR(ring); if(rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) || rt2x00_get_field32(txd->word0, TXD_W0_VALID)) { rtdm_lock_put_irqrestore(&rt2x00pci->lock, context); return -ENOMEM; } /* get and patch time stamp just before the transmission */ if (rtskb->xmit_stamp) *rtskb->xmit_stamp = cpu_to_be64(rtdm_clock_read() + *rtskb->xmit_stamp); /* copy rtskb to dma */ memcpy(data, rtskb->data, rtskb->len); rt2x00_write_tx_desc(rt2x00pci, txd, rtskb->len, rate, xmit_flags); rt2x00_ring_index_inc(ring); /* let the device do the rest ... */ rt2x00_register_write(rt2x00pci, TXCSR0, reg); rtdm_lock_put_irqrestore(&rt2x00pci->lock, context); return 0;}/* * PCI device handlers for usage by core module. */static struct _rt2x00_dev_handler rt2x00_pci_handler = { .dev_module = THIS_MODULE, .dev_probe = rt2x00_dev_probe, .dev_remove = rt2x00_dev_remove, .dev_radio_on = rt2x00_dev_radio_on, .dev_radio_off = rt2x00_dev_radio_off, .dev_update_config = rt2x00_dev_update_config, .dev_register_access = rt2x00_dev_register_access, .dev_xmit_packet = rt2x00_dev_xmit_packet,};int rt2x00_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { struct rtnet_device *rtnet_dev = NULL; int status = 0x00000000; DEBUG("start.\n"); if(id->driver_data != RT2560){ ERROR("detected device not supported.\n"); status = -ENODEV; goto exit; } if(pci_enable_device(pci_dev)){ ERROR("enable device failed.\n"); status = -EIO; goto exit; } pci_set_master(pci_dev); if(pci_set_dma_mask(pci_dev, DMA_64BIT_MASK) && pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)){ ERROR("PCI DMA not supported\n"); status = -EIO; goto exit_disable_device; } if(pci_request_regions(pci_dev, pci_name(pci_dev))){ ERROR("PCI request regions failed.\n"); status = -EBUSY; goto exit_disable_device; } INFO("pci_dev->irq=%d\n", pci_dev->irq); rtnet_dev = rt2x00_core_probe(&rt2x00_pci_handler, pci_dev, sizeof(struct _rt2x00_pci)); if(!rtnet_dev){ ERROR("rtnet_device allocation failed.\n"); status = -ENOMEM; goto exit_release_regions; } rtnet_dev->irq = pci_dev->irq; pci_set_drvdata(pci_dev, rtnet_dev); return 0; exit_release_regions: pci_release_regions(pci_dev); exit_disable_device: if(status != -EBUSY) pci_disable_device(pci_dev); exit: return status;}static void rt2x00_pci_remove(struct pci_dev *pci_dev) { struct rtnet_device *rtnet_dev = pci_get_drvdata(pci_dev); rt2x00_core_remove(rtnet_dev); pci_set_drvdata(pci_dev, NULL); pci_release_regions(pci_dev); pci_disable_device(pci_dev);}/* * RT2500 PCI module information. */char version[] = DRV_NAME " - " DRV_VERSION;struct pci_device_id rt2x00_device_pci_tbl[] = { { PCI_DEVICE(0x1814, 0x0201), .driver_data = RT2560}, /* Ralink 802.11g */ {0,}};MODULE_AUTHOR(DRV_AUTHOR);MODULE_DESCRIPTION("RTnet rt2500 PCI WLAN driver (PCI Module)");MODULE_LICENSE("GPL");struct pci_driver rt2x00_pci_driver ={ .name = DRV_NAME, .id_table = rt2x00_device_pci_tbl, .probe = rt2x00_pci_probe, .remove = __devexit_p(rt2x00_pci_remove),};static int __init rt2x00_pci_init(void) { rtdm_printk(KERN_INFO "Loading module: %s\n", version); return pci_register_driver(&rt2x00_pci_driver);}static void __exit rt2x00_pci_exit(void) { rtdm_printk(KERN_INFO "Unloading module: %s\n", version); pci_unregister_driver(&rt2x00_pci_driver);}module_init(rt2x00_pci_init);module_exit(rt2x00_pci_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -