symbian-qemu-0.9.1-12/qemu-symbian-svp/pc-bios/ohw.diff
author johnathan.white@2718R8BGH51.accenture.com
Mon, 08 Mar 2010 18:45:03 +0000
changeset 46 b6935a90ca64
parent 1 2fb8b9db1c86
permissions -rw-r--r--
Modify framebuffer and NGA framebuffer to read screen size from board model dtb file. Optimise memory usuage of frame buffer Add example minigui application with hooks to profiler (which writes results to S:\). Modified NGA framebuffer to run its own dfc queue at high priority

diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/bios.h OpenHackWare-release-0.4/src/bios.h
--- OpenHackWare-release-0.4.org/src/bios.h	2005-04-06 23:20:22.000000000 +0200
+++ OpenHackWare-release-0.4/src/bios.h	2005-07-07 01:10:20.000000000 +0200
@@ -64,6 +64,7 @@
     ARCH_CHRP,
     ARCH_MAC99,
     ARCH_POP,
+    ARCH_HEATHROW,
 };
 
 /* Hardware definition(s) */
@@ -174,6 +175,7 @@
 int bd_ioctl (bloc_device_t *bd, int func, void *args);
 uint32_t bd_seclen (bloc_device_t *bd);
 void bd_close (bloc_device_t *bd);
+void bd_reset_all(void);
 uint32_t bd_seclen (bloc_device_t *bd);
 uint32_t bd_maxbloc (bloc_device_t *bd);
 void bd_sect2CHS (bloc_device_t *bd, uint32_t secnum,
@@ -183,12 +185,12 @@
 part_t *bd_probe (int boot_device);
 bloc_device_t *bd_get (int device);
 void bd_put (bloc_device_t *bd);
-void bd_set_boot_part (bloc_device_t *bd, part_t *partition);
+void bd_set_boot_part (bloc_device_t *bd, part_t *partition, int partnum);
 part_t **_bd_parts (bloc_device_t *bd);
 
 void ide_pci_pc_register (uint32_t io_base0, uint32_t io_base1,
                           uint32_t io_base2, uint32_t io_base3,
-                          void *OF_private);
+                          void *OF_private0, void *OF_private1);
 void ide_pci_pmac_register (uint32_t io_base0, uint32_t io_base1,
                             void *OF_private);
 
@@ -399,17 +401,23 @@
                               uint16_t min_grant, uint16_t max_latency);
 void OF_finalize_pci_host (void *dev, int first_bus, int nb_busses);
 void OF_finalize_pci_device (void *dev, uint8_t bus, uint8_t devfn,
-                             uint32_t *regions, uint32_t *sizes);
+                             uint32_t *regions, uint32_t *sizes,
+                             int irq_line);
 void OF_finalize_pci_macio (void *dev, uint32_t base_address, uint32_t size,
                             void *private_data);
+void OF_finalize_pci_ide (void *dev, 
+                          uint32_t io_base0, uint32_t io_base1,
+                          uint32_t io_base2, uint32_t io_base3);
 int OF_register_bus (const unsigned char *name, uint32_t address,
                      const unsigned char *type);
 int OF_register_serial (const unsigned char *bus, const unsigned char *name,
                         uint32_t io_base, int irq);
 int OF_register_stdio (const unsigned char *dev_in,
                        const unsigned char *dev_out);
-void OF_vga_register (const unsigned char *name, uint32_t address,
-                      int width, int height, int depth);
+void OF_vga_register (const unsigned char *name, unused uint32_t address,
+                      int width, int height, int depth,
+                      unsigned long vga_bios_addr, 
+                      unsigned long vga_bios_size);
 void *OF_blockdev_register (void *parent, void *private,
                             const unsigned char *type,
                             const unsigned char *name, int devnum,
diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/bloc.c OpenHackWare-release-0.4/src/bloc.c
--- OpenHackWare-release-0.4.org/src/bloc.c	2005-04-06 23:21:00.000000000 +0200
+++ OpenHackWare-release-0.4/src/bloc.c	2005-07-08 00:28:26.000000000 +0200
@@ -55,6 +55,7 @@
     /* Partitions */
     part_t *parts, *bparts;
     part_t *boot_part;
+    int bpartnum;
     /* Chain */
     bloc_device_t *next;
 };
@@ -66,6 +67,7 @@
 
 static int ide_initialize (bloc_device_t *bd, int device);
 static int ide_read_sector (bloc_device_t *bd, void *buffer, int secnum);
+static int ide_reset (bloc_device_t *bd);
 
 static int mem_initialize (bloc_device_t *bd, int device);
 static int mem_read_sector (bloc_device_t *bd, void *buffer, int secnum);
@@ -212,6 +214,17 @@
 {
 }
 
+void bd_reset_all(void)
+{
+    bloc_device_t *bd;
+    for (bd = bd_list; bd != NULL; bd = bd->next) {
+        if (bd->init == &ide_initialize) {
+            /* reset IDE drive because Darwin wants all IDE devices to be reset */
+            ide_reset(bd);
+        }
+    }
+}
+
 uint32_t bd_seclen (bloc_device_t *bd)
 {
     return bd->seclen;
@@ -223,10 +236,12 @@
 }
 
 /* XXX: to be suppressed */
-void bd_set_boot_part (bloc_device_t *bd, part_t *partition)
+void bd_set_boot_part (bloc_device_t *bd, part_t *partition, int partnum)
 {
+    dprintf("%s: part %p (%p) %d\n", __func__, partition, bd->boot_part, partnum);
     if (bd->boot_part == NULL) {
         bd->boot_part = partition;
+        bd->bpartnum = partnum;
     }
 }
 
@@ -240,6 +255,13 @@
     return &bd->bparts;
 }
 
+void bd_set_boot_device (bloc_device_t *bd)
+{
+#if defined (USE_OPENFIRMWARE)
+    OF_blockdev_set_boot_device(bd->OF_private, bd->bpartnum, "\\\\ofwboot");
+#endif
+}
+
 part_t *bd_probe (int boot_device)
 {
     char devices[] = { /*'a', 'b',*/ 'c', 'd', 'e', 'f', 'm', '\0', };
@@ -272,9 +294,7 @@
         tmp = part_probe(bd, force_raw);
         if (boot_device == bd->device) {
             boot_part = tmp;
-#if defined (USE_OPENFIRMWARE)
-            OF_blockdev_set_boot_device(bd->OF_private, 2, "\\\\ofwboot");
-#endif
+            bd_set_boot_device(bd);
         }
     }
 
@@ -717,34 +737,29 @@
 /* IDE PCI access for pc */
 static uint8_t ide_pci_port_read (bloc_device_t *bd, int port)
 {
-    eieio();
-
-    return *(uint8_t *)(bd->io_base + port);
+    uint8_t value;
+    value = inb(bd->io_base + port);
+    return value;
 }
 
 static void ide_pci_port_write (bloc_device_t *bd, int port, uint8_t value)
 {
-    *(uint8_t *)(bd->io_base + port) = value;
-    eieio();
+    outb(bd->io_base + port, value);
 }
 
 static uint32_t ide_pci_data_readl (bloc_device_t *bd)
 {
-    eieio();
-
-    return *((uint32_t *)bd->io_base);
+    return inl(bd->io_base);
 }
 
 static void ide_pci_data_writel (bloc_device_t *bd, uint32_t val)
 {
-    *(uint32_t *)(bd->io_base) = val;
-    eieio();
+    outl(bd->io_base, val);
 }
 
 static void ide_pci_control_write (bloc_device_t *bd, uint32_t val)
 {
-    *((uint8_t *)bd->tmp) = val;
-    eieio();
+    outb(bd->tmp + 2, val);
 }
 
 static ide_ops_t ide_pci_pc_ops = {
@@ -761,7 +776,7 @@
 
 void ide_pci_pc_register (uint32_t io_base0, uint32_t io_base1,
                           uint32_t io_base2, uint32_t io_base3,
-                          unused void *OF_private)
+                          void *OF_private0, void *OF_private1)
 {
     if (ide_pci_ops == NULL) {
         ide_pci_ops = malloc(sizeof(ide_ops_t));
@@ -770,19 +785,19 @@
         memcpy(ide_pci_ops, &ide_pci_pc_ops, sizeof(ide_ops_t));
     }
     if ((io_base0 != 0 || io_base1 != 0) &&
-        ide_pci_ops->base[0] == 0 && ide_pci_ops->base[1] == 0) {
+        ide_pci_ops->base[0] == 0 && ide_pci_ops->base[2] == 0) {
         ide_pci_ops->base[0] = io_base0;
-        ide_pci_ops->base[1] = io_base1;
+        ide_pci_ops->base[2] = io_base1;
 #ifdef USE_OPENFIRMWARE
-        ide_pci_ops->OF_private[0] = OF_private;
+        ide_pci_ops->OF_private[0] = OF_private0;
 #endif
     }
     if ((io_base2 != 0 || io_base3 != 0) &&
-        ide_pci_ops->base[2] == 0 && ide_pci_ops->base[3] == 0) {
-        ide_pci_ops->base[2] = io_base2;
+        ide_pci_ops->base[1] == 0 && ide_pci_ops->base[3] == 0) {
+        ide_pci_ops->base[1] = io_base2;
         ide_pci_ops->base[3] = io_base3;
 #ifdef USE_OPENFIRMWARE
-        ide_pci_ops->OF_private[1] = OF_private;
+        ide_pci_ops->OF_private[1] = OF_private1;
 #endif
     }
 }
@@ -935,6 +950,8 @@
 }
 
 static void atapi_pad_req (void *buffer, int len);
+static void atapi_make_req (bloc_device_t *bd, uint32_t *buffer,
+                            int maxlen);
 static int atapi_read_sector (bloc_device_t *bd, void *buffer, int secnum);
 
 static int ide_initialize (bloc_device_t *bd, int device)
@@ -1035,9 +1052,7 @@
         DPRINTF("INQUIRY\n");
         len = spc_inquiry_req(&atapi_buffer, 36);
         atapi_pad_req(&atapi_buffer, len);
-        ide_port_write(bd, 0x07, 0xA0);
-        for (i = 0; i < 3; i++)
-            ide_data_writel(bd, ldswap32(&atapi_buffer[i]));
+        atapi_make_req(bd, atapi_buffer, 36);
         status = ide_port_read(bd, 0x07);
         if (status != 0x48) {
             ERROR("ATAPI INQUIRY : status %0x != 0x48\n", status);
@@ -1053,9 +1068,7 @@
         DPRINTF("READ_CAPACITY\n");
         len = mmc_read_capacity_req(&atapi_buffer);
         atapi_pad_req(&atapi_buffer, len);
-        ide_port_write(bd, 0x07, 0xA0);
-        for (i = 0; i < 3; i++)
-            ide_data_writel(bd, ldswap32(&atapi_buffer[i]));
+        atapi_make_req(bd, atapi_buffer, 8);
         status = ide_port_read(bd, 0x07);
         if (status != 0x48) {
             ERROR("ATAPI READ_CAPACITY : status %0x != 0x48\n", status);
@@ -1105,6 +1118,22 @@
     memset(p + len, 0, 12 - len);
 }
 
+static void atapi_make_req (bloc_device_t *bd, uint32_t *buffer,
+                            int maxlen)
+{
+    int i;
+    /* select drive */
+    if (bd->drv == 0)
+        ide_port_write(bd, 0x06, 0x40);
+    else
+        ide_port_write(bd, 0x06, 0x50);
+    ide_port_write(bd, 0x04, maxlen & 0xff);
+    ide_port_write(bd, 0x05, (maxlen >> 8) & 0xff);
+    ide_port_write(bd, 0x07, 0xA0);
+    for (i = 0; i < 3; i++)
+        ide_data_writel(bd, ldswap32(&buffer[i]));
+}
+
 static int atapi_read_sector (bloc_device_t *bd, void *buffer, int secnum)
 {
     uint32_t atapi_buffer[4];
@@ -1112,16 +1141,9 @@
     uint32_t status, value;
     int i, len;
 
-    /* select drive */
-    if (bd->drv == 0)
-        ide_port_write(bd, 0x06, 0x40);
-    else
-        ide_port_write(bd, 0x06, 0x50);
     len = mmc_read12_req(atapi_buffer, secnum, 1);
     atapi_pad_req(&atapi_buffer, len);
-    ide_port_write(bd, 0x07, 0xA0);
-    for (i = 0; i < 3; i++)
-        ide_data_writel(bd, ldswap32(&atapi_buffer[i]));
+    atapi_make_req(bd, atapi_buffer, bd->seclen);
     status = ide_port_read(bd, 0x07);
     if (status != 0x48) {
         ERROR("ATAPI READ12 : status %0x != 0x48\n", status);
diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/libpart/apple.c OpenHackWare-release-0.4/src/libpart/apple.c
--- OpenHackWare-release-0.4.org/src/libpart/apple.c	2005-03-31 09:23:33.000000000 +0200
+++ OpenHackWare-release-0.4/src/libpart/apple.c	2005-07-03 16:17:41.000000000 +0200
@@ -199,14 +199,18 @@
         if (len == 0) {
             /* Place holder. Skip it */
             DPRINTF("%s placeholder part\t%d\n", __func__, i);
+            part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
+            part_register(bd, part, name, i);
         } else if (strncmp("Apple_Void", type, 32) == 0) {
             /* Void partition. Skip it */
             DPRINTF("%s Void part\t%d [%s]\n", __func__, i, type);
+            part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
+            part_register(bd, part, name, i);
         } else if (strncmp("Apple_Free", type, 32) == 0) {
             /* Free space. Skip it */
             DPRINTF("%s Free part (%d)\n", __func__, i);
             part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
-            part_register(bd, part, name);
+            part_register(bd, part, name, i);
         } else if (strncmp("Apple_partition_map", type, 32) == 0 ||
                    strncmp("Apple_Partition_Map", type, 32) == 0
 #if 0 // Is this really used or is it just a mistake ?
@@ -226,7 +230,7 @@
                  */
             }
             part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
-            part_register(bd, part, name);
+            part_register(bd, part, name, i);
         } else if (strncmp("Apple_Driver", type, 32) == 0 ||
                    strncmp("Apple_Driver43", type, 32) == 0 ||
                    strncmp("Apple_Driver43_CD", type, 32) == 0 ||
@@ -236,8 +240,12 @@
                    strncmp("Apple_Driver_IOKit", type, 32) == 0) {
             /* Drivers. don't care for now */
             DPRINTF("%s Drivers part\t%d [%s]\n", __func__, i, type);
+            part->flags = PART_TYPE_APPLE | PART_FLAG_DRIVER;
+            part_register(bd, part, name, i);
         } else if (strncmp("Apple_Patches", type, 32) == 0) {
             /* Patches: don't care for now */
+            part->flags = PART_TYPE_APPLE | PART_FLAG_PATCH;
+            part_register(bd, part, name, i);
             DPRINTF("%s Patches part\t%d [%s]\n", __func__, i, type);
         } else if (strncmp("Apple_HFS", type, 32) == 0 ||
                    strncmp("Apple_MFS", type, 32) == 0 ||
@@ -256,9 +264,8 @@
             count = partmap->bloc_cnt * HFS_BLOCSIZE;
             if (partmap->boot_size == 0 || partmap->boot_load == 0) {
                 printf("Not a bootable partition %d %d (%p %p)\n",
-                       partmap->boot_size, partmap->boot_load,boot_part, part);
-                if (boot_part == NULL)
-                    boot_part = part;
+                       partmap->boot_size, partmap->boot_load,
+                       boot_part, part);
                 part->flags = PART_TYPE_APPLE | PART_FLAG_FS;
             } else {
                 part->boot_start.bloc = partmap->boot_start;
@@ -278,8 +285,8 @@
                 boot_part = part;
                 part->flags = PART_TYPE_APPLE | PART_FLAG_FS | PART_FLAG_BOOT;
             }
-            printf("Partition: %d %s st %0x size %0x",
-                    i, name, partmap->start_bloc, partmap->bloc_cnt);
+            printf("Partition: %d '%s' '%s' st %0x size %0x",
+                    i, name, type, partmap->start_bloc, partmap->bloc_cnt);
 #ifndef DEBUG
             printf("\n");
 #endif
@@ -290,11 +297,13 @@
                     part->boot_load, part->boot_entry);
             DPRINTF("                           load %0x entry %0x %0x\n",
                     partmap->boot_load2, partmap->boot_entry2, HFS_BLOCSIZE);
-            part_register(bd, part, name);
+            part_register(bd, part, name, i);
         } else {
             memcpy(tmp, type, 32);
             tmp[32] = '\0';
             ERROR("Unknown partition type [%s]\n", tmp);
+            part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
+            part_register(bd, part, name, i);
         }
     }
  error:
diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/libpart/core.c OpenHackWare-release-0.4/src/libpart/core.c
--- OpenHackWare-release-0.4.org/src/libpart/core.c	2005-03-31 09:23:33.000000000 +0200
+++ OpenHackWare-release-0.4/src/libpart/core.c	2005-07-03 16:17:41.000000000 +0200
@@ -126,7 +126,7 @@
 }
 
 int part_register (bloc_device_t *bd, part_t *partition,
-                   const unsigned char *name)
+                   const unsigned char *name, int partnum)
 {
     part_t **cur;
 
@@ -134,6 +134,7 @@
     partition->bd = bd;
     partition->next = NULL;
     partition->name = strdup(name);
+    partition->partnum = partnum;
     for (cur = _bd_parts(bd); *cur != NULL; cur = &(*cur)->next)
         continue;
     *cur = partition;
@@ -141,29 +142,15 @@
     return 0;
 }
 
-static inline int set_boot_part (bloc_device_t *bd, int partnum)
-{
-    part_t *cur;
-
-    cur = part_get(bd, partnum);
-    if (cur == NULL)
-        return -1;
-    bd_set_boot_part(bd, cur);
-
-    return 0;
-}
-
 part_t *part_get (bloc_device_t *bd, int partnum)
 {
     part_t **listp, *cur;
-    int i;
 
     listp = _bd_parts(bd);
-    cur = *listp;
-    for (i = 0; i != partnum; i++) {
-        if (cur == NULL)
+    
+    for (cur = *listp; cur != NULL; cur = cur->next) {
+        if (cur->partnum == partnum)
             break;
-        cur = cur->next;
     }
     
     return cur;
@@ -192,17 +179,20 @@
     part_set_blocsize(bd, part, 512);
     part->bd = bd;
     part->flags = PART_TYPE_RAW | PART_FLAG_BOOT;
-    part_register(bd, part, "Raw");
+    part_register(bd, part, "Raw", 0);
 
     return part;
 }
 
+bloc_device_t *part_get_bd (part_t *part)
+{
+    return part->bd;
+}
+
 part_t *part_probe (bloc_device_t *bd, int set_raw)
 {
-    part_t *part0, *boot_part, **cur;
+    part_t *part0 = NULL, *boot_part, **cur;
 
-    /* Register the 0 partition: raw partition containing the whole disk */
-    part0 = part_get_raw(bd);
     /* Try to find a valid boot partition */
     boot_part = Apple_probe_partitions(bd);
     if (boot_part == NULL) {
@@ -210,10 +200,13 @@
         if (boot_part == NULL && arch == ARCH_PREP)
             boot_part = PREP_find_partition(bd);
         if (boot_part == NULL && set_raw != 0) {
-            boot_part = part0;
-            set_boot_part(bd, 0);
+            dprintf("Use bloc device as raw partition\n");
         }
     }
+    if (_bd_parts(bd) == NULL) {
+        /* Register the 0 partition: raw partition containing the whole disk */
+        part0 = part_get_raw(bd);
+    }
     /* Probe filesystem on each found partition */
     for (cur = _bd_parts(bd); *cur != NULL; cur = &(*cur)->next) {
         const unsigned char *map, *type;
@@ -248,23 +241,28 @@
             type = "unknown";
             break;
         }
-        DPRINTF("Probe filesystem on %s %s partition '%s' %s\n",
+        dprintf("Probe filesystem on %s %s partition '%s' %s %p\n",
                 type, map, (*cur)->name,
-                ((*cur)->flags) & PART_FLAG_BOOT ? "(bootable)" : "");
+                ((*cur)->flags) & PART_FLAG_BOOT ? "(bootable)" : "", *cur);
         if (((*cur)->flags) & PART_FLAG_FS) {
             if (((*cur)->flags) & PART_FLAG_BOOT)
                 (*cur)->fs = fs_probe(*cur, 1);
             else
                 (*cur)->fs = fs_probe(*cur, 0);
+        } else if (((*cur)->flags) & PART_TYPE_RAW) {
+            (*cur)->fs = fs_probe(*cur, 2);
         } else {
             (*cur)->fs = fs_probe(*cur, 2);
         }
-        if (((*cur)->flags) & PART_FLAG_BOOT) {
-            bd_set_boot_part(bd, *cur);
             fs_get_bootfile((*cur)->fs);
+        if (((*cur)->flags) & PART_FLAG_BOOT) {
+            dprintf("Partition is bootable (%d)\n", (*cur)->partnum);
+            bd_set_boot_part(bd, *cur, (*cur)->partnum);
+            if (boot_part == NULL)
+                boot_part = *cur;
         }
     }
-    DPRINTF("Boot partition: %p %p %p %p\n", boot_part, boot_part->fs,
+    dprintf("Boot partition: %p %p %p %p\n", boot_part, boot_part->fs,
             part_fs(boot_part), part0);
 
     return boot_part;
@@ -279,6 +277,7 @@
     part->boot_size.offset = 0;
     part->boot_load = 0;
     part->boot_entry = 0;
+    part->flags |= PART_FLAG_BOOT;
 
     return 0;
 }
diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/libpart/isofs.c OpenHackWare-release-0.4/src/libpart/isofs.c
--- OpenHackWare-release-0.4.org/src/libpart/isofs.c	2005-03-31 09:23:33.000000000 +0200
+++ OpenHackWare-release-0.4/src/libpart/isofs.c	2005-07-03 16:17:41.000000000 +0200
@@ -242,7 +242,7 @@
                    part->boot_start.bloc, part->boot_size.bloc,
                    part->boot_load, part->boot_entry);
             part->flags = PART_TYPE_ISO9660 | PART_FLAG_BOOT;
-            part_register(bd, part, name);
+            part_register(bd, part, name, i + 1);
             fs_raw_set_bootfile(part, part->boot_start.bloc,
                                 part->boot_start.offset,
                                 part->boot_size.bloc,
diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/libpart/libpart.h OpenHackWare-release-0.4/src/libpart/libpart.h
--- OpenHackWare-release-0.4.org/src/libpart/libpart.h	2005-03-31 09:23:33.000000000 +0200
+++ OpenHackWare-release-0.4/src/libpart/libpart.h	2005-07-03 16:17:41.000000000 +0200
@@ -30,6 +30,7 @@
 
 struct part_t {
     bloc_device_t *bd;
+    int partnum;
     uint32_t start;      /* Partition first bloc             */
     uint32_t size;       /* Partition size, in blocs         */
     uint32_t spb;
@@ -54,7 +55,7 @@
 };
 
 int part_register (bloc_device_t *bd, part_t *partition,
-                   const unsigned char *name);
+                   const unsigned char *name, int partnum);
 void part_set_blocsize (bloc_device_t *bd, part_t *part, uint32_t blocsize);
 void part_private_set (part_t *part, void *private);
 void *part_private_get (part_t *part);
diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/libpart/prep.c OpenHackWare-release-0.4/src/libpart/prep.c
--- OpenHackWare-release-0.4.org/src/libpart/prep.c	2005-03-31 09:23:33.000000000 +0200
+++ OpenHackWare-release-0.4/src/libpart/prep.c	2005-07-03 16:17:41.000000000 +0200
@@ -164,7 +164,7 @@
             part->boot_load = 0;
             part->boot_entry = boot_offset - part->bloc_size;
             part->flags = PART_TYPE_PREP | PART_FLAG_BOOT;
-            part_register(bd, part, "PREP boot");
+            part_register(bd, part, "PREP boot", i);
             fs_raw_set_bootfile(part, part->boot_start.bloc,
                                 part->boot_start.offset,
                                 part->boot_size.bloc,
diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/main.c OpenHackWare-release-0.4/src/main.c
--- OpenHackWare-release-0.4.org/src/main.c	2005-03-31 09:23:33.000000000 +0200
+++ OpenHackWare-release-0.4/src/main.c	2005-06-07 23:48:39.000000000 +0200
@@ -364,20 +364,24 @@
     void *load_base, *load_entry, *last_alloc, *load_end;
     uint32_t memsize, boot_image_size, cmdline_size, ramdisk_size;
     uint32_t boot_base, boot_nb;
-    int boot_device;
+    int boot_device, i;
+    static const uint32_t isa_base_tab[3] = {
+        0x80000000, /* PREP */
+        0xFE000000, /* Grackle (Heathrow) */
+        0xF2000000, /* UniNorth (Mac99)  */
+    };
 
     /* Retrieve NVRAM configuration */
- nvram_retry:
+    for(i = 0; i < 3; i++) {
+        isa_io_base = isa_base_tab[i];
     nvram = NVRAM_get_config(&memsize, &boot_device,
                              &boot_image, &boot_image_size,
                              &cmdline, &cmdline_size,
                              &ramdisk, &ramdisk_size);
-    if (nvram == NULL) {
-        /* Retry with another isa_io_base */
-        if (isa_io_base == 0x80000000) {
-            isa_io_base = 0xF2000000;
-            goto nvram_retry;
+        if (nvram)
+            break;
         }
+    if (i == 3) {
         ERROR("Unable to load configuration from NVRAM. Aborting...\n");
         return -1;
     }
@@ -402,7 +406,7 @@
         cpu_name = CPU_get_name(pvr);
         OF_register_cpu(cpu_name, 0, pvr,
                         200 * 1000 * 1000, 200 * 1000 * 1000,
-                        100 * 1000 * 1000, 10 * 1000 * 1000,
+                        100 * 1000 * 1000, 100 * 1000 * 1000,
                         0x0092);
     }
     OF_register_memory(memsize, 512 * 1024 /* TOFIX */);
@@ -433,9 +437,12 @@
     vga_puts(copyright);
     vga_puts("\n");
 
+#if 0
     /* QEMU is quite incoherent: d is cdrom, not second drive */
+    /* XXX: should probe CD-ROM position */
     if (boot_device == 'd')
         boot_device = 'e';
+#endif
     /* Open boot device */
     boot_part = bd_probe(boot_device);
     if (boot_device == 'm') {
diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/nvram.c OpenHackWare-release-0.4/src/nvram.c
--- OpenHackWare-release-0.4.org/src/nvram.c	2005-03-31 09:23:33.000000000 +0200
+++ OpenHackWare-release-0.4/src/nvram.c	2005-06-04 23:44:03.000000000 +0200
@@ -334,6 +334,7 @@
         ret = NVRAM_chrp_format(nvram);
         break;
     case ARCH_MAC99:
+    case ARCH_HEATHROW: /* XXX: may be incorrect */
         ret = NVRAM_mac99_format(nvram);
         break;
     case ARCH_POP:
@@ -409,13 +410,12 @@
         arch = ARCH_MAC99;
     } else if (strcmp(sign, "POP") == 0) {
         arch = ARCH_POP;
+    } else if (strcmp(sign, "HEATHROW") == 0) {
+        arch = ARCH_HEATHROW;
     } else {
         ERROR("Unknown PPC architecture: '%s'\n", sign);
         return NULL;
     }
-    /* HACK */
-    if (arch == ARCH_CHRP)
-        arch = ARCH_MAC99;
     lword = NVRAM_get_lword(nvram, 0x30);
     *RAM_size = lword;
     byte = NVRAM_get_byte(nvram, 0x34);
diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/of.c OpenHackWare-release-0.4/src/of.c
--- OpenHackWare-release-0.4.org/src/of.c	2005-04-06 23:17:26.000000000 +0200
+++ OpenHackWare-release-0.4/src/of.c	2005-07-07 23:30:08.000000000 +0200
@@ -489,7 +489,7 @@
         ERROR("%s can't alloc new node '%s' name\n", __func__, name);
         return NULL;
     }
-    new->prop_address = OF_prop_int_new(env, new, "address", address);
+    new->prop_address = OF_prop_int_new(env, new, "unit-address", address);
     if (new->prop_address == NULL) {
         free(new->prop_name->value);
         free(new->prop_name);
@@ -1017,6 +1017,33 @@
                            string, strlen(string) + 1);
 }
 
+/* convert '\1' char to '\0' */
+static OF_prop_t *OF_prop_string_new1 (OF_env_t *env, OF_node_t *node,
+                                       const unsigned char *name,
+                                       const unsigned char *string)
+{
+    int len, i;
+    OF_prop_t *ret;
+    unsigned char *str;
+
+    if (strchr(string, '\1') == NULL) {
+        return OF_prop_string_new(env, node, name, string);
+    } else {
+        len = strlen(string) + 1;
+        str = malloc(len);
+        if (!str)
+            return NULL;
+        memcpy(str, string, len);
+        for(i = 0; i < len; i++)
+            if (str[i] == '\1')
+                str[i] = '\0';
+        ret = OF_property_new(env, node, name,
+                              str, len);
+        free(str);
+        return ret;
+    }
+}
+
 __attribute__ (( section (".OpenFirmware") ))
 static OF_prop_t *OF_prop_int_new (OF_env_t *env, OF_node_t *node,
                                    const unsigned char *name, uint32_t value)
@@ -1421,15 +1448,12 @@
 __attribute__ (( section (".OpenFirmware") ))
 int OF_init (void)
 {
-    const unsigned char compat_str[] =
 #if 0
         "PowerMac3,1\0MacRISC\0Power Macintosh\0";
         "PowerMac1,2\0MacRISC\0Power Macintosh\0";
         "AAPL,PowerMac G3\0PowerMac G3\0MacRISC\0Power Macintosh\0";
         "AAPL,PowerMac3,0\0MacRISC\0Power Macintosh\0";
         "AAPL,Gossamer\0MacRISC\0Power Macintosh\0";
-#else
-        "AAPL,PowerMac G3\0PowerMac G3\0MacRISC\0Power Macintosh\0";
 #endif
     OF_env_t *OF_env;
     OF_node_t *als, *opt, *chs, *pks;
@@ -1455,15 +1479,21 @@
         return -1;
     }
     OF_prop_string_new(OF_env, OF_node_root, "device_type", "bootrom");
-#if 0
-    OF_prop_string_new(OF_env, OF_node_root,
-                       "model", "PPC Open Hack'Ware " BIOS_VERSION);
-#else
+    if (arch == ARCH_HEATHROW) {
+        const unsigned char compat_str[] =
+            "PowerMac1,1\0MacRISC\0Power Macintosh";
+        OF_property_new(OF_env, OF_node_root, "compatible",
+                        compat_str, sizeof(compat_str));
     OF_prop_string_new(OF_env, OF_node_root,
-                       "model", compat_str);
-#endif
+                           "model", "Power Macintosh");
+    } else {
+        const unsigned char compat_str[] =
+            "PowerMac3,1\0MacRISC\0Power Macintosh";
     OF_property_new(OF_env, OF_node_root, "compatible",
                     compat_str, sizeof(compat_str));
+        OF_prop_string_new(OF_env, OF_node_root,
+                           "model", "PowerMac3,1");
+    }
 #if 0
     OF_prop_string_new(OF_env, OF_node_root, "copyright", copyright);
 #else
@@ -1561,14 +1591,15 @@
         range.size = 0x00800000;
         OF_property_new(OF_env, rom, "ranges", &range, sizeof(OF_range_t));
         OF_prop_int_new(OF_env, rom, "#address-cells", 1);
+
         /* "/rom/boot-rom@fff00000" node */
-        brom = OF_node_new(OF_env, OF_node_root, "boot-rom", 0xfff00000);
+        brom = OF_node_new(OF_env, rom, "boot-rom", 0xfff00000);
         if (brom == NULL) {
             ERROR("Cannot create 'boot-rom'\n");
             return -1;
         }
         regs.address = 0xFFF00000;
-        regs.size = 0x00010000;
+        regs.size = 0x00100000;
         OF_property_new(OF_env, brom, "reg", &regs, sizeof(OF_regprop_t));
         OF_prop_string_new(OF_env, brom, "write-characteristic", "flash");
         OF_prop_string_new(OF_env, brom, "BootROM-build-date",
@@ -1577,7 +1608,7 @@
         OF_prop_string_new(OF_env, brom, "copyright", copyright);
         OF_prop_string_new(OF_env, brom, "model", BIOS_str);
         OF_prop_int_new(OF_env, brom, "result", 0);
-#if 0
+#if 1
         {
             /* Hack taken 'as-is' from PearPC */
             unsigned char info[] = {
@@ -1596,7 +1627,9 @@
         OF_node_put(OF_env, brom);
         OF_node_put(OF_env, rom);
     }
+#if 0
     /* From here, hardcoded hacks to get a Mac-like machine */
+    /* XXX: Core99 does not seem to like this NVRAM tree */
     /* "/nvram@fff04000" node */
     {
         OF_regprop_t regs;
@@ -1617,6 +1650,7 @@
         OF_prop_int_new(OF_env, chs, "nvram", OF_pack_handle(OF_env, nvr));
         OF_node_put(OF_env, nvr);
     }
+#endif
     /* "/pseudo-hid" : hid emulation as Apple does */
     {
         OF_node_t *hid;
@@ -1663,7 +1697,27 @@
         }
         OF_node_put(OF_env, hid);
     }
+    if (arch == ARCH_MAC99) {
+        OF_node_t *unin;
+        OF_regprop_t regs;
 
+        unin = OF_node_new(OF_env, OF_node_root,
+                           "uni-n", 0xf8000000);
+        if (unin == NULL) {
+            ERROR("Cannot create 'uni-n'\n");
+            return -1;
+        }
+        OF_prop_string_new(OF_env, unin, "device-type", "memory-controller");
+        OF_prop_string_new(OF_env, unin, "model", "AAPL,UniNorth");
+        OF_prop_string_new(OF_env, unin, "compatible", "uni-north");
+        regs.address = 0xf8000000;
+        regs.size = 0x01000000;
+        OF_property_new(OF_env, unin, "reg", &regs, sizeof(regs));
+        OF_prop_int_new(OF_env, unin, "#address-cells", 1);
+        OF_prop_int_new(OF_env, unin, "#size-cells", 1);
+        OF_prop_int_new(OF_env, unin, "device-rev", 3);
+        OF_node_put(OF_env, unin);
+    }
     
 #if 1 /* This is mandatory for claim to work
        * but I don't know where it should really be (in cpu ?)
@@ -1693,7 +1747,9 @@
 
     /* "/options/boot-args" node */
     {
-        const unsigned char *args = "-v rootdev cdrom";
+        //        const unsigned char *args = "-v rootdev cdrom";
+        //const unsigned char *args = "-v io=0xffffffff";
+        const unsigned char *args = "-v";
         /* Ask MacOS X to print debug messages */
         //        OF_prop_string_new(OF_env, chs, "machargs", args);
         //        OF_prop_string_new(OF_env, opt, "boot-command", args);
@@ -2013,17 +2069,17 @@
     OF_prop_int_new(OF_env, node, "min-grant", min_grant);
     OF_prop_int_new(OF_env, node, "max-latency", max_latency);
     if (dev->type != NULL)
-        OF_prop_string_new(OF_env, node, "device_type", dev->type);
+        OF_prop_string_new1(OF_env, node, "device_type", dev->type);
     if (dev->compat != NULL)
-        OF_prop_string_new(OF_env, node, "compatible", dev->compat);
+        OF_prop_string_new1(OF_env, node, "compatible", dev->compat);
     if (dev->model != NULL)
-        OF_prop_string_new(OF_env, node, "model", dev->model);
+        OF_prop_string_new1(OF_env, node, "model", dev->model);
     if (dev->acells != 0)
         OF_prop_int_new(OF_env, node, "#address-cells", dev->acells);
     if (dev->scells != 0)
-        OF_prop_int_new(OF_env, node, "#interrupt-cells", dev->acells);
+        OF_prop_int_new(OF_env, node, "#size-cells", dev->scells);
     if (dev->icells != 0)
-        OF_prop_int_new(OF_env, node, "#size-cells", dev->acells);
+        OF_prop_int_new(OF_env, node, "#interrupt-cells", dev->icells);
     dprintf("Done %p %p\n", parent, node);
     
     return node;
@@ -2040,8 +2096,9 @@
     OF_env_t *OF_env;
     pci_range_t ranges[3];
     OF_regprop_t regs[1];
-    OF_node_t *pci_host;
+    OF_node_t *pci_host, *als;
     int nranges;
+    unsigned char buffer[OF_NAMELEN_MAX];
 
     OF_env = OF_env_main;
     dprintf("register PCI host '%s' '%s' '%s' '%s'\n",
@@ -2052,6 +2109,17 @@
         ERROR("Cannot create pci host\n");
         return NULL;
     }
+    
+    als = OF_node_get(OF_env, "aliases");
+    if (als == NULL) {
+        ERROR("Cannot get 'aliases'\n");
+        return NULL;
+    }
+    sprintf(buffer, "/%s", dev->name);
+    OF_prop_string_set(OF_env, als, "pci", buffer);
+    OF_node_put(OF_env, als);
+    
+
     regs[0].address = cfg_base;
     regs[0].size = cfg_len;
     OF_property_new(OF_env, pci_host, "reg", regs, sizeof(OF_regprop_t));
@@ -2136,6 +2204,11 @@
     return pci_dev;
 }
 
+/* XXX: suppress that, used for interrupt map init */
+OF_node_t *pci_host_node;
+uint32_t pci_host_interrupt_map[7 * 32];
+int pci_host_interrupt_map_len = 0;
+
 void OF_finalize_pci_host (void *dev, int first_bus, int nb_busses)
 {
     OF_env_t *OF_env;
@@ -2145,10 +2218,12 @@
     regs[0].address = first_bus;
     regs[0].size = nb_busses;
     OF_property_new(OF_env, dev, "bus-range", regs, sizeof(OF_regprop_t));
+    pci_host_node = dev;
 }
 
 void OF_finalize_pci_device (void *dev, uint8_t bus, uint8_t devfn,
-                             uint32_t *regions, uint32_t *sizes)
+                             uint32_t *regions, uint32_t *sizes,
+                             int irq_line)
 {
     OF_env_t *OF_env;
     pci_reg_prop_t pregs[6], rregs[6];
@@ -2156,6 +2231,7 @@
     int i, j, k;
 
     OF_env = OF_env_main;
+    /* XXX: only useful for VGA card in fact */
     if (regions[0] != 0x00000000)
         OF_prop_int_set(OF_env, dev, "address", regions[0] & ~0x0000000F);
     for (i = 0, j = 0, k = 0; i < 6; i++) {
@@ -2222,7 +2298,22 @@
     } else {
         OF_property_new(OF_env, dev, "assigned-addresses", NULL, 0);
     }
-#if 0
+    if (irq_line >= 0) {
+        int i;
+        OF_prop_int_new(OF_env, dev, "interrupts", 1);
+        i = pci_host_interrupt_map_len;
+        pci_host_interrupt_map[i++] = (devfn << 8) & 0xf800;
+        pci_host_interrupt_map[i++] = 0;
+        pci_host_interrupt_map[i++] = 0;
+        pci_host_interrupt_map[i++] = 0;
+        pci_host_interrupt_map[i++] = 0; /* pic handle will be patched later */
+        pci_host_interrupt_map[i++] = irq_line;
+        if (arch != ARCH_HEATHROW) {
+            pci_host_interrupt_map[i++] = 1;
+        }
+        pci_host_interrupt_map_len = i;
+    }
+#if 1
     {
         OF_prop_t *prop_name = ((OF_node_t *)dev)->prop_name;
 
@@ -2390,6 +2481,54 @@
     return 0;
 }
 
+static void keylargo_ata(OF_node_t *mio, uint32_t base_address,
+                         uint32_t base, int irq1, int irq2, 
+                         uint16_t pic_phandle)
+{
+    OF_env_t *OF_env = OF_env_main;
+    OF_node_t *ata;
+    OF_regprop_t regs[2];
+
+    ata = OF_node_new(OF_env, mio, "ata-4", base);
+    if (ata == NULL) {
+        ERROR("Cannot create 'ata-4'\n");
+        return;
+    }
+    OF_prop_string_new(OF_env, ata, "device_type", "ata");
+#if 1
+    OF_prop_string_new(OF_env, ata, "compatible", "key2largo-ata");
+    OF_prop_string_new(OF_env, ata, "model", "ata-4");
+    OF_prop_string_new(OF_env, ata, "cable-type", "80-conductor");
+#else
+    OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
+    OF_prop_string_new(OF_env, ata, "model", "ata-4");
+#endif
+    OF_prop_int_new(OF_env, ata, "#address-cells", 1);
+    OF_prop_int_new(OF_env, ata, "#size-cells", 0);
+    regs[0].address = base;
+    regs[0].size = 0x00001000;
+#if 0 // HACK: Don't set up DMA registers
+    regs[1].address = 0x00008A00;
+    regs[1].size = 0x00001000;
+    OF_property_new(OF_env, ata, "reg",
+                    regs, 2 * sizeof(OF_regprop_t));
+#else
+    OF_property_new(OF_env, ata, "reg",
+                    regs, sizeof(OF_regprop_t));
+#endif
+    OF_prop_int_new(OF_env, ata, "interrupt-parent", pic_phandle);
+    regs[0].address = irq1;
+    regs[0].size = 0x00000001;
+    regs[1].address = irq2;
+    regs[1].size = 0x00000000;
+    OF_property_new(OF_env, ata, "interrupts",
+                    regs, 2 * sizeof(OF_regprop_t));
+    if (base == 0x1f000)
+        ide_pci_pmac_register(base_address + base, 0x00000000, ata);
+    else
+        ide_pci_pmac_register(0x00000000, base_address + base, ata);
+}
+
 void OF_finalize_pci_macio (void *dev, uint32_t base_address, uint32_t size,
                             void *private_data)
 {
@@ -2398,6 +2537,8 @@
     pci_reg_prop_t pregs[2];
     OF_node_t *mio, *chs, *als;
     uint16_t pic_phandle;
+    int rec_len;
+    OF_prop_t *mio_reg;
 
     OF_DPRINTF("mac-io: %p\n", dev);
     OF_env = OF_env_main;
@@ -2416,10 +2557,14 @@
     mio = dev;
     mio->private_data = private_data;
     pregs[0].addr.hi = 0x00000000;
-    pregs[0].addr.mid = 0x82013810;
+    pregs[0].addr.mid = 0x00000000;
     pregs[0].addr.lo = 0x00000000;
     pregs[0].size_hi = base_address;
     pregs[0].size_lo = size;
+    mio_reg = OF_property_get(OF_env, mio, "reg");
+    if (mio_reg && mio_reg->vlen >= 5 * 4) {
+        pregs[0].addr.mid = ((pci_reg_prop_t *)mio_reg->value)->addr.hi;
+    }
     OF_property_new(OF_env, mio, "ranges",
                     &pregs, sizeof(pci_reg_prop_t));
 #if 0
@@ -2431,8 +2576,32 @@
     OF_property_new(OF_env, mio, "assigned-addresses",
                     &pregs, sizeof(pci_reg_prop_t));
 #endif
+
+    if (arch == ARCH_HEATHROW) {
+        /* Heathrow PIC */
+        OF_regprop_t regs;
+        OF_node_t *mpic;
+        const char compat_str[] = "heathrow\0mac-risc";
+
+        mpic = OF_node_new(OF_env, mio, "interrupt-controller", 0x10);
+        if (mpic == NULL) {
+            ERROR("Cannot create 'mpic'\n");
+            goto out;
+        }
+        OF_prop_string_new(OF_env, mpic, "device_type", "interrupt-controller");
+        OF_property_new(OF_env, mpic, "compatible", compat_str, sizeof(compat_str));
+        OF_prop_int_new(OF_env, mpic, "#interrupt-cells", 1);
+        regs.address = 0x10;
+        regs.size = 0x20;
+        OF_property_new(OF_env, mpic, "reg",
+                        &regs, sizeof(regs));
+        OF_property_new(OF_env, mpic, "interrupt-controller", NULL, 0);
+        pic_phandle = OF_pack_handle(OF_env, mpic);
+        OF_prop_int_new(OF_env, chs, "interrupt-controller", pic_phandle);
+        OF_node_put(OF_env, mpic);
+        rec_len = 6;
+    } else {
     /* OpenPIC */
-    {
         OF_regprop_t regs[4];
         OF_node_t *mpic;
         mpic = OF_node_new(OF_env, mio, "interrupt-controller", 0x40000);
@@ -2455,8 +2624,37 @@
         pic_phandle = OF_pack_handle(OF_env, mpic);
         OF_prop_int_new(OF_env, chs, "interrupt-controller", pic_phandle);
         OF_node_put(OF_env, mpic);
+        rec_len = 7;
     }
-#if 1
+
+    /* patch pci host table */
+    /* XXX: do it after the PCI init */
+    {
+        int i;
+        uint32_t tab[4];
+
+        for(i = 0; i < pci_host_interrupt_map_len; i += rec_len)
+            pci_host_interrupt_map[i + 4] = pic_phandle;
+#if 0
+        dprintf("interrupt-map:\n");
+        for(i = 0; i < pci_host_interrupt_map_len; i++) {
+            dprintf(" %08x", pci_host_interrupt_map[i]);
+            if ((i % rec_len) == (rec_len - 1))
+                dprintf("\n");
+        }
+        dprintf("\n");
+#endif
+        OF_property_new(OF_env, pci_host_node, "interrupt-map", 
+                        pci_host_interrupt_map, 
+                        pci_host_interrupt_map_len * sizeof(uint32_t));
+        tab[0] = 0xf800;
+        tab[1] = 0;
+        tab[2] = 0;
+        tab[3] = 0;
+        OF_property_new(OF_env, pci_host_node, "interrupt-map-mask", 
+                        tab, 4 * sizeof(uint32_t));
+    }
+#if 0
     /* escc is usefull to get MacOS X debug messages */
     {
         OF_regprop_t regs[8];
@@ -2645,85 +2843,12 @@
         OF_node_put(OF_env, scc);
     }
 #endif
-    /* IDE controller */
-    {
-        OF_node_t *ata;
-        OF_regprop_t regs[2];
-        ata = OF_node_new(OF_env, mio, "ata-4", 0x1f000);
-        if (ata == NULL) {
-            ERROR("Cannot create 'ata-4'\n");
-            goto out;
-        }
-        OF_prop_string_new(OF_env, ata, "device_type", "ata");
-#if 1
-        OF_prop_string_new(OF_env, ata, "compatible", "keylargo-ata");
-        OF_prop_string_new(OF_env, ata, "model", "ata-4");
-#else
-        OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
-        OF_prop_string_new(OF_env, ata, "model", "ata-4");
-#endif
-        OF_prop_int_new(OF_env, ata, "#address-cells", 1);
-        OF_prop_int_new(OF_env, ata, "#size-cells", 0);
-        regs[0].address = 0x0001F000;
-        regs[0].size = 0x00001000;
-#if 0 // HACK: Don't set up DMA registers
-        regs[1].address = 0x00008A00;
-        regs[1].size = 0x00001000;
-        OF_property_new(OF_env, ata, "reg",
-                        regs, 2 * sizeof(OF_regprop_t));
-#else
-        OF_property_new(OF_env, ata, "reg",
-                        regs, sizeof(OF_regprop_t));
-#endif
-        OF_prop_int_new(OF_env, ata, "interrupt-parent", pic_phandle);
-        regs[0].address = 0x00000013;
-        regs[0].size = 0x00000001;
-        regs[1].address = 0x0000000B;
-        regs[1].size = 0x00000000;
-        OF_property_new(OF_env, ata, "interrupts",
-                        regs, 2 * sizeof(OF_regprop_t));
-        ide_pci_pmac_register(base_address + 0x1f000, 0x00000000, ata);
-
-    }
-    {
-        OF_node_t *ata;
-        OF_regprop_t regs[2];
-        ata = OF_node_new(OF_env, mio, "ata-4", 0x20000);
-        if (ata == NULL) {
-            ERROR("Cannot create 'ata-4'\n");
-            goto out;
-        }
-        OF_prop_string_new(OF_env, ata, "device_type", "ata");
-#if 1
-        OF_prop_string_new(OF_env, ata, "compatible", "keylargo-ata");
-        OF_prop_string_new(OF_env, ata, "model", "ata-4");
-#else
-        OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
-        OF_prop_string_new(OF_env, ata, "model", "ata-4");
-#endif
-        OF_prop_int_new(OF_env, ata, "#address-cells", 1);
-        OF_prop_int_new(OF_env, ata, "#size-cells", 0);
-        regs[0].address = 0x00020000;
-        regs[0].size = 0x00001000;
-#if 0 // HACK: Don't set up DMA registers
-        regs[1].address = 0x00008A00;
-        regs[1].size = 0x00001000;
-        OF_property_new(OF_env, ata, "reg",
-                        regs, 2 * sizeof(OF_regprop_t));
-#else
-        OF_property_new(OF_env, ata, "reg",
-                        regs, sizeof(OF_regprop_t));
-#endif
-        OF_prop_int_new(OF_env, ata, "interrupt-parent", pic_phandle);
-        regs[0].address = 0x00000014;
-        regs[0].size = 0x00000001;
-        regs[1].address = 0x0000000B;
-        regs[1].size = 0x00000000;
-        OF_property_new(OF_env, ata, "interrupts",
-                        regs, 2 * sizeof(OF_regprop_t));
-        ide_pci_pmac_register(0x00000000, base_address + 0x20000, ata);
-
+    /* Keylargo IDE controller: need some work (DMA problem ?) */
+    if (arch == ARCH_MAC99) {
+        keylargo_ata(mio, base_address, 0x1f000, 0x13, 0xb, pic_phandle);
+        keylargo_ata(mio, base_address, 0x20000, 0x14, 0xb, pic_phandle);
     }
+#if 0
     /* Timer */
     {
         OF_node_t *tmr;
@@ -2746,10 +2871,11 @@
                         regs, sizeof(OF_regprop_t));
         OF_node_put(OF_env, tmr);
     }
+#endif
     /* VIA-PMU */
     {
         /* Controls adb, RTC and power-mgt (forget it !) */
-        OF_node_t *via, *adb, *rtc;
+        OF_node_t *via, *adb;
         OF_regprop_t regs[1];
 #if 0 // THIS IS A HACK AND IS COMPLETELY ABSURD !
       // (but needed has Qemu doesn't emulate via-pmu).
@@ -2773,14 +2899,21 @@
         regs[0].size = 0x00002000;
         OF_property_new(OF_env, via, "reg", regs, sizeof(OF_regprop_t));
         OF_prop_int_new(OF_env, via, "interrupt-parent", pic_phandle);
+        if (arch == ARCH_HEATHROW) {
+            OF_prop_int_new(OF_env, via, "interrupts", 0x12);
+        } else {
         regs[0].address = 0x00000019;
         regs[0].size = 0x00000001;
         OF_property_new(OF_env, via, "interrupts",
                         regs, sizeof(OF_regprop_t));
+        }
+        /* force usage of OF bus speeds */
+        OF_prop_int_new(OF_env, via, "BusSpeedCorrect", 1);
 #if 0
         OF_prop_int_new(OF_env, via, "pmu-version", 0x00D0740C);
 #endif
-#if 1
+        {
+            OF_node_t *kbd, *mouse;
         /* ADB pseudo-device */
         adb = OF_node_new(OF_env, via, "adb", OF_ADDRESS_NONE);
         if (adb == NULL) {
@@ -2797,9 +2930,26 @@
         OF_prop_int_new(OF_env, adb, "#size-cells", 0);
         OF_pack_get_path(OF_env, tmp, 512, adb);
         OF_prop_string_new(OF_env, als, "adb", tmp);
-        /* XXX: add "keyboard@2" and "mouse@3" */
-        OF_node_put(OF_env, adb);
-#endif
+
+            kbd = OF_node_new(OF_env, adb, "keyboard", 2);
+            if (kbd == NULL) {
+                ERROR("Cannot create 'kbd'\n");
+                goto out;
+            }
+            OF_prop_string_new(OF_env, kbd, "device_type", "keyboard");
+            OF_prop_int_new(OF_env, kbd, "reg", 2);
+
+            mouse = OF_node_new(OF_env, adb, "mouse", 3);
+            if (mouse == NULL) {
+                ERROR("Cannot create 'mouse'\n");
+                goto out;
+            }
+            OF_prop_string_new(OF_env, mouse, "device_type", "mouse");
+            OF_prop_int_new(OF_env, mouse, "reg", 3);
+            OF_prop_int_new(OF_env, mouse, "#buttons", 3);
+        }
+        {
+            OF_node_t *rtc;
         
         rtc = OF_node_new(OF_env, via, "rtc", OF_ADDRESS_NONE);
         if (rtc == NULL) {
@@ -2813,14 +2963,68 @@
         OF_prop_string_new(OF_env, rtc, "compatible", "rtc");
 #endif
         OF_node_put(OF_env, rtc);
-        OF_node_put(OF_env, via);
     }
+        //        OF_node_put(OF_env, via);
+    }
+    {
+        OF_node_t *pmgt;
+        pmgt = OF_node_new(OF_env, mio, "power-mgt", OF_ADDRESS_NONE);
+        OF_prop_string_new(OF_env, pmgt, "device_type", "power-mgt");
+        OF_prop_string_new(OF_env, pmgt, "compatible", "cuda");
+        OF_prop_string_new(OF_env, pmgt, "mgt-kind", "min-consumption-pwm-led");
+        OF_node_put(OF_env, pmgt);
+    }
+
+    if (arch == ARCH_HEATHROW) {
+        /* NVRAM */
+        OF_node_t *nvr;
+        OF_regprop_t regs;
+        nvr = OF_node_new(OF_env, mio, "nvram", 0x60000);
+        OF_prop_string_new(OF_env, nvr, "device_type", "nvram");
+        regs.address = 0x60000;
+        regs.size = 0x00020000;
+        OF_property_new(OF_env, nvr, "reg", &regs, sizeof(regs));
+        OF_prop_int_new(OF_env, nvr, "#bytes", 0x2000);
+        OF_node_put(OF_env, nvr);
+    }
+
  out:
     //    OF_node_put(OF_env, mio);
     OF_node_put(OF_env, chs);
     OF_node_put(OF_env, als);
 }
 
+void OF_finalize_pci_ide (void *dev, 
+                          uint32_t io_base0, uint32_t io_base1,
+                          uint32_t io_base2, uint32_t io_base3)
+{
+    OF_env_t *OF_env = OF_env_main;
+    OF_node_t *pci_ata = dev;
+    OF_node_t *ata, *atas[2];
+    int i;
+
+    OF_prop_int_new(OF_env, pci_ata, "#address-cells", 1);
+    OF_prop_int_new(OF_env, pci_ata, "#size-cells", 0);
+
+    /* XXX: Darwin handles only one device */
+    for(i = 0; i < 1; i++) {
+        ata = OF_node_new(OF_env, pci_ata, "ata-4", i);
+        if (ata == NULL) {
+            ERROR("Cannot create 'ata-4'\n");
+            return;
+        }
+        OF_prop_string_new(OF_env, ata, "device_type", "ata");
+        OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
+        OF_prop_string_new(OF_env, ata, "model", "ata-4");
+        OF_prop_int_new(OF_env, ata, "#address-cells", 1);
+        OF_prop_int_new(OF_env, ata, "#size-cells", 0);
+        OF_prop_int_new(OF_env, ata, "reg", i);
+        atas[i] = ata;
+    }
+    ide_pci_pc_register(io_base0, io_base1, io_base2, io_base3,
+                        atas[0], atas[1]);
+}
+
 /*****************************************************************************/
 /* Fake package */
 static void OF_method_fake (OF_env_t *OF_env)
@@ -2862,11 +3066,11 @@
     /* As we get a 1:1 mapping, do nothing */
     ihandle = popd(OF_env);
     args = (void *)popd(OF_env);
-    address = popd(OF_env);
-    virt = popd(OF_env);
-    size = popd(OF_env);
     popd(OF_env);
-    OF_DPRINTF("Translate address %0x %0x %0x %0x\n", ihandle, address,
+    size = popd(OF_env);
+    virt = popd(OF_env);
+    address = popd(OF_env);
+    OF_DPRINTF("Map %0x %0x %0x %0x\n", ihandle, address,
                virt, size);
     pushd(OF_env, 0);
 }
@@ -3270,7 +3474,7 @@
     OF_prop_string_new(OF_env, dsk, "device_type", "block");
     OF_prop_string_new(OF_env, dsk, "category", type);
     OF_prop_int_new(OF_env, dsk, "device_id", devnum);
-    OF_prop_int_new(OF_env, dsk, "reg", 0);
+    OF_prop_int_new(OF_env, dsk, "reg", devnum);
     OF_method_new(OF_env, dsk, "open", &OF_blockdev_open);
     OF_method_new(OF_env, dsk, "seek", &OF_blockdev_seek);
     OF_method_new(OF_env, dsk, "read", &OF_blockdev_read);
@@ -3432,7 +3636,8 @@
 }
 
 void OF_vga_register (const unsigned char *name, unused uint32_t address,
-                      int width, int height, int depth)
+                      int width, int height, int depth,
+                      unsigned long vga_bios_addr, unsigned long vga_bios_size)
 {
     OF_env_t *OF_env;
     unsigned char tmp[OF_NAMELEN_MAX];
@@ -3504,6 +3709,18 @@
     OF_prop_string_new(OF_env, als, "display", tmp);
     OF_node_put(OF_env, als);
     /* XXX: may also need read-rectangle */
+
+    if (vga_bios_size >= 8) {
+        const uint8_t *p;
+        int size;
+        /* check the QEMU VGA BIOS header */
+        p = (const uint8_t *)vga_bios_addr;
+        if (p[0] == 'N' && p[1] == 'D' && p[2] == 'R' && p[3] == 'V') {
+            size = *(uint32_t *)(p + 4);
+            OF_property_new(OF_env, disp, "driver,AAPL,MacOS,PowerPC", 
+                            p + 8, size);
+        }
+    }
  out:
     OF_node_put(OF_env, disp);
 }
@@ -4451,7 +4668,10 @@
         break;
     case 0x233441d3: /* MacOS X 10.2 and OpenDarwin 1.41 */
         /* Create "memory-map" pseudo device */
-        popd(OF_env);
+        {
+            OF_node_t *map;
+            uint32_t phandle;
+
         /* Find "/packages" */
         chs = OF_pack_find_by_name(OF_env, OF_node_root, "/chosen");
         if (chs == NULL) {
@@ -4459,10 +4679,6 @@
             ERROR("Cannot get '/chosen'\n");
             break;
         }
-        {
-#if 1
-            OF_node_t *map;
-            uint32_t phandle;
             map = OF_node_new(OF_env, chs, "memory-map", OF_ADDRESS_NONE);
             if (map == NULL) {
                 pushd(OF_env, -1);
@@ -4473,11 +4689,8 @@
             OF_node_put(OF_env, map);
             OF_node_put(OF_env, chs);
             pushd(OF_env, phandle);
-        }
-#else
-        pushd(OF_env, 0);
-#endif
         pushd(OF_env, 0);
+        }
         break;
     case 0x32a2d18e: /* MacOS X 10.2 and OpenDarwin 6.02 */
         /* Return screen ihandle */
@@ -4540,9 +4753,10 @@
     case 0x4ad41f2d:
         /* Yaboot: wait 10 ms: sure ! */
         break;
+
     default:
         /* ERROR */
-        printf("Script:\n%s\n", FString);
+        printf("Script: len=%d\n%s\n", (int)strlen(FString), FString);
         printf("Call %0x NOT IMPLEMENTED !\n", crc);
         bug();
         break;
@@ -4581,6 +4795,7 @@
 {
     OF_CHECK_NBARGS(OF_env, 0);
     /* Should free all OF resources */
+    bd_reset_all();
 #if defined (DEBUG_BIOS)
     {
         uint16_t loglevel = 0x02 | 0x10 | 0x80;
diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/pci.c OpenHackWare-release-0.4/src/pci.c
--- OpenHackWare-release-0.4.org/src/pci.c	2005-03-31 09:23:33.000000000 +0200
+++ OpenHackWare-release-0.4/src/pci.c	2005-07-07 23:27:37.000000000 +0200
@@ -99,8 +99,8 @@
     uint16_t min_grant;
     uint16_t max_latency;
     uint8_t  irq_line;
-    uint32_t regions[6];
-    uint32_t sizes[6];
+    uint32_t regions[7]; /* the region 6 is the PCI ROM */
+    uint32_t sizes[7];
     pci_device_t *next;
 };
 
@@ -158,6 +158,7 @@
 
 /* IRQ numbers assigned to PCI IRQs */
 static uint8_t prep_pci_irqs[4] = { 9, 11, 9, 11 };
+static uint8_t heathrow_pci_irqs[4] = { 0x15, 0x16, 0x17, 0x18 };
 static uint8_t pmac_pci_irqs[4] = { 8, 9, 10, 11 };
 
 /* PREP PCI host */
@@ -399,6 +400,79 @@
     &uninorth_config_readl, &uninorth_config_writel,
 };
 
+/* Grackle PCI host */
+
+static uint32_t grackle_cfg_address (pci_bridge_t *bridge,
+                                     uint8_t bus, uint8_t devfn,
+                                     uint8_t offset)
+{
+    uint32_t addr;
+    addr = 0x80000000 | (bus << 16) | (devfn << 8) | (offset & 0xfc);
+    stswap32((uint32_t *)bridge->cfg_addr, addr);
+    return bridge->cfg_data + (offset & 3);
+}
+
+static uint8_t grackle_config_readb (pci_bridge_t *bridge,
+                                      uint8_t bus, uint8_t devfn,
+                                      uint8_t offset)
+{
+    uint32_t addr;
+    addr = grackle_cfg_address(bridge, bus, devfn, offset);
+    return *((uint8_t *)addr);
+}
+
+static void grackle_config_writeb (pci_bridge_t *bridge,
+                                    uint8_t bus, uint8_t devfn,
+                                    uint8_t offset, uint8_t val)
+{
+    uint32_t addr;
+    addr = grackle_cfg_address(bridge, bus, devfn, offset);
+    *((uint8_t *)addr) = val;
+}
+
+static uint16_t grackle_config_readw (pci_bridge_t *bridge,
+                                       uint8_t bus, uint8_t devfn,
+                                       uint8_t offset)
+{
+    uint32_t addr;
+    addr = grackle_cfg_address(bridge, bus, devfn, offset);
+    return ldswap16((uint16_t *)addr);
+}
+
+static void grackle_config_writew (pci_bridge_t *bridge,
+                                    uint8_t bus, uint8_t devfn,
+                                    uint8_t offset, uint16_t val)
+{
+    uint32_t addr;
+    addr = grackle_cfg_address(bridge, bus, devfn, offset);
+    stswap16((uint16_t *)addr, val);
+}
+
+static uint32_t grackle_config_readl (pci_bridge_t *bridge,
+                                       uint8_t bus, uint8_t devfn,
+                                       uint8_t offset)
+{
+    uint32_t addr;
+    addr = grackle_cfg_address(bridge, bus, devfn, offset);
+    return ldswap32((uint32_t *)addr);
+}
+
+static void grackle_config_writel (pci_bridge_t *bridge,
+                                    uint8_t bus, uint8_t devfn,
+                                    uint8_t offset, uint32_t val)
+{
+    uint32_t addr;
+
+    addr = grackle_cfg_address(bridge, bus, devfn, offset);
+    stswap32((uint32_t *)addr, val);
+}
+
+static pci_ops_t grackle_pci_ops = {
+    &grackle_config_readb, &grackle_config_writeb,
+    &grackle_config_readw, &grackle_config_writew,
+    &grackle_config_readl, &grackle_config_writel,
+};
+
 static inline uint8_t pci_config_readb (pci_bridge_t *bridge,
                                         uint8_t bus, uint8_t devfn,
                                         uint8_t offset)
@@ -466,12 +540,22 @@
     },
 };
 
+static int ide_config_cb2 (pci_device_t *device)
+{
+    OF_finalize_pci_ide(device->common.OF_private,
+                        device->regions[0] & ~0x0000000F,
+                        device->regions[1] & ~0x0000000F,
+                        device->regions[2] & ~0x0000000F,
+                        device->regions[3] & ~0x0000000F);
+    return 0;
+}
+
 static pci_dev_t ide_devices[] = {
     {
-        0x8086, 0x0100,
-        NULL, "Qemu IDE", "Qemu IDE",    "ide",
+        0x1095, 0x0646, /* CMD646 IDE controller */
+        "pci-ide", "pci-ata", NULL, NULL,
         0, 0, 0,
-        NULL, NULL,
+        ide_config_cb2, NULL,
     },
     {
         0xFFFF, 0xFFFF,
@@ -481,7 +565,9 @@
     },
 };
 
-static int ide_config_cb (pci_device_t *device)
+#if 0
+/* should base it on PCI ID, not on arch */
+static int ide_config_cb (unused pci_device_t *device)
 {
     printf("Register IDE controller\n");
     switch (arch) {
@@ -491,14 +577,8 @@
                               device->common.OF_private);
         break;
     default:
-        ide_pci_pc_register(device->regions[0] & ~0x0000000F,
-                            device->regions[1] & ~0x0000000F,
-                            device->regions[2] & ~0x0000000F,
-                            device->regions[3] & ~0x0000000F,
-                            device->common.OF_private);
         break;
     }
-
     return 0;
 }
 
@@ -512,16 +592,12 @@
                               device->common.OF_private);
         break;
     default:
-        ide_pci_pc_register(device->regions[0] & ~0x0000000F,
-                            device->regions[1] & ~0x0000000F,
-                            device->regions[2] & ~0x0000000F,
-                            device->regions[3] & ~0x0000000F,
-                            device->common.OF_private);
         break;
     }
 
     return 0;
 }
+#endif
 
 static pci_subclass_t mass_subclass[] = {
     {
@@ -530,7 +606,7 @@
     },
     {
         0x01, "IDE controller",             "ide", ide_devices, NULL,
-        &ide_config_cb, NULL,
+        NULL, NULL,
     },
     {
         0x02, "Floppy disk controller",     NULL,  NULL, NULL,
@@ -546,7 +622,7 @@
     },
     {
         0x05, "ATA controller",             "ata", NULL, NULL,
-        &ata_config_cb, NULL,
+        NULL, NULL,
     },
     {
         0x80, "misc mass-storage controller", NULL, NULL, NULL,
@@ -646,7 +722,9 @@
         /* VGA 640x480x16 */
         OF_vga_register(device->common.device->name,
                         device->regions[0] & ~0x0000000F,
-                        vga_width, vga_height, vga_depth);
+                        vga_width, vga_height, vga_depth,
+                        device->regions[6] & ~0x0000000F,
+                        device->sizes[6]);
     }
     vga_console_register();
 
@@ -750,6 +828,13 @@
     NULL, &PREP_pci_ops,
 };
 
+pci_dev_t grackle_fake_bridge = {
+    0xFFFF, 0xFFFF,
+    "pci", "pci-bridge", "DEC,21154", "DEC,21154.pci-bridge",
+    -1, -1, -1,
+    NULL, &grackle_pci_ops,
+};
+
 static pci_dev_t hbrg_devices[] = {
     {
         0x106B, 0x0020, NULL,
@@ -758,8 +843,8 @@
         NULL, &uninorth_agp_fake_bridge,
     },
     {
-        0x106B, 0x001F,
-        NULL, "pci", "AAPL,UniNorth", "uni-north",
+        0x106B, 0x001F, NULL, 
+        "pci", "AAPL,UniNorth", "uni-north",
         3, 2, 1,
         NULL, &uninorth_fake_bridge,
     },
@@ -770,10 +855,10 @@
         NULL, &uninorth_fake_bridge,
     },
     {
-        0x1011, 0x0026, NULL,
-        "pci-bridge", NULL, NULL,
+        0x1057, 0x0002, "pci",
+        "pci", "MOT,MPC106", "grackle",
         3, 2, 1,
-        NULL, &PREP_pci_ops,
+        NULL, &grackle_fake_bridge,
     },
     {
         0x1057, 0x4801, NULL,
@@ -1443,7 +1528,14 @@
 }
 
 static const pci_dev_t misc_pci[] = {
-    /* Apple Mac-io controller */
+    /* Paddington Mac I/O */
+    { 
+        0x106B, 0x0017,
+        "mac-io", "mac-io", "AAPL,343S1211", "paddington\1heathrow",
+        1, 1, 1,
+        &macio_config_cb, NULL,
+    },
+    /* KeyLargo Mac I/O */
     { 
         0x106B, 0x0022,
         "mac-io", "mac-io", "AAPL,Keylargo", "Keylargo",
@@ -1599,7 +1691,7 @@
                                       uint8_t min_grant, uint8_t max_latency,
                                       int irq_line)
 {
-    uint32_t cmd;
+    uint32_t cmd, addr;
     int i;
 
     device->min_grant = min_grant;
@@ -1611,22 +1703,28 @@
         printf("MAP PCI device %d:%d to IRQ %d\n",
                device->bus, device->devfn, irq_line);
     }
-    for (i = 0; i < 6; i++) {
+    for (i = 0; i < 7; i++) {
         if ((device->regions[i] & ~0xF) != 0x00000000 &&
             (device->regions[i] & ~0xF) != 0xFFFFFFF0) {
             printf("Map PCI device %d:%d %d to %0x %0x (%s)\n",
                    device->bus, device->devfn, i,
                    device->regions[i], device->sizes[i],
-                   device->regions[i] & 0x00000001 ? "I/O" : "memory");
+                   (device->regions[i] & 0x00000001) && i != 6 ? "I/O" : 
+                    "memory");
+            if (i != 6) {
             cmd = pci_config_readl(bridge, device->bus, device->devfn, 0x04);
             if (device->regions[i] & 0x00000001)
                 cmd |= 0x00000001;
             else
                 cmd |= 0x00000002;
             pci_config_writel(bridge, device->bus, device->devfn, 0x04, cmd);
+            }
+            if (i == 6)
+                addr = 0x30; /* PCI ROM */
+            else
+                addr = 0x10 + (i * sizeof(uint32_t));
             pci_config_writel(bridge, device->bus, device->devfn,
-                              0x10 + (i * sizeof(uint32_t)),
-                              device->regions[i]);
+                              addr, device->regions[i]);
         }
     }
 }
@@ -1900,7 +1998,7 @@
         goto out;
     }
     ret = (pci_u_t *)newd;
-    max_areas = 6;
+    max_areas = 7;
     /* register PCI device in OF tree */
     if (bridge->dev.common.type == PCI_FAKE_BRIDGE) {
         newd->common.OF_private =
@@ -1927,6 +2025,9 @@
             /* Handle 64 bits memory mapping */
             continue;
         }
+        if (i == 6)
+            addr = 0x30; /* PCI ROM */
+        else
         addr = 0x10 + (i * sizeof(uint32_t));
         /* Get region size
          * Note: we assume it's always a power of 2
@@ -1935,7 +2036,7 @@
         smask = pci_config_readl(bridge, bus, devfn, addr);
         if (smask == 0x00000000 || smask == 0xFFFFFFFF)
             continue;
-        if (smask & 0x00000001) {
+        if ((smask & 0x00000001) != 0 && i != 6) {
             /* I/O space */
             base = io_base;
             /* Align to a minimum of 256 bytes (arbitrary) */
@@ -1947,6 +2048,8 @@
             /* Align to a minimum of 64 kB (arbitrary) */
             min_align = 1 << 16;
             amask = 0x0000000F;
+            if (i == 6)
+                smask |= 1; /* PCI ROM enable */
         }
         omask = smask & amask;
         smask &= ~amask;
@@ -1980,7 +2083,10 @@
     if (irq_pin > 0) {
         /* assign the IRQ */
         irq_pin = ((devfn >> 3) + irq_pin - 1) & 3;
-        if (arch == ARCH_PREP) {
+        /* XXX: should base it on the PCI bridge type, not the arch */
+        switch(arch) {
+        case ARCH_PREP:
+            {
             int elcr_port, val;
             irq_line = prep_pci_irqs[irq_pin];
             /* set the IRQ to level-sensitive */
@@ -1988,14 +2094,22 @@
             val = inb(elcr_port);
             val |= 1 << (irq_line & 7);
             outb(elcr_port, val);
-        } else {
+            }
+            break;
+        case ARCH_MAC99:
             irq_line = pmac_pci_irqs[irq_pin];
+            break;
+        case ARCH_HEATHROW:
+            irq_line = heathrow_pci_irqs[irq_pin];
+            break;
+        default:
+            break;
         }
     }
  update_device:
     pci_update_device(bridge, newd, min_grant, max_latency, irq_line);
     OF_finalize_pci_device(newd->common.OF_private, bus, devfn,
-                           newd->regions, newd->sizes);
+                           newd->regions, newd->sizes, irq_line);
     /* Call special inits if needed */
     if (dev->config_cb != NULL)
         (*dev->config_cb)(newd);
@@ -2049,6 +2163,32 @@
     case ARCH_CHRP:
         /* TODO */
         break;
+    case ARCH_HEATHROW:
+        dev = pci_find_device(0x06, 0x00, 0xFF, checkv, checkp);
+        if (dev == NULL)
+            return -1;
+        fake_host = pci_add_host(hostp, dev,
+                                 (0x06 << 24) | (0x00 << 16) | (0xFF << 8));
+        if (fake_host == NULL)
+            return -1;
+        fake_host->dev.common.type = PCI_FAKE_HOST;
+        dev = &grackle_fake_bridge;
+        if (dev == NULL)
+            goto free_fake_host;
+        fake_bridge = pci_add_bridge(fake_host, 0, 0, dev,
+                                     (0x06 << 24) | (0x04 << 16) | (0xFF << 8),
+                                     cfg_base, cfg_len,
+                                     cfg_base + 0x7ec00000,
+                                     cfg_base + 0x7ee00000,
+                                     mem_base, mem_len,
+                                     io_base, io_len,
+                                     rbase, rlen,
+                                     0,
+                                     &grackle_pci_ops);
+        if (fake_bridge == NULL)
+            goto free_fake_host;
+        fake_bridge->dev.common.type = PCI_FAKE_BRIDGE;
+        break;
     case ARCH_MAC99:
         dev = pci_find_device(0x06, 0x00, 0xFF, checkv, checkp);
         if (dev == NULL)
@@ -2167,6 +2307,30 @@
     case ARCH_CHRP:
         /* TODO */
         break;
+    case ARCH_HEATHROW:
+        cfg_base = 0x80000000;
+        cfg_len  = 0x7f000000;
+        mem_base = 0x80000000;
+        mem_len  = 0x01000000;
+        io_base  = 0xfe000000;
+        io_len   = 0x00800000;
+#if 1
+        rbase    = 0xfd000000;
+        rlen     = 0x01000000;
+#else
+        rbase    = 0x00000000;
+        rlen     = 0x01000000;
+#endif
+        if (pci_check_host(&pci_main, cfg_base, cfg_len,
+                           mem_base, mem_len, io_base, io_len, rbase, rlen,
+                           0x1057, 0x0002) == 0) {
+            isa_io_base = io_base;
+            busnum++;
+        }
+        for (curh = pci_main; curh->next != NULL; curh = curh->next)
+            continue;
+        pci_check_devices(curh);
+        break;
     case ARCH_MAC99:
         /* We are supposed to have 3 host bridges:
          * - the uninorth AGP bridge at 0xF0000000