qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] qemu: test-irq device


From: Michael S. Tsirkin
Subject: [Qemu-devel] [PATCH] qemu: test-irq device
Date: Mon, 20 Jul 2009 14:32:08 +0300
User-agent: Mutt/1.5.19 (2009-01-05)

This device is used to test uio_pci_generic driver I submitted to linux
kernel. The device implements standard interrupt disable and interrupt
status bits, as well as custom set interrupt and interrupt counter
registers used for debugging the driver.

The implementation is on top of kraxel-qdev.v9 branch, and can also be
seen as a demotnstration of the new infrastructure: to add the device,
user simply adds -device test-irq to qemu command line.

Signed-off-by: Michael S. Tsirkin <address@hidden>
---

Posting the patch here in case someone finds it useful.
Does it make sense to have such a test device in qemu?

 Makefile.hw     |    2 +-
 Makefile.target |    2 +-
 hw/pci.h        |    1 +
 hw/test-irq.c   |  116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 119 insertions(+), 2 deletions(-)
 create mode 100644 hw/test-irq.c

diff --git a/Makefile.hw b/Makefile.hw
index f7a9507..e393693 100644
--- a/Makefile.hw
+++ b/Makefile.hw
@@ -16,7 +16,7 @@ CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 
-D_LARGEFILE_SOURCE
 CPPFLAGS+=-I$(SRC_PATH)/fpu
 
 obj-y =
-obj-y += virtio.o virtio-pci.o
+obj-y += virtio.o virtio-pci.o test-irq.o
 obj-y += fw_cfg.o
 obj-y += watchdog.o
 obj-y += nand.o ecc.o
diff --git a/Makefile.target b/Makefile.target
index a593503..11e99f5 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -492,7 +492,7 @@ obj-y = vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o 
machine.o \
         gdbstub.o gdbstub-xml.o msix.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
-obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o
+obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o test-irq.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 
 LIBS+=-lz
diff --git a/hw/pci.h b/hw/pci.h
index ab92092..355896f 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -99,6 +99,7 @@ typedef struct PCIIORegion {
 #define  PCI_COMMAND_IO                0x1     /* Enable response in I/O space 
*/
 #define  PCI_COMMAND_MEMORY    0x2     /* Enable response in Memory space */
 #define  PCI_COMMAND_MASTER    0x4     /* Enable bus master */
+#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
 #define PCI_STATUS              0x06    /* 16 bits */
 #define PCI_REVISION_ID         0x08    /* 8 bits  */
 #define PCI_CLASS_PROG         0x09    /* Reg. Level Programming Interface */
diff --git a/hw/test-irq.c b/hw/test-irq.c
new file mode 100644
index 0000000..fda156c
--- /dev/null
+++ b/hw/test-irq.c
@@ -0,0 +1,116 @@
+/*
+ * Test IRQ PCI Device
+ *
+ * Author: Michael S. Tsirkin <address@hidden>
+ *
+ *  Copyright (c) 2009, Red Hat Inc, Michael S. Tsirkin (address@hidden)
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include <inttypes.h>
+
+#include "pci.h"
+#include "sysbus.h"
+
+#define  PCI_STATUS_INTERRUPT  0x08 /* Interrupt status */
+#define  PCI_DEVICE_ID_TEST_IRQ 0x2009
+
+/* Status register: 1 bit to control interrupt */
+#define TEST_IRQ_STATUS 0x40
+#define TEST_IRQ_STATUS_MASK 0x1
+
+/* Counter register: 4 byte counter for interrupt asserted */
+#define TEST_IRQ_COUNTER 0x44
+
+struct test_irq_device {
+    PCIDevice pdev;
+    uint32_t counter;
+};
+
+/* test-irq device */
+
+static void test_irq_reset(void *opaque)
+{
+    struct test_irq_device *dev = opaque;
+    dev->counter = 0;
+}
+
+static void test_irq_set(struct test_irq_device *dev)
+{
+    ++dev->counter;
+    pci_set_long(dev->pdev.config + TEST_IRQ_COUNTER, dev->counter);
+    qemu_set_irq(dev->pdev.irq[0], 1);
+}
+
+static void test_irq_clr(struct test_irq_device *dev)
+{
+    qemu_set_irq(dev->pdev.irq[0], 0);
+}
+
+static void test_irq_write_config(PCIDevice *pdev, uint32_t address,
+                                 uint32_t val, int len)
+{
+    int is_disabled, was_disabled, was_requested, is_requested,
+        was_asserted, is_asserted;
+    uint16_t status;
+    struct test_irq_device *tdev;
+    tdev = container_of(pdev, struct test_irq_device, pdev);
+
+    was_disabled = pci_get_word(pdev->config + PCI_COMMAND) &
+        PCI_COMMAND_INTX_DISABLE;
+    was_requested = pdev->config[TEST_IRQ_STATUS] & TEST_IRQ_STATUS_MASK;
+
+    pci_default_write_config(pdev, address, val, len);
+
+    is_disabled = pci_get_word(pdev->config + PCI_COMMAND) &
+        PCI_COMMAND_INTX_DISABLE;
+    is_requested = pdev->config[TEST_IRQ_STATUS] & TEST_IRQ_STATUS_MASK;
+
+    status = pci_get_word(pdev->config + PCI_STATUS);
+    if (is_requested)
+        status |= PCI_STATUS_INTERRUPT;
+    else
+        status &= ~PCI_STATUS_INTERRUPT;
+    pci_set_word(pdev->config + PCI_STATUS, status);
+
+    was_asserted = was_requested && !was_disabled;
+    is_asserted = is_requested && !is_disabled;
+
+    if (!was_asserted && is_asserted) {
+        test_irq_set(tdev);
+    } else if (was_asserted && !is_asserted) {
+        test_irq_clr(tdev);
+    }
+}
+
+static void test_irq_initpci(PCIDevice *pdev)
+{
+    struct test_irq_device *tdev;
+    uint8_t *command = pdev->wmask + PCI_COMMAND;
+
+    pdev->wmask[TEST_IRQ_STATUS] = 0x1;
+    pci_set_word(command, PCI_COMMAND_INTX_DISABLE | pci_get_word(command));
+    pci_config_set_vendor_id(pdev->config, PCI_VENDOR_ID_REDHAT_QUMRANET);
+    pci_config_set_device_id(pdev->config, PCI_DEVICE_ID_TEST_IRQ);
+    pdev->config[PCI_INTERRUPT_PIN] = 0x1;
+    pdev->config_write = test_irq_write_config;
+
+    tdev = container_of(pdev, struct test_irq_device, pdev);
+    qemu_register_reset(test_irq_reset, tdev);
+}
+
+static PCIDeviceInfo test_irq_info = {
+    .qdev.name    = "test-irq",
+    .qdev.size    = sizeof(struct test_irq_device),
+    .init         = test_irq_initpci,
+};
+
+static void test_irq_register_device(void)
+{
+    pci_qdev_register(&test_irq_info);
+}
+
+device_init(test_irq_register_device)
-- 
1.6.2.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]