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

📄 rtl81xx.c

📁 1. 8623L平台
💻 C
📖 第 1 页 / 共 2 页
字号:
        if (i < MACADDR_LEN - 1)            uart_puts(":");    }    uart_puts("\n");    // Setup MAC address, only permits access by 4 bytes    // Before programming the IDR registers, unlock some registers    rtl81xx_writel(CR93C46_EEM_CONFIGWEN, REG_CR93C46);    for (i = 0; i < 2; ++i)        rtl81xx_writel(((unsigned int *) dev->dev_addr)[i], REG_IDR + i * 4);    rtl81xx_writel(CR93C46_EEM_NORMAL, REG_CR93C46);    // enable Rx and Tx    rtl81xx_writeb(CR_TE | CR_RE, REG_CR);    rtl81xx_writel(g_rx_config, REG_RCR);    rtl81xx_writel(g_tx_config, REG_TCR);    // disable early rx interrupt    rtl81xx_writew(rtl81xx_readw(REG_MULINT) & 0xf000, REG_MULINT);    // setup Rx and Tx buffer    rtl81xx_writel(db->rx_buf_dma, REG_RBSTART);    for (i = 0; i < TX_DESC_NUM; ++i)        rtl81xx_writel(db->tx_bufs_dma[i], REG_TSAD0 + i * 4);    db->rx_cur = 0;    db->tx_cur = 0;    db->tx_last = 0;    // enable interrupt    rtl81xx_writew(g_imr, REG_IMR);        return 0;}int rtl81xx_open(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    rtl81xx_init(dev);    em86xx_request_irq(db->pcidev.irqline, rtl81xx_irq, dev);    dev->state = NETDEV_UP;    return 0;}int rtl81xx_close(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    /* Disable TX/RX */    rtl81xx_writeb(0, REG_CR);    em86xx_free_irq(db->pcidev.irqline);    dev->state = NETDEV_DOWN;        return 0;}int rtl81xx_rx_interrupt(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    struct sk_buff *skb;    unsigned int rx_cur = db->rx_cur;    int npacket = 0;#if RTL81XX_VERBOSE    uart_printf("RX : CBR = %04x, CAPR = %04x, rx_cur = %08x\n",        rtl81xx_readw(REG_CBR), rtl81xx_readw(REG_CAPR), rx_cur);#endif    for (;;) {        int offset = rx_cur & (RX_BUF_LEN - 1);        unsigned int rx_status, rx_size;        // if Rx buffer is empty, clear Rx interrupt and exit        if (rtl81xx_readb(REG_CR) & CR_BUFE) {            if (rtl81xx_readw(REG_ISR) & ISR_ROK)                rtl81xx_writew(ISR_ROK, REG_ISR);            break;        }        // flush cache because transfer is done by PCI bus mastering        em86xx_flush_cache_data_region(db->rx_buf + offset, db->rx_buf + offset + ETH_BUF_LEN);        // read packet information        rx_status = *(unsigned int *) (db->rx_buf + offset);        rx_size = rx_status >> 16;        // check the validity of packet        if (rx_size > ETH_BUF_LEN + 4 || rx_size <= 16 + 4) {            uart_printf("RTL81XX: Received invalid packet size %d\n", rx_size - 4);            return -1;        }        if ((rx_status & RXHEADER_ROK) == 0) {            uart_printf("RTL81XX: Received error packet\n");            return -1;        }#if RTL81XX_VERBOSE        {            int i;            unsigned char *ptr = (unsigned char *) db->rx_buf + offset + 4;                uart_printf("     size = %d : ", rx_size);            for (i = 0; i < 12; ++i)                uart_printf("%02X ", ptr[i]);            uart_puts("\n");        }#endif        // copy packet : packet size is rx_size - header size (4 bytes)        ++npacket;        if ((skb = skb_alloc(rx_size)) != NULL) {            skb->len = rx_size - 4;            memcpy(skb->data, (void *) (db->rx_buf + offset + 4), skb->len);            skb_put(skb);        }        // update pointer, align on 32 bits boundary        db->rx_cur = rx_cur = (rx_cur + rx_size + 4 + 3) & ~3;        rtl81xx_writew(rx_cur - 16, REG_CAPR);    }     return npacket;}void rtl81xx_tx_interrupt(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    unsigned int status;    int i, idx;    for (i = db->tx_last; i < db->tx_cur; ++i) {        idx = i % TX_DESC_NUM;        status = rtl81xx_readl(REG_TSD0 + idx * 4);        if (status & (TSD_TABT | TSD_OWC | TSD_TUN)) {            uart_printf("RTL81XX: Transmit failed for %d\n", i);            // if abort, clear abort bit            if (status & TSD_TABT) {                rtl81xx_writel(TCR_CLRABT, REG_TCR);                rtl81xx_writew(ISR_TER, REG_ISR);            }        } else if (status & TSD_TOK) {#if RTL81XX_VERBOSE            uart_printf("TX : Success %d\n", i);#endif        } else            break;        skb_free((struct sk_buff *) db->tx_skb[idx]);        db->tx_skb[idx] = NULL;        ++db->tx_last;    }}void rtl81xx_irq(int irq, void *pdata){    struct net_device *dev = (struct net_device *) pdata;    unsigned int isr;       while ((isr = rtl81xx_readw(REG_ISR)) != 0) {/*if (isr & ISR_ROK)uart_puts("[R]");if (isr & ISR_TOK)uart_puts("[t]");*/#if RTL81XX_VERBOSE        uart_puts("[ ");        if (isr & ISR_ROK)            uart_puts("RxOK ");        if (isr & ISR_RER)            uart_puts("RxErr ");        if (isr & ISR_TOK)            uart_puts("TxOK ");        if (isr & ISR_TER)            uart_puts("TxErr ");        if (isr & ISR_RXOVW)            uart_puts("RxOverflow ");        if (isr & ISR_PUNLINKCHG)            uart_puts("Underrun ");        if (isr & ISR_FOVW)            uart_puts("RxFifoOverflow ");        if (isr & ISR_LENCHG)            uart_puts("LenChange ");        if (isr & ISR_TIMEOUT)            uart_puts("Timeout ");        if (isr & ISR_SERR)            uart_puts("SERR ");        uart_puts("]\n");#endif        if (isr & (ISR_RXOVW | ISR_FOVW))            uart_puts("RTL81XX: Buffer overflow error\n");        rtl81xx_writew(isr & ~(ISR_ROK | ISR_FOVW | ISR_RXOVW | ISR_TER), REG_ISR);        if (isr & (ISR_ROK | ISR_FOVW | ISR_RXOVW))            rtl81xx_rx_interrupt(dev);        if (isr & (ISR_RER | ISR_RXOVW | ISR_PUNLINKCHG | ISR_FOVW | ISR_TIMEOUT | ISR_SERR)) {            if (isr & (ISR_RXOVW | ISR_FOVW))                rtl81xx_writew(ISR_RXOVW | ISR_FOVW, REG_ISR);        }        if (isr & (ISR_TOK | ISR_TER))            rtl81xx_tx_interrupt(dev);    }}int rtl81xx_send_packet(struct sk_buff *skb, struct net_device *dev, int async){    board_info_t *db = (board_info_t *) dev->priv;    int tx_cur = db->tx_cur % TX_DESC_NUM;    unsigned int len = skb->len;    // check the validity of packet    if (skb->len > ETH_BUF_LEN) {        uart_printf("RTL81XX: Packet size too big (%d)\n", skb->len);        return 1;    }    // copy payload    if (skb->len < ETH_ZLEN) {        memset((void *) db->tx_bufs[tx_cur], 0, ETH_ZLEN);        len = ETH_ZLEN;    }    memcpy((void *) db->tx_bufs[tx_cur], skb->data, skb->len);    em86xx_clean_cache_data_region(db->tx_bufs[tx_cur], db->tx_bufs[tx_cur] + skb->len);    // update data structure    db->tx_skb[tx_cur] = skb;    ++db->tx_cur;    // set TSD register//uart_puts("[T]");#if RTL81XX_VERBOSE    uart_printf("TX: Transmit packet %d\n", tx_cur);#if 0    {        struct sk_buff *new_skb = skb_dup(skb);        ipv4_dump_packet(new_skb, 0, 1);        skb_free(new_skb);    }#endif#endif    rtl81xx_writel(g_tsd | len, REG_TSD0 + tx_cur * 4);    // wait for the completion    if (!async) {        unsigned int startticks = timer_getticks();        // check current mode and interrupt status        // synchronous mode must not be used in interrupt mode        if (!em86xx_irqenabled()) {            uart_puts("RTL81XX: Interrupt is disabled in synchronous mode\n");            return 0;        }        do {            if (db->tx_skb[tx_cur] == NULL)                return 0;        } while (!timer_timeout(startticks, 3000));        uart_printf("RTL81XX: Transmit failure %d\n", db->tx_cur - 1);        rtl81xx_writel(0, REG_TSD0 + tx_cur * 4);        skb_free(skb);    }    return 0;}int rtl81xx_receive_packet(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    em86xx_mask_irq(db->pcidev.irqline);        // if (rtl81xx_readw(REG_ISR) & ISR_ROK)    //     return rtl81xx_rx_interrupt(dev);    rtl81xx_irq(0, dev);    em86xx_unmask_irq(db->pcidev.irqline);    return 0;}void rtl81xx_print_status(struct net_device *dev){}//// Supplmentary functions//void rtl81xx_chip_reset(void){    /* Disable TX/RX */    rtl81xx_writeb(0, REG_CR);    // send reset command    rtl81xx_writeb(CR_RST, REG_CR);    // wait for reset is done    while (rtl81xx_readb(REG_CR) & CR_RST)        ;}#define rtl81xx_eeprom_delay()                  rtl81xx_readb(REG_CR)#define rtl81xx_eeprom_strobe(data, sk)         rtl81xx_writeb(CR93C46_EEM_PROGRAM | CR93C46_EECS | (data) | ((sk) ? CR93C46_EESK : 0), REG_CR93C46)#define rtl81xx_read_eeprom_bit()               ((rtl81xx_readb(REG_CR93C46) & CR93C46_EEDO) ? 1 : 0)#define rtl81xx_write_eeprom_bit(bit, sk)       rtl81xx_eeprom_strobe((bit) ? CR93C46_EEDI : 0, sk)__inline__ void rtl81xx_write_eeprom_bits(int data, int bits){    int i;    // send bits (MSB first)    for (i = bits - 1; i >= 0; --i) {        rtl81xx_write_eeprom_bit(data & (1 << i), 0);        rtl81xx_eeprom_delay();        rtl81xx_write_eeprom_bit(data & (1 << i), 1);        rtl81xx_eeprom_delay();    }}__inline__ unsigned int rtl81xx_read_eeprom_bits(int bits){    int i;    unsigned int data = 0;    for (i = 0; i < bits; ++i) {        rtl81xx_eeprom_strobe(0, 1);        rtl81xx_eeprom_delay();        data <<= 1;        data |= rtl81xx_read_eeprom_bit();        rtl81xx_eeprom_strobe(0, 0);        rtl81xx_eeprom_delay();    }    return data;}// addr : address// addr_len : bits of addressunsigned int rtl81xx_read_eeprom(int addr, int addr_len){    unsigned int data;    // start EEPROM access    rtl81xx_writeb(CR93C46_EEM_PROGRAM, REG_CR93C46);    rtl81xx_writeb(CR93C46_EEM_PROGRAM | CR93C46_EECS, REG_CR93C46);    rtl81xx_eeprom_delay();    // sends 5 bits command    rtl81xx_write_eeprom_bits(CR93C46_CMD_READ, 5);    // sends address    rtl81xx_write_eeprom_bits(addr, addr_len);    rtl81xx_eeprom_strobe(0, 0);    rtl81xx_eeprom_delay();    // read 16 bits data    data = rtl81xx_read_eeprom_bits(16);    // terminate EEPROM access    rtl81xx_writeb(0, REG_CR93C46);    rtl81xx_eeprom_delay();    return data;}

⌨️ 快捷键说明

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