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

📄 rtl8139.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
    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;    uint32_t   TCTR;    uint32_t   TimerInt;    int64_t    TCTR_base;    /* Tally counters */    RTL8139TallyCounters tally_counters;    /* Non-persistent data */    uint8_t   *cplus_txbuffer;    int        cplus_txbuffer_len;    int        cplus_txbuffer_offset;    /* PCI interrupt timer */    QEMUTimer *timer;} RTL8139State;void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command){    DEBUG_PRINT(("RTL8139: eeprom command 0x%02x\n", command));    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;            DEBUG_PRINT(("RTL8139: eeprom read from address 0x%02x data=0x%04x\n",                   eeprom->address, eeprom->output));        }        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 */            DEBUG_PRINT(("RTL8139: eeprom begin write to address 0x%02x\n",                   eeprom->address));        }        break;        default:            eeprom->mode = Chip9346_none;            switch (command & Chip9346_op_ext_mask)            {                case Chip9346_op_write_enable:                    DEBUG_PRINT(("RTL8139: eeprom write enabled\n"));                    break;                case Chip9346_op_write_all:                    DEBUG_PRINT(("RTL8139: eeprom begin write all\n"));                    break;                case Chip9346_op_write_disable:                    DEBUG_PRINT(("RTL8139: eeprom write disabled\n"));                    break;            }            break;    }}void prom9346_shift_clock(EEprom9346 *eeprom){    int bit = eeprom->eedi?1:0;    ++ eeprom->tick;    DEBUG_PRINT(("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo));    switch (eeprom->mode)    {        case Chip9346_enter_command_mode:            if (bit)            {                eeprom->mode = Chip9346_read_command;                eeprom->tick = 0;                eeprom->input = 0;                DEBUG_PRINT(("eeprom: +++ synchronized, begin command read\n"));            }            break;        case Chip9346_read_command:            eeprom->input = (eeprom->input << 1) | (bit & 1);            if (eeprom->tick == 8)            {                prom9346_decode_command(eeprom, eeprom->input & 0xff);            }            break;        case Chip9346_data_read:            eeprom->eedo = (eeprom->output & 0x8000)?1:0;            eeprom->output <<= 1;            if (eeprom->tick == 16)            {#if 1        // the FreeBSD drivers (rl and re) don't explicitly toggle        // CS between reads (or does setting Cfg9346 to 0 count too?),        // so we need to enter wait-for-command state here                eeprom->mode = Chip9346_enter_command_mode;                eeprom->input = 0;                eeprom->tick = 0;                DEBUG_PRINT(("eeprom: +++ end of read, awaiting next command\n"));#else        // original behaviour                ++eeprom->address;                eeprom->address &= EEPROM_9346_ADDR_MASK;                eeprom->output = eeprom->contents[eeprom->address];                eeprom->tick = 0;                DEBUG_PRINT(("eeprom: +++ read next address 0x%02x data=0x%04x\n",                       eeprom->address, eeprom->output));#endif            }            break;        case Chip9346_data_write:            eeprom->input = (eeprom->input << 1) | (bit & 1);            if (eeprom->tick == 16)            {                DEBUG_PRINT(("RTL8139: eeprom write to address 0x%02x data=0x%04x\n",                       eeprom->address, eeprom->input));                eeprom->contents[eeprom->address] = eeprom->input;                eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */                eeprom->tick = 0;                eeprom->input = 0;            }            break;        case Chip9346_data_write_all:            eeprom->input = (eeprom->input << 1) | (bit & 1);            if (eeprom->tick == 16)            {                int i;                for (i = 0; i < EEPROM_9346_SIZE; i++)                {                    eeprom->contents[i] = eeprom->input;                }                DEBUG_PRINT(("RTL8139: eeprom filled with data=0x%04x\n",                       eeprom->input));                eeprom->mode = Chip9346_enter_command_mode;                eeprom->tick = 0;                eeprom->input = 0;            }            break;        default:            break;    }}int prom9346_get_wire(RTL8139State *s){    EEprom9346 *eeprom = &s->eeprom;    if (!eeprom->eecs)        return 0;    return eeprom->eedo;}void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi){    EEprom9346 *eeprom = &s->eeprom;    uint8_t old_eecs = eeprom->eecs;    uint8_t old_eesk = eeprom->eesk;    eeprom->eecs = eecs;    eeprom->eesk = eesk;    eeprom->eedi = eedi;    DEBUG_PRINT(("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n",                 eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo));    if (!old_eecs && eecs)    {        /* Synchronize start */        eeprom->tick = 0;        eeprom->input = 0;        eeprom->output = 0;        eeprom->mode = Chip9346_enter_command_mode;        DEBUG_PRINT(("=== eeprom: begin access, enter command mode\n"));    }    if (!eecs)    {        DEBUG_PRINT(("=== eeprom: end access\n"));        return;    }    if (!old_eesk && eesk)    {        /* SK front rules */        prom9346_shift_clock(eeprom);    }}static void rtl8139_update_irq(RTL8139State *s){    int isr;    isr = (s->IntrStatus & s->IntrMask) & 0xffff;    DEBUG_PRINT(("RTL8139: Set IRQ line %d to %d (%04x %04x)\n",       s->irq, isr ? 1 : 0, s->IntrStatus, s->IntrMask));    if (s->irq == 16) {        /* PCI irq */        pci_set_irq(s->pci_dev, 0, (isr != 0));    } else {        /* ISA irq */        pic_set_irq(s->irq, (isr != 0));    }}#define POLYNOMIAL 0x04c11db6/* From FreeBSD *//* XXX: optimize */static int compute_mcast_idx(const uint8_t *ep){    uint32_t crc;    int carry, i, j;    uint8_t b;    crc = 0xffffffff;    for (i = 0; i < 6; i++) {        b = *ep++;        for (j = 0; j < 8; j++) {            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);            crc <<= 1;            b >>= 1;            if (carry)                crc = ((crc ^ POLYNOMIAL) | carry);        }    }    return (crc >> 26);}static int rtl8139_RxWrap(RTL8139State *s){    /* wrapping enabled; assume 1.5k more buffer space if size < 65536 */    return (s->RxConfig & (1 << 7));}static int rtl8139_receiver_enabled(RTL8139State *s){    return s->bChipCmdState & CmdRxEnb;}static int rtl8139_transmitter_enabled(RTL8139State *s){    return s->bChipCmdState & CmdTxEnb;}static int rtl8139_cp_receiver_enabled(RTL8139State *s){    return s->CpCmd & CPlusRxEnb;}static int rtl8139_cp_transmitter_enabled(RTL8139State *s){    return s->CpCmd & CPlusTxEnb;}static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size){    if (s->RxBufAddr + size > s->RxBufferSize)    {        int wrapped = MOD2(s->RxBufAddr + size, s->RxBufferSize);        /* write packet data */        if (wrapped && !(s->RxBufferSize < 65536 && rtl8139_RxWrap(s)))        {            DEBUG_PRINT((">>> RTL8139: rx packet wrapped in buffer at %d\n", size-wrapped));            if (size > wrapped)            {                cpu_physical_memory_write( s->RxBuf + s->RxBufAddr,                                           buf, size-wrapped );            }            /* reset buffer pointer */            s->RxBufAddr = 0;            cpu_physical_memory_write( s->RxBuf + s->RxBufAddr,                                       buf + (size-wrapped), wrapped );            s->RxBufAddr = wrapped;            return;        }    }    /* non-wrapping path or overwrapping enabled */    cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, buf, size );    s->RxBufAddr += size;}#define MIN_BUF_SIZE 60static inline target_phys_addr_t rtl8139_addr64(uint32_t low, uint32_t high){#if TARGET_PHYS_ADDR_BITS > 32    return low | ((target_phys_addr_t)high << 32);#else    return low;#endif}static int rtl8139_can_receive(void *opaque){    RTL8139State *s = opaque;    int avail;    /* Recieve (drop) packets if card is disabled.  */    if (!s->clock_enabled)      return 1;    if (!rtl8139_receiver_enabled(s))      return 1;    if (rtl8139_cp_receiver_enabled(s)) {        /* ??? Flow control not implemented in c+ mode.           This is a hack to work around slirp deficiencies anyway.  */        return 1;    } else {        avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr,                     s->RxBufferSize);        return (avail == 0 || avail >= 1514);    }}static void rtl8139_do_receive(void *opaque, const uint8_t *buf, int size, int do_interrupt){    RTL8139State *s = opaque;    uint32_t packet_header = 0;    uint8_t buf1[60];    static const uint8_t broadcast_macaddr[6] =         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };    DEBUG_PRINT((">>> RTL8139: received len=%d\n", size));    /* test if board clock is stopped */    if (!s->clock_enabled)    {        DEBUG_PRINT(("RTL8139: stopped ==========================\n"));        return;    }    /* first check if receiver is enabled */    if (!rtl8139_receiver_enabled(s))    {        DEBUG_PRINT(("RTL8139: receiver disabled ================\n"));        return;    }    /* XXX: check this */    if (s->RxConfig & AcceptAllPhys) {        /* promiscuous: receive all */        DEBUG_PRINT((">>> RTL8139: packet received in promiscuous mode\n"));    } else {        if (!memcmp(buf,  broadcast_macaddr, 6)) {            /* broadcast address */            if (!(s->RxConfig & AcceptBroadcast))            {                DEBUG_PRINT((">>> RTL8139: broadcast packet rejected\n"));                /* update tally counter */                ++s->tally_counters.RxERR;                return;            }            packet_header |= RxBroadcast;            DEBUG_PRINT((">>> RTL8139: broadcast packet received\n"));            /* update tally counter */            ++s->tally_counters.RxOkBrd;        } else if (buf[0] & 0x01) {            /* multicast */            if (!(s->RxConfig & AcceptMulticast))            {                DEBUG_PRINT((">>> RTL8139: multicast packet rejected\n"));                /* update tally counter */                ++s->tally_counters.RxERR;                return;            }            int mcast_idx = compute_mcast_idx(buf);            if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))            {                DEBUG_PRINT((">>> RTL8139: multicast address mismatch\n"));

⌨️ 快捷键说明

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