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

📄 e100.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
        logout("Invalid operation direction(dir=%x)\n", dir);}static void eeprom_reset(E100State *s, int type){    eeprom_t *e = &s->eeprom;    if ( type == EEPROM_RESET_ALL )    {        memset(e, 0x0, sizeof(eeprom_t));        e->val_type = NOP;        logout("EEPROM reset all\n");        return;    }    CSR(CSR_EEPROM, eedo) = 1;    e->start_bit = 0;    e->opcode = 0;    e->address = 0;    e->data = 0;    e->val = 0;    e->val_len = 0;    e->val_type = NOP;    e->cs = 0;    e->sk = 0;    logout("EEPROM select reset\n");}static void do_eeprom_op(E100State *s, eeprom_t *e, int cs, int sk, int di, int dir){    int assert_cs = (cs == 1 && e->cs == 0);    int de_assert_cs = (cs == 0 && e->cs == 1);    int de_assert_sk = (sk == 0 && e->sk == 1);    // Chip select is not be enabled    if ( cs == 0 && e->cs == 0 )    {        logout("Invalid EECS signal\n");        return;    }    // update state    e->cs = cs;    e->sk = sk;    // Do nothing    if ( assert_cs )    {        logout("EECS assert\n");        return;    }    // Complete one command    if ( de_assert_cs )    {        if ( e->val_type == DATA && e->opcode == EEPROM_WRITE )        {            e->data = e->val;            memcpy((void *)((unsigned long)e->contents + e->address),                    &e->data, sizeof(e->data));            logout("EEPROM write complete(data=%#x)\n", e->data);        }        eeprom_trace(0,0,0,NOP,1);        eeprom_reset(s, EEPROM_SELECT_RESET);        logout("EECS de-asserted\n");        return;    }    // Chip is selected and serial clock is change, so the operation is vaild    if ( cs == 1 && de_assert_sk == 1)    {        // Set start bit        if ( e->start_bit == 0 && di == 1 )        {             e->start_bit = di;             e->val_len = 0;             e->val = 0;             e->val_type = OPCODE;             eeprom_trace(0,0,0,OPCODE,1);             logout("EEPROM start bit set\n");             return;        }        // Data in DI is vaild        else if ( e->start_bit == 1 )        {            // If current operation is eeprom read, ignore DI            if ( !(e->val_type == DATA && e->opcode == EEPROM_READ) )            {                e->val = (e->val << 1) | di;                e->val_len ++;            }            switch ( e->val_type )            {                // Get the opcode.                case OPCODE:                    eeprom_trace(CSR(CSR_EEPROM, eedo), di, e->opcode, 0, 0);                    if ( e->val_len  == 2 )                    {                        e->opcode = e->val;                        e->val = 0;                        e->val_len = 0;                        e->val_type = ADDR;                        eeprom_trace(0,0,0,ADDR,1);                        logout("EEPROM get opcode(opcode name=%s,opcode=%#x )\n",                                EEPROM_OPCODE_NAME(e->opcode), e->opcode);                    }                    break;                // Get address                case ADDR:                    eeprom_trace(CSR(CSR_EEPROM, eedo), di, e->opcode, 0, 0);                    if ( e->val_len == e->addr_len )                    {                        e->address = e->val;                        e->val = 0;                        e->val_len = 0;                        e->val_type = DATA;                        // We prepare data eary for later read operation                        if ( e->opcode == EEPROM_READ )                        {                            memcpy(&e->data, (void *)(e->contents + e->address),                                    sizeof(e->data));                            logout("EEPROM prepare data to read(addr=%#x,data=%#x)\n",                                     e->address, e->data);                        }                        // Write dummy 0 to response to driver the address is written complete                        CSR(CSR_EEPROM, eedo) = 0;                        eeprom_trace(0,0,0,DATA,1);                        logout("EEPROM get address(addr=%#x)\n", e->address);                    }                    break;                // Only do data out operation                case DATA:                    if ( e->opcode == EEPROM_READ )                    {                        // Start from the most significant bit                        //uint16_t t = ((e->data & (1<<(sizeof(e->data)*8 - e->val_len - 1))) != 0);                        uint16_t t = !!(e->data & (0x8000U >> e->val_len));                        CSR(CSR_EEPROM, eedo) = t;                        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++ )                            {

⌨️ 快捷键说明

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