qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v2 4/4] serial: add 2x + 4x pci variant


From: Paolo Bonzini
Subject: Re: [Qemu-devel] [PATCH v2 4/4] serial: add 2x + 4x pci variant
Date: Fri, 28 Sep 2012 16:08:35 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20120911 Thunderbird/15.0.1

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 <address@hidden>
> ---
>  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.
> + *
>   * address@hidden ~]# 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 via email to

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