[OpenBIOS] [PATCH 3/5] ppc: add ESCC legacy support

Mark Cave-Ayland mark.cave-ayland at ilande.co.uk
Wed Aug 19 21:19:46 CET 2015


On 18/08/15 19:17, Cormac O'Brien wrote:

> 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 at c-obrien.org>
> ---
>  drivers/escc.c | 85 +++++++++++++++++++++++++++++++++++++++++++++-------------
>  drivers/escc.h |  2 ++
>  drivers/pci.c  |  6 +++++
>  3 files changed, 75 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/escc.c b/drivers/escc.c
> index 240043b..972b06a 100644
> --- a/drivers/escc.c
> +++ b/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)));
>  
> @@ -429,14 +451,17 @@ escc_add_channel(const char *path, const char *node, phys_addr_t addr,
>              (char *)&props, 1 * sizeof(cell)));
>  
>      props[0] = (0x24) + offset;
> -    props[1] = 0;
> +    props[1] = 4 + (offset * 2);
> +    props[2] = 5 + (offset * 2);

I'm slightly curious as to whether things still work with props[1] and
props[2] set to 0 here. The reason being that these reference DBDMA
serial interrupts which QEMU doesn't (yet) emulate and so it might be
better to declare these as zero which should tell the driver to disable
the interrupt rather than waiting for something that is non-existent.

>      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_OFFSET + offset * 0x20,
> +                       CONFIG_SERIAL_SPEED);
> +    }

Can we also initialise the legacy ports here at the same time, e.g.

if (legacy) {
   ...
   ...
} else {
   ...
   ...
}

For QEMU it doesn't necessarily matter since the legacy ports are
aliased onto the non-legacy ports, but in case this changes at a later
date (or someone is interested to run this on real hardware) then we
might as well do this at the same time.

>  }
>  
>  void
> @@ -467,10 +492,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/drivers/escc.h b/drivers/escc.h
> index caaf00d..e73f267 100644
> --- a/drivers/escc.h
> +++ b/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/drivers/pci.c b/drivers/pci.c
> index 366f4a1..a68e9dc 100644
> --- a/drivers/pci.c
> +++ b/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
> 


ATB,

Mark.




More information about the OpenBIOS mailing list