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

📄 ne2kpci.c

📁 em86xx 完整启动程序,支持网络下载与串通下载
💻 C
字号:
/***************************************** Copyright (c) 2002-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the boot loader *//* * ne2kpci.c * * ethernet driver for NE2000 compatible PCI adapter */#include "config.h"#include "uart.h"#include "util.h"#include "net.h"#include "pcicommon.h"#include "io.h"#include "timer.h"//// compatibility// #define virt_to_phys(x) ((unsigned int)(x))// // constant defitions related NE2K PCI//#define RTL8029_VENDOR_ID   0x10ec#define RTL8029_DEVICE_ID   0x8029// standard NE2K registers#define NE_CR               0x00    // R/W 0,1,2,3 : Command Register#define NE_CLDA0            0x01    // R 0#define NE_CLDA1            0x02    // R 0#define NE_BNRY             0x03    // R/W 0#define NE_TSR              0x04    // R 0 : Transmission Status Register#define NE_NCR              0x05    // R 0#define NE_FIFO             0x06    // R 0#define NE_ISR              0x07    // R/W 0 : Interrupt Status Register#define NE_CRDA0            0x08    // R 0#define NE_CRDA1            0x09    // R 0#define NE_RSR              0x0c    // R 0 : Receive Status Register#define NE_CNTR0            0x0d    // R 0#define NE_CNTR1            0x0e    // R 0#define NE_CNTR2            0x0f    // R 0#define NE_PSTART           0x01    // W 0, R 2#define NE_PSTOP            0x02    // W 0, R 2#define NE_TPSR             0x04    // W 0#define NE_TBCR0            0x05    // W 0#define NE_TBCR1            0x06    // W 0#define NE_RSAR0            0x08    // W 0#define NE_RSAR1            0x09    // W 0#define NE_RBCR0            0x0a    // W 0#define NE_RBCR1            0x0b    // W 1#define NE_RCR              0x0c    // W 0,2 : Receive Configuration Register#define NE_TCR              0x0d    // W 0,2 : Transmit Configuration Register#define NE_DCR              0x0e    // W 0,2 : Data Configuration Register#define NE_IMR              0x0f    // W 0,2 : Interrupt Mask Register#define NE_PAR              0x01    // R/W 1 : 6 bytes#define NE_CURR             0x07    // R/W 1#define NE_MAR              0x08    // R/W 1 : 8 bytes#define NE_DATAPORT         0x10#define NE_RESET            0x1f// RTL8029 specific registers#define NE_8029ID0          0x0a    // R 0#define NE_8029ID1          0x0b    // R 0// NE_CMD#define ENCMD_STOP          0x01    /* Stop and reset the chip */#define ENCMD_START         0x02    /* Start the chip, clear reset */#define ENCMD_TRANS         0x04    /* Transmit a frame */#define ENCMD_RREAD         0x08    /* Remote read */#define ENCMD_RWRITE        0x10    /* Remote write  */#define ENCMD_NODMA         0x20    /* Remote DMA */#define ENCMD_PAGE0         0x00    /* Select page chip registers */#define ENCMD_PAGE1         0x40    /* using the two high-order bits */#define ENCMD_PAGE2         0x80    /* Page 3 is invalid. */// NE_ISR#define ENISR_RX            0x01    /* Receiver, no error */#define ENISR_TX            0x02    /* Transmitter, no error */#define ENISR_RX_ERR        0x04    /* Receiver, with error */#define ENISR_TX_ERR        0x08    /* Transmitter, with error */#define ENISR_OVER          0x10    /* Receiver overwrote the ring */#define ENISR_COUNTERS      0x20    /* Counters need emptying */#define ENISR_RDC           0x40    /* remote dma complete */#define ENISR_RESET         0x80    /* Reset completed */#define ENISR_ALL           0x3f    /* Interrupts we will enable */// NE_DCR#define ENDCFG_WTS          0x01    /* word transfer mode selection */#define ENDCFG_BOS          0x02    /* byte order selection */// NE_RSR#define ENRSR_RXOK          0x01    /* Received a good packet */#define ENRSR_CRC           0x02    /* CRC error */#define ENRSR_FAE           0x04    /* frame alignment error */#define ENRSR_FO            0x08    /* FIFO overrun */#define ENRSR_MPA           0x10    /* missed pkt */#define ENRSR_PHY           0x20    /* physical/multicast address */#define ENRSR_DIS           0x40    /* receiver disable. set in monitor mode */#define ENRSR_DEF           0x80    /* deferring */// NE_TSR#define ENTSR_PTX           0x01    /* Packet transmitted without error */#define ENTSR_ND            0x02    /* The transmit wasn't deferred. */#define ENTSR_COL           0x04    /* The transmit collided at least once. */#define ENTSR_ABT           0x08    /* The transmit collided 16 times, and was deferred. */#define ENTSR_CRS           0x10    /* The carrier sense was lost. */#define ENTSR_FU            0x20    /* A "FIFO underrun" occurred during transmit. */#define ENTSR_CDH           0x40    /* The collision detect "heartbeat" signal was lost. */#define ENTSR_OWC           0x80    /* There was an out-of-window collision. */// buffer#define NE_START_PG         0x40    /* First page of Tx buffer */#define NE_STOP_PG          0x80    /* Last page + 1 of RX ring */#define TX_PAGES            12//// type definitions// typedef struct board_info {    struct my_pci_dev pcidev;    unsigned int ioaddr;    unsigned char prom[32];    int tx_start_page, stop_page;    int rx_start_page;    int tx1, tx2;    int current_page;} board_info_t;//// global variables// static board_info_t g_board_info;//// Basic I/O//unsigned char ne2kpci_inb(int offset){    return pci_readb(g_board_info.ioaddr + offset);}void ne2kpci_outb(int data, int offset){    pci_writeb(data, g_board_info.ioaddr + offset);}int ne2kpci_set_page(int page){    unsigned int data = ne2kpci_inb(NE_CR);    data &= ~0xc0;    data |= (page << 6);    ne2kpci_outb(data, NE_CR);    return 0;}//// Init & Main//int ne2kpci_probe(struct net_device *dev);static int ne2kpci_init(struct net_device *dev);static int ne2kpci_open(struct net_device *dev);static int ne2kpci_close(struct net_device *dev);static int ne2kpci_irq_pending(struct net_device *dev);static void ne2kpci_irq(int irq, void *pdata);static int ne2kpci_send_packet(struct sk_buff *skbuff, struct net_device *dev);static int ne2kpci_receive_packet(struct net_device *dev);static void ne2kpci_print_status(struct net_device *dev);int ne2kpci_probe(struct net_device *dev){    board_info_t *db = &g_board_info;    unsigned int id0, id1;    if (pci_lookup(RTL8029_VENDOR_ID, RTL8029_DEVICE_ID, &db->pcidev)) {        uart_printf("Found RTL8029 at PCI IDSEL %d\n", db->pcidev.idsel);        // check I/O address         pci_configure_device(&db->pcidev);        uart_printf("  Assign I/O address from 0x%08x, size 0x%x\n", db->pcidev.resource[0].start, db->pcidev.resource[0].size);        db->ioaddr = db->pcidev.resource[0].start;        // enable device        pci_write_config_word(PCI_COMMAND, PCI_COMMAND_IO);        // check 8029 ID        ne2kpci_set_page(0);        id0 = ne2kpci_inb(NE_8029ID0);        id1 = ne2kpci_inb(NE_8029ID1);        uart_printf("  RTL8029 ID %sfound\n", (id0 == 0x50 && id1 == 0x43) ? "" : "not ");        // register functions        dev->state = NETDEV_DOWN;        dev->priv = db;        dev->init = ne2kpci_init;        dev->open = ne2kpci_open;        dev->close = ne2kpci_close;        dev->irq_pending = ne2kpci_irq_pending;        dev->send_packet = ne2kpci_send_packet;        dev->receive_packet = ne2kpci_receive_packet;        dev->print_status = ne2kpci_print_status;        return 1;    }    return 0;}int ne2kpci_init(struct net_device *dev){    static struct {        unsigned char offset;        unsigned char data;    } s_reg_init[] = {        { NE_CR, 0x21 },        // NODMA & STOP        { NE_DCR, 0x49 },       // Word         { NE_RBCR0, 0x00 },     // clear remote byte count register        { NE_RBCR1, 0x00 },        { NE_IMR, 0x00 },       // clear interrupt mask register        { NE_ISR, 0xff },       // clear interrupt status register        { NE_RCR, 0x20 },       // monotir mode        { NE_TCR, 0x02 },       // loopback mode        { NE_RBCR0, 0x20 },        { NE_RBCR1, 0x00 },         { NE_RSAR0, 0x00 },        { NE_RSAR1, 0x00 },        { NE_CR, 0x0a },    };        board_info_t *db = (board_info_t *) dev->priv;    unsigned int startticks;    int i;    // reset    ne2kpci_set_page(0);    ne2kpci_outb(ne2kpci_inb(NE_RESET), NE_RESET);    // wait for reset ACK    startticks = timer_getticks();     while ((ne2kpci_inb(NE_ISR) & ENISR_RESET) == 0) {        if (timer_timeout(startticks, 5)) {            uart_puts("NE2KPCI : Reset failed\n");            return 1;        }    }    // clear all interrupt    ne2kpci_outb(0xff, NE_ISR);    // initialize registers    for (i = 0; i < sizeof s_reg_init / sizeof s_reg_init[0]; ++i)        ne2kpci_outb(s_reg_init[i].data, s_reg_init[i].offset);    // read EPROM    for (i = 0; i < 32; ++i)        db->prom[i] = ne2kpci_inb(NE_DATAPORT);    uart_printf("NE2KPCI : MAC Address is %02X:%02X:%02X:%02X:%02X:%02X\n",        db->prom[0], db->prom[1], db->prom[2], db->prom[3], db->prom[4], db->prom[5]);    // setup data structures    db->tx_start_page = NE_START_PG;    db->stop_page = NE_STOP_PG;    db->rx_start_page = db->tx_start_page + TX_PAGES;    // setup trasmit page and receive ring    ne2kpci_outb(db->tx_start_page, NE_TPSR);    db->tx1 = db->tx2 = 0;    ne2kpci_outb(db->rx_start_page, NE_PSTART);    ne2kpci_outb(db->stop_page - 1, NE_BNRY);    db->current_page = db->rx_start_page;    ne2kpci_outb(db->stop_page, NE_PSTOP);    // setup physical address     ne2kpci_set_page(1);    for (i = 0; i < 6; ++i)        ne2kpci_outb(db->prom[i], NE_PAR + i);    // setup rx page    ne2kpci_outb(db->rx_start_page, NE_CURR);    ne2kpci_set_page(0);        return 0;}int ne2kpci_start(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    ne2kpci_outb(0xff, NE_ISR);    ne2kpci_outb(0x3f, NE_IMR);    ne2kpci_outb(0x22, NE_CR);    ne2kpci_outb(0x00, NE_TCR);    ne2kpci_outb(0x04, NE_RCR);    return 0;}int ne2kpci_open(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    ne2kpci_init(dev);    em86xx_request_irq(db->pcidev.irqline, ne2kpci_irq, dev);    ne2kpci_start(dev);    dev->state = NETDEV_UP;            return 0;}int ne2kpci_close(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    em86xx_free_irq(db->pcidev.irqline);    dev->state = NETDEV_DOWN;                return 0;}int ne2kpci_irq_pending(struct net_device *dev){    return 0;}void ne2kpci_rx_overrun(struct net_device *dev){    uart_puts("NE2KPCI : RX Overrun\n");}void ne2kpci_rx(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    unsigned int curpage, frame;        ne2kpci_outb(ENCMD_NODMA | ENCMD_PAGE1, NE_CR);    curpage = ne2kpci_inb(NE_CURR);    ne2kpci_outb(ENCMD_NODMA | ENCMD_PAGE0, NE_CR);        frame = ne2kpci_inb(NE_BNRY) + 1;}void ne2kpci_tx(struct net_device *dev){}void ne2kpci_tx_error(struct net_device *dev){}void ne2kpci_irq(int irq, void *pdata){    struct net_device *dev = (struct net_device *) pdata;    board_info_t *db = (board_info_t *) dev->priv;    unsigned int isr;        ne2kpci_set_page(0);    while ((isr = ne2kpci_inb(NE_ISR)) != 0) {        if (isr & ENISR_OVER) {            // overrun            ne2kpci_rx_overrun(dev);        } else if (isr & (ENISR_RX | ENISR_RX_ERR)) {            // RX or RX error            ne2kpci_rx(dev);            } else if (isr & ENISR_TX) {            // TX            ne2kpci_tx(dev);        } else if (isr & ENISR_TX_ERR) {            // TX error            ne2kpci_tx_error(dev);        } else if (isr & ENISR_COUNTERS) {            // update counter            ne2kpci_outb(ENISR_COUNTERS, NE_ISR);        } else if (isr & ENISR_RDC) {            ne2kpci_outb(ENISR_RDC, NE_ISR);        }        ne2kpci_outb(ENCMD_NODMA | ENCMD_START, NE_CR);    }}int ne2kpci_send_packet(struct sk_buff *skb, struct net_device *dev){    return 0;}int ne2kpci_receive_packet(struct net_device *dev){    return 0;}void ne2kpci_print_status(struct net_device *dev){}

⌨️ 快捷键说明

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