From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v2 4/4] serial: add 2x + 4x pci variant
Date: Fri, 28 Sep 2012 16:08:35 +0200 [thread overview]
Message-ID: <k44b12$20q$1@ger.gmane.org> (raw)
In-Reply-To: <1348661674-16722-5-git-send-email-kraxel@redhat.com>
Il 26/09/2012 14:14, Gerd Hoffmann ha scritto:
> Add multiport serial card implementation, with two variants,
> one featuring two and one featuring four ports.
>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
> docs/qemupciserial.inf | 2 +
> hw/serial-pci.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 159 insertions(+), 0 deletions(-)
>
> diff --git a/docs/qemupciserial.inf b/docs/qemupciserial.inf
> index 905a929..911eaa6 100644
> --- a/docs/qemupciserial.inf
> +++ b/docs/qemupciserial.inf
> @@ -11,6 +11,8 @@
> ; (Com+Lpt)" from the list. Click "Have a disk". Select this file.
> ; Procedure may vary a bit depending on the windows version.
>
> +; FIXME: This file covers the single port version only.
> +
Looks like this is what you want for Windows:
http://msdn.microsoft.com/en-us/library/windows/hardware/ff542737%28v=vs.85%29.aspx
It's a special "splitter" driver that makes a fake bus with multiple
devices on it, out of a single device
Paolo
> [Version]
> Signature="$CHICAGO$"
> Class=Ports
> diff --git a/hw/serial-pci.c b/hw/serial-pci.c
> index 88b71f5..54bd4eb 100644
> --- a/hw/serial-pci.c
> +++ b/hw/serial-pci.c
> @@ -28,6 +28,14 @@
> * pci region 0 is a io bar, 8 bytes long, with the 16550 uart mapped to it.
> * interrupt is wired to pin A.
> *
> + * pci-serial-4x spec:
> + * pci region 0 is a io bar, with four 16550 uarts mapped after each other,
> + * the first at offset 0, second at 8, third at 16 and fourth at 24.
> + * interrupt is wired to pin A.
> + *
> + * pci-serial-2x spec:
> + * same as pci-serial-4x but with two uarts only.
> + *
> * [root@fedora ~]# lspci -vnse
> * 00:0e.0 0700: 1b36:0002 (rev 01) (prog-if 00 [8250])
> * Subsystem: 1af4:1100
> @@ -40,11 +48,23 @@
> #include "serial.h"
> #include "pci.h"
>
> +#define PCI_SERIAL_MAX_PORTS 4
> +
> typedef struct PCISerialState {
> PCIDevice dev;
> SerialState state;
> } PCISerialState;
>
> +typedef struct PCIMultiSerialState {
> + PCIDevice dev;
> + MemoryRegion iobar;
> + uint32_t ports;
> + char *name[PCI_SERIAL_MAX_PORTS];
> + SerialState state[PCI_SERIAL_MAX_PORTS];
> + uint32_t level[PCI_SERIAL_MAX_PORTS];
> + qemu_irq *irqs;
> +} PCIMultiSerialState;
> +
> static int serial_pci_init(PCIDevice *dev)
> {
> PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
> @@ -61,6 +81,56 @@ static int serial_pci_init(PCIDevice *dev)
> return 0;
> }
>
> +static void multi_serial_irq_mux(void *opaque, int n, int level)
> +{
> + PCIMultiSerialState *pci = opaque;
> + int i, pending = 0;
> +
> + pci->level[n] = level;
> + for (i = 0; i < pci->ports; i++) {
> + if (pci->level[i]) {
> + pending = 1;
> + }
> + }
> + qemu_set_irq(pci->dev.irq[0], pending);
> +}
> +
> +static int multi_serial_pci_init(PCIDevice *dev)
> +{
> + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
> + PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev);
> + SerialState *s;
> + int i;
> +
> + switch (pc->device_id) {
> + case 0x0003:
> + pci->ports = 2;
> + break;
> + case 0x0004:
> + pci->ports = 4;
> + break;
> + }
> + assert(pci->ports > 0);
> + assert(pci->ports <= PCI_SERIAL_MAX_PORTS);
> +
> + pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
> + memory_region_init(&pci->iobar, "multiserial", 8 * pci->ports);
> + pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar);
> + pci->irqs = qemu_allocate_irqs(multi_serial_irq_mux, pci,
> + pci->ports);
> +
> + for (i = 0; i < pci->ports; i++) {
> + s = pci->state + i;
> + s->baudbase = 115200;
> + serial_init_core(s);
> + s->irq = pci->irqs[i];
> + pci->name[i] = g_strdup_printf("uart #%d", i+1);
> + memory_region_init_io(&s->io, &serial_io_ops, s, pci->name[i], 8);
> + memory_region_add_subregion(&pci->iobar, 8 * i, &s->io);
> + }
> + return 0;
> +}
> +
> static void serial_pci_exit(PCIDevice *dev)
> {
> PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
> @@ -70,6 +140,22 @@ static void serial_pci_exit(PCIDevice *dev)
> memory_region_destroy(&s->io);
> }
>
> +static void multi_serial_pci_exit(PCIDevice *dev)
> +{
> + PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev);
> + SerialState *s;
> + int i;
> +
> + for (i = 0; i < pci->ports; i++) {
> + s = pci->state + i;
> + qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
> + memory_region_destroy(&s->io);
> + g_free(pci->name[i]);
> + }
> + memory_region_destroy(&pci->iobar);
> + qemu_free_irqs(pci->irqs);
> +}
> +
> static const VMStateDescription vmstate_pci_serial = {
> .name = "pci-serial",
> .version_id = 1,
> @@ -81,11 +167,38 @@ static const VMStateDescription vmstate_pci_serial = {
> }
> };
>
> +static const VMStateDescription vmstate_pci_multi_serial = {
> + .name = "pci-serial-multi",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .fields = (VMStateField[]) {
> + VMSTATE_PCI_DEVICE(dev, PCIMultiSerialState),
> + VMSTATE_STRUCT_ARRAY(state, PCIMultiSerialState, PCI_SERIAL_MAX_PORTS,
> + 0, vmstate_serial, SerialState),
> + VMSTATE_UINT32_ARRAY(level, PCIMultiSerialState, PCI_SERIAL_MAX_PORTS),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> static Property serial_pci_properties[] = {
> DEFINE_PROP_CHR("chardev", PCISerialState, state.chr),
> DEFINE_PROP_END_OF_LIST(),
> };
>
> +static Property multi_2x_serial_pci_properties[] = {
> + DEFINE_PROP_CHR("chardev1", PCIMultiSerialState, state[0].chr),
> + DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr),
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static Property multi_4x_serial_pci_properties[] = {
> + DEFINE_PROP_CHR("chardev1", PCIMultiSerialState, state[0].chr),
> + DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr),
> + DEFINE_PROP_CHR("chardev3", PCIMultiSerialState, state[2].chr),
> + DEFINE_PROP_CHR("chardev4", PCIMultiSerialState, state[3].chr),
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> static void serial_pci_class_initfn(ObjectClass *klass, void *data)
> {
> DeviceClass *dc = DEVICE_CLASS(klass);
> @@ -100,6 +213,34 @@ static void serial_pci_class_initfn(ObjectClass *klass, void *data)
> dc->props = serial_pci_properties;
> }
>
> +static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
> + pc->init = multi_serial_pci_init;
> + pc->exit = multi_serial_pci_exit;
> + pc->vendor_id = 0x1b36; /* Red Hat */
> + pc->device_id = 0x0003;
> + pc->revision = 1;
> + pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
> + dc->vmsd = &vmstate_pci_multi_serial;
> + dc->props = multi_2x_serial_pci_properties;
> +}
> +
> +static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
> + pc->init = multi_serial_pci_init;
> + pc->exit = multi_serial_pci_exit;
> + pc->vendor_id = 0x1b36; /* Red Hat */
> + pc->device_id = 0x0004;
> + pc->revision = 1;
> + pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
> + dc->vmsd = &vmstate_pci_multi_serial;
> + dc->props = multi_4x_serial_pci_properties;
> +}
> +
> static TypeInfo serial_pci_info = {
> .name = "pci-serial",
> .parent = TYPE_PCI_DEVICE,
> @@ -107,9 +248,25 @@ static TypeInfo serial_pci_info = {
> .class_init = serial_pci_class_initfn,
> };
>
> +static TypeInfo multi_2x_serial_pci_info = {
> + .name = "pci-serial-2x",
> + .parent = TYPE_PCI_DEVICE,
> + .instance_size = sizeof(PCIMultiSerialState),
> + .class_init = multi_2x_serial_pci_class_initfn,
> +};
> +
> +static TypeInfo multi_4x_serial_pci_info = {
> + .name = "pci-serial-4x",
> + .parent = TYPE_PCI_DEVICE,
> + .instance_size = sizeof(PCIMultiSerialState),
> + .class_init = multi_4x_serial_pci_class_initfn,
> +};
> +
> static void serial_pci_register_types(void)
> {
> type_register_static(&serial_pci_info);
> + type_register_static(&multi_2x_serial_pci_info);
> + type_register_static(&multi_4x_serial_pci_info);
> }
>
> type_init(serial_pci_register_types)
>
prev parent reply other threads:[~2012-09-28 14:10 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-09-26 12:14 [Qemu-devel] [PATCH v2 0/4] add pci-serial devices Gerd Hoffmann
2012-09-26 12:14 ` [Qemu-devel] [PATCH v2 1/4] serial: split serial.c Gerd Hoffmann
2012-09-26 12:14 ` [Qemu-devel] [PATCH v2 2/4] serial: add pci variant Gerd Hoffmann
2012-09-26 12:14 ` [Qemu-devel] [PATCH v2 3/4] serial: add windows inf file for the pci card to docs Gerd Hoffmann
2012-09-29 11:41 ` Blue Swirl
2012-09-26 12:14 ` [Qemu-devel] [PATCH v2 4/4] serial: add 2x + 4x pci variant Gerd Hoffmann
2012-09-28 14:08 ` Paolo Bonzini [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='k44b12$20q$1@ger.gmane.org' \
--to=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.