static uint32_t do_phy_read(Ftgmac100State *s, int reg) { uint32_t val; if (reg > 31) { /* we only advertise one phy */ return 0; } switch (reg) { case 0: /* Basic Control */ val = s->phy_control; break; case 1: /* Basic Status */ val = s->phy_status; break; case 2: /* ID1 */ val = 0x0007; break; case 3: /* ID2 */ val = 0xc0d1; break; case 4: /* Auto-neg advertisement */ val = s->phy_advertise; break; case 5: /* Auto-neg Link Partner Ability */ val = 0x0f71; break; case 6: /* Auto-neg Expansion */ val = 1; break; val = 0x0800; break; case 29: /* Interrupt source. */ val = s->phy_int; s->phy_int = 0; phy_update_irq(s); break; case 30: /* Interrupt mask */ val = s->phy_int_mask; break; case 0x0a: /* 1000BASE-T status */ case 17: case 18: case 27: case 31: qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n", __func__, reg); val = 0; break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n", __func__, reg); val = 0; break; } PHY_DEBUG("PHY read 0x%04x @%d\n", val, reg); return val; }
static void phy_update_link(lan9118_state *s) { /* Autonegotiation status mirrors link status. */ if (qemu_get_queue(s->nic)->link_down) { s->phy_status &= ~0x0024; s->phy_int |= PHY_INT_DOWN; } else { s->phy_status |= 0x0024; s->phy_int |= PHY_INT_ENERGYON; s->phy_int |= PHY_INT_AUTONEG_COMPLETE; } phy_update_irq(s); }
static void phy_update_link(Ftgmac100State *s) { /* Autonegotiation status mirrors link status. */ if (qemu_get_queue(s->nic)->link_down) { PHY_DEBUG("link is down\n"); s->phy_status &= ~0x0024; s->phy_int |= PHY_INT_DOWN; } else { PHY_DEBUG("link is up\n"); s->phy_status |= 0x0024; s->phy_int |= PHY_INT_ENERGYON; s->phy_int |= PHY_INT_AUTONEG_COMPLETE; } phy_update_irq(s); }
static void do_phy_write(Ftgmac100State *s, int reg, uint32_t val) { PHY_DEBUG("PHY: write 0x%04x @%d\n", val, reg); if (reg > 31) { /* we only advertise one phy */ return; } switch (reg) { case 0: /* Basic Control */ if (val & 0x8000) { phy_reset(s); } else { s->phy_control = val & 0x7980; /* Complete autonegotiation immediately. */ if (val & 0x1000) { s->phy_status |= 0x0020; } } break; case 4: /* Auto-neg advertisement */ s->phy_advertise = (val & 0x2d7f) | 0x80; break; case 30: /* Interrupt mask */ s->phy_int_mask = val & 0xff; phy_update_irq(s); break; case 17: case 18: case 27: case 31: qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n", __func__, reg); break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n", __func__, reg); break; } }