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

📄 e100.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* Initialize EEDO bit to 1. Due to driver would detect dummy 0 at     * EEDO bit, so initialize it to 1 is safety a way.     */    CSR(CSR_EEPROM, eedo) = 1;    // no pending interrupts    s->scb_stat = 0;    return;}static void e100_software_reset(E100State *s){    memset(s->pci_mem.mem, 0x0, sizeof(s->pci_mem.mem));    // Clear multicast list    memset(s->mult_list, 0x0, sizeof(s->mult_list));    // Set MDI register to default value    memcpy(&s->mdimem[0], &e100_mdi_default[0], sizeof(s->mdimem));    s->is_multcast_enable = 1;    /* Clean FIFO buffer */    memset(s->pkt_buf, 0x0, sizeof(s->pkt_buf));    s->pkt_buf_len = 0;    memset(&s->statistics, 0x0, sizeof(s->statistics));    e100_selective_reset(s);    return;}static void e100_reset(void *opaque){    E100State *s = (E100State *) opaque;    logout("%p\n", s);    e100_software_reset(s);}static void e100_save(QEMUFile * f, void *opaque){    //TODO    return;}static int e100_load(QEMUFile * f, void *opaque, int version_id){    //TODO    return 0;}/* Interrupt functions */static void e100_interrupt(E100State *s, uint16_t int_type){    //TODO: Add another i8255x card supported mask bit    if ( !CSR(CSR_CMD,m) )    {        //Set bit in stat/ack, so driver can no what interrupt happen        CSR_VAL(CSR_STATUS) |= int_type;        s->scb_stat = CSR(CSR_STATUS, stat_ack);        /* SCB maske and SCB Bit M do not disable interrupt. */        logout("Trigger an interrupt(type = %s(%#x), SCB Status = %#x)\n",                INT_NAME(int_type), int_type, CSR_VAL(CSR_STATUS));        pci_set_irq(s->pci_dev, 0, 1);    }}static void e100_interrupt_ack(E100State * s, uint8_t ack){    /* Ignore acknowledege if driver write 0 to ack or     * according interrupt bit is not set     */    if ( !ack || !(s->scb_stat & ack) )    {        logout("Illegal interrupt ack(ack=%#x, SCB Stat/Ack=%#x), ignore it\n",                ack, s->scb_stat);        // Due to we do write operation before e100_execute(), so        // we must restore value of ack field here        CSR(CSR_STATUS, stat_ack) = s->scb_stat;        return;    }    s->scb_stat &= ~ack;    CSR(CSR_STATUS, stat_ack) = s->scb_stat;    logout("Interrupt ack(name=%s,val=%#x)\n", INT_NAME(({uint16_t bit = ack<<8;bit;})),ack);    if ( !s->scb_stat )    {        logout("All interrupts are acknowledeged, de-assert interrupt line\n");        pci_set_irq(s->pci_dev, 0, 0);    }}static void e100_self_test(uint32_t res_addr){    struct    {        uint32_t st_sign;           /* Self Test Signature */        uint32_t st_result;         /* Self Test Results */    } test_res;    test_res.st_sign = (uint32_t)-1;    test_res.st_result = 0; // Our self test always success    cpu_physical_memory_write(res_addr, (uint8_t *)&test_res, sizeof(test_res));    logout("Write self test result to %#x\n", res_addr);}static void scb_port_func(E100State *s, uint32_t val, int dir){#define PORT_SELECTION_MASK 0xfU    uint32_t sel = val & PORT_SELECTION_MASK;    switch ( sel )    {        case PORT_SOFTWARE_RESET:            logout("do PORT_SOFTWARE_RESET!\n");            e100_software_reset(s);            break;        case PORT_SELF_TEST:            e100_self_test(val & ~PORT_SELECTION_MASK);            logout("do PORT_SELF_TEST!\n");            break;        case PORT_SELECTIVE_RESET:            logout("do PORT_SELECTIVE_RESET!\n");            e100_selective_reset(s);            break;        case PORT_DUMP:            logout("do PORT_SOFTWARE_RESET!\n");            break;        case PORT_DUMP_WAKE_UP:            logout("do PORT_SOFTWARE_RESET!\n");            break;        default:            logout("Unkonw SCB port command(selection function = %#x)\n", sel);    }}static void e100_write_mdi(E100State *s, uint32_t val){    uint32_t ie = (val & 0x20000000) >> 29;    uint32_t opcode = (val & 0x0c000000) >> 26;    uint32_t phyaddr = (val & 0x03e00000) >> 21;    uint32_t regaddr = (val & 0x001f0000) >> 16;    uint32_t data = val & 0x0000ffff;    logout("Write MDI:\n"           "\topcode:%#x\n"           "\tphy address:%#x\n"           "\treg address:%#x\n"           "\tie:%#x\n"           "\tdata:%#x\n",           opcode, phyaddr, regaddr, ie, data);    /* We use default value --- PHY1     * If driver operate on other PHYs, do nothing and     * deceive it that the operation is finished     */    if ( phyaddr != 1 )    {        logout("Unsupport PHY address(phy = %#x)\n", phyaddr);        goto done;    }    // 1: MDI write    // 2: MDI read    if ( opcode != MDI_WRITE && opcode != MDI_READ )    {        logout("Invalid Opcode(opcode = %#x)\n", opcode);        return;    }    // Current only support MDI generic registers.    if ( regaddr > 6 )    {        logout("Invalid phy register index( phy register addr = %#x)\n", regaddr);    }    if ( opcode == MDI_WRITE )    {        // MDI write        switch ( regaddr )        {            case 0:    // Control Register                if ( data & 0x8000 ) // Reset                {                    /* Reset status and control registers to default. */                    s->mdimem[0] = e100_mdi_default[0];                    s->mdimem[1] = e100_mdi_default[1];                    data = s->mdimem[regaddr];                }                else                {                    /* Restart Auto Configuration = Normal Operation */                    data &= ~0x0200;                }                break;            case 1:    // Status Register                logout("Invalid write on readonly register(opcode = %#x)\n", opcode);                data = s->mdimem[regaddr];                break;            case 2:            case 3:            case 4:            case 5:            case 6:                break;        }        s->mdimem[regaddr] = data;        logout("MDI WRITE: reg = %#x, data = %#x\n", regaddr, data);    }    else if ( opcode == MDI_READ )    {        // MDI read        switch ( regaddr )        {            case 0: // Control Register                if ( data & 0x8000 ) // Reset                {                    /* Reset status and control registers to default. */                    s->mdimem[0] = e100_mdi_default[0];                    s->mdimem[1] = e100_mdi_default[1];                }                break;            case 1: // Status Register                // Auto Negotiation complete, set sticky bit to 1                s->mdimem[regaddr] |= 0x0026;                break;            case 2: // PHY Identification Register (Word 1)            case 3: // PHY Identification Register (Word 2)                break;            case 5: // Auto-Negotiation Link Partner Ability Register                s->mdimem[regaddr] = 0x41fe;                break;            case 6: // Auto-Negotiation Expansion Register                s->mdimem[regaddr] = 0x0001;                break;        }        data = s->mdimem[regaddr];        logout("MDI READ: reg = %#x, data = %#x\n", regaddr, data);    }    /* Emulation takes no time to finish MDI transaction.     * Set MDI bit in SCB status register. */done:    val |= BIT(28);    val = (val & 0xffff0000) + data;    CSR_WRITE(SCB_MDI, val, uint32_t);    if ( ie )        e100_interrupt(s, (uint16_t)INT_MDI);}static void scb_mdi_func(E100State *s, uint32_t val, int dir){    if ( dir == OP_READ )        // Do nothing, just tell driver we are ready        CSR_VAL(CSR_MDI) |= BIT(28);    else if ( dir == OP_WRITE )        e100_write_mdi(s, val);    else        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;

⌨️ 快捷键说明

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