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

📄 rt_rt2500pci.c

📁 硬实时linux补丁rtai下的网络协议栈 最新
💻 C
📖 第 1 页 / 共 3 页
字号:
/* rt2500pci.c * * Copyright (C) 2004 - 2005 rt2x00-2.0.0-b3 SourceForge Project *	                     <http://rt2x00.serialmonkey.com> *               2006        rtnet adaption by Daniel Gregorek  *                           <dxg@gmx.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* * Module: rt_rt2500pci * Abstract: rt2500pci device specific routines. * Supported chipsets: RT2560. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/delay.h>#include "rt2x00.h"#include "rt2500pci.h"#include <rtnet_port.h>#ifdef DRV_NAME#undef DRV_NAME#define DRV_NAME			"rt_rt2500pci"#endif /* DRV_NAME *//* handler for direct register access from core module */static int rt2x00_dev_register_access(struct _rt2x00_core * core, 				      int request,				      u32 address,				      u32 * value) {        struct _rt2x00_pci * rt2x00pci = rt2x00_priv(core);    u8 u8_value;        switch(request) {    case IOC_RTWLAN_REGREAD:        rt2x00_register_read(rt2x00pci, address, value);        break;    case IOC_RTWLAN_REGWRITE:        rt2x00_register_write(rt2x00pci, address, *value);        break;    case IOC_RTWLAN_BBPREAD:        rt2x00_bbp_regread(rt2x00pci, address, &u8_value);        *value = u8_value;        break;    case IOC_RTWLAN_BBPWRITE:        rt2x00_bbp_regwrite(rt2x00pci, address, *value);        break;    default:        return -1;    }    return 0;}/* * 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_dev     = rtnetdev_priv(ring->core->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_dev->stats.tx_packets++;                break;            case TX_SUCCESS_RETRY:                rtwlan_dev->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));}static void rt2x00_interrupt_rxdone(struct _data_ring * ring, nanosecs_abs_t *time_stamp) {    struct _rt2x00_pci	 * rt2x00pci  = rt2x00_priv(ring->core);    struct rtnet_device  * rtnet_dev  = ring->core->rtnet_dev;     struct rtwlan_device * rtwlan_dev     = 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_dev->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);        rtwlan_dev->stats.rx_packets++;        rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);        rt2x00_ring_index_inc(&rt2x00pci->rx);    }}int rt2x00_interrupt(rtdm_irq_t *irq_handle) {    nanosecs_abs_t time_stamp = rtdm_clock_read();    struct rtnet_device   * rtnet_dev = rtdm_irq_get_arg(irq_handle, struct rtnet_device);    struct rtwlan_device  * rtwlan_dev    = rtnetdev_priv(rtnet_dev);    struct _rt2x00_core   * core      = rtwlan_priv(rtwlan_dev);    struct _rt2x00_pci	  * rt2x00pci = rt2x00_priv(core);    unsigned int old_packet_cnt       = rtwlan_dev->stats.rx_packets;    u32			reg           = 0x00000000;    rtdm_lock_get(&rt2x00pci->lock);        rt2x00_register_read(rt2x00pci, CSR7, &reg);    rt2x00_register_write(rt2x00pci, CSR7, reg);    if(!reg) {        rtdm_lock_put(&rt2x00pci->lock);        return RTDM_IRQ_NONE;    }    if(rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))		/* Beacon timer expired interrupt. */        DEBUG("Beacon timer expired.\n");    if(rt2x00_get_field32(reg, CSR7_RXDONE))		/* Rx ring done interrupt. */        rt2x00_interrupt_rxdone(&rt2x00pci->rx, &time_stamp);    if(rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))	/* Atim ring transmit done interrupt. */        DEBUG("AtimTxDone.\n");    if(rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))	/* Priority ring transmit done interrupt. */        DEBUG("PrioTxDone.\n");    if(rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))	/* Tx ring transmit done interrupt. */        rt2x00_interrupt_txdone(&rt2x00pci->tx);    rtdm_lock_put(&rt2x00pci->lock);    if (old_packet_cnt != rtwlan_dev->stats.rx_packets)        rt_mark_stack_mgr(rtnet_dev);    return RTDM_IRQ_HANDLED;}void rt2x00_init_eeprom(struct _rt2x00_pci * rt2x00pci, struct _rt2x00_config * config) {    u32		reg = 0x00000000;    u16		eeprom = 0x0000;    /*     * 1 - Detect EEPROM width.     */    rt2x00_register_read(rt2x00pci, CSR21, &reg);    rt2x00pci->eeprom_width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ? EEPROM_WIDTH_93c46 : EEPROM_WIDTH_93c66;    /*     * 2 - Identify rf chipset.     */    eeprom = rt2x00_eeprom_read_word(rt2x00pci, EEPROM_ANTENNA);    set_chip(&rt2x00pci->chip, RT2560, rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE));    /*     * 3 - Identify default antenna configuration.     */    config->antenna_tx = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);    config->antenna_rx = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);    DEBUG("antenna_tx=%d antenna_rx=%d\n", config->antenna_tx, config->antenna_rx);    /*     * 4 - Read BBP data from EEPROM and store in private structure.     */    memset(&rt2x00pci->eeprom, 0x00, sizeof(rt2x00pci->eeprom));    for(eeprom = 0; eeprom < EEPROM_BBP_SIZE; eeprom++)        rt2x00pci->eeprom[eeprom] = rt2x00_eeprom_read_word(rt2x00pci, EEPROM_BBP_START + eeprom);}void rt2x00_dev_read_mac(struct _rt2x00_pci * rt2x00pci, struct rtnet_device * rtnet_dev) {    u32			reg[2];    memset(&reg, 0x00, sizeof(reg));    rt2x00_register_multiread(rt2x00pci, CSR3, &reg[0], sizeof(reg));    rtnet_dev->dev_addr[0] = rt2x00_get_field32(reg[0], CSR3_BYTE0);    rtnet_dev->dev_addr[1] = rt2x00_get_field32(reg[0], CSR3_BYTE1);    rtnet_dev->dev_addr[2] = rt2x00_get_field32(reg[0], CSR3_BYTE2);    rtnet_dev->dev_addr[3] = rt2x00_get_field32(reg[0], CSR3_BYTE3);    rtnet_dev->dev_addr[4] = rt2x00_get_field32(reg[1], CSR4_BYTE4);    rtnet_dev->dev_addr[5] = rt2x00_get_field32(reg[1], CSR4_BYTE5);    rtnet_dev->addr_len = 6;}int rt2x00_dev_probe(struct _rt2x00_core * core, void * priv) {    struct pci_dev	*pci_dev = (struct pci_dev*)priv;    struct _rt2x00_pci	*rt2x00pci = core->priv;    memset(rt2x00pci, 0x00, sizeof(*rt2x00pci));    if(unlikely(!pci_dev)){        ERROR("invalid priv pointer.\n");        return -ENODEV;    }    rt2x00pci->pci_dev = pci_dev;    rt2x00pci->rx.data_addr = NULL;    rt2x00pci->tx.data_addr = NULL;    rt2x00pci->csr_addr = ioremap(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0));    if(!rt2x00pci->csr_addr){        ERROR("ioremap failed.\n");        return -ENOMEM;    }    rt2x00_init_eeprom(rt2x00pci, &core->config);      rt2x00_dev_read_mac(rt2x00pci, core->rtnet_dev);      return 0;}int rt2x00_dev_remove(struct _rt2x00_core * core) {    struct _rt2x00_pci	*rt2x00pci = rt2x00_priv(core);    if(rt2x00pci->csr_addr){        iounmap(rt2x00pci->csr_addr);        rt2x00pci->csr_addr = NULL;    }      return 0;}/* * rt2x00_clear_ring * During the initialization some of the descriptor variables are filled in. * The default value of the owner variable is different between the types of the descriptor, * DMA ring entries that receive packets are owned by the device untill a packet is received. * DMA ring entries that are used to transmit a packet are owned by the module untill the device, * for these rings the valid bit is set to 0 to indicate it is ready for use. * should transmit the packet that particular DMA ring entry. * The BUFFER_ADDRESS variable is used to link a descriptor to a packet data block. */static voidrt2x00_clear_ring(struct _rt2x00_pci *rt2x00pci, struct _data_ring *ring) {    struct _rxd		*rxd = NULL;    struct _txd		*txd = NULL;    dma_addr_t		data_dma = ring->data_dma + (ring->max_entries * ring->desc_size);    u8			counter = 0x00;    memset(ring->data_addr, 0x00, ring->mem_size);    for(; counter < ring->max_entries; counter++){        if(ring->ring_type == RING_RX){            rxd = (struct _rxd*)__DESC_ADDR(ring, counter);            rt2x00_set_field32(&rxd->word1, RXD_W1_BUFFER_ADDRESS, data_dma);            rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);        }else{            txd = (struct _txd*)__DESC_ADDR(ring, counter);	            rt2x00_set_field32(&txd->word1, TXD_W1_BUFFER_ADDRESS, data_dma);            rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);            rt2x00_set_field32(&txd->word0, TXD_W0_OWNER_NIC, 0);        }        data_dma += ring->entry_size;    }    rt2x00_ring_clear_index(ring);}/* * rt2x00_init_ring_register * The registers should be updated with the descriptor size and the * number of entries of each ring. * The address of the first entry of the descriptor ring is written to the register * corresponding to the ring. */static void rt2x00_init_ring_register(struct _rt2x00_pci *rt2x00pci) {    u32			reg = 0x00000000;    /* Initialize ring register for RX/TX */    rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00pci->tx.desc_size);    rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00pci->tx.max_entries);    rt2x00_register_write(rt2x00pci, TXCSR2, reg);    reg = 0x00000000;    rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER, rt2x00pci->tx.data_dma);    rt2x00_register_write(rt2x00pci, TXCSR3, reg);    reg = 0x00000000;    rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00pci->rx.desc_size);    rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00pci->rx.max_entries);    rt2x00_register_write(rt2x00pci, RXCSR1, reg);    reg = 0x00000000;    rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, rt2x00pci->rx.data_dma);    rt2x00_register_write(rt2x00pci, RXCSR2, reg);}static intrt2x00_init_registers(struct _rt2x00_pci *rt2x00pci) {    u32		reg = 0x00000000;    DEBUG("Start.\n");    rt2x00_register_write(rt2x00pci, PWRCSR0, cpu_to_le32(0x3f3b3100));    rt2x00_register_write(rt2x00pci, PSCSR0, cpu_to_le32(0x00020002));    rt2x00_register_write(rt2x00pci, PSCSR1, cpu_to_le32(0x00000002));    rt2x00_register_write(rt2x00pci, PSCSR2, cpu_to_le32(0x00020002));    rt2x00_register_write(rt2x00pci, PSCSR3, cpu_to_le32(0x00000002));    rt2x00_register_read(rt2x00pci, TIMECSR, &reg);    rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);    rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);    rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);    rt2x00_register_write(rt2x00pci, TIMECSR, reg);    rt2x00_register_read(rt2x00pci, CSR9, &reg);    rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT, (rt2x00pci->rx.entry_size / 128));    rt2x00_register_write(rt2x00pci, CSR9, reg);    rt2x00_register_write(rt2x00pci, CNT3, cpu_to_le32(0x3f080000));    rt2x00_register_read(rt2x00pci, RXCSR0, &reg);    rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);    rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL, 0);    rt2x00_register_write(rt2x00pci, RXCSR0, reg);    rt2x00_register_write(rt2x00pci, MACCSR0, cpu_to_le32(0x00213223));    rt2x00_register_read(rt2x00pci, MACCSR1, &reg);    rt2x00_set_field32(&reg, MACCSR1_AUTO_TXBBP, 1);    rt2x00_set_field32(&reg, MACCSR1_AUTO_RXBBP, 1);    rt2x00_register_write(rt2x00pci, MACCSR1, reg);    rt2x00_register_read(rt2x00pci, MACCSR2, &reg);    rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);    rt2x00_register_write(rt2x00pci, MACCSR2, reg);

⌨️ 快捷键说明

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