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/>.
25 //#define DEBUG_I82378
28 #define DPRINTF(fmt, ...) \
29 do { fprintf(stderr, "i82378: " fmt , ## __VA_ARGS__); } while (0)
31 #define DPRINTF(fmt, ...) \
35 #define BADF(fmt, ...) \
36 do { fprintf(stderr, "i82378 ERROR: " fmt , ## __VA_ARGS__); } while (0)
38 typedef struct I82378State
{
45 typedef struct PCIi82378State
{
48 uint32_t isa_mem_base
;
52 static const VMStateDescription vmstate_pci_i82378
= {
55 .minimum_version_id
= 0,
56 .fields
= (VMStateField
[]) {
57 VMSTATE_PCI_DEVICE(pci_dev
, PCIi82378State
),
62 static void i82378_io_write(void *opaque
, target_phys_addr_t addr
,
63 uint64_t value
, unsigned int size
)
67 DPRINTF("%s: " TARGET_FMT_plx
"=%02" PRIx64
"\n", __func__
,
69 cpu_outb(addr
, value
);
72 DPRINTF("%s: " TARGET_FMT_plx
"=%04" PRIx64
"\n", __func__
,
74 cpu_outw(addr
, value
);
77 DPRINTF("%s: " TARGET_FMT_plx
"=%08" PRIx64
"\n", __func__
,
79 cpu_outl(addr
, value
);
86 static uint64_t i82378_io_read(void *opaque
, target_phys_addr_t addr
,
89 DPRINTF("%s: " TARGET_FMT_plx
"\n", __func__
, addr
);
102 static const MemoryRegionOps i82378_io_ops
= {
103 .read
= i82378_io_read
,
104 .write
= i82378_io_write
,
105 .endianness
= DEVICE_LITTLE_ENDIAN
,
108 static void i82378_mem_write(void *opaque
, target_phys_addr_t addr
,
109 uint64_t value
, unsigned int size
)
113 DPRINTF("%s: " TARGET_FMT_plx
"=%02" PRIx64
"\n", __func__
,
115 cpu_outb(addr
, value
);
118 DPRINTF("%s: " TARGET_FMT_plx
"=%04" PRIx64
"\n", __func__
,
120 cpu_outw(addr
, value
);
123 DPRINTF("%s: " TARGET_FMT_plx
"=%08" PRIx64
"\n", __func__
,
125 cpu_outl(addr
, value
);
132 static uint64_t i82378_mem_read(void *opaque
, target_phys_addr_t addr
,
135 DPRINTF("%s: " TARGET_FMT_plx
"\n", __func__
, addr
);
138 return cpu_inb(addr
);
140 return cpu_inw(addr
);
142 return cpu_inl(addr
);
148 static const MemoryRegionOps i82378_mem_ops
= {
149 .read
= i82378_mem_read
,
150 .write
= i82378_mem_write
,
151 .endianness
= DEVICE_LITTLE_ENDIAN
,
154 static void i82378_request_out0_irq(void *opaque
, int irq
, int level
)
156 I82378State
*s
= opaque
;
157 qemu_set_irq(s
->out
[0], level
);
160 static void i82378_request_pic_irq(void *opaque
, int irq
, int level
)
162 DeviceState
*dev
= opaque
;
163 PCIDevice
*pci
= DO_UPCAST(PCIDevice
, qdev
, dev
);
164 PCIi82378State
*s
= DO_UPCAST(PCIi82378State
, pci_dev
, pci
);
166 qemu_set_irq(s
->state
.i8259
[irq
], level
);
169 static void i82378_init(DeviceState
*dev
, I82378State
*s
)
171 ISABus
*isabus
= DO_UPCAST(ISABus
, qbus
, qdev_get_child_bus(dev
, "isa.0"));
181 Utility Bus Support Registers
183 All devices accept byte access only, except timer
186 qdev_init_gpio_out(dev
, s
->out
, 2);
187 qdev_init_gpio_in(dev
, i82378_request_pic_irq
, 16);
189 /* Workaround the fact that i8259 is not qdev'ified... */
190 out0_irq
= qemu_allocate_irqs(i82378_request_out0_irq
, s
, 1);
193 s
->i8259
= i8259_init(isabus
, *out0_irq
);
194 isa_bus_irqs(isabus
, s
->i8259
);
197 pit
= pit_init(isabus
, 0x40, 0, NULL
);
200 pcspk_init(isabus
, pit
);
203 isa
= isa_create_simple(isabus
, "i82374");
204 qdev_connect_gpio_out(&isa
->qdev
, 0, s
->out
[1]);
207 isa_create_simple(isabus
, "mc146818rtc");
210 static int pci_i82378_init(PCIDevice
*dev
)
212 PCIi82378State
*pci
= DO_UPCAST(PCIi82378State
, pci_dev
, dev
);
213 I82378State
*s
= &pci
->state
;
216 pci_conf
= dev
->config
;
217 pci_set_word(pci_conf
+ PCI_COMMAND
,
218 PCI_COMMAND_IO
| PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
);
219 pci_set_word(pci_conf
+ PCI_STATUS
,
220 PCI_STATUS_DEVSEL_MEDIUM
);
222 pci_conf
[PCI_INTERRUPT_PIN
] = 1; /* interrupt pin 0 */
224 memory_region_init_io(&s
->io
, &i82378_io_ops
, s
, "i82378-io", 0x00010000);
225 pci_register_bar(dev
, 0, PCI_BASE_ADDRESS_SPACE_MEMORY
, &s
->io
);
227 memory_region_init_io(&s
->mem
, &i82378_mem_ops
, s
, "i82378-mem", 0x01000000);
228 pci_register_bar(dev
, 1, PCI_BASE_ADDRESS_SPACE_MEMORY
, &s
->mem
);
230 /* Make I/O address read only */
231 pci_set_word(dev
->wmask
+ PCI_COMMAND
, PCI_COMMAND_SPECIAL
);
232 pci_set_long(dev
->wmask
+ PCI_BASE_ADDRESS_0
, 0);
233 pci_set_long(pci_conf
+ PCI_BASE_ADDRESS_0
, pci
->isa_io_base
);
235 isa_mem_base
= pci
->isa_mem_base
;
236 isa_bus_new(&dev
->qdev
, pci_address_space_io(dev
));
238 i82378_init(&dev
->qdev
, s
);
243 static Property i82378_properties
[] = {
244 DEFINE_PROP_HEX32("iobase", PCIi82378State
, isa_io_base
, 0x80000000),
245 DEFINE_PROP_HEX32("membase", PCIi82378State
, isa_mem_base
, 0xc0000000),
246 DEFINE_PROP_END_OF_LIST()
249 static void pci_i82378_class_init(ObjectClass
*klass
, void *data
)
251 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
252 DeviceClass
*dc
= DEVICE_CLASS(klass
);
254 k
->init
= pci_i82378_init
;
255 k
->vendor_id
= PCI_VENDOR_ID_INTEL
;
256 k
->device_id
= PCI_DEVICE_ID_INTEL_82378
;
258 k
->class_id
= PCI_CLASS_BRIDGE_ISA
;
259 k
->subsystem_vendor_id
= 0x0;
260 k
->subsystem_id
= 0x0;
261 dc
->vmsd
= &vmstate_pci_i82378
;
262 dc
->props
= i82378_properties
;
265 static TypeInfo pci_i82378_info
= {
267 .parent
= TYPE_PCI_DEVICE
,
268 .instance_size
= sizeof(PCIi82378State
),
269 .class_init
= pci_i82378_class_init
,
272 static void i82378_register_types(void)
274 type_register_static(&pci_i82378_info
);
277 type_init(i82378_register_types
)