xref: /openbmc/qemu/hw/char/serial-pci.c (revision d328fef93ae757a0dd65ed786a4086e27952eef3)
1  /*
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  
26  /* see docs/specs/pci-serial.rst */
27  
28  #include "qemu/osdep.h"
29  #include "qapi/error.h"
30  #include "qemu/module.h"
31  #include "hw/char/serial.h"
32  #include "hw/irq.h"
33  #include "hw/pci/pci_device.h"
34  #include "hw/qdev-properties.h"
35  #include "migration/vmstate.h"
36  #include "qom/object.h"
37  
38  struct PCISerialState {
39      PCIDevice dev;
40      SerialState state;
41      uint8_t prog_if;
42  };
43  
44  #define TYPE_PCI_SERIAL "pci-serial"
OBJECT_DECLARE_SIMPLE_TYPE(PCISerialState,PCI_SERIAL)45  OBJECT_DECLARE_SIMPLE_TYPE(PCISerialState, PCI_SERIAL)
46  
47  static void serial_pci_realize(PCIDevice *dev, Error **errp)
48  {
49      PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
50      SerialState *s = &pci->state;
51  
52      if (!qdev_realize(DEVICE(s), NULL, errp)) {
53          return;
54      }
55  
56      pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
57      pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
58      s->irq = pci_allocate_irq(&pci->dev);
59  
60      memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8);
61      pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
62  }
63  
serial_pci_exit(PCIDevice * dev)64  static void serial_pci_exit(PCIDevice *dev)
65  {
66      PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
67      SerialState *s = &pci->state;
68  
69      qdev_unrealize(DEVICE(s));
70      qemu_free_irq(s->irq);
71  }
72  
73  static const VMStateDescription vmstate_pci_serial = {
74      .name = "pci-serial",
75      .version_id = 1,
76      .minimum_version_id = 1,
77      .fields = (const VMStateField[]) {
78          VMSTATE_PCI_DEVICE(dev, PCISerialState),
79          VMSTATE_STRUCT(state, PCISerialState, 0, vmstate_serial, SerialState),
80          VMSTATE_END_OF_LIST()
81      }
82  };
83  
84  static Property serial_pci_properties[] = {
85      DEFINE_PROP_UINT8("prog_if",  PCISerialState, prog_if, 0x02),
86      DEFINE_PROP_END_OF_LIST(),
87  };
88  
serial_pci_class_initfn(ObjectClass * klass,void * data)89  static void serial_pci_class_initfn(ObjectClass *klass, void *data)
90  {
91      DeviceClass *dc = DEVICE_CLASS(klass);
92      PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
93      pc->realize = serial_pci_realize;
94      pc->exit = serial_pci_exit;
95      pc->vendor_id = PCI_VENDOR_ID_REDHAT;
96      pc->device_id = PCI_DEVICE_ID_REDHAT_SERIAL;
97      pc->revision = 1;
98      pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
99      dc->vmsd = &vmstate_pci_serial;
100      device_class_set_props(dc, serial_pci_properties);
101      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
102  }
103  
serial_pci_init(Object * o)104  static void serial_pci_init(Object *o)
105  {
106      PCISerialState *ps = PCI_SERIAL(o);
107  
108      object_initialize_child(o, "serial", &ps->state, TYPE_SERIAL);
109  
110      qdev_alias_all_properties(DEVICE(&ps->state), o);
111  }
112  
113  static const TypeInfo serial_pci_info = {
114      .name          = TYPE_PCI_SERIAL,
115      .parent        = TYPE_PCI_DEVICE,
116      .instance_size = sizeof(PCISerialState),
117      .instance_init = serial_pci_init,
118      .class_init    = serial_pci_class_initfn,
119      .interfaces = (InterfaceInfo[]) {
120          { INTERFACE_CONVENTIONAL_PCI_DEVICE },
121          { },
122      },
123  };
124  
serial_pci_register_types(void)125  static void serial_pci_register_types(void)
126  {
127      type_register_static(&serial_pci_info);
128  }
129  
130  type_init(serial_pci_register_types)
131