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

📄 e100.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                        logout("EEPROM read(reg address=%#x, reg val=%#x, do=%#x, len=%#x)\n",                                 e->address, e->data, t, e->val_len);                        if ( e->val_len > sizeof(e->data)*8 )                        {                            /* Driver may do more write op to de-assert EESK,                             * So we let EEPROM go to idle after a register be                             * read complete                             */                            e->val_type = NOP;                            logout("Read complete\n");                            break;                        }                        e->val_len ++;                    }                    eeprom_trace(CSR(CSR_EEPROM, eedo), di, e->opcode, 0, 0);                    // Do eerpom write when CS de-assert                    break;                default:                    break;            }        }    }    return;}static void scb_eeprom_func(E100State *s, uint32_t val, int dir){    int eecs = ((val & EEPROM_CS) != 0);    int eesk = ((val & EEPROM_SK) != 0);    int eedi = ((val & EEPROM_DI) != 0);    logout("EEPROM: Old(cs=%#x, sk=%#x), New(cs=%#x, sk=%#x, di=%#x)\n",             s->eeprom.cs, s->eeprom.sk, eecs, eesk, eedi);    do_eeprom_op(s, &s->eeprom, eecs, eesk, eedi, dir);    return;}static void e100_ru_command(E100State *s, uint8_t val){    switch ( val )    {        case RU_NOP:            /* Will not be here */            break;        case RU_START:            /* RU start */            SET_RU_STATE(RU_READY);            logout("RU is set to ready\n");            s->ru_offset = CSR_VAL(CSR_POINTER);            logout("RFD offset is at %#x\n", s->ru_offset);            break;        case RU_RESUME:            /* RU Resume */            if ( GET_RU_STATE == RU_SUSPENDED )                SET_RU_STATE(RU_READY);            logout("RU resume to ready\n");            break;        case RU_ADDR_LOAD:            /* Load RU base */            s->ru_base = CSR_VAL(CSR_POINTER);            logout("Load RU base address at %#x\n", s->ru_base);            break;        case RU_DMA_REDIRECT:            logout("RU DMA redirect not implemented\n");            break;        case RU_ABORT:            e100_interrupt(s, INT_RNR);            SET_RU_STATE(RU_IDLE);            logout("RU abort, go to idle\n");            break;        case RU_LOAD_HDS:            logout("RU load header data size(HDS) not implemented\n");        default:            break;    }}// This function will change CU's state, so CU start and// CU resume must set CU's state before itstatic void e100_execute_cb_list(E100State *s, int is_resume){    struct control_block cb = {0};    uint32_t cb_addr;    if ( !is_resume )        s->cu_offset = CSR_VAL(CSR_POINTER);    /* If call from CU resume, cu_offset has been set */    while (1)    {        cb_addr = s->cu_base + s->cu_offset;        cpu_physical_memory_read(cb_addr, (uint8_t *)&cb, sizeof(cb));        switch ( cb.cmd )        {            case CBL_NOP:                /* Do nothing */                break;            case CBL_IASETUP:                cpu_physical_memory_read(cb_addr + 8, &s->macaddr[0], sizeof(s->macaddr));                e100_dump("Setup Individual Address:", &s->macaddr[0], 6);                break;            case CBL_CONFIGURE:                {                    i82557_cfg_t *cfg = &s->config;                    assert(sizeof(s->config) == 22);                    cpu_physical_memory_read(cb_addr + 8, (uint8_t *)cfg, sizeof(s->config));                    logout("Setup card configuration:"                            "\tbyte count:%d\n"                            "\tRx FIFO limit:%d\n"                            "\tTx FIFO limit:%d\n"                            "\tAdaptive interframe spacing:%d\n"                            "\tRx DMA max:%d\n"                            "\tTX DMA max:%d\n"                            "\tDMBC enable:%d\n"                            "\tLate SCB:%d\n"                            "\tTNO:%d\n"                            "\tCI:%d\n"                            "\tDiscard overrun RX:%d\n"                            "\tSave bad frame:%d\n"                            "\tDiscard short RX:%d\n"                            "\tunderrun retry:%d\n"                            "\tMII:%d\n"                            "\tNSAI:%d\n"                            "\tPreamble len:%d\n"                            "\tloopback:%d\n"                            "\tliner pro:%d\n"                            "\tPRI mode:%d\n"                            "\tinterframe spacing:%d\n"                            "\tpromiscuous:%d\n"                            "\tbroadcast dis:%d\n"                            "\tCRS CDT:%d\n"                            "\tstripping:%d\n"                            "\tpadding:%d\n"                            "\tRX crc:%d\n"                            "\tforce fdx:%d\n"                            "\tfdx enable:%d\n"                            "\tmultiple IA:%d\n"                            "\tmulticast all:%d\n",                        cfg->byte_count, cfg->rx_fifo_limit, cfg->tx_fifo_limit,                        cfg->adpt_inf_spacing, cfg->rx_dma_max_bytes, cfg->tx_dma_max_bytes,                        cfg->dmbc_en, cfg->late_scb, cfg->tno_intr, cfg->ci_intr,                        cfg->dis_overrun_rx, cfg->save_bad_frame, cfg->dis_short_rx,                        cfg->underrun_retry, cfg->mii, cfg->nsai, cfg->preamble_len,                        cfg->loopback, cfg->linear_prio, cfg->pri_mode, cfg->interframe_spacing,                        cfg->promiscuous, cfg->broadcast_dis, cfg->crs_cdt, cfg->strip,                        cfg->padding, cfg->rx_crc, cfg->force_fdx, cfg->fdx_en,                        cfg->mul_ia, cfg->mul_all);                }                break;            case CBL_MULTCAST_ADDR_SETUP:                {                    uint16_t mult_list_count = 0;                    uint16_t size = 0;                    cpu_physical_memory_read(cb_addr + 8, (uint8_t *)&mult_list_count, 2);                    mult_list_count = (mult_list_count << 2) >> 2;                    if ( !mult_list_count )                    {                        logout("Multcast disabled(multicast count=0)\n");                        s->is_multcast_enable = 0;                        memset(s->mult_list, 0x0, sizeof(s->mult_list));                        break;                    }                    size = mult_list_count > sizeof(s->mult_list) ?                        sizeof(s->mult_list) : mult_list_count;                    cpu_physical_memory_read(cb_addr + 12, &s->mult_list[0], size);                    e100_dump("Setup Multicast list: ", &s->mult_list[0], size);                    break;                }            case CBL_TRANSMIT:                {                    struct                    {                        struct control_block cb;                        tbd_t tbd;                    } __attribute__ ((packed)) tx;                    struct                    {                        uint32_t addr;                        uint16_t size;                        uint16_t is_el_set;                    } tx_buf = {0};                    uint32_t tbd_array;                    uint16_t tcb_bytes;                    uint8_t sf;                    int len = s->pkt_buf_len;                    assert( len < sizeof(s->pkt_buf));                    cpu_physical_memory_read(cb_addr, (uint8_t *)&tx, sizeof(tx));                    tbd_array = le32_to_cpu(tx.tbd.tx_desc_addr);                    tcb_bytes = le16_to_cpu(tx.tbd.tcb_bytes);                    // Indicate use what mode to transmit(simple or flexible)                    sf = tx.cb.rs3 & 0x1;                    logout("Get a TBD:\n"                            "\tTBD array address:%#x\n"                            "\tTCB byte count:%#x\n"                            "\tEOF:%#x\n"                            "\tTransmit Threshold:%#x\n"                            "\tTBD number:%#x\n"                            "\tUse %s mode to send frame\n",                            tbd_array, tcb_bytes, tx.tbd.eof,                            tx.tbd.tx_threshold, tx.tbd.tbd_num,                            sf ? "Flexible" : "Simple");                    if ( !sf || tbd_array == (uint32_t)-1 )                    {                        /* Simple mode */                        /* For simple mode, TCB bytes should not be zero.                         * But we still check here for safety                         */                        if ( !tcb_bytes || tcb_bytes > sizeof(s->pkt_buf) )                            break;                        cpu_physical_memory_read(cb_addr+16, &s->pkt_buf[0], tcb_bytes);                        len = tcb_bytes;                        logout("simple mode(size=%d)\n", len);                    }                    else                    {                        /* Flexible mode */                        /* For flexible mode, TBD num should not be zero.                         * But we still check here for safety                         */                        if ( !tx.tbd.tbd_num )                            break;                        // I82557 don't support extend TCB                        if ( s->device == i82557C || s->device == i82557B )                        {                            /* Standard TCB mode */                            int i;                            for ( i=0; i<tx.tbd.tbd_num; i++ )                            {                                cpu_physical_memory_read(tbd_array, (uint8_t *)&tx_buf,                                        sizeof(tx_buf));                                tx_buf.is_el_set &= 0x1;                                tx_buf.size &= 0x7fff;                                tbd_array += 8;                                if ( tx_buf.size > sizeof(s->pkt_buf) - len )                                {                                    logout("Warning: Get a too big TBD, ignore it"                                            "(buf addr %#x, size %d, el:%#x)\n",                                            tx_buf.addr, tx_buf.size, tx_buf.is_el_set);                                    continue;                                }                                cpu_physical_memory_read(tx_buf.addr, &s->pkt_buf[len],                                        tx_buf.size);                                logout("TBD (standard mode): buf addr %#x, size %d, el:%#x\n",                                        tx_buf.addr, tx_buf.size, tx_buf.is_el_set);                                len += tx_buf.size;                                if ( tx_buf.is_el_set )                                    break;                            }                        }                        //FIXME: Extend mode is not be tested                        else                        {                            /* Extend TCB mode */                            /* A strandard TCB followed by two TBDs */                            uint32_t tbd_addr = cb_addr+16;                            int i = 0;                            for ( ; i<2 && i<tx.tbd.tbd_num; i++ )                            {                                cpu_physical_memory_read(tbd_array, (uint8_t *)&tx_buf,                                        sizeof(tx_buf));                                tx_buf.is_el_set &= 0x1;                                tbd_addr += 8;                                /* From Intel's spec, size of TBD equal to zero                                 * has same effect with EL bit set                                 */                                if ( tx_buf.size == 0 )                                {                                    tx_buf.is_el_set = 1;                                    break;                                }                                if ( tx_buf.size + len > sizeof(s->pkt_buf) )                                {                                    logout("TX frame is too large, discarding it"                                            "(buf addr=%#x, size=%#x)\n", tx_buf.addr,                                            tx_buf.size);                                    //continue;                                    break;                                }                                logout("TBD (extended mode): buf addr %#08x, size %#04x, el:%#x\n",                                        tx_buf.addr, tx_buf.size, tx_buf.is_el_set);                                cpu_physical_memory_read(tx_buf.addr, &s->pkt_buf[len],                                        tx_buf.size);                                len += tx_buf.size;                                if ( tx_buf.is_el_set )                                    break;                            }                            /* In extend TCB mode, TDB array point to the thrid TBD                             * if it is not NULL(0xffffffff) and EL bit of before                             * two TBDs is not set                             */                            if ( tbd_array != (uint32_t)-1 && !tx_buf.is_el_set )                            {                                tbd_addr = tbd_array;                                /* TBD number includes first two TBDs, so don't                                 * initialize i here                                 */                                for ( ; i<tx.tbd.tbd_num; i++ )                                {                                    cpu_physical_memory_read(tbd_addr, (uint8_t *)&tx_buf,                                            sizeof(tx_buf));                                    tx_buf.is_el_set &= 0x1;                                    tbd_addr += 8;                                    cpu_physical_memory_read(tx_buf.addr, &s->pkt_buf[len],                                            tx_buf.size);                                    logout("TBD (extended mode): buf addr 0x%#08x, size 0x%#04x\n",                                            tx_buf.addr, tx_buf.size);                                    len += tx_buf.size;                                    if ( tx_buf.is_el_set )                                        break;                                }                            }                        }                    }                    s->pkt_buf_len = len;/* Below codes are used for Threshold. But with these logic, network of guest * getting bad performance. So I comment it and leave codes here to hope anyone * fix it */#if 0                    /* If threshold is set, only send packet when threshold                     * bytes are read                     */                    if ( tx.tbd.tx_threshold && s->pkt_buf_len < tx.tbd.tx_threshold * 8 )                    {                        logout("Current data length in FIFO buffer:%d\n", s->pkt_buf_len);                        break;                    }#endif                    if ( s->pkt_buf_len )                    {                        qemu_send_packet(s->vc, s->pkt_buf, s->pkt_buf_len);                        s->statistics.tx_good_frames ++;                        logout("Send out frame successful(size=%d,"                                "already sent %d frames)\n", s->pkt_buf_len,                                s->statistics.tx_good_frames);                        s->pkt_buf_len = 0;                    }                    e100_dump("Dest addr:", (uint8_t *)s->pkt_buf, 6);                    e100_dump("Src addr:", (uint8_t *)(s->pkt_buf+6), 6);                    e100_dump("type:", (uint8_t *)(s->pkt_buf+8), 2);                    break;                }            case CBL_LOAD_MICROCODE:#ifdef DEBUG_E100                {                    /* Don't support load marco code, just dump it */                    #define MICRO_CODE_LEN 256                    uint8_t micro_code[MICRO_CODE_LEN] = {0};                    cpu_physical_memory_read(cb_addr+8, micro_code, MICRO_CODE_LEN);                    e100_dump("Load micro code:", micro_code, MICRO_CODE_LEN);                }#endif

⌨️ 快捷键说明

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