qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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)
> 

      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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).