summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2012-10-17 09:54:20 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2012-10-22 13:26:42 -0500
commit419ad67208a37367932a5bf88d3860f85e06282c (patch)
tree520c2681926eff73db642c9c08dcde1758ff9f7f /hw
parent488cb996cd8d8eaa5ecfdc6ba5f6cbd23a13271b (diff)
downloadqemu-419ad67208a37367932a5bf88d3860f85e06282c.tar.gz
qemu-419ad67208a37367932a5bf88d3860f85e06282c.tar.bz2
qemu-419ad67208a37367932a5bf88d3860f85e06282c.zip
serial: add pci variant
So we get a hot-pluggable 16550 uart. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/Makefile.objs1
-rw-r--r--hw/pci_ids.h1
-rw-r--r--hw/serial-pci.c101
-rw-r--r--hw/serial.c6
-rw-r--r--hw/serial.h1
5 files changed, 110 insertions, 0 deletions
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 16e7a1e6f3..af4ab0c735 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -21,6 +21,7 @@ common-obj-$(CONFIG_ESCC) += escc.o
common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
common-obj-$(CONFIG_SERIAL) += serial.o serial-isa.o
+common-obj-$(CONFIG_SERIAL_PCI) += serial-pci.o
common-obj-$(CONFIG_PARALLEL) += parallel.o
common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
common-obj-$(CONFIG_PCSPK) += pcspk.o
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index 301bf1cd86..c017a79998 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -37,6 +37,7 @@
#define PCI_CLASS_BRIDGE_PCI 0x0604
#define PCI_CLASS_BRIDGE_OTHER 0x0680
+#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
#define PCI_CLASS_COMMUNICATION_OTHER 0x0780
#define PCI_CLASS_PROCESSOR_CO 0x0b40
diff --git a/hw/serial-pci.c b/hw/serial-pci.c
new file mode 100644
index 0000000000..6fcf1170b3
--- /dev/null
+++ b/hw/serial-pci.c
@@ -0,0 +1,101 @@
+/*
+ * QEMU 16550A UART emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2008 Citrix Systems, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "serial.h"
+#include "pci.h"
+
+typedef struct PCISerialState {
+ PCIDevice dev;
+ SerialState state;
+} PCISerialState;
+
+static int serial_pci_init(PCIDevice *dev)
+{
+ PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
+ SerialState *s = &pci->state;
+
+ s->baudbase = 115200;
+ serial_init_core(s);
+
+ pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
+ s->irq = pci->dev.irq[0];
+
+ memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
+ pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
+ return 0;
+}
+
+static void serial_pci_exit(PCIDevice *dev)
+{
+ PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
+ SerialState *s = &pci->state;
+
+ serial_exit_core(s);
+ memory_region_destroy(&s->io);
+}
+
+static const VMStateDescription vmstate_pci_serial = {
+ .name = "pci-serial",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE(dev, PCISerialState),
+ VMSTATE_STRUCT(state, PCISerialState, 0, vmstate_serial, SerialState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static Property serial_pci_properties[] = {
+ DEFINE_PROP_CHR("chardev", PCISerialState, state.chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void serial_pci_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
+ pc->init = serial_pci_init;
+ pc->exit = serial_pci_exit;
+ pc->vendor_id = 0x1b36; /* Red Hat */
+ pc->device_id = 0x0002;
+ pc->revision = 1;
+ pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
+ dc->vmsd = &vmstate_pci_serial;
+ dc->props = serial_pci_properties;
+}
+
+static TypeInfo serial_pci_info = {
+ .name = "pci-serial",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCISerialState),
+ .class_init = serial_pci_class_initfn,
+};
+
+static void serial_pci_register_types(void)
+{
+ type_register_static(&serial_pci_info);
+}
+
+type_init(serial_pci_register_types)
diff --git a/hw/serial.c b/hw/serial.c
index 78e219df5c..5adbfafde5 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -692,6 +692,12 @@ void serial_init_core(SerialState *s)
serial_event, s);
}
+void serial_exit_core(SerialState *s)
+{
+ qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
+ qemu_unregister_reset(serial_reset, s);
+}
+
/* Change the main reference oscillator frequency. */
void serial_set_frequency(SerialState *s, uint32_t frequency)
{
diff --git a/hw/serial.h b/hw/serial.h
index 6f5293b202..55a1ac5e9b 100644
--- a/hw/serial.h
+++ b/hw/serial.h
@@ -84,6 +84,7 @@ extern const VMStateDescription vmstate_serial;
extern const MemoryRegionOps serial_io_ops;
void serial_init_core(SerialState *s);
+void serial_exit_core(SerialState *s);
void serial_set_frequency(SerialState *s, uint32_t frequency);
/* legacy pre qom */