📄 rtl81xx.c
字号:
/***************************************** Copyright (c) 2002-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the boot loader *//* * rtl81xx.c * * driver for RTL81xx PCI ethernet adapter * * by Ho Lee Mar 2004 */#include "config.h"#include "uart.h"#include "util.h"#include "net.h"#include "net_ipv4.h"#include "pcicommon.h"#include "io.h"#include "timer.h"#define RTL81XX_VERBOSE 0// // constant defitions related RTL81xx//// PCI ID#define RTL8139_VENDOR_ID 0x10ec#define RTL8139_DEVICE_ID 0x8139// Registers#define REG_IDR 0x00 // 6 bytes : MAC Address#define REG_MAR 0x08 // 8 bytes : Multicast registers#define REG_TSD0 0x10 // 4 bytes : Transmit status of descriptor 0#define REG_TSD1 0x14 // 4 bytes : Transmit status of descriptor 1#define REG_TSD2 0x18 // 4 bytes : Transmit status of descriptor 2#define REG_TSD3 0x1c // 4 bytes : Transmit status of descriptor 3#define REG_TSAD0 0x20 // 4 bytes : Transmit start address of descriptor 0#define REG_TSAD1 0x24 // 4 bytes : Transmit start address of descriptor 1#define REG_TSAD2 0x28 // 4 bytes : Transmit start address of descriptor 2#define REG_TSAD3 0x2c // 4 bytes : Transmit start address of descriptor 3#define REG_RBSTART 0x30 // 4 bytes : Receive (Rx) buffer start address#define REG_ERBCR 0x34 // 2 bytes : Early receive (Rx) byte count register#define REG_ERSR 0x36 // 1 byte : Early Rx status register#define REG_CR 0x37 // 1 byte : Command register#define REG_CAPR 0x38 // 2 bytes : current address of packet read#define REG_CBR 0x3a // 2 bytes : current buffer address#define REG_IMR 0x3c // 2 bytes : interrupt mask register#define REG_ISR 0x3e // 2 bytes : interrupt status register#define REG_TCR 0x40 // 4 bytes : Transmit (Tx) configuration register#define REG_CHIPVER 0x43 // 1 byte : Chip version #define REG_RCR 0x44 // 4 bytes : Receive (Rx) configuration register#define REG_TCTR 0x48 // 4 bytes : Timer count register#define REG_MPC 0x4c // 4 bytes : Missed packet counter#define REG_CR93C46 0x50 // 1 byte : 93C46 (93C56) command register#define REG_CONFIG0 0x51 // 1 byte : Configuration register 0#define REG_CONFIG1 0x52 // 1 byte : Configuration register 1#define REG_TIMERINT 0x54 // 4 bytes : Timer interrupt register#define REG_MSR 0x58 // 1 byte : Media status register#define REG_CONFIG3 0x59 // 1 byte : Configuration register 3#define REG_CONFIG4 0x5a // 1 byte : Configuration register 4#define REG_MULINT 0x5c // 2 bytes : Multiple interrupt select#define REG_RERID 0x5e // 1 bytes : PCI revision ID#define REG_TSAD 0x60 // 2 bytes : Transmit status of all descriptors#define REG_BMCR 0x62 // 2 bytes : Basic mode control register#define REG_BMSR 0x64 // 2 bytes : Basic mode status register#define REG_ANAR 0x66 // 2 bytes : Auto-nogitiation advertisement register#define REG_ANLPAR 0x68 // 2 bytes : Auto-negotiation link partner register#define REG_ANER 0x6a // 2 bytes : Auto-negotiation expansion register#define REG_DIS 0x6c // 2 bytes : Disconnect counter#define REG_FCSC 0x6e // 2 bytes : False carrier sense counter#define REG_NWAYTR 0x70 // 2 bytes : N-way test register#define REG_REC 0x72 // 2 bytes : RX_ER counter#define REG_CSCR 0x74 // 2 bytes : CS configuration register#define REG_PHY1_PARM 0x78 // 4 bytes : PHY parameter 1#define REG_TW_PARM 0x7c // 4 bytes : Twister parameter#define REG_PHY2_PARM 0x80 // 1 byte : PHY parameter 2#define REG_CRC 0x84 // 1 byte * 8 : Power management CRC register n for wakeup frame n#define REG_WAKEUP 0x8c // 8 bytes * 8 : Power management wakeup frame n#define REG_LSBCRC 0xcc // 1 byte * 8 : LSB of the mask byte of wakeup frame n#define REG_FLASH 0xd4 // 4 bytes : Flash memory read/write register#define REG_CONFIG5 0xd8 // 1 byte : Configuration register 5#define REG_FER 0xf0 // 4 bytes : Function event register#define REG_FEMR 0xf4 // 4 bytes : Function event mask register#define REG_FPSR 0xf8 // 4 bytes : Function present state register#define REG_FFER 0xfc // 4 bytes : function force event register// Receive status register in Rx packet header#define RXHEADER_ROK 0x0001 // Receive OK#define RXHEADER_FAE 0x0002 // Frame alignment error#define RXHEADER_CRC 0x0004 // CRC error#define RXHEADER_LONG 0x0008 // Long packet#define RXHEADER_RUNT 0x0010 // Runt packet received#define RXHEADER_ISE 0x0020 // Invalid symbol error#define RXHEADER_BAR 0x2000 // Broadcast address received#define RXHEADER_PAM 0x4000 // Physical address matched#define RXHEADER_MAR 0x8000 // Multicast address received// Transmit status register (REG_TSDn)#define TSD_SIZEMASK 0x00001fff // Descriptor size#define TSD_OWN 0x00002000 // OWN#define TSD_TUN 0x00004000 // Transmit FIFO underrun#define TSD_TOK 0x00008000 // Transmit OK#define TSD_ERTXTHMASK 0x003f0000 // Early Tx Threshold#define TSD_NCCMASK 0x0f000000 // Number of collision count#define TSD_CDH 0x10000000 // CD heart beat#define TSD_OWC 0x20000000 // Out of window collision#define TSD_TABT 0x40000000 // Transmit abort#define TSD_CRS 0x8000000 // carrier sense lost// Early Rx status register (REG_ERSR)#define ERSR_EROK 0x01 // Early Rx OK#define ERSR_EROVW 0x02 // Early Rx overwrite#define ERSR_ERBAD 0x04 // Early Rx bad packet#define ERSR_ERGOOD 0x08 // Early Rx good packet// Command register (REG_CR)#define CR_BUFE 0x01 // Buffer empty#define CR_TE 0x04 // Transmitter enable#define CR_RE 0x08 // Receiver enable#define CR_RST 0x10 // Reset// Interrupt status / mask register (REG_IMR, REG_ISR)#define ISR_ROK 0x0001 // Receive OK#define ISR_RER 0x0002 // Receive error#define ISR_TOK 0x0004 // Transmit OK#define ISR_TER 0x0008 // Transmit error#define ISR_RXOVW 0x0010 // Rx buffer overflow#define ISR_PUNLINKCHG 0x0020 // Packet underrun / Link change#define ISR_FOVW 0x0040 // Rx FIFO overflow#define ISR_LENCHG 0x2000 // Cable length change#define ISR_TIMEOUT 0x4000 // Timeout#define ISR_SERR 0x8000 // System error// Transmit configuration register (REG_TCR)#define TCR_CLRABT 0x00000001 // Clear abort#define TCR_TXRRMASK 0x000000f0 // Tx retry count#define TCR_MXDMAMASK 0x00000700 // Max DMA burst size#define TCR_CRC 0x00010000 // Append CRC#define TCR_LBKMASK 0x00060000 // Loopback test#define TCR_IFGMASK 0x03000000 // Interframe gap time#define TCR_BLID 0x08000000 // RTL8139B ID#define TCR_HWVERMASK 0x70000000 // Hardware version number// Receive configuration register (REG_RCR)#define RCR_AAP 0x00000001 // Accept all packets#define RCR_APM 0x00000002 // Accept physical match packets#define RCR_AM 0x00000004 // Accept multicast packets#define RCR_AB 0x00000008 // Accept broadcast packets#define RCR_AR 0x00000010 // Accept runt#define RCR_AER 0x00000020 // Accept error packets#define RCR_9356SEL 0x00000040 // Type of EEPROM#define RCR_WRAP 0x00000080 //#define RCR_MXDMAMASK 0x00000700 // Max DMA burst size per Rx DMA burst#define RCR_RBLENMASK 0x00001800 // Rx buffer length#define RCR_RXFTHMASK 0x0000e000 // Rx FIFO threshold#define RCR_RER8 0x00010000 // Receive error packet whose length is larger than 8 bytes#define RCR_MULERINT 0x00020000 // Multiple early interrupt select#define RCR_ERTHMASK 0x0f000000 // Early Rx threshold// 93C46 command register (REG_CR93C46)#define CR93C46_EEDO 0x01 // State of EEDO#define CR93C46_EEDI 0x02 // State of EEDI#define CR93C46_EESK 0x04 // State of EESK#define CR93C46_EECS 0x08 // State of EECS#define CR93C46_EEM_NORMAL 0x00 // Normal communication mode#define CR93C46_EEM_AUTOLOAD 0x40 // Auto-load#define CR93C46_EEM_PROGRAM 0x80 // 93C46 programming#define CR93C46_EEM_CONFIGWEN 0xc0 // Config register write enable#define CR93C46_CMD_WEN 4#define CR93C46_CMD_WRITE 5#define CR93C46_CMD_READ 6#define CR93C46_CMD_ERASE 7//// type definitions// #define RX_BUF_LEN 0x8000 // 32KB : Choose 32KB instead of 64KB for the sake of 'no wrap' // We have to wrap Rx buffer if 64KB is selected. // So allocate 1.5KB of extra buffer#define RX_BUF_TOTAL_LEN (RX_BUF_LEN + 16 + ETH_BUF_LEN)#define TX_DESC_NUM 4 // number of Tx descriptor#define TX_DESC_LEN ETH_BUF_LEN // size of Tx descriptor#define TX_BUF_LEN (TX_DESC_NUM * TX_DESC_LEN)typedef struct board_info { struct my_pci_dev pcidev; unsigned int ioaddr; int chipset; unsigned long rx_buf, rx_buf_dma; unsigned long tx_buf, tx_buf_dma, tx_bufs[TX_DESC_NUM], tx_bufs_dma[TX_DESC_NUM]; int rx_cur, tx_cur, tx_last; volatile struct sk_buff *tx_skb[TX_DESC_NUM];} board_info_t;//// global configuration & variables// static board_info_t g_board_info;// default IMR : enable all of interrupts except ISR_LENCHGstatic unsigned int g_imr = ISR_SERR | ISR_TIMEOUT | ISR_FOVW | ISR_PUNLINKCHG | ISR_RXOVW | ISR_TER | ISR_TOK | ISR_RER | ISR_ROK;// default TSD : Tx threshold = 256 bytesstatic unsigned int g_tsd = ((256 >> 5) << 16);// default TCR : Unlimited DMA, Retry count = 15static unsigned int g_tx_config = (7 << 8) | (15 << 4);// default RCR : No early Rx threshold, No multiple early interrupt, // No Rx threshold, Rx buffer = 32KB, Unlimited DMA, No wrap,// Accpet physical match and broadcast packetsstatic unsigned int g_rx_config = (7 << 13) | (0x2 << 11) | (7 << 8) | RCR_WRAP | RCR_APM | RCR_AB;//// Basic I/O//#define rtl81xx_readb(reg) pci_readb(g_board_info.ioaddr + (reg))#define rtl81xx_readw(reg) pci_readw(g_board_info.ioaddr + (reg))#define rtl81xx_readl(reg) pci_readl(g_board_info.ioaddr + (reg))#define rtl81xx_writeb(val, reg) pci_writeb(val, g_board_info.ioaddr + (reg))#define rtl81xx_writew(val, reg) pci_writew(val, g_board_info.ioaddr + (reg))#define rtl81xx_writel(val, reg) pci_writel(val, g_board_info.ioaddr + (reg))//// Function prototypes//int rtl81xx_probe(struct net_device *dev);static int rtl81xx_init(struct net_device *dev);static int rtl81xx_open(struct net_device *dev);static int rtl81xx_close(struct net_device *dev);static int rtl81xx_rx_interrupt(struct net_device *dev);static void rtl81xx_tx_interrupt(struct net_device *dev);static void rtl81xx_irq(int irq, void *pdata);static int rtl81xx_send_packet(struct sk_buff *skbuff, struct net_device *dev, int async);static int rtl81xx_receive_packet(struct net_device *dev);static void rtl81xx_print_status(struct net_device *dev);static void rtl81xx_chip_reset(void);static unsigned int rtl81xx_read_eeprom(int addr, int addr_len);//// Init & Main//int rtl81xx_probe(struct net_device *dev){ int i; board_info_t *db = &g_board_info; if (pci_lookup(RTL8139_VENDOR_ID, RTL8139_DEVICE_ID, &db->pcidev)) { uart_printf("Found RTL8139 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); uart_printf(" Assign Memory address from 0x%08x, size 0x%x\n", db->pcidev.resource[1].start, db->pcidev.resource[1].size); uart_printf(" Use Memory Mapped I/O\n"); db->ioaddr = db->pcidev.resource[1].start; // setup Rx and Tx buffer db->rx_buf = (unsigned long) malloc(RX_BUF_TOTAL_LEN); db->rx_buf_dma = virt_to_bus(db->rx_buf); db->tx_buf = (unsigned long) malloc(TX_BUF_LEN); db->tx_buf_dma = virt_to_bus(db->tx_buf); for (i = 0; i < TX_DESC_NUM; ++i) { db->tx_bufs[i] = db->tx_buf + TX_DESC_LEN * i; db->tx_bufs_dma[i] = virt_to_bus(db->tx_bufs[i]); } em86xx_flush_cache_data(); // register functions dev->state = NETDEV_DOWN; dev->priv = db; dev->init = rtl81xx_init; dev->open = rtl81xx_open; dev->close = rtl81xx_close; dev->send_packet = rtl81xx_send_packet; dev->receive_packet = rtl81xx_receive_packet; dev->print_status = rtl81xx_print_status; return 1; } return 0;}int rtl81xx_init(struct net_device *dev){ board_info_t *db = (board_info_t *) dev->priv; unsigned char chipver; unsigned char *chipver_name; int i; // Read chip information chipver = rtl81xx_readb(REG_CHIPVER); switch (chipver) { case 0x40 : /* RTL8139 */ chipver_name = "RTL8139"; db->chipset = 0; break; case 0x60 : /* RTL8139 rev. K */ chipver_name = "RTL8139 rev. K"; db->chipset = 1; break; case 0x70 : /* RTL8139A */ chipver_name = "RTL8139A"; db->chipset = 2; break; case 0x78 : /* RTL8139B */ chipver_name = "RTL8139B"; db->chipset = 3; break; case 0x7c : /* RTL8130 */ chipver_name = "RTL8130"; db->chipset = 4; break; case 0x74 : /* RTL8139C */ chipver_name = "RTL8139C"; db->chipset = 5; break; default : chipver_name = "Unknown"; db->chipset = 0; break; } uart_printf(" Chip version: 0x%02x (%s)\n", chipver, chipver_name); if (db->chipset >= 3) { /* Later than 8139B */ unsigned char config1 = rtl81xx_readb(REG_CONFIG1); rtl81xx_writel(CR93C46_EEM_CONFIGWEN, REG_CR93C46); config1 &= ~0x10; /* clear LWake */ rtl81xx_writeb(config1, REG_CONFIG1); rtl81xx_writel(CR93C46_EEM_NORMAL, REG_CR93C46); } else { unsigned char config1 = rtl81xx_readb(REG_CONFIG1); config1 &= ~0x3; /* Clear sleep/pwrdn */ rtl81xx_writeb(config1, REG_CONFIG1); } // Reset board rtl81xx_chip_reset(); // Read MAC Address ((unsigned short *) dev->dev_addr)[0] = rtl81xx_read_eeprom(7, 6); ((unsigned short *) dev->dev_addr)[1] = rtl81xx_read_eeprom(8, 6); ((unsigned short *) dev->dev_addr)[2] = rtl81xx_read_eeprom(9, 6); uart_puts(" MAC address: "); for (i = 0; i < MACADDR_LEN; ++i) { uart_printf("%02X", dev->dev_addr[i]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -