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

📄 e100.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                break;            case CBL_DUMP:                logout("Control block dump\n");                break;            case CBL_DIAGNOSE:                logout("Control block diagnose\n");                break;            default:                logout("Unknown Control block command(val=%#x)\n", cb.cmd);                break;        }        /* Now, we finished executing a command, update status of CB.         * We always success         */        cb.c = 1;        cb.ok = 1;        // Only update C bit and OK bit field in TCB        cpu_physical_memory_write(cb_addr, (uint8_t *)&cb, 2);        logout("Finished a command from CB list:\n"                "\tok:%d\n"                "\tc:%d\n"                "\tcommand name:%s(cmd=%#x)\n"                "\ti:%d\n"                "\ts:%d\n"                "\tel:%d\n"                "\tlink address:%#x\n",                cb.ok, cb.c, CB_CMD_NAME(cb.cmd), cb.cmd,                cb.i, cb.s, cb.el, cb.link_addr);        if ( cb.i )            e100_interrupt(s, (uint16_t)INT_CX_TNO);        // Suspend CU        if ( cb.s )        {            logout("CU go to suspend\n");            SET_CU_STATE(CU_SUSPENDED);            s->cu_next = cb.link_addr; // Save it for go on executing when resume            // Trigger CNA interrupt only when CNA mode is configured            if ( !(s->config.ci_intr) && cb.i )                e100_interrupt(s, (uint16_t)INT_CNA);            return;        }        // This is last command in CB list, CU go back to IDLE        if ( cb.el )        {            logout("Command block list is empty, CU go to idle\n");            SET_CU_STATE(CU_IDLE);            /* Either in CNA mode or CI mode, interrupt need be triggered             * when CU go to idle.             */            if ( cb.i )                e100_interrupt(s, (uint16_t)INT_CNA);            return;        }        s->cu_offset = le32_to_cpu(cb.link_addr); // get next CB offset    }}static void dump_statistics(E100State * s, uint32_t complete_word){    /* Dump statistical data. Most data is never changed by the emulation     * and always 0.     */    s->statistics.complete_word = complete_word;    cpu_physical_memory_write(s->statsaddr, (uint8_t *)&s->statistics, sizeof(s->statistics));}static void e100_cu_command(E100State *s, uint8_t val){    switch ( val )    {        case CU_NOP:            /* Will not be here */            break;        case CU_START:            /* This strictly follow Intel's spec */            if ( GET_CU_STATE != CU_IDLE && GET_CU_STATE != CU_SUSPENDED )            {                logout("Illegal CU start command. Device is not idle or suspend\n");                return;            }            SET_CU_STATE(CU_LPQ_ACTIVE);            logout("CU start\n");            e100_execute_cb_list(s, 0);            break;        case CU_RESUME:            {                uint32_t previous_cb = s->cu_base + s->cu_offset;                struct control_block cb;                /* Resume from suspend */                /* FIXME:From Intel's spec, CU resume from idle is                 * forbidden, but e100 drive in linux                 * indeed do this.                 */                if ( GET_CU_STATE == CU_IDLE )                {                    logout("Illegal resume form IDLE\n");                }                cpu_physical_memory_read(previous_cb, (uint8_t *)&cb,                                        sizeof(cb));                //FIXME: Need any speical handle when CU is active ?                /* Driver must clean S bit in previous CB when                 * it issue CU resume command                 */                if ( cb.s )                {                    logout("CU still in suspend\n");                    break;                }                SET_CU_STATE(CU_LPQ_ACTIVE);                if ( cb.el )                {                    logout("CB list is empty, CU just go to active\n");                    break;                }                // Continue next command                s->cu_offset = s->cu_next;                e100_execute_cb_list(s, 1);                logout("CU resume\n");            }            break;        case CU_STATSADDR:            /* Load dump counters address */            s->statsaddr = CSR_VAL(CSR_POINTER);            logout("Load Stats address at %#x\n", s->statsaddr);            break;        case CU_SHOWSTATS:            /* Dump statistical counters */            dump_statistics(s, 0xa005);            logout("Execute dump statistics\n");            break;        case CU_CMD_BASE:            /* Load CU base */            s->cu_base = CSR_VAL(CSR_POINTER);            logout("Load CU base at %x\n", s->cu_base);            break;        case CU_DUMPSTATS:            /* Dump statistical counters and reset counters. */            dump_statistics(s, 0xa007);            memset(&s->statistics, 0x0, sizeof(s->statistics));            logout("Execute dump and reset statistics\n");            break;        case CU_S_RESUME:            /* CU static resume */            logout("CU static resume is not implemented\n");            break;        default:            logout("Unknown CU command(val=%#x)\n", val);            break;    }}static void scb_cmd_func(E100State *s, uint16_t val, int dir){    /* ignore NOP operation */    if ( val & 0x0f )    {        e100_ru_command(s, val & 0x0f);        CSR(CSR_CMD, ru_cmd) = 0;    }    else if ( val & 0xf0 )    {        e100_cu_command(s, val & 0xf0);        CSR(CSR_CMD, cu_cmd) = 0;    }}enum{    WRITEB,    WRITEW,    WRITEL,    OP_IS_READ,} WRITE_BYTES;/* Driver may issue a command by writting one 32bit-entry, * two 16bit-entries or four 8bit-entries. In late two case, we * must wait until driver finish writting to the highest byte. The parameter * 'bytes' means write action of driver(writeb, wirtew, wirtel) */static void e100_execute(E100State *s, uint32_t addr_offset,        uint32_t val, int dir, int bytes){    switch ( addr_offset )    {        case SCB_STATUS:            if ( bytes == WRITEB )                break;        case SCB_ACK:            if ( dir == OP_WRITE )            {                uint8_t _val = 0;                if ( bytes == WRITEB )                    _val = (uint8_t)val;                else if ( bytes == WRITEW )                    _val = ((uint16_t)val) >> 8;                else if ( bytes == WRITEL)                {                    // This should not be happen                    _val = ((uint16_t)val) >> 8;                    logout("WARNNING: Drvier write 4 bytes to CSR register at offset %d,"                           "emulator may do things wrong!!!\n", addr_offset);                }                e100_interrupt_ack(s, _val);            }            break;        case SCB_CMD:            if ( dir == OP_WRITE )                scb_cmd_func(s, val, dir);/* I don't know whether there is any driver writes command words and * interrupt mask at same time by two bytes. This is not a regular operation. * but if we meet the case, below codes could copy with it. As far * as I know. windows's and linux's driver don't do this thing. */#if 0            if ( bytes == WRITEW && (val&0xff00) != 0 )                ;            else                break;#endif            break;        case SCB_INTERRUPT_MASK:            if ( dir == OP_WRITE )            {                uint8_t _val = 0;                if ( bytes == WRITEB )                    _val = (uint8_t)val;                else if ( bytes == WRITEW )                    _val = (val & 0xff00) >> 8;                else                    logout("WARNNING: Drvier write 4 bytes to CSR register at offset %d,"                           "emulator may do things wrong!!!\n", addr_offset);                // Driver generates a software interrupt                if ( _val & BIT(1) )                    e100_interrupt(s, INT_SWI);            }            break;        case SCB_PORT ... SCB_PORT + 3:            if ( dir == OP_WRITE )            {                // Waitting for driver write to the highest byte                if ( (bytes == WRITEB && addr_offset != SCB_PORT + 3) ||                     (bytes == WRITEW && addr_offset != SCB_PORT + 2) )                    break;                scb_port_func(s, CSR_VAL(CSR_PORT), dir);            }            break;        case SCB_MDI ... SCB_MDI + 3:            if ( dir == OP_WRITE )            {                // Waitting for driver write to the highest byte                if ( (bytes == WRITEB && addr_offset != SCB_MDI + 3) ||                     (bytes == WRITEW && addr_offset != SCB_MDI + 2) )                    break;            }            scb_mdi_func(s, CSR_VAL(CSR_MDI), dir);            break;        case SCB_EEPROM:            if ( dir == OP_WRITE )                scb_eeprom_func(s, val, dir);            // Nothing need do when driver read EEPROM registers of CSR            break;        case SCB_POINTER:            break;        default:            logout("Driver operate on CSR reg(offset=%#x,dir=%s,val=%#x)\n",                    addr_offset, dir==OP_WRITE?"write":"read", val);    }}/* MMIO access functions */static uint8_t e100_read1(E100State * s, uint32_t addr_offset){    uint8_t val = -1;    if ( addr_offset + sizeof(val) >= sizeof(s->pci_mem.mem) )    {        logout("Invaild read, beyond memory boundary(addr:%#x)\n", addr_offset                + s->region_base_addr[CSR_MEMORY_BASE]);        return val;    }    e100_execute(s, addr_offset, val, OP_READ, OP_IS_READ);    val = CSR_READ(addr_offset, uint8_t);    logout("READ1: Register name = %s, addr_offset = %#x, val=%#x\n", SCBNAME(addr_offset), addr_offset, val);    return val;}static uint16_t e100_read2(E100State * s, uint32_t addr_offset){    uint16_t val = -1;    if ( addr_offset + sizeof(val) >= sizeof(s->pci_mem.mem) )    {        logout("Invaild read, beyond memory boundary(addr:%#x)\n", addr_offset                 + s->region_base_addr[CSR_MEMORY_BASE]);        return val;    }    e100_execute(s, addr_offset, val, OP_READ, OP_IS_READ);    val = CSR_READ(addr_offset, uint16_t);    logout("READ2: Register name = %s, addr_offset = %#x, val=%#x\n", SCBNAME(addr_offset), addr_offset, val);    return val;}static uint32_t e100_read4(E100State * s, uint32_t addr_offset){    uint32_t val = -1;    if ( addr_offset + sizeof(val) >= sizeof(s->pci_mem.mem) )    {        logout("Invaild read, beyond memory boundary(addr:%#x)\n", addr_offset                 + s->region_base_addr[CSR_MEMORY_BASE]);        return val;    }    e100_execute(s, addr_offset, val, OP_READ, OP_IS_READ);    val = CSR_READ(addr_offset, uint32_t);    logout("READ4: Register name = %s, addr_offset = %#x, val=%#x\n", SCBNAME(addr_offset), addr_offset, val);    return val;}static uint32_t pci_mmio_readb(void *opaque, target_phys_addr_t addr){    E100State *s = opaque;    addr -= s->region_base_addr[CSR_MEMORY_BASE];    return e100_read1(s, addr);}static uint32_t pci_mmio_readw(void *opaque, target_phys_addr_t addr){    E100State *s = opaque;    addr -= s->region_base_addr[CSR_MEMORY_BASE];    return e100_read2(s, addr);}static uint32_t pci_mmio_readl(void *opaque, target_phys_addr_t addr){    E100State *s = opaque;    addr -= s->region_base_addr[CSR_MEMORY_BASE];    return e100_read4(s, addr);}static CPUReadMemoryFunc *pci_mmio_read[] = {    pci_mmio_readb,    pci_mmio_readw,    pci_mmio_readl};static void e100_write1(E100State * s, uint32_t addr_offset, uint8_t val){    if ( addr_offset + sizeof(val) >= sizeof(s->pci_mem.mem) )    {        logout("Invaild write, beyond memory boundary(addr = %#x, val = %#x\n", addr_offset                + s->region_base_addr[CSR_MEMORY_BASE], val);        return;    }    // SCB stauts is read-only word, can not be directly write    if ( addr_offset == SCB_STATUS )    {        return;    }    // EEDO bit of eeprom register is read-only, can not be written;    else if ( addr_offset == SCB_EEPROM )    {        int eedo = BIT(3) & CSR_VAL(CSR_EEPROM);        CSR_WRITE(addr_offset, val, uint8_t);        CSR(CSR_EEPROM, eedo) = !!(eedo & EEPROM_DO);        logout("WRITE1: Register name = %s, addr_offset = %#x, val = %#x\n", SCBNAME(addr_offset),addr_offset, (uint8_t)CSR_VAL(CSR_EEPROM));

⌨️ 快捷键说明

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