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

📄 rtl8139.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/** * QEMU RTL8139 emulation *  * Copyright (c) 2006 Igor Kovalenko *  * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE.  * Modifications: *  2006-Jan-28  Mark Malakanov :   TSAD and CSCR implementation (for Windows driver) *                  */#include "vl.h"/* debug RTL8139 card *///#define DEBUG_RTL8139 1/* debug RTL8139 card C+ mode only *///#define DEBUG_RTL8139CP 1/* RTL8139 provides frame CRC with received packet, this feature seems to be   ignored by most drivers, disabled by default *///#define RTL8139_CALCULATE_RXCRC 1#if defined(RTL8139_CALCULATE_RXCRC)/* For crc32 */#include <zlib.h>#endif#define SET_MASKED(input, mask, curr) \    ( ( (input) & ~(mask) ) | ( (curr) & (mask) ) )/* arg % size for size which is a power of 2 */#define MOD2(input, size) \    ( ( input ) & ( size - 1 )  )/* Symbolic offsets to registers. */enum RTL8139_registers {    MAC0 = 0,        /* Ethernet hardware address. */    MAR0 = 8,        /* Multicast filter. */    TxStatus0 = 0x10,    /* Transmit status (Four 32bit registers). */    TxAddr0 = 0x20,        /* Tx descriptors (also four 32bit). */    RxBuf = 0x30,    ChipCmd = 0x37,    RxBufPtr = 0x38,    RxBufAddr = 0x3A,    IntrMask = 0x3C,    IntrStatus = 0x3E,    TxConfig = 0x40,    RxConfig = 0x44,    Timer = 0x48,        /* A general-purpose counter. */    RxMissed = 0x4C,    /* 24 bits valid, write clears. */    Cfg9346 = 0x50,    Config0 = 0x51,    Config1 = 0x52,    FlashReg = 0x54,    MediaStatus = 0x58,    Config3 = 0x59,    Config4 = 0x5A,        /* absent on RTL-8139A */    HltClk = 0x5B,    MultiIntr = 0x5C,    PCIRevisionID = 0x5E,    TxSummary = 0x60, /* TSAD register. Transmit Status of All Descriptors*/    BasicModeCtrl = 0x62,    BasicModeStatus = 0x64,    NWayAdvert = 0x66,    NWayLPAR = 0x68,    NWayExpansion = 0x6A,    /* Undocumented registers, but required for proper operation. */    FIFOTMS = 0x70,        /* FIFO Control and test. */    CSCR = 0x74,        /* Chip Status and Configuration Register. */    PARA78 = 0x78,    PARA7c = 0x7c,        /* Magic transceiver parameter register. */    Config5 = 0xD8,        /* absent on RTL-8139A */    /* C+ mode */    TxPoll        = 0xD9,    /* Tell chip to check Tx descriptors for work */    RxMaxSize    = 0xDA, /* Max size of an Rx packet (8169 only) */    CpCmd        = 0xE0, /* C+ Command register (C+ mode only) */    IntrMitigate    = 0xE2,    /* rx/tx interrupt mitigation control */    RxRingAddrLO    = 0xE4, /* 64-bit start addr of Rx ring */    RxRingAddrHI    = 0xE8, /* 64-bit start addr of Rx ring */    TxThresh    = 0xEC, /* Early Tx threshold */};enum ClearBitMasks {    MultiIntrClear = 0xF000,    ChipCmdClear = 0xE2,    Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1),};enum ChipCmdBits {    CmdReset = 0x10,    CmdRxEnb = 0x08,    CmdTxEnb = 0x04,    RxBufEmpty = 0x01,};/* C+ mode */enum CplusCmdBits {    CPlusRxEnb = 0x0002,    CPlusTxEnb = 0x0001,};/* Interrupt register bits, using my own meaningful names. */enum IntrStatusBits {    PCIErr = 0x8000,    PCSTimeout = 0x4000,    RxFIFOOver = 0x40,    RxUnderrun = 0x20,    RxOverflow = 0x10,    TxErr = 0x08,    TxOK = 0x04,    RxErr = 0x02,    RxOK = 0x01,    RxAckBits = RxFIFOOver | RxOverflow | RxOK,};enum TxStatusBits {    TxHostOwns = 0x2000,    TxUnderrun = 0x4000,    TxStatOK = 0x8000,    TxOutOfWindow = 0x20000000,    TxAborted = 0x40000000,    TxCarrierLost = 0x80000000,};enum RxStatusBits {    RxMulticast = 0x8000,    RxPhysical = 0x4000,    RxBroadcast = 0x2000,    RxBadSymbol = 0x0020,    RxRunt = 0x0010,    RxTooLong = 0x0008,    RxCRCErr = 0x0004,    RxBadAlign = 0x0002,    RxStatusOK = 0x0001,};/* Bits in RxConfig. */enum rx_mode_bits {    AcceptErr = 0x20,    AcceptRunt = 0x10,    AcceptBroadcast = 0x08,    AcceptMulticast = 0x04,    AcceptMyPhys = 0x02,    AcceptAllPhys = 0x01,};/* Bits in TxConfig. */enum tx_config_bits {        /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */        TxIFGShift = 24,        TxIFG84 = (0 << TxIFGShift),    /* 8.4us / 840ns (10 / 100Mbps) */        TxIFG88 = (1 << TxIFGShift),    /* 8.8us / 880ns (10 / 100Mbps) */        TxIFG92 = (2 << TxIFGShift),    /* 9.2us / 920ns (10 / 100Mbps) */        TxIFG96 = (3 << TxIFGShift),    /* 9.6us / 960ns (10 / 100Mbps) */    TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */    TxCRC = (1 << 16),    /* DISABLE appending CRC to end of Tx packets */    TxClearAbt = (1 << 0),    /* Clear abort (WO) */    TxDMAShift = 8,        /* DMA burst value (0-7) is shifted this many bits */    TxRetryShift = 4,    /* TXRR value (0-15) is shifted this many bits */    TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */};/* Transmit Status of All Descriptors (TSAD) Register */enum TSAD_bits { TSAD_TOK3 = 1<<15, // TOK bit of Descriptor 3 TSAD_TOK2 = 1<<14, // TOK bit of Descriptor 2 TSAD_TOK1 = 1<<13, // TOK bit of Descriptor 1 TSAD_TOK0 = 1<<12, // TOK bit of Descriptor 0 TSAD_TUN3 = 1<<11, // TUN bit of Descriptor 3 TSAD_TUN2 = 1<<10, // TUN bit of Descriptor 2 TSAD_TUN1 = 1<<9, // TUN bit of Descriptor 1 TSAD_TUN0 = 1<<8, // TUN bit of Descriptor 0 TSAD_TABT3 = 1<<07, // TABT bit of Descriptor 3 TSAD_TABT2 = 1<<06, // TABT bit of Descriptor 2 TSAD_TABT1 = 1<<05, // TABT bit of Descriptor 1 TSAD_TABT0 = 1<<04, // TABT bit of Descriptor 0 TSAD_OWN3 = 1<<03, // OWN bit of Descriptor 3 TSAD_OWN2 = 1<<02, // OWN bit of Descriptor 2 TSAD_OWN1 = 1<<01, // OWN bit of Descriptor 1 TSAD_OWN0 = 1<<00, // OWN bit of Descriptor 0};/* Bits in Config1 */enum Config1Bits {    Cfg1_PM_Enable = 0x01,    Cfg1_VPD_Enable = 0x02,    Cfg1_PIO = 0x04,    Cfg1_MMIO = 0x08,    LWAKE = 0x10,        /* not on 8139, 8139A */    Cfg1_Driver_Load = 0x20,    Cfg1_LED0 = 0x40,    Cfg1_LED1 = 0x80,    SLEEP = (1 << 1),    /* only on 8139, 8139A */    PWRDN = (1 << 0),    /* only on 8139, 8139A */};/* Bits in Config3 */enum Config3Bits {    Cfg3_FBtBEn    = (1 << 0), /* 1 = Fast Back to Back */    Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */    Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */    Cfg3_CardB_En  = (1 << 3), /* 1 = enable CardBus registers */    Cfg3_LinkUp    = (1 << 4), /* 1 = wake up on link up */    Cfg3_Magic     = (1 << 5), /* 1 = wake up on Magic Packet (tm) */    Cfg3_PARM_En   = (1 << 6), /* 0 = software can set twister parameters */    Cfg3_GNTSel    = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */};/* Bits in Config4 */enum Config4Bits {    LWPTN = (1 << 2),    /* not on 8139, 8139A */};/* Bits in Config5 */enum Config5Bits {    Cfg5_PME_STS     = (1 << 0), /* 1 = PCI reset resets PME_Status */    Cfg5_LANWake     = (1 << 1), /* 1 = enable LANWake signal */    Cfg5_LDPS        = (1 << 2), /* 0 = save power when link is down */    Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */    Cfg5_UWF         = (1 << 4), /* 1 = accept unicast wakeup frame */    Cfg5_MWF         = (1 << 5), /* 1 = accept multicast wakeup frame */    Cfg5_BWF         = (1 << 6), /* 1 = accept broadcast wakeup frame */};enum RxConfigBits {    /* rx fifo threshold */    RxCfgFIFOShift = 13,    RxCfgFIFONone = (7 << RxCfgFIFOShift),    /* Max DMA burst */    RxCfgDMAShift = 8,    RxCfgDMAUnlimited = (7 << RxCfgDMAShift),    /* rx ring buffer length */    RxCfgRcv8K = 0,    RxCfgRcv16K = (1 << 11),    RxCfgRcv32K = (1 << 12),    RxCfgRcv64K = (1 << 11) | (1 << 12),    /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */    RxNoWrap = (1 << 7),};/* Twister tuning parameters from RealTek.   Completely undocumented, but required to tune bad links on some boards. *//*enum CSCRBits {    CSCR_LinkOKBit = 0x0400,    CSCR_LinkChangeBit = 0x0800,    CSCR_LinkStatusBits = 0x0f000,    CSCR_LinkDownOffCmd = 0x003c0,    CSCR_LinkDownCmd = 0x0f3c0,*/enum CSCRBits {    CSCR_Testfun = 1<<15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */     CSCR_LD  = 1<<9,  /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/    CSCR_HEART_BIT = 1<<8,  /* 1 = HEART BEAT enable, 0 = HEART BEAT disable. HEART BEAT function is only valid in 10Mbps mode. def 1*/    CSCR_JBEN = 1<<7,  /* 1 = enable jabber function. 0 = disable jabber function, def 1*/    CSCR_F_LINK_100 = 1<<6, /* Used to login force good link in 100Mbps for diagnostic purposes. 1 = DISABLE, 0 = ENABLE. def 1*/     CSCR_F_Connect  = 1<<5,  /* Assertion of this bit forces the disconnect function to be bypassed. def 0*/    CSCR_Con_status = 1<<3, /* This bit indicates the status of the connection. 1 = valid connected link detected; 0 = disconnected link detected. RO def 0*/    CSCR_Con_status_En = 1<<2, /* Assertion of this bit configures LED1 pin to indicate connection status. def 0*/    CSCR_PASS_SCR = 1<<0, /* Bypass Scramble, def 0*/};enum Cfg9346Bits {    Cfg9346_Lock = 0x00,    Cfg9346_Unlock = 0xC0,};typedef enum {    CH_8139 = 0,    CH_8139_K,    CH_8139A,    CH_8139A_G,    CH_8139B,    CH_8130,    CH_8139C,    CH_8100,    CH_8100B_8139D,    CH_8101,} chip_t;enum chip_flags {    HasHltClk = (1 << 0),    HasLWake = (1 << 1),};#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \    (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22)#define HW_REVID_MASK    HW_REVID(1, 1, 1, 1, 1, 1, 1)/* Size is 64 * 16bit words */#define EEPROM_9346_ADDR_BITS 6#define EEPROM_9346_SIZE  (1 << EEPROM_9346_ADDR_BITS)#define EEPROM_9346_ADDR_MASK (EEPROM_9346_SIZE - 1)enum Chip9346Operation{    Chip9346_op_mask = 0xc0,          /* 10 zzzzzz */    Chip9346_op_read = 0x80,          /* 10 AAAAAA */    Chip9346_op_write = 0x40,         /* 01 AAAAAA D(15)..D(0) */    Chip9346_op_ext_mask = 0xf0,      /* 11 zzzzzz */    Chip9346_op_write_enable = 0x30,  /* 00 11zzzz */    Chip9346_op_write_all = 0x10,     /* 00 01zzzz */    Chip9346_op_write_disable = 0x00, /* 00 00zzzz */};enum Chip9346Mode{    Chip9346_none = 0,    Chip9346_enter_command_mode,    Chip9346_read_command,    Chip9346_data_read,      /* from output register */    Chip9346_data_write,     /* to input register, then to contents at specified address */    Chip9346_data_write_all, /* to input register, then filling contents */};typedef struct EEprom9346{    uint16_t contents[EEPROM_9346_SIZE];    int      mode;    uint32_t tick;    uint8_t  address;    uint16_t input;    uint16_t output;    uint8_t eecs;    uint8_t eesk;    uint8_t eedi;    uint8_t eedo;} EEprom9346;typedef struct RTL8139State {    uint8_t phys[8]; /* mac address */    uint8_t mult[8]; /* multicast mask array */    uint32_t TxStatus[4]; /* TxStatus0 */    uint32_t TxAddr[4];   /* TxAddr0 */    uint32_t RxBuf;       /* Receive buffer */    uint32_t RxBufferSize;/* internal variable, receive ring buffer size in C mode */    uint32_t RxBufPtr;    uint32_t RxBufAddr;    uint16_t IntrStatus;    uint16_t IntrMask;    uint32_t TxConfig;    uint32_t RxConfig;    uint32_t RxMissed;    uint16_t CSCR;    uint8_t  Cfg9346;    uint8_t  Config0;    uint8_t  Config1;    uint8_t  Config3;    uint8_t  Config4;    uint8_t  Config5;    uint8_t  clock_enabled;    uint8_t  bChipCmdState;    uint16_t MultiIntr;    uint16_t BasicModeCtrl;    uint16_t BasicModeStatus;    uint16_t NWayAdvert;    uint16_t NWayLPAR;    uint16_t NWayExpansion;    uint16_t CpCmd;    uint8_t  TxThresh;    int irq;    PCIDevice *pci_dev;    VLANClientState *vc;    uint8_t macaddr[6];    int rtl8139_mmio_io_addr;    /* C ring mode */    uint32_t   currTxDesc;    /* C+ mode */    uint32_t   currCPlusRxDesc;    uint32_t   currCPlusTxDesc;    uint32_t   RxRingAddrLO;    uint32_t   RxRingAddrHI;    EEprom9346 eeprom;    } RTL8139State;void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command){#if defined(DEBUG_RTL8139)    printf("RTL8139: eeprom command 0x%02x\n", command);#endif    switch (command & Chip9346_op_mask)    {        case Chip9346_op_read:        {            eeprom->address = command & EEPROM_9346_ADDR_MASK;            eeprom->output = eeprom->contents[eeprom->address];            eeprom->eedo = 0;            eeprom->tick = 0;            eeprom->mode = Chip9346_data_read;#if defined(DEBUG_RTL8139)            printf("RTL8139: eeprom read from address 0x%02x data=0x%04x\n",                   eeprom->address, eeprom->output);#endif        }        break;        case Chip9346_op_write:        {            eeprom->address = command & EEPROM_9346_ADDR_MASK;            eeprom->input = 0;            eeprom->tick = 0;            eeprom->mode = Chip9346_none; /* Chip9346_data_write */#if defined(DEBUG_RTL8139)            printf("RTL8139: eeprom begin write to address 0x%02x\n",                   eeprom->address);#endif        }        break;        default:            eeprom->mode = Chip9346_none;            switch (command & Chip9346_op_ext_mask)            {                case Chip9346_op_write_enable:#if defined(DEBUG_RTL8139)                    printf("RTL8139: eeprom write enabled\n");#endif                    break;                case Chip9346_op_write_all:#if defined(DEBUG_RTL8139)                    printf("RTL8139: eeprom begin write all\n");#endif                    break;                case Chip9346_op_write_disable:#if defined(DEBUG_RTL8139)                    printf("RTL8139: eeprom write disabled\n");#endif                    break;            }            break;    }}void prom9346_shift_clock(EEprom9346 *eeprom){    int bit = eeprom->eedi?1:0;    ++ eeprom->tick;#if defined(DEBUG_RTL8139)    printf("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo);#endif    switch (eeprom->mode)    {        case Chip9346_enter_command_mode:            if (bit)            {                eeprom->mode = Chip9346_read_command;                eeprom->tick = 0;                eeprom->input = 0;#if defined(DEBUG_RTL8139)                printf("eeprom: +++ synchronized, begin command read\n");#endif            }            break;        case Chip9346_read_command:            eeprom->input = (eeprom->input << 1) | (bit & 1);            if (eeprom->tick == 8)

⌨️ 快捷键说明

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