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 | #include "qemu/osdep.h" |
27 | #include "qapi/error.h" |
28 | #include "qemu/module.h" |
29 | #include "sysemu/sysemu.h" |
30 | #include "hw/char/serial.h" |
31 | #include "hw/isa/isa.h" |
32 | #include "hw/qdev-properties.h" |
33 | #include "migration/vmstate.h" |
34 | |
35 | #define ISA_SERIAL(obj) OBJECT_CHECK(ISASerialState, (obj), TYPE_ISA_SERIAL) |
36 | |
37 | typedef struct ISASerialState { |
38 | ISADevice parent_obj; |
39 | |
40 | uint32_t index; |
41 | uint32_t iobase; |
42 | uint32_t isairq; |
43 | SerialState state; |
44 | } ISASerialState; |
45 | |
46 | static const int isa_serial_io[MAX_ISA_SERIAL_PORTS] = { |
47 | 0x3f8, 0x2f8, 0x3e8, 0x2e8 |
48 | }; |
49 | static const int isa_serial_irq[MAX_ISA_SERIAL_PORTS] = { |
50 | 4, 3, 4, 3 |
51 | }; |
52 | |
53 | static void serial_isa_realizefn(DeviceState *dev, Error **errp) |
54 | { |
55 | static int index; |
56 | ISADevice *isadev = ISA_DEVICE(dev); |
57 | ISASerialState *isa = ISA_SERIAL(dev); |
58 | SerialState *s = &isa->state; |
59 | |
60 | if (isa->index == -1) { |
61 | isa->index = index; |
62 | } |
63 | if (isa->index >= MAX_ISA_SERIAL_PORTS) { |
64 | error_setg(errp, "Max. supported number of ISA serial ports is %d." , |
65 | MAX_ISA_SERIAL_PORTS); |
66 | return; |
67 | } |
68 | if (isa->iobase == -1) { |
69 | isa->iobase = isa_serial_io[isa->index]; |
70 | } |
71 | if (isa->isairq == -1) { |
72 | isa->isairq = isa_serial_irq[isa->index]; |
73 | } |
74 | index++; |
75 | |
76 | s->baudbase = 115200; |
77 | isa_init_irq(isadev, &s->irq, isa->isairq); |
78 | serial_realize_core(s, errp); |
79 | qdev_set_legacy_instance_id(dev, isa->iobase, 3); |
80 | |
81 | memory_region_init_io(&s->io, OBJECT(isa), &serial_io_ops, s, "serial" , 8); |
82 | isa_register_ioport(isadev, &s->io, isa->iobase); |
83 | } |
84 | |
85 | static const VMStateDescription vmstate_isa_serial = { |
86 | .name = "serial" , |
87 | .version_id = 3, |
88 | .minimum_version_id = 2, |
89 | .fields = (VMStateField[]) { |
90 | VMSTATE_STRUCT(state, ISASerialState, 0, vmstate_serial, SerialState), |
91 | VMSTATE_END_OF_LIST() |
92 | } |
93 | }; |
94 | |
95 | static Property serial_isa_properties[] = { |
96 | DEFINE_PROP_UINT32("index" , ISASerialState, index, -1), |
97 | DEFINE_PROP_UINT32("iobase" , ISASerialState, iobase, -1), |
98 | DEFINE_PROP_UINT32("irq" , ISASerialState, isairq, -1), |
99 | DEFINE_PROP_CHR("chardev" , ISASerialState, state.chr), |
100 | DEFINE_PROP_UINT32("wakeup" , ISASerialState, state.wakeup, 0), |
101 | DEFINE_PROP_END_OF_LIST(), |
102 | }; |
103 | |
104 | static void serial_isa_class_initfn(ObjectClass *klass, void *data) |
105 | { |
106 | DeviceClass *dc = DEVICE_CLASS(klass); |
107 | |
108 | dc->realize = serial_isa_realizefn; |
109 | dc->vmsd = &vmstate_isa_serial; |
110 | dc->props = serial_isa_properties; |
111 | set_bit(DEVICE_CATEGORY_INPUT, dc->categories); |
112 | } |
113 | |
114 | static const TypeInfo serial_isa_info = { |
115 | .name = TYPE_ISA_SERIAL, |
116 | .parent = TYPE_ISA_DEVICE, |
117 | .instance_size = sizeof(ISASerialState), |
118 | .class_init = serial_isa_class_initfn, |
119 | }; |
120 | |
121 | static void serial_register_types(void) |
122 | { |
123 | type_register_static(&serial_isa_info); |
124 | } |
125 | |
126 | type_init(serial_register_types) |
127 | |
128 | static void serial_isa_init(ISABus *bus, int index, Chardev *chr) |
129 | { |
130 | DeviceState *dev; |
131 | ISADevice *isadev; |
132 | |
133 | isadev = isa_create(bus, TYPE_ISA_SERIAL); |
134 | dev = DEVICE(isadev); |
135 | qdev_prop_set_uint32(dev, "index" , index); |
136 | qdev_prop_set_chr(dev, "chardev" , chr); |
137 | qdev_init_nofail(dev); |
138 | } |
139 | |
140 | void serial_hds_isa_init(ISABus *bus, int from, int to) |
141 | { |
142 | int i; |
143 | |
144 | assert(from >= 0); |
145 | assert(to <= MAX_ISA_SERIAL_PORTS); |
146 | |
147 | for (i = from; i < to; ++i) { |
148 | if (serial_hd(i)) { |
149 | serial_isa_init(bus, i, serial_hd(i)); |
150 | } |
151 | } |
152 | } |
153 | |