From nobody Fri May 17 03:01:00 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1554097304229183.6375437397968; Sun, 31 Mar 2019 22:41:44 -0700 (PDT) Received: from localhost ([127.0.0.1]:49473 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hAphR-0002o7-6b for importer@patchew.org; Mon, 01 Apr 2019 01:41:37 -0400 Received: from eggs.gnu.org ([209.51.188.92]:59225) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hApgW-00028j-LP for qemu-devel@nongnu.org; Mon, 01 Apr 2019 01:40:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hApgS-0002ep-Qa for qemu-devel@nongnu.org; Mon, 01 Apr 2019 01:40:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54652) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hApgM-0002Uj-JO for qemu-devel@nongnu.org; Mon, 01 Apr 2019 01:40:32 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9CD02308FC20 for ; Mon, 1 Apr 2019 05:40:21 +0000 (UTC) Received: from thuth.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1C67858B2; Mon, 1 Apr 2019 05:40:01 +0000 (UTC) From: Thomas Huth To: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Michael S. Tsirkin" Date: Mon, 1 Apr 2019 07:39:56 +0200 Message-Id: <1554097196-9434-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Mon, 01 Apr 2019 05:40:21 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH] hw/char: Move multi-serial devices into separate file X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Miroslav Rezanina , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" In our downstream distribution of QEMU, we'd like to ship the binary without the multi-serial PCI devices. To make this disablement easier, let's move the devices into a separate file and add a proper Kconfig- switch for these devices. Signed-off-by: Thomas Huth Reviewed-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- I've forgot to Cc: qemu-devel when I sent this yesterday, so sorry if you've got this mail twice. hw/char/Kconfig | 6 ++ hw/char/Makefile.objs | 1 + hw/char/serial-pci-multi.c | 208 +++++++++++++++++++++++++++++++++++++++++= ++++ hw/char/serial-pci.c | 170 ------------------------------------ 4 files changed, 215 insertions(+), 170 deletions(-) create mode 100644 hw/char/serial-pci-multi.c diff --git a/hw/char/Kconfig b/hw/char/Kconfig index 6360c9f..40e7a8b 100644 --- a/hw/char/Kconfig +++ b/hw/char/Kconfig @@ -24,6 +24,12 @@ config SERIAL_PCI depends on PCI select SERIAL =20 +config SERIAL_PCI_MULTI + bool + default y if PCI_DEVICES + depends on PCI + select SERIAL + config VIRTIO_SERIAL bool default y diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs index cf086e7..02d8a66 100644 --- a/hw/char/Makefile.objs +++ b/hw/char/Makefile.objs @@ -7,6 +7,7 @@ common-obj-$(CONFIG_PL011) +=3D pl011.o common-obj-$(CONFIG_SERIAL) +=3D serial.o common-obj-$(CONFIG_SERIAL_ISA) +=3D serial-isa.o common-obj-$(CONFIG_SERIAL_PCI) +=3D serial-pci.o +common-obj-$(CONFIG_SERIAL_PCI_MULTI) +=3D serial-pci-multi.o common-obj-$(CONFIG_VIRTIO_SERIAL) +=3D virtio-console.o common-obj-$(CONFIG_XILINX) +=3D xilinx_uartlite.o common-obj-$(CONFIG_XEN) +=3D xen_console.o diff --git a/hw/char/serial-pci-multi.c b/hw/char/serial-pci-multi.c new file mode 100644 index 0000000..63dcbaa --- /dev/null +++ b/hw/char/serial-pci-multi.c @@ -0,0 +1,208 @@ +/* + * QEMU 16550A multi UART emulation + * + * SPDX-License-Identifier: MIT + * + * 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"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * 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 OT= HER + * 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. + */ + +/* see docs/specs/pci-serial.txt */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/char/serial.h" +#include "hw/pci/pci.h" + +#define PCI_SERIAL_MAX_PORTS 4 + +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; + uint8_t prog_if; +} PCIMultiSerialState; + +static void multi_serial_pci_exit(PCIDevice *dev) +{ + PCIMultiSerialState *pci =3D DO_UPCAST(PCIMultiSerialState, dev, dev); + SerialState *s; + int i; + + for (i =3D 0; i < pci->ports; i++) { + s =3D pci->state + i; + serial_exit_core(s); + memory_region_del_subregion(&pci->iobar, &s->io); + g_free(pci->name[i]); + } + qemu_free_irqs(pci->irqs, pci->ports); +} + +static void multi_serial_irq_mux(void *opaque, int n, int level) +{ + PCIMultiSerialState *pci =3D opaque; + int i, pending =3D 0; + + pci->level[n] =3D level; + for (i =3D 0; i < pci->ports; i++) { + if (pci->level[i]) { + pending =3D 1; + } + } + pci_set_irq(&pci->dev, pending); +} + +static void multi_serial_pci_realize(PCIDevice *dev, Error **errp) +{ + PCIDeviceClass *pc =3D PCI_DEVICE_GET_CLASS(dev); + PCIMultiSerialState *pci =3D DO_UPCAST(PCIMultiSerialState, dev, dev); + SerialState *s; + Error *err =3D NULL; + int i, nr_ports =3D 0; + + switch (pc->device_id) { + case 0x0003: + nr_ports =3D 2; + break; + case 0x0004: + nr_ports =3D 4; + break; + } + assert(nr_ports > 0); + assert(nr_ports <=3D PCI_SERIAL_MAX_PORTS); + + pci->dev.config[PCI_CLASS_PROG] =3D pci->prog_if; + pci->dev.config[PCI_INTERRUPT_PIN] =3D 0x01; + memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * nr_por= ts); + pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar); + pci->irqs =3D qemu_allocate_irqs(multi_serial_irq_mux, pci, + nr_ports); + + for (i =3D 0; i < nr_ports; i++) { + s =3D pci->state + i; + s->baudbase =3D 115200; + serial_realize_core(s, &err); + if (err !=3D NULL) { + error_propagate(errp, err); + multi_serial_pci_exit(dev); + return; + } + s->irq =3D pci->irqs[i]; + pci->name[i] =3D g_strdup_printf("uart #%d", i + 1); + memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, + pci->name[i], 8); + memory_region_add_subregion(&pci->iobar, 8 * i, &s->io); + pci->ports++; + } +} + +static const VMStateDescription vmstate_pci_multi_serial =3D { + .name =3D "pci-serial-multi", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_PCI_DEVICE(dev, PCIMultiSerialState), + VMSTATE_STRUCT_ARRAY(state, PCIMultiSerialState, PCI_SERIAL_MAX_PO= RTS, + 0, vmstate_serial, SerialState), + VMSTATE_UINT32_ARRAY(level, PCIMultiSerialState, PCI_SERIAL_MAX_PO= RTS), + VMSTATE_END_OF_LIST() + } +}; + +static Property multi_2x_serial_pci_properties[] =3D { + DEFINE_PROP_CHR("chardev1", PCIMultiSerialState, state[0].chr), + DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr), + DEFINE_PROP_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02), + DEFINE_PROP_END_OF_LIST(), +}; + +static Property multi_4x_serial_pci_properties[] =3D { + 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_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02), + DEFINE_PROP_END_OF_LIST(), +}; + +static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *dat= a) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + PCIDeviceClass *pc =3D PCI_DEVICE_CLASS(klass); + pc->realize =3D multi_serial_pci_realize; + pc->exit =3D multi_serial_pci_exit; + pc->vendor_id =3D PCI_VENDOR_ID_REDHAT; + pc->device_id =3D PCI_DEVICE_ID_REDHAT_SERIAL2; + pc->revision =3D 1; + pc->class_id =3D PCI_CLASS_COMMUNICATION_SERIAL; + dc->vmsd =3D &vmstate_pci_multi_serial; + dc->props =3D multi_2x_serial_pci_properties; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); +} + +static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *dat= a) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + PCIDeviceClass *pc =3D PCI_DEVICE_CLASS(klass); + pc->realize =3D multi_serial_pci_realize; + pc->exit =3D multi_serial_pci_exit; + pc->vendor_id =3D PCI_VENDOR_ID_REDHAT; + pc->device_id =3D PCI_DEVICE_ID_REDHAT_SERIAL4; + pc->revision =3D 1; + pc->class_id =3D PCI_CLASS_COMMUNICATION_SERIAL; + dc->vmsd =3D &vmstate_pci_multi_serial; + dc->props =3D multi_4x_serial_pci_properties; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); +} + +static const TypeInfo multi_2x_serial_pci_info =3D { + .name =3D "pci-serial-2x", + .parent =3D TYPE_PCI_DEVICE, + .instance_size =3D sizeof(PCIMultiSerialState), + .class_init =3D multi_2x_serial_pci_class_initfn, + .interfaces =3D (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, +}; + +static const TypeInfo multi_4x_serial_pci_info =3D { + .name =3D "pci-serial-4x", + .parent =3D TYPE_PCI_DEVICE, + .instance_size =3D sizeof(PCIMultiSerialState), + .class_init =3D multi_4x_serial_pci_class_initfn, + .interfaces =3D (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, +}; + +static void multi_serial_pci_register_types(void) +{ + type_register_static(&multi_2x_serial_pci_info); + type_register_static(&multi_4x_serial_pci_info); +} + +type_init(multi_serial_pci_register_types) diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c index cb0d04c..2d5ffae 100644 --- a/hw/char/serial-pci.c +++ b/hw/char/serial-pci.c @@ -30,26 +30,12 @@ #include "hw/char/serial.h" #include "hw/pci/pci.h" =20 -#define PCI_SERIAL_MAX_PORTS 4 - typedef struct PCISerialState { PCIDevice dev; SerialState state; uint8_t prog_if; } PCISerialState; =20 -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; - uint8_t prog_if; -} PCIMultiSerialState; - -static void multi_serial_pci_exit(PCIDevice *dev); =20 static void serial_pci_realize(PCIDevice *dev, Error **errp) { @@ -72,64 +58,6 @@ static void serial_pci_realize(PCIDevice *dev, Error **e= rrp) pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io); } =20 -static void multi_serial_irq_mux(void *opaque, int n, int level) -{ - PCIMultiSerialState *pci =3D opaque; - int i, pending =3D 0; - - pci->level[n] =3D level; - for (i =3D 0; i < pci->ports; i++) { - if (pci->level[i]) { - pending =3D 1; - } - } - pci_set_irq(&pci->dev, pending); -} - -static void multi_serial_pci_realize(PCIDevice *dev, Error **errp) -{ - PCIDeviceClass *pc =3D PCI_DEVICE_GET_CLASS(dev); - PCIMultiSerialState *pci =3D DO_UPCAST(PCIMultiSerialState, dev, dev); - SerialState *s; - Error *err =3D NULL; - int i, nr_ports =3D 0; - - switch (pc->device_id) { - case 0x0003: - nr_ports =3D 2; - break; - case 0x0004: - nr_ports =3D 4; - break; - } - assert(nr_ports > 0); - assert(nr_ports <=3D PCI_SERIAL_MAX_PORTS); - - pci->dev.config[PCI_CLASS_PROG] =3D pci->prog_if; - pci->dev.config[PCI_INTERRUPT_PIN] =3D 0x01; - memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * nr_por= ts); - pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar); - pci->irqs =3D qemu_allocate_irqs(multi_serial_irq_mux, pci, - nr_ports); - - for (i =3D 0; i < nr_ports; i++) { - s =3D pci->state + i; - s->baudbase =3D 115200; - serial_realize_core(s, &err); - if (err !=3D NULL) { - error_propagate(errp, err); - multi_serial_pci_exit(dev); - return; - } - s->irq =3D pci->irqs[i]; - pci->name[i] =3D g_strdup_printf("uart #%d", i+1); - memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, - pci->name[i], 8); - memory_region_add_subregion(&pci->iobar, 8 * i, &s->io); - pci->ports++; - } -} - static void serial_pci_exit(PCIDevice *dev) { PCISerialState *pci =3D DO_UPCAST(PCISerialState, dev, dev); @@ -139,21 +67,6 @@ static void serial_pci_exit(PCIDevice *dev) qemu_free_irq(s->irq); } =20 -static void multi_serial_pci_exit(PCIDevice *dev) -{ - PCIMultiSerialState *pci =3D DO_UPCAST(PCIMultiSerialState, dev, dev); - SerialState *s; - int i; - - for (i =3D 0; i < pci->ports; i++) { - s =3D pci->state + i; - serial_exit_core(s); - memory_region_del_subregion(&pci->iobar, &s->io); - g_free(pci->name[i]); - } - qemu_free_irqs(pci->irqs, pci->ports); -} - static const VMStateDescription vmstate_pci_serial =3D { .name =3D "pci-serial", .version_id =3D 1, @@ -165,41 +78,12 @@ static const VMStateDescription vmstate_pci_serial =3D= { } }; =20 -static const VMStateDescription vmstate_pci_multi_serial =3D { - .name =3D "pci-serial-multi", - .version_id =3D 1, - .minimum_version_id =3D 1, - .fields =3D (VMStateField[]) { - VMSTATE_PCI_DEVICE(dev, PCIMultiSerialState), - VMSTATE_STRUCT_ARRAY(state, PCIMultiSerialState, PCI_SERIAL_MAX_PO= RTS, - 0, vmstate_serial, SerialState), - VMSTATE_UINT32_ARRAY(level, PCIMultiSerialState, PCI_SERIAL_MAX_PO= RTS), - VMSTATE_END_OF_LIST() - } -}; - static Property serial_pci_properties[] =3D { DEFINE_PROP_CHR("chardev", PCISerialState, state.chr), DEFINE_PROP_UINT8("prog_if", PCISerialState, prog_if, 0x02), DEFINE_PROP_END_OF_LIST(), }; =20 -static Property multi_2x_serial_pci_properties[] =3D { - DEFINE_PROP_CHR("chardev1", PCIMultiSerialState, state[0].chr), - DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr), - DEFINE_PROP_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02), - DEFINE_PROP_END_OF_LIST(), -}; - -static Property multi_4x_serial_pci_properties[] =3D { - 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_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02), - DEFINE_PROP_END_OF_LIST(), -}; - static void serial_pci_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); @@ -215,36 +99,6 @@ static void serial_pci_class_initfn(ObjectClass *klass,= void *data) set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } =20 -static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *dat= a) -{ - DeviceClass *dc =3D DEVICE_CLASS(klass); - PCIDeviceClass *pc =3D PCI_DEVICE_CLASS(klass); - pc->realize =3D multi_serial_pci_realize; - pc->exit =3D multi_serial_pci_exit; - pc->vendor_id =3D PCI_VENDOR_ID_REDHAT; - pc->device_id =3D PCI_DEVICE_ID_REDHAT_SERIAL2; - pc->revision =3D 1; - pc->class_id =3D PCI_CLASS_COMMUNICATION_SERIAL; - dc->vmsd =3D &vmstate_pci_multi_serial; - dc->props =3D multi_2x_serial_pci_properties; - set_bit(DEVICE_CATEGORY_INPUT, dc->categories); -} - -static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *dat= a) -{ - DeviceClass *dc =3D DEVICE_CLASS(klass); - PCIDeviceClass *pc =3D PCI_DEVICE_CLASS(klass); - pc->realize =3D multi_serial_pci_realize; - pc->exit =3D multi_serial_pci_exit; - pc->vendor_id =3D PCI_VENDOR_ID_REDHAT; - pc->device_id =3D PCI_DEVICE_ID_REDHAT_SERIAL4; - pc->revision =3D 1; - pc->class_id =3D PCI_CLASS_COMMUNICATION_SERIAL; - dc->vmsd =3D &vmstate_pci_multi_serial; - dc->props =3D multi_4x_serial_pci_properties; - set_bit(DEVICE_CATEGORY_INPUT, dc->categories); -} - static const TypeInfo serial_pci_info =3D { .name =3D "pci-serial", .parent =3D TYPE_PCI_DEVICE, @@ -256,33 +110,9 @@ static const TypeInfo serial_pci_info =3D { }, }; =20 -static const TypeInfo multi_2x_serial_pci_info =3D { - .name =3D "pci-serial-2x", - .parent =3D TYPE_PCI_DEVICE, - .instance_size =3D sizeof(PCIMultiSerialState), - .class_init =3D multi_2x_serial_pci_class_initfn, - .interfaces =3D (InterfaceInfo[]) { - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { }, - }, -}; - -static const TypeInfo multi_4x_serial_pci_info =3D { - .name =3D "pci-serial-4x", - .parent =3D TYPE_PCI_DEVICE, - .instance_size =3D sizeof(PCIMultiSerialState), - .class_init =3D multi_4x_serial_pci_class_initfn, - .interfaces =3D (InterfaceInfo[]) { - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { }, - }, -}; - 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); } =20 type_init(serial_pci_register_types) --=20 1.8.3.1