Hi all,
Here is a slightly reworked version of Cormac's GSoC MacOS 9 patchset which I believe is ready to apply.
A considerable amount of time was spent by Cormac finding the correct set of properties required by OS 9 whilst also not regressing existing images. The patchset in it's current form here passes all of my local PPC image tests while still progressing OS 9 boot as before.
The patches are mostly untouched other than adding my SoB except for patch 3 where I altered the version referenced in the comment and commit message, and splitting patch 4 into 2 separate patches as requested by Alex, along with some other minor tidy-ups.
Note: patch 1 from Cormac's original patchset was a hack from me to allow the OS 9 bootloader to run, however it is not included here because it causes problems with yaboot. People interested in the OS 9 work can apply the patch by hand in the meantime.
Several review comments suggested the use of a helper function for string properties, however recent work on SPARC has shown that building up string properties in this way is prevalent throughout the OpenBIOS codebase. In the interest of progressing work in this area, I'd like to apply the patches as-is and then globally rework string properties using a helper at a later date.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Cormac O'Brien (4): ppc: fix up power-mgt properties ppc: add ESCC legacy support ppc: fix CUDA ADB packet header format ppc: fix up IDE device tree and control transfer
Mark Cave-Ayland (1): ppc: add ob_ide_quiesce() and call it from the PPC CIF quiesce word
openbios-devel/arch/ppc/qemu/methods.c | 2 + openbios-devel/drivers/cuda.c | 17 +++++- openbios-devel/drivers/escc.c | 88 ++++++++++++++++++++++++------ openbios-devel/drivers/escc.h | 2 + openbios-devel/drivers/ide.c | 36 ++++++++++-- openbios-devel/drivers/pci.c | 6 ++ openbios-devel/include/drivers/drivers.h | 1 + 7 files changed, 128 insertions(+), 24 deletions(-)
From: Cormac O'Brien cormac@c-obrien.org
Modify some basic device tree properties to more accurately emulate a real Mac machine.
Signed-off-by: Cormac O'Brien cormac@c-obrien.org Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/drivers/cuda.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/openbios-devel/drivers/cuda.c b/openbios-devel/drivers/cuda.c index 9555dea..f117b0b 100644 --- a/openbios-devel/drivers/cuda.c +++ b/openbios-devel/drivers/cuda.c @@ -380,7 +380,8 @@ powermgt_init(char *path)
ph = find_dev(buf); set_property(ph, "device_type", "power-mgt", 10); - set_property(ph, "compatible", "power-mgt", 10); + set_property(ph, "mgt-kind", "min-consumption-pwm-led", strlen("min-consumption-pwm-led") + 1); + set_property(ph, "compatible", "cuda", strlen("cuda") + 1); }
cuda_t *cuda_init (const char *path, phys_addr_t base)
From: Cormac O'Brien cormac@c-obrien.org
Mac OS 9 requires that the host provide escc-legacy serial ports, so we add them here to get further in the boot process.
Signed-off-by: Cormac O'Brien cormac@c-obrien.org Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/drivers/escc.c | 88 +++++++++++++++++++++++++++++++++-------- openbios-devel/drivers/escc.h | 2 + openbios-devel/drivers/pci.c | 6 +++ 3 files changed, 79 insertions(+), 17 deletions(-)
diff --git a/openbios-devel/drivers/escc.c b/openbios-devel/drivers/escc.c index 240043b..afb97fa 100644 --- a/openbios-devel/drivers/escc.c +++ b/openbios-devel/drivers/escc.c @@ -380,12 +380,22 @@ ob_zs_init(phys_addr_t base, uint64_t offset, int intr, int slave, int keyboard)
static void escc_add_channel(const char *path, const char *node, phys_addr_t addr, - uint32_t offset) + int esnum) { char buf[64], tty[32]; phandle_t dnode, aliases; - int len; - cell props[2]; + + cell props[10]; + int offset; + int legacy; + + switch (esnum) { + case 2: offset = 1; legacy = 0; break; + case 3: offset = 0; legacy = 0; break; + case 4: offset = 1; legacy = 1; break; + case 5: offset = 0; legacy = 1; break; + default: return; + }
/* add device */
@@ -411,16 +421,28 @@ escc_add_channel(const char *path, const char *node, phys_addr_t addr, set_property(dnode, "device_type", "serial", strlen("serial") + 1);
- snprintf(buf, sizeof(buf), "ch-%s", node); - len = strlen(buf) + 1; - snprintf(buf + len, sizeof(buf) - len, "CHRP,es2"); - set_property(dnode, "compatible", buf, len + 9); - - props[0] = IO_ESCC_OFFSET + offset * 0x20; - props[1] = 0x00000020; - set_property(dnode, "reg", (char *)&props, 2 * sizeof(cell)); + snprintf(buf, sizeof(buf), "chrp,es%d", esnum); + set_property(dnode, "compatible", buf, 9); + + if (legacy) { + props[0] = IO_ESCC_LEGACY_OFFSET + offset * 0x4; + props[1] = 0x00000001; + props[2] = IO_ESCC_LEGACY_OFFSET + offset * 0x4 + 2; + props[3] = 0x00000001; + props[4] = IO_ESCC_LEGACY_OFFSET + offset * 0x4 + 6; + props[5] = 0x00000001; + set_property(dnode, "reg", (char *)&props, 6 * sizeof(cell)); + } else { + props[0] = IO_ESCC_OFFSET + offset * 0x20; + props[1] = 0x00000020; + set_property(dnode, "reg", (char *)&props, 2 * sizeof(cell)); + }
- props[0] = addr + IO_ESCC_OFFSET + offset * 0x20; + if (legacy) { + props[0] = addr + IO_ESCC_LEGACY_OFFSET + offset * 0x4; + } else { + props[0] = addr + IO_ESCC_OFFSET + offset * 0x20; + } OLDWORLD(set_property(dnode, "AAPL,address", (char *)&props, 1 * sizeof(cell)));
@@ -430,13 +452,21 @@ escc_add_channel(const char *path, const char *node, phys_addr_t addr,
props[0] = (0x24) + offset; props[1] = 0; + props[2] = 0; NEWWORLD(set_property(dnode, "interrupts", - (char *)&props, 2 * sizeof(cell))); + (char *)&props, 3 * sizeof(cell)));
device_end();
- uart_init_line((unsigned char*)addr + IO_ESCC_OFFSET + offset * 0x20, - CONFIG_SERIAL_SPEED); + if (legacy) { + uart_init_line( + (unsigned char*)addr + IO_ESCC_LEGACY_OFFSET + offset * 0x4, + CONFIG_SERIAL_SPEED); + } else { + uart_init_line( + (unsigned char*)addr + IO_ESCC_OFFSET + offset * 0x20, + CONFIG_SERIAL_SPEED); + } }
void @@ -467,10 +497,34 @@ escc_init(const char *path, phys_addr_t addr)
fword("finish-device");
- escc_add_channel(buf, "a", addr, 1); - escc_add_channel(buf, "b", addr, 0); + escc_add_channel(buf, "a", addr, 2); + escc_add_channel(buf, "b", addr, 3);
escc_serial_dev = (unsigned char *)addr + IO_ESCC_OFFSET + (CONFIG_SERIAL_PORT ? 0 : 0x20); + + push_str(path); + fword("find-device"); + fword("new-device"); + + push_str("escc-legacy"); + fword("device-name"); + + snprintf(buf, sizeof(buf), "%s/escc-legacy", path); + + dnode = find_dev(buf); + + set_int_property(dnode, "#address-cells", 1); + props[0] = __cpu_to_be32(IO_ESCC_LEGACY_OFFSET); + props[1] = __cpu_to_be32(IO_ESCC_LEGACY_SIZE); + set_property(dnode, "reg", (char *)&props, sizeof(props)); + set_property(dnode, "device_type", "escc-legacy", + strlen("escc-legacy") + 1); + set_property(dnode, "compatible", "chrp,es1", 9); + + fword("finish-device"); + + escc_add_channel(buf, "a", addr, 4); + escc_add_channel(buf, "b", addr, 5); } #endif diff --git a/openbios-devel/drivers/escc.h b/openbios-devel/drivers/escc.h index caaf00d..e73f267 100644 --- a/openbios-devel/drivers/escc.h +++ b/openbios-devel/drivers/escc.h @@ -1,6 +1,8 @@
#define IO_ESCC_SIZE 0x00001000 #define IO_ESCC_OFFSET 0x00013000 +#define IO_ESCC_LEGACY_SIZE 0x00001000 +#define IO_ESCC_LEGACY_OFFSET 0x00012000
#define ZS_REGS 8
diff --git a/openbios-devel/drivers/pci.c b/openbios-devel/drivers/pci.c index 366f4a1..a68e9dc 100644 --- a/openbios-devel/drivers/pci.c +++ b/openbios-devel/drivers/pci.c @@ -1420,6 +1420,12 @@ static void ob_pci_host_set_interrupt_map(phandle_t host) target_node = find_dev("/pci/mac-io/escc/ch-b"); set_int_property(target_node, "interrupt-parent", dnode);
+ target_node = find_dev("/pci/mac-io/escc-legacy/ch-a"); + set_int_property(target_node, "interrupt-parent", dnode); + + target_node = find_dev("/pci/mac-io/escc-legacy/ch-b"); + set_int_property(target_node, "interrupt-parent", dnode); + /* QEMU only emulates 2 of the 3 ata buses currently */ /* On a new world Mac these are not numbered but named by the * ATA version they support. Thus we have: ata-3, ata-3, ata-4
From: Cormac O'Brien cormac@c-obrien.org
QEMU <= 2.4 uses a 2-byte header for CUDA ADB packets where it should use a 3-byte one, so this commit allows cuda_adb_req() to differentiate between the two formats and act accordingly.
Signed-off-by: Cormac O'Brien cormac@c-obrien.org Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/drivers/cuda.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/openbios-devel/drivers/cuda.c b/openbios-devel/drivers/cuda.c index f117b0b..836380f 100644 --- a/openbios-devel/drivers/cuda.c +++ b/openbios-devel/drivers/cuda.c @@ -144,8 +144,18 @@ static int cuda_adb_req (void *host, const uint8_t *snd_buf, int len, // CUDA_DPRINTF("len: %d %02x\n", len, snd_buf[0]); len = cuda_request(host, ADB_PACKET, snd_buf, len, buffer); if (len > 1 && buffer[0] == ADB_PACKET) { - pos = buffer + 2; - len -= 2; + /* QEMU <= 2.4 uses a 2-byte header where it should use a 3-byte one, + * so we check to see what kind of header we ought to use. + */ + if (len > 2 && buffer[2] == snd_buf[0]) { + /* Correct 3-byte header */ + pos = buffer + 3; + len -= 3; + } else { + /* Old 2-byte header */ + pos = buffer + 2; + len -= 2; + } } else { pos = buffer + 1; len = -1;
On 09/10/15 17:20, Mark Cave-Ayland wrote:
From: Cormac O'Brien cormac@c-obrien.org
QEMU <= 2.4 uses a 2-byte header for CUDA ADB packets where it should use a 3-byte one, so this commit allows cuda_adb_req() to differentiate between the two formats and act accordingly.
Signed-off-by: Cormac O'Brien cormac@c-obrien.org Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
openbios-devel/drivers/cuda.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/openbios-devel/drivers/cuda.c b/openbios-devel/drivers/cuda.c index f117b0b..836380f 100644 --- a/openbios-devel/drivers/cuda.c +++ b/openbios-devel/drivers/cuda.c @@ -144,8 +144,18 @@ static int cuda_adb_req (void *host, const uint8_t *snd_buf, int len, // CUDA_DPRINTF("len: %d %02x\n", len, snd_buf[0]); len = cuda_request(host, ADB_PACKET, snd_buf, len, buffer); if (len > 1 && buffer[0] == ADB_PACKET) {
pos = buffer + 2;
len -= 2;
/* QEMU <= 2.4 uses a 2-byte header where it should use a 3-byte one,
* so we check to see what kind of header we ought to use.
*/
if (len > 2 && buffer[2] == snd_buf[0]) {
/* Correct 3-byte header */
pos = buffer + 3;
len -= 3;
} else {
/* Old 2-byte header */
pos = buffer + 2;
len -= 2;
} else { pos = buffer + 1; len = -1;}
For the record this patch is actually correct, however after some further testing with QEMU the comment is wrong - it's only ADB *error* packets which have a 3 byte header, whilst normal packets still have a 2 byte header.
Other than that the patchset passes all my tests here, so I'll commit it shortly in preparation for sending a QEMU pull request.
ATB,
Mark.
From: Cormac O'Brien cormac@c-obrien.org
Mac OS 9 is finicky about devices having the correct properties, so we change some IDE data to more closely model a real New World Mac.
Signed-off-by: Cormac O'Brien cormac@c-obrien.org Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/drivers/ide.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/openbios-devel/drivers/ide.c b/openbios-devel/drivers/ide.c index 327c64a..ce9305a 100644 --- a/openbios-devel/drivers/ide.c +++ b/openbios-devel/drivers/ide.c @@ -1581,6 +1581,12 @@ int macio_ide_init(const char *path, uint32_t addr, int nb_channels) set_property(dnode, "compatible", (is_oldworld() ? "heathrow-ata" : "keylargo-ata"), 13);
+ set_property(dnode, "model", ((current_channel == 3) ? + "ata-3" : "ata-4"), strlen("ata-*") + 1); + + set_property(dnode, "AAPL,connector", "ata", + strlen("ata") + 1); + props[0] = 0x00000526; props[1] = 0x00000085; props[2] = 0x00000025; @@ -1589,8 +1595,8 @@ int macio_ide_init(const char *path, uint32_t addr, int nb_channels) props[5] = 0x00000000; props[6] = 0x00000000; props[7] = 0x00000000; - OLDWORLD(set_property(dnode, "AAPL,pio-timing", - (char *)&props, 8*sizeof(props[0]))); + set_property(dnode, "AAPL,pio-timing", + (char *)&props, 8*sizeof(props[0]));
/* The first interrupt entry is the ide interrupt, the second the dbdma interrupt */ @@ -1634,8 +1640,8 @@ int macio_ide_init(const char *path, uint32_t addr, int nb_channels) (char *)&props, 2*sizeof(props[0])));
props[0] = 0; - OLDWORLD(set_property(dnode, "AAPL,bus-id", (char*)props, - 1 * sizeof(props[0]))); + set_property(dnode, "AAPL,bus-id", (char*)props, + 1 * sizeof(props[0])); IDE_DPRINTF(DEV_NAME": [io ports 0x%lx]\n", current_channel, chan->mmio);
Add a new ob_ide_quiesce() function and hook it into QEMU PPC's ciface_quiesce() routine to properly prepare the drives for transferring control to the operating system.
Without this OS 9 becomes confused about the initial drive state on boot and refuses to correctly detect and initialise it.
Based upon an original patch by Cormac O'Brien cormac@c-obrien.org.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/arch/ppc/qemu/methods.c | 2 ++ openbios-devel/drivers/ide.c | 22 ++++++++++++++++++++++ openbios-devel/include/drivers/drivers.h | 1 + 3 files changed, 25 insertions(+)
diff --git a/openbios-devel/arch/ppc/qemu/methods.c b/openbios-devel/arch/ppc/qemu/methods.c index cb72bc1..930b47c 100644 --- a/openbios-devel/arch/ppc/qemu/methods.c +++ b/openbios-devel/arch/ppc/qemu/methods.c @@ -114,6 +114,8 @@ static void ciface_quiesce( unsigned long args[], unsigned long ret[] ) { usb_exit(); + + ob_ide_quiesce(); #if 0 unsigned long msr; /* This seems to be the correct thing to do - but I'm not sure */ diff --git a/openbios-devel/drivers/ide.c b/openbios-devel/drivers/ide.c index ce9305a..5125b78 100644 --- a/openbios-devel/drivers/ide.c +++ b/openbios-devel/drivers/ide.c @@ -1488,6 +1488,28 @@ int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0, return 0; }
+void ob_ide_quiesce(void) +{ + struct ide_channel *channel; + int i; + + channel = channels; + while (channel) { + for (i = 0; i < 2; i++) { + struct ide_drive *drive = &channel->drives[i]; + + if (!drive->present) + continue; + + ob_ide_select_drive(drive); + ob_ide_software_reset(drive); + ob_ide_device_type_check(drive); + } + + channel = channel->next; + } +} + #if defined(CONFIG_DRIVER_MACIO) static unsigned char macio_ide_inb(struct ide_channel *chan, unsigned int port) diff --git a/openbios-devel/include/drivers/drivers.h b/openbios-devel/include/drivers/drivers.h index 3b83b12..48f81a8 100644 --- a/openbios-devel/include/drivers/drivers.h +++ b/openbios-devel/include/drivers/drivers.h @@ -52,6 +52,7 @@ void kbd_init(uint64_t base); /* drivers/ide.c */ int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0, uint32_t io_port1, uint32_t ctl_port1); +void ob_ide_quiesce(void); int macio_ide_init(const char *path, uint32_t addr, int nb_channels); #endif #ifdef CONFIG_DRIVER_ESP
On behalf of everyone who is eager to see Mac OS 9 boot in QEMU, thank you.
On 09/10/15 17:29, Programmingkid wrote:
On behalf of everyone who is eager to see Mac OS 9 boot in QEMU, thank you.
I would direct the thanks towards Cormac for working on this over the summer, and also Google for running GSoC which is what has made this all possible.
ATB,
Mark.