mac-io: Add escc-legacy memory alias region

Mac OS X's debugging serial driver accesses the ESCC through a different
register layout, called "escc-legacy". This layout differs from the normal
escc register layout purely by the location of the respective registers.

This patch adds a memory alias region that takes normal escc registers and
maps them into the escc-legacy register space.

With this patch applied, a Mac OS X guest successfully emits debug output
on the serial port when run with debug parameters set, for example by running:

  $ qemu-system-ppc -prom-env -'boot-args=-v debug=0x8 io=0xff serial=0x3' \
                    -cdrom 10.4.iso -boot d

Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
Alexander Graf 2013-06-26 13:58:31 +02:00
parent 593c181160
commit 0d54a5024f

View File

@ -69,12 +69,59 @@ typedef struct NewWorldMacIOState {
MACIOIDEState ide[2];
} NewWorldMacIOState;
/*
* The mac-io has two interfaces to the ESCC. One is called "escc-legacy",
* while the other one is the normal, current ESCC interface.
*
* The magic below creates memory aliases to spawn the escc-legacy device
* purely by rerouting the respective registers to our escc region. This
* works because the only difference between the two memory regions is the
* register layout, not their semantics.
*
* Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf
*/
static void macio_escc_legacy_setup(MacIOState *macio_state)
{
MemoryRegion *escc_legacy = g_new(MemoryRegion, 1);
MemoryRegion *bar = &macio_state->bar;
int i;
static const int maps[] = {
0x00, 0x00,
0x02, 0x20,
0x04, 0x10,
0x06, 0x30,
0x08, 0x40,
0x0A, 0x50,
0x60, 0x60,
0x70, 0x70,
0x80, 0x70,
0x90, 0x80,
0xA0, 0x90,
0xB0, 0xA0,
0xC0, 0xB0,
0xD0, 0xC0,
0xE0, 0xD0,
0xF0, 0xE0,
};
memory_region_init(escc_legacy, "escc-legacy", 256);
for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
MemoryRegion *port = g_new(MemoryRegion, 1);
memory_region_init_alias(port, "escc-legacy-port", macio_state->escc_mem,
maps[i+1], 0x2);
memory_region_add_subregion(escc_legacy, maps[i], port);
}
memory_region_add_subregion(bar, 0x12000, escc_legacy);
}
static void macio_bar_setup(MacIOState *macio_state)
{
MemoryRegion *bar = &macio_state->bar;
if (macio_state->escc_mem) {
memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem);
macio_escc_legacy_setup(macio_state);
}
}