]> rtime.felk.cvut.cz Git - mf6xx.git/blobdiff - src/qemu/hw/mf624.c
Update MF624 emulation for QEMU 2.0 and 2.1 infrastructure.
[mf6xx.git] / src / qemu / hw / mf624.c
old mode 100755 (executable)
new mode 100644 (file)
index 621e4bf..3912c97
@@ -1,19 +1,22 @@
-/* 
+/*
  * Humusoft MF624 DAQ card implementation
- * 
+ *
  * Copyright (C) 2011 Rostislav Lisovy (lisovy@gmail.com)
- * 
+ *
  * Licensed under GPLv2 license
  */
-#include "hw.h"
-#include "pci.h"
-#include "../qemu-thread.c"
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h> 
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "qemu/event_notifier.h"
+#include "qemu/osdep.h"
+#include "qemu/thread.h"
+#include "qemu/sockets.h"
+#include "sysemu/char.h"
+
+#define TYPE_MF624_DEV "mf624"
+
+#define MF624_DEV(obj) \
+    OBJECT_CHECK(mf624_state_t, (obj), TYPE_MF624_DEV)
 
 #define PCI_VENDOR_ID_HUMUSOFT         0x186c
 #define PCI_DEVICE_ID_MF624            0x0624
@@ -28,7 +31,7 @@
 #define INTCSR_off                     0x4C
 #define GPIOC_off                      0x54
 
-/* BAR2 */ 
+/* BAR2 */
 #define ADDATA_off                     0x00
 #define ADCTRL_off                     0x00
 #define ADDATA1_off                    0x02
@@ -93,14 +96,19 @@ typedef struct {
 
 typedef struct {
        PCIDevice dev;
+       MemoryRegion mmio_bar0;
+       MemoryRegion mmio_bar2;
+       MemoryRegion mmio_bar4;
+        qemu_irq     irq;
 
+        QemuThread socket_thread;
        int socket_srv;
        int socket_tmp;
        uint32_t port;
        int addr;
 
-        /* The real voltage which is on inputs od A/D convertors.
-       Until new conversion is started, there is still old value in ADC registers*/    
+       /* The real voltage which is on inputs od A/D convertors.
+       Until new conversion is started, there is still old value in ADC registers*/
        unsigned int real_world_AD0; //Value in "ADC internal" format
        unsigned int real_world_AD1;
        unsigned int real_world_AD2;
@@ -114,14 +122,15 @@ typedef struct {
        unsigned int BAR0_mem_table_index;
        unsigned int BAR2_mem_table_index;
        unsigned int BAR4_mem_table_index;
-       
+
        // Internal registers values
        BAR0_t BAR0;
        BAR2_t BAR2;
        BAR4_t BAR4;
 
-       int ADDATA_FIFO[8]; //this array tells us which ADCs are being converted        
-       unsigned int ADDATA_FIFO_POSITION; //ADDATA is FIFO register; 
+
+       int ADDATA_FIFO[8]; //this array tells us which ADCs are being converted
+       unsigned int ADDATA_FIFO_POSITION; //ADDATA is FIFO register;
                                //We need to know, position in this FIFO =
                                //Which value will come next
 } mf624_state_t;
@@ -156,7 +165,7 @@ static void mf624_init_registers(mf624_state_t* s)
 
        //Initialize all registers to default values
        s->BAR0.INTCSR = INTCSR_default_value;
-       s->BAR0.GPIOC = GPIOC_default_value; 
+       s->BAR0.GPIOC = GPIOC_default_value;
        s->BAR2.ADDATA = 0x0;
        s->BAR2.ADCTRL = 0x0;
        s->BAR2.ADDATA1 = 0x0;
@@ -181,6 +190,14 @@ static void mf624_init_registers(mf624_state_t* s)
        s->ADDATA_FIFO_POSITION = 0;
 }
 
+static void
+mf624_reset(void *opaque)
+{
+    mf624_state_t *s = (mf624_state_t *)opaque;
+
+    mf624_init_registers(s);
+}
+
 /* After some widget's value is changed, new value is send via socket to Qemu */
 static void socket_write(mf624_state_t *s, const char* reg, double val)
 {
@@ -214,7 +231,7 @@ static void socket_read(mf624_state_t* dev)
                        perror("read()");
                        return;
                }
-               
+
                if (received_length == 0) {
                        printf("Error while reading from socket. Client disconnected?\n");
                        return;
@@ -252,7 +269,7 @@ static void socket_read(mf624_state_t* dev)
                        }
                        else {
                                printf("reg = %s; val = %f\n", reg, val);
-                       } 
+                       }
                }
        }
 }
@@ -264,7 +281,7 @@ static void* init_socket(void* ptr)
        struct sockaddr_in addr_srv;
        int port;
        int yes = 1;
-       
+
        mf624_state_t* dev = (mf624_state_t*) ptr;
 
        dev->socket_tmp = -1;
@@ -275,7 +292,7 @@ static void* init_socket(void* ptr)
                perror("socket()");
                return NULL;
        }
-       
+
        if (setsockopt(dev->socket_srv, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
                perror("setsockopt()");
                return NULL;
@@ -291,7 +308,7 @@ static void* init_socket(void* ptr)
                perror("bind()");
                return NULL;
        }
-       
+
        if (listen(dev->socket_srv, 5) == -1) {
                perror("listen()");
                return NULL;
@@ -304,13 +321,14 @@ static void* init_socket(void* ptr)
                dev->socket_tmp = accept(dev->socket_srv, (struct sockaddr*) &addr_client, &len_client);
                if (dev->socket_tmp == -1) {
                        perror("accept()");
+                        return NULL;
                }
 
                printf("Client connected\n");
-       
-               socket_read(dev); // should run forever if everything is OK; 
+
+               socket_read(dev); // should run forever if everything is OK;
                                // If error occurs (client disconnected), returns here
-               
+
                close(dev->socket_tmp);
        }
 
@@ -319,7 +337,7 @@ static void* init_socket(void* ptr)
 
 //-----------------------------------------------------------------------------
 
-static void mf624_BAR0_write32(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void mf624_BAR0_write32(void *opaque, hwaddr addr, uint64_t value, unsigned size)
 {
        mf624_state_t *s = opaque;
 
@@ -328,7 +346,7 @@ static void mf624_BAR0_write32(void *opaque, target_phys_addr_t addr, uint32_t v
                        s->BAR0.INTCSR = (value & 0x7FF) | INTCSR_default_value; // Only first 11 bits are writable
                        socket_write(s, "INTCSR", s->BAR0.INTCSR);
                        break;
-                       
+
                case GPIOC_off:
                        //Don't write anywhere else than into these two bits
                        s->BAR0.GPIOC = (value & (GPIOC_LDAC_mask | GPIOC_DACEN_mask)) | GPIOC_default_value;
@@ -346,7 +364,7 @@ static void mf624_BAR0_write32(void *opaque, target_phys_addr_t addr, uint32_t v
                                socket_write(s, "DA6", dacinternal_to_volts(s->BAR2.DA6));
                                socket_write(s, "DA7", dacinternal_to_volts(s->BAR2.DA7));
                        }
-                       
+
                        //Is output forced to GND?
                        if (!(s->BAR0.GPIOC & GPIOC_DACEN_mask))
                        {
@@ -361,15 +379,15 @@ static void mf624_BAR0_write32(void *opaque, target_phys_addr_t addr, uint32_t v
                                socket_write(s, "DA7", dacinternal_to_volts(GND));
                        }
                        break;
-                       
+
                default:
-                       printf("mf624_BAR0_write32(): addr = %d; value = %d\n", addr, value);
+                       printf("mf624_BAR0_write32(): addr = " TARGET_FMT_plx
+                               "; value = 0x%" PRIx64 "\n", addr, value);
                        break;
        }
 }
 
-
-static uint32_t mf624_BAR0_read32(void *opaque, target_phys_addr_t addr)
+static uint64_t mf624_BAR0_read32(void *opaque, hwaddr addr, unsigned size)
 {
        mf624_state_t *s = opaque;
 
@@ -381,13 +399,13 @@ static uint32_t mf624_BAR0_read32(void *opaque, target_phys_addr_t addr)
                        return s->BAR0.GPIOC;
 
                default:
-                       printf("mf624_BAR0_read32(): addr = %d\n", addr);
+                       printf("mf624_BAR0_read32(): addr = "
+                               TARGET_FMT_plx "\n", addr);
                        return 0x0;
        }
 }
 
-
-static uint32_t mf624_BAR2_read16(void *opaque, target_phys_addr_t addr)
+static uint64_t mf624_BAR2_read16(void *opaque, hwaddr addr, unsigned size)
 {
        int i;
        int ADDATA_val = 0xFFFF;
@@ -410,7 +428,7 @@ static uint32_t mf624_BAR2_read16(void *opaque, target_phys_addr_t addr)
                                                s->ADDATA_FIFO_POSITION = i; // Move to next AD to be read
                                        }
                                }
-                               
+
                                switch (s->ADDATA_FIFO_POSITION)
                                {
                                        case 0:
@@ -456,7 +474,7 @@ static uint32_t mf624_BAR2_read16(void *opaque, target_phys_addr_t addr)
                case ADSTART_off:
                        s->BAR0.GPIOC |= GPIOC_EOLC_mask; // Conversion in progress
                        s->ADDATA_FIFO_POSITION = 0;
-                       for (i = 0; i < 5000; i++) 
+                       for (i = 0; i < 5000; i++)
                                ; // Small delay simulating real conversion
 
                        // Check before assignement, if particular ADC is enabled
@@ -468,20 +486,20 @@ static uint32_t mf624_BAR2_read16(void *opaque, target_phys_addr_t addr)
                        s->BAR2.ADDATA5 = (s->BAR2.ADCTRL & (1 << 5)) ? s->real_world_AD5 : s->BAR2.ADDATA5;
                        s->BAR2.ADDATA6 = (s->BAR2.ADCTRL & (1 << 6)) ? s->real_world_AD6 : s->BAR2.ADDATA6;
                        s->BAR2.ADDATA7 = (s->BAR2.ADCTRL & (1 << 7)) ? s->real_world_AD7 : s->BAR2.ADDATA7;
-                       
+
                        //All channels converted
                        s->BAR0.GPIOC &= ~ GPIOC_EOLC_mask;
-                       
+
                        return 0xFFFF; // Semirandom value
 
                default:
-                       printf("mf624_BAR2_read16(): addr = %d\n", addr);
+                       printf("mf624_BAR2_read16(): addr = "
+                               TARGET_FMT_plx "\n", addr);
                        return 0x0;
        }
 }
 
-
-static void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void mf624_BAR2_write16(void *opaque, hwaddr addr, uint64_t value, unsigned size)
 {
        mf624_state_t *s = opaque;
 
@@ -507,7 +525,7 @@ static void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t v
 
                case DA1_off:
                        s->BAR2.DA1 = value;
-                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
+                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) &&
                                (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
                                socket_write(s, "DA1", dacinternal_to_volts(s->BAR2.DA1));
                        }
@@ -515,7 +533,7 @@ static void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t v
 
                case DA2_off:
                        s->BAR2.DA2 = value;
-                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
+                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) &&
                                (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
                                socket_write(s, "DA2", dacinternal_to_volts(s->BAR2.DA2));
                        }
@@ -523,7 +541,7 @@ static void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t v
 
                case DA3_off:
                        s->BAR2.DA3 = value;
-                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
+                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) &&
                                (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
                                socket_write(s, "DA3", dacinternal_to_volts(s->BAR2.DA3));
                        }
@@ -531,7 +549,7 @@ static void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t v
 
                case DA4_off:
                        s->BAR2.DA4 = value;
-                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
+                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) &&
                                (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
                                socket_write(s, "DA4", dacinternal_to_volts(s->BAR2.DA4));
                        }
@@ -539,7 +557,7 @@ static void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t v
 
                case DA5_off:
                        s->BAR2.DA5 = value;
-                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
+                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) &&
                                (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
                                socket_write(s, "DA5", dacinternal_to_volts(s->BAR2.DA5));
                        }
@@ -547,7 +565,7 @@ static void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t v
 
                case DA6_off:
                        s->BAR2.DA6 = value;
-                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
+                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) &&
                                (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
                                socket_write(s, "DA6", dacinternal_to_volts(s->BAR2.DA6));
                        }
@@ -555,172 +573,170 @@ static void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t v
 
                case DA7_off:
                        s->BAR2.DA7 = value;
-                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
+                       if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) &&
                                (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
                                socket_write(s, "DA7", dacinternal_to_volts(s->BAR2.DA7));
                        }
                        break;
 
                default:
-                       printf("mf624_BAR2_write16(): addr = %d; value = %d\n", addr, value);
+                       printf("mf624_BAR2_write16(): addr = " TARGET_FMT_plx
+                               "; value = 0x%" PRIx64 "\n", addr, value);
                        break;
        }
 }
 
-
-static void mf624_BAR4_write32(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void mf624_BAR4_write32(void *opaque, hwaddr addr, uint64_t value, unsigned size)
 {
-       printf("mf624_BAR4_write32(): addr = %d; value = %d\n", addr, value);
+       printf("mf624_BAR4_write32(): addr = " TARGET_FMT_plx
+               "; value = 0x%" PRIx64 "\n", addr, value);
 }
 
-static uint32_t mf624_BAR4_read32(void *opaque, target_phys_addr_t addr)
+static uint64_t mf624_BAR4_read32(void *opaque, hwaddr addr, unsigned size)
 {
-       printf("mf624_BAR4_read32(): addr = %d\n", addr);
+       printf("mf624_BAR4_read32(): addr = " TARGET_FMT_plx "\n", addr);
        return 0x0;
 }
 
+//-----------------------------------------------------------------------------
 
-static CPUReadMemoryFunc * const mf624_BAR0_read[3] = {
-       NULL, /* read8 */
-       NULL, /* read16 */
-       mf624_BAR0_read32,
-};
-static CPUWriteMemoryFunc * const mf624_BAR0_write[3] = {
-       NULL, /* write8 */
-       NULL, /* write16 */
-       mf624_BAR0_write32,
+static const MemoryRegionOps mf624_BAR0_mmio_ops = {
+    .read = mf624_BAR0_read32,
+    .write = mf624_BAR0_write32,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
-static CPUReadMemoryFunc * const mf624_BAR2_read[3] = {
-       NULL, /* read8 */
-       mf624_BAR2_read16,
-       NULL, /* read32 */
-};
-static CPUWriteMemoryFunc * const mf624_BAR2_write[3] = {
-       NULL, /* write8 */
-       mf624_BAR2_write16,
-       NULL, /* write32 */
+static const MemoryRegionOps mf624_BAR2_mmio_ops = {
+    .read = mf624_BAR2_read16,
+    .write = mf624_BAR2_write16,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 2,
+        .max_access_size = 2,
+    },
 };
 
-static CPUReadMemoryFunc * const mf624_BAR4_read[3] = {
-       NULL, /* read8 */
-       NULL, /* read16 */
-       mf624_BAR4_read32,
+static const MemoryRegionOps mf624_BAR4_mmio_ops = {
+    .read = mf624_BAR4_read32,
+    .write = mf624_BAR4_write32,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
-static CPUWriteMemoryFunc * const mf624_BAR4_write[3] = {
-       NULL, /* write8 */
-       NULL, /* write16 */
-       mf624_BAR4_write32,
-};
-//-----------------------------------------------------------------------------
-       
-static void mf624_map(PCIDevice *pci_dev, int region_num,
-                       pcibus_t addr, pcibus_t size, int type)
+
+#define DEFAULT_PORT                   55555
+static int mf624_init(PCIDevice *pci_dev)
 {
-       mf624_state_t *s = DO_UPCAST(mf624_state_t, dev, pci_dev);
+    mf624_state_t *s = MF624_DEV(pci_dev); //alocation of mf624_state_t
+    uint8_t *pci_conf;
 
-       switch (region_num) {
-               case 0:
-                       //printf("reg%d, addr = %x\n", region_num, addr);
-                       cpu_register_physical_memory(addr + 0x0, BAR0_size, s->BAR0_mem_table_index);
-                       break;
-               case 2:
-                       //printf("reg%d, addr = %x\n", region_num, addr);
-                       cpu_register_physical_memory(addr + 0x0, BAR2_size, s->BAR2_mem_table_index);
-                       break;
-               case 4:
-                       //printf("reg%d, addr = %x\n", region_num, addr);
-                       cpu_register_physical_memory(addr + 0x0, BAR4_size, s->BAR4_mem_table_index);
-                       break;
-               default:
-                       printf("FFFUUU\n");
-       }
+    if (s->port == DEFAULT_PORT) {
+        s->port += instance; // Each instance of the same device should have another port number
+        instance ++;
+    }
 
-}
+    //Set all internal registers to default values
+    mf624_init_registers(s);
 
-#define DEFAULT_PORT                   55555
-static int pci_mf624_init(PCIDevice *pci_dev)
-{
-       mf624_state_t *s = DO_UPCAST(mf624_state_t, dev, pci_dev); //alocation of mf624_state_t
-       uint8_t *pci_conf;
-       QemuThread socket_thread;
+    pci_conf = pci_dev->config;
+    pci_conf[PCI_INTERRUPT_PIN] = 0x1; // interrupt pin 0
 
-       printf("MF624 Loaded.\n");
+    s->irq = pci_allocate_irq(&s->dev);
 
-       if (s->port == DEFAULT_PORT) {
-               s->port += instance; // Each instance of the same device should have another port number
-               instance ++;
-       }
+    qemu_register_reset(mf624_reset, s);
 
-       //Set all internal registers to default values
-       mf624_init_registers(s);
+    memory_region_init_io(&s->mmio_bar0, OBJECT(s), &mf624_BAR0_mmio_ops, s, "mf624_bar0", BAR0_size);
+    memory_region_init_io(&s->mmio_bar2, OBJECT(s), &mf624_BAR2_mmio_ops, s, "mf624_bar2", BAR2_size);
+    memory_region_init_io(&s->mmio_bar4, OBJECT(s), &mf624_BAR4_mmio_ops, s, "mf624_bar4", BAR4_size);
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_bar0);
+    pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_bar2);
+    pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_bar4);
 
-       pci_conf = s->dev.config;
-       pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_HUMUSOFT);
-       pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_MF624);
-       pci_config_set_class(pci_conf, PCI_CLASS_SIGNAL_PROCESSING_CONTROLLER);
-       pci_conf[PCI_SUBSYSTEM_VENDOR_ID] = PCI_VENDOR_ID_HUMUSOFT & 0xff;
-       pci_conf[PCI_SUBSYSTEM_VENDOR_ID + 1] = PCI_VENDOR_ID_HUMUSOFT >> 8;
-       pci_conf[PCI_SUBSYSTEM_ID] = PCI_DEVICE_ID_MF624 & 0xff;
-       pci_conf[PCI_SUBSYSTEM_ID + 1] = PCI_DEVICE_ID_MF624 >> 8;
+    //Create thread, which will be blocked on reading from socket (connected to "I/O GUI")
 
-       pci_conf[PCI_INTERRUPT_PIN] = 0x1; // interrupt pin 0
+    qemu_thread_create(&s->socket_thread, "mf624_io_thread",
+                       init_socket, (void*) s, QEMU_THREAD_JOINABLE);
+    return 0;
+}
 
+static void qdev_mf624_reset(DeviceState *dev)
+{
+    mf624_state_t *s = MF624_DEV(dev);
+    mf624_init_registers(s);
+}
 
-       s->BAR0_mem_table_index = cpu_register_io_memory(mf624_BAR0_read,
-                                                mf624_BAR0_write,
-                                                s,
-                                                DEVICE_NATIVE_ENDIAN);
+static void mf624_exit(PCIDevice *pci_dev)
+{
+    mf624_state_t *s = MF624_DEV(pci_dev);
 
-       s->BAR2_mem_table_index = cpu_register_io_memory(mf624_BAR2_read,
-                                                mf624_BAR2_write,
-                                                s,
-                                                DEVICE_NATIVE_ENDIAN);
+    close(s->socket_srv);
 
-       s->BAR4_mem_table_index = cpu_register_io_memory(mf624_BAR4_read,
-                                                mf624_BAR4_write,
-                                                s,
-                                                DEVICE_NATIVE_ENDIAN);
+    qemu_thread_join(&s->socket_thread);
 
-       //printf("BAR0: %d\n", s->BAR0_offset);
-       //printf("BAR2: %d\n", s->BAR2_offset);
-       //printf("BAR4: %d\n", s->BAR4_offset);
+    qemu_unregister_reset(mf624_reset, s);
 
-       pci_register_bar(&s->dev, 0, BAR0_size, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map);
-       pci_register_bar(&s->dev, 2, BAR2_size, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map);
-       pci_register_bar(&s->dev, 4, BAR4_size, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map);
+    memory_region_destroy(&s->mmio_bar0);
+    memory_region_destroy(&s->mmio_bar2);
+    memory_region_destroy(&s->mmio_bar4);
 
-       //Create thread, which will be blocked on reading from socket (connected to "I/O GUI")
-       qemu_thread_create(&socket_thread, init_socket, (void*) s);
-       return 0;
+    qemu_free_irq(s->irq);
 }
 
-static int pci_mf624_exit(PCIDevice *pci_dev)
-{
-       mf624_state_t *s = DO_UPCAST(mf624_state_t, dev, pci_dev);
-       close(s->socket_srv);
+static const VMStateDescription vmstate_mf624 = {
+    .name = "mf624",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
 
-       return 0;
-}
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(dev, mf624_state_t),
+        VMSTATE_UINT32(port, mf624_state_t),
+        VMSTATE_END_OF_LIST()
+    }
 
+};
 
-static PCIDeviceInfo mf624_info = {
-       .qdev.name  = "mf624",
-       .qdev.size  = sizeof(mf624_state_t),
-       .init       = pci_mf624_init,
-       .exit       = pci_mf624_exit,
-       .qdev.props = (Property[]) {
-               DEFINE_PROP_UINT32("port", mf624_state_t, port, DEFAULT_PORT),
-               DEFINE_PROP_END_OF_LIST(),
-       }
+static Property mf624_properties[] = {
+    DEFINE_PROP_UINT32("port", mf624_state_t, port, DEFAULT_PORT),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mf624_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = mf624_init;
+    k->exit = mf624_exit;
+    k->vendor_id = PCI_VENDOR_ID_HUMUSOFT;
+    k->device_id = PCI_DEVICE_ID_MF624;
+    k->revision = 0x00;
+    k->class_id = PCI_CLASS_SIGNAL_PROCESSING_CONTROLLER;
+    k->subsystem_vendor_id = PCI_VENDOR_ID_HUMUSOFT;
+    k->subsystem_id = PCI_DEVICE_ID_MF624;
+    dc->desc = "Humusoft MF624";
+    dc->props = mf624_properties;
+    dc->vmsd = &vmstate_mf624;
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    dc->reset = qdev_mf624_reset;
+}
+
+static const TypeInfo mf624_info = {
+    .name          = TYPE_MF624_DEV,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof( mf624_state_t),
+    .class_init    = mf624_class_init,
 };
 
-static void mf624_register_device(void)
+static void mf624_register_types(void)
 {
-       pci_qdev_register(&mf624_info);
+    type_register_static(&mf624_info);
 }
 
-device_init(mf624_register_device)
+type_init(mf624_register_types)