mirror of
https://github.com/qemu/qemu.git
synced 2025-08-08 16:36:26 +00:00
rtl8139: implement 8139cp link status
Add a link status chang callback and change the link status bit in BMSR & MSR accordingly. Tested in Linux/Windows guests. The link status bit of MediaStatus is infered from BasicModeStatus, they are inverse. nc.link_down could not be migrated, this patch updates link_down in rtl8139_post_load() to keep it coincident with real link status. Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: Amos Kong <akong@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
This commit is contained in:
parent
4bb26682f7
commit
9e12c5aff2
24
hw/rtl8139.c
24
hw/rtl8139.c
@ -167,7 +167,7 @@ enum IntrStatusBits {
|
|||||||
PCIErr = 0x8000,
|
PCIErr = 0x8000,
|
||||||
PCSTimeout = 0x4000,
|
PCSTimeout = 0x4000,
|
||||||
RxFIFOOver = 0x40,
|
RxFIFOOver = 0x40,
|
||||||
RxUnderrun = 0x20,
|
RxUnderrun = 0x20, /* Packet Underrun / Link Change */
|
||||||
RxOverflow = 0x10,
|
RxOverflow = 0x10,
|
||||||
TxErr = 0x08,
|
TxErr = 0x08,
|
||||||
TxOK = 0x04,
|
TxOK = 0x04,
|
||||||
@ -3003,7 +3003,8 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MediaStatus:
|
case MediaStatus:
|
||||||
ret = 0xd0;
|
/* The LinkDown bit of MediaStatus is inverse with link status */
|
||||||
|
ret = 0xd0 | (~s->BasicModeStatus & 0x04);
|
||||||
DPRINTF("MediaStatus read 0x%x\n", ret);
|
DPRINTF("MediaStatus read 0x%x\n", ret);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3258,6 +3259,10 @@ static int rtl8139_post_load(void *opaque, int version_id)
|
|||||||
s->cplus_enabled = s->CpCmd != 0;
|
s->cplus_enabled = s->CpCmd != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* nc.link_down can't be migrated, so infer link_down according
|
||||||
|
* to link status bit in BasicModeStatus */
|
||||||
|
s->nic->nc.link_down = (s->BasicModeStatus & 0x04) == 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3449,12 +3454,27 @@ static void pci_rtl8139_uninit(PCIDevice *dev)
|
|||||||
qemu_del_net_client(&s->nic->nc);
|
qemu_del_net_client(&s->nic->nc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rtl8139_set_link_status(NetClientState *nc)
|
||||||
|
{
|
||||||
|
RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque;
|
||||||
|
|
||||||
|
if (nc->link_down) {
|
||||||
|
s->BasicModeStatus &= ~0x04;
|
||||||
|
} else {
|
||||||
|
s->BasicModeStatus |= 0x04;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->IntrStatus |= RxUnderrun;
|
||||||
|
rtl8139_update_irq(s);
|
||||||
|
}
|
||||||
|
|
||||||
static NetClientInfo net_rtl8139_info = {
|
static NetClientInfo net_rtl8139_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = rtl8139_can_receive,
|
.can_receive = rtl8139_can_receive,
|
||||||
.receive = rtl8139_receive,
|
.receive = rtl8139_receive,
|
||||||
.cleanup = rtl8139_cleanup,
|
.cleanup = rtl8139_cleanup,
|
||||||
|
.link_status_changed = rtl8139_set_link_status,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pci_rtl8139_init(PCIDevice *dev)
|
static int pci_rtl8139_init(PCIDevice *dev)
|
||||||
|
Loading…
Reference in New Issue
Block a user