]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/pcnet.c
hw: honor low bit in mipssim machine
[mirror_qemu.git] / hw / pcnet.c
index 3fc8cf7b1b8f0d0927657cb3e92ef1e6d63e609a..5e63eb5c06c79c9226e35b678e0351d68203def0 100644 (file)
@@ -1028,9 +1028,9 @@ static int pcnet_tdte_poll(PCNetState *s)
     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;
 
@@ -1039,9 +1039,9 @@ static int pcnet_can_receive(VLANClientState *vc)
 
 #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;
@@ -1268,11 +1268,11 @@ static void pcnet_transmit(PCNetState *s)
                 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 */
@@ -1601,14 +1601,14 @@ static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
     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
@@ -1732,7 +1732,8 @@ static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
     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);
@@ -1887,21 +1888,16 @@ static const VMStateDescription vmstate_pci_pcnet = {
 
 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;
 }
 
@@ -1925,7 +1921,8 @@ static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
     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);
@@ -1943,9 +1940,9 @@ static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
     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);
 }
@@ -1955,13 +1952,20 @@ static int pci_pcnet_uninit(PCIDevice *dev)
     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);
@@ -1977,24 +1981,35 @@ static int pci_pcnet_init(PCIDevice *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);
 
@@ -2005,8 +2020,6 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
     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) {
@@ -2015,7 +2028,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
         }
     }
 
-    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)
@@ -2029,6 +2042,7 @@ static PCIDeviceInfo pcnet_info = {
     .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[]) {