Skip to contentSkip to conversation

serial device hotplug patch series.

GIT PULL New Gerd Hoffmann 3 participants 11 messages Oct 17, 2012 – Oct 22, 2012

lore
Share & tools
lore
#0 lore raw

Hi,

Next round of the serial device hotplug series. Left out chardev patches due to confligting in-flight patches and ongoing discussions, carrying only pci-serial and usb-serial bits.

Adressed Anthonys comments: Added license to serial.h and moved documentation to docs/specs/pci-serial.txt.

please pull,
Gerd

The following changes since commit 6f4d6b09088ee161ff4be0e4db4e4c0962c79070:

target-mips: Pass MIPSCPU to mips_vpe_sleep() (2012-10-17 01:32:11 +0200)

are available in the git repository at:
git://git.kraxel.org/qemu serial.3

Gerd Hoffmann (7):
serial: split serial.c
serial: add pci variant
serial: add windows inf file for the pci card to docs
serial: add 2x + 4x pci variant
serial: add pci-serial documentation
usb-serial: don't magically zap chardev on umplug
usb-serial: only expose device in guest when the chardev is open

 default-configs/pci.mak   |    2 +
 docs/qemupciserial.inf    |  109 +++++++++++++++++++
 docs/specs/pci-serial.txt |   34 ++++++
 hw/Makefile.objs          |    3 +-
 hw/alpha_dp264.c          |    1 +
 hw/kzm.c                  |    2 +-
 hw/mips_fulong2e.c        |    1 +
 hw/mips_jazz.c            |    1 +
 hw/mips_malta.c           |    1 +
 hw/mips_mipssim.c         |    2 +-
 hw/mips_r4k.c             |    1 +
 hw/musicpal.c             |    2 +-
 hw/omap_uart.c            |    3 +-
 hw/openrisc_sim.c         |    3 +-
 hw/pc.c                   |    1 +
 hw/pc.h                   |   27 -----
 hw/pci_ids.h              |    1 +
 hw/petalogix_ml605_mmu.c  |    2 +-
 hw/ppc/e500.c             |    2 +-
 hw/ppc405_uc.c            |    2 +-
 hw/ppc440_bamboo.c        |    2 +-
 hw/ppc_prep.c             |    1 +
 hw/pxa2xx.c               |    2 +-
 hw/serial-isa.c           |  130 +++++++++++++++++++++++
 hw/serial-pci.c           |  252 +++++++++++++++++++++++++++++++++++++++++++++
 hw/serial.c               |  149 ++-------------------------
 hw/serial.h               |   99 ++++++++++++++++++
 hw/sm501.c                |    2 +-
 hw/sun4u.c                |    1 +
 hw/usb/dev-serial.c       |   21 +++-
 hw/virtex_ml507.c         |    2 +-
 hw/xtensa_lx60.c          |    3 +-
 32 files changed, 681 insertions(+), 183 deletions(-)
 create mode 100644 docs/qemupciserial.inf
 create mode 100644 docs/specs/pci-serial.txt
 create mode 100644 hw/serial-isa.c
 create mode 100644 hw/serial-pci.c
 create mode 100644 hw/serial.h
#1 lore raw

PATCH 1/7 serial: split serial.c

Split serial.c into serial.c, serial.h and serial-isa.c. While being at creating a serial.h header file move the serial prototypes from pc.h to the new serial.h. The latter leads to s/pc.h/serial.h/ in tons of boards which just want the serial bits from pc.h

---
 hw/Makefile.objs         |    2 +-
 hw/alpha_dp264.c         |    1 +
 hw/kzm.c                 |    2 +-
 hw/mips_fulong2e.c       |    1 +
 hw/mips_jazz.c           |    1 +
 hw/mips_malta.c          |    1 +
 hw/mips_mipssim.c        |    2 +-
 hw/mips_r4k.c            |    1 +
 hw/musicpal.c            |    2 +-
 hw/omap_uart.c           |    3 +-
 hw/openrisc_sim.c        |    3 +-
 hw/pc.c                  |    1 +
 hw/pc.h                  |   27 ---------
 hw/petalogix_ml605_mmu.c |    2 +-
 hw/ppc/e500.c            |    2 +-
 hw/ppc405_uc.c           |    2 +-
 hw/ppc440_bamboo.c       |    2 +-
 hw/ppc_prep.c            |    1 +
 hw/pxa2xx.c              |    2 +-
 hw/serial-isa.c          |  130 +++++++++++++++++++++++++++++++++++++++++
 hw/serial.c              |  143 ++--------------------------------------------
 hw/serial.h              |   98 +++++++++++++++++++++++++++++++
 hw/sm501.c               |    2 +-
 hw/sun4u.c               |    1 +
 hw/virtex_ml507.c        |    2 +-
 hw/xtensa_lx60.c         |    3 +-
 26 files changed, 257 insertions(+), 180 deletions(-)
 create mode 100644 hw/serial-isa.c
 create mode 100644 hw/serial.h
hw/Makefile.objs +1 -1
index 854faa9..16e7a1e 100644
@@ -20,7 +20,7 @@ common-obj-$(CONFIG_M48T59) += m48t59.o
 common-obj-$(CONFIG_ESCC) += escc.o
 common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
 
-common-obj-$(CONFIG_SERIAL) += serial.o
+common-obj-$(CONFIG_SERIAL) += serial.o serial-isa.o
 common-obj-$(CONFIG_PARALLEL) += parallel.o
 common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
 common-obj-$(CONFIG_PCSPK) += pcspk.o
hw/alpha_dp264.c +1 -0
index 5ea04c7..8ce04e5 100644
@@ -15,6 +15,7 @@
 #include "mc146818rtc.h"
 #include "ide.h"
 #include "i8254.h"
+#include "serial.h"
 
 #define MAX_IDE_BUS 2
 
hw/kzm.c +1 -1
index 68cd1b4..1f3082b 100644
@@ -21,7 +21,7 @@
 #include "net.h"
 #include "sysemu.h"
 #include "boards.h"
-#include "pc.h" /* for the FPGA UART that emulates a 16550 */
+#include "serial.h"
 #include "imx.h"
 
     /* Memory map for Kzm Emulation Baseboard:
hw/mips_fulong2e.c +1 -0
index d4a8672..a3cb3ab 100644
@@ -20,6 +20,7 @@
 
 #include "hw.h"
 #include "pc.h"
+#include "serial.h"
 #include "fdc.h"
 #include "net.h"
 #include "boards.h"
hw/mips_jazz.c +1 -0
index db927f1..d35cd54 100644
@@ -26,6 +26,7 @@
 #include "mips.h"
 #include "mips_cpudevs.h"
 #include "pc.h"
+#include "serial.h"
 #include "isa.h"
 #include "fdc.h"
 #include "sysemu.h"
hw/mips_malta.c +1 -0
index 632b466..8f73b1b 100644
@@ -24,6 +24,7 @@
 
 #include "hw.h"
 #include "pc.h"
+#include "serial.h"
 #include "fdc.h"
 #include "net.h"
 #include "boards.h"
hw/mips_mipssim.c +1 -1
index 830f635..0ee6756 100644
@@ -27,7 +27,7 @@
 #include "hw.h"
 #include "mips.h"
 #include "mips_cpudevs.h"
-#include "pc.h"
+#include "serial.h"
 #include "isa.h"
 #include "net.h"
 #include "sysemu.h"
hw/mips_r4k.c +1 -0
index 967a76e..b3be80b 100644
@@ -11,6 +11,7 @@
 #include "mips.h"
 #include "mips_cpudevs.h"
 #include "pc.h"
+#include "serial.h"
 #include "isa.h"
 #include "net.h"
 #include "sysemu.h"
hw/musicpal.c +1 -1
index f305e21..346fe41 100644
@@ -15,7 +15,7 @@
 #include "net.h"
 #include "sysemu.h"
 #include "boards.h"
-#include "pc.h"
+#include "serial.h"
 #include "qemu-timer.h"
 #include "ptimer.h"
 #include "block.h"
hw/omap_uart.c +1 -2
index 167d5c4..1c16a54 100644
@@ -20,8 +20,7 @@
 #include "qemu-char.h"
 #include "hw.h"
 #include "omap.h"
-/* We use pc-style serial ports.  */
-#include "pc.h"
+#include "serial.h"
 #include "exec-memory.h"
 
 /* UARTs */
hw/openrisc_sim.c +2 -1
index 55e97f0..e484613 100644
@@ -21,7 +21,8 @@
 #include "hw.h"
 #include "boards.h"
 #include "elf.h"
-#include "pc.h"
+#include "serial.h"
+#include "net.h"
 #include "loader.h"
 #include "exec-memory.h"
 #include "sysemu.h"
hw/pc.c +1 -0
index 6c0722d..805e8ca 100644
@@ -23,6 +23,7 @@
  */
 #include "hw.h"
 #include "pc.h"
+#include "serial.h"
 #include "apic.h"
 #include "fdc.h"
 #include "ide.h"
hw/pc.h +0 -27
index 9923d96..6cba7ce 100644
@@ -12,33 +12,6 @@
 
 /* PC-style peripherals (also used by other machines).  */
 
-/* serial.c */
-
-SerialState *serial_init(int base, qemu_irq irq, int baudbase,
-                         CharDriverState *chr);
-SerialState *serial_mm_init(MemoryRegion *address_space,
-                            target_phys_addr_t base, int it_shift,
-                            qemu_irq irq, int baudbase,
-                            CharDriverState *chr, enum device_endian);
-static inline bool serial_isa_init(ISABus *bus, int index,
-                                   CharDriverState *chr)
-{
-    ISADevice *dev;
-
-    dev = isa_try_create(bus, "isa-serial");
-    if (!dev) {
-        return false;
-    }
-    qdev_prop_set_uint32(&dev->qdev, "index", index);
-    qdev_prop_set_chr(&dev->qdev, "chardev", chr);
-    if (qdev_init(&dev->qdev) < 0) {
-        return false;
-    }
-    return true;
-}
-
-void serial_set_frequency(SerialState *s, uint32_t frequency);
-
 /* parallel.c */
 static inline bool parallel_init(ISABus *bus, int index, CharDriverState *chr)
 {
hw/petalogix_ml605_mmu.c +1 -1
index b9bfbed..1c12c5b 100644
@@ -34,7 +34,7 @@
 #include "boards.h"
 #include "xilinx.h"
 #include "blockdev.h"
-#include "pc.h"
+#include "serial.h"
 #include "exec-memory.h"
 #include "ssi.h"
 
hw/ppc/e500.c +1 -1
index d23f9b2..846f53a 100644
@@ -19,7 +19,7 @@
 #include "e500.h"
 #include "net.h"
 #include "hw/hw.h"
-#include "hw/pc.h"
+#include "hw/serial.h"
 #include "hw/pci.h"
 #include "hw/boards.h"
 #include "sysemu.h"
hw/ppc405_uc.c +1 -1
index b52ab2f..e81409d 100644
@@ -24,7 +24,7 @@
 #include "hw.h"
 #include "ppc.h"
 #include "ppc405.h"
-#include "pc.h"
+#include "serial.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
 #include "qemu-log.h"
hw/ppc440_bamboo.c +1 -1
index c198071..7e6fa85 100644
@@ -23,7 +23,7 @@
 #include "loader.h"
 #include "elf.h"
 #include "exec-memory.h"
-#include "pc.h"
+#include "serial.h"
 #include "ppc.h"
 #include "ppc405.h"
 #include "sysemu.h"
hw/ppc_prep.c +1 -0
index 1544430..50fd567 100644
@@ -24,6 +24,7 @@
 #include "hw.h"
 #include "nvram.h"
 #include "pc.h"
+#include "serial.h"
 #include "fdc.h"
 #include "net.h"
 #include "sysemu.h"
hw/pxa2xx.c +1 -1
index d5f1420..4ec904f 100644
@@ -10,7 +10,7 @@
 #include "sysbus.h"
 #include "pxa.h"
 #include "sysemu.h"
-#include "pc.h"
+#include "serial.h"
 #include "i2c.h"
 #include "ssi.h"
 #include "qemu-char.h"
hw/serial-isa.c new file +130 -0

130 lines not on this page · raw message

hw/serial.c +5 -138

192 lines not on this page · raw message

hw/serial.h new file +98 -0

98 lines not on this page · raw message

hw/sm501.c +1 -1
index 786e076..050d096 100644
@@ -24,7 +24,7 @@
 
 #include <stdio.h>
 #include "hw.h"
-#include "pc.h"
+#include "serial.h"
 #include "console.h"
 #include "devices.h"
 #include "sysbus.h"
hw/sun4u.c +1 -0
index 940db33..2397906 100644
@@ -25,6 +25,7 @@
 #include "pci.h"
 #include "apb_pci.h"
 #include "pc.h"
+#include "serial.h"
 #include "nvram.h"
 #include "fdc.h"
 #include "net.h"
hw/virtex_ml507.c +1 -1
index 79bc0d1..6ae5f60 100644
@@ -24,7 +24,7 @@
 
 #include "sysbus.h"
 #include "hw.h"
-#include "pc.h"
+#include "serial.h"
 #include "net.h"
 #include "flash.h"
 #include "sysemu.h"
hw/xtensa_lx60.c +2 -1
index 3653f65..99d8b4f 100644
@@ -31,7 +31,8 @@
 #include "elf.h"
 #include "memory.h"
 #include "exec-memory.h"
-#include "pc.h"
+#include "serial.h"
+#include "net.h"
 #include "sysbus.h"
 #include "flash.h"
 #include "blockdev.h"
Signature · 1 line
1.7.1
#2 lore raw

PATCH 2/7 serial: add pci variant

In reply to Gerd Hoffmann

So we get a hot-pluggable 16550 uart.

---
 default-configs/pci.mak |    2 +
 hw/Makefile.objs        |    1 +
 hw/pci_ids.h            |    1 +
 hw/serial-pci.c         |  101 +++++++++++++++++++++++++++++++++++++++++++++++
 hw/serial.c             |    6 +++
 hw/serial.h             |    1 +
 6 files changed, 112 insertions(+), 0 deletions(-)
 create mode 100644 hw/serial-pci.c
default-configs/pci.mak +2 -0
index 69e18f1..ae9d1eb 100644
@@ -19,3 +19,5 @@ CONFIG_IDE_PCI=y
 CONFIG_AHCI=y
 CONFIG_ESP=y
 CONFIG_ESP_PCI=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_PCI=y
hw/Makefile.objs +1 -0
index 16e7a1e..af4ab0c 100644
@@ -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
hw/pci_ids.h +1 -0
index 301bf1c..c017a79 100644
@@ -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
hw/serial-pci.c new file +101 -0

101 lines not on this page · raw message

hw/serial.c +6 -0
index 78e219d..5adbfaf 100644
@@ -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)
 {
hw/serial.h +1 -0
index 6f5293b..55a1ac5 100644
@@ -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 */
Signature · 1 line
1.7.1
#3 lore raw

PATCH 3/7 serial: add windows inf file for the pci card to docs

In reply to Gerd Hoffmann
---
 docs/qemupciserial.inf |  109 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 109 insertions(+), 0 deletions(-)
 create mode 100644 docs/qemupciserial.inf
docs/qemupciserial.inf new file +109 -0
new file mode 100644
index 0000000..3474310
@@ -0,0 +1,109 @@
+; qemupciserial.inf for QEMU, based on MSPORTS.INF
+
+; The driver itself is shipped with Windows (serial.sys).  This is
+; just a inf file to tell windows which pci id the serial pci card
+; emulated by qemu has, and to apply a name tag to it which windows
+; will show in the device manager.
+
+; Installing the driver: Go to device manager.  You should find a "pci
+; serial card" tagged with a yellow question mark.  Open properties.
+; Pick "update driver".  Then "select driver manually".  Pick "Ports
+; (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.
+
+[Version]
+Signature="$CHICAGO$"
+Class=Ports
+ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
+Provider=%QEMU%
+DriverVer=09/24/2012,1.3.0
+
+[SourceDisksNames]
+3426=windows cd
+
+[SourceDisksFiles]
+serial.sys 		= 3426
+serenum.sys 		= 3426
+
+[DestinationDirs]
+DefaultDestDir  = 11        ;LDID_SYS
+ComPort.NT.Copy = 12        ;DIRID_DRIVERS
+SerialEnumerator.NT.Copy=12 ;DIRID_DRIVERS
+
+; Drivers
+;----------------------------------------------------------
+[Manufacturer]
+%QEMU%=QEMU,NTx86
+
+[QEMU.NTx86]
+%QEMU-PCI_SERIAL.DeviceDesc% = ComPort, "PCI\VEN_1b36&DEV_0002&CC_0700"
+
+; COM sections
+;----------------------------------------------------------
+[ComPort.AddReg]
+HKR,,PortSubClass,1,01
+
+[ComPort.NT]
+AddReg=ComPort.AddReg, ComPort.NT.AddReg
+LogConfig=caa
+SyssetupPnPFlags = 1
+
+[ComPort.NT.HW]
+AddReg=ComPort.NT.HW.AddReg
+
+[ComPort.NT.AddReg]
+HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
+
+[ComPort.NT.HW.AddReg]
+HKR,,"UpperFilters",0x00010000,"serenum"
+
+;-------------- Service installation
+; Port Driver (function driver for this device)
+[ComPort.NT.Services]
+AddService = Serial, 0x00000002, Serial_Service_Inst, Serial_EventLog_Inst
+AddService = Serenum,,Serenum_Service_Inst
+
+; -------------- Serial Port Driver install sections
+[Serial_Service_Inst]
+DisplayName    = %Serial.SVCDESC%
+ServiceType    = 1               ; SERVICE_KERNEL_DRIVER
+StartType      = 1               ; SERVICE_SYSTEM_START (this driver may do detection)
+ErrorControl   = 0               ; SERVICE_ERROR_IGNORE
+ServiceBinary  = %12%\serial.sys
+LoadOrderGroup = Extended base
+
+; -------------- Serenum Driver install section
+[Serenum_Service_Inst]
+DisplayName    = %Serenum.SVCDESC%
+ServiceType    = 1               ; SERVICE_KERNEL_DRIVER
+StartType      = 3               ; SERVICE_DEMAND_START
+ErrorControl   = 1               ; SERVICE_ERROR_NORMAL
+ServiceBinary  = %12%\serenum.sys
+LoadOrderGroup = PNP Filter
+
+[Serial_EventLog_Inst]
+AddReg = Serial_EventLog_AddReg
+
+[Serial_EventLog_AddReg]
+HKR,,EventMessageFile,0x00020000,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\serial.sys"
+HKR,,TypesSupported,0x00010001,7
+
+; The following sections are COM port resource configs.
+; Section name format means:
+; Char 1 = c (COM port)
+; Char 2 = I/O config: 1 (3f8), 2 (2f8), 3 (3e8), 4 (2e8), a (any)
+; Char 3 = IRQ config: #, a (any)
+
+[caa]                   ; Any base, any IRQ
+ConfigPriority=HARDRECONFIG
+IOConfig=8@100-ffff%fff8(3ff::)
+IRQConfig=S:3,4,5,7,9,10,11,12,14,15
+
+[Strings]
+QEMU="QEMU"
+QEMU-PCI_SERIAL.DeviceDesc="QEMU Serial PCI Card"
+
+Serial.SVCDESC   = "Serial port driver"
+Serenum.SVCDESC = "Serenum Filter Driver"
Signature · 1 line
1.7.1
#4 lore raw

PATCH 3/7 serial: add windows inf file for the pci card to docs

Quoted 6 lines
---
 docs/qemupciserial.inf |  109 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 109 insertions(+), 0 deletions(-)

create mode 100644 docs/qemupciserial.inf

[...]

Did you try to add emulation of a PCI serial card natively recognized by Windows XP (at least),
like SIIG CyberSerial card?
Available models described in msports.inf are vendorId 131F, deviceId 1000, subsystem 00000000, revision 2, or with vendorId 131F, deviceId 2000, class code 0700)

Regards,

Hervé

#5 lore raw

Re: [Qemu-devel] [PATCH 3/7] serial: add windows inf file for the pci card to docs

Quoted 7 lines · Hervé Poussineau
Quoted 7 lines
---
 docs/qemupciserial.inf |  109
++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 109 insertions(+), 0 deletions(-)

create mode 100644 docs/qemupciserial.inf

Quoted 5 lines

[...]

Did you try to add emulation of a PCI serial card natively recognized by Windows XP (at least),
like SIIG CyberSerial card?

Thats the only one. Looked at the linux code for it, a comment mumbled something about a eeprom holding card configuration, /me figured I better don't go that route. If it would have been a simple card with just a 16550 & nothing else I would have picked it.

cheers,
Gerd

#6 lore raw

PATCH 4/7 serial: add 2x + 4x pci variant

In reply to Gerd Hoffmann

Add multiport serial card implementation, with two variants, one featuring two and one featuring four ports.

---
 hw/serial-pci.c |  149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 149 insertions(+), 0 deletions(-)
hw/serial-pci.c +149 -0
index 6fcf117..badd297 100644
@@ -26,11 +26,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);
@@ -47,6 +59,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);
@@ -56,6 +118,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;
+        serial_exit_core(s);
+        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,
@@ -67,11 +145,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);
@@ -86,6 +191,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,
@@ -93,9 +226,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)
Signature · 1 line
1.7.1
#7 lore raw

PATCH 5/7 serial: add pci-serial documentation

In reply to Gerd Hoffmann
---
 docs/specs/pci-serial.txt |   34 ++++++++++++++++++++++++++++++++++
 hw/serial-pci.c           |    2 ++
 2 files changed, 36 insertions(+), 0 deletions(-)
 create mode 100644 docs/specs/pci-serial.txt
docs/specs/pci-serial.txt new file +34 -0
new file mode 100644
index 0000000..66c761f
@@ -0,0 +1,34 @@
+
+QEMU pci serial devices
+=======================
+
+There is one single-port variant and two muliport-variants.  Linux
+guests out-of-the box with all cards.  There is a Windows inf file
+(docs/qemupciserial.inf) to setup the single-port card in Windows
+guests.
+
+
+single-port card
+----------------
+
+Name:   pci-serial
+PCI ID: 1b36:0002
+
+PCI Region 0:
+   IO bar, 8 bytes long, with the 16550 uart mapped to it.
+   Interrupt is wired to pin A.
+
+
+multiport cards
+---------------
+
+Name:   pci-serial-2x
+PCI ID: 1b36:0003
+
+Name:   pci-serial-4x
+PCI ID: 1b36:0004
+
+PCI Region 0:
+   IO bar, with two/four 16550 uart mapped after each other.
+   The first is at offset 0, second at offset 8, ...
+   Interrupt is wired to pin A.
hw/serial-pci.c +2 -0
index badd297..95dc5c8 100644
@@ -23,6 +23,8 @@
  * THE SOFTWARE.
  */
 
+/* see docs/specs/pci-serial.txt */
+
 #include "serial.h"
 #include "pci.h"
 
Signature · 1 line
1.7.1
#8 lore raw

PATCH 6/7 usb-serial: don't magically zap chardev on umplug

In reply to Gerd Hoffmann
---
 hw/usb/dev-serial.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
hw/usb/dev-serial.c +1 -1
index 69b6e48..43214cd 100644
@@ -421,7 +421,7 @@ static void usb_serial_handle_destroy(USBDevice *dev)
 {
     USBSerialState *s = (USBSerialState *)dev;
 
-    qemu_chr_delete(s->cs);
+    qemu_chr_add_handlers(s->cs, NULL, NULL, NULL, NULL);
 }
 
 static int usb_serial_can_read(void *opaque)
Signature · 1 line
1.7.1
#9 lore raw

PATCH 7/7 usb-serial: only expose device in guest when the chardev is open

In reply to Gerd Hoffmann
---
 hw/usb/dev-serial.c |   19 +++++++++++++++++--
 1 files changed, 17 insertions(+), 2 deletions(-)
hw/usb/dev-serial.c +17 -2
index 43214cd..a466f99 100644
@@ -427,6 +427,10 @@ static void usb_serial_handle_destroy(USBDevice *dev)
 static int usb_serial_can_read(void *opaque)
 {
     USBSerialState *s = opaque;
+
+    if (!s->dev.attached) {
+        return 0;
+    }
     return RECV_BUF - s->recv_used;
 }
 
@@ -469,8 +473,14 @@ static void usb_serial_event(void *opaque, int event)
         case CHR_EVENT_FOCUS:
             break;
         case CHR_EVENT_OPENED:
-            usb_serial_reset(s);
-            /* TODO: Reset USB port */
+            if (!s->dev.attached) {
+                usb_device_attach(&s->dev);
+            }
+            break;
+        case CHR_EVENT_CLOSED:
+            if (s->dev.attached) {
+                usb_device_detach(&s->dev);
+            }
             break;
     }
 }
@@ -481,6 +491,7 @@ static int usb_serial_initfn(USBDevice *dev)
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
+    dev->auto_attach = 0;
 
     if (!s->cs) {
         error_report("Property chardev is required");
@@ -490,6 +501,10 @@ static int usb_serial_initfn(USBDevice *dev)
     qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
                           usb_serial_event, s);
     usb_serial_handle_reset(dev);
+
+    if (s->cs->opened && !dev->attached) {
+        usb_device_attach(dev);
+    }
     return 0;
 }
 
Signature · 1 line
1.7.1
#10 lore raw
In reply to Gerd Hoffmann
Quoted 9 lines · Gerd Hoffmann

Hi,

Next round of the serial device hotplug series. Left out chardev patches due to confligting in-flight patches and ongoing discussions, carrying only pci-serial and usb-serial bits.

Adressed Anthonys comments: Added license to serial.h and moved documentation to docs/specs/pci-serial.txt.

Applied. Thanks.

Regards,

Anthony Liguori

Quoted 57 lines

please pull,
Gerd

The following changes since commit 6f4d6b09088ee161ff4be0e4db4e4c0962c79070:

target-mips: Pass MIPSCPU to mips_vpe_sleep() (2012-10-17 01:32:11 +0200)

are available in the git repository at:
git://git.kraxel.org/qemu serial.3

Gerd Hoffmann (7):
serial: split serial.c
serial: add pci variant
serial: add windows inf file for the pci card to docs
serial: add 2x + 4x pci variant
serial: add pci-serial documentation
usb-serial: don't magically zap chardev on umplug
usb-serial: only expose device in guest when the chardev is open

 default-configs/pci.mak   |    2 +
 docs/qemupciserial.inf    |  109 +++++++++++++++++++
 docs/specs/pci-serial.txt |   34 ++++++
 hw/Makefile.objs          |    3 +-
 hw/alpha_dp264.c          |    1 +
 hw/kzm.c                  |    2 +-
 hw/mips_fulong2e.c        |    1 +
 hw/mips_jazz.c            |    1 +
 hw/mips_malta.c           |    1 +
 hw/mips_mipssim.c         |    2 +-
 hw/mips_r4k.c             |    1 +
 hw/musicpal.c             |    2 +-
 hw/omap_uart.c            |    3 +-
 hw/openrisc_sim.c         |    3 +-
 hw/pc.c                   |    1 +
 hw/pc.h                   |   27 -----
 hw/pci_ids.h              |    1 +
 hw/petalogix_ml605_mmu.c  |    2 +-
 hw/ppc/e500.c             |    2 +-
 hw/ppc405_uc.c            |    2 +-
 hw/ppc440_bamboo.c        |    2 +-
 hw/ppc_prep.c             |    1 +
 hw/pxa2xx.c               |    2 +-
 hw/serial-isa.c           |  130 +++++++++++++++++++++++
 hw/serial-pci.c           |  252 +++++++++++++++++++++++++++++++++++++++++++++
 hw/serial.c               |  149 ++-------------------------
 hw/serial.h               |   99 ++++++++++++++++++
 hw/sm501.c                |    2 +-
 hw/sun4u.c                |    1 +
 hw/usb/dev-serial.c       |   21 +++-
 hw/virtex_ml507.c         |    2 +-
 hw/xtensa_lx60.c          |    3 +-
 32 files changed, 681 insertions(+), 183 deletions(-)
 create mode 100644 docs/qemupciserial.inf
 create mode 100644 docs/specs/pci-serial.txt
 create mode 100644 hw/serial-isa.c
 create mode 100644 hw/serial-pci.c
 create mode 100644 hw/serial.h