*
* Licensed under GPLv2 license
*/
-#include "hw.h"
-#include "pci.h"
-#include "qemu-thread.h"
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-/* #define QEMU_VER_ABOVE_015 */
+#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
typedef struct {
PCIDevice dev;
- #ifdef QEMU_VER_ABOVE_015
MemoryRegion mmio_bar0;
MemoryRegion mmio_bar2;
MemoryRegion mmio_bar4;
- #endif /*QEMU_VER_ABOVE_015*/
+ qemu_irq irq;
+ QemuThread socket_thread;
int socket_srv;
int socket_tmp;
uint32_t port;
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)
{
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");
//-----------------------------------------------------------------------------
-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;
break;
default:
- printf("mf624_BAR0_write32(): addr = " TARGET_FMT_plx "; 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;
return s->BAR0.GPIOC;
default:
- printf("mf624_BAR0_read32(): addr = " TARGET_FMT_plx "\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;
return 0xFFFF; // Semirandom value
default:
- printf("mf624_BAR2_read16(): addr = " TARGET_FMT_plx "\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;
break;
default:
- printf("mf624_BAR2_write16(): addr = " TARGET_FMT_plx "; 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 = " TARGET_FMT_plx "; 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 = " TARGET_FMT_plx "\n", addr);
return 0x0;
//-----------------------------------------------------------------------------
-#ifdef QEMU_VER_ABOVE_015
-
static const MemoryRegionOps mf624_BAR0_mmio_ops = {
- .old_mmio = {
- .read = {
- NULL,
- NULL,
- mf624_BAR0_read32,
- },
- .write = {
- NULL,
- NULL,
- mf624_BAR0_write32,
- },
- },
+ .read = mf624_BAR0_read32,
+ .write = mf624_BAR0_write32,
.endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
};
static const MemoryRegionOps mf624_BAR2_mmio_ops = {
- .old_mmio = {
- .read = {
- NULL,
- mf624_BAR2_read16,
- NULL,
- },
- .write = {
- NULL,
- mf624_BAR2_write16,
- NULL,
- },
- },
+ .read = mf624_BAR2_read16,
+ .write = mf624_BAR2_write16,
.endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 2,
+ .max_access_size = 2,
+ },
};
static const MemoryRegionOps mf624_BAR4_mmio_ops = {
- .old_mmio = {
- .read = {
- NULL,
- NULL,
- mf624_BAR4_read32,
- },
- .write = {
- NULL,
- NULL,
- mf624_BAR4_write32,
- },
- },
+ .read = mf624_BAR4_read32,
+ .write = mf624_BAR4_write32,
.endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
};
-#else /*QEMU_VER_ABOVE_015*/
+#define DEFAULT_PORT 55555
+static int mf624_init(PCIDevice *pci_dev)
+{
+ mf624_state_t *s = MF624_DEV(pci_dev); //alocation of mf624_state_t
+ uint8_t *pci_conf;
-static CPUReadMemoryFunc * const mf624_BAR0_read[3] = {
- NULL, /* read8 */
- NULL, /* read16 */
- mf624_BAR0_read32,
-};
+ if (s->port == DEFAULT_PORT) {
+ s->port += instance; // Each instance of the same device should have another port number
+ instance ++;
+ }
-static CPUWriteMemoryFunc * const mf624_BAR0_write[3] = {
- NULL, /* write8 */
- NULL, /* write16 */
- mf624_BAR0_write32,
-};
+ //Set all internal registers to default values
+ mf624_init_registers(s);
-static CPUReadMemoryFunc * const mf624_BAR2_read[3] = {
- NULL, /* read8 */
- mf624_BAR2_read16,
- NULL, /* read32 */
-};
+ pci_conf = pci_dev->config;
+ pci_conf[PCI_INTERRUPT_PIN] = 0x1; // interrupt pin 0
-static CPUWriteMemoryFunc * const mf624_BAR2_write[3] = {
- NULL, /* write8 */
- mf624_BAR2_write16,
- NULL, /* write32 */
-};
+ s->irq = pci_allocate_irq(&s->dev);
-static CPUReadMemoryFunc * const mf624_BAR4_read[3] = {
- NULL, /* read8 */
- NULL, /* read16 */
- mf624_BAR4_read32,
-};
+ qemu_register_reset(mf624_reset, s);
-static CPUWriteMemoryFunc * const mf624_BAR4_write[3] = {
- NULL, /* write8 */
- NULL, /* write16 */
- mf624_BAR4_write32,
-};
+ 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);
+ //Create thread, which will be blocked on reading from socket (connected to "I/O GUI")
-//-----------------------------------------------------------------------------
+ qemu_thread_create(&s->socket_thread, "mf624_io_thread",
+ init_socket, (void*) s, QEMU_THREAD_JOINABLE);
+ return 0;
+}
-static void mf624_map(PCIDevice *pci_dev, int region_num,
- pcibus_t addr, pcibus_t size, int type)
+static void qdev_mf624_reset(DeviceState *dev)
{
- mf624_state_t *s = DO_UPCAST(mf624_state_t, dev, pci_dev);
-
- 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");
- }
-
+ mf624_state_t *s = MF624_DEV(dev);
+ mf624_init_registers(s);
}
-#endif /*QEMU_VER_ABOVE_015*/
-
-#define DEFAULT_PORT 55555
-static int pci_mf624_init(PCIDevice *pci_dev)
+static void mf624_exit(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;
+ mf624_state_t *s = MF624_DEV(pci_dev);
- printf("MF624 Loaded.\n");
+ close(s->socket_srv);
- if (s->port == DEFAULT_PORT) {
- s->port += instance; // Each instance of the same device should have another port number
- instance ++;
- }
+ qemu_thread_join(&s->socket_thread);
- //Set all internal registers to default values
- mf624_init_registers(s);
-
- 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;
-
- pci_conf[PCI_INTERRUPT_PIN] = 0x1; // interrupt pin 0
-
- #ifdef QEMU_VER_ABOVE_015
- memory_region_init_io(&s->mmio_bar0, &mf624_BAR0_mmio_ops, s, "mf624_bar0", BAR0_size);
- memory_region_init_io(&s->mmio_bar2, &mf624_BAR2_mmio_ops, s, "mf624_bar2", BAR2_size);
- memory_region_init_io(&s->mmio_bar4, &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);
- #else /*QEMU_VER_ABOVE_015*/
- s->BAR0_mem_table_index = cpu_register_io_memory(mf624_BAR0_read,
- mf624_BAR0_write,
- s,
- DEVICE_NATIVE_ENDIAN);
-
- s->BAR2_mem_table_index = cpu_register_io_memory(mf624_BAR2_read,
- mf624_BAR2_write,
- s,
- DEVICE_NATIVE_ENDIAN);
-
- s->BAR4_mem_table_index = cpu_register_io_memory(mf624_BAR4_read,
- mf624_BAR4_write,
- s,
- DEVICE_NATIVE_ENDIAN);
-
- 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);
- #endif /*QEMU_VER_ABOVE_015*/
-
- //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_unregister_reset(mf624_reset, s);
-static int pci_mf624_exit(PCIDevice *pci_dev)
-{
- mf624_state_t *s = DO_UPCAST(mf624_state_t, dev, pci_dev);
- close(s->socket_srv);
+ memory_region_destroy(&s->mmio_bar0);
+ memory_region_destroy(&s->mmio_bar2);
+ memory_region_destroy(&s->mmio_bar4);
- return 0;
+ qemu_free_irq(s->irq);
}
+static const VMStateDescription vmstate_mf624 = {
+ .name = "mf624",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
-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(),
- }
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE(dev, mf624_state_t),
+ VMSTATE_UINT32(port, mf624_state_t),
+ VMSTATE_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)