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

📄 eepro100.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 4 页
字号:
    PCI_CONFIG_32(PCI_BASE_ADDRESS_1, PCI_ADDRESS_SPACE_IO);#if 0    /* Flash Memory Mapped Base Address */    PCI_CONFIG_32(PCI_BASE_ADDRESS_2, 0xfffe0000 | PCI_ADDRESS_SPACE_MEM);#endif#endif    /* Expansion ROM Base Address (depends on boot disable!!!) */    PCI_CONFIG_32(0x30, 0x00000000);    /* Capability Pointer */    PCI_CONFIG_8(0x34, 0xdc);    /* Interrupt Pin */    PCI_CONFIG_8(0x3d, 1);      // interrupt pin 0    /* Minimum Grant */    PCI_CONFIG_8(0x3e, 0x08);    /* Maximum Latency */    PCI_CONFIG_8(0x3f, 0x18);    /* Power Management Capabilities / Next Item Pointer / Capability ID */    PCI_CONFIG_32(0xdc, 0x7e210001);    switch (device) {    case i82551:        //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209);        PCI_CONFIG_8(PCI_REVISION_ID, 0x0f);        break;    case i82557B:        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);        PCI_CONFIG_8(PCI_REVISION_ID, 0x02);        break;    case i82557C:        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);        PCI_CONFIG_8(PCI_REVISION_ID, 0x03);        break;    case i82558B:        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);        PCI_CONFIG_16(PCI_STATUS, 0x2810);        PCI_CONFIG_8(PCI_REVISION_ID, 0x05);        break;    case i82559C:        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);        PCI_CONFIG_16(PCI_STATUS, 0x2810);        //~ PCI_CONFIG_8(PCI_REVISION_ID, 0x08);        break;    case i82559ER:        //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209);        PCI_CONFIG_16(PCI_STATUS, 0x2810);        PCI_CONFIG_8(PCI_REVISION_ID, 0x09);        break;    //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1029);    //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1030);       /* 82559 InBusiness 10/100 */    default:        logout("Device %X is undefined!\n", device);    }    if (device == i82557C || device == i82558B || device == i82559C) {        logout("Get device id and revision from EEPROM!!!\n");    }}static void nic_selective_reset(EEPRO100State * s){    size_t i;    uint16_t *eeprom_contents = eeprom93xx_data(s->eeprom);    //~ eeprom93xx_reset(s->eeprom);    memcpy(eeprom_contents, s->macaddr, 6);    eeprom_contents[0xa] = 0x4000;    uint16_t sum = 0;    for (i = 0; i < EEPROM_SIZE - 1; i++) {        sum += eeprom_contents[i];    }    eeprom_contents[EEPROM_SIZE - 1] = 0xbaba - sum;    memset(s->mem, 0, sizeof(s->mem));    uint32_t val = BIT(21);    memcpy(&s->mem[SCBCtrlMDI], &val, sizeof(val));    assert(sizeof(s->mdimem) == sizeof(eepro100_mdi_default));    memcpy(&s->mdimem[0], &eepro100_mdi_default[0], sizeof(s->mdimem));}static void nic_reset(void *opaque){    EEPRO100State *s = (EEPRO100State *) opaque;    logout("%p\n", s);    static int first;    if (!first) {        first = 1;    }    nic_selective_reset(s);}#if defined(DEBUG_EEPRO100)static const char *reg[PCI_IO_SIZE / 4] = {    "Command/Status",    "General Pointer",    "Port",    "EEPROM/Flash Control",    "MDI Control",    "Receive DMA Byte Count",    "Flow control register",    "General Status/Control"};static char *regname(uint32_t addr){    static char buf[16];    if (addr < PCI_IO_SIZE) {        const char *r = reg[addr / 4];        if (r != 0) {            sprintf(buf, "%s+%u", r, addr % 4);        } else {            sprintf(buf, "0x%02x", addr);        }    } else {        sprintf(buf, "??? 0x%08x", addr);    }    return buf;}#endif                          /* DEBUG_EEPRO100 */#if 0static uint16_t eepro100_read_status(EEPRO100State * s){    uint16_t val = s->status;    logout("val=0x%04x\n", val);    return val;}static void eepro100_write_status(EEPRO100State * s, uint16_t val){    logout("val=0x%04x\n", val);    s->status = val;}#endif/***************************************************************************** * * Command emulation. * ****************************************************************************/#if 0static uint16_t eepro100_read_command(EEPRO100State * s){    uint16_t val = 0xffff;    //~ logout("val=0x%04x\n", val);    return val;}#endif/* Commands that can be put in a command list entry. */enum commands {    CmdNOp = 0,    CmdIASetup = 1,    CmdConfigure = 2,    CmdMulticastList = 3,    CmdTx = 4,    CmdTDR = 5,                 /* load microcode */    CmdDump = 6,    CmdDiagnose = 7,    /* And some extra flags: */    CmdSuspend = 0x4000,        /* Suspend after completion. */    CmdIntr = 0x2000,           /* Interrupt after completion. */    CmdTxFlex = 0x0008,         /* Use "Flexible mode" for CmdTx command. */};static cu_state_t get_cu_state(EEPRO100State * s){    return ((s->mem[SCBStatus] >> 6) & 0x03);}static void set_cu_state(EEPRO100State * s, cu_state_t state){    s->mem[SCBStatus] = (s->mem[SCBStatus] & 0x3f) + (state << 6);}static ru_state_t get_ru_state(EEPRO100State * s){    return ((s->mem[SCBStatus] >> 2) & 0x0f);}static void set_ru_state(EEPRO100State * s, ru_state_t state){    s->mem[SCBStatus] = (s->mem[SCBStatus] & 0xc3) + (state << 2);}static void dump_statistics(EEPRO100State * s){    /* Dump statistical data. Most data is never changed by the emulation     * and always 0, so we first just copy the whole block and then those     * values which really matter.     * Number of data should check configuration!!!     */    cpu_physical_memory_write(s->statsaddr, (uint8_t *) & s->statistics, 64);    stl_phys(s->statsaddr + 0, s->statistics.tx_good_frames);    stl_phys(s->statsaddr + 36, s->statistics.rx_good_frames);    stl_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);    stl_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors);    //~ stw_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);    //~ stw_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);    //~ missing("CU dump statistical counters");}static void eepro100_cu_command(EEPRO100State * s, uint8_t val){    eepro100_tx_t tx;    uint32_t cb_address;    switch (val) {    case CU_NOP:        /* No operation. */        break;    case CU_START:        if (get_cu_state(s) != cu_idle) {            /* Intel documentation says that CU must be idle for the CU             * start command. Intel driver for Linux also starts the CU             * from suspended state. */            logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle);            //~ assert(!"wrong CU state");        }        set_cu_state(s, cu_active);        s->cu_offset = s->pointer;      next_command:        cb_address = s->cu_base + s->cu_offset;        cpu_physical_memory_read(cb_address, (uint8_t *) & tx, sizeof(tx));        uint16_t status = le16_to_cpu(tx.status);        uint16_t command = le16_to_cpu(tx.command);        logout            ("val=0x%02x (cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",             val, status, command, tx.link);        bool bit_el = ((command & 0x8000) != 0);        bool bit_s = ((command & 0x4000) != 0);        bool bit_i = ((command & 0x2000) != 0);        bool bit_nc = ((command & 0x0010) != 0);        //~ bool bit_sf = ((command & 0x0008) != 0);        uint16_t cmd = command & 0x0007;        s->cu_offset = le32_to_cpu(tx.link);        switch (cmd) {        case CmdNOp:            /* Do nothing. */            break;        case CmdIASetup:            cpu_physical_memory_read(cb_address + 8, &s->macaddr[0], 6);            logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6));            break;        case CmdConfigure:            cpu_physical_memory_read(cb_address + 8, &s->configuration[0],                                     sizeof(s->configuration));            logout("configuration: %s\n", nic_dump(&s->configuration[0], 16));            break;        case CmdMulticastList:            //~ missing("multicast list");            break;        case CmdTx:            (void)0;            uint32_t tbd_array = le32_to_cpu(tx.tx_desc_addr);            uint16_t tcb_bytes = (le16_to_cpu(tx.tcb_bytes) & 0x3fff);            logout                ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",                 tbd_array, tcb_bytes, tx.tbd_count);            assert(!bit_nc);            //~ assert(!bit_sf);            assert(tcb_bytes <= 2600);            /* Next assertion fails for local configuration. */            //~ assert((tcb_bytes > 0) || (tbd_array != 0xffffffff));            if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {                logout                    ("illegal values of TBD array address and TCB byte count!\n");            }            uint8_t buf[MAX_ETH_FRAME_SIZE + 4];            uint16_t size = 0;            uint32_t tbd_address = cb_address + 0x10;            assert(tcb_bytes <= sizeof(buf));            while (size < tcb_bytes) {                uint32_t tx_buffer_address = ldl_phys(tbd_address);                uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);                //~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);                tbd_address += 8;                logout                    ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",                     tx_buffer_address, tx_buffer_size);                cpu_physical_memory_read(tx_buffer_address, &buf[size],                                         tx_buffer_size);                size += tx_buffer_size;            }            if (tbd_array == 0xffffffff) {                /* Simplified mode. Was already handled by code above. */            } else {                /* Flexible mode. */                uint8_t tbd_count = 0;                if (!(s->configuration[6] & BIT(4))) {                    /* Extended TCB. */                    assert(tcb_bytes == 0);                    for (; tbd_count < 2; tbd_count++) {                        uint32_t tx_buffer_address = ldl_phys(tbd_address);                        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);                        uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);                        tbd_address += 8;                        logout                            ("TBD (extended mode): buffer address 0x%08x, size 0x%04x\n",                             tx_buffer_address, tx_buffer_size);                        cpu_physical_memory_read(tx_buffer_address, &buf[size],                                                 tx_buffer_size);                        size += tx_buffer_size;                        if (tx_buffer_el & 1) {                            break;                        }                    }                }                tbd_address = tbd_array;                for (; tbd_count < tx.tbd_count; tbd_count++) {                    uint32_t tx_buffer_address = ldl_phys(tbd_address);                    uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);                    uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);                    tbd_address += 8;                    logout                        ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",                         tx_buffer_address, tx_buffer_size);                    cpu_physical_memory_read(tx_buffer_address, &buf[size],                                             tx_buffer_size);                    size += tx_buffer_size;                    if (tx_buffer_el & 1) {                        break;                    }                }            }            qemu_send_packet(s->vc, buf, size);            s->statistics.tx_good_frames++;            /* Transmit with bad status would raise an CX/TNO interrupt.             * (82557 only). Emulation never has bad status. */            //~ eepro100_cx_interrupt(s);            break;        case CmdTDR:            logout("load microcode\n");            /* Starting with offset 8, the command contains             * 64 dwords microcode which we just ignore here. */            break;        default:            missing("undefined command");        }        /* Write new status (success). */        stw_phys(cb_address, status | 0x8000 | 0x2000);        if (bit_i) {            /* CU completed action. */            eepro100_cx_interrupt(s);        }        if (bit_el) {            /* CU becomes idle. */            set_cu_state(s, cu_idle);            eepro100_cna_interrupt(s);        } else if (bit_s) {            /* CU becomes suspended. */            set_cu_state(s, cu_suspended);            eepro100_cna_interrupt(s);        } else {            /* More entries in list. */            logout("CU list with at least one more entry\n");            goto next_command;        }        logout("CU list empty\n");        /* List is empty. Now CU is idle or suspended. */        break;    case CU_RESUME:        if (get_cu_state(s) != cu_suspended) {            logout("bad CU resume from CU state %u\n", get_cu_state(s));            /* Workaround for bad Linux eepro100 driver which resumes             * from idle state. */            //~ missing("cu resume");            set_cu_state(s, cu_suspended);        }        if (get_cu_state(s) == cu_suspended) {            logout("CU resuming\n");            set_cu_state(s, cu_active);            goto next_command;        }        break;    case CU_STATSADDR:        /* Load dump counters address. */        s->statsaddr = s->pointer;        logout("val=0x%02x (status address)\n", val);        break;    case CU_SHOWSTATS:        /* Dump statistical counters. */        dump_statistics(s);        break;    case CU_CMD_BASE:        /* Load CU base. */        logout("val=0x%02x (CU base address)\n", val);        s->cu_base = s->pointer;        break;    case CU_DUMPSTATS:        /* Dump and reset statistical counters. */        dump_statistics(s);        memset(&s->statistics, 0, sizeof(s->statistics));        break;    case CU_SRESUME:        /* CU static resume. */        missing("CU static resume");        break;    default:        missing("Undefined CU command");    }}static void eepro100_ru_command(EEPRO100State * s, uint8_t val){    switch (val) {    case RU_NOP:        /* No operation. */        break;    case RX_START:        /* RU start. */        if (get_ru_state(s) != ru_idle) {            logout("RU state is %u, should be %u\n", get_ru_state(s), ru_idle);            //~ assert(!"wrong RU state");        }        set_ru_state(s, ru_ready);        s->ru_offset = s->pointer;        logout("val=0x%02x (rx start)\n", val);        break;    case RX_RESUME:        /* Restart RU. */        if (get_ru_state(s) != ru_suspended) {            logout("RU state is %u, should be %u\n", get_ru_state(s),                   ru_suspended);            //~ assert(!"wrong RU state");        }        set_ru_state(s, ru_ready);        break;    case RX_ADDR_LOAD:        /* Load RU base. */        logout("val=0x%02x (RU base address)\n", val);        s->ru_base = s->pointer;        break;    default:        logout("val=0x%02x (undefined RU command)\n", val);        missing("Undefined SU command");    }}static void eepro100_write_command(EEPRO100State * s, uint8_t val){    eepro100_ru_command(s, val & 0x0f);    eepro100_cu_command(s, val & 0xf0);    if ((val) == 0) {        logout("val=0x%02x\n", val);    }    /* Clear command byte after command was accepted. */    s->mem[SCBCmd] = 0;}/***************************************************************************** * * EEPROM emulation. *

⌨️ 快捷键说明

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