]> git.proxmox.com Git - qemu.git/blobdiff - hw/lan9118.c
target-s390x: Fix debug output
[qemu.git] / hw / lan9118.c
index 78777c73362f8ea8efabc9e72d4a79a3ace47083..6596979d8b09731badcf6803c2d28f2f0e2ec3cc 100644 (file)
@@ -11,9 +11,9 @@
  */
 
 #include "sysbus.h"
-#include "net.h"
+#include "net/net.h"
 #include "devices.h"
-#include "sysemu.h"
+#include "sysemu/sysemu.h"
 #include "ptimer.h"
 /* For crc32 */
 #include <zlib.h>
@@ -235,11 +235,21 @@ typedef struct {
     int32_t rxp_offset;
     int32_t rxp_size;
     int32_t rxp_pad;
+
+    uint32_t write_word_prev_offset;
+    uint32_t write_word_n;
+    uint16_t write_word_l;
+    uint16_t write_word_h;
+    uint32_t read_word_prev_offset;
+    uint32_t read_word_n;
+    uint32_t read_long;
+
+    uint32_t mode_16bit;
 } lan9118_state;
 
 static const VMStateDescription vmstate_lan9118 = {
     .name = "lan9118",
-    .version_id = 1,
+    .version_id = 2,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
         VMSTATE_PTIMER(timer, lan9118_state),
@@ -294,6 +304,14 @@ static const VMStateDescription vmstate_lan9118 = {
         VMSTATE_INT32(rxp_offset, lan9118_state),
         VMSTATE_INT32(rxp_size, lan9118_state),
         VMSTATE_INT32(rxp_pad, lan9118_state),
+        VMSTATE_UINT32_V(write_word_prev_offset, lan9118_state, 2),
+        VMSTATE_UINT32_V(write_word_n, lan9118_state, 2),
+        VMSTATE_UINT16_V(write_word_l, lan9118_state, 2),
+        VMSTATE_UINT16_V(write_word_h, lan9118_state, 2),
+        VMSTATE_UINT32_V(read_word_prev_offset, lan9118_state, 2),
+        VMSTATE_UINT32_V(read_word_n, lan9118_state, 2),
+        VMSTATE_UINT32_V(read_long, lan9118_state, 2),
+        VMSTATE_UINT32_V(mode_16bit, lan9118_state, 2),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -366,7 +384,7 @@ static void phy_update_link(lan9118_state *s)
     phy_update_irq(s);
 }
 
-static void lan9118_set_link(VLANClientState *nc)
+static void lan9118_set_link(NetClientState *nc)
 {
     phy_update_link(DO_UPCAST(NICState, nc, nc)->opaque);
 }
@@ -383,14 +401,14 @@ static void phy_reset(lan9118_state *s)
 
 static void lan9118_reset(DeviceState *d)
 {
-    lan9118_state *s = FROM_SYSBUS(lan9118_state, sysbus_from_qdev(d));
+    lan9118_state *s = FROM_SYSBUS(lan9118_state, SYS_BUS_DEVICE(d));
     s->irq_cfg &= (IRQ_TYPE | IRQ_POL);
     s->int_sts = 0;
     s->int_en = 0;
     s->fifo_int = 0x48000000;
     s->rx_cfg = 0;
     s->tx_cfg = 0;
-    s->hw_cfg = 0x00050000;
+    s->hw_cfg = s->mode_16bit ? 0x00050000 : 0x00050004;
     s->pmt_ctrl &= 0x45;
     s->gpio_cfg = 0;
     s->txp->fifo_used = 0;
@@ -429,13 +447,16 @@ static void lan9118_reset(DeviceState *d)
     s->mac_mii_data = 0;
     s->mac_flow = 0;
 
+    s->read_word_n = 0;
+    s->write_word_n = 0;
+
     phy_reset(s);
 
     s->eeprom_writable = 0;
     lan9118_reload_eeprom(s);
 }
 
-static int lan9118_can_receive(VLANClientState *nc)
+static int lan9118_can_receive(NetClientState *nc)
 {
     return 1;
 }
@@ -479,7 +500,7 @@ static int lan9118_filter(lan9118_state *s, const uint8_t *addr)
         }
     } else {
         /* Hash matching  */
-        hash = (crc32(~0, addr, 6) >> 26);
+        hash = compute_mcast_idx(addr);
         if (hash & 0x20) {
             return (s->mac_hashh >> (hash & 0x1f)) & 1;
         } else {
@@ -488,7 +509,7 @@ static int lan9118_filter(lan9118_state *s, const uint8_t *addr)
     }
 }
 
-static ssize_t lan9118_receive(VLANClientState *nc, const uint8_t *buf,
+static ssize_t lan9118_receive(NetClientState *nc, const uint8_t *buf,
                                size_t size)
 {
     lan9118_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
@@ -979,12 +1000,12 @@ static void lan9118_tick(void *opaque)
     lan9118_update(s);
 }
 
-static void lan9118_writel(void *opaque, target_phys_addr_t offset,
+static void lan9118_writel(void *opaque, hwaddr offset,
                            uint64_t val, unsigned size)
 {
     lan9118_state *s = (lan9118_state *)opaque;
     offset &= 0xff;
-    
+
     //DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
     if (offset >= 0x20 && offset < 0x40) {
         /* TX FIFO */
@@ -1034,7 +1055,7 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset,
             /* SRST */
             lan9118_reset(&s->busdev.qdev);
         } else {
-            s->hw_cfg = val & 0x003f300;
+            s->hw_cfg = (val & 0x003f300) | (s->hw_cfg & 0x4);
         }
         break;
     case CSR_RX_DP_CTRL:
@@ -1113,7 +1134,49 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset,
     lan9118_update(s);
 }
 
-static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset,
+static void lan9118_writew(void *opaque, hwaddr offset,
+                           uint32_t val)
+{
+    lan9118_state *s = (lan9118_state *)opaque;
+    offset &= 0xff;
+
+    if (s->write_word_prev_offset != (offset & ~0x3)) {
+        /* New offset, reset word counter */
+        s->write_word_n = 0;
+        s->write_word_prev_offset = offset & ~0x3;
+    }
+
+    if (offset & 0x2) {
+        s->write_word_h = val;
+    } else {
+        s->write_word_l = val;
+    }
+
+    //DPRINTF("Writew reg 0x%02x = 0x%08x\n", (int)offset, val);
+    s->write_word_n++;
+    if (s->write_word_n == 2) {
+        s->write_word_n = 0;
+        lan9118_writel(s, offset & ~3, s->write_word_l +
+                (s->write_word_h << 16), 4);
+    }
+}
+
+static void lan9118_16bit_mode_write(void *opaque, hwaddr offset,
+                                     uint64_t val, unsigned size)
+{
+    switch (size) {
+    case 2:
+        lan9118_writew(opaque, offset, (uint32_t)val);
+        return;
+    case 4:
+        lan9118_writel(opaque, offset, val, size);
+        return;
+    }
+
+    hw_error("lan9118_write: Bad size 0x%x\n", size);
+}
+
+static uint64_t lan9118_readl(void *opaque, hwaddr offset,
                               unsigned size)
 {
     lan9118_state *s = (lan9118_state *)opaque;
@@ -1149,7 +1212,7 @@ static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset,
     case CSR_TX_CFG:
         return s->tx_cfg;
     case CSR_HW_CFG:
-        return s->hw_cfg | 0x4;
+        return s->hw_cfg;
     case CSR_RX_DP_CTRL:
         return 0;
     case CSR_RX_FIFO_INF:
@@ -1187,13 +1250,61 @@ static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset,
     return 0;
 }
 
+static uint32_t lan9118_readw(void *opaque, hwaddr offset)
+{
+    lan9118_state *s = (lan9118_state *)opaque;
+    uint32_t val;
+
+    if (s->read_word_prev_offset != (offset & ~0x3)) {
+        /* New offset, reset word counter */
+        s->read_word_n = 0;
+        s->read_word_prev_offset = offset & ~0x3;
+    }
+
+    s->read_word_n++;
+    if (s->read_word_n == 1) {
+        s->read_long = lan9118_readl(s, offset & ~3, 4);
+    } else {
+        s->read_word_n = 0;
+    }
+
+    if (offset & 2) {
+        val = s->read_long >> 16;
+    } else {
+        val = s->read_long & 0xFFFF;
+    }
+
+    //DPRINTF("Readw reg 0x%02x, val 0x%x\n", (int)offset, val);
+    return val;
+}
+
+static uint64_t lan9118_16bit_mode_read(void *opaque, hwaddr offset,
+                                        unsigned size)
+{
+    switch (size) {
+    case 2:
+        return lan9118_readw(opaque, offset);
+    case 4:
+        return lan9118_readl(opaque, offset, size);
+    }
+
+    hw_error("lan9118_read: Bad size 0x%x\n", size);
+    return 0;
+}
+
 static const MemoryRegionOps lan9118_mem_ops = {
     .read = lan9118_readl,
     .write = lan9118_writel,
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void lan9118_cleanup(VLANClientState *nc)
+static const MemoryRegionOps lan9118_16bit_mem_ops = {
+    .read = lan9118_16bit_mode_read,
+    .write = lan9118_16bit_mode_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void lan9118_cleanup(NetClientState *nc)
 {
     lan9118_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
@@ -1201,7 +1312,7 @@ static void lan9118_cleanup(VLANClientState *nc)
 }
 
 static NetClientInfo net_lan9118_info = {
-    .type = NET_CLIENT_TYPE_NIC,
+    .type = NET_CLIENT_OPTIONS_KIND_NIC,
     .size = sizeof(NICState),
     .can_receive = lan9118_can_receive,
     .receive = lan9118_receive,
@@ -1214,8 +1325,10 @@ static int lan9118_init1(SysBusDevice *dev)
     lan9118_state *s = FROM_SYSBUS(lan9118_state, dev);
     QEMUBH *bh;
     int i;
+    const MemoryRegionOps *mem_ops =
+            s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops;
 
-    memory_region_init_io(&s->mmio, &lan9118_mem_ops, s, "lan9118-mmio", 0x100);
+    memory_region_init_io(&s->mmio, mem_ops, s, "lan9118-mmio", 0x100);
     sysbus_init_mmio(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
@@ -1240,6 +1353,7 @@ static int lan9118_init1(SysBusDevice *dev)
 
 static Property lan9118_properties[] = {
     DEFINE_NIC_PROPERTIES(lan9118_state, conf),
+    DEFINE_PROP_UINT32("mode_16bit", lan9118_state, mode_16bit, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -1254,14 +1368,14 @@ static void lan9118_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_lan9118;
 }
 
-static TypeInfo lan9118_info = {
+static const TypeInfo lan9118_info = {
     .name          = "lan9118",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(lan9118_state),
     .class_init    = lan9118_class_init,
 };
 
-static void lan9118_register_devices(void)
+static void lan9118_register_types(void)
 {
     type_register_static(&lan9118_info);
 }
@@ -1277,9 +1391,9 @@ void lan9118_init(NICInfo *nd, uint32_t base, qemu_irq irq)
     dev = qdev_create(NULL, "lan9118");
     qdev_set_nic_properties(dev, nd);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(s, 0, base);
     sysbus_connect_irq(s, 0, irq);
 }
 
-device_init(lan9118_register_devices)
+type_init(lan9118_register_types)