@@ -242,6 +242,7 @@ obj-ppc-y = ppc.o
obj-ppc-y += vga.o
# PREP target
obj-ppc-y += i8259.o mc146818rtc.o
+obj-ppc-y += prep_systemio.o
obj-ppc-y += ppc_prep.o
# OldWorld PowerMac
obj-ppc-y += ppc_oldworld.o
@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "ppc_prep.h"
#include "hw.h"
#include "nvram.h"
#include "pc.h"
@@ -258,117 +259,55 @@ static CPUReadMemoryFunc * const PPC_XCSR_read[] = {
#endif
/* Fake super-io ports for PREP platform (Intel 82378ZB) */
-typedef struct sysctrl_t {
- qemu_irq reset_irq;
- M48t59State *nvram;
- uint8_t state;
- uint8_t syscontrol;
- uint8_t fake_io[2];
- int contiguous_map;
- int endian;
-} sysctrl_t;
-
-enum {
- STATE_HARDFILE = 0x01,
-};
-
-static sysctrl_t *sysctrl;
-
static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val)
{
- sysctrl_t *sysctrl = opaque;
+ uint8_t *fake_io = opaque;
PPC_IO_DPRINTF("0x%08" PRIx32 " => 0x%02" PRIx32 "\n", addr - PPC_IO_BASE,
val);
- sysctrl->fake_io[addr - 0x0398] = val;
+ fake_io[addr - 0x0398] = val;
}
static uint32_t PREP_io_read (void *opaque, uint32_t addr)
{
- sysctrl_t *sysctrl = opaque;
+ uint8_t *fake_io = opaque;
PPC_IO_DPRINTF("0x%08" PRIx32 " <= 0x%02" PRIx32 "\n", addr - PPC_IO_BASE,
- sysctrl->fake_io[addr - 0x0398]);
- return sysctrl->fake_io[addr - 0x0398];
+ fake_io[addr - 0x0398]);
+ return fake_io[addr - 0x0398];
}
+#if 0
static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
{
- sysctrl_t *sysctrl = opaque;
-
PPC_IO_DPRINTF("0x%08" PRIx32 " => 0x%02" PRIx32 "\n",
addr - PPC_IO_BASE, val);
switch (addr) {
- case 0x0092:
- /* Special port 92 */
- /* Check soft reset asked */
- if (val & 0x01) {
- qemu_irq_raise(sysctrl->reset_irq);
- } else {
- qemu_irq_lower(sysctrl->reset_irq);
- }
- /* Check LE mode */
- if (val & 0x02) {
- sysctrl->endian = 1;
- } else {
- sysctrl->endian = 0;
- }
- break;
- case 0x0800:
- /* Motorola CPU configuration register : read-only */
- break;
- case 0x0802:
- /* Motorola base module feature register : read-only */
- break;
- case 0x0803:
- /* Motorola base module status register : read-only */
- break;
- case 0x0808:
- /* Hardfile light register */
- if (val & 1)
- sysctrl->state |= STATE_HARDFILE;
- else
- sysctrl->state &= ~STATE_HARDFILE;
- break;
case 0x0810:
/* Password protect 1 register */
- if (sysctrl->nvram != NULL)
- m48t59_toggle_lock(sysctrl->nvram, 1);
+ // TODO m48t59_toggle_lock(sysctrl->nvram, 1);
break;
case 0x0812:
/* Password protect 2 register */
- if (sysctrl->nvram != NULL)
- m48t59_toggle_lock(sysctrl->nvram, 2);
+ // TODO m48t59_toggle_lock(sysctrl->nvram, 2);
break;
case 0x0814:
/* L2 invalidate register */
// tlb_flush(first_cpu, 1);
break;
- case 0x081C:
- /* system control register */
- sysctrl->syscontrol = val & 0x0F;
- break;
- case 0x0850:
- /* I/O map type register */
- sysctrl->contiguous_map = val & 0x01;
- break;
default:
printf("ERROR: unaffected IO port write: %04" PRIx32
" => %02" PRIx32"\n", addr, val);
break;
}
}
+#endif
static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
{
- sysctrl_t *sysctrl = opaque;
uint32_t retval = 0xFF;
switch (addr) {
- case 0x0092:
- /* Special port 92 */
- retval = 0x00;
- break;
case 0x0800:
/* Motorola CPU configuration register */
retval = 0xEF; /* MPC750 */
@@ -377,44 +316,14 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
/* Motorola Base module feature register */
retval = 0xAD; /* No ESCC, PMC slot neither ethernet */
break;
- case 0x0803:
- /* Motorola base module status register */
- retval = 0xE0; /* Standard MPC750 */
- break;
- case 0x080C:
- /* Equipment present register:
- * no L2 cache
- * no upgrade processor
- * no cards in PCI slots
- * SCSI fuse is bad
- */
- retval = 0x3C;
- break;
case 0x0810:
/* Motorola base module extended feature register */
retval = 0x39; /* No USB, CF and PCI bridge. NVRAM present */
break;
- case 0x0814:
- /* L2 invalidate: don't care */
- break;
- case 0x0818:
- /* Keylock */
- retval = 0x00;
- break;
- case 0x081C:
- /* system control register
- * 7 - 6 / 1 - 0: L2 cache enable
- */
- retval = sysctrl->syscontrol;
- break;
case 0x0823:
/* */
retval = 0x03; /* no L2 cache */
break;
- case 0x0850:
- /* I/O map type register */
- retval = sysctrl->contiguous_map;
- break;
default:
printf("ERROR: unaffected IO port: %04" PRIx32 " read\n", addr);
break;
@@ -425,10 +334,10 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
return retval;
}
-static inline target_phys_addr_t prep_IO_address(sysctrl_t *sysctrl,
+static inline target_phys_addr_t prep_IO_address(ISAPrepSystemIo800State *state,
target_phys_addr_t addr)
{
- if (sysctrl->contiguous_map == 0) {
+ if (prep_is_iomap_contiguous(state)) {
/* 64 KB contiguous space for IOs */
addr &= 0xFFFF;
} else {
@@ -442,18 +351,18 @@ static inline target_phys_addr_t prep_IO_address(sysctrl_t *sysctrl,
static void PPC_prep_io_writeb (void *opaque, target_phys_addr_t addr,
uint32_t value)
{
- sysctrl_t *sysctrl = opaque;
+ ISAPrepSystemIo800State *dev = opaque;
- addr = prep_IO_address(sysctrl, addr);
+ addr = prep_IO_address(dev, addr);
cpu_outb(addr, value);
}
static uint32_t PPC_prep_io_readb (void *opaque, target_phys_addr_t addr)
{
- sysctrl_t *sysctrl = opaque;
+ ISAPrepSystemIo800State *dev = opaque;
uint32_t ret;
- addr = prep_IO_address(sysctrl, addr);
+ addr = prep_IO_address(dev, addr);
ret = cpu_inb(addr);
return ret;
@@ -462,19 +371,19 @@ static uint32_t PPC_prep_io_readb (void *opaque, target_phys_addr_t addr)
static void PPC_prep_io_writew (void *opaque, target_phys_addr_t addr,
uint32_t value)
{
- sysctrl_t *sysctrl = opaque;
+ ISAPrepSystemIo800State *dev = opaque;
- addr = prep_IO_address(sysctrl, addr);
+ addr = prep_IO_address(dev, addr);
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
cpu_outw(addr, value);
}
static uint32_t PPC_prep_io_readw (void *opaque, target_phys_addr_t addr)
{
- sysctrl_t *sysctrl = opaque;
+ ISAPrepSystemIo800State *dev = opaque;
uint32_t ret;
- addr = prep_IO_address(sysctrl, addr);
+ addr = prep_IO_address(dev, addr);
ret = cpu_inw(addr);
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
@@ -484,19 +393,19 @@ static uint32_t PPC_prep_io_readw (void *opaque, target_phys_addr_t addr)
static void PPC_prep_io_writel (void *opaque, target_phys_addr_t addr,
uint32_t value)
{
- sysctrl_t *sysctrl = opaque;
+ ISAPrepSystemIo800State *dev = opaque;
- addr = prep_IO_address(sysctrl, addr);
+ addr = prep_IO_address(dev, addr);
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
cpu_outl(addr, value);
}
static uint32_t PPC_prep_io_readl (void *opaque, target_phys_addr_t addr)
{
- sysctrl_t *sysctrl = opaque;
+ ISAPrepSystemIo800State *dev = opaque;
uint32_t ret;
- addr = prep_IO_address(sysctrl, addr);
+ addr = prep_IO_address(dev, addr);
ret = cpu_inl(addr);
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
@@ -566,6 +475,8 @@ static void ppc_prep_init (ram_addr_t ram_size,
{
CPUState *env = NULL;
char *filename;
+ ISADevice *systemio;
+ uint8_t *fake_io;
nvram_t nvram;
M48t59State *m48t59;
int PPC_io_memory;
@@ -580,8 +491,6 @@ static void ppc_prep_init (ram_addr_t ram_size,
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
DriveInfo *fd[MAX_FD];
- sysctrl = qemu_mallocz(sizeof(sysctrl_t));
-
linux_boot = (kernel_filename != NULL);
/* init CPUs */
@@ -668,10 +577,11 @@ static void ppc_prep_init (ram_addr_t ram_size,
/* Hmm, prep has no pci-isa bridge ??? */
isa_bus_new(NULL);
isa_bus_irqs(i8259);
+ systemio = isa_create_simple("prep-systemio800");
// pci_bus = i440fx_init();
/* Register 8 MB of ISA IO space (needed for non-contiguous map) */
PPC_io_memory = cpu_register_io_memory(PPC_prep_io_read,
- PPC_prep_io_write, sysctrl,
+ PPC_prep_io_write, systemio,
DEVICE_LITTLE_ENDIAN);
cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
@@ -719,14 +629,13 @@ static void ppc_prep_init (ram_addr_t ram_size,
register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
/* Register fake IO ports for PREP */
- sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
- register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
- register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
+ fake_io = qemu_mallocz(2);
+ register_ioport_read(0x398, 2, 1, &PREP_io_read, fake_io);
+ register_ioport_write(0x398, 2, 1, &PREP_io_write, fake_io);
/* System control ports */
- register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl);
- register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl);
- register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl);
- register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl);
+ register_ioport_read(0x0800, 2/*3*/, 1, &PREP_io_800_readb, systemio);
+ //register_ioport_read(0x0810, 1, 1, PREP_io_800_readb, systemio);
+ register_ioport_read(0x0823, 1, 1, PREP_io_800_readb, systemio);
/* PCI intack location */
PPC_io_memory = cpu_register_io_memory(PPC_intack_read,
PPC_intack_write, NULL,
@@ -746,7 +655,6 @@ static void ppc_prep_init (ram_addr_t ram_size,
m48t59 = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
if (m48t59 == NULL)
return;
- sysctrl->nvram = m48t59;
/* Initialise NVRAM */
nvram.opaque = m48t59;
@@ -834,6 +742,11 @@ static void ibm_40p_init(ram_addr_t ram_size,
qdev_connect_gpio_out(&pci->qdev, 0, env->irq_inputs[PPC6xx_INPUT_INT]);
qdev_connect_gpio_out(&pci->qdev, 1, *cpu_exit_irq);
+ /* PReP System I/O */
+ isa = isa_create("prep-systemio800");
+ qdev_prop_set_uint8(&isa->qdev, "board-identification", 0xfc);
+ qdev_init_nofail(&isa->qdev);
+
/* Super I/O (parallel + serial ports) */
isa = isa_create("isa-pc87312");
qdev_prop_set_chr(&isa->qdev, "parallel", parallel_hds[0]);
new file mode 100644
@@ -0,0 +1,24 @@
+#ifndef PPC_PREP_H
+#define PPC_PREP_H
+
+#include "isa.h"
+
+
+typedef struct PrepIo800State {
+ uint8_t system_control; /* 0x081c */
+ uint8_t iomap_type; /* 0x0850 */
+ uint32_t mem_parity_error_address;
+ qemu_irq softreset_irq;
+} PrepIo800State;
+
+typedef struct ISAPrepSystemIo800State {
+ ISADevice dev;
+ uint8_t board_identification; /* 0x0852 */
+ PrepIo800State state;
+} ISAPrepSystemIo800State;
+
+
+int prep_is_iomap_contiguous(ISAPrepSystemIo800State *s);
+
+
+#endif
new file mode 100644
@@ -0,0 +1,335 @@
+/*
+ * QEMU PReP System I/O emulation
+ *
+ * Copyright (c) 2003-2007 Jocelyn Mayer
+ * Copyright (c) 2010 Herve Poussineau
+ * Copyright (c) 2010-2011 Andreas Faerber
+ *
+ * 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 "ppc_prep.h"
+
+//#define DEBUG_PREPIO
+
+#ifdef DEBUG_PREPIO
+#define DPRINTF(fmt, ...) \
+do { \
+ fprintf(stderr, "io800: " fmt , ## __VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(fmt, ...) \
+do {} while (0)
+#endif
+#define BADF(fmt, ...) \
+do { fprintf(stderr, "io800 ERROR: " fmt , ## __VA_ARGS__); } while (0)
+
+/* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */
+#define BIT(n) (1 << (7 - (n)))
+
+
+/* PORT 0092 -- Special Port 92 (Read/Write) */
+
+enum {
+ PORT0092_SOFTRESET = BIT(7),
+ PORT0092_LE_MODE = BIT(6),
+};
+
+static void prep_port0092_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ PrepIo800State *s = opaque;
+
+ if ((val & PORT0092_SOFTRESET) != 0) {
+ qemu_irq_raise(s->softreset_irq);
+ } else {
+ qemu_irq_lower(s->softreset_irq);
+ }
+
+ if ((val & PORT0092_LE_MODE) != 0) {
+ /* XXX Not supported yet */
+ } else {
+ /* Nothing to do */
+ }
+}
+
+static uint32_t prep_port0092_read(void *opaque, uint32_t addr)
+{
+ /* XXX LE mode unsupported */
+ return 0;
+}
+
+/* SIMM ID (32/8 MB) */
+
+static uint32_t prep_port0803_read(void *opaque, uint32_t addr)
+{
+ return 3; // XXX or 0xe0
+}
+
+/* SIMM Presence */
+
+static uint32_t prep_port0804_read(void *opaque, uint32_t addr)
+{
+ return 0;
+}
+
+/* PORT 0808 -- Hardfile Light Register (Write Only) */
+
+enum {
+ PORT0808_HARDFILE_LIGHT_ON = BIT(7),
+};
+
+static void prep_port0808_write(void *opaque, uint32_t addr, uint32_t val)
+{
+}
+
+/* PORT 080C -- Equipment Present Register (Read Only) */
+
+enum {
+ PORT080C_L2_CACHE_ABSENT = BIT(7),
+ PORT080C_UPGRADE_PROCESSOR_ABSENT = BIT(6),
+ PORT080C_L2_CACHE_256KB_OR_ABSENT = BIT(5),
+ PORT080C_L2_CACHE_COPYBACK_OR_ABSENT = BIT(4),
+ PORT080C_PCI_SLOT1_CARD_ABSENT = BIT(3),
+ PORT080C_PCI_SLOT2_CARD_ABSENT = BIT(2),
+ PORT080C_SCSI_FUSE_OK = BIT(1),
+};
+
+static uint32_t prep_port080c_read(void *opaque, uint32_t addr)
+{
+ /* no L2 cache
+ * no upgrade processor
+ * no cards in PCI slots
+ * SCSI fuse is bad
+ */
+ return PORT080C_L2_CACHE_ABSENT |
+ PORT080C_L2_CACHE_256KB_OR_ABSENT |
+ PORT080C_L2_CACHE_COPYBACK_OR_ABSENT |
+ PORT080C_UPGRADE_PROCESSOR_ABSENT |
+ PORT080C_PCI_SLOT1_CARD_ABSENT |
+ PORT080C_PCI_SLOT2_CARD_ABSENT;
+}
+
+/* PORT 0810 -- Password Protect 1 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0810_write(void *opaque, uint32_t addr, uint32_t val)
+{
+}
+
+/* PORT 0812 -- Password Protect 2 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0812_write(void *opaque, uint32_t addr, uint32_t val)
+{
+}
+
+/* PORT 0814 -- L2 Invalidate Register (Write Only) */
+
+static void prep_port0814_write(void *opaque, uint32_t addr, uint32_t val)
+{
+}
+
+/* PORT 0818 -- Reserved for Keylock (Read Only) */
+
+enum {
+ PORT0818_KEYLOCK_SIGNAL_HIGH = BIT(7),
+};
+
+static uint32_t prep_port0818_read(void *opaque, uint32_t addr)
+{
+ return 0;
+}
+
+/* PORT 081C -- System Control Register (Read/Write) */
+
+enum {
+ PORT081C_FLOPPY_MOTOR_INHIBIT = BIT(3),
+ PORT081C_MASK_TEA = BIT(2),
+ PORT081C_L2_UPDATE_INHIBIT = BIT(1),
+ PORT081C_L2_CACHEMISS_INHIBIT = BIT(0),
+};
+
+static void prep_port081c_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ PrepIo800State *s = opaque;
+ s->system_control = val;
+}
+
+static uint32_t prep_port081c_read(void *opaque, uint32_t addr)
+{
+ PrepIo800State *s = opaque;
+ return s->system_control;
+}
+
+/* Memory Controller Size Programming Register */
+
+static void prep_port0820_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ PrepIo800State *s = opaque;
+ if (val == 0xe3) {
+ s->mem_parity_error_address = 1; /* HACK */
+ }
+}
+
+/* Read Memory Parity Error */
+
+static uint32_t prep_port0840_read(void *opaque, uint32_t addr)
+{
+ PrepIo800State *s = opaque;
+ return s->mem_parity_error_address != 0 ? 1 : 0;
+}
+
+/* System Board Identification */
+
+static uint32_t prep_port0852_read(void *opaque, uint32_t addr)
+{
+ ISAPrepSystemIo800State *s = opaque;
+ return s->board_identification;
+}
+
+/* PORT 0850 -- I/O Map Type Register (Read/Write) */
+
+enum {
+ PORT0850_IOMAP_NONCONTIGUOUS = BIT(7),
+};
+
+static uint32_t prep_port0850_read(void *opaque, uint32_t addr)
+{
+ PrepIo800State *s = opaque;
+ return s->iomap_type;
+}
+
+static void prep_port0850_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ PrepIo800State *s = opaque;
+ s->iomap_type = val;
+}
+
+int prep_is_iomap_contiguous(ISAPrepSystemIo800State *s)
+{
+ return (s->state.iomap_type & PORT0850_IOMAP_NONCONTIGUOUS) == 0;
+}
+
+
+static uint32_t ppc_parity_error_readl(void *opaque, target_phys_addr_t addr)
+{
+ PrepIo800State* s = opaque;
+ uint32_t val = s->mem_parity_error_address;
+
+ DPRINTF("%s: read 0x%08x at [" TARGET_FMT_plx "]\n", __func__, val, addr);
+
+ return val;
+}
+
+static CPUReadMemoryFunc * const ppc_parity_error_read[] = {
+ NULL,
+ NULL,
+ ppc_parity_error_readl,
+};
+
+static CPUWriteMemoryFunc * const ppc_parity_error_write[] = {
+ NULL,
+ NULL,
+ NULL,
+};
+
+static void prep_register_ioport(uint16_t start, int length,
+ IOPortReadFunc *read_func,
+ IOPortWriteFunc *write_func,
+ void *opaque)
+{
+ if (read_func != NULL) {
+ register_ioport_read(start, length, 1, read_func, opaque);
+ }
+ if (write_func != NULL) {
+ register_ioport_write(start, length, 1, write_func, opaque);
+ }
+}
+
+static int prep_systemio_isa_init(ISADevice *dev)
+{
+ ISAPrepSystemIo800State *isa = DO_UPCAST(ISAPrepSystemIo800State, dev, dev);
+ PrepIo800State *s = &isa->state;
+ int io;
+
+ s->iomap_type = 0; /* contiguous mode CHECKME 0x1? */
+ s->softreset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
+
+ prep_register_ioport(0x0092, 1, prep_port0092_read,
+ prep_port0092_write, s);
+
+ prep_register_ioport(0x0803, 1, prep_port0803_read, NULL, s);
+ prep_register_ioport(0x0804, 1, prep_port0804_read, NULL, s);
+ prep_register_ioport(0x0808, 4, NULL,
+ prep_port0808_write, s);
+ prep_register_ioport(0x080c, 4, prep_port080c_read, NULL, s);
+ prep_register_ioport(0x0810, 2, NULL,
+ prep_port0810_write, s);
+ prep_register_ioport(0x0812, 2, NULL,
+ prep_port0812_write, s);
+ prep_register_ioport(0x0814, 4, NULL,
+ prep_port0814_write, s);
+ prep_register_ioport(0x0818, 1, prep_port0818_read, NULL, s);
+ prep_register_ioport(0x081c, 4, prep_port081c_read,
+ prep_port081c_write, s);
+ prep_register_ioport(0x0820, 1, NULL,
+ prep_port0820_write, s);
+ prep_register_ioport(0x0840, 2, prep_port0840_read, NULL, s);
+ /* Reference Implementation supposedly uses 0x0850 - 0x0853 */
+ prep_register_ioport(0x0850, 2, prep_port0850_read,
+ prep_port0850_write, s);
+ prep_register_ioport(0x0852, 1, prep_port0852_read, NULL, isa);
+
+ io = cpu_register_io_memory(ppc_parity_error_read,
+ ppc_parity_error_write, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0xBFFFEFF0, 0x4, io);
+ return 0;
+}
+
+static const VMStateDescription vmstate_prep_systemio = {
+ .name = "prep_systemio",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(state.system_control, ISAPrepSystemIo800State),
+ VMSTATE_UINT8(state.iomap_type, ISAPrepSystemIo800State),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static ISADeviceInfo prep_systemio800_info = {
+ .init = prep_systemio_isa_init,
+ .qdev.name = "prep-systemio800",
+ .qdev.size = sizeof(ISAPrepSystemIo800State),
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_UINT8("board-identification", ISAPrepSystemIo800State,
+ board_identification, 0),
+ DEFINE_PROP_END_OF_LIST()
+ },
+ .qdev.vmsd = &vmstate_prep_systemio,
+ .qdev.no_user = 1,
+};
+
+static void prep_systemio_register_devices(void)
+{
+ isa_qdev_register(&prep_systemio800_info);
+}
+
+device_init(prep_systemio_register_devices)