i8254: Factor out interface header
[qemu/ar7.git] / hw / i82378.c
blobd3c4ac5f72b9750eb6c2af948621392e56436fa5
1 /*
2 * QEMU Intel i82378 emulation (PCI to ISA bridge)
4 * Copyright (c) 2010-2011 Hervé Poussineau
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include "pci.h"
21 #include "pc.h"
22 #include "i8254.h"
24 //#define DEBUG_I82378
26 #ifdef DEBUG_I82378
27 #define DPRINTF(fmt, ...) \
28 do { fprintf(stderr, "i82378: " fmt , ## __VA_ARGS__); } while (0)
29 #else
30 #define DPRINTF(fmt, ...) \
31 do {} while (0)
32 #endif
34 #define BADF(fmt, ...) \
35 do { fprintf(stderr, "i82378 ERROR: " fmt , ## __VA_ARGS__); } while (0)
37 typedef struct I82378State {
38 qemu_irq out[2];
39 qemu_irq *i8259;
40 MemoryRegion io;
41 MemoryRegion mem;
42 } I82378State;
44 typedef struct PCIi82378State {
45 PCIDevice pci_dev;
46 uint32_t isa_io_base;
47 uint32_t isa_mem_base;
48 I82378State state;
49 } PCIi82378State;
51 static const VMStateDescription vmstate_pci_i82378 = {
52 .name = "pci-i82378",
53 .version_id = 0,
54 .minimum_version_id = 0,
55 .fields = (VMStateField[]) {
56 VMSTATE_PCI_DEVICE(pci_dev, PCIi82378State),
57 VMSTATE_END_OF_LIST()
61 static void i82378_io_write(void *opaque, target_phys_addr_t addr,
62 uint64_t value, unsigned int size)
64 switch (size) {
65 case 1:
66 DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__,
67 addr, value);
68 cpu_outb(addr, value);
69 break;
70 case 2:
71 DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__,
72 addr, value);
73 cpu_outw(addr, value);
74 break;
75 case 4:
76 DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__,
77 addr, value);
78 cpu_outl(addr, value);
79 break;
80 default:
81 abort();
85 static uint64_t i82378_io_read(void *opaque, target_phys_addr_t addr,
86 unsigned int size)
88 DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
89 switch (size) {
90 case 1:
91 return cpu_inb(addr);
92 case 2:
93 return cpu_inw(addr);
94 case 4:
95 return cpu_inl(addr);
96 default:
97 abort();
101 static const MemoryRegionOps i82378_io_ops = {
102 .read = i82378_io_read,
103 .write = i82378_io_write,
104 .endianness = DEVICE_LITTLE_ENDIAN,
107 static void i82378_mem_write(void *opaque, target_phys_addr_t addr,
108 uint64_t value, unsigned int size)
110 switch (size) {
111 case 1:
112 DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__,
113 addr, value);
114 cpu_outb(addr, value);
115 break;
116 case 2:
117 DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__,
118 addr, value);
119 cpu_outw(addr, value);
120 break;
121 case 4:
122 DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__,
123 addr, value);
124 cpu_outl(addr, value);
125 break;
126 default:
127 abort();
131 static uint64_t i82378_mem_read(void *opaque, target_phys_addr_t addr,
132 unsigned int size)
134 DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
135 switch (size) {
136 case 1:
137 return cpu_inb(addr);
138 case 2:
139 return cpu_inw(addr);
140 case 4:
141 return cpu_inl(addr);
142 default:
143 abort();
147 static const MemoryRegionOps i82378_mem_ops = {
148 .read = i82378_mem_read,
149 .write = i82378_mem_write,
150 .endianness = DEVICE_LITTLE_ENDIAN,
153 static void i82378_request_out0_irq(void *opaque, int irq, int level)
155 I82378State *s = opaque;
156 qemu_set_irq(s->out[0], level);
159 static void i82378_request_pic_irq(void *opaque, int irq, int level)
161 DeviceState *dev = opaque;
162 PCIDevice *pci = DO_UPCAST(PCIDevice, qdev, dev);
163 PCIi82378State *s = DO_UPCAST(PCIi82378State, pci_dev, pci);
165 qemu_set_irq(s->state.i8259[irq], level);
168 static void i82378_init(DeviceState *dev, I82378State *s)
170 ISABus *isabus = DO_UPCAST(ISABus, qbus, qdev_get_child_bus(dev, "isa.0"));
171 ISADevice *pit;
172 qemu_irq *out0_irq;
174 /* This device has:
175 2 82C59 (irq)
176 1 82C54 (pit)
177 2 82C37 (dma)
179 Utility Bus Support Registers
181 All devices accept byte access only, except timer
184 qdev_init_gpio_out(dev, s->out, 2);
185 qdev_init_gpio_in(dev, i82378_request_pic_irq, 16);
187 /* Workaround the fact that i8259 is not qdev'ified... */
188 out0_irq = qemu_allocate_irqs(i82378_request_out0_irq, s, 1);
190 /* 2 82C59 (irq) */
191 s->i8259 = i8259_init(isabus, *out0_irq);
192 isa_bus_irqs(isabus, s->i8259);
194 /* 1 82C54 (pit) */
195 pit = pit_init(isabus, 0x40, 0);
197 /* speaker */
198 pcspk_init(pit);
200 /* 2 82C37 (dma) */
201 DMA_init(1, &s->out[1]);
202 isa_create_simple(isabus, "i82374");
204 /* timer */
205 isa_create_simple(isabus, "mc146818rtc");
208 static int pci_i82378_init(PCIDevice *dev)
210 PCIi82378State *pci = DO_UPCAST(PCIi82378State, pci_dev, dev);
211 I82378State *s = &pci->state;
212 uint8_t *pci_conf;
214 pci_conf = dev->config;
215 pci_set_word(pci_conf + PCI_COMMAND,
216 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
217 pci_set_word(pci_conf + PCI_STATUS,
218 PCI_STATUS_DEVSEL_MEDIUM);
220 pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */
222 memory_region_init_io(&s->io, &i82378_io_ops, s, "i82378-io", 0x00010000);
223 pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io);
225 memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000);
226 memory_region_set_coalescing(&s->mem);
227 pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
229 /* Make I/O address read only */
230 pci_set_word(dev->wmask + PCI_COMMAND, PCI_COMMAND_SPECIAL);
231 pci_set_long(dev->wmask + PCI_BASE_ADDRESS_0, 0);
232 pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, pci->isa_io_base);
234 isa_mem_base = pci->isa_mem_base;
235 isa_bus_new(&dev->qdev, pci_address_space_io(dev));
237 i82378_init(&dev->qdev, s);
239 return 0;
242 static Property i82378_properties[] = {
243 DEFINE_PROP_HEX32("iobase", PCIi82378State, isa_io_base, 0x80000000),
244 DEFINE_PROP_HEX32("membase", PCIi82378State, isa_mem_base, 0xc0000000),
245 DEFINE_PROP_END_OF_LIST()
248 static void pci_i82378_class_init(ObjectClass *klass, void *data)
250 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
251 DeviceClass *dc = DEVICE_CLASS(klass);
253 k->init = pci_i82378_init;
254 k->vendor_id = PCI_VENDOR_ID_INTEL;
255 k->device_id = PCI_DEVICE_ID_INTEL_82378;
256 k->revision = 0x03;
257 k->class_id = PCI_CLASS_BRIDGE_ISA;
258 k->subsystem_vendor_id = 0x0;
259 k->subsystem_id = 0x0;
260 dc->vmsd = &vmstate_pci_i82378;
261 dc->props = i82378_properties;
264 static TypeInfo pci_i82378_info = {
265 .name = "i82378",
266 .parent = TYPE_PCI_DEVICE,
267 .instance_size = sizeof(PCIi82378State),
268 .class_init = pci_i82378_class_init,
271 static void i82378_register_types(void)
273 type_register_static(&pci_i82378_info);
276 type_init(i82378_register_types)