📄 eepro100.c.svn-base
字号:
****************************************************************************/#define EEPROM_CS 0x02#define EEPROM_SK 0x01#define EEPROM_DI 0x04#define EEPROM_DO 0x08static uint16_t eepro100_read_eeprom(EEPRO100State * s){ uint16_t val; memcpy(&val, &s->mem[SCBeeprom], sizeof(val)); if (eeprom93xx_read(s->eeprom)) { val |= EEPROM_DO; } else { val &= ~EEPROM_DO; } return val;}static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val){ logout("write val=0x%02x\n", val); /* mask unwriteable bits */ //~ val = SET_MASKED(val, 0x31, eeprom->value); int eecs = ((val & EEPROM_CS) != 0); int eesk = ((val & EEPROM_SK) != 0); int eedi = ((val & EEPROM_DI) != 0); eeprom93xx_write(eeprom, eecs, eesk, eedi);}static void eepro100_write_pointer(EEPRO100State * s, uint32_t val){ s->pointer = le32_to_cpu(val); logout("val=0x%08x\n", val);}/***************************************************************************** * * MDI emulation. * ****************************************************************************/#if defined(DEBUG_EEPRO100)static const char *mdi_op_name[] = { "opcode 0", "write", "read", "opcode 3"};static const char *mdi_reg_name[] = { "Control", "Status", "PHY Identification (Word 1)", "PHY Identification (Word 2)", "Auto-Negotiation Advertisement", "Auto-Negotiation Link Partner Ability", "Auto-Negotiation Expansion"};#endif /* DEBUG_EEPRO100 */static uint32_t eepro100_read_mdi(EEPRO100State * s){ uint32_t val; memcpy(&val, &s->mem[0x10], sizeof(val));#ifdef DEBUG_EEPRO100 uint8_t raiseint = (val & BIT(29)) >> 29; uint8_t opcode = (val & BITS(27, 26)) >> 26; uint8_t phy = (val & BITS(25, 21)) >> 21; uint8_t reg = (val & BITS(20, 16)) >> 16; uint16_t data = (val & BITS(15, 0));#endif /* Emulation takes no time to finish MDI transaction. */ val |= BIT(28); TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n", val, raiseint, mdi_op_name[opcode], phy, mdi_reg_name[reg], data)); return val;}//~ #define BITS(val, upper, lower) (val & ???)static void eepro100_write_mdi(EEPRO100State * s, uint32_t val){ uint8_t raiseint = (val & BIT(29)) >> 29; uint8_t opcode = (val & BITS(27, 26)) >> 26; uint8_t phy = (val & BITS(25, 21)) >> 21; uint8_t reg = (val & BITS(20, 16)) >> 16; uint16_t data = (val & BITS(15, 0)); if (phy != 1) { /* Unsupported PHY address. */ //~ logout("phy must be 1 but is %u\n", phy); data = 0; } else if (opcode != 1 && opcode != 2) { /* Unsupported opcode. */ logout("opcode must be 1 or 2 but is %u\n", opcode); data = 0; } else if (reg > 6) { /* Unsupported register. */ logout("register must be 0...6 but is %u\n", reg); data = 0; } else { TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n", val, raiseint, mdi_op_name[opcode], phy, mdi_reg_name[reg], data)); if (opcode == 1) { /* MDI write */ switch (reg) { case 0: /* Control Register */ if (data & 0x8000) { /* Reset status and control registers to default. */ s->mdimem[0] = eepro100_mdi_default[0]; s->mdimem[1] = eepro100_mdi_default[1]; data = s->mdimem[reg]; } else { /* Restart Auto Configuration = Normal Operation */ data &= ~0x0200; } break; case 1: /* Status Register */ missing("not writable"); data = s->mdimem[reg]; break; case 2: /* PHY Identification Register (Word 1) */ case 3: /* PHY Identification Register (Word 2) */ missing("not implemented"); break; case 4: /* Auto-Negotiation Advertisement Register */ case 5: /* Auto-Negotiation Link Partner Ability Register */ break; case 6: /* Auto-Negotiation Expansion Register */ default: missing("not implemented"); } s->mdimem[reg] = data; } else if (opcode == 2) { /* MDI read */ switch (reg) { case 0: /* Control Register */ if (data & 0x8000) { /* Reset status and control registers to default. */ s->mdimem[0] = eepro100_mdi_default[0]; s->mdimem[1] = eepro100_mdi_default[1]; } break; case 1: /* Status Register */ s->mdimem[reg] |= 0x0020; break; case 2: /* PHY Identification Register (Word 1) */ case 3: /* PHY Identification Register (Word 2) */ case 4: /* Auto-Negotiation Advertisement Register */ break; case 5: /* Auto-Negotiation Link Partner Ability Register */ s->mdimem[reg] = 0x41fe; break; case 6: /* Auto-Negotiation Expansion Register */ s->mdimem[reg] = 0x0001; break; } data = s->mdimem[reg]; } /* Emulation takes no time to finish MDI transaction. * Set MDI bit in SCB status register. */ s->mem[SCBAck] |= 0x08; val |= BIT(28); if (raiseint) { eepro100_mdi_interrupt(s); } } val = (val & 0xffff0000) + data; memcpy(&s->mem[0x10], &val, sizeof(val));}/***************************************************************************** * * Port emulation. * ****************************************************************************/#define PORT_SOFTWARE_RESET 0#define PORT_SELFTEST 1#define PORT_SELECTIVE_RESET 2#define PORT_DUMP 3#define PORT_SELECTION_MASK 3typedef struct { uint32_t st_sign; /* Self Test Signature */ uint32_t st_result; /* Self Test Results */} eepro100_selftest_t;static uint32_t eepro100_read_port(EEPRO100State * s){ return 0;}static void eepro100_write_port(EEPRO100State * s, uint32_t val){ val = le32_to_cpu(val); uint32_t address = (val & ~PORT_SELECTION_MASK); uint8_t selection = (val & PORT_SELECTION_MASK); switch (selection) { case PORT_SOFTWARE_RESET: nic_reset(s); break; case PORT_SELFTEST: logout("selftest address=0x%08x\n", address); eepro100_selftest_t data; cpu_physical_memory_read(address, (uint8_t *) & data, sizeof(data)); data.st_sign = 0xffffffff; data.st_result = 0; cpu_physical_memory_write(address, (uint8_t *) & data, sizeof(data)); break; case PORT_SELECTIVE_RESET: logout("selective reset, selftest address=0x%08x\n", address); nic_selective_reset(s); break; default: logout("val=0x%08x\n", val); missing("unknown port selection"); }}/***************************************************************************** * * General hardware emulation. * ****************************************************************************/static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr){ uint8_t val; if (addr <= sizeof(s->mem) - sizeof(val)) { memcpy(&val, &s->mem[addr], sizeof(val)); } switch (addr) { case SCBStatus: //~ val = eepro100_read_status(s); logout("addr=%s val=0x%02x\n", regname(addr), val); break; case SCBAck: //~ val = eepro100_read_status(s); logout("addr=%s val=0x%02x\n", regname(addr), val); break; case SCBCmd: logout("addr=%s val=0x%02x\n", regname(addr), val); //~ val = eepro100_read_command(s); break; case SCBIntmask: logout("addr=%s val=0x%02x\n", regname(addr), val); break; case SCBPort + 3: logout("addr=%s val=0x%02x\n", regname(addr), val); break; case SCBeeprom: val = eepro100_read_eeprom(s); break; case 0x1b: /* PMDR (power management driver register) */ val = 0; logout("addr=%s val=0x%02x\n", regname(addr), val); break; case 0x1d: /* general status register */ /* 100 Mbps full duplex, valid link */ val = 0x07; logout("addr=General Status val=%02x\n", val); break; default: logout("addr=%s val=0x%02x\n", regname(addr), val); missing("unknown byte read"); } return val;}static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr){ uint16_t val; if (addr <= sizeof(s->mem) - sizeof(val)) { memcpy(&val, &s->mem[addr], sizeof(val)); } logout("addr=%s val=0x%04x\n", regname(addr), val); switch (addr) { case SCBStatus: //~ val = eepro100_read_status(s); break; case SCBeeprom: val = eepro100_read_eeprom(s); break; default: logout("addr=%s val=0x%04x\n", regname(addr), val); missing("unknown word read"); } return val;}static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr){ uint32_t val; if (addr <= sizeof(s->mem) - sizeof(val)) { memcpy(&val, &s->mem[addr], sizeof(val)); } switch (addr) { case SCBStatus: //~ val = eepro100_read_status(s); logout("addr=%s val=0x%08x\n", regname(addr), val); break; case SCBPointer: //~ val = eepro100_read_pointer(s); logout("addr=%s val=0x%08x\n", regname(addr), val); break; case SCBPort: val = eepro100_read_port(s); logout("addr=%s val=0x%08x\n", regname(addr), val); break; case SCBCtrlMDI: val = eepro100_read_mdi(s); break; default: logout("addr=%s val=0x%08x\n", regname(addr), val); missing("unknown longword read"); } return val;}static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val){ if (addr <= sizeof(s->mem) - sizeof(val)) { memcpy(&s->mem[addr], &val, sizeof(val)); } logout("addr=%s val=0x%02x\n", regname(addr), val); switch (addr) { case SCBStatus: //~ eepro100_write_status(s, val); break; case SCBAck: eepro100_acknowledge(s); break; case SCBCmd: eepro100_write_command(s, val); break; case SCBIntmask: if (val & BIT(1)) { eepro100_swi_interrupt(s); } eepro100_interrupt(s, 0); break; case SCBPort + 3: case SCBFlow: case SCBFlow + 1: case SCBFlow + 2: case SCBFlow + 3: logout("addr=%s val=0x%02x\n", regname(addr), val); break; case SCBeeprom: eepro100_write_eeprom(s->eeprom, val); break; default: logout("addr=%s val=0x%02x\n", regname(addr), val); missing("unknown byte write"); }}static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val){ if (addr <= sizeof(s->mem) - sizeof(val)) { memcpy(&s->mem[addr], &val, sizeof(val)); } logout("addr=%s val=0x%04x\n", regname(addr), val); switch (addr) { case SCBStatus: //~ eepro100_write_status(s, val); eepro100_acknowledge(s); break; case SCBCmd: eepro100_write_command(s, val); eepro100_write1(s, SCBIntmask, val >> 8); break; case SCBeeprom: eepro100_write_eeprom(s->eeprom, val); break; default: logout("addr=%s val=0x%04x\n", regname(addr), val); missing("unknown word write"); }}static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val){ if (addr <= sizeof(s->mem) - sizeof(val)) { memcpy(&s->mem[addr], &val, sizeof(val)); } switch (addr) { case SCBPointer: eepro100_write_pointer(s, val); break; case SCBPort: logout("addr=%s val=0x%08x\n", regname(addr), val); eepro100_write_port(s, val); break; case SCBCtrlMDI: eepro100_write_mdi(s, val); break; default: logout("addr=%s val=0x%08x\n", regname(addr), val); missing("unknown longword write"); }}static uint32_t ioport_read1(void *opaque, uint32_t addr){ EEPRO100State *s = opaque; //~ logout("addr=%s\n", regname(addr)); return eepro100_read1(s, addr - s->region[1]);}static uint32_t ioport_read2(void *opaque, uint32_t addr){ EEPRO100State *s = opaque; return eepro100_read2(s, addr - s->region[1]);}static uint32_t ioport_read4(void *opaque, uint32_t addr){ EEPRO100State *s = opaque; return eepro100_read4(s, addr - s->region[1]);}static void ioport_write1(void *opaque, uint32_t addr, uint32_t val){ EEPRO100State *s = opaque; //~ logout("addr=%s val=0x%02x\n", regname(addr), val); eepro100_write1(s, addr - s->region[1], val);}static void ioport_write2(void *opaque, uint32_t addr, uint32_t val){ EEPRO100State *s = opaque; eepro100_write2(s, addr - s->region[1], val);}static void ioport_write4(void *opaque, uint32_t addr, uint32_t val){ EEPRO100State *s = opaque; eepro100_write4(s, addr - s->region[1], val);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -