mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 02:24:58 -06:00
hw: move target-independent files to subdirectories
This patch tackles all files that are compiled once, moving them to subdirectories of hw/. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
ce3b494cb5
commit
49ab747f66
227 changed files with 205 additions and 208 deletions
|
@ -0,0 +1,7 @@
|
|||
common-obj-y += isa-bus.o
|
||||
common-obj-$(CONFIG_APM) += apm.o
|
||||
common-obj-$(CONFIG_I82378) += i82378.o
|
||||
common-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
|
||||
common-obj-$(CONFIG_PC87312) += pc87312.o
|
||||
common-obj-$(CONFIG_PIIX4) += piix4.o
|
||||
|
102
hw/isa/apm.c
Normal file
102
hw/isa/apm.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* QEMU PC APM controller Emulation
|
||||
* This is split out from acpi.c
|
||||
*
|
||||
* Copyright (c) 2006 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
* Contributions after 2012-01-13 are licensed under the terms of the
|
||||
* GNU GPL, version 2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "hw/isa/apm.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/pci/pci.h"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define APM_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
|
||||
#else
|
||||
# define APM_DPRINTF(format, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
/* fixed I/O location */
|
||||
#define APM_CNT_IOPORT 0xb2
|
||||
#define APM_STS_IOPORT 0xb3
|
||||
|
||||
static void apm_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
|
||||
unsigned size)
|
||||
{
|
||||
APMState *apm = opaque;
|
||||
addr &= 1;
|
||||
APM_DPRINTF("apm_ioport_writeb addr=0x%x val=0x%02x\n", addr, val);
|
||||
if (addr == 0) {
|
||||
apm->apmc = val;
|
||||
|
||||
if (apm->callback) {
|
||||
(apm->callback)(val, apm->arg);
|
||||
}
|
||||
} else {
|
||||
apm->apms = val;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t apm_ioport_readb(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
APMState *apm = opaque;
|
||||
uint32_t val;
|
||||
|
||||
addr &= 1;
|
||||
if (addr == 0) {
|
||||
val = apm->apmc;
|
||||
} else {
|
||||
val = apm->apms;
|
||||
}
|
||||
APM_DPRINTF("apm_ioport_readb addr=0x%x val=0x%02x\n", addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
const VMStateDescription vmstate_apm = {
|
||||
.name = "APM State",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT8(apmc, APMState),
|
||||
VMSTATE_UINT8(apms, APMState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const MemoryRegionOps apm_ops = {
|
||||
.read = apm_ioport_readb,
|
||||
.write = apm_ioport_writeb,
|
||||
.impl = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 1,
|
||||
},
|
||||
};
|
||||
|
||||
void apm_init(PCIDevice *dev, APMState *apm, apm_ctrl_changed_t callback,
|
||||
void *arg)
|
||||
{
|
||||
apm->callback = callback;
|
||||
apm->arg = arg;
|
||||
|
||||
/* ioport 0xb2, 0xb3 */
|
||||
memory_region_init_io(&apm->io, &apm_ops, apm, "apm-io", 2);
|
||||
memory_region_add_subregion(pci_address_space_io(dev), APM_CNT_IOPORT,
|
||||
&apm->io);
|
||||
}
|
277
hw/isa/i82378.c
Normal file
277
hw/isa/i82378.c
Normal file
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* QEMU Intel i82378 emulation (PCI to ISA bridge)
|
||||
*
|
||||
* Copyright (c) 2010-2011 Hervé Poussineau
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/timer/i8254.h"
|
||||
#include "hw/audio/pcspk.h"
|
||||
|
||||
//#define DEBUG_I82378
|
||||
|
||||
#ifdef DEBUG_I82378
|
||||
#define DPRINTF(fmt, ...) \
|
||||
do { fprintf(stderr, "i82378: " fmt , ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
#define BADF(fmt, ...) \
|
||||
do { fprintf(stderr, "i82378 ERROR: " fmt , ## __VA_ARGS__); } while (0)
|
||||
|
||||
typedef struct I82378State {
|
||||
qemu_irq out[2];
|
||||
qemu_irq *i8259;
|
||||
MemoryRegion io;
|
||||
MemoryRegion mem;
|
||||
} I82378State;
|
||||
|
||||
typedef struct PCIi82378State {
|
||||
PCIDevice pci_dev;
|
||||
uint32_t isa_io_base;
|
||||
uint32_t isa_mem_base;
|
||||
I82378State state;
|
||||
} PCIi82378State;
|
||||
|
||||
static const VMStateDescription vmstate_pci_i82378 = {
|
||||
.name = "pci-i82378",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_PCI_DEVICE(pci_dev, PCIi82378State),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
||||
|
||||
static void i82378_io_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__,
|
||||
addr, value);
|
||||
cpu_outb(addr, value);
|
||||
break;
|
||||
case 2:
|
||||
DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__,
|
||||
addr, value);
|
||||
cpu_outw(addr, value);
|
||||
break;
|
||||
case 4:
|
||||
DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__,
|
||||
addr, value);
|
||||
cpu_outl(addr, value);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t i82378_io_read(void *opaque, hwaddr addr,
|
||||
unsigned int size)
|
||||
{
|
||||
DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
|
||||
switch (size) {
|
||||
case 1:
|
||||
return cpu_inb(addr);
|
||||
case 2:
|
||||
return cpu_inw(addr);
|
||||
case 4:
|
||||
return cpu_inl(addr);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps i82378_io_ops = {
|
||||
.read = i82378_io_read,
|
||||
.write = i82378_io_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void i82378_mem_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__,
|
||||
addr, value);
|
||||
cpu_outb(addr, value);
|
||||
break;
|
||||
case 2:
|
||||
DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__,
|
||||
addr, value);
|
||||
cpu_outw(addr, value);
|
||||
break;
|
||||
case 4:
|
||||
DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__,
|
||||
addr, value);
|
||||
cpu_outl(addr, value);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t i82378_mem_read(void *opaque, hwaddr addr,
|
||||
unsigned int size)
|
||||
{
|
||||
DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
|
||||
switch (size) {
|
||||
case 1:
|
||||
return cpu_inb(addr);
|
||||
case 2:
|
||||
return cpu_inw(addr);
|
||||
case 4:
|
||||
return cpu_inl(addr);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps i82378_mem_ops = {
|
||||
.read = i82378_mem_read,
|
||||
.write = i82378_mem_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void i82378_request_out0_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
I82378State *s = opaque;
|
||||
qemu_set_irq(s->out[0], level);
|
||||
}
|
||||
|
||||
static void i82378_request_pic_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
DeviceState *dev = opaque;
|
||||
PCIDevice *pci = DO_UPCAST(PCIDevice, qdev, dev);
|
||||
PCIi82378State *s = DO_UPCAST(PCIi82378State, pci_dev, pci);
|
||||
|
||||
qemu_set_irq(s->state.i8259[irq], level);
|
||||
}
|
||||
|
||||
static void i82378_init(DeviceState *dev, I82378State *s)
|
||||
{
|
||||
ISABus *isabus = DO_UPCAST(ISABus, qbus, qdev_get_child_bus(dev, "isa.0"));
|
||||
ISADevice *pit;
|
||||
ISADevice *isa;
|
||||
qemu_irq *out0_irq;
|
||||
|
||||
/* This device has:
|
||||
2 82C59 (irq)
|
||||
1 82C54 (pit)
|
||||
2 82C37 (dma)
|
||||
NMI
|
||||
Utility Bus Support Registers
|
||||
|
||||
All devices accept byte access only, except timer
|
||||
*/
|
||||
|
||||
qdev_init_gpio_out(dev, s->out, 2);
|
||||
qdev_init_gpio_in(dev, i82378_request_pic_irq, 16);
|
||||
|
||||
/* Workaround the fact that i8259 is not qdev'ified... */
|
||||
out0_irq = qemu_allocate_irqs(i82378_request_out0_irq, s, 1);
|
||||
|
||||
/* 2 82C59 (irq) */
|
||||
s->i8259 = i8259_init(isabus, *out0_irq);
|
||||
isa_bus_irqs(isabus, s->i8259);
|
||||
|
||||
/* 1 82C54 (pit) */
|
||||
pit = pit_init(isabus, 0x40, 0, NULL);
|
||||
|
||||
/* speaker */
|
||||
pcspk_init(isabus, pit);
|
||||
|
||||
/* 2 82C37 (dma) */
|
||||
isa = isa_create_simple(isabus, "i82374");
|
||||
qdev_connect_gpio_out(&isa->qdev, 0, s->out[1]);
|
||||
|
||||
/* timer */
|
||||
isa_create_simple(isabus, "mc146818rtc");
|
||||
}
|
||||
|
||||
static int pci_i82378_init(PCIDevice *dev)
|
||||
{
|
||||
PCIi82378State *pci = DO_UPCAST(PCIi82378State, pci_dev, dev);
|
||||
I82378State *s = &pci->state;
|
||||
uint8_t *pci_conf;
|
||||
|
||||
pci_conf = dev->config;
|
||||
pci_set_word(pci_conf + PCI_COMMAND,
|
||||
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
|
||||
pci_set_word(pci_conf + PCI_STATUS,
|
||||
PCI_STATUS_DEVSEL_MEDIUM);
|
||||
|
||||
pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */
|
||||
|
||||
memory_region_init_io(&s->io, &i82378_io_ops, s, "i82378-io", 0x00010000);
|
||||
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io);
|
||||
|
||||
memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000);
|
||||
pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
|
||||
|
||||
/* Make I/O address read only */
|
||||
pci_set_word(dev->wmask + PCI_COMMAND, PCI_COMMAND_SPECIAL);
|
||||
pci_set_long(dev->wmask + PCI_BASE_ADDRESS_0, 0);
|
||||
pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, pci->isa_io_base);
|
||||
|
||||
isa_mem_base = pci->isa_mem_base;
|
||||
isa_bus_new(&dev->qdev, pci_address_space_io(dev));
|
||||
|
||||
i82378_init(&dev->qdev, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Property i82378_properties[] = {
|
||||
DEFINE_PROP_HEX32("iobase", PCIi82378State, isa_io_base, 0x80000000),
|
||||
DEFINE_PROP_HEX32("membase", PCIi82378State, isa_mem_base, 0xc0000000),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
static void pci_i82378_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
k->init = pci_i82378_init;
|
||||
k->vendor_id = PCI_VENDOR_ID_INTEL;
|
||||
k->device_id = PCI_DEVICE_ID_INTEL_82378;
|
||||
k->revision = 0x03;
|
||||
k->class_id = PCI_CLASS_BRIDGE_ISA;
|
||||
k->subsystem_vendor_id = 0x0;
|
||||
k->subsystem_id = 0x0;
|
||||
dc->vmsd = &vmstate_pci_i82378;
|
||||
dc->props = i82378_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo pci_i82378_info = {
|
||||
.name = "i82378",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIi82378State),
|
||||
.class_init = pci_i82378_class_init,
|
||||
};
|
||||
|
||||
static void i82378_register_types(void)
|
||||
{
|
||||
type_register_static(&pci_i82378_info);
|
||||
}
|
||||
|
||||
type_init(i82378_register_types)
|
282
hw/isa/isa-bus.c
Normal file
282
hw/isa/isa-bus.c
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* isa bus support for qdev.
|
||||
*
|
||||
* Copyright (c) 2009 Gerd Hoffmann <kraxel@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "hw/hw.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
static ISABus *isabus;
|
||||
hwaddr isa_mem_base = 0;
|
||||
|
||||
static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent);
|
||||
static char *isabus_get_fw_dev_path(DeviceState *dev);
|
||||
|
||||
static void isa_bus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
BusClass *k = BUS_CLASS(klass);
|
||||
|
||||
k->print_dev = isabus_dev_print;
|
||||
k->get_fw_dev_path = isabus_get_fw_dev_path;
|
||||
}
|
||||
|
||||
static const TypeInfo isa_bus_info = {
|
||||
.name = TYPE_ISA_BUS,
|
||||
.parent = TYPE_BUS,
|
||||
.instance_size = sizeof(ISABus),
|
||||
.class_init = isa_bus_class_init,
|
||||
};
|
||||
|
||||
ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io)
|
||||
{
|
||||
if (isabus) {
|
||||
fprintf(stderr, "Can't create a second ISA bus\n");
|
||||
return NULL;
|
||||
}
|
||||
if (NULL == dev) {
|
||||
dev = qdev_create(NULL, "isabus-bridge");
|
||||
qdev_init_nofail(dev);
|
||||
}
|
||||
|
||||
isabus = FROM_QBUS(ISABus, qbus_create(TYPE_ISA_BUS, dev, NULL));
|
||||
isabus->address_space_io = address_space_io;
|
||||
return isabus;
|
||||
}
|
||||
|
||||
void isa_bus_irqs(ISABus *bus, qemu_irq *irqs)
|
||||
{
|
||||
if (!bus) {
|
||||
hw_error("Can't set isa irqs with no isa bus present.");
|
||||
}
|
||||
bus->irqs = irqs;
|
||||
}
|
||||
|
||||
/*
|
||||
* isa_get_irq() returns the corresponding qemu_irq entry for the i8259.
|
||||
*
|
||||
* This function is only for special cases such as the 'ferr', and
|
||||
* temporary use for normal devices until they are converted to qdev.
|
||||
*/
|
||||
qemu_irq isa_get_irq(ISADevice *dev, int isairq)
|
||||
{
|
||||
assert(!dev || DO_UPCAST(ISABus, qbus, dev->qdev.parent_bus) == isabus);
|
||||
if (isairq < 0 || isairq > 15) {
|
||||
hw_error("isa irq %d invalid", isairq);
|
||||
}
|
||||
return isabus->irqs[isairq];
|
||||
}
|
||||
|
||||
void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
|
||||
{
|
||||
assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
|
||||
dev->isairq[dev->nirqs] = isairq;
|
||||
*p = isa_get_irq(dev, isairq);
|
||||
dev->nirqs++;
|
||||
}
|
||||
|
||||
static inline void isa_init_ioport(ISADevice *dev, uint16_t ioport)
|
||||
{
|
||||
if (dev && (dev->ioport_id == 0 || ioport < dev->ioport_id)) {
|
||||
dev->ioport_id = ioport;
|
||||
}
|
||||
}
|
||||
|
||||
void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start)
|
||||
{
|
||||
memory_region_add_subregion(isabus->address_space_io, start, io);
|
||||
isa_init_ioport(dev, start);
|
||||
}
|
||||
|
||||
void isa_register_portio_list(ISADevice *dev, uint16_t start,
|
||||
const MemoryRegionPortio *pio_start,
|
||||
void *opaque, const char *name)
|
||||
{
|
||||
PortioList *piolist = g_new(PortioList, 1);
|
||||
|
||||
/* START is how we should treat DEV, regardless of the actual
|
||||
contents of the portio array. This is how the old code
|
||||
actually handled e.g. the FDC device. */
|
||||
isa_init_ioport(dev, start);
|
||||
|
||||
portio_list_init(piolist, pio_start, opaque, name);
|
||||
portio_list_add(piolist, isabus->address_space_io, start);
|
||||
}
|
||||
|
||||
static int isa_qdev_init(DeviceState *qdev)
|
||||
{
|
||||
ISADevice *dev = ISA_DEVICE(qdev);
|
||||
ISADeviceClass *klass = ISA_DEVICE_GET_CLASS(dev);
|
||||
|
||||
if (klass->init) {
|
||||
return klass->init(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void isa_device_init(Object *obj)
|
||||
{
|
||||
ISADevice *dev = ISA_DEVICE(obj);
|
||||
|
||||
dev->isairq[0] = -1;
|
||||
dev->isairq[1] = -1;
|
||||
}
|
||||
|
||||
ISADevice *isa_create(ISABus *bus, const char *name)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
if (!bus) {
|
||||
hw_error("Tried to create isa device %s with no isa bus present.",
|
||||
name);
|
||||
}
|
||||
dev = qdev_create(&bus->qbus, name);
|
||||
return ISA_DEVICE(dev);
|
||||
}
|
||||
|
||||
ISADevice *isa_try_create(ISABus *bus, const char *name)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
if (!bus) {
|
||||
hw_error("Tried to create isa device %s with no isa bus present.",
|
||||
name);
|
||||
}
|
||||
dev = qdev_try_create(&bus->qbus, name);
|
||||
return ISA_DEVICE(dev);
|
||||
}
|
||||
|
||||
ISADevice *isa_create_simple(ISABus *bus, const char *name)
|
||||
{
|
||||
ISADevice *dev;
|
||||
|
||||
dev = isa_create(bus, name);
|
||||
qdev_init_nofail(&dev->qdev);
|
||||
return dev;
|
||||
}
|
||||
|
||||
ISADevice *isa_vga_init(ISABus *bus)
|
||||
{
|
||||
switch (vga_interface_type) {
|
||||
case VGA_CIRRUS:
|
||||
return isa_create_simple(bus, "isa-cirrus-vga");
|
||||
case VGA_QXL:
|
||||
fprintf(stderr, "%s: qxl: no PCI bus\n", __func__);
|
||||
return NULL;
|
||||
case VGA_STD:
|
||||
return isa_create_simple(bus, "isa-vga");
|
||||
case VGA_VMWARE:
|
||||
fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __func__);
|
||||
return NULL;
|
||||
case VGA_NONE:
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)
|
||||
{
|
||||
ISADevice *d = ISA_DEVICE(dev);
|
||||
|
||||
if (d->isairq[1] != -1) {
|
||||
monitor_printf(mon, "%*sisa irqs %d,%d\n", indent, "",
|
||||
d->isairq[0], d->isairq[1]);
|
||||
} else if (d->isairq[0] != -1) {
|
||||
monitor_printf(mon, "%*sisa irq %d\n", indent, "",
|
||||
d->isairq[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static int isabus_bridge_init(SysBusDevice *dev)
|
||||
{
|
||||
/* nothing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void isabus_bridge_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = isabus_bridge_init;
|
||||
dc->fw_name = "isa";
|
||||
dc->no_user = 1;
|
||||
}
|
||||
|
||||
static const TypeInfo isabus_bridge_info = {
|
||||
.name = "isabus-bridge",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(SysBusDevice),
|
||||
.class_init = isabus_bridge_class_init,
|
||||
};
|
||||
|
||||
static void isa_device_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *k = DEVICE_CLASS(klass);
|
||||
k->init = isa_qdev_init;
|
||||
k->bus_type = TYPE_ISA_BUS;
|
||||
}
|
||||
|
||||
static const TypeInfo isa_device_type_info = {
|
||||
.name = TYPE_ISA_DEVICE,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(ISADevice),
|
||||
.instance_init = isa_device_init,
|
||||
.abstract = true,
|
||||
.class_size = sizeof(ISADeviceClass),
|
||||
.class_init = isa_device_class_init,
|
||||
};
|
||||
|
||||
static void isabus_register_types(void)
|
||||
{
|
||||
type_register_static(&isa_bus_info);
|
||||
type_register_static(&isabus_bridge_info);
|
||||
type_register_static(&isa_device_type_info);
|
||||
}
|
||||
|
||||
static char *isabus_get_fw_dev_path(DeviceState *dev)
|
||||
{
|
||||
ISADevice *d = (ISADevice*)dev;
|
||||
char path[40];
|
||||
int off;
|
||||
|
||||
off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
|
||||
if (d->ioport_id) {
|
||||
snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id);
|
||||
}
|
||||
|
||||
return g_strdup(path);
|
||||
}
|
||||
|
||||
MemoryRegion *isa_address_space(ISADevice *dev)
|
||||
{
|
||||
return get_system_memory();
|
||||
}
|
||||
|
||||
MemoryRegion *isa_address_space_io(ISADevice *dev)
|
||||
{
|
||||
if (dev) {
|
||||
return isa_bus_from_device(dev)->address_space_io;
|
||||
}
|
||||
|
||||
return isabus->address_space_io;
|
||||
}
|
||||
|
||||
type_init(isabus_register_types)
|
81
hw/isa/isa_mmio.c
Normal file
81
hw/isa/isa_mmio.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Memory mapped access to ISA IO space.
|
||||
*
|
||||
* Copyright (c) 2006 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
static void isa_mmio_writeb (void *opaque, hwaddr addr,
|
||||
uint32_t val)
|
||||
{
|
||||
cpu_outb(addr & IOPORTS_MASK, val);
|
||||
}
|
||||
|
||||
static void isa_mmio_writew(void *opaque, hwaddr addr,
|
||||
uint32_t val)
|
||||
{
|
||||
cpu_outw(addr & IOPORTS_MASK, val);
|
||||
}
|
||||
|
||||
static void isa_mmio_writel(void *opaque, hwaddr addr,
|
||||
uint32_t val)
|
||||
{
|
||||
cpu_outl(addr & IOPORTS_MASK, val);
|
||||
}
|
||||
|
||||
static uint32_t isa_mmio_readb (void *opaque, hwaddr addr)
|
||||
{
|
||||
return cpu_inb(addr & IOPORTS_MASK);
|
||||
}
|
||||
|
||||
static uint32_t isa_mmio_readw(void *opaque, hwaddr addr)
|
||||
{
|
||||
return cpu_inw(addr & IOPORTS_MASK);
|
||||
}
|
||||
|
||||
static uint32_t isa_mmio_readl(void *opaque, hwaddr addr)
|
||||
{
|
||||
return cpu_inl(addr & IOPORTS_MASK);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps isa_mmio_ops = {
|
||||
.old_mmio = {
|
||||
.write = { isa_mmio_writeb, isa_mmio_writew, isa_mmio_writel },
|
||||
.read = { isa_mmio_readb, isa_mmio_readw, isa_mmio_readl, },
|
||||
},
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
void isa_mmio_setup(MemoryRegion *mr, hwaddr size)
|
||||
{
|
||||
memory_region_init_io(mr, &isa_mmio_ops, NULL, "isa-mmio", size);
|
||||
}
|
||||
|
||||
void isa_mmio_init(hwaddr base, hwaddr size)
|
||||
{
|
||||
MemoryRegion *mr = g_malloc(sizeof(*mr));
|
||||
|
||||
isa_mmio_setup(mr, size);
|
||||
memory_region_add_subregion(get_system_memory(), base, mr);
|
||||
}
|
402
hw/isa/pc87312.c
Normal file
402
hw/isa/pc87312.c
Normal file
|
@ -0,0 +1,402 @@
|
|||
/*
|
||||
* QEMU National Semiconductor PC87312 (Super I/O)
|
||||
*
|
||||
* Copyright (c) 2010-2012 Herve Poussineau
|
||||
* Copyright (c) 2011-2012 Andreas Färber
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hw/isa/pc87312.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "char/char.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
#define REG_FER 0
|
||||
#define REG_FAR 1
|
||||
#define REG_PTR 2
|
||||
|
||||
#define FER_PARALLEL_EN 0x01
|
||||
#define FER_UART1_EN 0x02
|
||||
#define FER_UART2_EN 0x04
|
||||
#define FER_FDC_EN 0x08
|
||||
#define FER_FDC_4 0x10
|
||||
#define FER_FDC_ADDR 0x20
|
||||
#define FER_IDE_EN 0x40
|
||||
#define FER_IDE_ADDR 0x80
|
||||
|
||||
#define FAR_PARALLEL_ADDR 0x03
|
||||
#define FAR_UART1_ADDR 0x0C
|
||||
#define FAR_UART2_ADDR 0x30
|
||||
#define FAR_UART_3_4 0xC0
|
||||
|
||||
#define PTR_POWER_DOWN 0x01
|
||||
#define PTR_CLOCK_DOWN 0x02
|
||||
#define PTR_PWDN 0x04
|
||||
#define PTR_IRQ_5_7 0x08
|
||||
#define PTR_UART1_TEST 0x10
|
||||
#define PTR_UART2_TEST 0x20
|
||||
#define PTR_LOCK_CONF 0x40
|
||||
#define PTR_EPP_MODE 0x80
|
||||
|
||||
|
||||
/* Parallel port */
|
||||
|
||||
static inline bool is_parallel_enabled(PC87312State *s)
|
||||
{
|
||||
return s->regs[REG_FER] & FER_PARALLEL_EN;
|
||||
}
|
||||
|
||||
static const uint32_t parallel_base[] = { 0x378, 0x3bc, 0x278, 0x00 };
|
||||
|
||||
static inline uint32_t get_parallel_iobase(PC87312State *s)
|
||||
{
|
||||
return parallel_base[s->regs[REG_FAR] & FAR_PARALLEL_ADDR];
|
||||
}
|
||||
|
||||
static const uint32_t parallel_irq[] = { 5, 7, 5, 0 };
|
||||
|
||||
static inline uint32_t get_parallel_irq(PC87312State *s)
|
||||
{
|
||||
int idx;
|
||||
idx = (s->regs[REG_FAR] & FAR_PARALLEL_ADDR);
|
||||
if (idx == 0) {
|
||||
return (s->regs[REG_PTR] & PTR_IRQ_5_7) ? 7 : 5;
|
||||
} else {
|
||||
return parallel_irq[idx];
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool is_parallel_epp(PC87312State *s)
|
||||
{
|
||||
return s->regs[REG_PTR] & PTR_EPP_MODE;
|
||||
}
|
||||
|
||||
|
||||
/* UARTs */
|
||||
|
||||
static const uint32_t uart_base[2][4] = {
|
||||
{ 0x3e8, 0x338, 0x2e8, 0x220 },
|
||||
{ 0x2e8, 0x238, 0x2e0, 0x228 }
|
||||
};
|
||||
|
||||
static inline uint32_t get_uart_iobase(PC87312State *s, int i)
|
||||
{
|
||||
int idx;
|
||||
idx = (s->regs[REG_FAR] >> (2 * i + 2)) & 0x3;
|
||||
if (idx == 0) {
|
||||
return 0x3f8;
|
||||
} else if (idx == 1) {
|
||||
return 0x2f8;
|
||||
} else {
|
||||
return uart_base[idx & 1][(s->regs[REG_FAR] & FAR_UART_3_4) >> 6];
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t get_uart_irq(PC87312State *s, int i)
|
||||
{
|
||||
int idx;
|
||||
idx = (s->regs[REG_FAR] >> (2 * i + 2)) & 0x3;
|
||||
return (idx & 1) ? 3 : 4;
|
||||
}
|
||||
|
||||
static inline bool is_uart_enabled(PC87312State *s, int i)
|
||||
{
|
||||
return s->regs[REG_FER] & (FER_UART1_EN << i);
|
||||
}
|
||||
|
||||
|
||||
/* Floppy controller */
|
||||
|
||||
static inline bool is_fdc_enabled(PC87312State *s)
|
||||
{
|
||||
return s->regs[REG_FER] & FER_FDC_EN;
|
||||
}
|
||||
|
||||
static inline uint32_t get_fdc_iobase(PC87312State *s)
|
||||
{
|
||||
return (s->regs[REG_FER] & FER_FDC_ADDR) ? 0x370 : 0x3f0;
|
||||
}
|
||||
|
||||
|
||||
/* IDE controller */
|
||||
|
||||
static inline bool is_ide_enabled(PC87312State *s)
|
||||
{
|
||||
return s->regs[REG_FER] & FER_IDE_EN;
|
||||
}
|
||||
|
||||
static inline uint32_t get_ide_iobase(PC87312State *s)
|
||||
{
|
||||
return (s->regs[REG_FER] & FER_IDE_ADDR) ? 0x170 : 0x1f0;
|
||||
}
|
||||
|
||||
|
||||
static void reconfigure_devices(PC87312State *s)
|
||||
{
|
||||
error_report("pc87312: unsupported device reconfiguration (%02x %02x %02x)",
|
||||
s->regs[REG_FER], s->regs[REG_FAR], s->regs[REG_PTR]);
|
||||
}
|
||||
|
||||
static void pc87312_soft_reset(PC87312State *s)
|
||||
{
|
||||
static const uint8_t fer_init[] = {
|
||||
0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4b, 0x4b,
|
||||
0x4b, 0x4b, 0x4b, 0x4b, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||
0x49, 0x49, 0x49, 0x49, 0x07, 0x07, 0x07, 0x07,
|
||||
0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x08, 0x00,
|
||||
};
|
||||
static const uint8_t far_init[] = {
|
||||
0x10, 0x11, 0x11, 0x39, 0x24, 0x38, 0x00, 0x01,
|
||||
0x01, 0x09, 0x08, 0x08, 0x10, 0x11, 0x39, 0x24,
|
||||
0x00, 0x01, 0x01, 0x00, 0x10, 0x11, 0x39, 0x24,
|
||||
0x10, 0x11, 0x11, 0x39, 0x24, 0x38, 0x10, 0x10,
|
||||
};
|
||||
static const uint8_t ptr_init[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
};
|
||||
|
||||
s->read_id_step = 0;
|
||||
s->selected_index = REG_FER;
|
||||
|
||||
s->regs[REG_FER] = fer_init[s->config & 0x1f];
|
||||
s->regs[REG_FAR] = far_init[s->config & 0x1f];
|
||||
s->regs[REG_PTR] = ptr_init[s->config & 0x1f];
|
||||
}
|
||||
|
||||
static void pc87312_hard_reset(PC87312State *s)
|
||||
{
|
||||
pc87312_soft_reset(s);
|
||||
}
|
||||
|
||||
static void pc87312_io_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
unsigned int size)
|
||||
{
|
||||
PC87312State *s = opaque;
|
||||
|
||||
trace_pc87312_io_write(addr, val);
|
||||
|
||||
if ((addr & 1) == 0) {
|
||||
/* Index register */
|
||||
s->read_id_step = 2;
|
||||
s->selected_index = val;
|
||||
} else {
|
||||
/* Data register */
|
||||
if (s->selected_index < 3) {
|
||||
s->regs[s->selected_index] = val;
|
||||
reconfigure_devices(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t pc87312_io_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
PC87312State *s = opaque;
|
||||
uint32_t val;
|
||||
|
||||
if ((addr & 1) == 0) {
|
||||
/* Index register */
|
||||
if (s->read_id_step++ == 0) {
|
||||
val = 0x88;
|
||||
} else if (s->read_id_step++ == 1) {
|
||||
val = 0;
|
||||
} else {
|
||||
val = s->selected_index;
|
||||
}
|
||||
} else {
|
||||
/* Data register */
|
||||
if (s->selected_index < 3) {
|
||||
val = s->regs[s->selected_index];
|
||||
} else {
|
||||
/* Invalid selected index */
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
trace_pc87312_io_read(addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pc87312_io_ops = {
|
||||
.read = pc87312_io_read,
|
||||
.write = pc87312_io_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static int pc87312_post_load(void *opaque, int version_id)
|
||||
{
|
||||
PC87312State *s = opaque;
|
||||
|
||||
reconfigure_devices(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pc87312_reset(DeviceState *d)
|
||||
{
|
||||
PC87312State *s = PC87312(d);
|
||||
|
||||
pc87312_soft_reset(s);
|
||||
}
|
||||
|
||||
static int pc87312_init(ISADevice *dev)
|
||||
{
|
||||
PC87312State *s;
|
||||
DeviceState *d;
|
||||
ISADevice *isa;
|
||||
ISABus *bus;
|
||||
CharDriverState *chr;
|
||||
DriveInfo *drive;
|
||||
char name[5];
|
||||
int i;
|
||||
|
||||
s = PC87312(dev);
|
||||
bus = isa_bus_from_device(dev);
|
||||
pc87312_hard_reset(s);
|
||||
isa_register_ioport(dev, &s->io, s->iobase);
|
||||
|
||||
if (is_parallel_enabled(s)) {
|
||||
chr = parallel_hds[0];
|
||||
if (chr == NULL) {
|
||||
chr = qemu_chr_new("par0", "null", NULL);
|
||||
}
|
||||
isa = isa_create(bus, "isa-parallel");
|
||||
d = DEVICE(isa);
|
||||
qdev_prop_set_uint32(d, "index", 0);
|
||||
qdev_prop_set_uint32(d, "iobase", get_parallel_iobase(s));
|
||||
qdev_prop_set_uint32(d, "irq", get_parallel_irq(s));
|
||||
qdev_prop_set_chr(d, "chardev", chr);
|
||||
qdev_init_nofail(d);
|
||||
s->parallel.dev = isa;
|
||||
trace_pc87312_info_parallel(get_parallel_iobase(s),
|
||||
get_parallel_irq(s));
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (is_uart_enabled(s, i)) {
|
||||
chr = serial_hds[i];
|
||||
if (chr == NULL) {
|
||||
snprintf(name, sizeof(name), "ser%d", i);
|
||||
chr = qemu_chr_new(name, "null", NULL);
|
||||
}
|
||||
isa = isa_create(bus, "isa-serial");
|
||||
d = DEVICE(isa);
|
||||
qdev_prop_set_uint32(d, "index", i);
|
||||
qdev_prop_set_uint32(d, "iobase", get_uart_iobase(s, i));
|
||||
qdev_prop_set_uint32(d, "irq", get_uart_irq(s, i));
|
||||
qdev_prop_set_chr(d, "chardev", chr);
|
||||
qdev_init_nofail(d);
|
||||
s->uart[i].dev = isa;
|
||||
trace_pc87312_info_serial(i, get_uart_iobase(s, i),
|
||||
get_uart_irq(s, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (is_fdc_enabled(s)) {
|
||||
isa = isa_create(bus, "isa-fdc");
|
||||
d = DEVICE(isa);
|
||||
qdev_prop_set_uint32(d, "iobase", get_fdc_iobase(s));
|
||||
qdev_prop_set_uint32(d, "irq", 6);
|
||||
drive = drive_get(IF_FLOPPY, 0, 0);
|
||||
if (drive != NULL) {
|
||||
qdev_prop_set_drive_nofail(d, "driveA", drive->bdrv);
|
||||
}
|
||||
drive = drive_get(IF_FLOPPY, 0, 1);
|
||||
if (drive != NULL) {
|
||||
qdev_prop_set_drive_nofail(d, "driveB", drive->bdrv);
|
||||
}
|
||||
qdev_init_nofail(d);
|
||||
s->fdc.dev = isa;
|
||||
trace_pc87312_info_floppy(get_fdc_iobase(s));
|
||||
}
|
||||
|
||||
if (is_ide_enabled(s)) {
|
||||
isa = isa_create(bus, "isa-ide");
|
||||
d = DEVICE(isa);
|
||||
qdev_prop_set_uint32(d, "iobase", get_ide_iobase(s));
|
||||
qdev_prop_set_uint32(d, "iobase2", get_ide_iobase(s) + 0x206);
|
||||
qdev_prop_set_uint32(d, "irq", 14);
|
||||
qdev_init_nofail(d);
|
||||
s->ide.dev = isa;
|
||||
trace_pc87312_info_ide(get_ide_iobase(s));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pc87312_initfn(Object *obj)
|
||||
{
|
||||
PC87312State *s = PC87312(obj);
|
||||
|
||||
memory_region_init_io(&s->io, &pc87312_io_ops, s, "pc87312", 2);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pc87312 = {
|
||||
.name = "pc87312",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.post_load = pc87312_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT8(read_id_step, PC87312State),
|
||||
VMSTATE_UINT8(selected_index, PC87312State),
|
||||
VMSTATE_UINT8_ARRAY(regs, PC87312State, 3),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static Property pc87312_properties[] = {
|
||||
DEFINE_PROP_HEX32("iobase", PC87312State, iobase, 0x398),
|
||||
DEFINE_PROP_UINT8("config", PC87312State, config, 1),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
static void pc87312_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
|
||||
|
||||
ic->init = pc87312_init;
|
||||
dc->reset = pc87312_reset;
|
||||
dc->vmsd = &vmstate_pc87312;
|
||||
dc->props = pc87312_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo pc87312_type_info = {
|
||||
.name = TYPE_PC87312,
|
||||
.parent = TYPE_ISA_DEVICE,
|
||||
.instance_size = sizeof(PC87312State),
|
||||
.instance_init = pc87312_initfn,
|
||||
.class_init = pc87312_class_init,
|
||||
};
|
||||
|
||||
static void pc87312_register_types(void)
|
||||
{
|
||||
type_register_static(&pc87312_type_info);
|
||||
}
|
||||
|
||||
type_init(pc87312_register_types)
|
132
hw/isa/piix4.c
Normal file
132
hw/isa/piix4.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* QEMU PIIX4 PCI Bridge Emulation
|
||||
*
|
||||
* Copyright (c) 2006 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
PCIDevice *piix4_dev;
|
||||
|
||||
typedef struct PIIX4State {
|
||||
PCIDevice dev;
|
||||
} PIIX4State;
|
||||
|
||||
static void piix4_reset(void *opaque)
|
||||
{
|
||||
PIIX4State *d = opaque;
|
||||
uint8_t *pci_conf = d->dev.config;
|
||||
|
||||
pci_conf[0x04] = 0x07; // master, memory and I/O
|
||||
pci_conf[0x05] = 0x00;
|
||||
pci_conf[0x06] = 0x00;
|
||||
pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
|
||||
pci_conf[0x4c] = 0x4d;
|
||||
pci_conf[0x4e] = 0x03;
|
||||
pci_conf[0x4f] = 0x00;
|
||||
pci_conf[0x60] = 0x0a; // PCI A -> IRQ 10
|
||||
pci_conf[0x61] = 0x0a; // PCI B -> IRQ 10
|
||||
pci_conf[0x62] = 0x0b; // PCI C -> IRQ 11
|
||||
pci_conf[0x63] = 0x0b; // PCI D -> IRQ 11
|
||||
pci_conf[0x69] = 0x02;
|
||||
pci_conf[0x70] = 0x80;
|
||||
pci_conf[0x76] = 0x0c;
|
||||
pci_conf[0x77] = 0x0c;
|
||||
pci_conf[0x78] = 0x02;
|
||||
pci_conf[0x79] = 0x00;
|
||||
pci_conf[0x80] = 0x00;
|
||||
pci_conf[0x82] = 0x00;
|
||||
pci_conf[0xa0] = 0x08;
|
||||
pci_conf[0xa2] = 0x00;
|
||||
pci_conf[0xa3] = 0x00;
|
||||
pci_conf[0xa4] = 0x00;
|
||||
pci_conf[0xa5] = 0x00;
|
||||
pci_conf[0xa6] = 0x00;
|
||||
pci_conf[0xa7] = 0x00;
|
||||
pci_conf[0xa8] = 0x0f;
|
||||
pci_conf[0xaa] = 0x00;
|
||||
pci_conf[0xab] = 0x00;
|
||||
pci_conf[0xac] = 0x00;
|
||||
pci_conf[0xae] = 0x00;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_piix4 = {
|
||||
.name = "PIIX4",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.minimum_version_id_old = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_PCI_DEVICE(dev, PIIX4State),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static int piix4_initfn(PCIDevice *dev)
|
||||
{
|
||||
PIIX4State *d = DO_UPCAST(PIIX4State, dev, dev);
|
||||
|
||||
isa_bus_new(&d->dev.qdev, pci_address_space_io(dev));
|
||||
piix4_dev = &d->dev;
|
||||
qemu_register_reset(piix4_reset, d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn)
|
||||
{
|
||||
PCIDevice *d;
|
||||
|
||||
d = pci_create_simple_multifunction(bus, devfn, true, "PIIX4");
|
||||
*isa_bus = DO_UPCAST(ISABus, qbus, qdev_get_child_bus(&d->qdev, "isa.0"));
|
||||
return d->devfn;
|
||||
}
|
||||
|
||||
static void piix4_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->no_hotplug = 1;
|
||||
k->init = piix4_initfn;
|
||||
k->vendor_id = PCI_VENDOR_ID_INTEL;
|
||||
k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0;
|
||||
k->class_id = PCI_CLASS_BRIDGE_ISA;
|
||||
dc->desc = "ISA bridge";
|
||||
dc->no_user = 1;
|
||||
dc->vmsd = &vmstate_piix4;
|
||||
}
|
||||
|
||||
static const TypeInfo piix4_info = {
|
||||
.name = "PIIX4",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PIIX4State),
|
||||
.class_init = piix4_class_init,
|
||||
};
|
||||
|
||||
static void piix4_register_types(void)
|
||||
{
|
||||
type_register_static(&piix4_info);
|
||||
}
|
||||
|
||||
type_init(piix4_register_types)
|
Loading…
Add table
Add a link
Reference in a new issue