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/>.
24 //#define DEBUG_I82378
27 #define DPRINTF(fmt, ...) \
28 do { fprintf(stderr, "i82378: " fmt , ## __VA_ARGS__); } while (0)
30 #define DPRINTF(fmt, ...) \
34 #define BADF(fmt, ...) \
35 do { fprintf(stderr, "i82378 ERROR: " fmt , ## __VA_ARGS__); } while (0)
37 typedef struct I82378State
{
44 typedef struct PCIi82378State
{
47 uint32_t isa_mem_base
;
51 static const VMStateDescription vmstate_pci_i82378
= {
54 .minimum_version_id
= 0,
55 .fields
= (VMStateField
[]) {
56 VMSTATE_PCI_DEVICE(pci_dev
, PCIi82378State
),
61 static void i82378_io_write(void *opaque
, target_phys_addr_t addr
,
62 uint64_t value
, unsigned int size
)
66 DPRINTF("%s: " TARGET_FMT_plx
"=%02" PRIx64
"\n", __func__
,
68 cpu_outb(addr
, value
);
71 DPRINTF("%s: " TARGET_FMT_plx
"=%04" PRIx64
"\n", __func__
,
73 cpu_outw(addr
, value
);
76 DPRINTF("%s: " TARGET_FMT_plx
"=%08" PRIx64
"\n", __func__
,
78 cpu_outl(addr
, value
);
85 static uint64_t i82378_io_read(void *opaque
, target_phys_addr_t addr
,
88 DPRINTF("%s: " TARGET_FMT_plx
"\n", __func__
, addr
);
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
)
112 DPRINTF("%s: " TARGET_FMT_plx
"=%02" PRIx64
"\n", __func__
,
114 cpu_outb(addr
, value
);
117 DPRINTF("%s: " TARGET_FMT_plx
"=%04" PRIx64
"\n", __func__
,
119 cpu_outw(addr
, value
);
122 DPRINTF("%s: " TARGET_FMT_plx
"=%08" PRIx64
"\n", __func__
,
124 cpu_outl(addr
, value
);
131 static uint64_t i82378_mem_read(void *opaque
, target_phys_addr_t addr
,
134 DPRINTF("%s: " TARGET_FMT_plx
"\n", __func__
, addr
);
137 return cpu_inb(addr
);
139 return cpu_inw(addr
);
141 return cpu_inl(addr
);
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"));
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);
191 s
->i8259
= i8259_init(isabus
, *out0_irq
);
192 isa_bus_irqs(isabus
, s
->i8259
);
195 pit
= pit_init(isabus
, 0x40, 0);
201 DMA_init(1, &s
->out
[1]);
202 isa_create_simple(isabus
, "i82374");
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
;
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
);
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
;
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
= {
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
)