📄 ne2kpci.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 + -