blob: cd56924a4393f7fefc82b37ecd89172fbf0d83ea [file] [log] [blame]
Gerd Hoffmann419ad672012-10-17 09:54:20 +02001/*
2 * QEMU 16550A UART emulation
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 * Copyright (c) 2008 Citrix Systems, Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
Gerd Hoffmann90734e02012-10-17 09:54:23 +020026/* see docs/specs/pci-serial.txt */
27
Peter Maydellb6a0aa02016-01-26 18:17:03 +000028#include "qemu/osdep.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010029#include "qapi/error.h"
Markus Armbruster0b8fa322019-05-23 16:35:07 +020030#include "qemu/module.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010031#include "hw/char/serial.h"
Markus Armbruster64552b62019-08-12 07:23:42 +020032#include "hw/irq.h"
Paolo Bonzini83c9f4c2013-02-04 15:40:22 +010033#include "hw/pci/pci.h"
Markus Armbrustera27bd6c2019-08-12 07:23:51 +020034#include "hw/qdev-properties.h"
Markus Armbrusterd6454272019-08-12 07:23:45 +020035#include "migration/vmstate.h"
Gerd Hoffmann419ad672012-10-17 09:54:20 +020036
37typedef struct PCISerialState {
38 PCIDevice dev;
39 SerialState state;
BALATON Zoltan13cc2c32014-02-27 02:05:05 +010040 uint8_t prog_if;
Gerd Hoffmann419ad672012-10-17 09:54:20 +020041} PCISerialState;
42
Marc-André Lureau7781b882019-10-21 23:32:12 +020043#define TYPE_PCI_SERIAL "pci-serial"
44#define PCI_SERIAL(s) OBJECT_CHECK(PCISerialState, (s), TYPE_PCI_SERIAL)
Gerd Hoffmanna48da7b2015-05-06 12:58:19 +020045
Markus Armbruster28d85902015-01-19 15:52:33 +010046static void serial_pci_realize(PCIDevice *dev, Error **errp)
Gerd Hoffmann419ad672012-10-17 09:54:20 +020047{
48 PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
49 SerialState *s = &pci->state;
50
Markus Armbruster668f62e2020-07-07 18:06:02 +020051 if (!qdev_realize(DEVICE(s), NULL, errp)) {
Markus Armbruster28d85902015-01-19 15:52:33 +010052 return;
Andreas Färberdb895a12012-11-25 02:37:14 +010053 }
Gerd Hoffmann419ad672012-10-17 09:54:20 +020054
BALATON Zoltan13cc2c32014-02-27 02:05:05 +010055 pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
Gerd Hoffmann419ad672012-10-17 09:54:20 +020056 pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
Marcel Apfelbaum9e64f8a2013-10-07 10:36:39 +030057 s->irq = pci_allocate_irq(&pci->dev);
Gerd Hoffmann419ad672012-10-17 09:54:20 +020058
Paolo Bonzini300b1fc2013-06-06 21:25:08 -040059 memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8);
Gerd Hoffmann419ad672012-10-17 09:54:20 +020060 pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
Gerd Hoffmann419ad672012-10-17 09:54:20 +020061}
62
63static void serial_pci_exit(PCIDevice *dev)
64{
65 PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
66 SerialState *s = &pci->state;
67
Markus Armbruster981c3dc2020-06-10 07:31:56 +020068 qdev_unrealize(DEVICE(s));
Marcel Apfelbaum9e64f8a2013-10-07 10:36:39 +030069 qemu_free_irq(s->irq);
Gerd Hoffmann419ad672012-10-17 09:54:20 +020070}
71
72static const VMStateDescription vmstate_pci_serial = {
73 .name = "pci-serial",
74 .version_id = 1,
75 .minimum_version_id = 1,
Juan Quintelad49805a2014-04-16 15:32:32 +020076 .fields = (VMStateField[]) {
Gerd Hoffmann419ad672012-10-17 09:54:20 +020077 VMSTATE_PCI_DEVICE(dev, PCISerialState),
78 VMSTATE_STRUCT(state, PCISerialState, 0, vmstate_serial, SerialState),
79 VMSTATE_END_OF_LIST()
80 }
81};
82
83static Property serial_pci_properties[] = {
84 DEFINE_PROP_CHR("chardev", PCISerialState, state.chr),
BALATON Zoltan13cc2c32014-02-27 02:05:05 +010085 DEFINE_PROP_UINT8("prog_if", PCISerialState, prog_if, 0x02),
Gerd Hoffmann419ad672012-10-17 09:54:20 +020086 DEFINE_PROP_END_OF_LIST(),
87};
88
89static void serial_pci_class_initfn(ObjectClass *klass, void *data)
90{
91 DeviceClass *dc = DEVICE_CLASS(klass);
92 PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
Markus Armbruster28d85902015-01-19 15:52:33 +010093 pc->realize = serial_pci_realize;
Gerd Hoffmann419ad672012-10-17 09:54:20 +020094 pc->exit = serial_pci_exit;
Paolo Bonzini5c03a252012-12-13 10:19:38 +010095 pc->vendor_id = PCI_VENDOR_ID_REDHAT;
96 pc->device_id = PCI_DEVICE_ID_REDHAT_SERIAL;
Gerd Hoffmann419ad672012-10-17 09:54:20 +020097 pc->revision = 1;
98 pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
99 dc->vmsd = &vmstate_pci_serial;
Marc-André Lureau4f67d302020-01-10 19:30:32 +0400100 device_class_set_props(dc, serial_pci_properties);
Marcel Apfelbaum125ee0e2013-07-29 17:17:45 +0300101 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
Gerd Hoffmann419ad672012-10-17 09:54:20 +0200102}
103
Marc-André Lureau7781b882019-10-21 23:32:12 +0200104static void serial_pci_init(Object *o)
105{
106 PCISerialState *ps = PCI_SERIAL(o);
107
Markus Armbruster9fc7fc42020-06-10 07:32:25 +0200108 object_initialize_child(o, "serial", &ps->state, TYPE_SERIAL);
Marc-André Lureau7781b882019-10-21 23:32:12 +0200109}
110
Andreas Färber8c43a6f2013-01-10 16:19:07 +0100111static const TypeInfo serial_pci_info = {
Marc-André Lureau7781b882019-10-21 23:32:12 +0200112 .name = TYPE_PCI_SERIAL,
Gerd Hoffmann419ad672012-10-17 09:54:20 +0200113 .parent = TYPE_PCI_DEVICE,
114 .instance_size = sizeof(PCISerialState),
Marc-André Lureau7781b882019-10-21 23:32:12 +0200115 .instance_init = serial_pci_init,
Gerd Hoffmann419ad672012-10-17 09:54:20 +0200116 .class_init = serial_pci_class_initfn,
Eduardo Habkostfd3b02c2017-09-27 16:56:34 -0300117 .interfaces = (InterfaceInfo[]) {
118 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
119 { },
120 },
Gerd Hoffmann419ad672012-10-17 09:54:20 +0200121};
122
123static void serial_pci_register_types(void)
124{
125 type_register_static(&serial_pci_info);
Gerd Hoffmann419ad672012-10-17 09:54:20 +0200126}
127
128type_init(serial_pci_register_types)