return !!(CSR_CXST(s) & 0x8000);
}
-static int pcnet_can_receive(VLANClientState *vc)
+int pcnet_can_receive(VLANClientState *nc)
{
- PCNetState *s = vc->opaque;
+ PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
if (CSR_STOP(s) || CSR_SPND(s))
return 0;
#define MIN_BUF_SIZE 60
-static ssize_t pcnet_receive(VLANClientState *vc, const uint8_t *buf, size_t size_)
+ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_)
{
- PCNetState *s = vc->opaque;
+ PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
int is_padr = 0, is_bcast = 0, is_ladr = 0;
uint8_t buf1[60];
int remaining;
if (BCR_SWSTYLE(s) == 1)
add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
- pcnet_receive(s->vc, s->buffer, s->xmit_pos);
+ pcnet_receive(&s->nic->nc, s->buffer, s->xmit_pos);
s->looptest = 0;
} else
- if (s->vc)
- qemu_send_packet(s->vc, s->buffer, s->xmit_pos);
+ if (s->nic)
+ qemu_send_packet(&s->nic->nc, s->buffer, s->xmit_pos);
s->csr[0] &= ~0x0008; /* clear TDMD */
s->csr[4] |= 0x0004; /* set TXSTRT */
printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
#endif
/* Check APROMWE bit to enable write access */
- if (pcnet_bcr_readw(s,2) & 0x80)
+ if (pcnet_bcr_readw(s,2) & 0x100)
s->prom[addr & 15] = val;
}
static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
{
PCNetState *s = opaque;
- uint32_t val = s->prom[addr &= 15];
+ uint32_t val = s->prom[addr & 15];
#ifdef PCNET_DEBUG
printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
#endif
PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
#ifdef PCNET_DEBUG_IO
- printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
+ printf("pcnet_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%04"FMT_PCIBUS"\n",
+ addr, size);
#endif
register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
void pcnet_common_cleanup(PCNetState *d)
{
- d->vc = NULL;
+ d->nic = NULL;
}
-int pcnet_common_init(DeviceState *dev, PCNetState *s,
- NetCleanup *cleanup)
+int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
{
s->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, s);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
- s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC,
- s->conf.vlan, s->conf.peer,
- dev->info->name, dev->id,
- pcnet_can_receive, pcnet_receive, NULL, NULL,
- cleanup, s);
- qemu_format_nic_info_str(s->vc, s->conf.macaddr.a);
+ s->nic = qemu_new_nic(info, &s->conf, dev->info->name, dev->id, s);
+ qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
return 0;
}
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_map addr=0x%08x 0x%08x\n", addr, size);
+ printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
+ addr, size);
#endif
cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
cpu_physical_memory_read(addr, buf, len);
}
-static void pci_pcnet_cleanup(VLANClientState *vc)
+static void pci_pcnet_cleanup(VLANClientState *nc)
{
- PCNetState *d = vc->opaque;
+ PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque;
pcnet_common_cleanup(d);
}
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, dev);
cpu_unregister_io_memory(d->state.mmio_index);
- vmstate_unregister(&vmstate_pci_pcnet, d);
qemu_del_timer(d->state.poll_timer);
qemu_free_timer(d->state.poll_timer);
- qemu_del_vlan_client(d->state.vc);
+ qemu_del_vlan_client(&d->state.nic->nc);
return 0;
}
+static NetClientInfo net_pci_pcnet_info = {
+ .type = NET_CLIENT_TYPE_NIC,
+ .size = sizeof(NICState),
+ .can_receive = pcnet_can_receive,
+ .receive = pcnet_receive,
+ .cleanup = pci_pcnet_cleanup,
+};
+
static int pci_pcnet_init(PCIDevice *pci_dev)
{
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AMD);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_AMD_LANCE);
- *(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007);
- *(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280);
- pci_conf[0x08] = 0x10;
- pci_conf[0x09] = 0x00;
+ /* TODO: value should be 0 at RST# */
+ pci_set_word(pci_conf + PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_set_word(pci_conf + PCI_STATUS,
+ PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
+ pci_conf[PCI_REVISION_ID] = 0x10;
+ /* TODO: 0 is the default anyway, no need to set it. */
+ pci_conf[PCI_CLASS_PROG] = 0x00;
pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
- *(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001);
- *(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000);
+ /* TODO: not necessary, is set when BAR is registered. */
+ pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_SPACE_IO);
+ pci_set_long(pci_conf + PCI_BASE_ADDRESS_0 + 4,
+ PCI_BASE_ADDRESS_SPACE_MEMORY);
- pci_conf[0x3d] = 1; // interrupt pin 0
- pci_conf[0x3e] = 0x06;
- pci_conf[0x3f] = 0xff;
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, 0x0);
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0);
+
+ /* TODO: value must be 0 at RST# */
+ pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0
+ pci_conf[PCI_MIN_GNT] = 0x06;
+ pci_conf[PCI_MAX_LAT] = 0xff;
/* Handler for memory-mapped I/O */
s->mmio_index =
cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state);
+ /* TODO: use pci_dev, avoid cast below. */
pci_register_bar((PCIDevice *)d, 0, PCNET_IOPORT_SIZE,
PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
s->phys_mem_read = pci_physical_memory_read;
s->phys_mem_write = pci_physical_memory_write;
- vmstate_register(-1, &vmstate_pci_pcnet, d);
-
if (!pci_dev->qdev.hotplugged) {
static int loaded = 0;
if (!loaded) {
}
}
- return pcnet_common_init(&pci_dev->qdev, s, pci_pcnet_cleanup);
+ return pcnet_common_init(&pci_dev->qdev, s, &net_pci_pcnet_info);
}
static void pci_reset(DeviceState *dev)
.qdev.name = "pcnet",
.qdev.size = sizeof(PCIPCNetState),
.qdev.reset = pci_reset,
+ .qdev.vmsd = &vmstate_pci_pcnet,
.init = pci_pcnet_init,
.exit = pci_pcnet_uninit,
.qdev.props = (Property[]) {