- O2, enums, and switch statements work in romcc
authorEric Biederman <ebiederm@xmission.com>
Sat, 11 Oct 2003 06:20:25 +0000 (06:20 +0000)
committerEric Biederman <ebiederm@xmission.com>
Sat, 11 Oct 2003 06:20:25 +0000 (06:20 +0000)
  - Support for compiling romcc on non x86 platforms
  - new romc options -msse and -mmmx for specifying extra registers to use
  - Bug fixes to device the device disable/enable framework and an amd8111 implementation
  - Move the link specification to the chip specification instead of the path
  - Allow specifying devices with internal bridges.
  - Initial via epia support
 - Opteron errata fixes

git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1200 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

90 files changed:
NEWS
src/arch/i386/lib/console.inc
src/arch/i386/lib/cpu.c
src/boot/hardwaremain.c
src/config/Config.lb
src/config/Options.lb
src/cpu/k8/cpufixup.c
src/cpu/p6/mtrr.c
src/devices/chip.c
src/devices/device.c
src/devices/device_util.c
src/devices/hypertransport.c
src/devices/pci_device.c
src/devices/root_device.c
src/include/cpu/k8/mtrr.h
src/include/device/chip.h
src/include/device/device.h
src/include/device/path.h
src/mainboard/amd/quartet/mptable.c
src/mainboard/arima/hdama/Config.lb
src/mainboard/arima/hdama/auto.c
src/mainboard/arima/hdama/failover.c
src/mainboard/arima/hdama/irq_tables.c
src/mainboard/arima/hdama/mainboard.c
src/mainboard/arima/hdama/mptable.c
src/northbridge/amd/amdk8/Config.lb
src/northbridge/amd/amdk8/coherent_ht.c
src/northbridge/amd/amdk8/cpu_rev.c [new file with mode: 0644]
src/northbridge/amd/amdk8/misc_control.c
src/northbridge/amd/amdk8/northbridge.c
src/northbridge/amd/amdk8/raminit.c
src/northbridge/via/vt8601/northbridge.c
src/pc80/vgabios.c
src/pc80/vgachip.h
src/southbridge/amd/amd8111/Config.lb
src/southbridge/amd/amd8111/amd8111.c [new file with mode: 0644]
src/southbridge/amd/amd8111/amd8111.h [new file with mode: 0644]
src/southbridge/amd/amd8111/amd8111_ac97.c [new file with mode: 0644]
src/southbridge/amd/amd8111/amd8111_acpi.c
src/southbridge/amd/amd8111/amd8111_early_smbus.c
src/southbridge/amd/amd8111/amd8111_ide.c
src/southbridge/amd/amd8111/amd8111_lpc.c
src/southbridge/amd/amd8111/amd8111_nic.c [new file with mode: 0644]
src/southbridge/amd/amd8111/amd8111_usb.c
src/southbridge/amd/amd8111/amd8111_usb2.c
src/southbridge/amd/amd8131/amd8131_bridge.c
src/southbridge/via/vt8231/chip.h
src/southbridge/via/vt8231/vt8231.c
src/southbridge/via/vt8231/vt8231_early_serial.c
src/southbridge/via/vt8231/vt8231_early_smbus.c
src/superio/NSC/pc87360/chip.h
src/superio/NSC/pc87360/superio.c
targets/arima/hdama/Config.lb
targets/buildtarget
util/newconfig/Makefile
util/newconfig/config.g
util/options/build_opt_tbl.c
util/romcc/Makefile
util/romcc/results/linux_test1.out [new file with mode: 0644]
util/romcc/results/linux_test2.out [new file with mode: 0644]
util/romcc/results/linux_test3.out [new file with mode: 0644]
util/romcc/results/linux_test4.out [new file with mode: 0644]
util/romcc/results/linux_test5.out [new file with mode: 0644]
util/romcc/results/linux_test6.out [new file with mode: 0644]
util/romcc/results/linux_test7.out [new file with mode: 0644]
util/romcc/romcc.c
util/romcc/tests/fail_test4.c [new file with mode: 0644]
util/romcc/tests/fail_test5.c [new file with mode: 0644]
util/romcc/tests/linux_console.h [new file with mode: 0644]
util/romcc/tests/linux_syscall.h [new file with mode: 0644]
util/romcc/tests/linux_test1.c [new file with mode: 0644]
util/romcc/tests/linux_test2.c [new file with mode: 0644]
util/romcc/tests/linux_test3.c [new file with mode: 0644]
util/romcc/tests/linux_test4.c [new file with mode: 0644]
util/romcc/tests/linux_test5.c [new file with mode: 0644]
util/romcc/tests/linux_test6.c [new file with mode: 0644]
util/romcc/tests/linux_test7.c [new file with mode: 0644]
util/romcc/tests/linuxi386_syscall.h [new file with mode: 0644]
util/romcc/tests/raminit_test6.c [new file with mode: 0644]
util/romcc/tests/simple_test57.c [new file with mode: 0644]
util/romcc/tests/simple_test58.c [new file with mode: 0644]
util/romcc/tests/simple_test60.c
util/romcc/tests/simple_test61.c [new file with mode: 0644]
util/romcc/tests/simple_test62.c [new file with mode: 0644]
util/romcc/tests/simple_test63.c [new file with mode: 0644]
util/romcc/tests/simple_test64.c [new file with mode: 0644]
util/romcc/tests/simple_test65.c [new file with mode: 0644]
util/romcc/tests/simple_test66.c [new file with mode: 0644]
util/romcc/tests/simple_test67.c [new file with mode: 0644]
util/romcc/tests/simple_test68.c [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 1e2feb71d22285f7314024f0ecae1c1d1c7d9b09..d122514043e00115f36227e09962370bfed0a9c2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,12 @@
+- 1.1.5
+  - O2, enums, and switch statements work in romcc
+  - Support for compiling romcc on non x86 platforms
+  - new romc options -msse and -mmmx for specifying extra registers to use
+  - Bug fixes to device the device disable/enable framework and an amd8111 implementation
+  - Move the link specification to the chip specification instead of the path
+  - Allow specifying devices with internal bridges.
+  - Initial via epia support
+  - Opteron errata fixes
 - 1.1.4
   Major restructuring of hypertransport handling.
   Major rewerite of superio/NSC/pc87360 as a proof of concept for handling superio resources dynamically
index 2f031e5d10236e99e3dc8a41438820ebe473cff9..b617b8c1d0a19226920345e5bd872483b5de534a 100644 (file)
@@ -526,5 +526,7 @@ console_tx_string:
        jmp     console_tx_string
 
 console0:
+#if 0
        CONSOLE_INFO_TX_STRING($console_test)
+#endif
 
index baa029c02cdd3810e7fe67aaa6ec0e4d33b0808a..ad982dbc6cb91371aed3d3306f8edfcd7bbb314e 100644 (file)
@@ -125,7 +125,7 @@ unsigned long cpu_initialize(struct mem_range *mem)
         */
        unsigned long processor_id = this_processors_id();
        printk_notice("Initializing CPU #%d\n", processor_id);
-       
+
        /* some cpus need a fixup done. This is the hook for doing that. */
        cpufixup(mem);
 
index 687b102bbea75b67bc746cd707995d6d7e26593a..6231d1167ed42b0e5cff4c81df9a224d19b6f7c0 100644 (file)
@@ -160,7 +160,6 @@ void hardwaremain(int boot_complete)
 
        /* If we have already booted attempt a hard reboot */
        if (boot_complete) {
-               printk_spew("calling hard_reset\n");
                hard_reset();
        }
        CONFIGURE(CONF_PASS_PRE_PCI);
index ee617c9a60b68f3a9bc745ca1d779cd3728183f9..822f76906c17b889947a274f7426b2f7b887c606 100644 (file)
@@ -7,7 +7,7 @@ makedefine LIBGCC_FILE_NAME := $(shell $(CC) -print-libgcc-file-name)
 makedefine GCC_INC_DIR := $(shell $(CC) -print-search-dirs | sed -ne "s/install: \(.*\)/\1include/gp")
 
 makedefine CPPFLAGS := -I$(TOP)/src/include -I$(TOP)/src/arch/$(ARCH)/include -I$(GCC_INC_DIR) $(CPUFLAGS)
-makedefine ROMCCPPFLAGS := -D__ROMCC__=0 -D__ROMCC_MINOR__=34
+makedefine ROMCCPPFLAGS := -D__ROMCC__=0 -D__ROMCC_MINOR__=36
 makedefine CFLAGS := $(CPU_OPT) $(CPPFLAGS) -Os -nostdinc -nostdlib -fno-builtin  -Wall
 
 makedefine HOSTCFLAGS:= -Os -Wall
@@ -116,7 +116,7 @@ end
 
 makerule ./romcc   
        depends "$(TOP)/util/romcc/romcc.c" 
-       action  "$(HOSTCC) -g $(HOSTCFLAGS) -DVERSION='\"0.34\"' -DRELEASE_DATE='\"4 July 2003\"' $< -o $@"
+       action  "$(HOSTCC) -g $(HOSTCFLAGS) -DVERSION='\"0.36\"' -DRELEASE_DATE='\"10 October 2003\"' $< -o $@"
 end
 
 makerule build_opt_tbl   
index 98d9e8a3bd2cb4a0c7872a78f7e905cf371cef50..1a12e76dbe6de06af3af165196e93fb8d2881397 100644 (file)
@@ -117,7 +117,7 @@ define OBJCOPY
        comment "Objcopy command"
 end
 define LINUXBIOS_VERSION
-       default "1.1.4"
+       default "1.1.5"
        export always
        comment "LinuxBIOS version"
 end
index d5ccfc299dde0c333395aa164c6d3a9ead90930d..6aa6722579dc917b5b40558bd9f65c92a7024b96 100644 (file)
@@ -4,15 +4,67 @@
 #include <cpu/p6/msr.h>
 #include <cpu/k8/mtrr.h>
 #include <device/device.h>
+#include "../../northbridge/amd/amdk8/cpu_rev.c"
 #include <device/chip.h>
-
 #include "chip.h"
 
+#define MCI_STATUS 0x401
+
+static inline void disable_cache(void)
+{
+       unsigned int tmp;
+       /* Disable cache */
+       /* Write back the cache and flush TLB */
+       asm volatile (
+               "movl  %%cr0, %0\n\t"
+               "orl  $0x40000000, %0\n\t"
+               "wbinvd\n\t"
+               "movl  %0, %%cr0\n\t"
+               "wbinvd\n\t"
+               :"=r" (tmp)
+               ::"memory");
+}
+
+static inline void enable_cache(void)
+{
+       unsigned int tmp;
+       // turn cache back on. 
+       asm volatile (
+               "movl  %%cr0, %0\n\t"
+               "andl  $0x9fffffff, %0\n\t"
+               "movl  %0, %%cr0\n\t"
+               :"=r" (tmp)
+               ::"memory");
+}
+
+static inline msr_t rdmsr_amd(unsigned index)
+{
+        msr_t result;
+        __asm__ __volatile__ (
+                "rdmsr"
+                : "=a" (result.lo), "=d" (result.hi)
+                : "c" (index), "D" (0x9c5a203a)
+                );
+        return result;
+}
+
+static inline void wrmsr_amd(unsigned index, msr_t msr)
+{
+        __asm__ __volatile__ (
+                "wrmsr"
+                : /* No outputs */
+                : "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (0x9c5a203a)
+                );
+}
+
 void k8_cpufixup(struct mem_range *mem)
 {
        unsigned long mmio_basek, tomk;
        unsigned long i;
        msr_t msr;
+
+       disable_cache();
+       
        /* Except for the PCI MMIO hold just before 4GB there are no
         * significant holes in the address space, so just account
         * for those two and move on.
@@ -32,28 +84,15 @@ void k8_cpufixup(struct mem_range *mem)
                mmio_basek = tomk;
        }
 
-#if 1
-        /* Report the amount of memory. */
-        print_debug("cpufixup RAM: 0x");
-        print_debug_hex32(tomk);
-        print_debug(" KB\r\n");
-#endif
-
-        /* Now set top of memory */
-        msr.lo = (tomk & 0x003fffff) << 10;
-        msr.hi = (tomk & 0xffc00000) >> 22;
-        wrmsr(TOP_MEM2, msr);
-
-        /* Leave a 64M hole between TOP_MEM and TOP_MEM2
-         * so I can see my rom chip and other I/O devices.
-         */
-        if (tomk >= 0x003f0000) {
-                tomk = 0x3f0000;
-        } //    tom_k = 0x3c0000;
-        msr.lo = (tomk & 0x003fffff) << 10;
-        msr.hi = (tomk & 0xffc00000) >> 22;
-        wrmsr(TOP_MEM, msr);
+       /* Setup TOP_MEM */
+       msr.hi = mmio_basek >> 22;
+       msr.lo = mmio_basek << 10;
+       wrmsr(TOP_MEM, msr);
 
+       /* Setup TOP_MEM2 */
+       msr.hi = tomk >> 22;
+       msr.lo = tomk << 10;
+       wrmsr(TOP_MEM2, msr);
 
        /* zero the IORR's before we enable to prevent
         * undefined side effects.
@@ -66,6 +105,64 @@ void k8_cpufixup(struct mem_range *mem)
        msr = rdmsr(SYSCFG_MSR);
        msr.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_TOM2En;
        wrmsr(SYSCFG_MSR, msr);
+
+       /* zero the machine check error status registers */
+       msr.lo = 0;
+       msr.hi = 0;
+       for(i=0; i<5; i++) {
+               wrmsr(MCI_STATUS + (i*4),msr);
+       }
+       
+       if (is_cpu_pre_c0()) {
+               /* Erratum 63... */
+               msr = rdmsr(HWCR_MSR);
+               msr.lo |= (1 << 6);
+               wrmsr(HWCR_MSR, msr);
+               /* Erratum 69... */
+#if 1
+               msr = rdmsr_amd(BU_CFG_MSR);
+               msr.hi |= (1 << (45 - 32));
+               wrmsr_amd(BU_CFG_MSR, msr);
+#endif
+               /* Erratum 81... */
+#if 1
+               msr = rdmsr_amd(DC_CFG_MSR);
+               msr.lo |=  (1 << 10);
+               wrmsr_amd(DC_CFG_MSR, msr);
+#endif
+                       
+       }
+       /* Erratum 89 ... */
+       msr = rdmsr(NB_CFG_MSR);
+       msr.lo |= 1 << 3;
+
+       if (!is_cpu_pre_c0()) {
+               /* Erratum 86 Disable data masking on C0 and 
+                * later processor revs.
+                * FIXME this is only needed if ECC is enabled.
+                */
+               msr.hi |= 1 << (36 - 32);
+       }       
+       wrmsr(NB_CFG_MSR, msr);
+#if 1  /* The following erratum fixes reset the cpu ???? */
+       
+       /* Erratum 97 ... */
+       if (!is_cpu_pre_c0()) {
+               msr = rdmsr_amd(DC_CFG_MSR);
+               msr.lo |= 1 << 3;
+               wrmsr_amd(DC_CFG_MSR, msr);
+       }       
+       
+       /* Erratum 94 ... */
+       msr = rdmsr_amd(IC_CFG_MSR);
+       msr.lo |= 1 << 11;
+       wrmsr_amd(IC_CFG_MSR, msr);
+
+#endif
+
+       /* Erratum 91 prefetch miss is handled in the kernel */
+       
+       enable_cache();
 }
 
 static
@@ -87,10 +184,6 @@ void k8_enable(struct chip *chip, enum chip_pass pass)
 }
 
 struct chip_control cpu_k8_control = {
-        enable: k8_enable,
-        name:   "AMD K8"
+        .enable = k8_enable,
+        .name   = "AMD K8",
 };
-
-
-
-
index b0678833166b83b25dc773950c3b51aa8a3b0106..1225fafe0803990b369a4148f4c5ccf14f0fad53 100644 (file)
@@ -92,7 +92,7 @@ static void intel_set_var_mtrr(unsigned int reg, unsigned long basek, unsigned l
        base.lo  = basek << 10;
 
        if (sizek < 4*1024*1024) {
-               mask.hi = 0x0F;
+               mask.hi = 0x0FF;
                mask.lo = ~((sizek << 10) -1);
        }
        else {
index b7eace38f009fae5754e8fe445f758a2efe7d3be..c9e1ac564318394e975a225f1f41c2edf0bb6bb9 100644 (file)
@@ -46,16 +46,33 @@ void chip_enumerate(struct chip *chip)
                int identical_paths;
                identical_paths = 
                        (i > 0) &&
-                       (path_eq(&chip->path[i - 1].path, &chip->path[i].path)) &&
-                       (chip->path[i - 1].channel == chip->path[i].channel);
+                       (path_eq(&chip->path[i - 1].path, &chip->path[i].path));
                if (!identical_paths) {
+                       struct bus *parent;
+                       int bus;
                        link = 0;
                        dev = 0;
+                       parent = chip->bus;
                        switch(chip->path[i].path.type) {
                        case DEVICE_PATH_NONE:
                                break;
+                       case DEVICE_PATH_PCI:
+                               bus = chip->path[i].path.u.pci.bus;
+                               if (bus != 0) {
+                                       device_t dev;
+                                       int i = 1;
+                                       dev = chip->dev;
+                                       while(dev && (i != bus)) {
+                                               dev = dev->next;
+                                               i++;
+                                       }
+                                       if ((i == bus) && dev) {
+                                               parent = &dev->link[0];
+                                       }
+                               }
+                               /* Fall through */
                        default:
-                               dev = alloc_dev(chip->bus, &chip->path[i].path);
+                               dev = alloc_dev(parent, &chip->path[i].path);
                                break;
                        }
                }
@@ -63,12 +80,13 @@ void chip_enumerate(struct chip *chip)
                        link += 1;
                }
                if (dev) {
-                       printk_spew("path %s %s\n", dev_path(dev), identical_paths?"identical":"");
+                       printk_spew("path (%p) %s %s", dev, dev_path(dev), identical_paths?"identical":"");
+                       printk_spew(" parent: (%p) %s\n",dev->bus->dev,  dev_path(dev->bus->dev));
+                       dev->chip = chip;
                        dev->enable = chip->path[i].enable;
                        dev->links = link + 1;
                        for(child = chip->children; child; child = child->next) {
-                               if (!child->bus &&
-                                       child->path[0].channel == i) {
+                               if (!child->bus && child->link == i) {
                                        child->bus = &dev->link[link];
                                }
                        }
index 289c0766ea9bdc324ac2434d077d8fcbd04ba414..c6dd5fc4ad3309a7af0029480da382ad9e5638e5 100644 (file)
@@ -115,6 +115,9 @@ static void read_resources(struct bus *bus)
                                dev_path(curdev));
                        continue;
                }
+               if (!curdev->enable) {
+                       continue;
+               }
                curdev->ops->read_resources(curdev);
                /* Read in subtractive resources behind the current device */
                links = 0;
@@ -251,16 +254,12 @@ void compute_allocate_resource(
        min_align = 0;
        base = bridge->base;
 
-       printk_spew("%s: bus %p, bridge %p, type_mask 0x%x, type 0x%x\n",
-                               __FUNCTION__, 
-                               bus, bridge, type_mask, type);
-       printk_spew("vendor 0x%x device 0x%x class 0x%x \n", 
-                       bus->dev->vendor, bus->dev->device, bus->dev->class);
-               printk_spew("%s compute_allocate_%s: base: %08lx size: %08lx align: %d gran: %d\n", 
-                       dev_path(bus->dev),
-                       (bridge->flags & IORESOURCE_IO)? "io":
-                       (bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem",
-                       base, bridge->size, bridge->align, bridge->gran);
+       printk_spew("%s compute_allocate_%s: base: %08lx size: %08lx align: %d gran: %d\n", 
+               dev_path(bus->dev),
+               (bridge->flags & IORESOURCE_IO)? "io":
+               (bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem",
+               base, bridge->size, bridge->align, bridge->gran);
+
 
        /* We want different minimum alignments for different kinds of
         * resources.  These minimums are not device type specific
@@ -406,6 +405,9 @@ void assign_resources(struct bus *bus)
                                dev_path(curdev));
                        continue;
                }
+               if (!curdev->enable) {
+                       continue;
+               }
                curdev->ops->set_resources(curdev);
        }
        printk_debug("ASSIGNED RESOURCES, bus %d\n", bus->secondary);
@@ -422,6 +424,9 @@ void enable_resources(struct device *dev)
                        dev_path(dev));
                return;
        }
+       if (!dev->enable) {
+               return;
+       }
        dev->ops->enable_resources(dev);
 }
 
@@ -444,13 +449,12 @@ void dev_enumerate(void)
 void dev_configure(void)
 {
        struct device *root = &dev_root;
-       printk_info("%s: Allocating resources...", __FUNCTION__);
+       printk_info("Allocating resources...");
        printk_debug("\n");
 
 
        root->ops->read_resources(root);
 
-       printk_spew("%s: done reading resources...\n", __FUNCTION__);
        /* Make certain the io devices are allocated somewhere
         * safe.
         */
@@ -465,10 +469,8 @@ void dev_configure(void)
        root->resource[1].flags |= IORESOURCE_SET;
        // now just set things into registers ... we hope ...
        root->ops->set_resources(root);
-       printk_spew("%s: done setting resources...\n", __FUNCTION__);
 
        allocate_vga_resource();
-       printk_spew("%s: done vga resources...\n", __FUNCTION__);
 
        printk_info("done.\n");
 }
@@ -494,7 +496,7 @@ void dev_initialize(void)
 
        printk_info("Initializing devices...\n");
        for (dev = all_devices; dev; dev = dev->next) {
-               if (dev->ops && dev->ops->init) {
+               if (dev->enable && dev->ops && dev->ops->init) {
                        printk_debug("%s init\n", dev_path(dev));
                        dev->ops->init(dev);
                }
index 384a3be8e02e104e6788bbada28895d66814b16e..6652c86ea0c2475b9aa1cab2a0c7a10a01778124 100644 (file)
@@ -30,15 +30,17 @@ device_t alloc_find_dev(struct bus *parent, struct device_path *path)
  */
 struct device *dev_find_slot(unsigned int bus, unsigned int devfn)
 {
-       struct device *dev;
+       struct device *dev, *result;
 
+       result = 0;
        for (dev = all_devices; dev; dev = dev->next) {
                if ((dev->bus->secondary == bus) && 
                        (dev->path.u.pci.devfn == devfn)) {
+                       result = dev;
                        break;
                }
        }
-       return dev;
+       return result;
 }
 
 /** Find a device of a given vendor and type
@@ -88,6 +90,9 @@ const char *dev_path(device_t dev)
        }
        else {
                switch(dev->path.type) {
+               case DEVICE_PATH_ROOT:
+                       memcpy(buffer, "Root Device", 12);
+                       break;
                case DEVICE_PATH_PCI:
                        sprintf(buffer, "PCI: %02x:%02x.%01x",
                                dev->bus->secondary, 
@@ -116,8 +121,12 @@ int path_eq(struct device_path *path1, struct device_path *path2)
                switch(path1->type) {
                case DEVICE_PATH_NONE:
                        break;
+               case DEVICE_PATH_ROOT:
+                       equal = 1;
+                       break;
                case DEVICE_PATH_PCI:
-                       equal = path1->u.pci.devfn == path2->u.pci.devfn;
+                       equal = (path1->u.pci.bus == path2->u.pci.bus) &&
+                               (path1->u.pci.devfn == path2->u.pci.devfn);
                        break;
                case DEVICE_PATH_PNP:
                        equal = (path1->u.pnp.port == path2->u.pnp.port) &&
index 0c1dc3959a56fb13efaec267fd95717eb1f41632..326f343662aa5ba0ccc6f8dad113c09cbefc79da 100644 (file)
@@ -4,6 +4,7 @@
 #include <device/path.h>
 #include <device/pci.h>
 #include <device/hypertransport.h>
+#include <device/chip.h>
 #include <part/hard_reset.h>
 #include <part/fallback_boot.h>
 
@@ -243,11 +244,19 @@ unsigned int hypertransport_scan_chain(struct bus *bus, unsigned int max)
                        /* Add this device to the pci bus chain */
                        *chain_last = dev;
                        /* Run the magice enable/disable sequence for the device */
-                       if (dev->ops && dev->ops->enable) {
-                               dev->ops->enable(dev);
+                       if (dev->chip && dev->chip->control && dev->chip->control->enable_dev) {
+                               dev->chip->control->enable_dev(dev);
                        }
                        /* Now read the vendor and device id */
                        id = pci_read_config32(dev, PCI_VENDOR_ID);
+
+                       /* If the chain is fully enumerated quit */
+                       if (id == 0xffffffff || id == 0x00000000 ||
+                               id == 0x0000ffff || id == 0xffff0000) {
+                               printk_err("Missing static device: %s\n",
+                                       dev_path(dev));
+                               break;
+                       }
                }
                /* Update the device chain tail */
                for(func = dev; func; func = func->sibling) {
@@ -268,7 +277,8 @@ unsigned int hypertransport_scan_chain(struct bus *bus, unsigned int max)
                /* Find the hypertransport link capability */
                pos = ht_lookup_slave_capability(dev);
                if (pos == 0) {
-                       printk_err("Hypertransport link capability not found");
+                       printk_err("%s Hypertransport link capability not found", 
+                               dev_path(dev));
                        break;
                }
                
index 806734c18b95827c43726a7173a034881fbd5d38..031d855fbfab76fa994ca6b90f320fa0cae137c0 100644 (file)
@@ -18,6 +18,7 @@
 #include <device/device.h>
 #include <device/pci.h>
 #include <device/pci_ids.h>
+#include <device/chip.h>
 #include <part/hard_reset.h>
 #include <part/fallback_boot.h>
 
@@ -175,7 +176,6 @@ static void pci_bridge_read_bases(struct device *dev)
 
        /* FIXME handle bridges without some of the optional resources */
 
-       printk_spew("%s: path %s\n", __FUNCTION__, dev_path(dev));
        /* Initialize the io space constraints on the current bus */
        dev->resource[reg].base  = 0;
        dev->resource[reg].size  = 0;
@@ -215,7 +215,6 @@ static void pci_bridge_read_bases(struct device *dev)
        reg++;
 
        dev->resources = reg;
-       printk_spew("DONE %s: path %s\n", __FUNCTION__, dev_path(dev));
 }
 
 
@@ -455,11 +454,13 @@ static void set_pci_ops(struct device *dev)
                break;
        default:
        bad:
-               printk_err("%s [%04x/%04x/%06x] has unknown header "
-                       "type %02x, ignoring.\n",
-                       dev_path(dev),
-                       dev->vendor, dev->device, 
-                       dev->class >> 8, dev->hdr_type);
+               if (dev->enable) {
+                       printk_err("%s [%04x/%04x/%06x] has unknown header "
+                               "type %02x, ignoring.\n",
+                               dev_path(dev),
+                               dev->vendor, dev->device, 
+                               dev->class >> 8, dev->hdr_type);
+               }
        }
        return;
 }
@@ -556,17 +557,16 @@ unsigned int pci_scan_bus(struct bus *bus,
                }
                else {
                        /* Run the magic enable/disable sequence for the device */
-                       if (dev->ops && dev->ops->enable) {
-                               dev->ops->enable(dev);
+                       if (dev->chip && dev->chip->control && dev->chip->control->enable_dev) {
+                               dev->chip->control->enable_dev(dev);
                        }
                        /* Now read the vendor and device id */
                        id = pci_read_config32(dev, PCI_VENDOR_ID);
                }
-
                /* Read the rest of the pci configuration information */
                hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
                class = pci_read_config32(dev, PCI_CLASS_REVISION);
-
+               
                /* Store the interesting information in the device structure */
                dev->vendor = id & 0xffff;
                dev->device = (id >> 16) & 0xffff;
@@ -576,20 +576,19 @@ unsigned int pci_scan_bus(struct bus *bus,
 
                /* Look at the vendor and device id, or at least the 
                 * header type and class and figure out which set of configuration
-                * methods to use.
+                * methods to use.  Unless we already have some pci ops.
                 */
-               if (!dev->ops) {
-                       set_pci_ops(dev);
-                       /* Error if we don't have some pci operations for it */
-                       if (!dev->ops) {
-                               printk_err("%s No device operations\n",
-                                       dev_path(dev));
-                               continue;
-                       }
-                       /* Now run the magic enable/disable sequence for the device */
-                       if (dev->ops && dev->ops->enable) {
-                               dev->ops->enable(dev);
-                       }
+               set_pci_ops(dev);
+               /* Error if we don't have some pci operations for it */
+               if (dev->enable && !dev->ops) {
+                       printk_err("%s No device operations\n",
+                               dev_path(dev));
+                       continue;
+               }
+
+               /* Now run the magic enable/disable sequence for the device */
+               if (dev->ops && dev->ops->enable) {
+                       dev->ops->enable(dev);
                }
 
                printk_debug("%s [%04x/%04x] %s\n", 
@@ -632,8 +631,7 @@ unsigned int pci_scan_bridge(struct device *dev, unsigned int max)
        struct bus *bus;
        uint32_t buses;
        uint16_t cr;
-       
-       printk_spew("%s: dev %p, max %d\n", __FUNCTION__, dev, max);
+
        bus = &dev->link[0];
        dev->links = 1;
 
@@ -707,7 +705,6 @@ static void pci_level_irq(unsigned char intNum)
        }
 }
 
-
 /*
     This function assigns IRQs for all functions contained within
     the indicated device address.  If the device does not exist or does
index ae022773631586b098b39cdbc7bc9c4cb5ca7c3b..4a076a1bb3740d45a4a45fc94334f6e69441a25f 100644 (file)
@@ -123,6 +123,8 @@ struct device_operations default_dev_ops_root = {
 struct device dev_root = {
        .ops = &default_dev_ops_root,
        .bus = &dev_root.link[0],
+       .path = { .type = DEVICE_PATH_ROOT },
+       .enable = 1,
        .links = 1,
        .link = {
                [0] = {
index 5f08a512156f873cae88a4359e3c57e50bdd4ad0..5a965eebb8500bb488d2f8eac433813f25c5ea97 100644 (file)
@@ -30,5 +30,9 @@
 #define TOP_MEM                                0xC001001A
 #define TOP_MEM2                       0xC001001D
 #define HWCR_MSR                       0xC0010015
+#define NB_CFG_MSR                     0xC001001f
+#define IC_CFG_MSR                     0xC0011021
+#define DC_CFG_MSR                     0xC0011022
+#define BU_CFG_MSR                     0xC0011023
 
 #endif /* CPU_K8_MTRR_H */
index a98625a7abe01c2eeba0d6026922a5fb59891b45..dc078a96b773a40cb869cbffc99401e2195c45a0 100644 (file)
@@ -49,6 +49,7 @@ enum chip_pass {
  */
 
 struct chip;
+struct device;
 
 /* there is one of these for each TYPE of chip */
 struct chip_control {
@@ -56,6 +57,7 @@ struct chip_control {
        char *name;
        void (*enable)(struct chip *, enum chip_pass);
        void (*enumerate)(struct chip *chip);
+       void (*enable_dev)(struct device *dev);
 };
 
 
@@ -72,6 +74,7 @@ struct bus;
 #define MAX_CHIP_PATHS 16
 #endif
 struct chip {
+       unsigned link;
        struct chip_control *control; /* for this device */
        struct chip_device_path path[MAX_CHIP_PATHS]; /* can be 0, in which case the default is taken */
        char *configuration; /* can be 0. */
index e7b0317db3fef87fd18fca1497fa37b0e0588fed..1b2b0169dc05417411e190a37522ce6f5c1e35af 100644 (file)
@@ -35,6 +35,7 @@ struct bus {
  * combination:
  */
 
+struct chip;
 struct device {
        struct bus *    bus;            /* bus this device is on */
        device_t        sibling;        /* next device on this bus */
@@ -72,6 +73,7 @@ struct device {
 
        unsigned long rom_address;
        struct device_operations *ops;
+       struct chip *chip;
 };
 
 extern struct device   dev_root;       /* root bus */
@@ -94,7 +96,7 @@ extern void enumerate_static_device(void);
 extern const char *dev_path(device_t dev);
 
 /* Helper functions */
-device_t alloc_find_dev(struct bus *bus, struct device_path *path);
+device_t alloc_find_dev(struct bus *parent, struct device_path *path);
 device_t dev_find_device (unsigned int vendor, unsigned int device, device_t from);
 device_t dev_find_class (unsigned int class, device_t from);
 device_t dev_find_slot (unsigned int bus, unsigned int devfn);
index cf89a68466a2ef2f627d7f463fff19c483468869..20d76d1bbee1b2fe86044b2655a12eabce8e7814 100644 (file)
@@ -3,6 +3,7 @@
 
 enum device_path_type {
        DEVICE_PATH_NONE = 0,
+       DEVICE_PATH_ROOT,
        DEVICE_PATH_PCI,
        DEVICE_PATH_PNP,
        DEVICE_PATH_I2C,
@@ -10,6 +11,7 @@ enum device_path_type {
 
 struct pci_path
 {
+       unsigned bus;
        unsigned devfn;
 };
 
index 94ac7357445815ac9557ae218690d36353e8e796..6c29589a81db55506b625cc639f52fcec5519e42 100644 (file)
@@ -7,8 +7,8 @@
 void *smp_write_config_table(void *v, unsigned long * processor_map)
 {
        static const char sig[4] = "PCMP";
-       static const char oem[8] = "LNXI    ";
-       static const char productid[12] = "HDAMA       ";
+       static const char oem[8] = "AMD     ";
+       static const char productid[12] = "QUARTET     ";
        struct mp_config_table *mc;
        unsigned char bus_num;
        unsigned char bus_isa;
index b056124b742e2bef9e4b166b4b6f99ae316283b1..2604021cc7f36805a3c5351d60757f5ce8acf55d 100644 (file)
@@ -161,7 +161,7 @@ makerule ./auto.E
 end
 makerule ./auto.inc 
        depends "./auto.E ./romcc"
-       action  "./romcc -mcpu=k8  -O ./auto.E > auto.inc"
+       action  "./romcc -mcpu=k8 -O2 ./auto.E > auto.inc"
 end
 
 ##
@@ -231,32 +231,36 @@ northbridge amd/amdk8 "mc0"
        pci 0:18.1
        pci 0:18.2
        pci 0:18.3
-       southbridge amd/amd8131 "amd8131"
+       southbridge amd/amd8131 "amd8131" link 0
                pci 0:0.0
                pci 0:0.1
                pci 0:1.0
                pci 0:1.1
        end
-       southbridge amd/amd8111 "amd8111"
+       southbridge amd/amd8111 "amd8111" link 0
                pci 0:0.0
-               pci 0:1.0
-               pci 0:1.1
-               pci 0:1.2
-               pci 0:1.3
-               pci 0:1.5
-               pci 0:1.6
-               superio NSC/pc87360
-                       pnp 1:2e.0
-                       pnp 1:2e.1
-                       pnp 1:2e.2
-                       pnp 1:2e.3
-                       pnp 1:2e.4
-                       pnp 1:2e.5
-                       pnp 1:2e.6
-                       pnp 1:2e.7
-                       pnp 1:2e.8
-                       pnp 1:2e.9
-                       pnp 1:2e.a
+               pci 0:1.0 on
+               pci 0:1.1 on
+               pci 0:1.2 on
+               pci 0:1.3 on
+               pci 0:1.5 off
+               pci 0:1.6 off
+               pci 1:0.0 on
+               pci 1:0.1 on
+               pci 1:0.2 on
+               pci 1:1.0 off
+               superio NSC/pc87360 link 1
+                       pnp 2e.0
+                       pnp 2e.1
+                       pnp 2e.2
+                       pnp 2e.3
+                       pnp 2e.4
+                       pnp 2e.5
+                       pnp 2e.6
+                       pnp 2e.7
+                       pnp 2e.8
+                       pnp 2e.9
+                       pnp 2e.a
                        register "com1" = "{1, 0, 0x3f8, 4}"
                        register "lpt" = "{1}"
                end
index f0651d1b09ef0d39df2bb836fd8b0b40914924dd..244d0ea305e67cdc25d31c29ff073aa084b9f805 100644 (file)
@@ -1,5 +1,4 @@
 #define ASSEMBLY 1
-
 #include <stdint.h>
 #include <device/pci_def.h>
 #include <cpu/p6/apic.h>
 #include "cpu/p6/boot_cpu.c"
 #include "northbridge/amd/amdk8/reset_test.c"
 #include "debug.c"
+#include "northbridge/amd/amdk8/cpu_rev.c"
 
 #define SIO_BASE 0x2e
-#define MAXIMUM_CONSOLE_LOGLEVEL 9
-#define DEFAULT_CONSOLE_LOGLEVEL 9
 
 static void memreset_setup(void)
 {
-       /* Set the memreset low */
-       outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 28);
-       /* Ensure the BIOS has control of the memory lines */
-       outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 29);
+       if (is_cpu_pre_c0()) {
+               /* Set the memreset low */
+               outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 28);
+               /* Ensure the BIOS has control of the memory lines */
+               outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 29);
+       }
+       else {
+               /* Ensure the CPU has controll of the memory lines */
+               outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 29);
+       }
 }
 
 static void memreset(int controllers, const struct mem_controller *ctrl)
 {
-       udelay(800);
-       /* Set memreset_high */
-       outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 28);
-       udelay(90);
+       if (is_cpu_pre_c0()) {
+               udelay(800);
+               /* Set memreset_high */
+               outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 28);
+               udelay(90);
+       }
 }
 
 static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes)
@@ -92,9 +98,6 @@ static void coherent_ht_mainboard(unsigned cpus)
 {
 }
 
-#include "northbridge/amd/amdk8/cpu_ldtstop.c"
-#include "southbridge/amd/amd8111/amd8111_ldtstop.c"
-
 #include "northbridge/amd/amdk8/raminit.c"
 #include "northbridge/amd/amdk8/coherent_ht.c"
 #include "sdram/generic_sdram.c"
@@ -201,7 +204,7 @@ static void main(void)
        enumerate_ht_chain(0);
        distinguish_cpu_resets(0);
        
-#if 1
+#if 0
        print_pci_devices();
 #endif
        enable_smbus();
@@ -211,10 +214,10 @@ static void main(void)
        memreset_setup();
        sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);
 
-#if 1
+#if 0
        dump_pci_devices();
 #endif
-#if 1
+#if 0
        dump_pci_device(PCI_DEV(0, 0x18, 2));
 #endif
 
index 8eeeaef7e1b056cdf76f25f959b51bf2f30c18d9..bd9c17020ec077595b157cc5275c6cff88a6b4f2 100644 (file)
@@ -27,6 +27,10 @@ static void main(void)
                        asm("jmp __cpu_reset");
                }
        }
+       /* Is this a deliberate reset by the bios */
+       else if (bios_reset_detected() && last_boot_normal()) {
+               asm("jmp __normal_image");
+       }
        /* Is this a secondary cpu? */
        else if (!boot_cpu() && last_boot_normal()) {
                asm("jmp __normal_image");
index 2c0095c17763e54887c1e2d314927447f04bef79..142864fbb1fd9306faa672202b4ac6fafee93fb4 100644 (file)
@@ -1,43 +1,34 @@
-/* This file was generated by getpir.c, do not modify! 
-   (but if you do, please run checkpir on it to verify)
-   Contains the IRQ Routing Table dumped directly from your memory , wich BIOS sets up
-
-   Documentation at : http://www.microsoft.com/hwdev/busbios/PCIIRQ.HTM
-*/
-
 #include <arch/pirq_routing.h>
 
-
 const struct irq_routing_table intel_irq_routing_table = {
        PIRQ_SIGNATURE, /* u32 signature */
        PIRQ_VERSION,   /* u16 version   */
-       32+16*18,        /* there can be total 18 devices on the bus */
-       1,           /* Where the interrupt router lies (bus) */
-       0x23,           /* Where the interrupt router lies (dev) */
-       0,         /* IRQs devoted exclusively to PCI usage */
+       32+16*9,        /* there can be total 9 devices on the bus */
+       1,              /* Where the interrupt router lies (bus) */
+       (4<<3)|3,       /* Where the interrupt router lies (dev) */
+       0x0,            /* IRQs devoted exclusively to PCI usage */
        0x1022,         /* Vendor */
        0x746b,         /* Device */
-       0,         /* Crap (miniport) */
+       0,              /* Crap (miniport) */
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
-       0x35,         /*  u8 checksum , this hase to set to some value that would give 0 after the sum of all bytes for this structure (including checksum) */
-       {
-               {0,0xc0, {{0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}}, 0, 0},
-               {0,0x50, {{0x1, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}}, 0, 0},
-               {0x2,0x8, {{0x2, 0xdef8}, {0x3, 0xdef8}, {0x4, 0xdef8}, {0x1, 0xdef8}}, 0x3, 0},
-               {0x2,0x10, {{0x3, 0xdef8}, {0x4, 0xdef8}, {0x1, 0xdef8}, {0x2, 0xdef8}}, 0x4, 0},
-               {0x2,0x18, {{0x4, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}}, 0x0, 0},
-               {0x2,0x20, {{0x4, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}}, 0x0, 0},
-               {0x2,0x28, {{0x2, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}}, 0xa, 0},
-               {0,0x58, {{0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}}, 0, 0},
-               {0x3,0x8, {{0x2, 0xdef8}, {0x3, 0xdef8}, {0x4, 0xdef8}, {0x1, 0xdef8}}, 0x1, 0},
-               {0x3,0x10, {{0x3, 0xdef8}, {0x4, 0xdef8}, {0x1, 0xdef8}, {0x2, 0xdef8}}, 0x2, 0},
-               {0x3,0x18, {{0x4, 0xdef8}, {0x1, 0xdef8}, {0x2, 0xdef8}, {0x3, 0xdef8}}, 0x9, 0},
-               {0,0x30, {{0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}}, 0, 0},
-               {0x1,0, {{0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}, {0x4, 0xdef8}}, 0, 0},
-               {0x1,0x28, {{0x2, 0xdef8}, {0x3, 0xdef8}, {0x4, 0xdef8}, {0x1, 0xdef8}}, 0x5, 0},
-               {0x1,0x20, {{0x1, 0xdef8}, {0x2, 0xdef8}, {0x3, 0xdef8}, {0x4, 0xdef8}}, 0x6, 0},
-               {0x1,0x30, {{0x3, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}}, 0xb, 0},
-               {0,0x38, {{0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}}, 0, 0},
-               {0,0xc8, {{0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}, {0, 0xdef8}}, 0, 0},
+       0xb0,           /*  u8 checksum , mod 256 checksum must give zero */
+       {       /* bus, devfn,     {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu  */
+               /* PCI Slot 1 */
+               {0x03, (0x01<<3)|0, {{0x02, 0xdef8}, {0x03, 0xdef8}, {0x04, 0xdef8}, {0x01, 0xdef8}}, 0x01, 0},
+               /* PCI Slot 2 */
+               {0x03, (0x02<<3)|0, {{0x03, 0xdef8}, {0x04, 0xdef8}, {0x01, 0xdef8}, {0x02, 0xdef8}}, 0x02, 0},
+               /* PCI Slot 3 */
+               {0x02, (0x01<<3)|0, {{0x02, 0xdef8}, {0x03, 0xdef8}, {0x04, 0xdef8}, {0x01, 0xdef8}}, 0x03, 0},
+               /* PCI Slot 4 */
+               {0x02, (0x02<<3)|0, {{0x03, 0xdef8}, {0x04, 0xdef8}, {0x01, 0xdef8}, {0x02, 0xdef8}}, 0x04, 0},
+               /* PCI Slot 5 */
+               {0x04, (0x05<<3)|0, {{0x02, 0xdef8}, {0x03, 0xdef8}, {0x04, 0xdef8}, {0x01, 0xdef8}}, 0x05, 0},
+               /* PCI Slot 6 */
+               {0x04, (0x04<<3)|0, {{0x01, 0xdef8}, {0x02, 0xdef8}, {0x03, 0xdef8}, {0x04, 0xdef8}}, 0x06, 0},
+               /* Onboard NICS */
+               {0x02, (0x03<<3)|0, {{0x04, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0},
+               {0x02, (0x04<<3)|0, {{0x04, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0},
+               /* Let Linux know about bus 1 */
+               {0x01, (0x04<<3)|3, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0},
        }
 };
index c5812ece3f28ef577ae9d85ef905e6458716e331..82041282f643b60e2b7ab1a403b6c33be95c396a 100644 (file)
@@ -1,4 +1,3 @@
-
 #include <console/console.h>
 #include <device/device.h>
 #include <device/pci.h>
index 94ac7357445815ac9557ae218690d36353e8e796..bd9df2e3ac63e4ba114e774e0961bb26a37ac3c5 100644 (file)
@@ -48,8 +48,8 @@ void *smp_write_config_table(void *v, unsigned long * processor_map)
                else {
                        printk_debug("ERROR - could not find PCI 1:03.0, using defaults\n");
 
-                       bus_8111_1 = 3;
-                       bus_isa = 4;
+                       bus_8111_1 = 4;
+                       bus_isa = 5;
                }
                /* 8131-1 */
                dev = dev_find_slot(1, PCI_DEVFN(0x01,0));
@@ -60,7 +60,7 @@ void *smp_write_config_table(void *v, unsigned long * processor_map)
                else {
                        printk_debug("ERROR - could not find PCI 1:01.0, using defaults\n");
 
-                       bus_8131_1 = 1;
+                       bus_8131_1 = 2;
                }
                /* 8131-2 */
                dev = dev_find_slot(1, PCI_DEVFN(0x02,0));
@@ -71,7 +71,7 @@ void *smp_write_config_table(void *v, unsigned long * processor_map)
                else {
                        printk_debug("ERROR - could not find PCI 1:02.0, using defaults\n");
 
-                       bus_8131_2 = 2;
+                       bus_8131_2 = 3;
                }
        }
 
@@ -144,10 +144,6 @@ void *smp_write_config_table(void *v, unsigned long * processor_map)
                bus_isa, 0x00, MP_APIC_ALL, 0x01);
 
 
-       /* AGP Slot */
-       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               0x03, (6<<2)|0, 0x02, 0x12);
-
        /* PCI Slot 1 */
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
                bus_8131_2, (1<<2)|0, 0x02, 0x11);
index 6112ed18c8ccfec6372dd6c292880fd929fcaf74..0110e218ce48b650513e57d04455af8913e91dd5 100644 (file)
@@ -1,3 +1,4 @@
 config chip.h
 object northbridge.o
 driver misc_control.o
+driver mcf0_control.o
index b2839159c73347cfd2d3b185a08d48c0d0e07ebb..f05ee3d22db4c584748a4ac01d520befeccb4a95 100644 (file)
@@ -100,43 +100,6 @@ static void disable_probes(void)
        print_debug("done.\r\n");
 
 }
-//BY LYH
-#define WAIT_TIMES 1000
-static void wait_ap_stop(u8 node) 
-{
-       unsigned long reg;
-       unsigned long i;
-       for(i=0;i<WAIT_TIMES;i++) {
-               unsigned long regx;
-               regx = pci_read_config32(NODE_HT(node),0x6c);
-               if((regx & (1<<4))==1) break;
-        }
-       reg = pci_read_config32(NODE_HT(node),0x6c);
-        reg &= ~(1<<4);  // clear it
-        pci_write_config32(NODE_HT(node), 0x6c, reg);
-
-}
-static void notify_bsp_ap_is_stopped(void)
-{
-       unsigned long reg;
-       unsigned long apic_id;
-        apic_id = *((volatile unsigned long *)(APIC_DEFAULT_BASE+APIC_ID));
-       apic_id >>= 24;
-#if 0
-       print_debug("applicaton cpu apic_id: ");
-       print_debug_hex32(apic_id);
-       print_debug("\r\n");
-#endif
-       /* AP  apic_id == node_id ? */
-        if(apic_id != 0) {
-               /* set the ColdResetbit to notify BSP that AP is stopped */
-                reg = pci_read_config32(NODE_HT(apic_id), 0x6C);
-                reg |= 1<<4;
-                pci_write_config32(NODE_HT(apic_id), 0x6C, reg);
-        }
-}
-//BY LYH END
 
 static void enable_routing(u8 node)
 {
@@ -169,15 +132,8 @@ static void enable_routing(u8 node)
        print_debug_hex32(node);
 
        val=pci_read_config32(NODE_HT(node), 0x6c);
-        val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0)); 
-       pci_write_config32(NODE_HT(node), 0x6c, val);
-//BY LYH
-#if 1
-       if(node!=0) {
-               wait_ap_stop(node);
-       }
-#endif
-//BY LYH END
+       val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0));
+       pci_write_config32(NODE_HT(node), 0x6c, val);
 
        print_debug(" done.\r\n");
 }
@@ -225,6 +181,62 @@ static bool check_connection(u8 src, u8 dest, u8 link)
        return 1;
 }
 
+static void optimize_connection(u8 node1, u8 link1, u8 node2, u8 link2)
+{
+       static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
+       static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
+       uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask;
+       uint8_t width_cap1, width_cap2, width_cap, width, ln_width1, ln_width2;
+       uint8_t freq;
+       /* Set link width and frequency */
+
+       /* Get the frequency capabilities */
+       freq_cap1  = pci_read_config16(NODE_HT(node1), 0x80 + link1 + PCI_HT_CAP_HOST_FREQ_CAP);
+       freq_cap2  = pci_read_config16(NODE_HT(node2), 0x80 + link2 + PCI_HT_CAP_HOST_FREQ_CAP);
+
+       /* Calculate the highest possible frequency */
+#if 1
+       /* FIXME!!!!!!! 
+        * This method of computing the fastes frequency is broken.
+        * Because the frequencies (i.e. 100Mhz) are not ordered.
+        */
+       freq = log2(freq_cap1 & freq_cap2 & 0xff);
+#else
+       /* Only allow supported frequencies 800Mhz and below */
+       freq = log2(freq_cap1 & freq_cap2 & 0x3f);
+#endif
+
+       /* Set the Calulcated link frequency */
+       pci_write_config8(NODE_HT(node1), 0x80 + link1 + PCI_HT_CAP_HOST_FREQ, freq);
+       pci_write_config8(NODE_HT(node2), 0x80 + link2 + PCI_HT_CAP_HOST_FREQ, freq);
+
+       /* Get the width capabilities */
+       width_cap1 = pci_read_config8(NODE_HT(node1),  0x80 + link1 + PCI_HT_CAP_HOST_WIDTH);
+       width_cap2 = pci_read_config8(NODE_HT(node2),  0x80 + link2 + PCI_HT_CAP_HOST_WIDTH);
+
+       /* Calculate node1's input width */
+       ln_width1 = link_width_to_pow2[width_cap1 & 7];
+       ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7];
+       if (ln_width1 > ln_width2) {
+               ln_width1 = ln_width2;
+       }
+       width = pow2_to_link_width[ln_width1];
+       /* Calculate node1's output width */
+       ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7];
+       ln_width2 = link_width_to_pow2[width_cap2 & 7];
+       if (ln_width1 > ln_width2) {
+               ln_width1 = ln_width2;
+       }
+       width |= pow2_to_link_width[ln_width1] << 4;
+       
+       /* Set node1's widths */
+       pci_write_config8(NODE_HT(node1), 0x80 + link1 + PCI_HT_CAP_HOST_WIDTH + 1, width);
+
+       /* Set node2's widths */
+       width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
+       pci_write_config8(NODE_HT(node2), 0x80 + link2 + PCI_HT_CAP_HOST_WIDTH + 1, width);
+}
+
 static void fill_row(u8 node, u8 row, u32 value)
 {
 #if 0
@@ -346,6 +358,7 @@ static u8 setup_smp(void)
        }
 
        /* We found 2 nodes so far */
+       optimize_connection(0, ACROSS, 7, ACROSS);
        setup_node(0, cpus);    /* Node 1 is there. Setup Node 0 correctly */
        setup_remote_node(1, cpus);  /* Setup the routes on the remote node */
         rename_temp_node(1);    /* Rename Node 7 to Node 1  */
@@ -444,17 +457,6 @@ static unsigned detect_mp_capabilities(unsigned cpus)
 
 #endif
 
-/* this is a shrunken cpuid. */
-
-static unsigned int cpuid(unsigned int op)
-{
-       unsigned int ret;
-
-       asm volatile ( "cpuid" : "=a" (ret) : "a" (op));
-
-       return ret;
-}
-
 static void coherent_ht_finalize(unsigned cpus)
 {
        int node;
@@ -469,7 +471,7 @@ static void coherent_ht_finalize(unsigned cpus)
 #if 1
        print_debug("coherent_ht_finalize\r\n");
 #endif
-       rev_a0=((cpuid(1)&0xffff)==0x0f10);
+       rev_a0= is_cpu_rev_a0();
 
        for (node=0; node<cpus; node++) {
                u32 val;
@@ -479,7 +481,11 @@ static void coherent_ht_finalize(unsigned cpus)
                pci_write_config32(NODE_HT(node),0x60,val);
 
                val=pci_read_config32(NODE_HT(node), 0x68);
+#if 1
+               val |= 0x00008000;
+#else
                val |= 0x0f00c800;  // 0x00008000->0f00c800 BY LYH
+#endif
                pci_write_config32(NODE_HT(node),0x68,val);
 
                if (rev_a0) {
@@ -508,7 +514,7 @@ static int setup_coherent_ht_domain(void)
 #endif
        coherent_ht_finalize(cpus);
 
-       /* this should probably go away again. */
+       /* FIXME this should probably go away again. */
        coherent_ht_mainboard(cpus);
        return reset_needed;
 }
diff --git a/src/northbridge/amd/amdk8/cpu_rev.c b/src/northbridge/amd/amdk8/cpu_rev.c
new file mode 100644 (file)
index 0000000..51f2359
--- /dev/null
@@ -0,0 +1,25 @@
+/* this is a shrunken cpuid. */
+
+static unsigned int cpuid(unsigned int op)
+{
+       unsigned int ret;
+       unsigned dummy2,dummy3,dummy4;
+
+       asm volatile ( 
+               "cpuid" 
+               : "=a" (ret), "=b" (dummy2), "=c" (dummy3), "=d" (dummy4)
+               : "a" (op)
+               );
+
+       return ret;
+}
+
+static int is_cpu_rev_a0(void)
+{
+       return (cpuid(1) & 0xffff) == 0x0f10;
+}
+
+static int is_cpu_pre_c0(void)
+{
+       return (cpuid(1) & 0xffef) < 0x0f48;
+}
index 639e34fbaf0d2002bc5b8b817183c646a435c400..045f5cef06dc523ba2a32ebd4c9d181c590d06d2 100644 (file)
@@ -8,6 +8,7 @@
 #include <device/pci.h>
 #include <device/pci_ids.h>
 #include <device/pci_ops.h>
+#include "./cpu_rev.c"
 
 static void misc_control_init(struct device *dev)
 {
@@ -17,7 +18,48 @@ static void misc_control_init(struct device *dev)
        cmd = pci_read_config32(dev, 0x44);
        cmd |= (1<<6) | (1<<25);
        pci_write_config32(dev, 0x44, cmd );
+       if (is_cpu_pre_c0()) {
+               /* errata 58 */
+               cmd = pci_read_config32(dev, 0x80);
+               cmd &= ~(1<<0);
+               pci_write_config32(dev, 0x80, cmd );
+               cmd = pci_read_config32(dev, 0x84);
+               cmd &= ~(1<<24);
+               cmd &= ~(1<<8);
+               pci_write_config32(dev, 0x84, cmd );
+               /* errata 66 */
+               cmd = pci_read_config32(dev, 0x70);
+               cmd &= ~(1<<0);
+               cmd |= (1<<1);
+               pci_write_config32(dev, 0x70, cmd );
+               cmd = pci_read_config32(dev, 0x7c);
+               cmd &= ~(3<<4);
+               pci_write_config32(dev, 0x7c, cmd );
+       }
+       else {
+               /* errata 98 */
+#if 0          
+               cmd = pci_read_config32(dev, 0xd4);
+               if(cmd != 0x04e20707) {
+                       cmd = 0x04e20707;
+                       pci_write_config32(dev, 0xd4, cmd );
+                       hard_reset();
+               }
+#endif
 
+               cmd = 0x04e20707;
+               pci_write_config32(dev, 0xd4, cmd );
+       }
+#if 1  
+       cmd = pci_read_config32(dev, 0xdc);
+       if((cmd & 0x0000ff00) != 0x02500) {
+               cmd &= 0xffff00ff;
+               cmd |= 0x00002500;
+               pci_write_config32(dev, 0xdc, cmd );
+               printk_debug("resetting cpu\n");
+               hard_reset();
+       }
+#endif 
        printk_debug("done.\n");
 }
 
index 7bcb1567ba41b1cb09f958085e0bd9de4526a193..13845c5a700f240716ddf1983f47e80a4d75cf0e 100644 (file)
@@ -475,6 +475,6 @@ static void enumerate(struct chip *chip)
 }
 
 struct chip_control northbridge_amd_amdk8_control = {
-       .enumerate = enumerate,
        .name   = "AMD K8 Northbridge",
+       .enumerate = enumerate,
 };
index 802e4318b483b2dcc60a69c2367cfe98ac825c5b..437ef2655da77b1db50cd424a3b679efa2d64a93 100644 (file)
 #define         DCH_MEMCLK_EN3       (1 << 29) 
 
 /* Function 3 */
+#define MCA_NB_CONFIG      0x44
+#define   MNC_ECC_EN       (1 << 22)
+#define   MNC_CHIPKILL_EN  (1 << 23)
 #define SCRUB_CONTROL     0x58
 #define          SCRUB_NONE        0
 #define          SCRUB_40ns        1
@@ -1127,23 +1130,6 @@ static void spd_set_ram_size(const struct mem_controller *ctrl)
        }
 }
 
-//BY LYH //Fill next base reg with right value
-static void fill_last(unsigned long node_id,unsigned long base)
-{
-        unsigned i;
-        unsigned base_reg;
-        base &=0xffff0000;
-        device_t device;
-        for(device = PCI_DEV(0, 0x18, 1); device <= PCI_DEV(0, 0x1f, 1); device
-+= PCI_DEV(0, 1, 0)) {
-                for(i=node_id+1;i<=7;i++) {
-                        base_reg=0x40+(i<<3);
-                        pci_write_config32(device,base_reg,base);
-                }
-        }
-}
-//BY LYH END
 static void route_dram_accesses(const struct mem_controller *ctrl,
        unsigned long base_k, unsigned long limit_k)
 {
@@ -1177,7 +1163,12 @@ static void set_top_mem(unsigned tom_k)
 {
        /* Error if I don't have memory */
        if (!tom_k) {
-               die("No memory");
+               set_bios_reset();
+               print_debug("No memory - reset");
+               /* enable cf9 */
+               pci_write_config8(PCI_DEV(0, 0x04, 3), 0x41, 0xf1);
+               /* reset */
+               outb(0x0e, 0x0cf9);
        }
 
 #if 1
@@ -1204,15 +1195,102 @@ static void set_top_mem(unsigned tom_k)
        wrmsr(TOP_MEM, msr);
 }
 
-static void order_dimms(const struct mem_controller *ctrl)
+static unsigned long interleave_chip_selects(const struct mem_controller *ctrl)
 {
-       unsigned long tom, tom_k, base_k;
-       unsigned node_id;
+       /* 35 - 25 */
+       static const uint32_t csbase_low[] = { 
+       /* 32MB */      (1 << (13 - 4)),
+       /* 64MB */      (1 << (14 - 4)),
+       /* 128MB */     (1 << (14 - 4)), 
+       /* 256MB */     (1 << (15 - 4)),
+       /* 512MB */     (1 << (15 - 4)),
+       /* 1GB */       (1 << (16 - 4)),
+       /* 2GB */       (1 << (16 - 4)), 
+       };
+       uint32_t csbase_inc;
+       int chip_selects, index;
+       int bits;
+       int dual_channel;
+       unsigned common_size;
+       uint32_t csbase, csmask;
+
+       /* See if all of the memory chip selects are the same size
+        * and if so count them.
+        */
+       chip_selects = 0;
+       common_size = 0;
+       for(index = 0; index < 8; index++) {
+               unsigned size;
+               uint32_t value;
+               
+               value = pci_read_config32(ctrl->f2, DRAM_CSBASE + (index << 2));
+               
+               /* Is it enabled? */
+               if (!(value & 1)) {
+                       continue;
+               }
+               chip_selects++;
+               size = value >> 21;
+               if (common_size == 0) {
+                       common_size = size;
+               }
+               /* The size differed fail */
+               if (common_size != size) {
+                       return 0;
+               }
+       }
+       /* Chip selects can only be interleaved when there is
+        * more than one and their is a power of two of them.
+        */
+       bits = log2(chip_selects);
+       if (((1 << bits) != chip_selects) || (bits < 1) || (bits > 3)) {
+               return 0;
+               
+       }
+       /* Also we run out of address mask bits if we try and interleave 8 4GB dimms */
+       if ((bits == 3) && (common_size == (1 << (32 - 3)))) {
+               print_debug("8 4GB chip selects cannot be interleaved\r\n");
+               return 0;
+       }
+       /* Find the bits of csbase that we need to interleave on */
+       if (is_dual_channel(ctrl)) {
+               csbase_inc = csbase_low[log2(common_size) - 1] << 1;
+       } else {
+               csbase_inc = csbase_low[log2(common_size)];
+       }
+       /* Compute the initial values for csbase and csbask. 
+        * In csbase just set the enable bit and the base to zero.
+        * In csmask set the mask bits for the size and page level interleave.
+        */
+       csbase = 0 | 1;
+       csmask = (((common_size  << bits) - 1) << 21);
+       csmask |= 0xfe00 & ~((csbase_inc << bits) - csbase_inc);
+       for(index = 0; index < 8; index++) {
+               uint32_t value;
+
+               value = pci_read_config32(ctrl->f2, DRAM_CSBASE + (index << 2));
+               /* Is it enabled? */
+               if (!(value & 1)) {
+                       continue;
+               }
+               pci_write_config32(ctrl->f2, DRAM_CSBASE + (index << 2), csbase);
+               pci_write_config32(ctrl->f2, DRAM_CSMASK + (index << 2), csmask);
+               csbase += csbase_inc;
+       }
+       
+#if 1
+       print_debug("Interleaved\r\n");
+#endif 
+       /* Return the memory size in K */
+       return common_size << (15 + bits);
+}
 
-       /* Compute the memory base address address */
-       base_k = 0;
+static unsigned long order_chip_selects(const struct mem_controller *ctrl)
+{
+       unsigned long tom;
+       
        /* Remember which registers we have used in the high 8 bits of tom */
-       tom = base_k >> 15;
+       tom = 0;
        for(;;) {
                /* Find the largest remaining canidate */
                unsigned index, canidate;
@@ -1270,8 +1348,19 @@ static void order_dimms(const struct mem_controller *ctrl)
                pci_write_config32(ctrl->f2, DRAM_CSMASK + (canidate << 2), csmask);
                
        }
-       tom_k = (tom & ~0xff000000) << 15;
+       /* Return the memory size in K */
+       return (tom & ~0xff000000) << 15;
+}
+
+static void order_dimms(const struct mem_controller *ctrl)
+{
+       unsigned long tom, tom_k, base_k;
+       unsigned node_id;
 
+       tom_k = interleave_chip_selects(ctrl);
+       if (!tom_k) {
+               tom_k = order_chip_selects(ctrl);
+       }
        /* Compute the memory base address */
        base_k = 0;
        for(node_id = 0; node_id < ctrl->node_id; node_id++) {
@@ -1287,18 +1376,13 @@ static void order_dimms(const struct mem_controller *ctrl)
        }
        tom_k += base_k;
 #if 0
-       print_debug("tom: ");
-       print_debug_hex32(tom);
-       print_debug(" base_k: ");
+       print_debug("base_k: ");
        print_debug_hex32(base_k);
        print_debug(" tom_k: ");
        print_debug_hex32(tom_k);
        print_debug("\r\n");
 #endif
        route_dram_accesses(ctrl, base_k, tom_k);
-//BY LYH
-        fill_last(ctrl->node_id, tom_k<<2);
-//BY LYH END
        set_top_mem(tom_k);
 }
 
@@ -2063,6 +2147,10 @@ static void set_read_preamble(const struct mem_controller *ctrl, const struct me
                        /* 166Mhz, 7.5ns */
                        rdpreamble = ((7 << 1)+1);
                }
+               else if (divisor == ((5 << 1)+0)) {
+                       /* 200Mhz,  7ns */
+                       rdpreamble = ((7 << 1)+0);
+               }
        }
        else {
                int slots;
@@ -2175,6 +2263,8 @@ static void spd_set_dram_timing(const struct mem_controller *ctrl, const struct
 {
        int dimms;
        int i;
+       int rc;
+       
        init_Tref(ctrl, param);
        for(i = 0; (i < 4) && ctrl->channel0[i]; i++) {
                int rc;
@@ -2247,13 +2337,16 @@ static void sdram_enable(int controllers, const struct mem_controller *ctrl)
                print_debug_hex32(dcl);
                print_debug("\r\n");
 #endif
-#warning "FIXME set the ECC type to perform"
-#warning "FIXME initialize the scrub registers"
-#if 1
                if (dcl & DCL_DimmEccEn) {
+                       uint32_t mnc;
                        print_debug("ECC enabled\r\n");
+                       mnc = pci_read_config32(ctrl[i].f3, MCA_NB_CONFIG);
+                       mnc |= MNC_ECC_EN;
+                       if (dcl & DCL_128BitEn) {
+                               mnc |= MNC_CHIPKILL_EN;
+                       }
+                       pci_write_config32(ctrl[i].f3, MCA_NB_CONFIG, mnc);
                }
-#endif
                dcl |= DCL_DisDqsHys;
                pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
                dcl &= ~DCL_DisDqsHys;
@@ -2280,29 +2373,148 @@ static void sdram_enable(int controllers, const struct mem_controller *ctrl)
                } else {
                        print_debug(" done\r\n");
                }
-#if 0
                if (dcl & DCL_DimmEccEn) {
                        print_debug("Clearing memory: ");
-                       loops = 0;
-                       dcl &= ~DCL_MemClrStatus;
-                       pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
+                       if (!is_cpu_pre_c0()) {
+                               /* Wait until the automatic ram scrubber is finished */
+                               dcl &= ~(DCL_MemClrStatus | DCL_DramEnable);
+                               pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
+                               do {
+                                       dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
+                               } while(((dcl & DCL_MemClrStatus) == 0) || ((dcl & DCL_DramEnable) == 0) );
+                       }
+                       uint32_t base, last_scrub_k, scrub_k;
+                       uint32_t cnt,zstart,zend;
+                       msr_t msr,msr_201;
+
+                       /* First make certain the scrubber is disabled */
+                       pci_write_config32(ctrl[i].f3, SCRUB_CONTROL,
+                               (SCRUB_NONE << 16) | (SCRUB_NONE << 8) | (SCRUB_NONE << 0));
+
+                       /* load the start and end for the memory block to clear */
+                       msr_201 = rdmsr(0x201);
+                       zstart = pci_read_config32(ctrl[0].f1, 0x40 + (i*8));
+                       zend = pci_read_config32(ctrl[0].f1, 0x44 + (i*8));
+                       zstart >>= 16;
+                       zend >>=16;
+#if 1
+                       print_debug("addr ");
+                       print_debug_hex32(zstart);
+                       print_debug("-");
+                       print_debug_hex32(zend);
+                       print_debug("\r\n");
+#endif
                        
-                       do {
-                               dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
-                               loops += 1;
-                               if ((loops & 1023) == 0) {
-                                       print_debug(" ");
-                                       print_debug_hex32(loops);
-                               }
-                       } while(((dcl & DCL_MemClrStatus) == 0) && (loops < TIMEOUT_LOOPS));
-                       if (loops >= TIMEOUT_LOOPS) {
-                               print_debug("failed\r\n");
-                       } else {
-                               print_debug("done\r\n");
+                       /* Disable fixed mtrrs */
+                       msr = rdmsr(MTRRdefType_MSR);
+                       msr.lo &= ~(1<<10);
+                       wrmsr(MTRRdefType_MSR, msr);
+
+                       /* turn on the wrap 32 disable */
+                       msr = rdmsr(0xc0010015);
+                       msr.lo |= (1<<17);
+                       wrmsr(0xc0010015,msr);
+
+                       for(;zstart<zend;zstart+=4) {
+
+                               /* test for the last 64 meg of 4 gig space */
+                               if(zstart == 0x0fc)
+                                       continue;
+                               
+                               /* disable cache */
+                               __asm__ volatile(
+                                       "movl  %%cr0, %0\n\t"
+                                       "orl  $0x40000000, %0\n\t"
+                                       "movl  %0, %%cr0\n\t"
+                                       :"=r" (cnt)
+                                       );
+                               
+                               /* Set the variable mtrrs to write combine */
+                               msr.lo = 1 + ((zstart&0x0ff)<<24);
+                               msr.hi = (zstart&0x0ff00)>>8;
+                               wrmsr(0x200,msr);
+
+                               /* Set the limit to 64 meg of ram */
+                               msr.hi = 0x000000ff;
+                               msr.lo = 0xfc000800;
+                               wrmsr(0x201,msr);
+
+                               /* enable cache */
+                               __asm__ volatile(
+                                       "movl  %%cr0, %0\n\t"
+                                       "andl  $0x9fffffff, %0\n\t"
+                                       "movl  %0, %%cr0\n\t"   
+                                       :"=r" (cnt)     
+                                       );
+                               /* Set fs base address */
+                               msr.lo = (zstart&0xff) << 24;
+                               msr.hi = (zstart&0xff00) >> 8;
+                               wrmsr(0xc0000100,msr);
+
+                               print_debug_char((zstart > 0x0ff)?'+':'-');     
+                                       
+                               /* clear memory 64meg */
+                               __asm__ volatile(
+                                       "1: \n\t"
+                                       "movl %0, %%fs:(%1)\n\t"
+                                       "addl $4,%1\n\t"
+                                       "subl $1,%2\n\t"
+                                       "jnz 1b\n\t"
+                                       :
+                                       : "a" (0), "D" (0), "c" (0x01000000)
+                                       );                      
                        }
-                       pci_write_config32(ctrl[i].f3, SCRUB_ADDR_LOW, 0);
-                       pci_write_config32(ctrl[i].f3, SCRUB_ADDR_HIGH, 0);
+                       
+                       /* disable cache */
+                       __asm__ volatile(
+                               "movl  %%cr0, %0\n\t"
+                               "orl  $0x40000000, %0\n\t"
+                               "movl  %0, %%cr0\n\t"
+                               :"=r" (cnt)     
+                               );
+               
+                       /* restore msr registers */     
+                       msr = rdmsr(MTRRdefType_MSR);
+                       msr.lo |= 0x0400;
+                       wrmsr(MTRRdefType_MSR, msr);
+
+                       /* Restore the variable mtrrs */
+                       msr.lo = 6;
+                       msr.hi = 0;
+                       wrmsr(0x200,msr);
+                       wrmsr(0x201,msr_201);
+
+                       /* Set fs base to 0 */
+                       msr.lo = 0;
+                       msr.hi = 0;
+                       wrmsr(0xc0000100,msr);
+
+                       /* enable cache */
+                       __asm__ volatile(
+                               "movl  %%cr0, %0\n\t"
+                               "andl  $0x9fffffff, %0\n\t"
+                               "movl  %0, %%cr0\n\t"   
+                               :"=r" (cnt)     
+                               );
+                       
+                       /* turn off the wrap 32 disable */
+                       msr = rdmsr(0xc0010015);
+                       msr.lo &= ~(1<<17);
+                       wrmsr(0xc0010015,msr);
+
+                       /* Find the Srub base address for this cpu */
+                       base = pci_read_config32(ctrl[i].f1, 0x40 + (ctrl[i].node_id << 3));
+                       base &= 0xffff0000;
+
+                       /* Set the scrub base address registers */
+                       pci_write_config32(ctrl[i].f3, SCRUB_ADDR_LOW, base << 8);
+                       pci_write_config32(ctrl[i].f3, SCRUB_ADDR_HIGH, base >> 24);
+
+                       /* Enable scrubbing at the lowest possible rate */
+                       pci_write_config32(ctrl[i].f3, SCRUB_CONTROL, 
+                               (SCRUB_84ms << 16) | (SCRUB_84ms << 8) | (SCRUB_84ms << 0));
+
+                       print_debug("done\r\n");
                }
-#endif
        }
 }
index 3b655cbdb5a8f779da65ecaebfdf502411bc536e..5f5e5d9dd82ce8909d3b25b74957913b3c5eed6f 100644 (file)
@@ -38,21 +38,21 @@ struct mem_range *sizeram(void)
                idx++;
        }
        for(rambits = 0, i = 0; i < sizeof(ramregs)/sizeof(ramregs[0]); i++) {
-         unsigned char reg;
-         reg = pci_read_config8(dev, ramregs[i]);
-         /* these are ENDING addresses, not sizes. 
-          * if there is memory in this slot, then reg will be > rambits.
-          * So we just take the max, that gives us total. 
-          * We take the highest one to cover for once and future linuxbios
-          * bugs. We warn about bugs.
-          */
-         if (reg > rambits)
-           rambits = reg;
-         if (reg < rambits)
-           printk_err("ERROR! register 0x%x is not set!\n", 
-                      ramregs[i]);
+               unsigned char reg;
+               reg = pci_read_config8(dev, ramregs[i]);
+               /* these are ENDING addresses, not sizes. 
+                * if there is memory in this slot, then reg will be > rambits.
+                * So we just take the max, that gives us total. 
+                * We take the highest one to cover for once and future linuxbios
+                * bugs. We warn about bugs.
+                */
+               if (reg > rambits)
+                       rambits = reg;
+               if (reg < rambits)
+                       printk_err("ERROR! register 0x%x is not set!\n", 
+                               ramregs[i]);
        }
-
+       
        printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*8*1024);
        mem[0].sizek = rambits*8*1024;
 #if 1
@@ -77,48 +77,46 @@ static void enumerate(struct chip *chip)
  * slower than normal, ethernet drops packets).
  * Apparently these registers govern some sort of bus master behavior.
  */
-static void
-random_fixup() {
-  device_t pcidev = dev_find_slot(0, 0);
+static void random_fixup() {
+       device_t pcidev = dev_find_slot(0, 0);
 
-  printk_spew("VT8601 random fixup ...\n");
-  if (pcidev) {
-    pci_write_config8(pcidev, 0x70, 0xc0);
-    pci_write_config8(pcidev, 0x71, 0x88);
-    pci_write_config8(pcidev, 0x72, 0xec);
-    pci_write_config8(pcidev, 0x73, 0x0c);
-    pci_write_config8(pcidev, 0x74, 0x0e);
-    pci_write_config8(pcidev, 0x75, 0x81);
-    pci_write_config8(pcidev, 0x76, 0x52);
-  }
+       printk_spew("VT8601 random fixup ...\n");
+       if (pcidev) {
+               pci_write_config8(pcidev, 0x70, 0xc0);
+               pci_write_config8(pcidev, 0x71, 0x88);
+               pci_write_config8(pcidev, 0x72, 0xec);
+               pci_write_config8(pcidev, 0x73, 0x0c);
+               pci_write_config8(pcidev, 0x74, 0x0e);
+               pci_write_config8(pcidev, 0x75, 0x81);
+               pci_write_config8(pcidev, 0x76, 0x52);
+       }
 }
 
-static void 
-northbridge_init(struct chip *chip, enum chip_pass pass)
+static void northbridge_init(struct chip *chip, enum chip_pass pass)
 {
 
-  struct northbridge_via_vt8601_config *conf = 
-    (struct northbridge_via_vt8601_config *)chip->chip_info;
-
-  switch (pass) {
-  case CONF_PASS_PRE_PCI:
-    break;
+       struct northbridge_via_vt8601_config *conf = 
+               (struct northbridge_via_vt8601_config *)chip->chip_info;
 
-  case CONF_PASS_POST_PCI:
-    break;
-
-  case CONF_PASS_PRE_BOOT:
-    random_fixup();
-    break;
-
-  default:
-    /* nothing yet */
-    break;
-  }
+       switch (pass) {
+       case CONF_PASS_PRE_PCI:
+               break;
+               
+       case CONF_PASS_POST_PCI:
+               break;
+               
+       case CONF_PASS_PRE_BOOT:
+               random_fixup();
+               break;
+               
+       default:
+               /* nothing yet */
+               break;
+       }
 }
 
 struct chip_control northbridge_via_vt8601_control = {
        .enumerate = enumerate,
-       enable: northbridge_init,
-       .name   = "VIA vt8601 Northbridge",
+       .enable    = northbridge_init,
+       .name      = "VIA vt8601 Northbridge",
 };
index 05e3ce33ed1f805d1807b40c0b41effe5737d666..9aebf1d35cb2f0be371a6450e95851f488edaf9e 100644 (file)
 /* The address arguments to this function are PHYSICAL ADDRESSES */ 
 static void real_mode_switch_call_vga(unsigned long devfn)
 {
-  __asm__ __volatile__
-    (
-     // paranoia -- does ecx get saved? not sure. This is 
-     // the easiest safe thing to do.
-     "pushal\n"
-     /* save the stack */
-     "mov %esp, __stack\n"
-     "jmp 1f\n"
-     "__stack: .long 0\n"
-     "1:\n"
-     /* get devfn into %ecx */
-     "movl    %esp, %ebp\n"
-     "movl    8(%ebp), %ecx\n"
-     /*  This configures CS properly for real mode. */
-     "    ljmp $0x28, $__rms_16bit\n"
-     "__rms_16bit:                 \n"
-     ".code16                      \n" /* 16 bit code from here on... */
-
-     /* Load the segment registers w/ properly configured segment
-      * descriptors.  They will retain these configurations (limits,
-      * writability, etc.) once protected mode is turned off. */
-     "    mov  $0x30, %ax         \n"
-     "    mov  %ax, %ds          \n"
-     "    mov  %ax, %es          \n"
-     "    mov  %ax, %fs          \n"
-     "    mov  %ax, %gs          \n"
-     "    mov  %ax, %ss          \n"
-
-     /* Turn off protection (bit 0 in CR0) */
-     "    movl %cr0, %eax        \n"
-     "    andl $0xFFFFFFFE, %eax  \n"
-     "    movl %eax, %cr0        \n"
-
-     /* Now really going into real mode */
-     "    ljmp $0,  $__rms_real \n"
-     "__rms_real:                  \n"
-
-     // put the stack at the end of page zero. 
-     // that way we can easily share it between real and protected, 
-     // since the 16-bit ESP at segment 0 will work for any case. 
-     /* Setup a stack */
-     "    mov  $0x0, %ax       \n"
-     "    mov  %ax, %ss          \n"
-     "    movl  $0x1000, %eax       \n"
-     "    movl  %eax, %esp          \n"
-     /* debugging for RGM */
-     "    mov $0x11, %al       \n"
-     " outb    %al, $0x80\n"
-
-     /* Dump zeros in the other segregs */
-     "    xor  %ax, %ax          \n"
-     "    mov  %ax, %ds          \n"
-     "    mov  %ax, %es          \n"
-     "    mov  %ax, %fs          \n"
-     "    mov  %ax, %gs          \n"
-     "    mov %cx, %ax \n"
-     " .byte 0x9a, 0x03, 0, 0, 0xc0  \n"
-     " movb $0x55, %al\noutb %al, $0x80\n"
-     /* if we got here, just about done. 
-      * Need to get back to protected mode */
-     "movl     %cr0, %eax\n"
-     //       "andl    $0x7FFAFFD1, %eax\n" /* PG,AM,WP,NE,TS,EM,MP = 0 */
-     //        "orl    $0x60000001, %eax\n" /* CD, NW, PE = 1 */
-     "orl      $0x0000001, %eax\n" /* PE = 1 */
-     "movl     %eax, %cr0\n"
-     /* Now that we are in protected mode jump to a 32 bit code segment. */
-     "data32   ljmp    $0x10, $vgarestart\n"
-     "vgarestart:\n"
-     ".code32\n"
-     "    movw $0x18, %ax          \n"
-     "    mov  %ax, %ds          \n"
-     "    mov  %ax, %es          \n"
-     "    mov  %ax, %fs          \n"
-     "    mov  %ax, %gs          \n"
-     "    mov  %ax, %ss          \n"
-     ".globl vga_exit\n"
-     "vga_exit:\n"
-     "    mov  __stack, %esp\n"
-     "    popal\n"
-     );
+       __asm__ __volatile__
+               (
+                       // paranoia -- does ecx get saved? not sure. This is 
+                       // the easiest safe thing to do.
+                       "pushal\n"
+                       /* save the stack */
+                       "mov %esp, __stack\n"
+                       "jmp 1f\n"
+                       "__stack: .long 0\n"
+                       "1:\n"
+                       /* get devfn into %ecx */
+                       "movl    %esp, %ebp\n"
+                       "movl    8(%ebp), %ecx\n"
+                       /*  This configures CS properly for real mode. */
+                       "    ljmp $0x28, $__rms_16bit\n"
+                       "__rms_16bit:                 \n"
+                       ".code16                      \n" /* 16 bit code from here on... */
+                       
+                       /* Load the segment registers w/ properly configured segment
+                        * descriptors.  They will retain these configurations (limits,
+                        * writability, etc.) once protected mode is turned off. */
+                       "    mov  $0x30, %ax         \n"
+                       "    mov  %ax, %ds          \n"
+                       "    mov  %ax, %es          \n"
+                       "    mov  %ax, %fs          \n"
+                       "    mov  %ax, %gs          \n"
+                       "    mov  %ax, %ss          \n"
+                       
+                       /* Turn off protection (bit 0 in CR0) */
+                       "    movl %cr0, %eax        \n"
+                       "    andl $0xFFFFFFFE, %eax  \n"
+                       "    movl %eax, %cr0        \n"
+                       
+                       /* Now really going into real mode */
+                       "    ljmp $0,  $__rms_real \n"
+                       "__rms_real:                  \n"
+                       
+                       // put the stack at the end of page zero. 
+                       // that way we can easily share it between real and protected, 
+                       // since the 16-bit ESP at segment 0 will work for any case. 
+                       /* Setup a stack */
+                       "    mov  $0x0, %ax       \n"
+                       "    mov  %ax, %ss          \n"
+                       "    movl  $0x1000, %eax       \n"
+                       "    movl  %eax, %esp          \n"
+                       /* debugging for RGM */
+                       "    mov $0x11, %al     \n"
+                       " outb  %al, $0x80\n"
+                       
+                       /* Dump zeros in the other segregs */
+                       "    xor  %ax, %ax          \n"
+                       "    mov  %ax, %ds          \n"
+                       "    mov  %ax, %es          \n"
+                       "    mov  %ax, %fs          \n"
+                       "    mov  %ax, %gs          \n"
+                       "    mov %cx, %ax       \n"
+                       " .byte 0x9a, 0x03, 0, 0, 0xc0  \n"
+                       " movb $0x55, %al\noutb %al, $0x80\n"
+                       /* if we got here, just about done. 
+                        * Need to get back to protected mode */
+                       "movl   %cr0, %eax\n"
+                       //       "andl  $0x7FFAFFD1, %eax\n" /* PG,AM,WP,NE,TS,EM,MP = 0 */
+                       //      "orl    $0x60000001, %eax\n" /* CD, NW, PE = 1 */
+                       "orl    $0x0000001, %eax\n" /* PE = 1 */
+                       "movl   %eax, %cr0\n"
+                       /* Now that we are in protected mode jump to a 32 bit code segment. */
+                       "data32 ljmp    $0x10, $vgarestart\n"
+                       "vgarestart:\n"
+                       ".code32\n"
+                       "    movw $0x18, %ax          \n"
+                       "    mov  %ax, %ds          \n"
+                       "    mov  %ax, %es          \n"
+                       "    mov  %ax, %fs          \n"
+                       "    mov  %ax, %gs          \n"
+                       "    mov  %ax, %ss          \n"
+                       ".globl vga_exit\n"
+                       "vga_exit:\n"
+                       "    mov  __stack, %esp\n"
+                       "    popal\n"
+                       );
 }
 __asm__ (".text\n""real_mode_switch_end:\n");
 extern char real_mode_switch_end[];
@@ -153,53 +153,53 @@ extern char real_mode_switch_end[];
 void
 do_vgabios(void)
 {
-  struct pci_dev *dev;
-  unsigned long busdevfn;
-  unsigned int rom = 0;
-  unsigned char *buf;
-  unsigned int size = 64*1024;
-  int i;
-
-  for (i=0x400; i<0x500; i++) {
-    printk_debug("%02x%c", *(unsigned char *)i, i%16==15 ? '\n' : ' ');
-    *(unsigned char *) i = 0;
-  }
-
-  for (i=0x400; i<0x500; i++) {
-    printk_debug("%02x%c", *(unsigned char *)i, i%16==15 ? '\n' : ' ');
-  }
-
-  dev = pci_find_class(PCI_CLASS_DISPLAY_VGA <<8, NULL);
-
-  if (! dev) {
-    printk_debug("NO VGA FOUND\n");
-    return;
-  }
-  printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor, dev->device);
-
+       struct pci_dev *dev;
+       unsigned long busdevfn;
+       unsigned int rom = 0;
+       unsigned char *buf;
+       unsigned int size = 64*1024;
+       int i;
+       
+       for (i=0x400; i<0x500; i++) {
+               printk_debug("%02x%c", *(unsigned char *)i, i%16==15 ? '\n' : ' ');
+               *(unsigned char *) i = 0;
+       }
+       
+       for (i=0x400; i<0x500; i++) {
+               printk_debug("%02x%c", *(unsigned char *)i, i%16==15 ? '\n' : ' ');
+       }
+       
+       dev = pci_find_class(PCI_CLASS_DISPLAY_VGA <<8, NULL);
+       
+       if (! dev) {
+               printk_debug("NO VGA FOUND\n");
+               return;
+       }
+       printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor, dev->device);
+       
 #ifdef VGABIOS_START
-  // Use VGA BIOS blob at specified address
-  rom = VGABIOS_START;
+       // Use VGA BIOS blob at specified address
+       rom = VGABIOS_START;
 #else
-  pci_read_config32(dev, PCI_ROM_ADDRESS, &rom);
-  // paranoia
-  rom = 0xf0000000;
-  pci_write_config32(dev, PCI_ROM_ADDRESS, rom|1);
-  printk_debug("rom base, size: %x\n", rom);
+       pci_read_config32(dev, PCI_ROM_ADDRESS, &rom);
+       // paranoia
+       rom = 0xf0000000;
+       pci_write_config32(dev, PCI_ROM_ADDRESS, rom|1);
+       printk_debug("rom base, size: %x\n", rom);
 #endif
-  buf = (unsigned char *) rom;
-  if ((buf[0] == 0x55) && (buf[1] = 0xaa)) {
-    memcpy((void *) 0xc0000, buf, size);
-
-    for(i = 0; i < 16; i++)
-      printk_debug("0x%x ", buf[i]);
-    // check signature here later!
-    busdevfn = (dev->bus->secondary << 8) | dev->devfn;
-    real_mode_switch_call_vga(busdevfn);
-  } else 
-    printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]);
+       buf = (unsigned char *) rom;
+       if ((buf[0] == 0x55) && (buf[1] = 0xaa)) {
+               memcpy((void *) 0xc0000, buf, size);
+               
+               for(i = 0; i < 16; i++)
+                       printk_debug("0x%x ", buf[i]);
+               // check signature here later!
+               busdevfn = (dev->bus->secondary << 8) | dev->devfn;
+               real_mode_switch_call_vga(busdevfn);
+       } else 
+               printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]);
 #ifndef VGABIOS_START
-  pci_write_config32(dev, PCI_ROM_ADDRESS, 0);
+       pci_write_config32(dev, PCI_ROM_ADDRESS, 0);
 #endif
 }
 
@@ -209,7 +209,7 @@ do_vgabios(void)
 // to the BIOS. 
 // no longer. Dammit. We have to respond to these.
 struct realidt {
-  unsigned short offset, cs;
+       unsigned short offset, cs;
 }; 
 
 // from a handy writeup that andrey found.
@@ -228,15 +228,15 @@ struct realidt {
 // have to do address fixup in this little stub, and calls are absolute
 // so the handler is relocatable.
 void handler(void) {
-  __asm__ __volatile__ ( 
-                       ".code16\n"
-                       "idthandle:\n"
-                       "       pushal\n"
-                       "       movb $0, %al\n"
-                       "       ljmp $0, $callbiosint16\n"
-                       "end_idthandle:\n"
-                       ".code32\n"
-                       );
+       __asm__ __volatile__ ( 
+               ".code16\n"
+               "idthandle:\n"
+               "       pushal\n"
+               "       movb $0, %al\n"
+               "       ljmp $0, $callbiosint16\n"
+               "end_idthandle:\n"
+               ".code32\n"
+               );
 
 }
 
@@ -247,79 +247,79 @@ void handler(void) {
 // REFERENCE parameters. In this way, we can easily get 
 // returns back to the INTx caller (i.e. vgabios)
 void callbiosint(void) {
-  __asm__ __volatile__ (
-                       ".code16\n"
-                       "callbiosint16:\n"
-                       // clean up the int #. To save space we put it in the lower
-                       // byte. But the top 24 bits are junk. 
-                       "andl $0xff, %eax\n"
-                       // this push does two things:
-                       // - put the INT # on the stack as a parameter
-                       // - provides us with a temp for the %cr0 mods.
-                       "pushl  %eax\n"
-                       "movl    %cr0, %eax\n"
-                       //"andl    $0x7FFAFFD1, %eax\n" /* PG,AM,WP,NE,TS,EM,MP = 0 */
-                       //"orl    $0x60000001, %eax\n" /* CD, NW, PE = 1 */
-                       "orl    $0x00000001, %eax\n" /* PE = 1 */
-                       "movl    %eax, %cr0\n"
-                       /* Now that we are in protected mode jump to a 32 bit code segment. */
-                       "data32  ljmp    $0x10, $biosprotect\n"
-                       "biosprotect:\n"
-                       ".code32\n"
-                       "    movw $0x18, %ax          \n"
-                       "    mov  %ax, %ds          \n"
-                       "    mov  %ax, %es          \n"
-                       "    mov  %ax, %fs          \n"
-                       "    mov  %ax, %gs          \n"
-                       "    mov  %ax, %ss          \n"
-                       "       call    biosint \n"
-                       // back to real mode ...
-                       "    ljmp $0x28, $__rms_16bit\n"
-                       "__rms_16bit:                 \n"
-                       ".code16                      \n" /* 16 bit code from here on... */
-
-                       /* Load the segment registers w/ properly configured segment
-                        * descriptors.  They will retain these configurations (limits,
-                        * writability, etc.) once protected mode is turned off. */
-                       "    mov  $0x30, %ax         \n"
-                       "    mov  %ax, %ds          \n"
-                       "    mov  %ax, %es          \n"
-                       "    mov  %ax, %fs          \n"
-                       "    mov  %ax, %gs          \n"
-                       "    mov  %ax, %ss          \n"
-
-                       /* Turn off protection (bit 0 in CR0) */
-                       "    movl %cr0, %eax        \n"
-                       "    andl $0xFFFFFFFE, %eax  \n"
-                       "    movl %eax, %cr0        \n"
-
-                       /* Now really going into real mode */
-                       "    ljmp $0,  $__rms_real \n"
-                       "__rms_real:                  \n"
-
-                       /* Setup a stack */
-                       "    mov  $0x0, %ax       \n"
-                       "    mov  %ax, %ss          \n"
-                       /* ebugging for RGM */
-                       "    mov $0x11, %al      \n"
-                       " outb  %al, $0x80\n"
-                       "    xor  %ax, %ax          \n"
-                       "    mov  %ax, %ds          \n"
-                       "    mov  %ax, %es          \n"
-                       "    mov  %ax, %fs          \n"
-                       "    mov  %ax, %gs          \n"
-                       // pop the INT # that you pushed earlier
-                       "   popl        %eax\n"
-                       "       popal\n"
-                       "       iret\n"
-                       ".code32\n"
-                       );
+       __asm__ __volatile__ (
+               ".code16\n"
+               "callbiosint16:\n"
+               // clean up the int #. To save space we put it in the lower
+               // byte. But the top 24 bits are junk. 
+               "andl $0xff, %eax\n"
+               // this push does two things:
+               // - put the INT # on the stack as a parameter
+               // - provides us with a temp for the %cr0 mods.
+               "pushl  %eax\n"
+               "movl    %cr0, %eax\n"
+               //"andl    $0x7FFAFFD1, %eax\n" /* PG,AM,WP,NE,TS,EM,MP = 0 */
+               //"orl    $0x60000001, %eax\n" /* CD, NW, PE = 1 */
+               "orl    $0x00000001, %eax\n" /* PE = 1 */
+               "movl    %eax, %cr0\n"
+               /* Now that we are in protected mode jump to a 32 bit code segment. */
+               "data32  ljmp    $0x10, $biosprotect\n"
+               "biosprotect:\n"
+               ".code32\n"
+               "    movw $0x18, %ax          \n"
+               "    mov  %ax, %ds          \n"
+               "    mov  %ax, %es          \n"
+               "    mov  %ax, %fs          \n"
+               "    mov  %ax, %gs          \n"
+               "    mov  %ax, %ss          \n"
+               "       call    biosint \n"
+               // back to real mode ...
+               "    ljmp $0x28, $__rms_16bit\n"
+               "__rms_16bit:                 \n"
+               ".code16                      \n" /* 16 bit code from here on... */
+               
+               /* Load the segment registers w/ properly configured segment
+                * descriptors.  They will retain these configurations (limits,
+                * writability, etc.) once protected mode is turned off. */
+               "    mov  $0x30, %ax         \n"
+               "    mov  %ax, %ds          \n"
+               "    mov  %ax, %es          \n"
+               "    mov  %ax, %fs          \n"
+               "    mov  %ax, %gs          \n"
+               "    mov  %ax, %ss          \n"
+               
+               /* Turn off protection (bit 0 in CR0) */
+               "    movl %cr0, %eax        \n"
+               "    andl $0xFFFFFFFE, %eax  \n"
+               "    movl %eax, %cr0        \n"
+               
+               /* Now really going into real mode */
+               "    ljmp $0,  $__rms_real \n"
+               "__rms_real:                  \n"
+               
+               /* Setup a stack */
+               "    mov  $0x0, %ax       \n"
+               "    mov  %ax, %ss          \n"
+               /* ebugging for RGM */
+               "    mov $0x11, %al      \n"
+               " outb  %al, $0x80\n"
+               "    xor  %ax, %ax          \n"
+               "    mov  %ax, %ds          \n"
+               "    mov  %ax, %es          \n"
+               "    mov  %ax, %fs          \n"
+               "    mov  %ax, %gs          \n"
+               // pop the INT # that you pushed earlier
+               "   popl        %eax\n"
+               "       popal\n"
+               "       iret\n"
+               ".code32\n"
+               );
 }
 
 
 enum {
-  PCIBIOS = 0x1a, 
-  MEMSIZE = 0x12
+       PCIBIOS = 0x1a, 
+       MEMSIZE = 0x12
 };
 int
 pcibios(
@@ -350,116 +350,116 @@ biosint(
        unsigned long cs_ip,
        unsigned short stackflags
        ) {
-  unsigned long ip; 
-  unsigned long cs; 
-  unsigned long flags;
-  int ret = -1;
-
-  ip = cs_ip & 0xffff;
-  cs = cs_ip >> 16;
-  flags = stackflags;
-
-  printk_debug("biosint: # 0x%lx, eax 0x%lx ebx 0x%lx ecx 0x%lx edx 0x%lx\n", 
-              intnumber, eax, ebx, ecx, edx);
-  printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi 0x%lx\n", ebp, esp, edi, esi);
-  printk_debug("biosint: ip 0x%x cs 0x%x flags 0x%x\n", ip, cs, flags);
-  // cases in a good compiler are just as good as your own tables. 
-  switch (intnumber) {
-  case 0 ... 15:
-    // These are not BIOS service, but the CPU-generated exceptions
-    printk_info("biosint: Oops, exception %u\n", intnumber);
-    if (esp < 0x1000) {
-      printk_debug("Stack contents: ");
-      while (esp < 0x1000) {
-       printk_debug("0x%04x ", *(unsigned short *) esp);
-       esp += 2;
-      }
-      printk_debug("\n");
-    }
-    printk_debug("biosint: Bailing out\n");
-    // "longjmp"
-    vga_exit();
-    break;
-
-  case PCIBIOS:
-    ret = pcibios( &edi, &esi, &ebp, &esp, 
-                  &ebx, &edx, &ecx, &eax, &flags);
-    break;
-  case MEMSIZE: 
-    // who cares. 
-    eax = 64 * 1024;
-    ret = 0;
-    break;
-  default:
-    printk_info(__FUNCTION__ ": Unsupport int #0x%x\n", 
-               intnumber);
-    break;
-  }
-  if (ret)
-    flags |= 1; // carry flags
-  else
-    flags &= ~1;
-  stackflags = flags;
-  return ret;
+       unsigned long ip; 
+       unsigned long cs; 
+       unsigned long flags;
+       int ret = -1;
+       
+       ip = cs_ip & 0xffff;
+       cs = cs_ip >> 16;
+       flags = stackflags;
+       
+       printk_debug("biosint: # 0x%lx, eax 0x%lx ebx 0x%lx ecx 0x%lx edx 0x%lx\n", 
+               intnumber, eax, ebx, ecx, edx);
+       printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi 0x%lx\n", ebp, esp, edi, esi);
+       printk_debug("biosint: ip 0x%x cs 0x%x flags 0x%x\n", ip, cs, flags);
+       // cases in a good compiler are just as good as your own tables. 
+       switch (intnumber) {
+       case 0 ... 15:
+               // These are not BIOS service, but the CPU-generated exceptions
+               printk_info("biosint: Oops, exception %u\n", intnumber);
+               if (esp < 0x1000) {
+                       printk_debug("Stack contents: ");
+                       while (esp < 0x1000) {
+                               printk_debug("0x%04x ", *(unsigned short *) esp);
+                               esp += 2;
+                       }
+                       printk_debug("\n");
+               }
+               printk_debug("biosint: Bailing out\n");
+               // "longjmp"
+               vga_exit();
+               break;
+               
+       case PCIBIOS:
+               ret = pcibios( &edi, &esi, &ebp, &esp, 
+                       &ebx, &edx, &ecx, &eax, &flags);
+               break;
+       case MEMSIZE: 
+               // who cares. 
+               eax = 64 * 1024;
+               ret = 0;
+               break;
+       default:
+               printk_info(__FUNCTION__ ": Unsupport int #0x%x\n", 
+                       intnumber);
+               break;
+       }
+       if (ret)
+               flags |= 1; // carry flags
+       else
+               flags &= ~1;
+       stackflags = flags;
+       return ret;
 } 
 
 
-void
-setup_realmode_idt(void) {
-  extern unsigned char idthandle, end_idthandle;
-  int i;
-  struct realidt *idts = (struct realidt *) 0;
-  int codesize = &end_idthandle - &idthandle;
-  unsigned char *intbyte, *codeptr;
-
-  // for each int, we create a customized little handler
-  // that just pushes %ax, puts the int # in %al, 
-  // then calls the common interrupt handler. 
-  // this necessitated because intel didn't know much about 
-  // architecture when they did the 8086 (it shows)
-  // (hmm do they know anymore even now :-)
-  // obviously you can see I don't really care about memory 
-  // efficiency. If I did I would probe back through the stack
-  // and get it that way. But that's really disgusting.
-  for (i = 0; i < 256; i++) {
-    idts[i].cs = 0;
-    codeptr = (char*) 4096 + i * codesize;
-    idts[i].offset = (unsigned) codeptr;
-    memcpy(codeptr, &idthandle, codesize);
-    intbyte = codeptr + 3;
-    *intbyte = i;
-  }
-
-  // fixed entry points
-
-  // VGA BIOSes tend to hardcode f000:f065 as the previous handler of
-  // int10. 
-  // calling convention here is the same as INTs, we can reuse
-  // the int entry code.
-  codeptr = (char*) 0xff065;
-  memcpy(codeptr, &idthandle, codesize);
-  intbyte = codeptr + 3;
-  *intbyte = 0x42; /* int42 is the relocated int10 */
+void setup_realmode_idt(void) 
+{
+       extern unsigned char idthandle, end_idthandle;
+       int i;
+       struct realidt *idts = (struct realidt *) 0;
+       int codesize = &end_idthandle - &idthandle;
+       unsigned char *intbyte, *codeptr;
+       
+       // for each int, we create a customized little handler
+       // that just pushes %ax, puts the int # in %al, 
+       // then calls the common interrupt handler. 
+       // this necessitated because intel didn't know much about 
+       // architecture when they did the 8086 (it shows)
+       // (hmm do they know anymore even now :-)
+       // obviously you can see I don't really care about memory 
+       // efficiency. If I did I would probe back through the stack
+       // and get it that way. But that's really disgusting.
+       for (i = 0; i < 256; i++) {
+               idts[i].cs = 0;
+               codeptr = (char*) 4096 + i * codesize;
+               idts[i].offset = (unsigned) codeptr;
+               memcpy(codeptr, &idthandle, codesize);
+               intbyte = codeptr + 3;
+               *intbyte = i;
+       }
+       
+       // fixed entry points
+       
+       // VGA BIOSes tend to hardcode f000:f065 as the previous handler of
+       // int10. 
+       // calling convention here is the same as INTs, we can reuse
+       // the int entry code.
+       codeptr = (char*) 0xff065;
+       memcpy(codeptr, &idthandle, codesize);
+       intbyte = codeptr + 3;
+       *intbyte = 0x42; /* int42 is the relocated int10 */
 }
 
 
 
 enum {
-  CHECK = 0xb001,
-  FINDDEV = 0xb102,
-  READCONFBYTE = 0xb108,
-  READCONFWORD = 0xb109,
-  READCONFDWORD = 0xb10a,
-  WRITECONFBYTE = 0xb10b,
-  WRITECONFWORD = 0xb10c,
-  WRITECONFDWORD = 0xb10d
+       CHECK = 0xb001,
+       FINDDEV = 0xb102,
+       READCONFBYTE = 0xb108,
+       READCONFWORD = 0xb109,
+       READCONFDWORD = 0xb10a,
+       WRITECONFBYTE = 0xb10b,
+       WRITECONFWORD = 0xb10c,
+       WRITECONFDWORD = 0xb10d
 };
 
 // errors go in AH. Just set these up so that word assigns
 // will work. KISS. 
 enum {
-  PCIBIOS_NODEV = 0x8600,
-  PCIBIOS_BADREG = 0x8700
+       PCIBIOS_NODEV = 0x8600,
+       PCIBIOS_BADREG = 0x8700
 };
 
 int
@@ -474,145 +474,144 @@ pcibios(
        unsigned long *peax, 
        unsigned long *pflags
        ) {
-  unsigned long edi = *pedi;
-  unsigned long esi = *pesi;
-  unsigned long ebp = *pebp;
-  unsigned long esp = *pesp;
-  unsigned long ebx = *pebx;
-  unsigned long edx = *pedx;
-  unsigned long ecx = *pecx;
-  unsigned long eax = *peax;
-  unsigned long flags = *pflags;
-  unsigned short func = (unsigned short) eax;
-  int retval = 0;
-  unsigned short devid, vendorid, devfn;
-  short devindex; /* Use short to get rid of gabage in upper half of 32-bit register */
-  unsigned char bus;
-  struct pci_dev *dev;
-
-  switch(func) {
-  case  CHECK:
-    *pedx = 0x4350;
-    *pecx = 0x2049;
-    retval = 0;
-    break;
-  case FINDDEV:
-    {
-      devid = *pecx;
-      vendorid = *pedx;
-      devindex = *pesi;
-      dev = 0;
-      while ((dev = pci_find_device(vendorid, devid, dev))) {
-       if (devindex <= 0)
-         break;
-       devindex--;
-      }
-      if (dev) {
-       unsigned short busdevfn;
-       *peax = 0;
-       // busnum is an unsigned char;
-       // devfn is an int, so we mask it off. 
-       busdevfn = (dev->bus->secondary << 8)
-         | (dev->devfn & 0xff);
-       printk_debug("0x%x: return 0x%x\n", func, busdevfn);
-       *pebx = busdevfn;
-       retval = 0;
-      } else {
-       *peax = PCIBIOS_NODEV;
-       retval = -1;
-      }
-    }
-    break;
-  case READCONFDWORD:
-  case READCONFWORD:
-  case READCONFBYTE:
-  case WRITECONFDWORD:
-  case WRITECONFWORD:
-  case WRITECONFBYTE:
-    {
-      unsigned long dword;
-      unsigned short word;
-      unsigned char byte;
-      unsigned char reg;
-               
-      devfn = *pebx & 0xff;
-      bus = *pebx >> 8;
-      reg = *pedi;
-      dev = pci_find_slot(bus, devfn);
-      if (! dev) {
-       printk_debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
-       // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
-       *peax = PCIBIOS_BADREG;
-       retval = -1;
-      }
-      switch(func) {
-      case READCONFBYTE:
-       byte = pci_read_config8(dev, reg);
-       *pecx = byte;
-       break;
-      case READCONFWORD:
-       word = pci_read_config16(dev, reg);
-       *pecx = word;
-       break;
-      case READCONFDWORD:
-       dword = pci_read_config32(dev, reg);
-       *pecx = dword;
+       unsigned long edi = *pedi;
+       unsigned long esi = *pesi;
+       unsigned long ebp = *pebp;
+       unsigned long esp = *pesp;
+       unsigned long ebx = *pebx;
+       unsigned long edx = *pedx;
+       unsigned long ecx = *pecx;
+       unsigned long eax = *peax;
+       unsigned long flags = *pflags;
+       unsigned short func = (unsigned short) eax;
+       int retval = 0;
+       unsigned short devid, vendorid, devfn;
+       short devindex; /* Use short to get rid of gabage in upper half of 32-bit register */
+       unsigned char bus;
+       struct pci_dev *dev;
+       
+       switch(func) {
+       case  CHECK:
+               *pedx = 0x4350;
+               *pecx = 0x2049;
+               retval = 0;
+               break;
+       case FINDDEV:
+       {
+               devid = *pecx;
+               vendorid = *pedx;
+               devindex = *pesi;
+               dev = 0;
+               while ((dev = pci_find_device(vendorid, devid, dev))) {
+                       if (devindex <= 0)
+                               break;
+                       devindex--;
+               }
+               if (dev) {
+                       unsigned short busdevfn;
+                       *peax = 0;
+                       // busnum is an unsigned char;
+                       // devfn is an int, so we mask it off. 
+                       busdevfn = (dev->bus->secondary << 8)
+                               | (dev->devfn & 0xff);
+                       printk_debug("0x%x: return 0x%x\n", func, busdevfn);
+                       *pebx = busdevfn;
+                       retval = 0;
+               } else {
+                       *peax = PCIBIOS_NODEV;
+                       retval = -1;
+               }
+       }
        break;
-      case WRITECONFBYTE:
-       byte = *pecx;
-       write_config8(dev, reg, byte);
-       break;
-      case WRITECONFWORD:
-       word = *pecx;
-       write_config16(dev, reg, word);
-       break;
-      case WRITECONFDWORD:
-       word = *pecx;
-       write_config32(dev, reg, dword);
+       case READCONFDWORD:
+       case READCONFWORD:
+       case READCONFBYTE:
+       case WRITECONFDWORD:
+       case WRITECONFWORD:
+       case WRITECONFBYTE:
+       {
+               unsigned long dword;
+               unsigned short word;
+               unsigned char byte;
+               unsigned char reg;
+               
+               devfn = *pebx & 0xff;
+               bus = *pebx >> 8;
+               reg = *pedi;
+               dev = pci_find_slot(bus, devfn);
+               if (! dev) {
+                       printk_debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
+                       // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
+                       *peax = PCIBIOS_BADREG;
+                       retval = -1;
+               }
+               switch(func) {
+               case READCONFBYTE:
+                       byte = pci_read_config8(dev, reg);
+                       *pecx = byte;
+                       break;
+               case READCONFWORD:
+                       word = pci_read_config16(dev, reg);
+                       *pecx = word;
+                       break;
+               case READCONFDWORD:
+                       dword = pci_read_config32(dev, reg);
+                       *pecx = dword;
+                       break;
+               case WRITECONFBYTE:
+                       byte = *pecx;
+                       write_config8(dev, reg, byte);
+                       break;
+               case WRITECONFWORD:
+                       word = *pecx;
+                       write_config16(dev, reg, word);
+                       break;
+               case WRITECONFDWORD:
+                       word = *pecx;
+                       write_config32(dev, reg, dword);
+                       break;
+               }
+               
+               if (retval) 
+                       retval = PCIBIOS_BADREG;
+               printk_debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%lx\n", func, bus, devfn, reg, *pecx);
+               *peax = 0;
+               retval = 0;
+       }
        break;
-      }
-                       
-      if (retval) 
-       retval = PCIBIOS_BADREG;
-      printk_debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%lx\n", func, bus, devfn, reg, *pecx);
-      *peax = 0;
-      retval = 0;
-    }
-    break;
-  default:
-    printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n",  func);
-    break;
-  }
-
-  return retval;
+       default:
+               printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n",  func);
+               break;
+       }
+       
+       return retval;
 } 
 
-static void 
-vga_init(struct chip *chip, enum chip_pass pass)
+static void vga_init(struct chip *chip, enum chip_pass pass)
 {
 
-  struct pc80_vgabios_config *conf = 
-    (struct pc80_vgabios_config *)chip->chip_info;
-
-  switch (pass) {
-  case CONF_PASS_PRE_BOOT:
-
-    break;
-
-  default:
-    /* nothing yet */
-    break;
-  }
+       struct pc80_vgabios_config *conf = 
+               (struct pc80_vgabios_config *)chip->chip_info;
+       
+       switch (pass) {
+       case CONF_PASS_PRE_BOOT:
+               
+               break;
+               
+       default:
+               /* nothing yet */
+               break;
+       }
 }
 
 static void enumerate(struct chip *chip)
 {
-  /* don't really need to do anything */
+       /* don't really need to do anything */
 
 }
 
 struct chip_control southbridge_via_vt8231_control = {
-  .enumerate = enumerate,
-  enable: vga_init,
-  name:   "Legacy VGA bios"
+       .enumerate = enumerate,
+       .enable    = vga_init,
+       .name      = "Legacy VGA bios"
 };
index 02124b3df365fb7116f16e1ee3c6ed06366f4750..d43788cd667d5d6bbfc507cd75847433d73dea51 100644 (file)
@@ -4,7 +4,7 @@
 extern struct chip_control pc80_vgabios_control;
 
 struct pc80_vgabios_config {
-  int nothing;
+       int nothing;
 };
 
 #endif /* _PC80_VGABIOS */
index f8f38a9964a6c6554820366c1c2eb1e6ee8982ab..904b0995b589238890fbd7d27637a8596847b170 100644 (file)
@@ -1,5 +1,9 @@
+config amd8111.h
+driver amd8111.o
 driver amd8111_usb.o
 driver amd8111_lpc.o
 driver amd8111_ide.o
 driver amd8111_acpi.o
 driver amd8111_usb2.o
+#driver amd8111_ac97.o
+#driver amd8111_nic.o
diff --git a/src/southbridge/amd/amd8111/amd8111.c b/src/southbridge/amd/amd8111/amd8111.c
new file mode 100644 (file)
index 0000000..8dde5f1
--- /dev/null
@@ -0,0 +1,56 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/chip.h>
+#include "amd8111.h"
+
+void amd8111_enable(device_t dev)
+{
+       device_t lpc_dev;
+       device_t bus_dev;
+       unsigned index;
+       uint16_t reg_old, reg;
+
+       /* See if we are on the behind the amd8111 pci bridge */
+       bus_dev = dev->bus->dev;
+       if ((bus_dev->vendor == PCI_VENDOR_ID_AMD) && 
+               (bus_dev->device == PCI_DEVICE_ID_AMD_8111_PCI)) {
+               unsigned devfn;
+               devfn = bus_dev->path.u.pci.devfn + (1 << 3);
+               lpc_dev = dev_find_slot(bus_dev->bus->secondary, devfn);
+               index = ((dev->path.u.pci.devfn & ~7) >> 3) + 8;
+       } else {
+               unsigned devfn;
+               devfn = (dev->path.u.pci.devfn) & ~7;
+               lpc_dev = dev_find_slot(dev->bus->secondary, devfn);
+               index = dev->path.u.pci.devfn & 7;
+       }
+       if ((!lpc_dev) || (index >= 16) ||
+               (lpc_dev->vendor != PCI_VENDOR_ID_AMD) ||
+               (lpc_dev->device != PCI_DEVICE_ID_AMD_8111_ISA)) {
+               return;
+       }
+
+       reg = reg_old = pci_read_config16(lpc_dev, 0x48);
+       reg &= ~(1 << index);
+       if (dev->enable) {
+               reg |= (1 << index);
+       }
+       if (reg != reg_old) {
+#if 1
+               printk_warning("amd8111_enable dev: %s", dev_path(dev));
+               printk_warning(" lpc_dev: %s index: %d reg: %04x -> %04x ", 
+                       dev_path(lpc_dev), index, reg_old, reg);
+#endif
+               pci_write_config16(lpc_dev, 0x48, reg);
+#if 1
+               printk_warning("done\n");
+#endif
+       }
+}
+
+struct chip_control southbridge_amd_amd8111_control = {
+       .name       = "AMD 8111",
+       .enable_dev = amd8111_enable,
+};
diff --git a/src/southbridge/amd/amd8111/amd8111.h b/src/southbridge/amd/amd8111/amd8111.h
new file mode 100644 (file)
index 0000000..10e1529
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef AMD8111_H
+#define AMD8111_H
+
+struct southbridge_amd_amd8111_config 
+{
+};
+struct chip_control;
+extern struct chip_control southbridge_amd_amd8111_control;
+
+void amd8111_enable(device_t dev);
+
+#endif /* AMD8111_H */
diff --git a/src/southbridge/amd/amd8111/amd8111_ac97.c b/src/southbridge/amd/amd8111/amd8111_ac97.c
new file mode 100644 (file)
index 0000000..63a0e12
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * (C) 2003 Linux Networx
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "amd8111.h"
+
+
+static struct device_operations ac97audio_ops  = {
+       .read_resources   = pci_dev_read_resources,
+       .set_resources    = pci_dev_set_resources,
+       .enable_resources = pci_dev_enable_resources,
+       .enable           = amd8111_enable,
+       .init             = 0,
+       .scan_bus         = 0,
+};
+
+static struct pci_driver ac97audio_driver __pci_driver = {
+       .ops    = &ac97audio_ops,
+       .vendor = PCI_VENDOR_ID_AMD,
+       .device = 0x746D,
+};
+
+
+static struct device_operations ac97modem_ops  = {
+       .read_resources   = pci_dev_read_resources,
+       .set_resources    = pci_dev_set_resources,
+       .enable_resources = pci_dev_enable_resources,
+       .enable           = amd8111_enable,
+       .init             = 0,
+       .scan_bus         = 0,
+};
+
+static struct pci_driver ac97modem_driver __pci_driver = {
+       .ops    = &ac97modem_ops,
+       .vendor = PCI_VENDOR_ID_AMD,
+       .device = 0x746E,
+};
index 5fa6fdce298ee36669750a09df0b60be2e4d25cf..3a5a594f57694c3666d0774da642db51922177dd 100644 (file)
@@ -3,11 +3,23 @@
 #include <device/pci.h>
 #include <device/pci_ids.h>
 #include <device/pci_ops.h>
+#include <pc80/mc146818rtc.h>
+#include "amd8111.h"
+
+#define PREVIOUS_POWER_STATE 0x43
+#define MAINBOARD_POWER_OFF 0
+#define MAINBOARD_POWER_ON 1
+
+#ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL
+#define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
+#endif
+
 
 static void acpi_init(struct device *dev)
 {
        uint8_t byte;
        uint16_t word;
+       int on;
 
 #if 0
        printk_debug("ACPI: disabling NMI watchdog.. ");
@@ -35,6 +47,15 @@ static void acpi_init(struct device *dev)
        pci_write_config_dword(dev, 0x60, 0x06800000);
        printk_debug("done.\n");
 #endif
+       on = MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
+       get_option(&on, "power_on_after_fail");
+       byte = pci_read_config8(dev, PREVIOUS_POWER_STATE);
+       byte &= ~0x40;
+       if (!on) {
+               byte |= 0x40;
+       }
+       pci_write_config8(dev, PREVIOUS_POWER_STATE, byte);
+       printk_info("set power %s after power fail\n", on?"on":"off");
 
 }
 
@@ -42,8 +63,9 @@ static struct device_operations acpi_ops  = {
        .read_resources   = pci_dev_read_resources,
        .set_resources    = pci_dev_set_resources,
        .enable_resources = pci_dev_enable_resources,
-       .init = acpi_init,
-       .scan_bus = 0,
+       .init             = acpi_init,
+       .scan_bus         = 0,
+       .enable           = amd8111_enable,
 };
 
 static struct pci_driver acpi_driver __pci_driver = {
index e0aaa05ff4aa80451e3a71435a59e14006b31302..b9f142dc8e796f0ff487ab3ce02f0135878e092d 100644 (file)
@@ -21,6 +21,8 @@ static void enable_smbus(void)
        pci_write_config32(dev, 0x58, SMBUS_IO_BASE | 1);
        enable = pci_read_config8(dev, 0x41);
        pci_write_config8(dev, 0x41, enable | (1 << 7));
+       /* clear any lingering errors, so the transaction will run */
+       outw(inw(SMBUS_IO_BASE + SMBGSTATUS), SMBUS_IO_BASE + SMBGSTATUS);
 }
 
 
@@ -40,8 +42,12 @@ static int smbus_wait_until_ready(void)
                if ((val & 0x800) == 0) {
                        break;
                }
+               if(loops == (SMBUS_TIMEOUT / 2)) {
+                       outw(inw(SMBUS_IO_BASE + SMBGSTATUS), 
+                               SMBUS_IO_BASE + SMBGSTATUS);
+               }
        } while(--loops);
-       return loops?0:-1;
+       return loops?0:-2;
 }
 
 static int smbus_wait_until_done(void)
@@ -57,7 +63,7 @@ static int smbus_wait_until_done(void)
                        break;
                }
        } while(--loops);
-       return loops?0:-1;
+       return loops?0:-3;
 }
 
 static int smbus_read_byte(unsigned device, unsigned address)
@@ -67,7 +73,7 @@ static int smbus_read_byte(unsigned device, unsigned address)
        unsigned char byte;
 
        if (smbus_wait_until_ready() < 0) {
-               return -1;
+               return -2;
        }
        
        /* setup transaction */
@@ -93,7 +99,7 @@ static int smbus_read_byte(unsigned device, unsigned address)
 
        /* poll for transaction completion */
        if (smbus_wait_until_done() < 0) {
-               return -1;
+               return -3;
        }
 
        global_status_register = inw(SMBUS_IO_BASE + SMBGSTATUS);
index 11f795b0bb54010f02fb726e5be58fae873e1edd..4502bb3c45c7108e4af77e7a592ae482cbac1c3b 100644 (file)
@@ -3,6 +3,7 @@
 #include <device/pci.h>
 #include <device/pci_ids.h>
 #include <device/pci_ops.h>
+#include "amd8111.h"
 
 static void ide_init(struct device *dev)
 {
index b0c1672f5db76f2b3d9a9fc3069ff987632b964e..437ed2e877ce34ddc579b15420abca4650744b92 100644 (file)
@@ -6,6 +6,8 @@
 #include <device/pci.h>
 #include <device/pci_ids.h>
 #include <device/pci_ops.h>
+#include <device/chip.h>
+#include "amd8111.h"
 
 
 struct ioapicreg {
@@ -87,7 +89,6 @@ static void setup_ioapic(void)
 static void lpc_init(struct device *dev)
 {
        uint8_t byte;
-       uint16_t word;
        int pwr_on=-1;
 
        printk_debug("lpc_init\n");
@@ -100,14 +101,7 @@ static void lpc_init(struct device *dev)
 
        /* posted memory write enable */
        byte = pci_read_config8(dev, 0x46);
-       pci_write_config8(dev, 0x46, byte | (1<<0));
-
-//BY LYH
-        /* Disable AC97 and Ethernet */
-        word = pci_read_config16(dev, 0x48);
-        pci_write_config16(dev, 0x48, word & ~((1<<5)|(1<<6)|(1<<9)));
-//BY LYH END
+       pci_write_config8(dev, 0x46, byte | (1<<0)); 
 
        /* power after power fail */
        byte = pci_read_config8(dev, 0x43);
@@ -118,6 +112,10 @@ static void lpc_init(struct device *dev)
        }
        pci_write_config8(dev, 0x43, byte);
 
+       /* Enable Port 92 fast reset */
+       byte = pci_read_config8(dev, 0x41);
+       byte |= (1 << 5);
+       pci_write_config8(dev, 0x41, byte);
 
 }
 
@@ -159,6 +157,7 @@ static struct device_operations lpc_ops  = {
        .enable_resources = pci_dev_enable_resources,
        .init             = lpc_init,
        .scan_bus         = walk_static_devices,
+       .enable           = amd8111_enable,
 };
 
 static struct pci_driver lpc_driver __pci_driver = {
@@ -166,3 +165,4 @@ static struct pci_driver lpc_driver __pci_driver = {
        .vendor = PCI_VENDOR_ID_AMD,
        .device = PCI_DEVICE_ID_AMD_8111_ISA,
 };
+
diff --git a/src/southbridge/amd/amd8111/amd8111_nic.c b/src/southbridge/amd/amd8111/amd8111_nic.c
new file mode 100644 (file)
index 0000000..b379208
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * (C) 2003 Linux Networx
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "amd8111.h"
+
+
+static struct device_operations nic_ops  = {
+       .read_resources   = pci_dev_read_resources,
+       .set_resources    = pci_dev_set_resources,
+       .enable_resources = pci_dev_enable_resources,
+       .enable           = amd8111_enable,
+       .init             = 0,
+       .scan_bus         = 0,
+};
+
+static struct pci_driver nic_driver __pci_driver = {
+       .ops    = &nic_ops,
+       .vendor = PCI_VENDOR_ID_AMD,
+       .device = 0x7462,
+};
index cfef06dee2262666941574238ca13cfae8b178ed..46cfabbcda2764245dac4893d98afe63f9ab9263 100644 (file)
@@ -3,6 +3,7 @@
 #include <device/pci.h>
 #include <device/pci_ids.h>
 #include <device/pci_ops.h>
+#include "amd8111.h"
 
 static void usb_init(struct device *dev)
 {
@@ -25,6 +26,7 @@ static struct device_operations usb_ops  = {
        .enable_resources = pci_dev_enable_resources,
        .init             = usb_init,
        .scan_bus         = 0,
+       .enable           = amd8111_enable,
 };
 
 static struct pci_driver usb_driver __pci_driver = {
index 924e0e61092c32de248a04cd5bfe9601ad2bed7e..15ed69b0f10708357bb94b00437eceee8bb8ccaf 100644 (file)
@@ -7,6 +7,7 @@
 #include <device/pci.h>
 #include <device/pci_ids.h>
 #include <device/pci_ops.h>
+#include "amd8111.h"
 
 static void usb2_init(struct device *dev)
 {
@@ -23,17 +24,17 @@ static void usb2_init(struct device *dev)
 
 }
 
-static struct device_operations usb_ops  = {
+static struct device_operations usb2_ops  = {
        .read_resources   = pci_dev_read_resources,
        .set_resources    = pci_dev_set_resources,
        .enable_resources = pci_dev_enable_resources,
        .init             = usb2_init,
        .scan_bus         = 0,
+       .enable           = amd8111_enable,
 };
 
 static struct pci_driver usb2_driver __pci_driver = {
-       .ops    = &usb_ops,
+       .ops    = &usb2_ops,
        .vendor = PCI_VENDOR_ID_AMD,
        .device = PCI_DEVICE_ID_AMD_8111_USB2,
 };
-
index dccf962fbd2588e0faea5ecc63cb133ea654e596..9d28de4f32e66633545a5f45532ff4171b93b745 100644 (file)
@@ -29,6 +29,17 @@ static void pcix_init(device_t dev)
        word = pci_read_config16(dev, 0xe8);
         word = 0x0404;
         pci_write_config16(dev, 0xe8, word);
+
+       /* Set discard unrequested prefetch data */
+       word = pci_read_config16(dev, 0x4c);
+        word |= 1;
+        pci_write_config16(dev, 0x4c, word);
+       
+       /* Set split transaction limits */
+       word = pci_read_config16(dev, 0xa8);
+        pci_write_config16(dev, 0xaa, word);
+       word = pci_read_config16(dev, 0xac);
+        pci_write_config16(dev, 0xae, word);
        
        return;
 }
@@ -58,14 +69,6 @@ static void ioapic_enable(device_t dev)
                value &= ~((1 << 1) | (1 << 0));
        }
        pci_write_config32(dev, 0x44, value);
-
-//BY LYH
-        value = pci_read_config32(dev, 0x4);
-        value |= 6;
-        pci_write_config32(dev, 0x4, value);
-//BY LYH END
-
 }
 
 static struct device_operations ioapic_ops = {
index 0ae3b98c6317831e16247db9a413ccb70f16d3c9..fe3d33267585b3b1968ff6abbb3a5beeeb7db9ab 100644 (file)
@@ -9,13 +9,13 @@ struct southbridge_via_vt8231_config {
        /* I am putting in IDE as an example but obviously this needs
         * to be more complete!
         */
-  int enable_ide;
-  /* enables of functions of devices */
-  int enable_usb;
-  int enable_native_ide;
-  int enable_com_ports;
-  int enable_keyboard;
-  int enable_nvram;
+       int enable_ide;
+       /* enables of functions of devices */
+       int enable_usb;
+       int enable_native_ide;
+       int enable_com_ports;
+       int enable_keyboard;
+       int enable_nvram;
 };
 
 #endif /* _SOUTHBRIDGE_VIA_VT8231 */
index 470ab5acf1e8e9c11098d5ec63a24d101cfff63d..ea1f488f3e6bea03eb374d18c04926a7927ee8b7 100644 (file)
 
 void pc_keyboard_init(void);
 
-void
-hard_reset() {
-               printk_err("NO HARD RESET ON VT8231! FIX ME!\n");
+void hard_reset(void) 
+{
+       printk_err("NO HARD RESET ON VT8231! FIX ME!\n");
 }
+
 static void usb_on(int enable)
 {
-  
-  unsigned char regval;
-
-  /* Base 8231 controller */
-  device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, \
-                                 PCI_DEVICE_ID_VIA_8231, 0);
-  /* USB controller 1 */
-  device_t dev2 = dev_find_device(PCI_VENDOR_ID_VIA, \
-                                 PCI_DEVICE_ID_VIA_82C586_2, 0);
-  /* USB controller 2 */
-  device_t dev3 = dev_find_device(PCI_VENDOR_ID_VIA, \
-                                 PCI_DEVICE_ID_VIA_82C586_2, \
-                                 dev2);
-
-  /* enable USB1 */
-  if(dev2) {
-    if (enable) {
-      pci_write_config8(dev2, 0x3c, 0x05);
-      pci_write_config8(dev2, 0x04, 0x07);
-    } else {
-      pci_write_config8(dev2, 0x3c, 0x00);
-      pci_write_config8(dev2, 0x04, 0x00);
-    }
-  }
-
-  if(dev0) {
-    regval = pci_read_config8(dev0, 0x50);
-    if (enable) 
-      regval &= ~(0x10);    
-    else
-      regval |= 0x10;                
-    pci_write_config8(dev0, 0x50, regval);
-  }
-
-  /* enable USB2 */
-  if(dev3) {
-    if (enable) {
-      pci_write_config8(dev3, 0x3c, 0x05);
-      pci_write_config8(dev3, 0x04, 0x07);
-    } else {
-      pci_write_config8(dev3, 0x3c, 0x00);
-      pci_write_config8(dev3, 0x04, 0x00);
-    }
-  }
-
-  if(dev0) {
-    regval = pci_read_config8(dev0, 0x50);
-    if (enable) 
-      regval &= ~(0x20);    
-    else
-      regval |= 0x20;    
-    pci_write_config8(dev0, 0x50, regval);
-  }
-
+       unsigned char regval;
+
+       /* Base 8231 controller */
+       device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
+       /* USB controller 1 */
+       device_t dev2 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, 0);
+       /* USB controller 2 */
+       device_t dev3 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, dev2);
+       
+       /* enable USB1 */
+       if(dev2) {
+               if (enable) {
+                       pci_write_config8(dev2, 0x3c, 0x05);
+                       pci_write_config8(dev2, 0x04, 0x07);
+               } else {
+                       pci_write_config8(dev2, 0x3c, 0x00);
+                       pci_write_config8(dev2, 0x04, 0x00);
+               }
+       }
+       
+       if(dev0) {
+               regval = pci_read_config8(dev0, 0x50);
+               if (enable) 
+                       regval &= ~(0x10);    
+               else
+                       regval |= 0x10;               
+               pci_write_config8(dev0, 0x50, regval);
+       }
+       
+       /* enable USB2 */
+       if(dev3) {
+               if (enable) {
+                       pci_write_config8(dev3, 0x3c, 0x05);
+                       pci_write_config8(dev3, 0x04, 0x07);
+               } else {
+                       pci_write_config8(dev3, 0x3c, 0x00);
+                       pci_write_config8(dev3, 0x04, 0x00);
+               }
+       }
+       
+       if(dev0) {
+               regval = pci_read_config8(dev0, 0x50);
+               if (enable) 
+                       regval &= ~(0x20);    
+               else
+                       regval |= 0x20;    
+               pci_write_config8(dev0, 0x50, regval);
+       }
 }
 
-static void keyboard_on()
+static void keyboard_on(void)
 {
-  unsigned char regval;
-
-  /* Base 8231 controller */
-  device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, \
-                                 PCI_DEVICE_ID_VIA_8231, 0);
-
-  /* kevinh/Ispiri - update entire function to use 
-     new pci_write_config8 */
-
-  if (dev0) {
-    regval = pci_read_config8(dev0, 0x51);
-    regval |= 0x0f; 
-    pci_write_config8(dev0, 0x51, regval);
-  }
-  pc_keyboard_init();
+       unsigned char regval;
+       
+       /* Base 8231 controller */
+       device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
+       
+       /* kevinh/Ispiri - update entire function to use 
+          new pci_write_config8 */
 
+       if (dev0) {
+               regval = pci_read_config8(dev0, 0x51);
+               regval |= 0x0f; 
+               pci_write_config8(dev0, 0x51, regval);
+       }
+       pc_keyboard_init();
 }
 
-static void nvram_on()
+static void nvram_on(void)
 {
-  /*
-   * the VIA 8231 South has a very different nvram setup than the 
-   * piix4e ...
-   * turn on ProMedia nvram.
-   * TO DO: use the PciWriteByte function here.
-   */
-
-  /*
-   * kevinh/Ispiri - I don't think this is the correct address/value
-   * intel_conf_writeb(0x80008841, 0xFF);
-   */
+       /*
+        * the VIA 8231 South has a very different nvram setup than the 
+        * piix4e ...
+        * turn on ProMedia nvram.
+        * TO DO: use the PciWriteByte function here.
+        */
+       
+       /*
+        * kevinh/Ispiri - I don't think this is the correct address/value
+        * intel_conf_writeb(0x80008841, 0xFF);
+        */
 }
 
 
@@ -115,22 +108,22 @@ static void nvram_on()
  */
 static void ethernet_fixup()
 {
-  device_t     edev;
-  uint8_t              byte;
-
-  printk_info("Ethernet fixup\n");
-
-  edev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_7, 0);
-  if (edev) {
-    printk_debug("Configuring VIA LAN\n");
-
-    /* We don't need stepping - though the device supports it */
-    byte = pci_read_config8(edev, PCI_COMMAND);
-    byte &= ~PCI_COMMAND_WAIT;
-    pci_write_config8(edev, PCI_COMMAND, byte);
-  } else {
-    printk_debug("VIA LAN not found\n");
-  }
+       device_t        edev;
+       uint8_t         byte;
+
+       printk_info("Ethernet fixup\n");
+
+       edev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_7, 0);
+       if (edev) {
+               printk_debug("Configuring VIA LAN\n");
+               
+               /* We don't need stepping - though the device supports it */
+               byte = pci_read_config8(edev, PCI_COMMAND);
+               byte &= ~PCI_COMMAND_WAIT;
+               pci_write_config8(edev, PCI_COMMAND, byte);
+       } else {
+               printk_debug("VIA LAN not found\n");
+       }
 }
 
 
@@ -145,13 +138,14 @@ static void ethernet_fixup()
  * (e.g. device_t). This needs to get fixed. We need low-level pci scans
  * in the C code. 
  */
-static void vt8231_pci_enable(struct southbridge_via_vt8231_config *conf) {
-  /*
-       unsigned long busdevfn = 0x8000;
-       if (conf->enable_ide) {
-               printk_debug("%s: enabling IDE function\n", __FUNCTION__);
-       }
-  */
+static void vt8231_pci_enable(struct southbridge_via_vt8231_config *conf) 
+{
+       /*
+         unsigned long busdevfn = 0x8000;
+         if (conf->enable_ide) {
+         printk_debug("%s: enabling IDE function\n", __FUNCTION__);
+         }
+       */
 }
 
 /* PIRQ init
@@ -170,7 +164,7 @@ static const unsigned char slotIrqs[4] = { 5, 10, 12, 11 };
 */
 static void pci_routing_fixup(void)
 {
-  device_t dev;
+       device_t dev;
 
         dev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
        printk_info("%s: dev is %p\n", __FUNCTION__, dev);
@@ -204,260 +198,258 @@ static void pci_routing_fixup(void)
 
 
 void
-dump_south(void){
-  device_t dev0;
-  dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
-  int i,j;
-
-  for(i = 0; i < 256; i += 16) {
-    printk_debug("0x%x: ", i);
-    for(j = 0; j < 16; j++) {
-      printk_debug("%02x ", pci_read_config8(dev0, i+j));
-    }
-    printk_debug("\n");
-  }
+dump_south(void)
+{
+       device_t dev0;
+       dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
+       int i,j;
+       
+       for(i = 0; i < 256; i += 16) {
+               printk_debug("0x%x: ", i);
+               for(j = 0; j < 16; j++) {
+                       printk_debug("%02x ", pci_read_config8(dev0, i+j));
+               }
+               printk_debug("\n");
+       }
 }
 
 static void vt8231_init(struct southbridge_via_vt8231_config *conf)
 {
-  unsigned char enables;
-  device_t dev0;
-  device_t dev1;
-  device_t devpwr;
-
-  // to do: use the pcibios_find function here, instead of 
-  // hard coding the devfn. 
-  // done - kevinh/Ispiri
-  printk_debug("vt8231 init\n");
-  /* Base 8231 controller */
-  dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
-  /* IDE controller */
-  dev1 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, \
-                        0);
-  /* Power management controller */
-  devpwr = dev_find_device(PCI_VENDOR_ID_VIA, \
-                          PCI_DEVICE_ID_VIA_8231_4, 0);
-
-  // enable the internal I/O decode
-  enables = pci_read_config8(dev0, 0x6C);
-  enables |= 0x80;
-  pci_write_config8(dev0, 0x6C, enables);
-
-  // Map 4MB of FLASH into the address space
-  pci_write_config8(dev0, 0x41, 0x7f);
-
-  // Set bit 6 of 0x40, because Award does it (IO recovery time)
-  // IMPORTANT FIX - EISA 0x4d0 decoding must be on so that PCI 
-  // interrupts can be properly marked as level triggered.
-  enables = pci_read_config8(dev0, 0x40);
-  pci_write_config8(dev0, 0x40, enables);
-
-  // Set 0x42 to 0xf0 to match Award bios
-  enables = pci_read_config8(dev0, 0x42);
-  enables |= 0xf0;
-  pci_write_config8(dev0, 0x42, enables);
-
-  // Set bit 3 of 0x4a, to match award (dummy pci request)
-  enables = pci_read_config8(dev0, 0x4a);
-  enables |= 0x08;
-  pci_write_config8(dev0, 0x4a, enables);
-
-  // Set bit 3 of 0x4f to match award (use INIT# as cpu reset)
-  enables = pci_read_config8(dev0, 0x4f);
-  enables |= 0x08;
-  pci_write_config8(dev0, 0x4f, enables);
-
-  // Set 0x58 to 0x03 to match Award
-  pci_write_config8(dev0, 0x58, 0x03);
-
-  // enable the ethernet/RTC
-  if(dev0) {
-    enables = pci_read_config8(dev0, 0x51);
-    enables |= 0x18; 
-    pci_write_config8(dev0, 0x51, enables);
-  }
-       
-
-  // enable com1 and com2. 
-  if (conf->enable_com_ports) {
-    enables = pci_read_config8(dev0, 0x6e);
-
-    /* 0x80 is enable com port b, 0x10 is to make it com2, 0x8
-     * is enable com port a as com1 kevinh/Ispiri - Old code
-     * thought 0x01 would make it com1, that was wrong enables =
-     * 0x80 | 0x10 | 0x8 ; pci_write_config8(dev0, 0x6e,
-     * enables); // note: this is also a redo of some port of
-     * assembly, but we want everything up.
-     */
-
-    /* set com1 to 115 kbaud not clear how to do this yet.
-     * forget it; done in assembly.
-     */
-
-  }
-  // enable IDE, since Linux won't do it.
-  // First do some more things to devfn (17,0)
-  // note: this should already be cleared, according to the book. 
-  enables = pci_read_config8(dev0, 0x50);
-  printk_debug("IDE enable in reg. 50 is 0x%x\n", enables);
-  enables &= ~8; // need manifest constant here!
-  printk_debug("set IDE reg. 50 to 0x%x\n", enables);
-  pci_write_config8(dev0, 0x50, enables);
-
-  // set default interrupt values (IDE)
-  enables = pci_read_config8(dev0, 0x4c);
-  printk_debug("IRQs in reg. 4c are 0x%x\n", enables & 0xf);
-  // clear out whatever was there. 
-  enables &= ~0xf;
-  enables |= 4;
-  printk_debug("setting reg. 4c to 0x%x\n", enables);
-  pci_write_config8(dev0, 0x4c, enables);
-       
-  // set up the serial port interrupts. 
-  // com2 to 3, com1 to 4
-  pci_write_config8(dev0, 0x46, 0x04);
-  pci_write_config8(dev0, 0x47, 0x03);
-  pci_write_config8(dev0, 0x6e, 0x98);
-  //
-  // Power management setup
-  //
-  // Set ACPI base address to IO 0x4000
-  pci_write_config32(devpwr, 0x48, 0x4001);
-
-  // Enable ACPI access (and setup like award)
-  pci_write_config8(devpwr, 0x41, 0x84);
-
-  // Set hardware monitor base address to IO 0x6000
-  pci_write_config32(devpwr, 0x70, 0x6001);
-
-  // Enable hardware monitor (and setup like award)
-  pci_write_config8(devpwr, 0x74, 0x01);
-
-  // set IO base address to 0x5000
-  pci_write_config32(devpwr, 0x90, 0x5001);
-
-  // Enable SMBus 
-  pci_write_config8(devpwr, 0xd2, 0x01);
-
-  //
-  // IDE setup
-  //
-  if (conf->enable_native_ide) {
-    // Run the IDE controller in 'compatiblity mode - i.e. don't use PCI
-    // interrupts.  Using PCI ints confuses linux for some reason.
-         
-    printk_info("%s: enabling native IDE addresses\n", __FUNCTION__);
-    enables = pci_read_config8(dev1, 0x42);
-    printk_debug("enables in reg 0x42 0x%x\n", enables);
-    enables &= ~0xc0;          // compatability mode
-    pci_write_config8(dev1, 0x42, enables);
-    enables = pci_read_config8(dev1, 0x42);
-    printk_debug("enables in reg 0x42 read back as 0x%x\n", enables);
-  }
-
-  enables = pci_read_config8(dev1, 0x40);
-  printk_debug("enables in reg 0x40 0x%x\n", enables);
-  enables |= 3;
-  pci_write_config8(dev1, 0x40, enables);
-  enables = pci_read_config8(dev1, 0x40);
-  printk_debug("enables in reg 0x40 read back as 0x%x\n", enables);
-
-  // Enable prefetch buffers
-  enables = pci_read_config8(dev1, 0x41);
-  enables |= 0xf0;
-  pci_write_config8(dev1, 0x41, enables);
-
-  // Lower thresholds (cause award does it)
-  enables = pci_read_config8(dev1, 0x43);
-  enables &= ~0x0f;
-  enables |=  0x05;
-  pci_write_config8(dev1, 0x43, enables);
-
-  // PIO read prefetch counter (cause award does it)
-  pci_write_config8(dev1, 0x44, 0x18);
-
-  // Use memory read multiple
-  pci_write_config8(dev1, 0x45, 0x1c);
-
-  // address decoding. 
-  // we want "flexible", i.e. 1f0-1f7 etc. or native PCI
-  // kevinh@ispiri.com - the standard linux drivers seem ass slow when 
-  // used in native mode - I've changed back to classic
-  enables = pci_read_config8(dev1, 0x9);
-  printk_debug("enables in reg 0x9 0x%x\n", enables);
-  // by the book, set the low-order nibble to 0xa. 
-  if (conf->enable_native_ide) {
-    enables &= ~0xf;
-    // cf/cg silicon needs an 'f' here. 
-    enables |= 0xf;
-  } else {
-    enables &= ~0x5;
-  }
-
-  pci_write_config8(dev1, 0x9, enables);
-  enables = pci_read_config8(dev1, 0x9);
-  printk_debug("enables in reg 0x9 read back as 0x%x\n", enables);
-
-  // standard bios sets master bit. 
-  enables = pci_read_config8(dev1, 0x4);
-  printk_debug("command in reg 0x4 0x%x\n", enables);
-  enables |= 7;
-       
-  // No need for stepping - kevinh@ispiri.com
-  enables &= ~0x80;
-
-  pci_write_config8(dev1, 0x4, enables);
-  enables = pci_read_config8(dev1, 0x4);
-  printk_debug("command in reg 0x4 reads back as 0x%x\n", enables);
-
-  if (! conf->enable_native_ide) {
-    // Use compatability mode - per award bios
-    pci_write_config32(dev1, 0x10, 0x0);
-    pci_write_config32(dev1, 0x14, 0x0);
-    pci_write_config32(dev1, 0x18, 0x0);
-    pci_write_config32(dev1, 0x1c, 0x0);
-         
-    // Force interrupts to use compat mode - just like Award bios
-    pci_write_config8(dev1, 0x3d, 00);
-    pci_write_config8(dev1, 0x3c, 0xff);
-  }
-
-
-  /* set up isa bus -- i/o recovery time, rom write enable, extend-ale */
-  pci_write_config8(dev0, 0x40, 0x54);
-  ethernet_fixup();
-
-  // Start the rtc
-  rtc_init(0);
+       unsigned char enables;
+       device_t dev0;
+       device_t dev1;
+       device_t devpwr;
+       
+       // to do: use the pcibios_find function here, instead of 
+       // hard coding the devfn. 
+       // done - kevinh/Ispiri
+       printk_debug("vt8231 init\n");
+       /* Base 8231 controller */
+       dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
+       /* IDE controller */
+       dev1 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, 0);
+       /* Power management controller */
+       devpwr = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4, 0);
+
+       // enable the internal I/O decode
+       enables = pci_read_config8(dev0, 0x6C);
+       enables |= 0x80;
+       pci_write_config8(dev0, 0x6C, enables);
+       
+       // Map 4MB of FLASH into the address space
+       pci_write_config8(dev0, 0x41, 0x7f);
+       
+       // Set bit 6 of 0x40, because Award does it (IO recovery time)
+       // IMPORTANT FIX - EISA 0x4d0 decoding must be on so that PCI 
+       // interrupts can be properly marked as level triggered.
+       enables = pci_read_config8(dev0, 0x40);
+       pci_write_config8(dev0, 0x40, enables);
+       
+       // Set 0x42 to 0xf0 to match Award bios
+       enables = pci_read_config8(dev0, 0x42);
+       enables |= 0xf0;
+       pci_write_config8(dev0, 0x42, enables);
+       
+       // Set bit 3 of 0x4a, to match award (dummy pci request)
+       enables = pci_read_config8(dev0, 0x4a);
+       enables |= 0x08;
+       pci_write_config8(dev0, 0x4a, enables);
+       
+       // Set bit 3 of 0x4f to match award (use INIT# as cpu reset)
+       enables = pci_read_config8(dev0, 0x4f);
+       enables |= 0x08;
+       pci_write_config8(dev0, 0x4f, enables);
+       
+       // Set 0x58 to 0x03 to match Award
+       pci_write_config8(dev0, 0x58, 0x03);
+       
+       // enable the ethernet/RTC
+       if(dev0) {
+               enables = pci_read_config8(dev0, 0x51);
+               enables |= 0x18; 
+               pci_write_config8(dev0, 0x51, enables);
+       }
+       
+       
+       // enable com1 and com2. 
+       if (conf->enable_com_ports) {
+               enables = pci_read_config8(dev0, 0x6e);
+               
+               /* 0x80 is enable com port b, 0x10 is to make it com2, 0x8
+                * is enable com port a as com1 kevinh/Ispiri - Old code
+                * thought 0x01 would make it com1, that was wrong enables =
+                * 0x80 | 0x10 | 0x8 ; pci_write_config8(dev0, 0x6e,
+                * enables); // note: this is also a redo of some port of
+                * assembly, but we want everything up.
+                */
+               
+               /* set com1 to 115 kbaud not clear how to do this yet.
+                * forget it; done in assembly.
+                */
+
+       }
+       // enable IDE, since Linux won't do it.
+       // First do some more things to devfn (17,0)
+       // note: this should already be cleared, according to the book. 
+       enables = pci_read_config8(dev0, 0x50);
+       printk_debug("IDE enable in reg. 50 is 0x%x\n", enables);
+       enables &= ~8; // need manifest constant here!
+       printk_debug("set IDE reg. 50 to 0x%x\n", enables);
+       pci_write_config8(dev0, 0x50, enables);
+       
+       // set default interrupt values (IDE)
+       enables = pci_read_config8(dev0, 0x4c);
+       printk_debug("IRQs in reg. 4c are 0x%x\n", enables & 0xf);
+       // clear out whatever was there. 
+       enables &= ~0xf;
+       enables |= 4;
+       printk_debug("setting reg. 4c to 0x%x\n", enables);
+       pci_write_config8(dev0, 0x4c, enables);
+       
+       // set up the serial port interrupts. 
+       // com2 to 3, com1 to 4
+       pci_write_config8(dev0, 0x46, 0x04);
+       pci_write_config8(dev0, 0x47, 0x03);
+       pci_write_config8(dev0, 0x6e, 0x98);
+       //
+       // Power management setup
+       //
+       // Set ACPI base address to IO 0x4000
+       pci_write_config32(devpwr, 0x48, 0x4001);
+       
+       // Enable ACPI access (and setup like award)
+       pci_write_config8(devpwr, 0x41, 0x84);
+       
+       // Set hardware monitor base address to IO 0x6000
+       pci_write_config32(devpwr, 0x70, 0x6001);
+       
+       // Enable hardware monitor (and setup like award)
+       pci_write_config8(devpwr, 0x74, 0x01);
+       
+       // set IO base address to 0x5000
+       pci_write_config32(devpwr, 0x90, 0x5001);
+       
+       // Enable SMBus 
+       pci_write_config8(devpwr, 0xd2, 0x01);
+       
+       //
+       // IDE setup
+       //
+       if (conf->enable_native_ide) {
+               // Run the IDE controller in 'compatiblity mode - i.e. don't use PCI
+               // interrupts.  Using PCI ints confuses linux for some reason.
+               
+               printk_info("%s: enabling native IDE addresses\n", __FUNCTION__);
+               enables = pci_read_config8(dev1, 0x42);
+               printk_debug("enables in reg 0x42 0x%x\n", enables);
+               enables &= ~0xc0;               // compatability mode
+               pci_write_config8(dev1, 0x42, enables);
+               enables = pci_read_config8(dev1, 0x42);
+               printk_debug("enables in reg 0x42 read back as 0x%x\n", enables);
+       }
+       
+       enables = pci_read_config8(dev1, 0x40);
+       printk_debug("enables in reg 0x40 0x%x\n", enables);
+       enables |= 3;
+       pci_write_config8(dev1, 0x40, enables);
+       enables = pci_read_config8(dev1, 0x40);
+       printk_debug("enables in reg 0x40 read back as 0x%x\n", enables);
+       
+       // Enable prefetch buffers
+       enables = pci_read_config8(dev1, 0x41);
+       enables |= 0xf0;
+       pci_write_config8(dev1, 0x41, enables);
+       
+       // Lower thresholds (cause award does it)
+       enables = pci_read_config8(dev1, 0x43);
+       enables &= ~0x0f;
+       enables |=  0x05;
+       pci_write_config8(dev1, 0x43, enables);
+       
+       // PIO read prefetch counter (cause award does it)
+       pci_write_config8(dev1, 0x44, 0x18);
+       
+       // Use memory read multiple
+       pci_write_config8(dev1, 0x45, 0x1c);
+       
+       // address decoding. 
+       // we want "flexible", i.e. 1f0-1f7 etc. or native PCI
+       // kevinh@ispiri.com - the standard linux drivers seem ass slow when 
+       // used in native mode - I've changed back to classic
+       enables = pci_read_config8(dev1, 0x9);
+       printk_debug("enables in reg 0x9 0x%x\n", enables);
+       // by the book, set the low-order nibble to 0xa. 
+       if (conf->enable_native_ide) {
+               enables &= ~0xf;
+               // cf/cg silicon needs an 'f' here. 
+               enables |= 0xf;
+       } else {
+               enables &= ~0x5;
+       }
+       
+       pci_write_config8(dev1, 0x9, enables);
+       enables = pci_read_config8(dev1, 0x9);
+       printk_debug("enables in reg 0x9 read back as 0x%x\n", enables);
+       
+       // standard bios sets master bit. 
+       enables = pci_read_config8(dev1, 0x4);
+       printk_debug("command in reg 0x4 0x%x\n", enables);
+       enables |= 7;
+       
+       // No need for stepping - kevinh@ispiri.com
+       enables &= ~0x80;
+       
+       pci_write_config8(dev1, 0x4, enables);
+       enables = pci_read_config8(dev1, 0x4);
+       printk_debug("command in reg 0x4 reads back as 0x%x\n", enables);
+       
+       if (! conf->enable_native_ide) {
+               // Use compatability mode - per award bios
+               pci_write_config32(dev1, 0x10, 0x0);
+               pci_write_config32(dev1, 0x14, 0x0);
+               pci_write_config32(dev1, 0x18, 0x0);
+               pci_write_config32(dev1, 0x1c, 0x0);
+               
+               // Force interrupts to use compat mode - just like Award bios
+               pci_write_config8(dev1, 0x3d, 00);
+               pci_write_config8(dev1, 0x3c, 0xff);
+       }
+       
+       
+       /* set up isa bus -- i/o recovery time, rom write enable, extend-ale */
+       pci_write_config8(dev0, 0x40, 0x54);
+       ethernet_fixup();
+       
+       // Start the rtc
+       rtc_init(0);
 }
 
-static void 
-southbridge_init(struct chip *chip, enum chip_pass pass)
+static void southbridge_init(struct chip *chip, enum chip_pass pass)
 {
 
-  struct southbridge_via_vt8231_config *conf = 
-    (struct southbridge_via_vt8231_config *)chip->chip_info;
-
-  switch (pass) {
-  case CONF_PASS_PRE_PCI:
-    vt8231_pci_enable(conf);
-    break;
-
-  case CONF_PASS_POST_PCI:
-    vt8231_init(conf);
-    printk_err("FUCK! ROUTING FIXUP!\n");
-    pci_routing_fixup();
-
-    break;
-  case CONF_PASS_PRE_BOOT:
-    pci_routing_fixup();
-    dump_south();
-    break;
-
-  default:
-    /* nothing yet */
-    break;
-  }
+       struct southbridge_via_vt8231_config *conf = 
+               (struct southbridge_via_vt8231_config *)chip->chip_info;
+
+       switch (pass) {
+       case CONF_PASS_PRE_PCI:
+               vt8231_pci_enable(conf);
+               break;
+               
+       case CONF_PASS_POST_PCI:
+               vt8231_init(conf);
+               printk_err("FUCK! ROUTING FIXUP!\n");
+               pci_routing_fixup();
+               
+               break;
+       case CONF_PASS_PRE_BOOT:
+               pci_routing_fixup();
+               dump_south();
+               break;
+               
+       default:
+               /* nothing yet */
+               break;
+       }
 }
 
 static void enumerate(struct chip *chip)
@@ -468,7 +460,7 @@ static void enumerate(struct chip *chip)
 }
 
 struct chip_control southbridge_via_vt8231_control = {
-  .enumerate = enumerate,
-  enable: southbridge_init,
-  name:   "VIA vt8231"
+       .enumerate = enumerate,
+       .enable    = southbridge_init,
+       .name      = "VIA vt8231"
 };
index ca7831df422c2bd7cf65ef03603f59bb2b498a69..1bfffed7f51c80178e22bd99cb63f703a58b9af6 100644 (file)
@@ -8,20 +8,20 @@
 #define SIO_BASE 0x3f0
 #define SIO_DATA  SIO_BASE+1
 
-static void
-vt8231_writesuper(uint8_t reg, uint8_t val) {
-  outb(reg, SIO_BASE);
-  outb(val, SIO_DATA);
+static void vt8231_writesuper(uint8_t reg, uint8_t val) 
+{
+       outb(reg, SIO_BASE);
+       outb(val, SIO_DATA);
 }
 
-static void
-vt8231_writesiobyte(uint16_t reg, uint8_t val) {
-  outb(val, reg);
+static void vt8231_writesiobyte(uint16_t reg, uint8_t val) 
+{
+       outb(val, reg);
 }
 
-static void
-vt8231_writesioword(uint16_t reg, uint16_t val) {
-  outw(val, reg);
+static void vt8231_writesioword(uint16_t reg, uint16_t val) 
+{
+       outw(val, reg);
 }
 
 
@@ -29,48 +29,47 @@ vt8231_writesioword(uint16_t reg, uint16_t val) {
    mainboard
  */
 
-static void
-enable_vt8231_serial(void) {
-  unsigned long x;
-  uint8_t c;
-  device_t dev;
-  outb(6, 0x80);
-  dev = pci_locate_device(PCI_ID(0x1106,0x8231), 0);
-  
-  if (dev == PCI_DEV_INVALID) {
-    outb(7, 0x80);
-    die("Serial controller not found\r\n");
-  }
-
-  /* first, you have to enable the superio and superio config. 
-     put a 6 reg 80
-  */
-  c = pci_read_config8(dev, 0x50);
-  c |= 6;
-  pci_write_config8(dev, 0x50, c);
-  outb(2, 0x80);
-  // now go ahead and set up com1. 
-  // set address
-  vt8231_writesuper(0xf4, 0xfe);
-  // enable serial out
-  vt8231_writesuper(0xf2, 7);
-  // That's it for the sio stuff.
-  //   movl    $SUPERIOCONFIG, %eax
-  //   movb    $9, %dl
-  //   PCI_WRITE_CONFIG_BYTE
-  // set up reg to set baud rate.
-  vt8231_writesiobyte(0x3fb, 0x80);
-  // Set 115 kb
-  vt8231_writesioword(0x3f8, 1);
-  // Set 9.6 kb
-  //   WRITESIOWORD(0x3f8, 12)
-  // now set no parity, one stop, 8 bits
-  vt8231_writesiobyte(0x3fb, 3);
-  // now turn on RTS, DRT
-  vt8231_writesiobyte(0x3fc, 3);
-  // Enable interrupts
-  vt8231_writesiobyte(0x3f9, 0xf);
-  // should be done. Dump a char for fun.
-  vt8231_writesiobyte(0x3f8, 48);
-  
+static void enable_vt8231_serial(void) 
+{
+       unsigned long x;
+       uint8_t c;
+       device_t dev;
+       outb(6, 0x80);
+       dev = pci_locate_device(PCI_ID(0x1106,0x8231), 0);
+       
+       if (dev == PCI_DEV_INVALID) {
+               outb(7, 0x80);
+               die("Serial controller not found\r\n");
+       }
+       
+       /* first, you have to enable the superio and superio config. 
+          put a 6 reg 80
+       */
+       c = pci_read_config8(dev, 0x50);
+       c |= 6;
+       pci_write_config8(dev, 0x50, c);
+       outb(2, 0x80);
+       // now go ahead and set up com1. 
+       // set address
+       vt8231_writesuper(0xf4, 0xfe);
+       // enable serial out
+       vt8231_writesuper(0xf2, 7);
+       // That's it for the sio stuff.
+       //      movl    $SUPERIOCONFIG, %eax
+       //      movb    $9, %dl
+       //      PCI_WRITE_CONFIG_BYTE
+       // set up reg to set baud rate.
+       vt8231_writesiobyte(0x3fb, 0x80);
+       // Set 115 kb
+       vt8231_writesioword(0x3f8, 1);
+       // Set 9.6 kb
+       //      WRITESIOWORD(0x3f8, 12)
+       // now set no parity, one stop, 8 bits
+       vt8231_writesiobyte(0x3fb, 3);
+       // now turn on RTS, DRT
+       vt8231_writesiobyte(0x3fc, 3);
+       // Enable interrupts
+       vt8231_writesiobyte(0x3f9, 0xf);
+       // should be done. Dump a char for fun.
+       vt8231_writesiobyte(0x3f8, 48);
 }
index 49b942cb2338cf23dce1fb77e280621f15ccab51..e419d59b636388b354308e36bf1ca84e045eebce 100644 (file)
 
 static void enable_smbus(void)
 {
-  device_t dev;
-  unsigned char c;
-  /* Power management controller */
-  dev = pci_locate_device(PCI_ID(0x1106,0x8235), 0);
-
-  if (dev == PCI_DEV_INVALID) {
-    die("SMBUS controller not found\r\n");
-  }
-
-  // set IO base address to SMBUS_IO_BASE
-  pci_write_config32(dev, 0x90, SMBUS_IO_BASE|1);
-
-  // Enable SMBus 
-  c = pci_read_config8(dev, 0xd2);
-  c |= 5;
-  pci_write_config8(dev, 0xd2, c);
-
-  /* make it work for I/O ...
-   */
-  dev = pci_locate_device(PCI_ID(0x1106,0x8231), 0);
-  c = pci_read_config8(dev, 4);
-  c |= 1;
-  pci_write_config8(dev, 4, c);
-  print_err_hex8(c);
-  print_err(" is the comm register\n");
-
-  print_debug("SMBus controller enabled\r\n");
+       device_t dev;
+       unsigned char c;
+       /* Power management controller */
+       dev = pci_locate_device(PCI_ID(0x1106,0x8235), 0);
+       
+       if (dev == PCI_DEV_INVALID) {
+               die("SMBUS controller not found\r\n");
+       }
+       
+       // set IO base address to SMBUS_IO_BASE
+       pci_write_config32(dev, 0x90, SMBUS_IO_BASE|1);
+       
+       // Enable SMBus 
+       c = pci_read_config8(dev, 0xd2);
+       c |= 5;
+       pci_write_config8(dev, 0xd2, c);
+       
+       /* make it work for I/O ...
+        */
+       dev = pci_locate_device(PCI_ID(0x1106,0x8231), 0);
+       c = pci_read_config8(dev, 4);
+       c |= 1;
+       pci_write_config8(dev, 4, c);
+       print_err_hex8(c);
+       print_err(" is the comm register\n");
+       
+       print_debug("SMBus controller enabled\r\n");
 }
 
 
 static inline void smbus_delay(void)
 {
-  outb(0x80, 0x80);
+       outb(0x80, 0x80);
 }
 
 static int smbus_wait_until_ready(void)
 {
        unsigned char c;
-  unsigned long loops;
-  loops = SMBUS_TIMEOUT;
-  do {
-    unsigned char val;
-    smbus_delay();
-    c = inb(SMBUS_IO_BASE + SMBHSTSTAT);
-    while((c & 1) == 1) {
-      print_err("c is ");
-      print_err_hex8(c);
-      print_err("\n");
-      c = inb(SMBUS_IO_BASE + SMBHSTSTAT);
-      /* nop */ 
-    }
-
-  } while(--loops);
-  return loops?0:-1;
+       unsigned long loops;
+       loops = SMBUS_TIMEOUT;
+       do {
+               unsigned char val;
+               smbus_delay();
+               c = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+               while((c & 1) == 1) {
+                       print_err("c is ");
+                       print_err_hex8(c);
+                       print_err("\n");
+                       c = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+                       /* nop */ 
+               }
+
+       } while(--loops);
+       return loops?0:-1;
 }
 
 void smbus_reset(void)
 {
-  outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
-  outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
-  outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
-  outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
-
-  smbus_wait_until_ready();
-  print_err("After reset status ");
-  print_err_hex8( inb(SMBUS_IO_BASE + SMBHSTSTAT));
-  print_err("\n");
+       outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
+       outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
+       outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
+       outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
+       
+       smbus_wait_until_ready();
+       print_err("After reset status ");
+       print_err_hex8( inb(SMBUS_IO_BASE + SMBHSTSTAT));
+       print_err("\n");
 }
   
 
 
 static int smbus_wait_until_done(void)
 {
-  unsigned long loops;
-  unsigned char byte;
-  loops = SMBUS_TIMEOUT;
-  do {
-    unsigned char val;
-    smbus_delay();
+       unsigned long loops;
+       unsigned char byte;
+       loops = SMBUS_TIMEOUT;
+       do {
+               unsigned char val;
+               smbus_delay();
                
-    byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
-    if (byte & 1)
-      break;
-
-  } while(--loops);
-  return loops?0:-1;
+               byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+               if (byte & 1)
+                       break;
+               
+       } while(--loops);
+       return loops?0:-1;
 }
 
 static void smbus_print_error(unsigned char host_status_register)
 {
 
-  print_err("smbus_error: ");
-  print_err_hex8(host_status_register);
-  print_err("\n");
-  if (host_status_register & (1 << 4)) {
-    print_err("Interrup/SMI# was Failed Bus Transaction\n");
-  }
-  if (host_status_register & (1 << 3)) {
-    print_err("Bus Error\n");
-  }
-  if (host_status_register & (1 << 2)) {
-    print_err("Device Error\n");
-  }
-  if (host_status_register & (1 << 1)) {
-    print_err("Interrupt/SMI# was Successful Completion\n");
-  }
-  if (host_status_register & (1 << 0)) {
-    print_err("Host Busy\n");
-  }
+       print_err("smbus_error: ");
+       print_err_hex8(host_status_register);
+       print_err("\n");
+       if (host_status_register & (1 << 4)) {
+               print_err("Interrup/SMI# was Failed Bus Transaction\n");
+       }
+       if (host_status_register & (1 << 3)) {
+               print_err("Bus Error\n");
+       }
+       if (host_status_register & (1 << 2)) {
+               print_err("Device Error\n");
+       }
+       if (host_status_register & (1 << 1)) {
+               print_err("Interrupt/SMI# was Successful Completion\n");
+       }
+       if (host_status_register & (1 << 0)) {
+               print_err("Host Busy\n");
+       }
 }
 
 
@@ -141,39 +141,39 @@ static void smbus_print_error(unsigned char host_status_register)
 static unsigned char smbus_read_byte(unsigned char devAdr, 
                                unsigned char bIndex) 
 {
-  unsigned short i;
-  unsigned char  bData;
-  unsigned char  sts = 0;
-                       
-  /* clear host status */
-  outb(0xff, SMBUS_IO_BASE);
-
-  /* check SMBUS ready */
-  for ( i = 0; i < 0xFFFF; i++ )
-    if ( (inb(SMBUS_IO_BASE) & 0x01) == 0 )
-      break;
-
-  /* set host command */
-  outb(bIndex, SMBUS_IO_BASE+3);
-
-  /* set slave address */
-  outb(devAdr | 0x01, SMBUS_IO_BASE+4);
-
-  /* start */
-  outb(0x48, SMBUS_IO_BASE+2);
-
-  /* SMBUS Wait Ready */
-  for ( i = 0; i < 0xFFFF; i++ )
-    if ( ((sts = inb(SMBUS_IO_BASE)) & 0x01) == 0 )
-      break;
-  if ((sts & ~3) != 0) {
-    smbus_print_error(sts);
-    return 0;
-  }
-  bData=inb(SMBUS_IO_BASE+5);
-
-  return bData;
-
+       unsigned short i;
+       unsigned char  bData;
+       unsigned char  sts = 0;
+       
+       /* clear host status */
+       outb(0xff, SMBUS_IO_BASE);
+       
+       /* check SMBUS ready */
+       for ( i = 0; i < 0xFFFF; i++ )
+               if ( (inb(SMBUS_IO_BASE) & 0x01) == 0 )
+                       break;
+       
+       /* set host command */
+       outb(bIndex, SMBUS_IO_BASE+3);
+       
+       /* set slave address */
+       outb(devAdr | 0x01, SMBUS_IO_BASE+4);
+       
+       /* start */
+       outb(0x48, SMBUS_IO_BASE+2);
+       
+       /* SMBUS Wait Ready */
+       for ( i = 0; i < 0xFFFF; i++ )
+               if ( ((sts = inb(SMBUS_IO_BASE)) & 0x01) == 0 )
+                       break;
+       if ((sts & ~3) != 0) {
+               smbus_print_error(sts);
+               return 0;
+       }
+       bData=inb(SMBUS_IO_BASE+5);
+       
+       return bData;
+       
 }
 
 /* for reference, here is the fancier version which we will use at some 
@@ -182,48 +182,48 @@ static unsigned char smbus_read_byte(unsigned char devAdr,
 # if 0
 int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
 {
-  unsigned char host_status_register;
-  unsigned char byte;
-
-  reset();
-
-  smbus_wait_until_ready();
-
-  /* setup transaction */
-  /* disable interrupts */
-  outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
-  /* set the device I'm talking too */
-  outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBXMITADD);
-  /* set the command/address... */
-  outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
-  /* set up for a byte data read */
-  outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x2 << 2),
-         SMBUS_IO_BASE + SMBHSTCTL);
-
-  /* clear any lingering errors, so the transaction will run */
-  outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
-
-  /* clear the data byte...*/
-  outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
-
-  /* start the command */
-  outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40),
-         SMBUS_IO_BASE + SMBHSTCTL);
-
-  /* poll for transaction completion */
-  smbus_wait_until_done();
-
-  host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
-
-  /* Ignore the In Use Status... */
-  host_status_register &= ~(1 << 6);
-
-  /* read results of transaction */
-  byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
-  smbus_print_error(byte);
-
-  *result = byte;
-  return host_status_register != 0x02;
+       unsigned char host_status_register;
+       unsigned char byte;
+       
+       reset();
+       
+       smbus_wait_until_ready();
+       
+       /* setup transaction */
+       /* disable interrupts */
+       outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
+       /* set the device I'm talking too */
+       outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBXMITADD);
+       /* set the command/address... */
+       outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
+       /* set up for a byte data read */
+       outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x2 << 2),
+               SMBUS_IO_BASE + SMBHSTCTL);
+       
+       /* clear any lingering errors, so the transaction will run */
+       outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+       
+       /* clear the data byte...*/
+       outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
+       
+       /* start the command */
+       outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40),
+               SMBUS_IO_BASE + SMBHSTCTL);
+       
+       /* poll for transaction completion */
+       smbus_wait_until_done();
+       
+       host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+       
+       /* Ignore the In Use Status... */
+       host_status_register &= ~(1 << 6);
+       
+       /* read results of transaction */
+       byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
+       smbus_print_error(byte);
+       
+       *result = byte;
+       return host_status_register != 0x02;
 }
 
 
index 24bf65061f437571722cd66b9e11379d408bac31..55787566fc700f06b6d8c86885e035f9e816153f 100644 (file)
@@ -14,7 +14,7 @@
 extern struct chip_control superio_NSC_pc87360_control;
 
 struct superio_NSC_pc87360_config {
-    struct com_ports com1;
-    struct lpt_ports lpt;
-    int port;
+       struct com_ports com1;
+       struct lpt_ports lpt;
+       int port;
 };
index 0ec41c3346ccd2ceee8eeb79b795b530282b795c..8765eb35cc33cdd6f4680f92431d8dac4381d04d 100644 (file)
@@ -305,7 +305,16 @@ static void enumerate(struct chip *chip)
                resource->base = conf->com1.irq;
                resource->flags = IORESOURCE_IRQ | IORESOURCE_FIXED | IORESOURCE_SET;
        }
-               
+
+       /* Process the hard codes for the keyboard controller */
+       path.u.pnp.device = KBC_DEVICE;
+       dev = alloc_find_dev(dev, &path);
+       resource = get_resource(dev, 0x60);
+       resource->base = 0x60;
+       resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_SET;
+       resource = get_resource(dev, 0x62);
+       resource->base = 0x64;
+       resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_SET;
 }
 
 struct chip_control superio_NSC_pc87360_control = {
index 6c74ee6207e89a7a97d18541e11159f1f46d2244..51d00fb3c4b32ee442d11ecfc41ee1fb58901a2b 100644 (file)
@@ -93,9 +93,7 @@ romimage "normal"
        option ROM_IMAGE_SIZE=0x10000
        option LINUXBIOS_EXTRA_VERSION=".0Normal"
        mainboard arima/hdama
-       payload /usr/share/etherboot/5.1.9pre2-lnxi-lb/tg3--ide_disk.zelf
-# use this to test a build if you don't have the etherboot
-#      payload /etc/hosts
+       payload /usr/share/etherboot/5.2.1eb1-lnxi-lb/tg3--ide_disk.zelf
 end
 
 romimage "fallback" 
@@ -103,7 +101,7 @@ romimage "fallback"
        option ROM_IMAGE_SIZE=0x10000
        option LINUXBIOS_EXTRA_VERSION=".0Fallback"
        mainboard arima/hdama
-       payload /usr/share/etherboot/5.1.9pre2-lnxi-lb/tg3--ide_disk.zelf
+       payload /usr/share/etherboot/5.2.1eb1-lnxi-lb/tg3--ide_disk.zelf
 # use this to test a build if you don't have the etherboot
 #      payload /etc/hosts
 end
index 9f8cb316192d9ba5177305a2f96c5cf684917f99..88d09b7c883ce627ff24919beccac49f004add9f 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-
+PYTHON=python
 # Target build script
 
 if [ $# -lt 1 ]; then
@@ -17,7 +17,9 @@ fi
 target_dir=$lbpath/targets
 config_lb=$1
 config_dir=$lbpath/util/newconfig
-config_py=$config_dir/config.py
+yapps2_py=$config_dir/yapps2.py
+config_g=$config_dir/config.g
+config_py=$config_lb/config.py
 
 if [ ! -d $target_dir ]; then
        echo "Target directory not found"
@@ -38,18 +40,12 @@ fi
 
 if [ ! -f $config_py ]; then
        echo "No linuxbios config script found. Rebuilding it.."
-       ( 
-         cd $config_dir 
-         make config.py
-       )
-       echo "done."
-       # exit 1
+       $PYTHON $yapps2_py $config_g $config_py
 fi
 
 # make sure config.py is up-to-date
 
-(cd $config_dir && make config.py)
-
-python $config_py $config_lb $lbpath
+export PYTHONPATH=$config_dir
+$PYTHON $config_py $config_lb $lbpath
 
 exit $?
index 374148254e2bd1b14da94c162de82c41ec4a15f7..3328380569791b014ca9b2c40ebe08f965d99460 100644 (file)
@@ -26,7 +26,6 @@ manual/index.html: yapps2.aux yapps2.tex
 
 DISTRIB:
        cd ..; zip -u yapps2.zip yapps2/{LICENSE,yapps2.py,yappsrt.py,parsedesc.g,examples/*.g,NOTES,yapps2.tex,Makefile,manual/*.html,manual/*.css,manual/*.png}
-                                                                               
+
 clean:
        rm -f config.py yappsrt.pyc parsedesc.py
-       
index 23bdea9a7915202215d9ac5e1be84ceebf7c5f87..5bec889092676b26cd198b7bbd9317f86506f73c 100644 (file)
@@ -580,7 +580,7 @@ class option_value:
 
 class partobj:
        """A configuration part"""
-       def __init__ (self, image, dir, parent, part, type_name, instance_name):
+       def __init__ (self, image, dir, parent, part, type_name, instance_name, link):
                debug.info(debug.object, "partobj dir %s parent %s part %s" \
                                % (dir, parent, part))
 
@@ -626,6 +626,11 @@ class partobj:
 
                # Path to the device
                self.path = ""
+
+                # Link from parent device
+                if ((link < 0) or (link > 2)):
+                       fatal("Invalid link")
+                self.link = link
                
                # If no instance name is supplied then generate
                # a unique name
@@ -704,6 +709,7 @@ class partobj:
                else:
                        file.write("struct chip static_root = {\n")
                file.write("\t/* %s %s */\n" % (self.part, self.dir))
+                file.write("\t.link = %d,\n" % (self.link))
                if (self.path != ""):
                        file.write("\t.path = { %s\n\t},\n" % (self.path) );
                if (self.siblings):
@@ -749,33 +755,29 @@ class partobj:
                value = dequote(value)
                setdict(self.registercode, field, value)
 
-       def addpcipath(self, enable, channel, slot, function):
+       def addpcipath(self, enable, bus, slot, function):
                """ Add a relative pci style path from our parent to this device """
-               if (channel < 0):
-                       fatal("Invalid channel")
+               if ((bus < 0) or (bus > 255)):
+                       fatal("Invalid bus")
                if ((slot < 0) or (slot > 0x1f)):
                        fatal("Invalid device id")
                if ((function < 0) or (function > 7)):
                        fatal("Invalid function")
-               self.path = "%s\n\t\t{ .channel = %d, .enable = %d, .path = {.type=DEVICE_PATH_PCI,.u={.pci={ .devfn = PCI_DEVFN(0x%x,%d) }}}}," % (self.path, channel, enable, slot, function)
+               self.path = "%s\n\t\t{ .enable = %d, .path = {.type=DEVICE_PATH_PCI,.u={.pci={ .bus = 0x%x, .devfn = PCI_DEVFN(0x%x,%d) }}}}," % (self.path, enable, bus, slot, function)
 
-       def addpnppath(self, enable, channel, port, device):
+       def addpnppath(self, enable, port, device):
                """ Add a relative path to a pnp device hanging off our parent """
-               if (channel < 0):
-                       fatal("Invalid channel")
                if ((port < 0) or (port > 65536)):
                        fatal("Invalid port")
                if ((device < 0) or (device > 0xff)):
                        fatal("Invalid device")
-               self.path = "%s\n\t\t{ .channel = %d, .enable = %d, .path={.type=DEVICE_PATH_PNP,.u={.pnp={ .port = 0x%x, .device = 0x%x }}}}," % (self.path, channel, enable, port, device)
+               self.path = "%s\n\t\t{ .enable = %d, .path={.type=DEVICE_PATH_PNP,.u={.pnp={ .port = 0x%x, .device = 0x%x }}}}," % (self.path, enable, port, device)
 
-       def addi2cpath(self, enable, channel, device):
+       def addi2cpath(self, enable, device):
                """ Add a relative path to a i2c device hanging off our parent """
-               if (channel < 0):
-                       fatal("Invalid channel")
                if ((device < 0) or (device > 0x7f)):
                        fatal("Invalid device")
-               self.path = "%s\n\t\t{ .channel = %d, .enable = %d, .path = {.type=DEVICE_PATH_I2C,.u={.i2c={ .device = 0x%x }}}}, " % (self.path, channel, enable, device)
+               self.path = "%s\n\t\t{ .enable = %d, .path = {.type=DEVICE_PATH_I2C,.u={.i2c={ .device = 0x%x }}}}, " % (self.path, enable, device)
 
        def usesoption(self, name):
                """Declare option that can be used by this part"""
@@ -1076,7 +1078,7 @@ def mainboard(path):
        setoption('MAINBOARD_VENDOR', vendor)
        setoption('MAINBOARD_PART_NUMBER', part_number)
        dodir('/config', 'Config.lb')
-       part('mainboard', path, 'Config.lb', 0)
+       part('mainboard', path, 'Config.lb', 0, 0)
        curimage.setroot(partstack.tos())
        partpop()
 
@@ -1117,14 +1119,14 @@ def cpudir(path):
        dodir(srcdir, "Config.lb")
        cpu_type = path
        
-def part(type, path, file, name):
+def part(type, path, file, name, link):
        global curimage, dirstack, partstack
        partdir = os.path.join(type, path)
        srcdir = os.path.join(treetop, 'src')
        fulldir = os.path.join(srcdir, partdir)
        type_name = flatten_name(os.path.join(type, path))
        newpart = partobj(curimage, fulldir, partstack.tos(), type, \
-                       type_name, name)
+                       type_name, name, link)
        print "Configuring PART %s, path %s" % (type, path)
        partstack.push(newpart)
        dirstack.push(fulldir)
@@ -1196,7 +1198,7 @@ def setarch(my_arch):
        global curimage
        curimage.setarch(my_arch)
        setoption('ARCH', my_arch)
-       part('arch', my_arch, 'Config.lb', 0)
+       part('arch', my_arch, 'Config.lb', 0, 0)
 
 def doconfigfile(path, confdir, file, rule):
        rname = os.path.join(confdir, file)
@@ -1328,6 +1330,7 @@ parser Config:
     token PCI:                 'pci'
     token PNP:                 'pnp'
     token I2C:                 'i2c'
+    token LINK:                 'link'
 
 
     rule expr:         logical                 {{ l = logical }}
@@ -1371,11 +1374,12 @@ parser Config:
                |       SOUTHBRIDGE             {{ return 'southbridge' }}
                |       CPU                     {{ return 'cpu' }}
 
-    rule partdef<<C>>:                         {{ name = 0 }}
+    rule partdef<<C>>:                         {{ name = 0 }} {{ link = 0 }}
                        parttype partid
                        [ STR                   {{ name = dequote(STR) }}
-                       ]                       {{ if (C): part(parttype, partid, 'Config.lb', name) }}
-                       partend<<C>>
+                        ][ LINK NUM             {{ link = long(NUM, 10) }}
+                       ]                       {{ if (C): part(parttype, partid, 'Config.lb', name, link) }}
+                       partend<<C>>            
 
     rule arch<<C>>:    ARCH ID                 {{ if (C): setarch(ID) }}
                        partend<<C>>
@@ -1430,22 +1434,20 @@ parser Config:
                        | OFF                   {{ val = 0 }}
                        ) ]                     {{ return val }}
     
-    rule pci<<C>>:     PCI HEX_NUM             {{ channel = int(HEX_NUM,16) }}
+    rule pci<<C>>:     PCI HEX_NUM             {{ bus = int(HEX_NUM,16) }}
                        ':' HEX_NUM             {{ slot = int(HEX_NUM,16) }}
                        '.' HEX_NUM             {{ function = int(HEX_NUM, 16) }}
                        enable 
-                                               {{ if (C): partstack.tos().addpcipath(enable, channel, slot, function) }}
+                                               {{ if (C): partstack.tos().addpcipath(enable, bus, slot, function) }}
 
-    rule pnp<<C>>:     PNP HEX_NUM             {{ channel = int(HEX_NUM,16) }}
-                       ':' HEX_NUM             {{ port = int(HEX_NUM,16) }}
+    rule pnp<<C>>:     PNP HEX_NUM             {{ port = int(HEX_NUM,16) }}
                        '.' HEX_NUM             {{ device = int(HEX_NUM, 16) }}
                        enable
-                                               {{ if (C): partstack.tos().addpnppath(enable, channel, port, device) }}
+                                               {{ if (C): partstack.tos().addpnppath(enable, port, device) }}
 
-    rule i2c<<C>>:     I2C HEX_NUM             {{ channel = int(HEX_NUM, 16) }}
-                       ':' HEX_NUM             {{ device = int(HEX_NUM, 16) }}
+    rule i2c<<C>>:     I2C HEX_NUM             {{ device = int(HEX_NUM, 16) }}
                        enable
-                                               {{ if (C): partstatck.tos().addi2cpath(enable, channel, device) }}
+                                               {{ if (C): partstatck.tos().addi2cpath(enable, device) }}
                        
     rule prtval:       expr                    {{ return str(expr) }}
                |       STR                     {{ return STR }}
index 982e01b136d55c7457e7ec62ccddedc81777ed0d..183aeab1bdd79055be5af9f09e56fc35c744f02b 100644 (file)
@@ -23,9 +23,10 @@ static unsigned char clip[9]={0,1,3,7,0x0f,0x1f,0x3f,0x7f,0xff};
        output  none
                if there is an overlap, the routine exits, other wise it returns.
 */
-void test_for_entry_overlaps(int entry_start,int entry_end)
+void test_for_entry_overlaps(void *entry_start, void *entry_end)
 {
-       long ptr;
+       int ptr;
+       char *cptr;
        int buffer_bit_size;
        int offset;
        int byte;
@@ -37,11 +38,12 @@ void test_for_entry_overlaps(int entry_start,int entry_end)
        /* calculate the size of the cmos buffer in bits */
        buffer_bit_size=(CMOS_IMAGE_BUFFER_SIZE*8);
        /* clear the temporary test buffer */
-       for(ptr=0;ptr<CMOS_IMAGE_BUFFER_SIZE;ptr++)
+       for(ptr=0; ptr < CMOS_IMAGE_BUFFER_SIZE; ptr++)
                test[ptr]=0;
+
        /* loop through each entry in the table testing for errors */
-       for(ptr=entry_start;ptr<entry_end;ptr+=ce->size) {
-               ce=(struct cmos_entries *)ptr;
+       for(cptr = entry_start; cptr < (char *)entry_end; cptr += ce->size) {
+               ce=(struct cmos_entries *)cptr;
                /* test if entry goes past the end of the buffer */
                if((ce->bit+ce->length)>buffer_bit_size) {
                        printf("Error - Entry %s start bit + length must be less than %d\n",
@@ -66,16 +68,17 @@ void test_for_entry_overlaps(int entry_start,int entry_end)
                        /* test if any of the bits have been previously used */
                        for(;byte_length;byte_length--,byte++) {
                                if(test[byte]) {
-                                    printf("Error - Entry %s uses same bits previously used\n",
+                                       printf("Error - Entry %s uses same bits previously used\n",
                                                ce->name);
-                                    exit(1);
+                                       exit(1);
                                }
                                test[byte]=clip[8]; /* set the bits defined in test */
                        }
                } else {
                        /* test if bits overlap byte boundaries */
                        if(ce->length>(8-offset)) {
-                                printf("Error - Entry %s length overlaps a byte boundry\n",                                        ce->name);
+                                printf("Error - Entry %s length overlaps a byte boundry\n",
+                                       ce->name);
                                 exit(1);
                         }
                        /* test for bits previously used */
@@ -158,8 +161,7 @@ int main(int argc, char **argv)
        long ptr;
        int cnt;
        char *cptr;
-       long offset;
-       int entry_start;
+       void *entry_start, *entry_end;
        int entries_length;
        int enum_length;
        int len;
@@ -268,21 +270,19 @@ int main(int argc, char **argv)
                        len+=(4-(len%4));
                ce->size=sizeof(struct cmos_entries)-32+len;
                cptr = (char*)ce;
-               cptr+=ce->size;  /* increment to the next table position */
+               cptr += ce->size;  /* increment to the next table position */
                ce = (struct cmos_entries*) cptr;
        }
 
        /* put the length of the entries into the header section */
-       entries_length=(long)cptr;
-       entries_length-=(long)(cmos_table+ct->header_length);
+       entries_length = (cptr - (char *)&cmos_table) - ct->header_length;
 
        /* compute the start of the enumerations section */
-       entry_start=(int)cmos_table;
-       entry_start+=ct->header_length;
-       offset=entry_start+entries_length;
-       c_enums_start=c_enums=(struct cmos_enums*)offset;
+       entry_start = ((char*)&cmos_table) + ct->header_length;
+       entry_end   = ((char *)entry_start) + entries_length;
+       c_enums_start = c_enums = (struct cmos_enums*)entry_end;
        /* test for overlaps in the entry records */
-       test_for_entry_overlaps(entry_start,offset);
+       test_for_entry_overlaps(entry_start, entry_end);
 
        for(;enum_mode;){ /* loop to build the enumerations section */
                if(fgets(line,INPUT_LINE_MAX,fp)==NULL) 
@@ -315,14 +315,14 @@ int main(int argc, char **argv)
                if(cnt%4)
                        cnt+=4-(cnt%4);
                /* store the record length */
-               c_enums->size=((long)&c_enums->text[cnt])-(long)c_enums;
+               c_enums->size=((char *)&c_enums->text[cnt]) - (char *)c_enums;
                /* store the record type */
                c_enums->tag=LB_TAG_OPTION_ENUM;
                /* increment to the next record */
                c_enums=(struct cmos_enums*)&c_enums->text[cnt];
        }
        /* save the enumerations length */
-       enum_length=(long)c_enums-(long)c_enums_start;
+       enum_length= (char *)c_enums - (char *)c_enums_start;
        ct->size=ct->header_length+enum_length+entries_length;
 
        /* Get the checksum records */
index 71a97d1f25e65184b7beeebc4584674a1cff093d..62df48d4348221345d99c122f9d0711ddb1ed837 100644 (file)
@@ -1,5 +1,5 @@
-VERSION:=0.34
-RELEASE_DATE:=4 July 2003
+VERSION:=0.36
+RELEASE_DATE:=10 October 2003
 PACKAGE:=romcc
 
 
@@ -17,6 +17,15 @@ romcc: romcc.c Makefile
 romcc_pg: romcc.c Makefile
        $(CC) $(CFLAGS) $(CPROF_FLAGS) -o $@ $<
 
+LINUX_TESTS=\
+       linux_test1.c \
+       linux_test2.c \
+       linux_test3.c \
+       linux_test4.c \
+       linux_test5.c \
+       linux_test6.c \
+       linux_test7.c \
+
 TESTS=\
        hello_world.c \
        hello_world2.c \
@@ -41,7 +50,6 @@ TESTS=\
        simple_test19.c \
        simple_test20.c \
        simple_test21.c \
-       simple_test22.c \
        simple_test23.c \
        simple_test24.c \
        simple_test25.c \
@@ -49,7 +57,6 @@ TESTS=\
        simple_test27.c \
        simple_test28.c \
        simple_test29.c \
-       simple_test30.c \
        simple_test31.c \
        simple_test32.c \
        simple_test33.c \
@@ -57,8 +64,6 @@ TESTS=\
        simple_test35.c \
        simple_test36.c \
        simple_test37.c \
-       simple_test38.c \
-       simple_test39.c \
        simple_test40.c \
        simple_test41.c \
        simple_test43.c \
@@ -71,43 +76,113 @@ TESTS=\
        simple_test51.c \
        simple_test52.c \
        simple_test53.c \
-       simple_test54.c \
        simple_test55.c \
        simple_test56.c \
-       simple_test59.c \
+       simple_test57.c \
+       simple_test58.c \
+       simple_test60.c \
+       simple_test61.c \
+       simple_test62.c \
+       simple_test63.c \
+       simple_test64.c \
+       simple_test65.c \
+       simple_test66.c \
+       simple_test67.c \
+       simple_test68.c \
        raminit_test.c \
        raminit_test2.c \
        raminit_test3.c \
        raminit_test4.c \
-       raminit_test5.c
+       raminit_test5.c \
+       raminit_test6.c \
+       $(LINUX_TESTS)
 
 FAIL_TESTS = \
        fail_test1.c \
        fail_test2.c \
-       fail_test3.c
+       fail_test3.c \
+       fail_test4.c \
+       fail_test5.c \
 
 TEST_SRCS:=$(patsubst %, tests/%, $(TESTS))
 TEST_ASM:=$(patsubst %.c, tests/%.S, $(TESTS))
+TEST_ASM_O:=$(patsubst %.c, tests/%.S-O, $(TESTS))
+TEST_ASM_O2:=$(patsubst %.c, tests/%.S-O2, $(TESTS))
+TEST_ASM_mmmx     :=$(patsubst %.c, tests/%.S-mmmx, $(TESTS))
+TEST_ASM_msse     :=$(patsubst %.c, tests/%.S-msse, $(TESTS))
+TEST_ASM_mmmx_msse:=$(patsubst %.c, tests/%.S-mmmx-msse, $(TESTS))
+TEST_ASM_O_mmmx     :=$(patsubst %.c, tests/%.S-O-mmmx, $(TESTS))
+TEST_ASM_O_msse     :=$(patsubst %.c, tests/%.S-O-msse, $(TESTS))
+TEST_ASM_O_mmmx_msse:=$(patsubst %.c, tests/%.S-O-mmmx-msse, $(TESTS))
+TEST_ASM_O2_mmmx     :=$(patsubst %.c, tests/%.S-O2-mmmx, $(TESTS))
+TEST_ASM_O2_msse     :=$(patsubst %.c, tests/%.S-O2-msse, $(TESTS))
+TEST_ASM_O2_mmmx_msse:=$(patsubst %.c, tests/%.S-O2-mmmx-msse, $(TESTS))
+TEST_ASM_ALL:= $(TEST_ASM) $(TEST_ASM_O) $(TEST_ASM_O2) $(TEST_ASM_mmmx) $(TEST_ASM_msse) $(TEST_ASM_mmmx_msse) $(TEST_ASM_O_mmmx) $(TEST_ASM_O_msse) $(TEST_ASM_O_mmmx_msse) $(TEST_ASM_O2_mmmx) $(TEST_ASM_O2_msse) $(TEST_ASM_O2_mmmx_msse)
+TEST_ASM_MOST:= $(TEST_ASM_O) $(TEST_ASM_O_mmmx) $(TEST_ASM_O_msse) $(TEST_ASM_O_mmmx_msse) $(TEST_ASM_O2) $(TEST_ASM_O2_mmmx) $(TEST_ASM_O2_msse) $(TEST_ASM_O2_mmmx_msse)
 TEST_OBJ:=$(patsubst %.c, tests/%.o, $(TESTS))
 TEST_ELF:=$(patsubst %.c, tests/%.elf, $(TESTS))
+LINUX_ELF:=$(patsubst %.c, tests/%.elf, $(LINUX_TESTS))
+LINUX_OUT:=$(patsubst %.c, tests/%.out, $(LINUX_TESTS))
 
 FAIL_SRCS:=$(patsubst %, tests/%, $(FAIL_TESTS))
 FAIL_OUT:=$(patsubst %.c, tests/%.out, $(FAIL_TESTS))
 
 
 $(TEST_ASM): %.S: %.c romcc
-       export ALLOC_CHECK_=2; ./romcc -O -mcpu=k8 -o $@ $< > $*.debug
+       export ALLOC_CHECK_=2; ./romcc -o $@ $< > $*.debug
+
+$(TEST_ASM_O): %.S-O: %.c romcc
+       export ALLOC_CHECK_=2; ./romcc -O -o $@ $< > $*.debug
+
+$(TEST_ASM_O2): %.S-O2: %.c romcc
+       export ALLOC_CHECK_=2; ./romcc -O2 -o $@ $< > $*.debug
+
+
+$(TEST_ASM_mmmx): %.S-mmmx: %.c romcc
+       export ALLOC_CHECK_=2; ./romcc -mmmx -o $@ $< > $*.debug
+
+$(TEST_ASM_msse): %.S-msse: %.c romcc
+       export ALLOC_CHECK_=2; ./romcc -msse -o $@ $< > $*.debug
+
+$(TEST_ASM_mmmx_msse): %.S-mmmx-msse: %.c romcc
+       export ALLOC_CHECK_=2; ./romcc -mmmx -msse -o $@ $< > $*.debug
+
+
+$(TEST_ASM_O_mmmx): %.S-O-mmmx: %.c romcc
+       export ALLOC_CHECK_=2; ./romcc -O -mmmx -o $@ $< > $*.debug
+
+$(TEST_ASM_O_msse): %.S-O-msse: %.c romcc
+       export ALLOC_CHECK_=2; ./romcc -O -msse -o $@ $< > $*.debug
+
+$(TEST_ASM_O_mmmx_msse): %.S-O-mmmx-msse: %.c romcc
+       export ALLOC_CHECK_=2; ./romcc -O -mmmx -msse -o $@ $< > $*.debug
+
+
+$(TEST_ASM_O2_mmmx): %.S-O2-mmmx: %.c romcc
+       export ALLOC_CHECK_=2; ./romcc -O2 -mmmx -o $@ $< > $*.debug
+
+$(TEST_ASM_O2_msse): %.S-O2-msse: %.c romcc
+       export ALLOC_CHECK_=2; ./romcc -O2 -msse -o $@ $< > $*.debug
+
+$(TEST_ASM_O2_mmmx_msse): %.S-O2-mmmx-msse: %.c romcc
+       export ALLOC_CHECK_=2; ./romcc -O2 -mmmx -msse -o $@ $< > $*.debug
+
 
 $(FAIL_OUT): %.out: %.c romcc
-       export ALLOC_CHECK_=2; if ./romcc -O -o $*.S $< > $*.debug 2> $@ ; then exit 1 ; else exit 0 ; fi
+       export ALLOC_CHECK_=2; if ./romcc -O2 -o $*.S $< > $*.debug 2> $@ ; then exit 1 ; else exit 0 ; fi
 
-$(TEST_OBJ): %.o: %.S
+$(TEST_OBJ): %.o: %.S-O2-mmmx
        as $< -o $@
 
 $(TEST_ELF): %.elf: %.o tests/ldscript.ld
        ld -T tests/ldscript.ld $< -o $@
 
-test: $(TEST_ELF) $(FAIL_OUT)
+$(LINUX_OUT): %.out: %.elf
+       ./$< > $@
+
+test: $(TEST_ELF) $(FAIL_OUT) $(TEST_ASM_MOST)
+
+run_linux: $(LINUX_OUT)
 
 echo:
        echo "TEST_SRCS=$(TEST_SRCS)"
@@ -119,5 +194,5 @@ echo:
        echo "FAIL_ASM=$(FAIL_ASM)"
 
 clean:
-       rm -f romcc romcc_pg core $(TEST_ASM) $(TEST_OBJ) $(TEST_ELF) tests/*.debug tests/*.debug2 tests/*.gmon.out tests/*.out
+       rm -f romcc romcc_pg core $(TEST_ASM_ALL) $(TEST_OBJ) $(TEST_ELF) tests/*.debug tests/*.debug2 tests/*.gmon.out tests/*.out
 
diff --git a/util/romcc/results/linux_test1.out b/util/romcc/results/linux_test1.out
new file mode 100644 (file)
index 0000000..e139c33
Binary files /dev/null and b/util/romcc/results/linux_test1.out differ
diff --git a/util/romcc/results/linux_test2.out b/util/romcc/results/linux_test2.out
new file mode 100644 (file)
index 0000000..ce61c09
--- /dev/null
@@ -0,0 +1,59 @@
+setting up coherent ht domain....
+0000c040 <-00010101
+0000c044 <-00010101
+0000c048 <-00010101
+0000c04c <-00010101
+0000c050 <-00010101
+0000c054 <-00010101
+0000c058 <-00010101
+0000c05c <-00010101
+0000c068 <-0f00840f
+0000c06c <-00000070
+0000c084 <-11110020
+0000c088 <-00000200
+0000c094 <-00ff0000
+0000c144 <-003f0000
+0000c14c <-00000001
+0000c154 <-00000002
+0000c15c <-00000003
+0000c164 <-00000004
+0000c16c <-00000005
+0000c174 <-00000006
+0000c17c <-00000007
+0000c140 <-00000003
+0000c148 <-00400000
+0000c150 <-00400000
+0000c158 <-00400000
+0000c160 <-00400000
+0000c168 <-00400000
+0000c170 <-00400000
+0000c178 <-00400000
+0000c184 <-00e1ff00
+0000c18c <-00dfff00
+0000c194 <-00e3ff00
+0000c19c <-00000000
+0000c1a4 <-00000000
+0000c1ac <-00000000
+0000c1b4 <-00000b00
+0000c1bc <-00fe0b00
+0000c180 <-00e00003
+0000c188 <-00d80003
+0000c190 <-00e20003
+0000c198 <-00000000
+0000c1a0 <-00000000
+0000c1a8 <-00000000
+0000c1b0 <-00000a03
+0000c1b8 <-00400003
+0000c1c4 <-0000d000
+0000c1cc <-000ff000
+0000c1d4 <-00000000
+0000c1dc <-00000000
+0000c1c0 <-0000d003
+0000c1c8 <-00001013
+0000c1d0 <-00000000
+0000c1d8 <-00000000
+0000c1e0 <-ff000003
+0000c1e4 <-00000000
+0000c1e8 <-00000000
+0000c1ec <-00000000
+done.
diff --git a/util/romcc/results/linux_test3.out b/util/romcc/results/linux_test3.out
new file mode 100644 (file)
index 0000000..06b38ce
--- /dev/null
@@ -0,0 +1,11 @@
+goto_test
+i = 00
+i = 01
+i = 02
+i = 03
+i = 04
+i = 05
+i = 06
+i = 07
+i = 08
+i = 09
diff --git a/util/romcc/results/linux_test4.out b/util/romcc/results/linux_test4.out
new file mode 100644 (file)
index 0000000..5d69fe6
--- /dev/null
@@ -0,0 +1,11 @@
+cpu_socketA
+.up=0002 .down=ffff .across=0001
+.up=0003 .down=ffff .across=0000
+.up=ffff .down=0000 .across=0003
+.up=ffff .down=0001 .across=0002
+
+cpu_socketB
+.up=0002 .down=ffff .across=0001
+.up=0003 .down=ffff .across=0000
+.up=ffff .down=0000 .across=0003
+.up=ffff .down=0001 .across=0002
diff --git a/util/romcc/results/linux_test5.out b/util/romcc/results/linux_test5.out
new file mode 100644 (file)
index 0000000..0c94914
--- /dev/null
@@ -0,0 +1,34 @@
+min_cycle_time: 75 min_latency: 02
+A
+B
+C
+C
+D
+E
+device: 00 new_cycle_time: 75 new_latency: 02
+G
+C
+D
+E
+G
+H
+device: 00 new_cycle_time: 75 new_latency: 02
+I
+device: 00 min_cycle_time: 75 min_latency: 02
+A
+B
+C
+C
+D
+E
+device: 01 new_cycle_time: 75 new_latency: 02
+G
+C
+D
+E
+G
+H
+device: 01 new_cycle_time: 75 new_latency: 02
+I
+device: 01 min_cycle_time: 75 min_latency: 02
+min_cycle_time: 75 min_latency: 02
diff --git a/util/romcc/results/linux_test6.out b/util/romcc/results/linux_test6.out
new file mode 100644 (file)
index 0000000..5978e19
--- /dev/null
@@ -0,0 +1,2 @@
+B
+Registered
diff --git a/util/romcc/results/linux_test7.out b/util/romcc/results/linux_test7.out
new file mode 100644 (file)
index 0000000..9d76d82
--- /dev/null
@@ -0,0 +1,32 @@
+val[00]: 0000c144 0000f8f8 00000000
+val[03]: 0000c14c 0000f8f8 00000001
+val[06]: 0000c154 0000f8f8 00000002
+val[09]: 0000c15c 0000f8f8 00000003
+val[0c]: 0000c164 0000f8f8 00000004
+val[0f]: 0000c16c 0000f8f8 00000005
+val[12]: 0000c174 0000f8f8 00000006
+val[15]: 0000c17c 0000f8f8 00000007
+val[00]: 0000c144 0000f8f8 00000000
+val[03]: 0000c14c 0000f8f8 00000001
+val[06]: 0000c154 0000f8f8 00000002
+val[09]: 0000c15c 0000f8f8 00000003
+val[0c]: 0000c164 0000f8f8 00000004
+val[0f]: 0000c16c 0000f8f8 00000005
+val[12]: 0000c174 0000f8f8 00000006
+val[15]: 0000c17c 0000f8f8 00000007
+val[00]: 0000c144 0000f8f8 00000000
+val[03]: 0000c14c 0000f8f8 00000001
+val[06]: 0000c154 0000f8f8 00000002
+val[09]: 0000c15c 0000f8f8 00000003
+val[0c]: 0000c164 0000f8f8 00000004
+val[0f]: 0000c16c 0000f8f8 00000005
+val[12]: 0000c174 0000f8f8 00000006
+val[15]: 0000c17c 0000f8f8 00000007
+val[00]: 0000c144 0000f8f8 00000000
+val[03]: 0000c14c 0000f8f8 00000001
+val[06]: 0000c154 0000f8f8 00000002
+val[09]: 0000c15c 0000f8f8 00000003
+val[0c]: 0000c164 0000f8f8 00000004
+val[0f]: 0000c16c 0000f8f8 00000005
+val[12]: 0000c174 0000f8f8 00000006
+val[15]: 0000c17c 0000f8f8 00000007
index 2b14506c502719444384cb69ba98b6b850e0c1d4..db7d61131e484400b94f03ada872586e8bb76bc8 100644 (file)
@@ -19,6 +19,7 @@
 #define DEBUG_COALESCING 0
 #define DEBUG_SDP_BLOCKS 0
 #define DEBUG_TRIPLE_COLOR 0
+#define DEBUG_SIMPLIFY 0
 
 #warning "FIXME boundary cases with small types in larger registers"
 #warning "FIXME give clear error messages about unused variables"
@@ -207,14 +208,32 @@ static char *slurp_file(const char *dirname, const char *filename, off_t *r_size
        return buf;
 }
 
-/* Long on the destination platform */
-#ifdef __x86_64__
-typedef unsigned int ulong_t;
-typedef int long_t;
-#else
-typedef unsigned long ulong_t;
-typedef long long_t;
-#endif
+/* Types on the destination platform */
+#warning "FIXME this assumes 32bit x86 is the destination"
+typedef int8_t   schar_t;
+typedef uint8_t  uchar_t;
+typedef int8_t   char_t;
+typedef int16_t  short_t;
+typedef uint16_t ushort_t;
+typedef int32_t  int_t;
+typedef uint32_t uint_t;
+typedef int32_t  long_t;
+typedef uint32_t ulong_t;
+
+#define SCHAR_T_MIN (-128)
+#define SCHAR_T_MAX 127
+#define UCHAR_T_MAX 255
+#define CHAR_T_MIN  SCHAR_T_MIN
+#define CHAR_T_MAX  SCHAR_T_MAX
+#define SHRT_T_MIN  (-32768)
+#define SHRT_T_MAX  32767
+#define USHRT_T_MAX 65535
+#define INT_T_MIN   (-LONG_T_MAX - 1)
+#define INT_T_MAX   2147483647
+#define UINT_T_MAX  4294967295U
+#define LONG_T_MIN  (-LONG_T_MAX - 1)
+#define LONG_T_MAX  2147483647
+#define ULONG_T_MAX 4294967295U
 
 struct file_state {
        struct file_state *prev;
@@ -506,11 +525,12 @@ struct token {
 struct op_info {
        const char *name;
        unsigned flags;
-#define PURE   1
-#define IMPURE 2
+#define PURE   1 /* Triple has no side effects */
+#define IMPURE 2 /* Triple has side effects */
 #define PURE_BITS(FLAGS) ((FLAGS) & 0x3)
-#define DEF    4
+#define DEF    4 /* Triple is a variable definition */
 #define BLOCK  8 /* Triple stores the current block */
+#define STRUCTURAL 16 /* Triple does not generate a machine instruction */
        unsigned char lhs, rhs, misc, targ;
 };
 
@@ -559,16 +579,16 @@ static const struct op_info table_ops[] = {
 [OP_LOAD       ] = OP( 0,  1, 0, 0, IMPURE | DEF | BLOCK, "load"),
 [OP_STORE      ] = OP( 0,  2, 0, 0, IMPURE | BLOCK , "store"),
 
-[OP_NOOP       ] = OP( 0,  0, 0, 0, PURE | BLOCK, "noop"),
+[OP_NOOP       ] = OP( 0,  0, 0, 0, PURE | BLOCK | STRUCTURAL, "noop"),
 
 [OP_INTCONST   ] = OP( 0,  0, 0, 0, PURE | DEF, "intconst"),
-[OP_BLOBCONST  ] = OP( 0,  0, 0, 0, PURE, "blobconst"),
+[OP_BLOBCONST  ] = OP( 0,  0, 0, 0, PURE , "blobconst"),
 [OP_ADDRCONST  ] = OP( 0,  0, 1, 0, PURE | DEF, "addrconst"),
 
 [OP_WRITE      ] = OP( 0,  2, 0, 0, PURE | BLOCK, "write"),
 [OP_READ       ] = OP( 0,  1, 0, 0, PURE | DEF | BLOCK, "read"),
 [OP_COPY       ] = OP( 0,  1, 0, 0, PURE | DEF | BLOCK, "copy"),
-[OP_PIECE      ] = OP( 0,  0, 1, 0, PURE | DEF, "piece"),
+[OP_PIECE      ] = OP( 0,  0, 1, 0, PURE | DEF | STRUCTURAL, "piece"),
 [OP_ASM        ] = OP(-1, -1, 0, 0, IMPURE, "asm"),
 [OP_DEREF      ] = OP( 0,  1, 0, 0, 0 | DEF | BLOCK, "deref"), 
 [OP_DOT        ] = OP( 0,  1, 0, 0, 0 | DEF | BLOCK, "dot"),
@@ -581,14 +601,14 @@ static const struct op_info table_ops[] = {
 /* Call is special most it can stand in for anything so it depends on context */
 [OP_CALL       ] = OP(-1, -1, 1, 0, 0 | BLOCK, "call"),
 /* The sizes of OP_CALL and OP_VAL_VEC depend upon context */
-[OP_VAL_VEC    ] = OP( 0, -1, 0, 0, 0 | BLOCK, "valvec"),
+[OP_VAL_VEC    ] = OP( 0, -1, 0, 0, 0 | BLOCK | STRUCTURAL, "valvec"),
 
-[OP_LIST       ] = OP( 0,  1, 1, 0, 0 | DEF, "list"),
+[OP_LIST       ] = OP( 0,  1, 1, 0, 0 | DEF | STRUCTURAL, "list"),
 /* The number of targets for OP_BRANCH depends on context */
 [OP_BRANCH     ] = OP( 0, -1, 0, 1, PURE | BLOCK, "branch"),
-[OP_LABEL      ] = OP( 0,  0, 0, 0, PURE | BLOCK, "label"),
-[OP_ADECL      ] = OP( 0,  0, 0, 0, PURE | BLOCK, "adecl"),
-[OP_SDECL      ] = OP( 0,  0, 1, 0, PURE | BLOCK, "sdecl"),
+[OP_LABEL      ] = OP( 0,  0, 0, 0, PURE | BLOCK | STRUCTURAL, "label"),
+[OP_ADECL      ] = OP( 0,  0, 0, 0, PURE | BLOCK | STRUCTURAL, "adecl"),
+[OP_SDECL      ] = OP( 0,  0, 1, 0, PURE | BLOCK | STRUCTURAL, "sdecl"),
 /* The number of RHS elements of OP_PHI depend upon context */
 [OP_PHI        ] = OP( 0, -1, 1, 0, PURE | DEF | BLOCK, "phi"),
 
@@ -697,6 +717,8 @@ struct triple {
 #define TRIPLE_FLAG_FLATTENED   (1 << 31)
 #define TRIPLE_FLAG_PRE_SPLIT   (1 << 30)
 #define TRIPLE_FLAG_POST_SPLIT  (1 << 29)
+#define TRIPLE_FLAG_VOLATILE    (1 << 28)
+#define TRIPLE_FLAG_LOCAL      (1 << 27)
        struct occurance *occurance;
        union {
                ulong_t cval;
@@ -762,7 +784,7 @@ struct hash_entry {
        int tok;
        struct macro *sym_define;
        struct symbol *sym_label;
-       struct symbol *sym_struct;
+       struct symbol *sym_tag;
        struct symbol *sym_ident;
 };
 
@@ -777,16 +799,20 @@ struct compile_state {
        const char *function;
        struct token token[4];
        struct hash_entry *hash_table[HASH_TABLE_SIZE];
+       struct hash_entry *i_switch;
+       struct hash_entry *i_case;
        struct hash_entry *i_continue;
        struct hash_entry *i_break;
+       struct hash_entry *i_default;
        int scope_depth;
        int if_depth, if_value;
        int macro_line;
        struct file_state *macro_file;
        struct triple *main_function;
+       struct triple *first;
        struct block *first_block, *last_block;
        int last_vertex;
-       int cpu;
+       unsigned long features;
        int debug;
        int optimize;
 };
@@ -817,12 +843,12 @@ struct compile_state {
 
 #define TYPE_SHIFT         8
 #define TYPE_MASK     0x1f00
-#define TYPE_INTEGER(TYPE)    (((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_ULLONG))
-#define TYPE_ARITHMETIC(TYPE) (((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_LDOUBLE))
+#define TYPE_INTEGER(TYPE)    ((((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_ULLONG)) || ((TYPE) == TYPE_ENUM))
+#define TYPE_ARITHMETIC(TYPE) ((((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_LDOUBLE)) || ((TYPE) == TYPE_ENUM))
 #define TYPE_UNSIGNED(TYPE)   ((TYPE) & 0x0100)
 #define TYPE_SIGNED(TYPE)     (!TYPE_UNSIGNED(TYPE))
-#define TYPE_MKUNSIGNED(TYPE) ((TYPE) | 0x0100)
-#define TYPE_RANK(TYPE)       ((TYPE) & ~0x0100)
+#define TYPE_MKUNSIGNED(TYPE) (((TYPE) & ~0xF000) | 0x0100)
+#define TYPE_RANK(TYPE)       ((TYPE) & ~0xF1FF)
 #define TYPE_PTR(TYPE)        (((TYPE) & TYPE_MASK) == TYPE_POINTER)
 #define TYPE_DEFAULT  0x0000
 #define TYPE_VOID     0x0100
@@ -839,8 +865,17 @@ struct compile_state {
 #define TYPE_FLOAT    0x0c00
 #define TYPE_DOUBLE   0x0d00
 #define TYPE_LDOUBLE  0x0e00 /* long double */
+
+/* Note: TYPE_ENUM is chosen very carefully so TYPE_RANK works */
+#define TYPE_ENUM     0x1600
+#define TYPE_LIST     0x1700
+/* TYPE_LIST is a basic building block when defining enumerations
+ * type->field_ident holds the name of this enumeration entry.
+ * type->right holds the entry in the list.
+ */
+
 #define TYPE_STRUCT   0x1000
-#define TYPE_ENUM     0x1100
+#define TYPE_UNION    0x1100
 #define TYPE_POINTER  0x1200 
 /* For TYPE_POINTER:
  * type->left holds the type pointed to.
@@ -860,17 +895,13 @@ struct compile_state {
  * type->left and type->right holds to types that overlap
  * each other in memory.
  */
-#define TYPE_ARRAY    0x1600
+#define TYPE_ARRAY    0x1800
 /* TYPE_ARRAY is a basic building block when definitng arrays.
  * type->left holds the type we are an array of.
  * type-> holds the number of elements.
  */
 
-#ifdef __x86_64__
-#define ELEMENT_COUNT_UNSPECIFIED (~0U)
-#else
-#define ELEMENT_COUNT_UNSPECIFIED (~0UL)
-#endif
+#define ELEMENT_COUNT_UNSPECIFIED ULONG_T_MAX
 
 struct type {
        unsigned int type;
@@ -880,13 +911,13 @@ struct type {
        struct hash_entry *type_ident;
 };
 
-#define MAX_REGISTERS      75
-#define MAX_REG_EQUIVS     16
-#define REGISTER_BITS      16
-#define MAX_VIRT_REGISTERS (1<<REGISTER_BITS)
 #define TEMPLATE_BITS      7
 #define MAX_TEMPLATES      (1<<TEMPLATE_BITS)
+#define MAX_REG_EQUIVS     16
 #define MAX_REGC           14
+#define MAX_REGISTERS      75
+#define REGISTER_BITS      7
+#define MAX_VIRT_REGISTERS (1<<REGISTER_BITS)
 #define REG_UNSET          0
 #define REG_UNNEEDED       1
 #define REG_VIRT0          (MAX_REGISTERS + 0)
@@ -895,10 +926,17 @@ struct type {
 #define REG_VIRT3          (MAX_REGISTERS + 3)
 #define REG_VIRT4          (MAX_REGISTERS + 4)
 #define REG_VIRT5          (MAX_REGISTERS + 5)
-#define REG_VIRT6          (MAX_REGISTERS + 5)
-#define REG_VIRT7          (MAX_REGISTERS + 5)
-#define REG_VIRT8          (MAX_REGISTERS + 5)
-#define REG_VIRT9          (MAX_REGISTERS + 5)
+#define REG_VIRT6          (MAX_REGISTERS + 6)
+#define REG_VIRT7          (MAX_REGISTERS + 7)
+#define REG_VIRT8          (MAX_REGISTERS + 8)
+#define REG_VIRT9          (MAX_REGISTERS + 9)
+
+#if (MAX_REGISTERS + 9) > MAX_VIRT_REGISTERS
+#error "MAX_VIRT_REGISTERS to small"
+#endif
+#if (MAX_REGC + REGISTER_BITS) > 27
+#error "Too many id bits used"
+#endif
 
 /* Provision for 8 register classes */
 #define REG_SHIFT  0
@@ -999,7 +1037,7 @@ static void loc(FILE *fp, struct compile_state *state, struct triple *triple)
                state->file->report_name, state->file->report_line, col);
 }
 
-static void __internal_error(struct compile_state *state, struct triple *ptr, 
+static void romcc_internal_error(struct compile_state *state, struct triple *ptr, 
        char *fmt, ...)
 {
        va_list args;
@@ -1017,7 +1055,7 @@ static void __internal_error(struct compile_state *state, struct triple *ptr,
 }
 
 
-static void __internal_warning(struct compile_state *state, struct triple *ptr, 
+static void romcc_internal_warning(struct compile_state *state, struct triple *ptr, 
        char *fmt, ...)
 {
        va_list args;
@@ -1034,12 +1072,15 @@ static void __internal_warning(struct compile_state *state, struct triple *ptr,
 
 
 
-static void __error(struct compile_state *state, struct triple *ptr, 
+static void romcc_error(struct compile_state *state, struct triple *ptr, 
        char *fmt, ...)
 {
        va_list args;
        va_start(args, fmt);
        loc(stderr, state, ptr);
+       if (ptr && (state->debug & DEBUG_ABORT_ON_ERROR)) {
+               fprintf(stderr, "%p %s ", ptr, tops(ptr->op));
+       }
        vfprintf(stderr, fmt, args);
        va_end(args);
        fprintf(stderr, "\n");
@@ -1050,7 +1091,7 @@ static void __error(struct compile_state *state, struct triple *ptr,
        exit(1);
 }
 
-static void __warning(struct compile_state *state, struct triple *ptr, 
+static void romcc_warning(struct compile_state *state, struct triple *ptr, 
        char *fmt, ...)
 {
        va_list args;
@@ -1063,15 +1104,15 @@ static void __warning(struct compile_state *state, struct triple *ptr,
 }
 
 #if DEBUG_ERROR_MESSAGES 
-#  define internal_error fprintf(stderr,  "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),__internal_error
-#  define internal_warning fprintf(stderr,  "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),__internal_warning
-#  define error fprintf(stderr, "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),__error
-#  define warning fprintf(stderr, "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),__warning
+#  define internal_error fprintf(stderr,  "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),romcc_internal_error
+#  define internal_warning fprintf(stderr,  "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),romcc_internal_warning
+#  define error fprintf(stderr, "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),romcc_error
+#  define warning fprintf(stderr, "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),romcc_warning
 #else
-#  define internal_error __internal_error
-#  define internal_warning __internal_warning
-#  define error __error
-#  define warning __warning
+#  define internal_error romcc_internal_error
+#  define internal_warning romcc_internal_warning
+#  define error romcc_error
+#  define warning romcc_warning
 #endif
 #define FINISHME() warning(state, 0, "FINISHME @ %s.%s:%d", __FILE__, __func__, __LINE__)
 
@@ -1236,7 +1277,9 @@ static struct occurance *new_occurance(struct compile_state *state)
                (last->col == col) &&
                (last->line == line) &&
                (last->function == function) &&
-               (strcmp(last->filename, filename) == 0)) {
+               ((last->filename == filename) ||
+                       (strcmp(last->filename, filename) == 0))) 
+       {
                get_occurance(last);
                return last;
        }
@@ -1501,7 +1544,10 @@ static struct block *block_of_triple(struct compile_state *state,
        struct triple *ins)
 {
        struct triple *first;
-       first = RHS(state->main_function, 0);
+       if (!ins) {
+               return 0;
+       }
+       first = state->first;
        while(ins != first && !triple_stores_block(state, ins)) {
                if (ins == ins->prev) {
                        internal_error(state, 0, "ins == ins->prev?");
@@ -1591,12 +1637,12 @@ static void display_triple(FILE *fp, struct triple *ins)
        if (ins->op == OP_INTCONST) {
                fprintf(fp, "(%p) %c%c %-7s %-2d %-10s <0x%08lx>         ",
                        ins, pre, post, reg, ins->template_id, tops(ins->op), 
-                       ins->u.cval);
+                       (unsigned long)(ins->u.cval));
        }
        else if (ins->op == OP_ADDRCONST) {
                fprintf(fp, "(%p) %c%c %-7s %-2d %-10s %-10p <0x%08lx>",
                        ins, pre, post, reg, ins->template_id, tops(ins->op), 
-                       MISC(ins, 0), ins->u.cval);
+                       MISC(ins, 0), (unsigned long)(ins->u.cval));
        }
        else {
                int i, count;
@@ -1630,7 +1676,17 @@ static void display_triple(FILE *fp, struct triple *ins)
        fflush(fp);
 }
 
-static int triple_is_pure(struct compile_state *state, struct triple *ins)
+static void display_func(FILE *fp, struct triple *func)
+{
+       struct triple *first, *ins;
+       first = ins = RHS(func, 0);
+       do {
+               display_triple(fp, ins);
+               ins = ins->next;
+       } while(ins != first);
+}
+
+static int triple_is_pure(struct compile_state *state, struct triple *ins, unsigned id)
 {
        /* Does the triple have no side effects.
         * I.e. Rexecuting the triple with the same arguments 
@@ -1643,7 +1699,7 @@ static int triple_is_pure(struct compile_state *state, struct triple *ins)
                internal_error(state, 0, "Purity of %s not known\n",
                        tops(ins->op));
        }
-       return pure == PURE;
+       return (pure == PURE) && !(id & TRIPLE_FLAG_VOLATILE);
 }
 
 static int triple_is_branch(struct compile_state *state, struct triple *ins)
@@ -1685,6 +1741,14 @@ static int triple_is_def(struct compile_state *state, struct triple *ins)
        return is_def;
 }
 
+static int triple_is_structural(struct compile_state *state, struct triple *ins)
+{
+       int is_structural;
+       valid_ins(state, ins);
+       is_structural = (table_ops[ins->op].flags & STRUCTURAL) == STRUCTURAL;
+       return is_structural;
+}
+
 static struct triple **triple_iter(struct compile_state *state,
        size_t count, struct triple **vector,
        struct triple *ins, struct triple **last)
@@ -1807,11 +1871,16 @@ static void release_triple(struct compile_state *state, struct triple *ptr)
        struct block *block;
        /* Make certain the we are not the first or last element of a block */
        block = block_of_triple(state, ptr);
-       if (block && (block->last == ptr)) {
-               block->last = ptr->prev;
-       }
-       if (block && (block->first == ptr)) {
-               block->first = ptr->next;
+       if (block) {
+               if ((block->last == ptr) && (block->first == ptr)) {
+                       block->last = block->first = 0;
+               }
+               else if (block->last == ptr) {
+                       block->last = ptr->prev;
+               }
+               else if (block->first == ptr) {
+                       block->first = ptr->next;
+               }
        }
        /* Remove ptr from use chains where it is the user */
        expr = triple_rhs(state, ptr, 0);
@@ -2240,9 +2309,9 @@ static void end_scope(struct compile_state *state)
                struct hash_entry *entry;
                entry = state->hash_table[i];
                while(entry) {
-                       end_scope_syms(&entry->sym_label,  depth);
-                       end_scope_syms(&entry->sym_struct, depth);
-                       end_scope_syms(&entry->sym_ident,  depth);
+                       end_scope_syms(&entry->sym_label, depth);
+                       end_scope_syms(&entry->sym_tag,   depth);
+                       end_scope_syms(&entry->sym_ident, depth);
                        entry = entry->next;
                }
        }
@@ -2957,19 +3026,17 @@ static long_t mprimary_expr(struct compile_state *state, int index)
                break;
        case TOK_LIT_INT:
        {
+               long lval;
                char *end;
                meat(state, index, TOK_LIT_INT);
                errno = 0;
-               val = strtol(state->token[index].val.str, &end, 0);
-#ifdef __x86_64__
-               if (((val == INT_MIN) || (val == INT_MAX)) &&
-                       (errno == ERANGE)) {
-#else
-               if (((val == LONG_MIN) || (val == LONG_MAX)) &&
-                       (errno == ERANGE)) {
-#endif
+               lval = strtol(state->token[index].val.str, &end, 0);
+               if ((lval > LONG_T_MAX) || (lval < LONG_T_MIN) ||
+                       (((lval == LONG_MIN) || (lval == LONG_MAX)) &&
+                               (errno == ERANGE))) {
                        error(state, 0, "Integer constant to large");
                }
+               val = lval;
                break;
        }
        default:
@@ -3779,6 +3846,12 @@ static struct type uint_type   = { .type  = TYPE_UINT };
 static struct type long_type   = { .type  = TYPE_LONG };
 static struct type ulong_type  = { .type  = TYPE_ULONG };
 
+static struct type void_func   = { 
+       .type  = TYPE_FUNCTION,
+       .left  = &void_type,
+       .right = &void_type,
+};
+
 static struct triple *variable(struct compile_state *state, struct type *type)
 {
        struct triple *result;
@@ -3913,7 +3986,7 @@ static void name_of(FILE *fp, struct type *type)
        }
        case TYPE_ARRAY:
                name_of(fp, type->left);
-               fprintf(fp, " [%ld]", type->elements);
+               fprintf(fp, " [%ld]", (long)(type->elements));
                break;
        default:
                fprintf(fp, "????: %x", type->type & TYPE_MASK);
@@ -4174,8 +4247,8 @@ static void arrays_complete(struct compile_state *state, struct type *type)
 static unsigned int do_integral_promotion(unsigned int type)
 {
        type &= TYPE_MASK;
-       if (TYPE_INTEGER(type) && 
-               TYPE_RANK(type) < TYPE_RANK(TYPE_INT)) {
+       if (type == TYPE_ENUM) type = TYPE_INT;
+       if (TYPE_INTEGER(type) && (TYPE_RANK(type) < TYPE_RANK(TYPE_INT))) {
                type = TYPE_INT;
        }
        return type;
@@ -4186,6 +4259,9 @@ static unsigned int do_arithmetic_conversion(
 {
        left &= TYPE_MASK;
        right &= TYPE_MASK;
+       /* Convert enums to ints */
+       if (left == TYPE_ENUM) left = TYPE_INT;
+       if (right == TYPE_ENUM) right = TYPE_INT;
        if ((left == TYPE_LDOUBLE) || (right == TYPE_LDOUBLE)) {
                return TYPE_LDOUBLE;
        }
@@ -4522,6 +4598,8 @@ static struct triple *int_const(
 }
 
 
+static struct triple *read_expr(struct compile_state *state, struct triple *def);
+
 static struct triple *do_mk_addr_expr(struct compile_state *state, 
        struct triple *expr, struct type *type, ulong_t offset)
 {
@@ -4544,6 +4622,9 @@ static struct triple *do_mk_addr_expr(struct compile_state *state,
                        RHS(expr, 0),
                        int_const(state, &ulong_type, offset));
        }
+       if (!result) {
+               internal_error(state, expr, "cannot take address of expression");
+       }
        return result;
 }
 
@@ -4633,6 +4714,10 @@ static struct triple *read_expr(struct compile_state *state, struct triple *def)
        if (is_in_reg(state, def)) {
                op = OP_READ;
        } else {
+               if (def->op == OP_SDECL) {
+                       def = mk_addr_expr(state, def, 0);
+                       def = mk_deref_expr(state, def);
+               }
                op = OP_LOAD;
        }
        return triple(state, op, def->type, def, 0);
@@ -5040,6 +5125,19 @@ static struct triple *flatten_cond(
        return read_expr(state, val);
 }
 
+static int local_triple(struct compile_state *state, 
+       struct triple *func, struct triple *ins)
+{
+       int local = (ins->id & TRIPLE_FLAG_LOCAL);
+#if 0
+       if (!local) {
+               fprintf(stderr, "global: ");
+               display_triple(stderr, ins);
+       }
+#endif
+       return local;
+}
+
 struct triple *copy_func(struct compile_state *state, struct triple *ofunc, 
        struct occurance *base_occurance)
 {
@@ -5051,7 +5149,7 @@ struct triple *copy_func(struct compile_state *state, struct triple *ofunc,
        fprintf(stdout, "\n");
        loc(stdout, state, 0);
        fprintf(stdout, "\n__________ copy_func _________\n");
-       print_triple(state, ofunc);
+       display_func(stdout, ofunc);
        fprintf(stdout, "__________ copy_func _________ done\n\n");
 #endif
 
@@ -5086,6 +5184,8 @@ struct triple *copy_func(struct compile_state *state, struct triple *ofunc,
                if (old == MISC(ofunc, 0)) {
                        MISC(nfunc, 0) = new;
                }
+               /* Remember which instructions are local */
+               old->id |= TRIPLE_FLAG_LOCAL;
                old = old->next;
        } while(old != ofirst);
 
@@ -5100,8 +5200,13 @@ struct triple *copy_func(struct compile_state *state, struct triple *ofunc,
                for(i = 0; i < count; i++) {
                        oexpr = &old->param[i];
                        nexpr = &new->param[i];
-                       if (!*nexpr && *oexpr && (*oexpr)->use) {
-                               *nexpr = (*oexpr)->use->member;
+                       if (*oexpr && !*nexpr) {
+                               if (!local_triple(state, ofunc, *oexpr)) {
+                                       *nexpr = *oexpr;
+                               }
+                               else if ((*oexpr)->use) {
+                                       *nexpr = (*oexpr)->use->member;
+                               }
                                if (*nexpr == old) {
                                        internal_error(state, 0, "new == old?");
                                }
@@ -5120,6 +5225,8 @@ struct triple *copy_func(struct compile_state *state, struct triple *ofunc,
        new = nfirst;
        do {
                unuse_triple(old, new);
+               /* Forget which instructions are local */
+               old->id &= ~TRIPLE_FLAG_LOCAL;
                old = old->next;
                new = new->next;
        } while ((old != ofirst) && (new != nfirst));
@@ -5169,7 +5276,7 @@ static struct triple *flatten_call(
        fprintf(stdout, "\n");
        loc(stdout, state, 0);
        fprintf(stdout, "\n__________ flatten_call _________\n");
-       print_triple(state, nfunc);
+       display_func(stdout, nfunc);
        fprintf(stdout, "__________ flatten_call _________ done\n\n");
 #endif
 
@@ -5238,8 +5345,9 @@ static struct triple *flatten(
                        }
                        break;
                case OP_BLOBCONST:
-                       insert_triple(state, first, ptr);
+                       insert_triple(state, state->first, ptr);
                        ptr->id |= TRIPLE_FLAG_FLATTENED;
+                       ptr->id &= ~TRIPLE_FLAG_LOCAL;
                        ptr = triple(state, OP_SDECL, ptr->type, ptr, 0);
                        use_triple(MISC(ptr, 0), ptr);
                        break;
@@ -5275,10 +5383,17 @@ static struct triple *flatten(
                        use_triple(ptr, MISC(ptr, 0));
                        break;
                case OP_ADDRCONST:
-               case OP_SDECL:
                        MISC(ptr, 0) = flatten(state, first, MISC(ptr, 0));
                        use_triple(MISC(ptr, 0), ptr);
                        break;
+               case OP_SDECL:
+                       first = state->first;
+                       MISC(ptr, 0) = flatten(state, first, MISC(ptr, 0));
+                       use_triple(MISC(ptr, 0), ptr);
+                       insert_triple(state, first, ptr);
+                       ptr->id |= TRIPLE_FLAG_FLATTENED;
+                       ptr->id &= ~TRIPLE_FLAG_LOCAL;
+                       return ptr;
                case OP_ADECL:
                        break;
                default:
@@ -5290,6 +5405,7 @@ static struct triple *flatten(
        if (ptr) {
                insert_triple(state, first, ptr);
                ptr->id |= TRIPLE_FLAG_FLATTENED;
+               ptr->id &= ~TRIPLE_FLAG_LOCAL;
        }
        return ptr;
 }
@@ -5489,6 +5605,11 @@ static int is_const(struct triple *ins)
        return IS_CONST_OP(ins->op);
 }
 
+static int is_simple_const(struct triple *ins)
+{
+       return IS_CONST_OP(ins->op) && (ins->op != OP_ADDRCONST);
+}
+
 static int constants_equal(struct compile_state *state, 
        struct triple *left, struct triple *right)
 {
@@ -5638,6 +5759,9 @@ static ulong_t read_const(struct compile_state *state,
                internal_error(state, rhs, "bad type to read_const\n");
                break;
        }
+       if (!is_simple_const(rhs)) {
+               internal_error(state, rhs, "bad op to read_const\n");
+       }
        return rhs->u.cval;
 }
 
@@ -5702,9 +5826,12 @@ static void wipe_ins(struct compile_state *state, struct triple *ins)
 static void mkcopy(struct compile_state *state, 
        struct triple *ins, struct triple *rhs)
 {
+       struct block *block;
+       block = block_of_triple(state, ins);
        wipe_ins(state, ins);
        ins->op = OP_COPY;
        ins->sizes = TRIPLE_SIZES(0, 1, 0, 0);
+       ins->u.block = block;
        RHS(ins, 0) = rhs;
        use_triple(RHS(ins, 0), ins);
 }
@@ -5739,7 +5866,7 @@ static void mkaddr_const(struct compile_state *state,
 static void flatten_structures(struct compile_state *state)
 {
        struct triple *ins, *first;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        /* Pass one expand structure values into valvecs.
         */
@@ -6004,6 +6131,7 @@ static void simplify_smod(struct compile_state *state, struct triple *ins)
                RHS(ins, 1) = val;
        }
 }
+
 static void simplify_umod(struct compile_state *state, struct triple *ins)
 {
        if (is_const(RHS(ins, 0)) && is_const(RHS(ins, 1))) {
@@ -6354,7 +6482,8 @@ static void simplify_lfalse(struct compile_state *state, struct triple *ins)
                mkconst(state, ins, left == 0);
        }
        /* Otherwise if I am the only user... */
-       else if ((RHS(ins, 0)->use->member == ins) && (RHS(ins, 0)->use->next == 0)) {
+       else if ((RHS(ins, 0)->use) &&
+               (RHS(ins, 0)->use->member == ins) && (RHS(ins, 0)->use->next == 0)) {
                int need_copy = 1;
                /* Invert a boolean operation */
                switch(RHS(ins, 0)->op) {
@@ -6423,22 +6552,88 @@ static void simplify_copy(struct compile_state *state, struct triple *ins)
        }
 }
 
+static int phi_present(struct block *block)
+{
+       struct triple *ptr;
+       if (!block) {
+               return 0;
+       }
+       ptr = block->first;
+       do {
+               if (ptr->op == OP_PHI) {
+                       return 1;
+               }
+               ptr = ptr->next;
+       } while(ptr != block->last);
+       return 0;
+}
+
+static int phi_dependency(struct block *block)
+{
+       /* A block has a phi dependency if a phi function
+        * depends on that block to exist, and makes a block
+        * that is otherwise useless unsafe to remove.
+        */
+       if (block && (
+                   phi_present(block->left) ||
+                   phi_present(block->right))) {
+               return 1;
+       }
+       return 0;
+}
+
+static struct triple *branch_target(struct compile_state *state, struct triple *ins)
+{
+       struct triple *targ;
+       targ = TARG(ins, 0);
+       /* During scc_transform temporary triples are allocated that
+        * loop back onto themselves. If I see one don't advance the
+        * target.
+        */
+       while(triple_is_structural(state, targ) && (targ->next != targ)) {
+               targ = targ->next;
+       }
+       return targ;
+}
+
+
 static void simplify_branch(struct compile_state *state, struct triple *ins)
 {
-       struct block *block;
+       int simplified;
        if (ins->op != OP_BRANCH) {
                internal_error(state, ins, "not branch");
        }
        if (ins->use != 0) {
                internal_error(state, ins, "branch use");
        }
-#warning "FIXME implement simplify branch."
        /* The challenge here with simplify branch is that I need to 
         * make modifications to the control flow graph as well
-        * as to the branch instruction itself.
+        * as to the branch instruction itself.  That is handled
+        * by rebuilding the basic blocks after simplify all is called.
+        */
+
+       /* If we have a branch to an unconditional branch update
+        * our target.  But watch out for dependencies from phi
+        * functions. 
+        */
+       do {
+               struct triple *targ;
+               simplified = 0;
+               targ = branch_target(state, ins);
+               if ((targ != ins) && triple_is_uncond_branch(state, targ)) {
+                       if (!phi_dependency(targ->u.block)) 
+                       {
+                               unuse_triple(TARG(ins, 0), ins);
+                               TARG(ins, 0) = TARG(targ, 0);
+                               use_triple(TARG(ins, 0), ins);
+                               simplified = 1;
+                       }
+               }
+       } while(simplified);
+
+       /* If we have a conditional branch with a constant condition
+        * make it an unconditional branch.
         */
-       block = ins->u.block;
-       
        if (TRIPLE_RHS(ins->sizes) && is_const(RHS(ins, 0))) {
                struct triple *targ;
                ulong_t value;
@@ -6454,8 +6649,11 @@ static void simplify_branch(struct compile_state *state, struct triple *ins)
                        unuse_triple(targ, ins);
                        TARG(ins, 0) = ins->next;
                }
-#warning "FIXME handle the case of making a branch unconditional"
        }
+       
+       /* If we have an unconditional branch to the next instruction
+        * make it a noop.
+        */
        if (TARG(ins, 0) == ins->next) {
                unuse_triple(ins->next, ins);
                if (TRIPLE_RHS(ins->sizes)) {
@@ -6467,50 +6665,26 @@ static void simplify_branch(struct compile_state *state, struct triple *ins)
                if (ins->use) {
                        internal_error(state, ins, "noop use != 0");
                }
-#warning "FIXME handle the case of killing a branch"
-       }
-}
-
-int phi_present(struct block *block)
-{
-       struct triple *ptr;
-       if (!block) {
-               return 0;
        }
-       ptr = block->first;
-       do {
-               if (ptr->op == OP_PHI) {
-                       return 1;
-               }
-               ptr = ptr->next;
-       } while(ptr != block->last);
-       return 0;
 }
 
 static void simplify_label(struct compile_state *state, struct triple *ins)
 {
-#warning "FIXME enable simplify_label"
-       struct triple *first, *last;
-       first = RHS(state->main_function, 0);
-       last = first->prev;
-       /* Ignore the first and last instructions */
-       if ((ins == first) || (ins == last)) {
+       struct triple *first;
+       first = state->first;
+       /* Ignore volatile labels */
+       if (!triple_is_pure(state, ins, ins->id)) {
                return;
        }
        if (ins->use == 0) {
                ins->op = OP_NOOP;
        }
        else if (ins->prev->op == OP_LABEL) {
-               struct block *block;
-               block = ins->prev->u.block;
                /* In general it is not safe to merge one label that
                 * imediately follows another.  The problem is that the empty
                 * looking block may have phi functions that depend on it.
                 */
-               if (!block || 
-                       (!phi_present(block->left) && 
-                       !phi_present(block->right))) 
-               {
+               if (!phi_dependency(ins->prev->u.block)) {
                        struct triple_set *user, *next;
                        ins->op = OP_NOOP;
                        for(user = ins->use; user; user = next) {
@@ -6532,22 +6706,43 @@ static void simplify_label(struct compile_state *state, struct triple *ins)
 
 static void simplify_phi(struct compile_state *state, struct triple *ins)
 {
-       struct triple **expr;
-       ulong_t value;
-       expr = triple_rhs(state, ins, 0);
-       if (!*expr || !is_const(*expr)) {
+       struct triple **slot;
+       struct triple *value;
+       int zrhs, i;
+       ulong_t cvalue;
+       slot = &RHS(ins, 0);
+       zrhs = TRIPLE_RHS(ins->sizes);
+       if (zrhs == 0) {
                return;
        }
-       value = read_const(state, ins, expr);
-       for(;expr;expr = triple_rhs(state, ins, expr)) {
-               if (!*expr || !is_const(*expr)) {
-                       return;
+       /* See if all of the rhs members of a phi have the same value */
+       if (slot[0] && is_simple_const(slot[0])) {
+               cvalue = read_const(state, ins, &slot[0]);
+               for(i = 1; i < zrhs; i++) {
+                       if (    !slot[i] ||
+                               !is_simple_const(slot[i]) ||
+                               (cvalue != read_const(state, ins, &slot[i]))) {
+                               break;
+                       }
                }
-               if (value != read_const(state, ins, expr)) {
+               if (i == zrhs) {
+                       mkconst(state, ins, cvalue);
                        return;
                }
        }
-       mkconst(state, ins, value);
+       
+       /* See if all of rhs members of a phi are the same */
+       value = slot[0];
+       for(i = 1; i < zrhs; i++) {
+               if (slot[i] != value) {
+                       break;
+               }
+       }
+       if (i == zrhs) {
+               /* If the phi has a single value just copy it */
+               mkcopy(state, ins, value);
+               return;
+       }
 }
 
 
@@ -6634,7 +6829,7 @@ static const simplify_t table_simplify[] = {
 #if 0
 #define simplify_branch          simplify_noop
 #endif
-#if 1
+#if 0
 #define simplify_label   simplify_noop
 #endif
 
@@ -6647,6 +6842,10 @@ static const simplify_t table_simplify[] = {
 #define simplify_bsr      simplify_noop
 #endif
 
+#if 1
+#define simplify_piece    simplify_noop
+#endif
+
 [OP_SDIVT      ] = simplify_sdivt,
 [OP_UDIVT      ] = simplify_udivt,
 [OP_SMUL       ] = simplify_smul,
@@ -6692,7 +6891,7 @@ static const simplify_t table_simplify[] = {
 [OP_WRITE      ] = simplify_noop,
 [OP_READ       ] = simplify_noop,
 [OP_COPY       ] = simplify_copy,
-[OP_PIECE      ] = simplify_noop,
+[OP_PIECE      ] = simplify_piece,
 [OP_ASM        ] = simplify_noop,
 
 [OP_DOT        ] = simplify_noop,
@@ -6736,14 +6935,66 @@ static void simplify(struct compile_state *state, struct triple *ins)
                                op, tops(op));
                        return;
                }
+#if !DEBUG_SIMPLIFY
                do_simplify(state, ins);
+#else
+               {
+                       struct triple *dup;
+                       int ins_count, dup_count;
+                       dup = dup_triple(state, ins);
+                       do_simplify(state, ins);
+                       ins_count = TRIPLE_SIZE(ins->sizes);
+                       dup_count = TRIPLE_SIZE(dup->sizes);
+                       if ((dup->op != ins->op) ||
+                               (ins_count != dup_count) ||
+                               (memcmp(dup->param, ins->param, 
+                                       dup_count * sizeof(dup->param[0])) != 0) ||
+                               (memcmp(&dup->u, &ins->u, sizeof(ins->u)) != 0)) 
+                       {
+                               int i, min_count;
+                               fprintf(stderr, "simplify: %11p", ins);
+                               if (dup->op == ins->op) {
+                                       fprintf(stderr, " %-11s", tops(ins->op));
+                               } else {
+                                       fprintf(stderr, " [%-10s %-10s]", 
+                                               tops(dup->op), tops(ins->op));
+                               }
+                               min_count = dup_count;
+                               if (min_count > ins_count) {
+                                       min_count = ins_count;
+                               }
+                               for(i = 0; i < min_count; i++) {
+                                       if (dup->param[i] == ins->param[i]) {
+                                               fprintf(stderr, " %-11p", ins->param[i]);
+                                       } else {
+                                               fprintf(stderr, " [%-10p %-10p]",
+                                                       dup->param[i], ins->param[i]);
+                                       }
+                               }
+                               for(; i < ins_count; i++) {
+                                       fprintf(stderr, " [%-9p]", ins->param[i]);
+                               }
+                               for(; i < dup_count; i++) {
+                                       fprintf(stderr, " [%-9p]", dup->param[i]);
+                               }
+                               fprintf(stderr, "\n");
+                               fflush(stderr);
+                       }
+                       xfree(dup);
+               }
+#endif
        } while(ins->op != op);
 }
 
 static void simplify_all(struct compile_state *state)
 {
        struct triple *ins, *first;
-       first = RHS(state->main_function, 0);
+       first = state->first;
+       ins = first->prev;
+       do {
+               simplify(state, ins);
+               ins = ins->prev;
+       } while(ins != first->prev);
        ins = first;
        do {
                simplify(state, ins);
@@ -6913,7 +7164,7 @@ static struct type *register_builtin_type(struct compile_state *state,
                        field = field->right;
                }
                elements++;
-               symbol(state, ident, &ident->sym_struct, 0, type);
+               symbol(state, ident, &ident->sym_tag, 0, type);
                type->type_ident = ident;
                type->elements = elements;
        }
@@ -7115,11 +7366,7 @@ static struct triple *integer_constant(struct compile_state *state)
        errno = 0;
        decimal = (tk->val.str[0] != '0');
        val = strtoul(tk->val.str, &end, 0);
-#ifdef __x86_64__
-       if ((val == UINT_MAX) && (errno == ERANGE)) {
-#else
-       if ((val == ULONG_MAX) && (errno == ERANGE)) {
-#endif
+       if ((val > ULONG_T_MAX) || ((val == ULONG_MAX) && (errno == ERANGE))) {
                error(state, 0, "Integer constant to large");
        }
        u = l = 0;
@@ -7143,33 +7390,25 @@ static struct triple *integer_constant(struct compile_state *state)
        }
        else if (l) {
                type = &long_type;
-#ifdef __x86_64__
-               if (!decimal && (val > INT_MAX)) {
-#else
-               if (!decimal && (val > LONG_MAX)) {
-#endif
+               if (!decimal && (val > LONG_T_MAX)) {
                        type = &ulong_type;
                }
        }
        else if (u) {
                type = &uint_type;
-               if (val > UINT_MAX) {
+               if (val > UINT_T_MAX) {
                        type = &ulong_type;
                }
        }
        else {
                type = &int_type;
-               if (!decimal && (val > INT_MAX) && (val <= UINT_MAX)) {
+               if (!decimal && (val > INT_T_MAX) && (val <= UINT_T_MAX)) {
                        type = &uint_type;
                }
-#ifdef __x86_64__
-               else if (!decimal && (val > INT_MAX)) {
-#else
-               else if (!decimal && (val > LONG_MAX)) {
-#endif
+               else if (!decimal && (val > LONG_T_MAX)) {
                        type = &ulong_type;
                }
-               else if (val > INT_MAX) {
+               else if (val > INT_T_MAX) {
                        type = &long_type;
                }
        }
@@ -7189,7 +7428,6 @@ static struct triple *primary_expr(struct compile_state *state)
                /* Here ident is either:
                 * a varable name
                 * a function name
-                * an enumeration constant.
                 */
                eat(state, TOK_IDENT);
                ident = state->token[0].ident;
@@ -7200,11 +7438,17 @@ static struct triple *primary_expr(struct compile_state *state)
                break;
        }
        case TOK_ENUM_CONST:
+       {
+               struct hash_entry *ident;
                /* Here ident is an enumeration constant */
                eat(state, TOK_ENUM_CONST);
-               def = 0;
-               FINISHME();
+               ident = state->token[0].ident;
+               if (!ident->sym_ident) {
+                       error(state, 0, "%s undeclared", ident->name);
+               }
+               def = ident->sym_ident->def;
                break;
+       }
        case TOK_LPAREN:
                eat(state, TOK_LPAREN);
                def = expr(state);
@@ -8106,35 +8350,113 @@ static void labeled_statement(struct compile_state *state, struct triple *first)
 
 static void switch_statement(struct compile_state *state, struct triple *first)
 {
-       FINISHME();
+       struct triple *value, *top, *end, *dbranch;
+       struct hash_entry *ident;
+
+       /* See if we have a valid switch statement */
        eat(state, TOK_SWITCH);
        eat(state, TOK_LPAREN);
-       expr(state);
+       value = expr(state);
+       integral(state, value);
+       value = read_expr(state, value);
        eat(state, TOK_RPAREN);
+       /* Generate the needed pieces */
+       top = label(state);
+       end = label(state);
+       dbranch = branch(state, end, 0);
+       /* Remember where case branches and break goes */
+       start_scope(state);
+       ident = state->i_switch;
+       symbol(state, ident, &ident->sym_ident, value, value->type);
+       ident = state->i_case;
+       symbol(state, ident, &ident->sym_ident, top, top->type);
+       ident = state->i_break;
+       symbol(state, ident, &ident->sym_ident, end, end->type);
+       ident = state->i_default;
+       symbol(state, ident, &ident->sym_ident, dbranch, dbranch->type);
+       /* Thread them together */
+       flatten(state, first, value);
+       flatten(state, first, top);
+       flatten(state, first, dbranch);
        statement(state, first);
-       error(state, 0, "switch statements are not implemented");
-       FINISHME();
+       flatten(state, first, end);
+       /* Cleanup the switch scope */
+       end_scope(state);
 }
 
 static void case_statement(struct compile_state *state, struct triple *first)
 {
-       FINISHME();
+       struct triple *cvalue, *dest, *test, *jmp;
+       struct triple *ptr, *value, *top, *dbranch;
+
+       /* See if w have a valid case statement */
        eat(state, TOK_CASE);
-       constant_expr(state);
+       cvalue = constant_expr(state);
+       integral(state, cvalue);
+       if (cvalue->op != OP_INTCONST) {
+               error(state, 0, "integer constant expected");
+       }
        eat(state, TOK_COLON);
+       if (!state->i_case->sym_ident) {
+               error(state, 0, "case statement not within a switch");
+       }
+
+       /* Lookup the interesting pieces */
+       top = state->i_case->sym_ident->def;
+       value = state->i_switch->sym_ident->def;
+       dbranch = state->i_default->sym_ident->def;
+
+       /* See if this case label has already been used */
+       for(ptr = top; ptr != dbranch; ptr = ptr->next) {
+               if (ptr->op != OP_EQ) {
+                       continue;
+               }
+               if (RHS(ptr, 1)->u.cval == cvalue->u.cval) {
+                       error(state, 0, "duplicate case %d statement",
+                               cvalue->u.cval);
+               }
+       }
+       /* Generate the needed pieces */
+       dest = label(state);
+       test = triple(state, OP_EQ, &int_type, value, cvalue);
+       jmp = branch(state, dest, test);
+       /* Thread the pieces together */
+       flatten(state, dbranch, test);
+       flatten(state, dbranch, jmp);
+       flatten(state, dbranch, label(state));
+       flatten(state, first, dest);
        statement(state, first);
-       error(state, 0, "case statements are not implemented");
-       FINISHME();
 }
 
 static void default_statement(struct compile_state *state, struct triple *first)
 {
-       FINISHME();
+       struct triple *dest;
+       struct triple *dbranch, *end;
+
+       /* See if we have a valid default statement */
        eat(state, TOK_DEFAULT);
        eat(state, TOK_COLON);
+
+       if (!state->i_case->sym_ident) {
+               error(state, 0, "default statement not within a switch");
+       }
+
+       /* Lookup the interesting pieces */
+       dbranch = state->i_default->sym_ident->def;
+       end = state->i_break->sym_ident->def;
+
+       /* See if a default statement has already happened */
+       if (TARG(dbranch, 0) != end) {
+               error(state, 0, "duplicate default statement");
+       }
+
+       /* Generate the needed pieces */
+       dest = label(state);
+
+       /* Thread the pieces together */
+       TARG(dbranch, 0) = dest;
+       flatten(state, first, dest);
        statement(state, first);
-       error(state, 0, "default statements are not implemented");
-       FINISHME();
 }
 
 static void asm_statement(struct compile_state *state, struct triple *first)
@@ -8577,33 +8899,71 @@ static struct type *typedef_name(
 }
 
 static struct type *enum_specifier(
-       struct compile_state *state, unsigned int specifiers)
+       struct compile_state *state, unsigned int spec)
 {
+       struct hash_entry *ident;
+       ulong_t base;
        int tok;
-       struct type *type;
-       type = 0;
-       FINISHME();
+       struct type *enum_type;
+       enum_type = 0;
+       ident = 0;
        eat(state, TOK_ENUM);
        tok = peek(state);
-       if (tok == TOK_IDENT) {
-               eat(state, TOK_IDENT);
+       if ((tok == TOK_IDENT) || (tok == TOK_ENUM_CONST) || (tok == TOK_TYPE_NAME)) {
+               eat(state, tok);
+               ident = state->token[0].ident;
+               
        }
-       if ((tok != TOK_IDENT) || (peek(state) == TOK_LBRACE)) {
+       base = 0;
+       if (!ident || (peek(state) == TOK_LBRACE)) {
+               struct type **next;
                eat(state, TOK_LBRACE);
+               enum_type = new_type(TYPE_ENUM | spec, 0, 0);
+               enum_type->type_ident = ident;
+               next = &enum_type->right;
                do {
+                       struct hash_entry *eident;
+                       struct triple *value;
+                       struct type *entry;
                        eat(state, TOK_IDENT);
+                       eident = state->token[0].ident;
+                       if (eident->sym_ident) {
+                               error(state, 0, "%s already declared", 
+                                       eident->name);
+                       }
+                       eident->tok = TOK_ENUM_CONST;
                        if (peek(state) == TOK_EQ) {
+                               struct triple *val;
                                eat(state, TOK_EQ);
-                               constant_expr(state);
-                       }
+                               val = constant_expr(state);
+                               integral(state, val);
+                               base = val->u.cval;
+                       }
+                       value = int_const(state, &int_type, base);
+                       symbol(state, eident, &eident->sym_ident, value, &int_type);
+                       entry = new_type(TYPE_LIST, 0, 0);
+                       entry->field_ident = eident;
+                       *next = entry;
+                       next = &entry->right;
+                       base += 1;
                        if (peek(state) == TOK_COMMA) {
                                eat(state, TOK_COMMA);
                        }
                } while(peek(state) != TOK_RBRACE);
                eat(state, TOK_RBRACE);
+               if (ident) {
+                       symbol(state, ident, &ident->sym_tag, 0, enum_type);
+               }
        }
-       FINISHME();
-       return type;
+       if (ident && ident->sym_tag &&
+               ident->sym_tag->type &&
+               ((ident->sym_tag->type->type & TYPE_MASK) == TYPE_ENUM)) {
+               enum_type = clone_type(spec, ident->sym_tag->type);
+       }
+       else if (ident && !enum_type) {
+               error(state, 0, "enum %s undeclared", ident->name);
+       }
+       return enum_type;
 }
 
 static struct type *struct_declarator(
@@ -8649,7 +9009,7 @@ static struct type *struct_or_union_specifier(
                break;
        }
        tok = peek(state);
-       if ((tok == TOK_IDENT) || (tok == TOK_TYPE_NAME)) {
+       if ((tok == TOK_IDENT) || (tok == TOK_ENUM_CONST) || (tok == TOK_TYPE_NAME)) {
                eat(state, tok);
                ident = state->token[0].ident;
        }
@@ -8689,13 +9049,15 @@ static struct type *struct_or_union_specifier(
                struct_type->type_ident = ident;
                struct_type->elements = elements;
                if (ident) {
-                       symbol(state, ident, &ident->sym_struct, 0, struct_type);
+                       symbol(state, ident, &ident->sym_tag, 0, struct_type);
                }
        }
-       if (ident && ident->sym_struct) {
-               struct_type = clone_type(spec,  ident->sym_struct->type);
+       if (ident && ident->sym_tag && 
+               ident->sym_tag->type && 
+               ((ident->sym_tag->type->type & TYPE_MASK) == TYPE_STRUCT)) {
+               struct_type = clone_type(spec, ident->sym_tag->type);
        }
-       else if (ident && !ident->sym_struct) {
+       else if (ident && !struct_type) {
                error(state, 0, "struct %s undeclared", ident->name);
        }
        return struct_type;
@@ -9078,7 +9440,6 @@ static struct triple *initializer(
        struct compile_state *state, struct type *type)
 {
        struct triple *result;
-#warning "FIXME handle string pointer initializers "
 #warning "FIXME more consistent initializer handling (where should eval_const_expr go?"
        if (peek(state) != TOK_LBRACE) {
                result = assignment_expr(state);
@@ -9089,6 +9450,12 @@ static struct triple *initializer(
                        (equiv_types(type->left, result->type->left))) {
                        type->elements = result->type->elements;
                }
+               if (is_stable(state, result) && 
+                       ((result->type->type & TYPE_MASK) == TYPE_ARRAY) &&
+                       (type->type & TYPE_MASK) != TYPE_ARRAY)
+               {
+                       result = array_to_pointer(state, result);
+               }
                if (!is_init_compatible(state, type, result->type)) {
                        error(state, 0, "Incompatible types in initializer");
                }
@@ -9423,19 +9790,19 @@ static void decls(struct compile_state *state)
  * Data structurs for optimation.
  */
 
-static void do_use_block(
+static int do_use_block(
        struct block *used, struct block_set **head, struct block *user, 
        int front)
 {
        struct block_set **ptr, *new;
        if (!used)
-               return;
+               return 0;
        if (!user)
-               return;
+               return 0;
        ptr = head;
        while(*ptr) {
                if ((*ptr)->member == user) {
-                       return;
+                       return 0;
                }
                ptr = &(*ptr)->next;
        }
@@ -9449,11 +9816,14 @@ static void do_use_block(
                new->next = 0;
                *ptr = new;
        }
+       return 1;
 }
-static void do_unuse_block(
+static int do_unuse_block(
        struct block *used, struct block_set **head, struct block *unuser)
 {
        struct block_set *use, **ptr;
+       int count;
+       count = 0;
        ptr = head;
        while(*ptr) {
                use = *ptr;
@@ -9461,25 +9831,29 @@ static void do_unuse_block(
                        *ptr = use->next;
                        memset(use, -1, sizeof(*use));
                        xfree(use);
+                       count += 1;
                }
                else {
                        ptr = &use->next;
                }
        }
+       return count;
 }
 
 static void use_block(struct block *used, struct block *user)
 {
+       int count;
        /* Append new to the head of the list, print_block
         * depends on this.
         */
-       do_use_block(used, &used->use, user, 1); 
-       used->users++;
+       count = do_use_block(used, &used->use, user, 1); 
+       used->users += count;
 }
 static void unuse_block(struct block *used, struct block *unuser)
 {
-       do_unuse_block(used, &used->use, unuser); 
-       used->users--;
+       int count;
+       count = do_unuse_block(used, &used->use, unuser); 
+       used->users -= count;
 }
 
 static void idom_block(struct block *idom, struct block *user)
@@ -9522,48 +9896,25 @@ static void unipdomf_block(struct block *block, struct block *unipdomf)
        do_unuse_block(block, &block->ipdomfrontier, unipdomf);
 }
 
-
-
-static int do_walk_triple(struct compile_state *state,
-       struct triple *ptr, int depth,
-       int (*cb)(struct compile_state *state, struct triple *ptr, int depth)) 
+static int walk_triples(
+       struct compile_state *state, 
+       int (*cb)(struct compile_state *state, struct triple *ptr))
 {
+       struct triple *ptr;
        int result;
-       result = cb(state, ptr, depth);
-       if ((result == 0) && (ptr->op == OP_LIST)) {
-               struct triple *list;
-               list = ptr;
-               ptr = RHS(list, 0);
-               do {
-                       result = do_walk_triple(state, ptr, depth + 1, cb);
-                       if (ptr->next->prev != ptr) {
-                               internal_error(state, ptr->next, "bad prev");
-                       }
-                       ptr = ptr->next;
-                       
-               } while((result == 0) && (ptr != RHS(list, 0)));
-       }
-       return result;
-}
-
-static int walk_triple(
-       struct compile_state *state, 
-       struct triple *ptr, 
-       int (*cb)(struct compile_state *state, struct triple *ptr, int depth))
-{
-       return do_walk_triple(state, ptr, 0, cb);
-}
-
-static void do_print_prefix(int depth)
-{
-       int i;
-       for(i = 0; i < depth; i++) {
-               printf("  ");
-       }
+       ptr = state->first;
+       do {
+               result = cb(state, ptr);
+               if (ptr->next->prev != ptr) {
+                       internal_error(state, ptr->next, "bad prev");
+               }
+               ptr = ptr->next;
+       } while((result == 0) && (ptr != state->first));
+       return result;
 }
 
 #define PRINT_LIST 1
-static int do_print_triple(struct compile_state *state, struct triple *ins, int depth)
+static int do_print_triple(struct compile_state *state, struct triple *ins)
 {
        int op;
        op = ins->op;
@@ -9575,7 +9926,6 @@ static int do_print_triple(struct compile_state *state, struct triple *ins, int
        if ((op == OP_LABEL) && (ins->use)) {
                printf("\n%p:\n", ins);
        }
-       do_print_prefix(depth);
        display_triple(stdout, ins);
 
        if ((ins->op == OP_BRANCH) && ins->use) {
@@ -9587,14 +9937,9 @@ static int do_print_triple(struct compile_state *state, struct triple *ins, int
        return 0;
 }
 
-static void print_triple(struct compile_state *state, struct triple *ins)
-{
-       walk_triple(state, ins, do_print_triple);
-}
-
 static void print_triples(struct compile_state *state)
 {
-       print_triple(state, state->main_function);
+       walk_triples(state, do_print_triple);
 }
 
 struct cf_block {
@@ -9641,8 +9986,7 @@ static struct block *basic_block(struct compile_state *state,
        struct triple *first)
 {
        struct block *block;
-       struct triple *ptr, *final;
-       int op;
+       struct triple *ptr;
        if (first->op != OP_LABEL) {
                internal_error(state, 0, "block does not start with a label");
        }
@@ -9650,11 +9994,6 @@ static struct block *basic_block(struct compile_state *state,
        if (first->u.block != 0) {
                return first->u.block;
        }
-       /* Lookup the final instruction.
-        * It is important that the final instruction has it's own
-        * basic block.
-        */
-       final = RHS(state->main_function, 0)->prev;
        /* Allocate another basic block structure */
        state->last_vertex += 1;
        block = xcmalloc(sizeof(*block), "block");
@@ -9662,8 +10001,7 @@ static struct block *basic_block(struct compile_state *state,
        block->vertex = state->last_vertex;
        ptr = first;
        do {
-               if ((ptr != first) && (ptr->op == OP_LABEL) && 
-                       ((ptr->use) || ptr == final)) {
+               if ((ptr != first) && (ptr->op == OP_LABEL) && (ptr->use)) { 
                        break;
                }
                block->last = ptr;
@@ -9671,20 +10009,20 @@ static struct block *basic_block(struct compile_state *state,
                if (triple_stores_block(state, ptr)) {
                        ptr->u.block = block;
                }
-               if (ptr->op == OP_BRANCH) {
+               if (triple_is_branch(state, ptr)) {
                        break;
                }
                ptr = ptr->next;
-       } while (ptr != RHS(state->main_function, 0));
-       if (ptr == RHS(state->main_function, 0))
-               return block;
-       op = ptr->op;
-       if (op == OP_LABEL) {
+       } while (ptr != state->first);
+       if (ptr == state->first) {
+               /* The block has no outflowing edges */
+       }
+       else if (ptr->op == OP_LABEL) {
                block->left = basic_block(state, ptr);
                block->right = 0;
                use_block(block->left, block);
        }
-       else if (op == OP_BRANCH) {
+       else if (triple_is_branch(state, ptr)) {
                block->left = 0;
                /* Trace the branch target */
                block->right = basic_block(state, TARG(ptr, 0));
@@ -9698,6 +10036,15 @@ static struct block *basic_block(struct compile_state *state,
        else {
                internal_error(state, 0, "Bad basic block split");
        }
+#if 0
+       fprintf(stderr, "basic_block: %10p [%2d] ( %10p - %10p ) %10p [%2d] %10p [%2d] \n",
+               block, block->vertex, 
+               block->first, block->last,
+               block->left ? block->left->first : 0,
+               block->left ? block->left->vertex : -1,
+               block->left ? block->left->first : 0,
+               block->left ? block->left->vertex : -1);
+#endif
        return block;
 }
 
@@ -9709,7 +10056,7 @@ static void walk_blocks(struct compile_state *state,
        struct triple *ptr, *first;
        struct block *last_block;
        last_block = 0;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ptr = first;
        do {
                struct block *block;
@@ -9770,7 +10117,7 @@ static void prune_nonblock_triples(struct compile_state *state)
        struct block *block;
        struct triple *first, *ins, *next;
        /* Delete the triples not in a basic block */
-       first = RHS(state->main_function, 0);
+       first = state->first;
        block = 0;
        ins = first;
        do {
@@ -9790,20 +10137,43 @@ static void prune_nonblock_triples(struct compile_state *state)
 
 static void setup_basic_blocks(struct compile_state *state)
 {
-       if (!triple_stores_block(state, RHS(state->main_function, 0)) ||
-               !triple_stores_block(state, RHS(state->main_function,0)->prev)) {
+       if (!triple_stores_block(state, state->first)) {
                internal_error(state, 0, "ins will not store block?");
        }
        /* Find the basic blocks */
        state->last_vertex = 0;
-       state->first_block = basic_block(state, RHS(state->main_function,0));
+       state->first_block = basic_block(state, state->first);
        /* Delete the triples not in a basic block */
        prune_nonblock_triples(state);
-       /* Find the last basic block */
-       state->last_block = RHS(state->main_function, 0)->prev->u.block;
-       if (!state->last_block) {
-               internal_error(state, 0, "end not used?");
+
+       /* Find the last basic block.
+        *
+        * For purposes of reverse flow computation it is
+        * important that the last basic block is empty.
+        * This allows the control flow graph to be modified to
+        * have one unique starting block and one unique final block.
+        * With the insertion of a few extra edges.
+        *
+        * If the final block contained instructions it could contain
+        * phi functions from edges that would never contribute a
+        * value.  Which for now at least I consider a compile error.
+        */
+       state->last_block = block_of_triple(state, state->first->prev);
+       if ((state->last_block->first != state->last_block->last) ||
+               (state->last_block->last->op != OP_LABEL))
+       {
+               struct block *block, *prev_block;
+               struct triple *final;
+               prev_block = state->last_block;
+               final = label(state);
+               flatten(state, state->first, final);
+               use_triple(final, final);
+               block = basic_block(state, final);
+               state->last_block = block;
+               prev_block->left = block;
+               use_block(prev_block->left, prev_block);
        }
+
        /* If we are debugging print what I have just done */
        if (state->debug & DEBUG_BASIC_BLOCKS) {
                print_blocks(state, stdout);
@@ -9886,7 +10256,7 @@ static void free_basic_blocks(struct compile_state *state)
        free_basic_block(state, state->first_block);
        state->last_vertex = 0;
        state->first_block = state->last_block = 0;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                if (triple_stores_block(state, ins)) {
@@ -9955,7 +10325,7 @@ static int initialize_sdblock(struct sdom_block *sd,
        return vertex;
 }
 
-static int initialize_sdpblock(
+static int initialize_spdblock(
        struct compile_state *state, struct sdom_block *sd,
        struct block *parent, struct block *block, int vertex)
 {
@@ -9973,24 +10343,24 @@ static int initialize_sdpblock(
        sd[vertex].ancestor = 0;
        sd[vertex].vertex   = vertex;
        for(user = block->use; user; user = user->next) {
-               vertex = initialize_sdpblock(state, sd, block, user->member, vertex);
+               vertex = initialize_spdblock(state, sd, block, user->member, vertex);
        }
        return vertex;
 }
 
-static int setup_sdpblocks(struct compile_state *state, struct sdom_block *sd)
+static int setup_spdblocks(struct compile_state *state, struct sdom_block *sd)
 {
        struct block *block;
        int vertex;
        /* Setup as many sdpblocks as possible without using fake edges */
-       vertex = initialize_sdpblock(state, sd, 0, state->last_block, 0);
+       vertex = initialize_spdblock(state, sd, 0, state->last_block, 0);
 
        /* Walk through the graph and find unconnected blocks.  If 
         * we can, add a fake edge from the unconnected blocks to the
         * end of the graph.
         */
        block = state->first_block->last->next->u.block;
-       for(; block && block != state->first_block; block =  block->last->next->u.block) {
+       for(; block && block != state->first_block; block = block->last->next->u.block) {
                if (sd[block->vertex].block == block) {
                        continue;
                }
@@ -10004,7 +10374,7 @@ static int setup_sdpblocks(struct compile_state *state, struct sdom_block *sd)
 
                block->left = state->last_block;
                use_block(block->left, block);
-               vertex = initialize_sdpblock(state, sd, state->last_block, block, vertex);
+               vertex = initialize_spdblock(state, sd, state->last_block, block, vertex);
        }
        return vertex;
 }
@@ -10248,7 +10618,7 @@ static void find_post_dominators(struct compile_state *state)
        /* Step 1 initialize the basic block information */
        sd = xcmalloc(sizeof(*sd) * (state->last_vertex + 1), "sdom_state");
 
-       vertex = setup_sdpblocks(state, sd);
+       vertex = setup_spdblocks(state, sd);
        if (vertex != state->last_vertex) {
                internal_error(state, 0, "missing %d blocks\n",
                        state->last_vertex - vertex);
@@ -10309,13 +10679,12 @@ static void find_block_ipdomf(struct compile_state *state, struct block *block)
                }
                find_block_ipdomf(state, child);
        }
-       if (block->left && block->left->ipdom != block) {
-               ipdomf_block(block, block->left);
-       }
-       if (block->right && block->right->ipdom != block) {
-               ipdomf_block(block, block->right);
+       for(user = block->use; user; user = user->next) {
+               if (user->member->ipdom != block) {
+                       ipdomf_block(block, user->member);
+               }
        }
-       for(user = block->idominates; user; user = user->next) {
+       for(user = block->ipdominates; user; user = user->next) {
                struct block_set *frontier;
                child = user->member;
                for(frontier = child->ipdomfrontier; frontier; frontier = frontier->next) {
@@ -10485,6 +10854,13 @@ static int tdominates(struct compile_state *state,
        return result;
 }
 
+static void analyze_basic_blocks(struct compile_state *state)
+{
+       setup_basic_blocks(state);
+       analyze_idominators(state);
+       analyze_ipdominators(state);
+}
+
 static void insert_phi_operations(struct compile_state *state)
 {
        size_t size;
@@ -10499,7 +10875,7 @@ static void insert_phi_operations(struct compile_state *state)
        work =        xcmalloc(size, "work");
        iter = 0;
 
-       first = RHS(state->main_function, 0);
+       first = state->first;
        for(var = first->next; var != first ; var = vnext) {
                struct block *block;
                struct triple_set *user, *unext;
@@ -10560,6 +10936,7 @@ static void insert_phi_operations(struct compile_state *state)
                                        front->last = front->first->next;
                                }
                                has_already[front->vertex] = iter;
+                               transform_to_arch_instruction(state, phi);
 
                                /* If necessary plan to visit the basic block */
                                if (work[front->vertex] >= iter) {
@@ -10577,35 +10954,68 @@ static void insert_phi_operations(struct compile_state *state)
 }
 
 
-static int count_and_number_adecls(struct compile_state *state)
+struct stack {
+       struct triple_set *top;
+       unsigned orig_id;
+};
+
+static int count_adecls(struct compile_state *state)
 {
        struct triple *first, *ins;
        int adecls = 0;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                if (ins->op == OP_ADECL) {
                        adecls += 1;
-                       ins->id = adecls;
                }
                ins = ins->next;
        } while(ins != first);
        return adecls;
 }
 
-static struct triple *peek_triple(struct triple_set **stacks, struct triple *var)
+static void number_adecls(struct compile_state *state, struct stack *stacks)
+{
+       struct triple *first, *ins;
+       int adecls = 0;
+       first = state->first;
+       ins = first;
+       do {
+               if (ins->op == OP_ADECL) {
+                       adecls += 1;
+                       stacks[adecls].orig_id = ins->id;
+                       ins->id = adecls;
+               }
+               ins = ins->next;
+       } while(ins != first);
+}
+
+static void restore_adecls(struct compile_state *state, struct stack *stacks)
+{
+       struct triple *first, *ins;
+       first = state->first;
+       ins = first;
+       do {
+               if (ins->op == OP_ADECL) {
+                       ins->id = stacks[ins->id].orig_id;
+               }
+               ins = ins->next;
+       } while(ins != first);
+}
+
+static struct triple *peek_triple(struct stack *stacks, struct triple *var)
 {
        struct triple_set *head;
        struct triple *top_val;
        top_val = 0;
-       head = stacks[var->id];
+       head = stacks[var->id].top;
        if (head) {
                top_val = head->member;
        }
        return top_val;
 }
 
-static void push_triple(struct triple_set **stacks, struct triple *var, struct triple *val)
+static void push_triple(struct stack *stacks, struct triple *var, struct triple *val)
 {
        struct triple_set *new;
        /* Append new to the head of the list,
@@ -10613,14 +11023,14 @@ static void push_triple(struct triple_set **stacks, struct triple *var, struct t
         */
        new = xcmalloc(sizeof(*new), "triple_set");
        new->member = val;
-       new->next   = stacks[var->id];
-       stacks[var->id] = new;
+       new->next   = stacks[var->id].top;
+       stacks[var->id].top = new;
 }
 
-static void pop_triple(struct triple_set **stacks, struct triple *var, struct triple *oldval)
+static void pop_triple(struct stack *stacks, struct triple *var, struct triple *oldval)
 {
        struct triple_set *set, **ptr;
-       ptr = &stacks[var->id];
+       ptr = &stacks[var->id].top;
        while(*ptr) {
                set = *ptr;
                if (set->member == oldval) {
@@ -10640,7 +11050,7 @@ static void pop_triple(struct triple_set **stacks, struct triple *var, struct tr
  * S(V)
  */
 static void fixup_block_phi_variables(
-       struct compile_state *state, struct triple_set **stacks, struct block *parent, struct block *block)
+       struct compile_state *state, struct stack *stacks, struct block *parent, struct block *block)
 {
        struct block_set *set;
        struct triple *ptr;
@@ -10687,7 +11097,7 @@ static void fixup_block_phi_variables(
 
 
 static void rename_block_variables(
-       struct compile_state *state, struct triple_set **stacks, struct block *block)
+       struct compile_state *state, struct stack *stacks, struct block *block)
 {
        struct block_set *user;
        struct triple *ptr, *next, *last;
@@ -10736,6 +11146,7 @@ static void rename_block_variables(
                                        tval = pre_triple(state, ptr, OP_COPY, ptr->type, val, 0);
                                        use_triple(val, tval);
                                }
+                               transform_to_arch_instruction(state, tval);
                                unuse_triple(val, ptr);
                                RHS(ptr, 1) = tval;
                                use_triple(tval, ptr);
@@ -10789,6 +11200,26 @@ static void rename_block_variables(
        block->last = last;
 }
 
+static void rename_variables(struct compile_state *state)
+{
+       struct stack *stacks;
+       int adecls;
+
+       /* Allocate stacks for the Variables */
+       adecls = count_adecls(state);
+       stacks = xcmalloc(sizeof(stacks[0])*(adecls + 1), "adecl stacks");
+
+       /* Give each adecl a stack */
+       number_adecls(state, stacks);
+
+       /* Rename the variables */
+       rename_block_variables(state, stacks, state->first_block);
+
+       /* Remove the stacks from the adecls */
+       restore_adecls(state, stacks);
+       xfree(stacks);
+}
+
 static void prune_block_variables(struct compile_state *state,
        struct block *block)
 {
@@ -10859,9 +11290,8 @@ static void prune_unused_phis(struct compile_state *state)
        struct phi_triple *live;
        int phis, i;
        
-
        /* Find the first instruction */
-       first = RHS(state->main_function, 0);
+       first = state->first;
 
        /* Count how many phi functions I need to process */
        phis = 0;
@@ -10916,36 +11346,34 @@ static void prune_unused_phis(struct compile_state *state)
        xfree(live);
 }
 
-
 static void transform_to_ssa_form(struct compile_state *state)
 {
-       struct triple_set **stacks;
-       int adecls;
        insert_phi_operations(state);
-#if 0
-       printf("@%s:%d\n", __FILE__, __LINE__);
-       print_blocks(state, stdout);
-#endif
-
-       /* Allocate stacks for the Variables */
-       adecls = count_and_number_adecls(state);
-       stacks = xcmalloc(sizeof(stacks[0])*(adecls + 1), "adecl stacks");
-       rename_block_variables(state, stacks, state->first_block);
-       xfree(stacks);
+       rename_variables(state);
 
        prune_block_variables(state, state->first_block);
-
-#if 1
        prune_unused_phis(state);
-#endif
-
 }
 
 
 static void clear_vertex(
        struct compile_state *state, struct block *block, void *arg)
 {
+       /* Clear the current blocks vertex and the vertex of all
+        * of the current blocks neighbors in case there are malformed
+        * blocks with now instructions at this point.
+        */
+       struct block_set *user;
        block->vertex = 0;
+       if (block->left) {
+               block->left->vertex = 0;
+       }
+       if (block->right) {
+               block->right->vertex = 0;
+       }
+       for(user = block->use; user; user = user->next) {
+               user->member->vertex = 0;
+       }
 }
 
 static void mark_live_block(
@@ -10970,7 +11398,7 @@ static void mark_live_block(
                        mark_live_block(state, (*targ)->u.block, next_vertex);
                }
        }
-       else if (block->last->next != RHS(state->main_function, 0)) {
+       else if (block->last->next != state->first) {
                struct triple *ins;
                ins = block->last->next;
                if (!triple_stores_block(state, ins)) {
@@ -10986,7 +11414,7 @@ static void transform_from_ssa_form(struct compile_state *state)
         * edges to blocks containting phi functions.
         */
        struct triple *first;
-       struct triple *phi, *next;
+       struct triple *phi, *var, *next;
        int next_vertex;
 
        /* Walk the control flow to see which blocks remain alive */
@@ -10994,22 +11422,34 @@ static void transform_from_ssa_form(struct compile_state *state)
        next_vertex = 1;
        mark_live_block(state, state->first_block, &next_vertex);
 
+#if 0
+       fprintf(stderr, "@ %s:%d\n", __FILE__, __LINE__);
+       print_blocks(state, stderr);
+#endif
+
        /* Walk all of the operations to find the phi functions */
-       first = RHS(state->main_function, 0);
+       first = state->first;
        for(phi = first->next; phi != first ; phi = next) {
                struct block_set *set;
                struct block *block;
                struct triple **slot;
-               struct triple *var, *read;
+               struct triple *var;
                struct triple_set *use, *use_next;
                int edge, used;
                next = phi->next;
                if (phi->op != OP_PHI) {
                        continue;
                }
+
                block = phi->u.block;
                slot  = &RHS(phi, 0);
 
+               /* If this phi is in a dead block just forget it */
+               if (block->vertex == 0) {
+                       release_triple(state, phi);
+                       continue;
+               }
+
                /* Forget uses from code in dead blocks */
                for(use = phi->use; use; use = use_next) {
                        struct block *ublock;
@@ -11027,55 +11467,61 @@ static void transform_from_ssa_form(struct compile_state *state)
                        }
                        unuse_triple(phi, use->member);
                }
-
-#warning "CHECK_ME does the OP_ADECL need to be placed somewhere that dominates all of the incoming phi edges?"
                /* A variable to replace the phi function */
                var = post_triple(state, phi, OP_ADECL, phi->type, 0,0);
-               /* A read of the single value that is set into the variable */
-               read = post_triple(state, var, OP_READ, phi->type, var, 0);
-               use_triple(var, read);
 
-               /* Replaces uses of the phi with variable reads */
-               propogate_use(state, phi, read);
+               /* Replaces use of phi with var */
+               propogate_use(state, phi, var);
 
                /* Walk all of the incoming edges/blocks and insert moves.
                 */
+               used = 0;
                for(edge = 0, set = block->use; set; set = set->next, edge++) {
-                       struct block *eblock;
+                       struct block *eblock, *vblock;
                        struct triple *move;
                        struct triple *val, *base;
                        eblock = set->member;
                        val = slot[edge];
                        slot[edge] = 0;
                        unuse_triple(val, phi);
+                       vblock = block_of_triple(state, val);
 
-                       if (!val || (val == &zero_triple) ||
-                               (block->vertex == 0) || (eblock->vertex == 0) ||
-                               (val == phi) || (val == read)) {
+                       /* If we don't have a value that belongs in an OP_WRITE
+                        * continue on.
+                        */
+                       if (!val || (val == &zero_triple) || (val == phi) || 
+                               (!vblock) || (vblock->vertex == 0)) {
                                continue;
                        }
+
+                       /* If the value occurs in a dead block see if a replacement
+                        * block can be found.
+                        */
+                       while(eblock && (eblock->vertex == 0)) {
+                               eblock = eblock->idom;
+                       }
+                       /* If not continue on with the next value. */
+                       if (!eblock || (eblock->vertex == 0)) {
+                               continue;
+                       }
+
+                       /* If we have an empty incoming block ignore it. */
+                       if (!eblock->first) {
+                               internal_error(state, 0, "empty block?");
+                       }
                        
                        /* Make certain the write is placed in the edge block... */
                        base = eblock->first;
                        if (block_of_triple(state, val) == eblock) {
                                base = val;
                        }
-                       move = post_triple(state, base, OP_WRITE, phi->type, var, val);
+                       move = post_triple(state, base, OP_WRITE, var->type, var, val);
                        use_triple(val, move);
                        use_triple(var, move);
+                       used = 1;
                }               
-               /* See if there are any writers of var */
-               used = 0;
-               for(use = var->use; use; use = use->next) {
-                       if ((use->member->op == OP_WRITE) &&
-                               (RHS(use->member, 0) == var)) {
-                               used = 1;
-                       }
-               }
                /* If var is not used free it */
                if (!used) {
-                       unuse_triple(var, read);
-                       free_triple(state, read);
                        free_triple(state, var);
                }
 
@@ -11083,8 +11529,76 @@ static void transform_from_ssa_form(struct compile_state *state)
                release_triple(state, phi);
        }
        
+       /* Walk all of the operations to find the adecls */
+       for(var = first->next; var != first ; var = var->next) {
+               struct triple_set *use, *use_next;
+               if (var->op != OP_ADECL) {
+                       continue;
+               }
+
+               /* Walk through all of the rhs uses of var and
+                * replace them with read of var.
+                */
+               for(use = var->use; use; use = use_next) {
+                       struct triple *read, *user;
+                       struct triple **slot;
+                       int zrhs, i, used;
+                       use_next = use->next;
+                       user = use->member;
+                       
+                       /* Generate a read of var */
+                       read = pre_triple(state, user, OP_READ, var->type, var, 0);
+                       use_triple(var, read);
+
+                       /* Find the rhs uses and see if they need to be replaced */
+                       used = 0;
+                       zrhs = TRIPLE_RHS(user->sizes);
+                       slot = &RHS(user, 0);
+                       for(i = 0; i < zrhs; i++) {
+                               if ((slot[i] == var) &&
+                                       ((i != 0) || (user->op != OP_WRITE))) 
+                               {
+                                       slot[i] = read;
+                                       used = 1;
+                               }
+                       }
+                       /* If we did use it cleanup the uses */
+                       if (used) {
+                               unuse_triple(var, user);
+                               use_triple(read, user);
+                       } 
+                       /* If we didn't use it release the extra triple */
+                       else {
+                               release_triple(state, read);
+                       }
+               }
+       }
 }
 
+#if 0
+#define HI() do { fprintf(stderr, "@ %s:%d\n", __FILE__, __LINE__); print_blocks(state, stderr); } while (0)
+#else
+#define HI() 
+#endif
+static void rebuild_ssa_form(struct compile_state *state)
+{
+HI();
+       transform_from_ssa_form(state);
+HI();
+       free_basic_blocks(state);
+       analyze_basic_blocks(state);
+HI();
+       insert_phi_operations(state);
+HI();
+       rename_variables(state);
+HI();
+       
+       prune_block_variables(state, state->first_block);
+HI();
+       prune_unused_phis(state);
+HI();
+}
+#undef HI
 
 /* 
  * Register conflict resolution
@@ -11376,7 +11890,7 @@ static void insert_copies_to_phi(struct compile_state *state)
        struct triple *phi;
 
        /* Walk all of the operations to find the phi functions */
-       first = RHS(state->main_function, 0);
+       first = state->first;
        for(phi = first->next; phi != first ; phi = phi->next) {
                struct block_set *set;
                struct block *block;
@@ -11812,7 +12326,7 @@ static int count_triples(struct compile_state *state)
 {
        struct triple *first, *ins;
        int triples = 0;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                triples++;
@@ -11826,7 +12340,7 @@ struct dead_triple {
        struct triple *triple;
        struct dead_triple *work_next;
        struct block *block;
-       int color;
+       int old_id;
        int flags;
 #define TRIPLE_FLAG_ALIVE 1
 };
@@ -11851,7 +12365,7 @@ static void awaken(
                        triple->id);
        }
        if (triple->op == OP_NOOP) {
-               internal_warning(state, triple, "awakening noop?");
+               internal_error(state, triple, "awakening noop?");
                return;
        }
        dt = &dtriple[triple->id];
@@ -11869,13 +12383,14 @@ static void eliminate_inefectual_code(struct compile_state *state)
        struct block *block;
        struct dead_triple *dtriple, *work_list, **work_list_tail, *dt;
        int triples, i;
-       struct triple *first, *ins;
+       struct triple *first, *final, *ins;
 
        /* Setup the work list */
        work_list = 0;
        work_list_tail = &work_list;
 
-       first = RHS(state->main_function, 0);
+       first = state->first;
+       final = state->first->prev;
 
        /* Count how many triples I have */
        triples = count_triples(state);
@@ -11887,29 +12402,20 @@ static void eliminate_inefectual_code(struct compile_state *state)
        i = 1;
        block = 0;
        do {
-               if (ins->op == OP_LABEL) {
-                       block = ins->u.block;
-               }
                dtriple[i].triple = ins;
-               dtriple[i].block  = block;
+               dtriple[i].block  = block_of_triple(state, ins);
                dtriple[i].flags  = 0;
-               dtriple[i].color  = ins->id;
+               dtriple[i].old_id = ins->id;
                ins->id = i;
                /* See if it is an operation we always keep */
-#warning "FIXME handle the case of killing a branch instruction"
-               if (!triple_is_pure(state, ins) || triple_is_branch(state, ins)) {
+               if (!triple_is_pure(state, ins, dtriple[i].old_id)) {
                        awaken(state, dtriple, &ins, &work_list_tail);
                }
-#if 1
-               /* Unconditionally keep the very last instruction */
-               else if (ins->next == first) {
-                       awaken(state, dtriple, &ins, &work_list_tail);
-               }
-#endif
                i++;
                ins = ins->next;
        } while(ins != first);
        while(work_list) {
+               struct block *block;
                struct dead_triple *dt;
                struct block_set *user;
                struct triple **expr;
@@ -11918,6 +12424,13 @@ static void eliminate_inefectual_code(struct compile_state *state)
                if (!work_list) {
                        work_list_tail = &work_list;
                }
+               /* Make certain the block the current instruction is in lives */
+               block = block_of_triple(state, dt->triple);
+               awaken(state, dtriple, &block->first, &work_list_tail);
+               if (triple_is_branch(state, block->last)) {
+                       awaken(state, dtriple, &block->last, &work_list_tail);
+               }
+
                /* Wake up the data depencencies of this triple */
                expr = 0;
                do {
@@ -11940,6 +12453,11 @@ static void eliminate_inefectual_code(struct compile_state *state)
                /* Wake up the reverse control dependencies of this triple */
                for(user = dt->block->ipdomfrontier; user; user = user->next) {
                        awaken(state, dtriple, &user->member->last, &work_list_tail);
+                       if ((user->member->left != state->last_block) &&
+                               !triple_is_cond_branch(state, user->member->last)) {
+                               internal_error(state, dt->triple, 
+                                       "conditional branch missing");
+                       }
                }
        }
        for(dt = &dtriple[1]; dt <= &dtriple[triples]; dt++) {
@@ -11947,15 +12465,8 @@ static void eliminate_inefectual_code(struct compile_state *state)
                        (dt->flags & TRIPLE_FLAG_ALIVE)) {
                        internal_error(state, dt->triple, "noop effective?");
                }
-               dt->triple->id = dt->color;     /* Restore the color */
+               dt->triple->id = dt->old_id;    /* Restore the color */
                if (!(dt->flags & TRIPLE_FLAG_ALIVE)) {
-#warning "FIXME handle the case of killing a basic block"
-                       if (dt->block->first == dt->triple) {
-                               continue;
-                       }
-                       if (dt->block->last == dt->triple) {
-                               dt->block->last = dt->triple->prev;
-                       }
                        release_triple(state, dt->triple);
                }
        }
@@ -11974,7 +12485,7 @@ static void insert_mandatory_copies(struct compile_state *state)
         * are inserting copies before instructions but that
         * case should be rare.
         */
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                struct triple_set *entry, *next;
@@ -12746,7 +13257,7 @@ static void initialize_live_ranges(
        size_t count, size;
        int i, j;
 
-       first = RHS(state->main_function, 0);
+       first = state->first;
        /* First count how many instructions I have.
         */
        count = count_triples(state);
@@ -12978,23 +13489,6 @@ static void verify_graph_ins(
        return;
 }
 
-#if DEBUG_CONSISTENCY > 1
-static void verify_interference_graph(
-       struct compile_state *state, struct reg_state *rstate)
-{
-#if 0
-       fprintf(stderr, "verify_interference_graph...\n");
-#endif
-
-       walk_variable_lifetimes(state, rstate->blocks, verify_graph_ins, rstate);
-#if 0
-       fprintf(stderr, "verify_interference_graph done\n");
-#endif
-}
-#else
-static inline void verify_interference_graph(
-       struct compile_state *state, struct reg_state *rstate) {}
-#endif
 
 static void print_interference_ins(
        struct compile_state *state, 
@@ -13241,7 +13735,7 @@ static void replace_block_use(struct compile_state *state,
 static void color_instructions(struct compile_state *state)
 {
        struct triple *ins, *first;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                if (triple_is_def(state, ins)) {
@@ -13808,14 +14302,13 @@ static int color_graph(struct compile_state *state, struct reg_state *rstate)
        return colored;
 }
 
-#if DEBUG_CONSISTENCY
 static void verify_colors(struct compile_state *state, struct reg_state *rstate)
 {
        struct live_range *lr;
        struct live_range_edge *edge;
        struct triple *ins, *first;
        char used[MAX_REGISTERS];
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                if (triple_is_def(state, ins)) {
@@ -13845,15 +14338,12 @@ static void verify_colors(struct compile_state *state, struct reg_state *rstate)
                ins = ins->next;
        } while(ins != first);
 }
-#else
-static inline void verify_colors(struct compile_state *state, struct reg_state *rstate) {}
-#endif
 
 static void color_triples(struct compile_state *state, struct reg_state *rstate)
 {
        struct live_range *lr;
        struct triple *first, *ins;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                if ((ins->id < 0) || (ins->id > rstate->defs)) {
@@ -13930,7 +14420,7 @@ static void ids_from_rstate(struct compile_state *state,
                print_blocks(state, stdout);
                print_control_flow(state);
        }
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                if (ins->id) {
@@ -14052,8 +14542,17 @@ static void allocate_registers(struct compile_state *state)
 #endif
                } while(coalesced);
 
+#if DEBUG_CONSISTENCY > 1
+# if 0
+               fprintf(stderr, "verify_graph_ins...\n");
+# endif
                /* Verify the interference graph */
-               verify_interference_graph(state, &rstate);
+               walk_variable_lifetimes(
+                       state, rstate.blocks, verify_graph_ins, &rstate);
+# if 0
+               fprintf(stderr, "verify_graph_ins done\n");
+#endif
+#endif
                        
                /* Build the groups low and high.  But with the nodes
                 * first sorted by degree order.
@@ -14169,6 +14668,11 @@ struct scc_state {
 static void scc_add_fedge(struct compile_state *state, struct scc_state *scc, 
        struct flow_edge *fedge)
 {
+       if ((fedge == scc->flow_work_list) ||
+               (fedge->work_next != fedge) ||
+               (fedge->work_prev != fedge)) {
+               return;
+       }
        if (!scc->flow_work_list) {
                scc->flow_work_list = fedge;
                fedge->work_next = fedge->work_prev = fedge;
@@ -14196,6 +14700,7 @@ static struct flow_edge *scc_next_fedge(
                } else {
                        scc->flow_work_list = 0;
                }
+               fedge->work_next = fedge->work_prev = fedge;
        }
        return fedge;
 }
@@ -14203,6 +14708,21 @@ static struct flow_edge *scc_next_fedge(
 static void scc_add_sedge(struct compile_state *state, struct scc_state *scc,
        struct ssa_edge *sedge)
 {
+#if DEBUG_SCC > 1
+       fprintf(stderr, "adding sedge: %5d (%4d -> %5d)\n",
+               sedge - scc->ssa_edges,
+               sedge->src->def->id,
+               sedge->dst->def->id);
+#endif
+       if ((sedge == scc->ssa_work_list) ||
+               (sedge->work_next != sedge) ||
+               (sedge->work_prev != sedge)) {
+#if DEBUG_SCC > 1
+               fprintf(stderr, "dupped sedge: %5d\n",
+                       sedge - scc->ssa_edges);
+#endif
+               return;
+       }
        if (!scc->ssa_work_list) {
                scc->ssa_work_list = sedge;
                sedge->work_next = sedge->work_prev = sedge;
@@ -14230,6 +14750,7 @@ static struct ssa_edge *scc_next_sedge(
                } else {
                        scc->ssa_work_list = 0;
                }
+               sedge->work_next = sedge->work_prev = sedge;
        }
        return sedge;
 }
@@ -14246,7 +14767,7 @@ static void initialize_scc_state(
        memset(scc, 0, sizeof(*scc));
 
        /* Inialize pass zero find out how much memory we need */
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        ins_count = ssa_edge_count = 0;
        do {
@@ -14472,6 +14993,7 @@ static void scc_visit_phi(struct compile_state *state, struct scc_state *scc,
        struct lattice_node *tmp;
        struct triple **slot, *old;
        struct flow_edge *fedge;
+       int changed;
        int index;
        if (lnode->def->op != OP_PHI) {
                internal_error(state, lnode->def, "not phi");
@@ -14484,6 +15006,13 @@ static void scc_visit_phi(struct compile_state *state, struct scc_state *scc,
        slot = &RHS(lnode->def, 0);
        index = 0;
        for(fedge = lnode->fblock->in; fedge; index++, fedge = fedge->in_next) {
+#if DEBUG_SCC
+               fprintf(stderr, "Examining edge: %d vertex: %d executable: %d\n", 
+                       index,
+                       fedge->dst->block->vertex,
+                       fedge->executable
+                       );
+#endif
                if (!fedge->executable) {
                        continue;
                }
@@ -14512,13 +15041,17 @@ static void scc_visit_phi(struct compile_state *state, struct scc_state *scc,
                        break;
                }
        }
+       changed = lval_changed(state, old, lnode);
 #if DEBUG_SCC
-       fprintf(stderr, "phi: %d -> %s\n",
+       fprintf(stderr, "%p phi:  %d -> %s %s\n",
+               lnode->def, 
                lnode->def->id,
-               (!lnode->val)? "lo": is_const(lnode->val)? "const": "hi");
+               ((!lnode->val)? "lo": is_const(lnode->val)? "const": "hi"),
+               changed? "changed" : ""
+               );
 #endif
        /* If the lattice value has changed update the work lists. */
-       if (lval_changed(state, old, lnode)) {
+       if (changed) {
                struct ssa_edge *sedge;
                for(sedge = lnode->out; sedge; sedge = sedge->out_next) {
                        scc_add_sedge(state, scc, sedge);
@@ -14608,16 +15141,23 @@ static int compute_lnode_val(struct compile_state *state, struct scc_state *scc,
        /* Find the cases that are always lattice lo */
        if (lnode->val && 
                triple_is_def(state, lnode->val) &&
-               !triple_is_pure(state, lnode->val)) {
+               !triple_is_pure(state, lnode->val, lnode->old_id)) {
                lnode->val = 0;
        }
-       if (lnode->val && 
-               (lnode->val->op == OP_SDECL) && 
-               (lnode->val != lnode->def)) {
-               internal_error(state, lnode->def, "bad sdecl");
-       }
        /* See if the lattice value has changed */
        changed = lval_changed(state, old, lnode);
+       /* See if this value should not change */
+       if (lnode->val && 
+               ((      !triple_is_def(state, lnode->def)  &&
+                       !triple_is_cond_branch(state, lnode->def)) ||
+                       (lnode->def->op == OP_PIECE))) {
+#warning "FIXME constant propogate through expressions with multiple left hand sides"
+               if (changed) {
+                       internal_warning(state, lnode->def, "non def changes value?");
+               }
+               lnode->val = 0;
+       }
+       /* See if we need to free the scratch value */
        if (lnode->val != scratch) {
                xfree(scratch);
        }
@@ -14708,19 +15248,35 @@ static void scc_writeback_values(
        struct compile_state *state, struct scc_state *scc)
 {
        struct triple *first, *ins;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                struct lattice_node *lnode;
                lnode = triple_to_lattice(state, scc, ins);
-               /* Restore id */
-               ins->id = lnode->old_id;
 #if DEBUG_SCC
-               if (lnode->val && !is_const(lnode->val)) {
-                       warning(state, lnode->def, 
-                               "lattice node still high?");
+               if (lnode->val && 
+                       !is_const(lnode->val) &&
+                       !triple_is_uncond_branch(state, lnode->val) &&
+                       (lnode->val->op != OP_NOOP)) 
+               {
+                       struct flow_edge *fedge;
+                       int executable;
+                       executable = 0;
+                       for(fedge = lnode->fblock->in; 
+                           !executable && fedge; fedge = fedge->in_next) {
+                               executable |= fedge->executable;
+                       }
+                       if (executable) {
+                               internal_warning(state, lnode->val,
+                                       "lattice node %d %s->%s still high?",
+                                       ins->id, 
+                                       tops(lnode->def->op),
+                                       tops(lnode->val->op));
+                       }
                }
 #endif
+               /* Restore id */
+               ins->id = lnode->old_id;
                if (lnode->val && (lnode->val != ins)) {
                        /* See if it something I know how to write back */
                        switch(lnode->val->op) {
@@ -14764,7 +15320,7 @@ static void scc_transform(struct compile_state *state)
                        struct block *block;
                        struct triple *ptr;
                        struct flow_block *fblock;
-                       int time;
+                       int reps;
                        int done;
                        if (fedge->executable) {
                                continue;
@@ -14778,15 +15334,15 @@ static void scc_transform(struct compile_state *state)
                        fedge->executable = 1;
                        fblock = fedge->dst;
                        block = fblock->block;
-                       time = 0;
+                       reps = 0;
                        for(fptr = fblock->in; fptr; fptr = fptr->in_next) {
                                if (fptr->executable) {
-                                       time++;
+                                       reps++;
                                }
                        }
 #if DEBUG_SCC
-                       fprintf(stderr, "vertex: %d time: %d\n", 
-                               block->vertex, time);
+                       fprintf(stderr, "vertex: %d reps: %d\n", 
+                               block->vertex, reps);
                        
 #endif
                        done = 0;
@@ -14797,7 +15353,7 @@ static void scc_transform(struct compile_state *state)
                                if (ptr->op == OP_PHI) {
                                        scc_visit_phi(state, &scc, lnode);
                                }
-                               else if (time == 1) {
+                               else if (reps == 1) {
                                        scc_visit_expr(state, &scc, lnode);
                                }
                        }
@@ -14840,7 +15396,7 @@ static void scc_transform(struct compile_state *state)
 static void transform_to_arch_instructions(struct compile_state *state)
 {
        struct triple *ins, *first;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                ins = transform_to_arch_instruction(state, ins);
@@ -14852,7 +15408,7 @@ static void verify_uses(struct compile_state *state)
 {
        struct triple *first, *ins;
        struct triple_set *set;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                struct triple **expr;
@@ -14892,7 +15448,7 @@ static void verify_blocks_present(struct compile_state *state)
        if (!state->first_block) {
                return;
        }
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                valid_ins(state, ins);
@@ -14930,6 +15486,9 @@ static void verify_blocks(struct compile_state *state)
                users = 0;
                for(user = block->use; user; user = user->next) {
                        users++;
+                       if (!user->member->first) {
+                               internal_error(state, block->first, "user is empty");
+                       }
                        if ((block == state->last_block) &&
                                (user->member == state->first_block)) {
                                continue;
@@ -14961,6 +15520,9 @@ static void verify_blocks(struct compile_state *state)
                                internal_error(state, block->first,
                                        "block does not use left");
                        }
+                       if (!block->left->first) {
+                               internal_error(state, block->first, "left block is empty");
+                       }
                }
                if (block->right) {
                        for(user = block->right->use; user; user = user->next) {
@@ -14972,12 +15534,22 @@ static void verify_blocks(struct compile_state *state)
                                internal_error(state, block->first,
                                        "block does not use right");
                        }
+                       if (!block->right->first) {
+                               internal_error(state, block->first, "right block is empty");
+                       }
                }
                if (block->users != users) {
                        internal_error(state, block->first, 
                                "computed users %d != stored users %d\n",
                                users, block->users);
                }
+               for(user = block->ipdomfrontier; user; user = user->next) {
+                       if ((user->member->left != state->last_block) &&
+                               !triple_is_cond_branch(state, user->member->last)) {
+                               internal_error(state, user->member->last,
+                                       "conditional branch missing");
+                       }
+               }
                if (!triple_stores_block(state, block->last->next)) {
                        internal_error(state, block->last->next, 
                                "cannot find next block");
@@ -15002,7 +15574,7 @@ static void verify_domination(struct compile_state *state)
                return;
        }
        
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                for(set = ins->use; set; set = set->next) {
@@ -15046,10 +15618,36 @@ static void verify_domination(struct compile_state *state)
        } while(ins != first);
 }
 
+static void verify_rhs(struct compile_state *state)
+{
+       struct triple *first, *ins;
+       first = state->first;
+       ins = first;
+       do {
+               struct triple **slot;
+               int zrhs, i;
+               zrhs = TRIPLE_RHS(ins->sizes);
+               slot = &RHS(ins, 0);
+               for(i = 0; i < zrhs; i++) {
+                       if (slot[i] == 0) {
+                               internal_error(state, ins,
+                                       "missing rhs %d on %s",
+                                       i, tops(ins->op));
+                       }
+                       if ((ins->op != OP_PHI) && (slot[i] == ins)) {
+                               internal_error(state, ins,
+                                       "ins == rhs[%d] on %s",
+                                       i, tops(ins->op));
+                       }
+               }
+               ins = ins->next;
+       } while(ins != first);
+}
+
 static void verify_piece(struct compile_state *state)
 {
        struct triple *first, *ins;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                struct triple *ptr;
@@ -15072,11 +15670,12 @@ static void verify_piece(struct compile_state *state)
                ins = ins->next;
        } while(ins != first);
 }
+
 static void verify_ins_colors(struct compile_state *state)
 {
        struct triple *first, *ins;
        
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                ins = ins->next;
@@ -15088,12 +15687,13 @@ static void verify_consistency(struct compile_state *state)
        verify_blocks_present(state);
        verify_blocks(state);
        verify_domination(state);
+       verify_rhs(state);
        verify_piece(state);
        verify_ins_colors(state);
 }
 #else 
 static void verify_consistency(struct compile_state *state) {}
-#endif /* DEBUG_USES */
+#endif /* DEBUG_CONSISTENCY */
 
 static void optimize(struct compile_state *state)
 {
@@ -15107,9 +15707,7 @@ static void optimize(struct compile_state *state)
        }
        verify_consistency(state);
        /* Analize the intermediate code */
-       setup_basic_blocks(state);
-       analyze_idominators(state);
-       analyze_ipdominators(state);
+       analyze_basic_blocks(state);
 
        /* Transform the code to ssa form. */
        /*
@@ -15121,23 +15719,21 @@ static void optimize(struct compile_state *state)
         * phi functions early and I kill them often.
         */
        transform_to_ssa_form(state);
-       eliminate_inefectual_code(state);
 
        verify_consistency(state);
        if (state->debug & DEBUG_CODE_ELIMINATION) {
                fprintf(stdout, "After transform_to_ssa_form\n");
                print_blocks(state, stdout);
        }
+       /* Remove dead code */
+       eliminate_inefectual_code(state);
+       rebuild_ssa_form(state);
+       verify_consistency(state);
+
        /* Do strength reduction and simple constant optimizations */
        if (state->optimize >= 1) {
                simplify_all(state);
-               transform_from_ssa_form(state);
-               free_basic_blocks(state);
-               setup_basic_blocks(state);
-               analyze_idominators(state);
-               analyze_ipdominators(state);
-               transform_to_ssa_form(state);
-               eliminate_inefectual_code(state);
+               rebuild_ssa_form(state);
        }
        if (state->debug & DEBUG_CODE_ELIMINATION) {
                fprintf(stdout, "After simplify_all\n");
@@ -15147,13 +15743,7 @@ static void optimize(struct compile_state *state)
        /* Propogate constants throughout the code */
        if (state->optimize >= 2) {
                scc_transform(state);
-               transform_from_ssa_form(state);
-               free_basic_blocks(state);
-               setup_basic_blocks(state);
-               analyze_idominators(state);
-               analyze_ipdominators(state);
-               transform_to_ssa_form(state);
-               eliminate_inefectual_code(state);
+               rebuild_ssa_form(state);
        }
        verify_consistency(state);
 #warning "WISHLIST implement single use constants (least possible register pressure)"
@@ -15168,7 +15758,9 @@ static void optimize(struct compile_state *state)
                print_blocks(state, stdout);
                print_control_flow(state);
        }
+       /* Remove dead code */
        eliminate_inefectual_code(state);
+       rebuild_ssa_form(state);
        verify_consistency(state);
        if (state->debug & DEBUG_CODE_ELIMINATION) {
                printf("After eliminate_inefectual_code\n");
@@ -15258,15 +15850,9 @@ static void print_op_asm(struct compile_state *state,
  */
 #define X86_4_8BIT_GPRS 1
 
-/* Recognized x86 cpu variants */
-#define BAD_CPU      0
-#define CPU_I386     1
-#define CPU_P3       2
-#define CPU_P4       3
-#define CPU_K7       4
-#define CPU_K8       5
-
-#define CPU_DEFAULT  CPU_I386
+/* x86 featrues */
+#define X86_MMX_REGS (1<<0)
+#define X86_XMM_REGS (1<<1)
 
 /* The x86 register classes */
 #define REGC_FLAGS       0
@@ -15423,26 +16009,48 @@ static const struct {
        [REGC_IMM8]       = { REGC_IMM8_FIRST,       REGC_IMM8_LAST },
 };
 
-static int arch_encode_cpu(const char *cpu)
+static int arch_encode_feature(const char *feature, unsigned long *features)
 {
        struct cpu {
                const char *name;
                int cpu;
        } cpus[] = {
-               { "i386", CPU_I386 },
-               { "p3",   CPU_P3 },
-               { "p4",   CPU_P4 },
-               { "k7",   CPU_K7 },
-               { "k8",   CPU_K8 },
-               {  0,     BAD_CPU }
+               { "i386", 0 },
+               { "p2",   X86_MMX_REGS },
+               { "p3",   X86_MMX_REGS | X86_XMM_REGS },
+               { "p4",   X86_MMX_REGS | X86_XMM_REGS },
+               { "k7",   X86_MMX_REGS },
+               { "k8",   X86_MMX_REGS | X86_XMM_REGS },
+               { "c3",   X86_MMX_REGS },
+               { "c3-2", X86_MMX_REGS | X86_XMM_REGS }, /* Nehemiah */
+               {  0,     0 }
        };
        struct cpu *ptr;
-       for(ptr = cpus; ptr->name; ptr++) {
-               if (strcmp(ptr->name, cpu) == 0) {
-                       break;
+       int result = 0;
+       if (strcmp(feature, "mmx") == 0) {
+               *features |= X86_MMX_REGS;
+       }
+       else if (strcmp(feature, "sse") == 0) {
+               *features |= X86_XMM_REGS;
+       }
+       else if (strncmp(feature, "cpu=", 4) == 0) {
+               const char *cpu = feature + 4;
+               for(ptr = cpus; ptr->name; ptr++) {
+                       if (strcmp(ptr->name, cpu) == 0) {
+                               break;
+                       }
+               }
+               if (ptr->name) {
+                       *features |= ptr->cpu; 
+               }
+               else {
+                       result = -1;
                }
        }
-       return ptr->cpu;
+       else {
+               result = -1;
+       }
+       return result;
 }
 
 static unsigned arch_regc_size(struct compile_state *state, int class)
@@ -15651,15 +16259,11 @@ static unsigned arch_avail_mask(struct compile_state *state)
                REGCM_GPR32 | REGCM_GPR32_8 | 
                REGCM_DIVIDEND32 | REGCM_DIVIDEND64 |
                REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8 | REGCM_FLAGS;
-       switch(state->cpu) {
-       case CPU_P3:
-       case CPU_K7:
+       if (state->features & X86_MMX_REGS) {
                avail_mask |= REGCM_MMX;
-               break;
-       case CPU_P4:
-       case CPU_K8:
-               avail_mask |= REGCM_MMX | REGCM_XMM;
-               break;
+       }
+       if (state->features & X86_XMM_REGS) {
+               avail_mask |= REGCM_XMM;
        }
        return avail_mask;
 }
@@ -16475,6 +17079,32 @@ static struct ins_template templates[] = {
        },
 };
 
+static void fixup_branch(struct compile_state *state,
+       struct triple *branch, int jmp_op, int cmp_op, struct type *cmp_type,
+       struct triple *left, struct triple *right)
+{
+       struct triple *test;
+       if (!left) {
+               internal_error(state, branch, "no branch test?");
+       }
+       test = pre_triple(state, branch,
+               cmp_op, cmp_type, left, right);
+       test->template_id = TEMPLATE_TEST32; 
+       if (cmp_op == OP_CMP) {
+               test->template_id = TEMPLATE_CMP32_REG;
+               if (get_imm32(test, &RHS(test, 1))) {
+                       test->template_id = TEMPLATE_CMP32_IMM;
+               }
+       }
+       use_triple(RHS(test, 0), test);
+       use_triple(RHS(test, 1), test);
+       unuse_triple(RHS(branch, 0), branch);
+       RHS(branch, 0) = test;
+       branch->op = jmp_op;
+       branch->template_id = TEMPLATE_JMP;
+       use_triple(RHS(branch, 0), branch);
+}
+
 static void fixup_branches(struct compile_state *state,
        struct triple *cmp, struct triple *use, int jmp_op)
 {
@@ -16485,7 +17115,7 @@ static void fixup_branches(struct compile_state *state,
                        fixup_branches(state, cmp, entry->member, jmp_op);
                }
                else if (entry->member->op == OP_BRANCH) {
-                       struct triple *branch, *test;
+                       struct triple *branch;
                        struct triple *left, *right;
                        left = right = 0;
                        left = RHS(cmp, 0);
@@ -16493,22 +17123,8 @@ static void fixup_branches(struct compile_state *state,
                                right = RHS(cmp, 1);
                        }
                        branch = entry->member;
-                       test = pre_triple(state, branch,
+                       fixup_branch(state, branch, jmp_op, 
                                cmp->op, cmp->type, left, right);
-                       test->template_id = TEMPLATE_TEST32; 
-                       if (cmp->op == OP_CMP) {
-                               test->template_id = TEMPLATE_CMP32_REG;
-                               if (get_imm32(test, &RHS(test, 1))) {
-                                       test->template_id = TEMPLATE_CMP32_IMM;
-                               }
-                       }
-                       use_triple(RHS(test, 0), test);
-                       use_triple(RHS(test, 1), test);
-                       unuse_triple(RHS(branch, 0), branch);
-                       RHS(branch, 0) = test;
-                       branch->op = jmp_op;
-                       branch->template_id = TEMPLATE_JMP;
-                       use_triple(RHS(branch, 0), branch);
                }
        }
 }
@@ -16875,10 +17491,14 @@ static struct triple *transform_to_arch_instruction(
                break;
        case OP_BRANCH:
                if (TRIPLE_RHS(ins->sizes) > 0) {
-                       internal_error(state, ins, "bad branch test");
+                       struct triple *left = RHS(ins, 0);
+                       fixup_branch(state, ins, OP_JMP_NOTEQ, OP_TEST, 
+                               left->type, left, 0);
+               }
+               else {
+                       ins->op = OP_JMP;
+                       ins->template_id = TEMPLATE_NOP;
                }
-               ins->op = OP_JMP;
-               ins->template_id = TEMPLATE_NOP;
                break;
        case OP_INB:
        case OP_INW:
@@ -16932,6 +17552,9 @@ static struct triple *transform_to_arch_instruction(
                        ins->template_id = TEMPLATE_CMP32_IMM;
                }
                break;
+       case OP_JMP:
+               ins->template_id = TEMPLATE_NOP;
+               break;
        case OP_JMP_EQ:      case OP_JMP_NOTEQ:
        case OP_JMP_SLESS:   case OP_JMP_ULESS:
        case OP_JMP_SMORE:   case OP_JMP_UMORE:
@@ -16964,7 +17587,7 @@ static long next_label(struct compile_state *state)
 static void generate_local_labels(struct compile_state *state)
 {
        struct triple *first, *label;
-       first = RHS(state->main_function, 0);
+       first = state->first;
        label = first;
        do {
                if ((label->op == OP_LABEL) || 
@@ -17051,7 +17674,7 @@ static void print_const_val(
        switch(ins->op) {
        case OP_INTCONST:
                fprintf(fp, " $%ld ", 
-                       (long_t)(ins->u.cval));
+                       (long)(ins->u.cval));
                break;
        case OP_ADDRCONST:
                if (MISC(ins, 0)->op != OP_SDECL) {
@@ -17062,8 +17685,8 @@ static void print_const_val(
                }
                fprintf(fp, " $L%s%lu+%lu ",
                        state->label_prefix, 
-                       MISC(ins, 0)->u.cval,
-                       ins->u.cval);
+                       (unsigned long)(MISC(ins, 0)->u.cval),
+                       (unsigned long)(ins->u.cval));
                break;
        default:
                internal_error(state, ins, "unknown constant type");
@@ -17079,17 +17702,20 @@ static void print_const(struct compile_state *state,
                switch(ins->type->type & TYPE_MASK) {
                case TYPE_CHAR:
                case TYPE_UCHAR:
-                       fprintf(fp, ".byte 0x%02lx\n", ins->u.cval);
+                       fprintf(fp, ".byte 0x%02lx\n", 
+                               (unsigned long)(ins->u.cval));
                        break;
                case TYPE_SHORT:
                case TYPE_USHORT:
-                       fprintf(fp, ".short 0x%04lx\n", ins->u.cval);
+                       fprintf(fp, ".short 0x%04lx\n", 
+                               (unsigned long)(ins->u.cval));
                        break;
                case TYPE_INT:
                case TYPE_UINT:
                case TYPE_LONG:
                case TYPE_ULONG:
-                       fprintf(fp, ".int %lu\n", ins->u.cval);
+                       fprintf(fp, ".int %lu\n", 
+                               (unsigned long)(ins->u.cval));
                        break;
                default:
                        internal_error(state, ins, "Unknown constant type");
@@ -17104,8 +17730,8 @@ static void print_const(struct compile_state *state,
                }
                fprintf(fp, ".int L%s%lu+%lu\n",
                        state->label_prefix,
-                       MISC(ins, 0)->u.cval,
-                       ins->u.cval);
+                       (unsigned long)(MISC(ins, 0)->u.cval),
+                       (unsigned long)(ins->u.cval));
                break;
        case OP_BLOBCONST:
        {
@@ -17146,7 +17772,7 @@ static void print_binary_op(struct compile_state *state,
 {
        unsigned mask;
        mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO;
-       if (RHS(ins, 0)->id != ins->id) {
+       if (ID_REG(RHS(ins, 0)->id) != ID_REG(ins->id)) {
                internal_error(state, ins, "invalid register assignment");
        }
        if (is_const(RHS(ins, 1))) {
@@ -17184,7 +17810,7 @@ static void print_op_shift(struct compile_state *state,
 {
        unsigned mask;
        mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO;
-       if (RHS(ins, 0)->id != ins->id) {
+       if (ID_REG(RHS(ins, 0)->id) != ID_REG(ins->id)) {
                internal_error(state, ins, "invalid register assignment");
        }
        if (is_const(RHS(ins, 1))) {
@@ -17577,14 +18203,14 @@ static void print_op_store(struct compile_state *state,
                value = (long_t)(src->u.cval);
                fprintf(fp, "\tmov%s $%ld, (%s)\n",
                        type_suffix(state, src->type),
-                       value,
+                       (long)(value),
                        reg(state, dst, REGCM_GPR32));
        }
        else if (is_const(dst) && (dst->op == OP_INTCONST)) {
                fprintf(fp, "\tmov%s %s, 0x%08lx\n",
                        type_suffix(state, src->type),
                        reg(state, src, REGCM_GPR8_LO | REGCM_GPR16 | REGCM_GPR32),
-                       dst->u.cval);
+                       (unsigned long)(dst->u.cval));
        }
        else {
                if (is_const(src) || is_const(dst)) {
@@ -17700,7 +18326,7 @@ static void print_op_branch(struct compile_state *state,
        fprintf(fp, "\t%s L%s%lu\n",
                bop, 
                state->label_prefix,
-               TARG(branch, 0)->u.cval);
+               (unsigned long)(TARG(branch, 0)->u.cval));
 }
 
 static void print_op_set(struct compile_state *state,
@@ -17766,7 +18392,8 @@ static void print_sdecl(struct compile_state *state,
 {
        fprintf(fp, ".section \"" DATA_SECTION "\"\n");
        fprintf(fp, ".balign %d\n", align_of(state, ins->type));
-       fprintf(fp, "L%s%lu:\n", state->label_prefix, ins->u.cval);
+       fprintf(fp, "L%s%lu:\n", 
+               state->label_prefix, (unsigned long)(ins->u.cval));
        print_const(state, MISC(ins, 0), fp);
        fprintf(fp, ".section \"" TEXT_SECTION "\"\n");
                
@@ -17865,7 +18492,8 @@ static void print_instruction(struct compile_state *state,
                if (!ins->use) {
                        return;
                }
-               fprintf(fp, "L%s%lu:\n", state->label_prefix, ins->u.cval);
+               fprintf(fp, "L%s%lu:\n", 
+                       state->label_prefix, (unsigned long)(ins->u.cval));
                break;
                /* Ignore OP_PIECE */
        case OP_PIECE:
@@ -17895,7 +18523,7 @@ static void print_instructions(struct compile_state *state)
        last_occurance = 0;
        fp = state->output;
        fprintf(fp, ".section \"" TEXT_SECTION "\"\n");
-       first = RHS(state->main_function, 0);
+       first = state->first;
        ins = first;
        do {
                if (print_location && 
@@ -17967,11 +18595,21 @@ static void print_tokens(struct compile_state *state)
        } while(tk->tok != TOK_EOF);
 }
 
+static void call_main(struct compile_state *state)
+{
+       struct triple *call;
+       call = new_triple(state, OP_CALL, &void_func, -1, -1);
+       call->type = &void_type;
+       MISC(call, 0) = state->main_function;
+       flatten(state, state->first, call);
+}
+
 static void compile(const char *filename, const char *ofilename, 
-       int cpu, int debug, int opt, const char *label_prefix)
+       unsigned long features, int debug, int opt, const char *label_prefix)
 {
        int i;
        struct compile_state state;
+       struct triple *ptr;
        memset(&state, 0, sizeof(state));
        state.file = 0;
        for(i = 0; i < sizeof(state.token)/sizeof(state.token[0]); i++) {
@@ -17979,7 +18617,7 @@ static void compile(const char *filename, const char *ofilename,
                state.token[i].tok = -1;
        }
        /* Remember the debug settings */
-       state.cpu      = cpu;
+       state.features = features;
        state.debug    = debug;
        state.optimize = opt;
        /* Remember the output filename */
@@ -17999,8 +18637,21 @@ static void compile(const char *filename, const char *ofilename,
        /* register the keywords the macro preprocessor knows */
        register_macro_keywords(&state);
        /* Memorize where some special keywords are. */
+       state.i_switch   = lookup(&state, "switch", 6);
+       state.i_case     = lookup(&state, "case", 4);
        state.i_continue = lookup(&state, "continue", 8);
        state.i_break    = lookup(&state, "break", 5);
+       state.i_default  = lookup(&state, "default", 7);
+
+       /* Allocate beginning bounding labels for the function list */
+       state.first = label(&state);
+       state.first->id |= TRIPLE_FLAG_VOLATILE;
+       use_triple(state.first, state.first);
+       ptr = label(&state);
+       ptr->id |= TRIPLE_FLAG_VOLATILE;
+       use_triple(ptr, ptr);
+       flatten(&state, state.first, ptr);
+
        /* Enter the globl definition scope */
        start_scope(&state);
        register_builtins(&state);
@@ -18012,6 +18663,9 @@ static void compile(const char *filename, const char *ofilename,
        /* Exit the global definition scope */
        end_scope(&state);
 
+       /* Call the main function */
+       call_main(&state);
+
        /* Now that basic compilation has happened 
         * optimize the intermediate code 
         */
@@ -18052,11 +18706,11 @@ int main(int argc, char **argv)
        const char *filename;
        const char *ofilename;
        const char *label_prefix;
-       int cpu;
+       unsigned long features;
        int last_argc;
        int debug;
        int optimize;
-       cpu = CPU_DEFAULT;
+       features = 0;
        label_prefix = "";
        ofilename = "auto.inc";
        optimize = 0;
@@ -18090,11 +18744,12 @@ int main(int argc, char **argv)
                        argv += 2;
                        argc -= 2;
                }
-               else if (strncmp(argv[1], "-mcpu=", 6) == 0) {
-                       cpu = arch_encode_cpu(argv[1] + 6);
-                       if (cpu == BAD_CPU) {
-                               arg_error("Invalid cpu specified: %s\n",
-                                       argv[1] + 6);
+               else if (strncmp(argv[1], "-m", 2) == 0) {
+                       int result;
+                       result = arch_encode_feature(argv[1] + 2, &features);
+                       if (result < 0) {
+                               arg_error("Invalid feature specified: %s\n",
+                                       argv[1] + 2);
                        }
                        argv++;
                        argc--;
@@ -18104,7 +18759,7 @@ int main(int argc, char **argv)
                arg_error("Wrong argument count %d\n", argc);
        }
        filename = argv[1];
-       compile(filename, ofilename, cpu, debug, optimize, label_prefix);
+       compile(filename, ofilename, features, debug, optimize, label_prefix);
 
        return 0;
 }
diff --git a/util/romcc/tests/fail_test4.c b/util/romcc/tests/fail_test4.c
new file mode 100644 (file)
index 0000000..a2d3bec
--- /dev/null
@@ -0,0 +1,14 @@
+static void main(void)
+{
+       static const int foo = 2;
+       switch(foo) {
+       case 1:
+               break;
+       case 2:
+               break;
+       case 1:
+               break;
+       default:
+               break;
+       }
+}
diff --git a/util/romcc/tests/fail_test5.c b/util/romcc/tests/fail_test5.c
new file mode 100644 (file)
index 0000000..efa4e76
--- /dev/null
@@ -0,0 +1,14 @@
+static void main(void)
+{
+       static const int foo = 2;
+       switch(foo) {
+       case 1:
+               break;
+       default:
+               break;
+       case 2:
+               break;
+       default:
+               break;
+       }
+}
diff --git a/util/romcc/tests/linux_console.h b/util/romcc/tests/linux_console.h
new file mode 100644 (file)
index 0000000..0837dfc
--- /dev/null
@@ -0,0 +1,136 @@
+#ifndef LINUX_CONSOLE_H
+#define LINUX_CONSOLE_H
+
+#include "linux_syscall.h"
+
+static const char *addr_of_char(unsigned char ch)
+{
+       static const char byte[] = {
+               0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+               0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+               0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
+               0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+               0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 
+               0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+               0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 
+               0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+               0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 
+               0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+               0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 
+               0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+               0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 
+               0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+               0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 
+               0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+               0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 
+               0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+               0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 
+               0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+               0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 
+               0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+               0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+               0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+               0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 
+               0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+               0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 
+               0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+               0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 
+               0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+               0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+               0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+       };
+       return byte + ch;
+}
+
+static void console_tx_byte(unsigned char ch)
+{
+       write(STDOUT_FILENO, addr_of_char(ch), 1);
+}
+
+static void console_tx_nibble(unsigned nibble)
+{
+       unsigned char digit;
+       digit = nibble + '0';
+       if (digit > '9') {
+               digit += 39;
+       }
+       console_tx_byte(digit);
+}
+
+static void console_tx_char(unsigned char byte)
+{
+       console_tx_byte(byte);
+}
+
+static void console_tx_hex8(unsigned char value)
+{
+       console_tx_nibble((value >> 4U) & 0x0fU);
+       console_tx_nibble(value & 0x0fU);
+}
+
+static void console_tx_hex16(unsigned short value)
+{
+       console_tx_nibble((value >> 12U) & 0x0FU);
+       console_tx_nibble((value >>  8U) & 0x0FU);
+       console_tx_nibble((value >>  4U) & 0x0FU);
+       console_tx_nibble(value & 0x0FU);
+}
+
+static void console_tx_hex32(unsigned short value)
+{
+       console_tx_nibble((value >> 28U) & 0x0FU);
+       console_tx_nibble((value >> 24U) & 0x0FU);
+       console_tx_nibble((value >> 20U) & 0x0FU);
+       console_tx_nibble((value >> 16U) & 0x0FU);
+       console_tx_nibble((value >> 12U) & 0x0FU);
+       console_tx_nibble((value >>  8U) & 0x0FU);
+       console_tx_nibble((value >>  4U) & 0x0FU);
+       console_tx_nibble(value & 0x0FU);
+}
+
+static void console_tx_string(const char *str)
+{
+       unsigned char ch;
+       while((ch = *str++) != '\0') {
+               console_tx_byte(ch);
+       }
+}
+
+static void print_emerg_char(unsigned char byte) { console_tx_char(byte); }
+static void print_emerg_hex8(unsigned char value) { console_tx_hex8(value); }
+static void print_emerg_hex16(unsigned short value){ console_tx_hex16(value); }
+static void print_emerg_hex32(unsigned int value) { console_tx_hex32(value); }
+static void print_emerg(const char *str) { console_tx_string(str); }
+
+static void print_warn_char(unsigned char byte) { console_tx_char(byte); }
+static void print_warn_hex8(unsigned char value) { console_tx_hex8(value); }
+static void print_warn_hex16(unsigned short value){ console_tx_hex16(value); }
+static void print_warn_hex32(unsigned int value) { console_tx_hex32(value); }
+static void print_warn(const char *str) { console_tx_string(str); }
+
+static void print_info_char(unsigned char byte) { console_tx_char(byte); }
+static void print_info_hex8(unsigned char value) { console_tx_hex8(value); }
+static void print_info_hex16(unsigned short value){ console_tx_hex16(value); }
+static void print_info_hex32(unsigned int value) { console_tx_hex32(value); }
+static void print_info(const char *str) { console_tx_string(str); }
+
+static void print_debug_char(unsigned char byte) { console_tx_char(byte); }
+static void print_debug_hex8(unsigned char value) { console_tx_hex8(value); }
+static void print_debug_hex16(unsigned short value){ console_tx_hex16(value); }
+static void print_debug_hex32(unsigned int value) { console_tx_hex32(value); }
+static void print_debug(const char *str) { console_tx_string(str); }
+
+static void print_spew_char(unsigned char byte) { console_tx_char(byte); }
+static void print_spew_hex8(unsigned char value) { console_tx_hex8(value); }
+static void print_spew_hex16(unsigned short value){ console_tx_hex16(value); }
+static void print_spew_hex32(unsigned int value) { console_tx_hex32(value); }
+static void print_spew(const char *str) { console_tx_string(str); }
+
+static void die(const char *str)
+{
+       print_emerg(str);
+       do {
+               asm volatile (" ");
+       } while(1);
+}
+#endif /* LINUX_CONSOLE_H */
diff --git a/util/romcc/tests/linux_syscall.h b/util/romcc/tests/linux_syscall.h
new file mode 100644 (file)
index 0000000..487095f
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef LINUX_SYSCALL_H
+#define LINUX_SYSCALL_H
+
+/* When I support other platforms use #ifdefs here */
+#include "linuxi386_syscall.h"
+
+#endif /* LINUX_SYSCALL_H */
diff --git a/util/romcc/tests/linux_test1.c b/util/romcc/tests/linux_test1.c
new file mode 100644 (file)
index 0000000..ee82148
--- /dev/null
@@ -0,0 +1,8 @@
+#include "linux_syscall.h"
+
+static void main(void)
+{
+       static const char msg[] = "hello world\r\n";
+       write(STDOUT_FILENO, msg, sizeof(msg));
+       _exit(0);
+}
diff --git a/util/romcc/tests/linux_test2.c b/util/romcc/tests/linux_test2.c
new file mode 100644 (file)
index 0000000..8f40fa0
--- /dev/null
@@ -0,0 +1,673 @@
+#include "linux_syscall.h"
+#include "linux_console.h"
+
+
+static void setup_coherent_ht_domain(void)
+{
+       static const unsigned int register_values[] = {
+#if 1
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x40) & 0xFF)), 0xfff0f0f0, 0x00010101,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x44) & 0xFF)), 0xfff0f0f0, 0x00010101,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x48) & 0xFF)), 0xfff0f0f0, 0x00010101,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x4c) & 0xFF)), 0xfff0f0f0, 0x00010101,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x50) & 0xFF)), 0xfff0f0f0, 0x00010101,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x54) & 0xFF)), 0xfff0f0f0, 0x00010101,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x58) & 0xFF)), 0xfff0f0f0, 0x00010101,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x5c) & 0xFF)), 0xfff0f0f0, 0x00010101,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x68) & 0xFF)), 0x00800000, 0x0f00840f,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x6C) & 0xFF)), 0xffffff8c, 0x00000000 | (1 << 6) |(1 << 5)| (1 << 4),
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x84) & 0xFF)), 0x00009c05, 0x11110020,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x88) & 0xFF)), 0xfffff0ff, 0x00000200,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((0) & 0x07) << 8) | ((0x94) & 0xFF)), 0xff000000, 0x00ff0000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x44) & 0xFF)), 0x0000f8f8, 0x003f0000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x4C) & 0xFF)), 0x0000f8f8, 0x00000001,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x54) & 0xFF)), 0x0000f8f8, 0x00000002,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x5C) & 0xFF)), 0x0000f8f8, 0x00000003,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x64) & 0xFF)), 0x0000f8f8, 0x00000004,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x6C) & 0xFF)), 0x0000f8f8, 0x00000005,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x74) & 0xFF)), 0x0000f8f8, 0x00000006,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x7C) & 0xFF)), 0x0000f8f8, 0x00000007,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x40) & 0xFF)), 0x0000f8fc, 0x00000003,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x48) & 0xFF)), 0x0000f8fc, 0x00400000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x50) & 0xFF)), 0x0000f8fc, 0x00400000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x58) & 0xFF)), 0x0000f8fc, 0x00400000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x60) & 0xFF)), 0x0000f8fc, 0x00400000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x68) & 0xFF)), 0x0000f8fc, 0x00400000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x70) & 0xFF)), 0x0000f8fc, 0x00400000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x78) & 0xFF)), 0x0000f8fc, 0x00400000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x84) & 0xFF)), 0x00000048, 0x00e1ff00,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x8C) & 0xFF)), 0x00000048, 0x00dfff00,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x94) & 0xFF)), 0x00000048, 0x00e3ff00,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x9C) & 0xFF)), 0x00000048, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xA4) & 0xFF)), 0x00000048, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xAC) & 0xFF)), 0x00000048, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xB4) & 0xFF)), 0x00000048, 0x00000b00,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xBC) & 0xFF)), 0x00000048, 0x00fe0b00,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x80) & 0xFF)), 0x000000f0, 0x00e00003,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x88) & 0xFF)), 0x000000f0, 0x00d80003,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x90) & 0xFF)), 0x000000f0, 0x00e20003,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0x98) & 0xFF)), 0x000000f0, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xA0) & 0xFF)), 0x000000f0, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xA8) & 0xFF)), 0x000000f0, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xB0) & 0xFF)), 0x000000f0, 0x00000a03,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xB8) & 0xFF)), 0x000000f0, 0x00400003,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xC4) & 0xFF)), 0xFE000FC8, 0x0000d000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xCC) & 0xFF)), 0xFE000FC8, 0x000ff000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xD4) & 0xFF)), 0xFE000FC8, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xDC) & 0xFF)), 0xFE000FC8, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xC0) & 0xFF)), 0xFE000FCC, 0x0000d003,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xC8) & 0xFF)), 0xFE000FCC, 0x00001013,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xD0) & 0xFF)), 0xFE000FCC, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xD8) & 0xFF)), 0xFE000FCC, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xE0) & 0xFF)), 0x0000FC88, 0xff000003,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xE4) & 0xFF)), 0x0000FC88, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xE8) & 0xFF)), 0x0000FC88, 0x00000000,
+        ( (((0) & 0xFF) << 16) | (((0x18) & 0x1f) << 11) | (((1) & 0x07) << 8) | ((0xEC) & 0xFF)), 0x0000FC88, 0x00000000,
+#else
+#define PCI_ADDR(BUS, DEV, FN, WHERE) ( \
+       (((BUS) & 0xFF) << 16) | \
+       (((DEV) & 0x1f) << 11) | \
+       (((FN) & 0x07) << 8) | \
+       ((WHERE) & 0xFF))
+
+       /* Routing Table Node i 
+        * F0:0x40 i = 0, 
+        * F0:0x44 i = 1,
+        * F0:0x48 i = 2, 
+        * F0:0x4c i = 3,
+        * F0:0x50 i = 4, 
+        * F0:0x54 i = 5,
+        * F0:0x58 i = 6, 
+        * F0:0x5c i = 7
+        * [ 0: 3] Request Route
+        *     [0] Route to this node
+        *     [1] Route to Link 0
+        *     [2] Route to Link 1
+        *     [3] Route to Link 2
+        * [11: 8] Response Route
+        *     [0] Route to this node
+        *     [1] Route to Link 0
+        *     [2] Route to Link 1
+        *     [3] Route to Link 2
+        * [19:16] Broadcast route
+        *     [0] Route to this node
+        *     [1] Route to Link 0
+        *     [2] Route to Link 1
+        *     [3] Route to Link 2
+        */
+       PCI_ADDR(0, 0x18, 0, 0x40), 0xfff0f0f0, 0x00010101,
+       PCI_ADDR(0, 0x18, 0, 0x44), 0xfff0f0f0, 0x00010101,
+       PCI_ADDR(0, 0x18, 0, 0x48), 0xfff0f0f0, 0x00010101,
+       PCI_ADDR(0, 0x18, 0, 0x4c), 0xfff0f0f0, 0x00010101,
+       PCI_ADDR(0, 0x18, 0, 0x50), 0xfff0f0f0, 0x00010101,
+       PCI_ADDR(0, 0x18, 0, 0x54), 0xfff0f0f0, 0x00010101,
+       PCI_ADDR(0, 0x18, 0, 0x58), 0xfff0f0f0, 0x00010101,
+       PCI_ADDR(0, 0x18, 0, 0x5c), 0xfff0f0f0, 0x00010101,
+
+       /* Hypetransport Transaction Control Register 
+        * F0:0x68
+        * [ 0: 0] Disable read byte probe
+        *         0 = Probes issues
+        *         1 = Probes not issued
+        * [ 1: 1] Disable Read Doubleword probe
+        *         0 = Probes issued
+        *         1 = Probes not issued
+        * [ 2: 2] Disable write byte probes
+        *         0 = Probes issued
+        *         1 = Probes not issued
+        * [ 3: 3] Disable Write Doubleword Probes
+        *         0 = Probes issued
+        *         1 = Probes not issued.
+        * [ 4: 4] Disable Memroy Controller Target Start
+        *         0 = TgtStart packets are generated
+        *         1 = TgtStart packets are not generated.
+        * [ 5: 5] CPU1 Enable
+        *         0 = Second CPU disabled or not present
+        *         1 = Second CPU enabled.
+        * [ 6: 6] CPU Request PassPW
+        *         0 = CPU requests do not pass posted writes
+        *         1 = CPU requests pass posted writes.
+        * [ 7: 7] CPU read Respons PassPW
+        *         0 = CPU Responses do not pass posted writes
+        *         1 = CPU responses pass posted writes.
+        * [ 8: 8] Disable Probe Memory Cancel
+        *         0 = Probes may generate MemCancels
+        *         1 = Probes may not generate MemCancels
+        * [ 9: 9] Disable Remote Probe Memory Cancel.
+        *         0 = Probes hitting dirty blocks generate memory cancel packets
+        *         1 = Only probed caches on the same node as the memory controller
+        *              generate cancel packets.
+        * [10:10] Disable Fill Probe
+        *         0 = Probes issued for cache fills
+        *         1 = Probes not issued for cache fills.
+        * [11:11] Response PassPw
+        *         0 = Downstream response PassPW based on original request
+        *         1 = Downstream response PassPW set to 1
+        * [12:12] Change ISOC to Ordered
+        *         0 = Bit 1 of coherent HT RdSz/WrSz command used for iosynchronous prioritization
+        *         1 = Bit 1 of coherent HT RdSz/WrSz command used for ordering.
+        * [14:13] Buffer Release Priority select 
+        *         00 = 64
+        *         01 = 16
+        *         10 = 8
+        *         11 = 2
+        * [15:15] Limit Coherent HT Configuration Space Range
+        *         0 = No coherent HT configuration space restrictions
+        *         1 = Limit coherent HT configuration space based on node count
+        * [16:16] Local Interrupt Conversion Enable.
+        *         0 = ExtInt/NMI interrups unaffected.
+        *         1 = ExtInt/NMI broadcat interrupts converted to LINT0/1
+        * [17:17] APIC Extended Broadcast Enable.
+        *         0 = APIC broadcast is 0F
+        *         1 = APIC broadcast is FF
+        * [18:18] APIC Extended ID Enable
+        *         0 = APIC ID is 4 bits.
+        *         1 = APIC ID is 8 bits.
+        * [19:19] APIC Extended Spurious Vector Enable
+        *         0 = Lower 4 bits of spurious vector are read-only 1111
+        *         1 = Lower 4 bits of spurious vecotr are writeable.
+        * [20:20] Sequence ID Source Node Enable
+        *         0 = Normal operation
+        *         1 = Keep SeqID on routed packets for debugging.
+        * [22:21] Downstream non-posted request limit
+        *         00 = No limit
+        *         01 = Limited to 1
+        *         10 = Limited to 4
+        *         11 = Limited to 8
+        * [23:23] RESERVED
+        * [25:24] Medium-Priority Bypass Count
+        *         - Maximum # of times a medium priority access can pass a low
+        *           priority access before Medium-Priority mode is disabled for one access.
+        * [27:26] High-Priority Bypass Count
+        *         - Maximum # of times a high prioirty access can pass a medium or low
+        *           priority access before High-prioirty mode is disabled for one access.
+        * [28:28] Enable High Priority CPU Reads
+        *         0 = Cpu reads are medium prioirty
+        *         1 = Cpu reads are high prioirty
+        * [29:29] Disable Low Priority Writes
+        *         0 = Non-isochronous writes are low priority
+        *         1 = Non-isochronous writes are medium prioirty
+        * [30:30] Disable High Priority Isochronous writes
+        *         0 = Isochronous writes are high priority
+        *         1 = Isochronous writes are medium priority
+        * [31:31] Disable Medium Priority Isochronous writes
+        *         0 = Isochronous writes are medium are high
+        *         1 = With bit 30 set makes Isochrouns writes low priority.
+        */
+       PCI_ADDR(0, 0x18, 0, 0x68), 0x00800000, 0x0f00840f,
+       /* HT Initialization Control Register
+        * F0:0x6C
+        * [ 0: 0] Routing Table Disable
+        *         0 = Packets are routed according to routing tables
+        *         1 = Packets are routed according to the default link field
+        * [ 1: 1] Request Disable (BSP should clear this)
+        *         0 = Request packets may be generated
+        *         1 = Request packets may not be generated.
+        * [ 3: 2] Default Link (Read-only)
+        *         00 = LDT0
+        *         01 = LDT1
+        *         10 = LDT2
+        *         11 = CPU on same node
+        * [ 4: 4] Cold Reset
+        *         - Scratch bit cleared by a cold reset
+        * [ 5: 5] BIOS Reset Detect
+        *         - Scratch bit cleared by a cold reset
+        * [ 6: 6] INIT Detect
+        *         - Scratch bit cleared by a warm or cold reset not by an INIT
+        *
+        */
+       PCI_ADDR(0, 0x18, 0, 0x6C), 0xffffff8c, 0x00000000 | (1 << 6) |(1 << 5)| (1 << 4),
+       /* LDTi Capabilities Registers
+        * F0:0x80 i = 0,
+        * F0:0xA0 i = 1,
+        * F0:0xC0 i = 2,
+        */
+       /* LDTi Link Control Registrs
+        * F0:0x84 i = 0,
+        * F0:0xA4 i = 1,
+        * F0:0xC4 i = 2,
+        * [ 1: 1] CRC Flood Enable
+        *         0 = Do not generate sync packets on CRC error
+        *         1 = Generate sync packets on CRC error
+        * [ 2: 2] CRC Start Test (Read-Only)
+        * [ 3: 3] CRC Force Frame Error
+        *         0 = Do not generate bad CRC
+        *         1 = Generate bad CRC
+        * [ 4: 4] Link Failure
+        *         0 = No link failure detected
+        *         1 = Link failure detected
+        * [ 5: 5] Initialization Complete
+        *         0 = Initialization not complete
+        *         1 = Initialization complete
+        * [ 6: 6] Receiver off
+        *         0 = Recevier on
+        *         1 = Receiver off
+        * [ 7: 7] Transmitter Off
+        *         0 = Transmitter on
+        *         1 = Transmitter off
+        * [ 9: 8] CRC_Error
+        *         00 = No error
+        *         [0] = 1 Error on byte lane 0
+        *         [1] = 1 Error on byte lane 1
+        * [12:12] Isochrnous Enable  (Read-Only)
+        * [13:13] HT Stop Tristate Enable
+        *         0 = Driven during an LDTSTOP_L
+        *         1 = Tristated during and LDTSTOP_L
+        * [14:14] Extended CTL Time 
+        *         0 = CTL is asserted for 16 bit times during link initialization
+        *         1 = CTL is asserted for 50us during link initialization
+        * [18:16] Max Link Width In (Read-Only?)
+        *         000 = 8 bit link
+        *         001 = 16bit link
+        * [19:19] Doubleword Flow Control in (Read-Only)
+        *         0 = This link does not support doubleword flow control
+        *         1 = This link supports doubleword flow control
+        * [22:20] Max Link Width Out (Read-Only?)
+        *         000 = 8 bit link
+        *         001 = 16bit link
+        * [23:23] Doubleworld Flow Control out (Read-Only)
+        *         0 = This link does not support doubleword flow control
+        *         1 = This link supports doubleworkd flow control
+        * [26:24] Link Width In
+        *         000 = Use 8 bits
+        *         001 = Use 16 bits
+        *         010 = reserved
+        *         011 = Use 32 bits
+        *         100 = Use 2 bits
+        *         101 = Use 4 bits
+        *         110 = reserved
+        *         111 = Link physically not connected
+        * [27:27] Doubleword Flow Control In Enable
+        *         0 = Doubleword flow control disabled
+        *         1 = Doubleword flow control enabled (Not currently supported)
+        * [30:28] Link Width Out
+        *         000 = Use 8 bits
+        *         001 = Use 16 bits
+        *         010 = reserved
+        *         011 = Use 32 bits
+        *         100 = Use 2 bits
+        *         101 = Use 4 bits
+        *         110 = reserved
+        *         111 = Link physically not connected
+        * [31:31] Doubleworld Flow Control Out Enable
+        *         0 = Doubleworld flow control disabled
+        *         1 = Doubleword flow control enabled (Not currently supported)
+        */
+       PCI_ADDR(0, 0x18, 0, 0x84), 0x00009c05, 0x11110020,
+       /* LDTi Frequency/Revision Registers
+        * F0:0x88 i = 0,
+        * F0:0xA8 i = 1,
+        * F0:0xC8 i = 2,
+        * [ 4: 0] Minor Revision
+        *         Contains the HT Minor revision
+        * [ 7: 5] Major Revision
+        *         Contains the HT Major revision
+        * [11: 8] Link Frequency  (Takes effect the next time the link is reconnected)
+        *         0000 = 200Mhz
+        *         0001 = reserved
+        *         0010 = 400Mhz
+        *         0011 = reserved
+        *         0100 = 600Mhz
+        *         0101 = 800Mhz
+        *         0110 = 1000Mhz
+        *         0111 = reserved
+        *         1000 = reserved
+        *         1001 = reserved
+        *         1010 = reserved
+        *         1011 = reserved
+        *         1100 = reserved
+        *         1101 = reserved
+        *         1110 = reserved
+        *         1111 = 100 Mhz
+        * [15:12] Error (Not currently Implemented)
+        * [31:16] Indicates the frequency capabilities of the link
+        *         [16] = 1 encoding 0000 of freq supported
+        *         [17] = 1 encoding 0001 of freq supported
+        *         [18] = 1 encoding 0010 of freq supported
+        *         [19] = 1 encoding 0011 of freq supported
+        *         [20] = 1 encoding 0100 of freq supported
+        *         [21] = 1 encoding 0101 of freq supported
+        *         [22] = 1 encoding 0110 of freq supported
+        *         [23] = 1 encoding 0111 of freq supported
+        *         [24] = 1 encoding 1000 of freq supported
+        *         [25] = 1 encoding 1001 of freq supported
+        *         [26] = 1 encoding 1010 of freq supported
+        *         [27] = 1 encoding 1011 of freq supported
+        *         [28] = 1 encoding 1100 of freq supported
+        *         [29] = 1 encoding 1101 of freq supported
+        *         [30] = 1 encoding 1110 of freq supported
+        *         [31] = 1 encoding 1111 of freq supported
+        */
+       PCI_ADDR(0, 0x18, 0, 0x88), 0xfffff0ff, 0x00000200,
+       /* LDTi Feature Capability
+        * F0:0x8C i = 0,
+        * F0:0xAC i = 1,
+        * F0:0xCC i = 2,
+        */
+       /* LDTi Buffer Count Registers
+        * F0:0x90 i = 0,
+        * F0:0xB0 i = 1,
+        * F0:0xD0 i = 2,
+        */
+       /* LDTi Bus Number Registers
+        * F0:0x94 i = 0,
+        * F0:0xB4 i = 1,
+        * F0:0xD4 i = 2,
+        * For NonCoherent HT specifies the bus number downstream (behind the host bridge)
+        * [ 0: 7] Primary Bus Number
+        * [15: 8] Secondary Bus Number
+        * [23:15] Subordiante Bus Number
+        * [31:24] reserved
+        */
+       PCI_ADDR(0, 0x18, 0, 0x94), 0xff000000, 0x00ff0000,
+       /* LDTi Type Registers
+        * F0:0x98 i = 0,
+        * F0:0xB8 i = 1,
+        * F0:0xD8 i = 2,
+        */
+       /* Careful set limit registers before base registers which contain the enables */
+       /* DRAM Limit i Registers
+        * F1:0x44 i = 0
+        * F1:0x4C i = 1
+        * F1:0x54 i = 2
+        * F1:0x5C i = 3
+        * F1:0x64 i = 4
+        * F1:0x6C i = 5
+        * F1:0x74 i = 6
+        * F1:0x7C i = 7
+        * [ 2: 0] Destination Node ID
+        *         000 = Node 0
+        *         001 = Node 1
+        *         010 = Node 2
+        *         011 = Node 3
+        *         100 = Node 4
+        *         101 = Node 5
+        *         110 = Node 6
+        *         111 = Node 7
+        * [ 7: 3] Reserved
+        * [10: 8] Interleave select
+        *         specifies the values of A[14:12] to use with interleave enable.
+        * [15:11] Reserved
+        * [31:16] DRAM Limit Address i Bits 39-24
+        *         This field defines the upper address bits of a 40 bit  address
+        *         that define the end of the DRAM region.
+        */
+#if MEMORY_1024MB
+       PCI_ADDR(0, 0x18, 1, 0x44), 0x0000f8f8, 0x003f0000,
+#endif
+#if MEMORY_512MB
+       PCI_ADDR(0, 0x18, 1, 0x44), 0x0000f8f8, 0x001f0000,
+#endif
+       PCI_ADDR(0, 0x18, 1, 0x4C), 0x0000f8f8, 0x00000001,
+       PCI_ADDR(0, 0x18, 1, 0x54), 0x0000f8f8, 0x00000002,
+       PCI_ADDR(0, 0x18, 1, 0x5C), 0x0000f8f8, 0x00000003,
+       PCI_ADDR(0, 0x18, 1, 0x64), 0x0000f8f8, 0x00000004,
+       PCI_ADDR(0, 0x18, 1, 0x6C), 0x0000f8f8, 0x00000005,
+       PCI_ADDR(0, 0x18, 1, 0x74), 0x0000f8f8, 0x00000006,
+       PCI_ADDR(0, 0x18, 1, 0x7C), 0x0000f8f8, 0x00000007,
+       /* DRAM Base i Registers
+        * F1:0x40 i = 0
+        * F1:0x48 i = 1
+        * F1:0x50 i = 2
+        * F1:0x58 i = 3
+        * F1:0x60 i = 4
+        * F1:0x68 i = 5
+        * F1:0x70 i = 6
+        * F1:0x78 i = 7
+        * [ 0: 0] Read Enable
+        *         0 = Reads Disabled
+        *         1 = Reads Enabled
+        * [ 1: 1] Write Enable
+        *         0 = Writes Disabled
+        *         1 = Writes Enabled
+        * [ 7: 2] Reserved
+        * [10: 8] Interleave Enable
+        *         000 = No interleave
+        *         001 = Interleave on A[12] (2 nodes)
+        *         010 = reserved
+        *         011 = Interleave on A[12] and A[14] (4 nodes)
+        *         100 = reserved
+        *         101 = reserved
+        *         110 = reserved
+        *         111 = Interleve on A[12] and A[13] and A[14] (8 nodes)
+        * [15:11] Reserved
+        * [13:16] DRAM Base Address i Bits 39-24
+        *         This field defines the upper address bits of a 40-bit address
+        *         that define the start of the DRAM region.
+        */
+       PCI_ADDR(0, 0x18, 1, 0x40), 0x0000f8fc, 0x00000003,
+#if MEMORY_1024MB
+       PCI_ADDR(0, 0x18, 1, 0x48), 0x0000f8fc, 0x00400000,
+       PCI_ADDR(0, 0x18, 1, 0x50), 0x0000f8fc, 0x00400000,
+       PCI_ADDR(0, 0x18, 1, 0x58), 0x0000f8fc, 0x00400000,
+       PCI_ADDR(0, 0x18, 1, 0x60), 0x0000f8fc, 0x00400000,
+       PCI_ADDR(0, 0x18, 1, 0x68), 0x0000f8fc, 0x00400000,
+       PCI_ADDR(0, 0x18, 1, 0x70), 0x0000f8fc, 0x00400000,
+       PCI_ADDR(0, 0x18, 1, 0x78), 0x0000f8fc, 0x00400000,
+#endif
+#if MEMORY_512MB
+       PCI_ADDR(0, 0x18, 1, 0x48), 0x0000f8fc, 0x00200000,
+       PCI_ADDR(0, 0x18, 1, 0x50), 0x0000f8fc, 0x00200000,
+       PCI_ADDR(0, 0x18, 1, 0x58), 0x0000f8fc, 0x00200000,
+       PCI_ADDR(0, 0x18, 1, 0x60), 0x0000f8fc, 0x00200000,
+       PCI_ADDR(0, 0x18, 1, 0x68), 0x0000f8fc, 0x00200000,
+       PCI_ADDR(0, 0x18, 1, 0x70), 0x0000f8fc, 0x00200000,
+       PCI_ADDR(0, 0x18, 1, 0x78), 0x0000f8fc, 0x00200000,
+#endif
+
+       /* Memory-Mapped I/O Limit i Registers
+        * F1:0x84 i = 0
+        * F1:0x8C i = 1
+        * F1:0x94 i = 2
+        * F1:0x9C i = 3
+        * F1:0xA4 i = 4
+        * F1:0xAC i = 5
+        * F1:0xB4 i = 6
+        * F1:0xBC i = 7
+        * [ 2: 0] Destination Node ID
+        *         000 = Node 0
+        *         001 = Node 1
+        *         010 = Node 2
+        *         011 = Node 3
+        *         100 = Node 4
+        *         101 = Node 5
+        *         110 = Node 6
+        *         111 = Node 7
+        * [ 3: 3] Reserved
+        * [ 5: 4] Destination Link ID
+        *         00 = Link 0
+        *         01 = Link 1
+        *         10 = Link 2
+        *         11 = Reserved
+        * [ 6: 6] Reserved
+        * [ 7: 7] Non-Posted
+        *         0 = CPU writes may be posted
+        *         1 = CPU writes must be non-posted
+        * [31: 8] Memory-Mapped I/O Limit Address i (39-16)
+        *         This field defines the upp adddress bits of a 40-bit address that
+        *         defines the end of a memory-mapped I/O region n
+        */
+       PCI_ADDR(0, 0x18, 1, 0x84), 0x00000048, 0x00e1ff00,
+       PCI_ADDR(0, 0x18, 1, 0x8C), 0x00000048, 0x00dfff00,
+       PCI_ADDR(0, 0x18, 1, 0x94), 0x00000048, 0x00e3ff00,
+       PCI_ADDR(0, 0x18, 1, 0x9C), 0x00000048, 0x00000000,
+       PCI_ADDR(0, 0x18, 1, 0xA4), 0x00000048, 0x00000000,
+       PCI_ADDR(0, 0x18, 1, 0xAC), 0x00000048, 0x00000000,
+       PCI_ADDR(0, 0x18, 1, 0xB4), 0x00000048, 0x00000b00,
+       PCI_ADDR(0, 0x18, 1, 0xBC), 0x00000048, 0x00fe0b00,
+
+       /* Memory-Mapped I/O Base i Registers
+        * F1:0x80 i = 0
+        * F1:0x88 i = 1
+        * F1:0x90 i = 2
+        * F1:0x98 i = 3
+        * F1:0xA0 i = 4
+        * F1:0xA8 i = 5
+        * F1:0xB0 i = 6
+        * F1:0xB8 i = 7
+        * [ 0: 0] Read Enable
+        *         0 = Reads disabled
+        *         1 = Reads Enabled
+        * [ 1: 1] Write Enable
+        *         0 = Writes disabled
+        *         1 = Writes Enabled
+        * [ 2: 2] Cpu Disable
+        *         0 = Cpu can use this I/O range
+        *         1 = Cpu requests do not use this I/O range
+        * [ 3: 3] Lock
+        *         0 = base/limit registers i are read/write
+        *         1 = base/limit registers i are read-only
+        * [ 7: 4] Reserved
+        * [31: 8] Memory-Mapped I/O Base Address i (39-16)
+        *         This field defines the upper address bits of a 40bit address 
+        *         that defines the start of memory-mapped I/O region i
+        */
+       PCI_ADDR(0, 0x18, 1, 0x80), 0x000000f0, 0x00e00003,
+       PCI_ADDR(0, 0x18, 1, 0x88), 0x000000f0, 0x00d80003,
+       PCI_ADDR(0, 0x18, 1, 0x90), 0x000000f0, 0x00e20003,
+       PCI_ADDR(0, 0x18, 1, 0x98), 0x000000f0, 0x00000000,
+       PCI_ADDR(0, 0x18, 1, 0xA0), 0x000000f0, 0x00000000,
+       PCI_ADDR(0, 0x18, 1, 0xA8), 0x000000f0, 0x00000000,
+       PCI_ADDR(0, 0x18, 1, 0xB0), 0x000000f0, 0x00000a03,
+#if MEMORY_1024MB
+       PCI_ADDR(0, 0x18, 1, 0xB8), 0x000000f0, 0x00400003,
+#endif
+#if MEMORY_512MB
+       PCI_ADDR(0, 0x18, 1, 0xB8), 0x000000f0, 0x00200003,
+#endif
+
+       /* PCI I/O Limit i Registers
+        * F1:0xC4 i = 0
+        * F1:0xCC i = 1
+        * F1:0xD4 i = 2
+        * F1:0xDC i = 3
+        * [ 2: 0] Destination Node ID
+        *         000 = Node 0
+        *         001 = Node 1
+        *         010 = Node 2
+        *         011 = Node 3
+        *         100 = Node 4
+        *         101 = Node 5
+        *         110 = Node 6
+        *         111 = Node 7
+        * [ 3: 3] Reserved
+        * [ 5: 4] Destination Link ID
+        *         00 = Link 0
+        *         01 = Link 1
+        *         10 = Link 2
+        *         11 = reserved
+        * [11: 6] Reserved
+        * [24:12] PCI I/O Limit Address i
+        *         This field defines the end of PCI I/O region n
+        * [31:25] Reserved
+        */
+       PCI_ADDR(0, 0x18, 1, 0xC4), 0xFE000FC8, 0x0000d000,
+       PCI_ADDR(0, 0x18, 1, 0xCC), 0xFE000FC8, 0x000ff000,
+       PCI_ADDR(0, 0x18, 1, 0xD4), 0xFE000FC8, 0x00000000,
+       PCI_ADDR(0, 0x18, 1, 0xDC), 0xFE000FC8, 0x00000000,
+
+       /* PCI I/O Base i Registers
+        * F1:0xC0 i = 0
+        * F1:0xC8 i = 1
+        * F1:0xD0 i = 2
+        * F1:0xD8 i = 3
+        * [ 0: 0] Read Enable
+        *         0 = Reads Disabled
+        *         1 = Reads Enabled
+        * [ 1: 1] Write Enable
+        *         0 = Writes Disabled
+        *         1 = Writes Enabled
+        * [ 3: 2] Reserved
+        * [ 4: 4] VGA Enable
+        *         0 = VGA matches Disabled
+        *         1 = matches all address < 64K and where A[9:0] is in the 
+        *             range 3B0-3BB or 3C0-3DF independen of the base & limit registers
+        * [ 5: 5] ISA Enable
+        *         0 = ISA matches Disabled
+        *         1 = Blocks address < 64K and in the last 768 bytes of eack 1K block
+        *             from matching agains this base/limit pair
+        * [11: 6] Reserved
+        * [24:12] PCI I/O Base i
+        *         This field defines the start of PCI I/O region n 
+        * [31:25] Reserved
+        */
+       PCI_ADDR(0, 0x18, 1, 0xC0), 0xFE000FCC, 0x0000d003,
+       PCI_ADDR(0, 0x18, 1, 0xC8), 0xFE000FCC, 0x00001013,
+       PCI_ADDR(0, 0x18, 1, 0xD0), 0xFE000FCC, 0x00000000,
+       PCI_ADDR(0, 0x18, 1, 0xD8), 0xFE000FCC, 0x00000000,
+
+       /* Config Base and Limit i Registers
+        * F1:0xE0 i = 0
+        * F1:0xE4 i = 1
+        * F1:0xE8 i = 2
+        * F1:0xEC i = 3
+        * [ 0: 0] Read Enable
+        *         0 = Reads Disabled
+        *         1 = Reads Enabled
+        * [ 1: 1] Write Enable
+        *         0 = Writes Disabled
+        *         1 = Writes Enabled
+        * [ 2: 2] Device Number Compare Enable
+        *         0 = The ranges are based on bus number
+        *         1 = The ranges are ranges of devices on bus 0
+        * [ 3: 3] Reserved
+        * [ 6: 4] Destination Node
+        *         000 = Node 0
+        *         001 = Node 1
+        *         010 = Node 2
+        *         011 = Node 3
+        *         100 = Node 4
+        *         101 = Node 5
+        *         110 = Node 6
+        *         111 = Node 7
+        * [ 7: 7] Reserved
+        * [ 9: 8] Destination Link
+        *         00 = Link 0
+        *         01 = Link 1
+        *         10 = Link 2
+        *         11 - Reserved
+        * [15:10] Reserved
+        * [23:16] Bus Number Base i
+        *         This field defines the lowest bus number in configuration region i
+        * [31:24] Bus Number Limit i
+        *         This field defines the highest bus number in configuration regin i
+        */
+       PCI_ADDR(0, 0x18, 1, 0xE0), 0x0000FC88, 0xff000003,
+       PCI_ADDR(0, 0x18, 1, 0xE4), 0x0000FC88, 0x00000000,
+       PCI_ADDR(0, 0x18, 1, 0xE8), 0x0000FC88, 0x00000000,
+       PCI_ADDR(0, 0x18, 1, 0xEC), 0x0000FC88, 0x00000000,
+#endif
+       };
+       int i;
+       int max;
+       print_debug("setting up coherent ht domain....\r\n");
+       max = sizeof(register_values)/sizeof(register_values[0]);
+       for(i = 0; i < max; i += 3) {
+               unsigned long reg;
+#if 1
+               print_debug_hex32(register_values[i]);
+               print_debug(" <-");
+               print_debug_hex32(register_values[i+2]);
+               print_debug("\r\n");
+#endif
+#if 0
+               reg = pci_read_config32(register_values[i]);
+               reg &= register_values[i+1];
+               reg |= register_values[i+2] & ~register_values[i+1];
+               pci_write_config32(register_values[i], reg);
+#endif
+       }
+       print_debug("done.\r\n");
+}
+
+static void main(void)
+{
+       static const char msg[] = "hello world\r\n";
+#if 0
+       write(STDOUT_FILENO, msg, sizeof(msg));
+#endif
+#if 1
+       setup_coherent_ht_domain();
+#endif
+       _exit(0);
+}
diff --git a/util/romcc/tests/linux_test3.c b/util/romcc/tests/linux_test3.c
new file mode 100644 (file)
index 0000000..97187ae
--- /dev/null
@@ -0,0 +1,28 @@
+#include "linux_syscall.h"
+#include "linux_console.h"
+static void goto_test(void)
+{
+       int i;
+       print_debug("goto_test\n");
+       
+       i = 0;
+       goto bottom;
+       {
+       top:
+               print_debug("i = "); 
+               print_debug_hex8(i); 
+               print_debug("\n");
+               
+               i = i + 1;
+       }
+ bottom:
+       if (i < 10) {
+               goto top;
+       }
+}
+
+static void main(void)
+{
+       goto_test();
+       _exit(0);
+}
diff --git a/util/romcc/tests/linux_test4.c b/util/romcc/tests/linux_test4.c
new file mode 100644 (file)
index 0000000..1f09918
--- /dev/null
@@ -0,0 +1,46 @@
+#include "linux_syscall.h"
+#include "linux_console.h"
+
+struct socket_desc {
+       short up;
+       short down;
+       short across;
+};
+
+static void main(void) 
+{
+       static const struct socket_desc cpu_socketsA[] = {
+               {  .up = 2,  .down = -1, .across = 1 }, /* Node 0 */
+               {  .up = 3,  .down = -1, .across = 0 }, /* Node 1 */
+               {  .up = -1, .down =  0, .across = 3 }, /* Node 2 */
+               {  .up = -1, .down =  1, .across = 2 }  /* Node 3 */
+       };
+       static const struct socket_desc cpu_socketsB[4] = {
+               {  2,  -1, 1 }, /* Node 0 */
+               {  3,  -1, 0 }, /* Node 1 */
+               {  -1,  0, 3 }, /* Node 2 */
+               {  -1,  1, 2 }  /* Node 3 */
+       };
+       int i;
+       print_debug("cpu_socketA\n");
+       for(i = 0; i < sizeof(cpu_socketsA)/sizeof(cpu_socketsA[0]); i++) {
+               print_debug(".up=");
+               print_debug_hex16(cpu_socketsA[i].up);
+               print_debug(" .down=");
+               print_debug_hex16(cpu_socketsA[i].down);
+               print_debug(" .across=");
+               print_debug_hex16(cpu_socketsA[i].across);
+               print_debug("\n");
+       }
+       print_debug("\ncpu_socketB\n");
+       for(i = 0; i < sizeof(cpu_socketsB)/sizeof(cpu_socketsB[0]); i++) {
+               print_debug(".up=");
+               print_debug_hex16(cpu_socketsB[i].up);
+               print_debug(" .down=");
+               print_debug_hex16(cpu_socketsB[i].down);
+               print_debug(" .across=");
+               print_debug_hex16(cpu_socketsB[i].across);
+               print_debug("\n");
+       }
+       _exit(0);
+}
diff --git a/util/romcc/tests/linux_test5.c b/util/romcc/tests/linux_test5.c
new file mode 100644 (file)
index 0000000..55613c2
--- /dev/null
@@ -0,0 +1,359 @@
+#include "linux_syscall.h"
+#include "linux_console.h"
+
+int log2(int value)
+{
+       /* __builtin_bsr is a exactly equivalent to the x86 machine
+        * instruction with the exception that it returns -1  
+        * when the value presented to it is zero.
+        * Otherwise __builtin_bsr returns the zero based index of
+        * the highest bit set.
+        */
+       return __builtin_bsr(value);
+}
+
+
+static int smbus_read_byte(unsigned device, unsigned address)
+{
+       static const unsigned char dimm[] = {
+0x80, 0x08, 0x07, 0x0d, 0x0a, 0x02, 0x48, 0x00, 0x04, 0x60, 0x70, 0x02, 0x82, 0x08, 0x08, 0x01,
+0x0e, 0x04, 0x0c, 0x01, 0x02, 0x20, 0x00, 0x75, 0x70, 0x00, 0x00, 0x48, 0x30, 0x48, 0x2a, 0x40,
+0x80, 0x80, 0x45, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+
+0x80, 0x08, 0x07, 0x0d, 0x0a, 0x02, 0x48, 0x00, 0x04, 0x60, 0x70, 0x02, 0x82, 0x08, 0x08, 0x01,
+0x0e, 0x04, 0x0c, 0x01, 0x02, 0x20, 0x00, 0x75, 0x70, 0x00, 0x00, 0x48, 0x30, 0x48, 0x2a, 0x40,
+0x80, 0x80, 0x45, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       };
+       return dimm[(device << 8) + address];
+}
+
+#define SMBUS_MEM_DEVICE_START 0x00
+#define SMBUS_MEM_DEVICE_END   0x01
+#define SMBUS_MEM_DEVICE_INC   1
+
+/* Function 2 */
+#define DRAM_CONFIG_HIGH   0x94
+#define  DCH_MEMCLK_SHIFT  20
+#define  DCH_MEMCLK_MASK   7
+#define  DCH_MEMCLK_100MHZ 0
+#define  DCH_MEMCLK_133MHZ 2
+#define  DCH_MEMCLK_166MHZ 5
+#define  DCH_MEMCLK_200MHZ 7
+
+/* Function 3 */
+#define NORTHBRIDGE_CAP    0xE8
+#define  NBCAP_128Bit         0x0001
+#define  NBCAP_MP             0x0002
+#define  NBCAP_BIG_MP         0x0004
+#define  NBCAP_ECC            0x0004
+#define  NBCAP_CHIPKILL_ECC   0x0010
+#define  NBCAP_MEMCLK_SHIFT   5
+#define  NBCAP_MEMCLK_MASK    3
+#define  NBCAP_MEMCLK_100MHZ  3
+#define  NBCAP_MEMCLK_133MHZ  2
+#define  NBCAP_MEMCLK_166MHZ  1
+#define  NBCAP_MEMCLK_200MHZ  0
+#define  NBCAP_MEMCTRL        0x0100
+
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+
+static unsigned spd_to_dimm(unsigned device)
+{
+       return (device - SMBUS_MEM_DEVICE_START);
+}
+
+static void disable_dimm(unsigned index)
+{
+       print_debug("disabling dimm"); 
+       print_debug_hex8(index); 
+       print_debug("\r\n");
+#if 0
+       pci_write_config32(PCI_DEV(0, 0x18, 2), DRAM_CSBASE + (((index << 1)+0)<<2), 0);
+       pci_write_config32(PCI_DEV(0, 0x18, 2), DRAM_CSBASE + (((index << 1)+1)<<2), 0);
+#endif
+}
+
+
+struct mem_param {
+       uint8_t cycle_time;
+       uint32_t dch_memclk;
+};
+
+static const struct mem_param *get_mem_param(unsigned min_cycle_time)
+{
+       static const struct mem_param speed[] = {
+               {
+                       .cycle_time = 0xa0,
+                       .dch_memclk = DCH_MEMCLK_100MHZ << DCH_MEMCLK_SHIFT,
+               },
+               {
+                       .cycle_time = 0x75,
+                       .dch_memclk = DCH_MEMCLK_133MHZ << DCH_MEMCLK_SHIFT,
+               },
+               {
+                       .cycle_time = 0x60,
+                       .dch_memclk = DCH_MEMCLK_166MHZ << DCH_MEMCLK_SHIFT,
+               },
+               {
+                       .cycle_time = 0x50,
+                       .dch_memclk = DCH_MEMCLK_200MHZ << DCH_MEMCLK_SHIFT,
+               },
+               {
+                       .cycle_time = 0x00,
+               },
+       };
+       const struct mem_param *param;
+       for(param = &speed[0]; param->cycle_time ; param++) {
+               if (min_cycle_time > (param+1)->cycle_time) {
+                       break;
+               }
+       }
+       if (!param->cycle_time) {
+               die("min_cycle_time to low");
+       }
+       return param;
+}
+
+#if 1
+static void debug(int c)
+{
+       print_debug_char(c);
+       print_debug_char('\r');
+       print_debug_char('\n');
+}
+#endif
+static const struct mem_param *spd_set_memclk(void)
+{
+       /* Compute the minimum cycle time for these dimms */
+       const struct mem_param *param;
+       unsigned min_cycle_time, min_latency;
+       unsigned device;
+       uint32_t value;
+
+       static const int latency_indicies[] = { 26, 23, 9 };
+       static const unsigned char min_cycle_times[] = {
+               [NBCAP_MEMCLK_200MHZ] = 0x50, /* 5ns */
+               [NBCAP_MEMCLK_166MHZ] = 0x60, /* 6ns */
+               [NBCAP_MEMCLK_133MHZ] = 0x75, /* 7.5ns */
+               [NBCAP_MEMCLK_100MHZ] = 0xa0, /* 10ns */
+       };
+
+
+#if 0
+       value = pci_read_config32(PCI_DEV(0, 0x18, 3), NORTHBRIDGE_CAP);
+#else
+       value = 0x50;
+#endif
+       min_cycle_time = min_cycle_times[(value >> NBCAP_MEMCLK_SHIFT) & NBCAP_MEMCLK_MASK];
+       min_latency = 2;
+
+#if 1
+       print_debug("min_cycle_time: "); 
+       print_debug_hex8(min_cycle_time); 
+       print_debug(" min_latency: ");
+       print_debug_hex8(min_latency);
+       print_debug("\r\n");
+#endif
+
+       /* Compute the least latency with the fastest clock supported
+        * by both the memory controller and the dimms.
+        */
+       for(device = SMBUS_MEM_DEVICE_START;
+               device <= SMBUS_MEM_DEVICE_END;
+               device += SMBUS_MEM_DEVICE_INC)
+       {
+               int new_cycle_time, new_latency;
+               int index;
+               int latencies;
+               int latency;
+
+               debug('A');
+               /* First find the supported CAS latencies
+                * Byte 18 for DDR SDRAM is interpreted:
+                * bit 0 == CAS Latency = 1.0
+                * bit 1 == CAS Latency = 1.5
+                * bit 2 == CAS Latency = 2.0
+                * bit 3 == CAS Latency = 2.5
+                * bit 4 == CAS Latency = 3.0
+                * bit 5 == CAS Latency = 3.5
+                * bit 6 == TBD
+                * bit 7 == TBD
+                */
+               new_cycle_time = 0xa0;
+               new_latency = 5;
+
+               latencies = smbus_read_byte(device, 18);
+               if (latencies <= 0) continue;
+
+               debug('B');
+               /* Compute the lowest cas latency supported */
+               latency = log2(latencies) -2;
+
+               /* Loop through and find a fast clock with a low latency */
+               for(index = 0; index < 3; index++, latency++) {
+                       int value;
+                       debug('C');
+                       if ((latency < 2) || (latency > 4) ||
+                               (!(latencies & (1 << latency)))) {
+                               continue;
+                       }
+                       debug('D');
+                       value = smbus_read_byte(device, latency_indicies[index]);
+                       if (value < 0) continue;
+
+                       debug('E');
+                       /* Only increase the latency if we decreas the clock */
+                       if ((value >= min_cycle_time) && (value < new_cycle_time)) {
+                               new_cycle_time = value;
+                               new_latency = latency;
+#if 1
+                               print_debug("device: ");
+                               print_debug_hex8(device);
+                               print_debug(" new_cycle_time: "); 
+                               print_debug_hex8(new_cycle_time); 
+                               print_debug(" new_latency: ");
+                               print_debug_hex8(new_latency);
+                               print_debug("\r\n");
+#endif
+                       }
+                       debug('G');
+               }
+               debug('H');
+#if 1
+               print_debug("device: ");
+               print_debug_hex8(device);
+               print_debug(" new_cycle_time: "); 
+               print_debug_hex8(new_cycle_time); 
+               print_debug(" new_latency: ");
+               print_debug_hex8(new_latency);
+               print_debug("\r\n");
+#endif
+               if (new_latency > 4){
+                       continue;
+               }
+               debug('I');
+               /* Does min_latency need to be increased? */
+               if (new_cycle_time > min_cycle_time) {
+                       min_cycle_time = new_cycle_time;
+               }
+               /* Does min_cycle_time need to be increased? */
+               if (new_latency > min_latency) {
+                       min_latency = new_latency;
+               }
+#if 1
+               print_debug("device: ");
+               print_debug_hex8(device);
+               print_debug(" min_cycle_time: "); 
+               print_debug_hex8(min_cycle_time); 
+               print_debug(" min_latency: ");
+               print_debug_hex8(min_latency);
+               print_debug("\r\n");
+#endif
+       }
+       /* Make a second pass through the dimms and disable
+        * any that cannot support the selected memclk and cas latency.
+        */
+       for(device = SMBUS_MEM_DEVICE_START;
+               device <= SMBUS_MEM_DEVICE_END;
+               device += SMBUS_MEM_DEVICE_INC)
+       {
+               int latencies;
+               int latency;
+               int index;
+               int value;
+               int dimm;
+               latencies = smbus_read_byte(device, 18);
+               if (latencies <= 0) {
+                       goto dimm_err;
+               }
+
+               /* Compute the lowest cas latency supported */
+               latency = log2(latencies) -2;
+
+               /* Walk through searching for the selected latency */
+               for(index = 0; index < 3; index++, latency++) {
+                       if (!(latencies & (1 << latency))) {
+                               continue;
+                       }
+                       if (latency == min_latency)
+                               break;
+               }
+               /* If I can't find the latency or my index is bad error */
+               if ((latency != min_latency) || (index >= 3)) {
+                       goto dimm_err;
+               }
+               
+               /* Read the min_cycle_time for this latency */
+               value = smbus_read_byte(device, latency_indicies[index]);
+               
+               /* All is good if the selected clock speed 
+                * is what I need or slower.
+                */
+               if (value <= min_cycle_time) {
+                       continue;
+               }
+               /* Otherwise I have an error, disable the dimm */
+       dimm_err:
+               disable_dimm(spd_to_dimm(device));
+       }
+#if 1
+       print_debug("min_cycle_time: "); 
+       print_debug_hex8(min_cycle_time); 
+       print_debug(" min_latency: ");
+       print_debug_hex8(min_latency);
+       print_debug("\r\n");
+#endif
+       /* Now that I know the minimum cycle time lookup the memory parameters */
+       param = get_mem_param(min_cycle_time);
+
+#if 0
+       /* Update DRAM Config High with our selected memory speed */
+       value = pci_read_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_HIGH);
+       value &= ~(DCH_MEMCLK_MASK << DCH_MEMCLK_SHIFT);
+       value |= param->dch_memclk;
+       pci_write_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_HIGH, value);
+
+       static const unsigned latencies[] = { 1, 5, 2 };
+       /* Update DRAM Timing Low wiht our selected cas latency */
+       value = pci_read_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_LOW);
+       value &= ~7;
+       value |= latencies[min_latency - 2];
+       pci_write_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_LOW, value);
+#endif
+       
+       return param;
+}
+
+static void main(void)
+{
+       const struct mem_param *param;
+       param = spd_set_memclk();
+       _exit(0);
+}
diff --git a/util/romcc/tests/linux_test6.c b/util/romcc/tests/linux_test6.c
new file mode 100644 (file)
index 0000000..f93ab92
--- /dev/null
@@ -0,0 +1,17 @@
+#include "linux_syscall.h"
+#include "linux_console.h"
+
+static void main(void)
+{
+       static const int value[] = { 1, 0 };
+       const char *str;
+       if (value[1]) {
+               print_debug("A\r\n");
+               str = "Unbuffered\r\n";
+       } else {
+               print_debug("B\r\n");
+               str = "Registered\r\n";
+       }
+       print_debug(str);
+       _exit(0);
+}
diff --git a/util/romcc/tests/linux_test7.c b/util/romcc/tests/linux_test7.c
new file mode 100644 (file)
index 0000000..409b6cb
--- /dev/null
@@ -0,0 +1,35 @@
+#include "linux_syscall.h"
+#include "linux_console.h"
+
+
+static void main(void)
+{
+       static const int cpu[] = { 0, 1, 2, 3 };
+       int i;
+       for(i = 0; i < sizeof(cpu)/sizeof(cpu[0]); i++) {
+               static const unsigned int register_values[] = {
+                       0x0000c144, 0x0000f8f8, 0x00000000,
+                       0x0000c14C, 0x0000f8f8, 0x00000001,
+                       0x0000c154, 0x0000f8f8, 0x00000002,
+                       0x0000c15C, 0x0000f8f8, 0x00000003,
+                       0x0000c164, 0x0000f8f8, 0x00000004,
+                       0x0000c16C, 0x0000f8f8, 0x00000005,
+                       0x0000c174, 0x0000f8f8, 0x00000006,
+                       0x0000c17C, 0x0000f8f8, 0x00000007,
+               };
+               int j;
+               int max = sizeof(register_values)/sizeof(register_values[0]);
+               for(j = 0; j < max; j += 3) {
+                       print_debug("val[");
+                       print_debug_hex8(j);
+                       print_debug("]: ");
+                       print_debug_hex32(register_values[j]);
+                       print_debug_char(' ');
+                       print_debug_hex32(register_values[j+1]);
+                       print_debug_char(' ');
+                       print_debug_hex32(register_values[j+2]);
+                       print_debug_char('\n');
+               }
+       }
+       _exit(0);
+}
diff --git a/util/romcc/tests/linuxi386_syscall.h b/util/romcc/tests/linuxi386_syscall.h
new file mode 100644 (file)
index 0000000..7eb513d
--- /dev/null
@@ -0,0 +1,299 @@
+struct syscall_result {
+       long val;
+       int errno;
+};
+
+static struct syscall_result syscall_return(long result)
+{
+       struct syscall_result res;
+       if (((unsigned long)result) >= ((unsigned long)-125)) {
+               res.errno = - result;
+               res.val = -1;
+       } else {
+               res.errno = 0;
+               res.val = result;
+       }
+       return res;
+}
+
+static struct syscall_result syscall0(unsigned long nr)
+{
+       long res;
+       asm volatile(
+               "int $0x80"
+               : "=a" (res)
+               : "a" (nr));
+       return syscall_return(res);
+}
+
+static struct syscall_result syscall1(unsigned long nr, unsigned long arg1)
+{
+       long res;
+       asm volatile(
+               "int $0x80"
+               : "=a" (res)
+               : "a" (nr), "b" (arg1));
+       return syscall_return(res);
+       
+}
+
+static struct syscall_result syscall2(unsigned long nr, unsigned long arg1, unsigned long arg2)
+{
+       long res;
+       asm volatile(
+               "int $0x80"
+               : "=a" (res)
+               : "a" (nr), "b" (arg1), "c" (arg2));
+       return syscall_return(res);
+       
+}
+
+
+static struct syscall_result syscall3(unsigned long nr, unsigned long arg1, unsigned long arg2,
+       unsigned long arg3)
+{
+       long res;
+       asm volatile(
+               "int $0x80"
+               : "=a" (res)
+               : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3));
+       return syscall_return(res);
+       
+}
+
+static struct syscall_result syscall4(unsigned long nr, unsigned long arg1, unsigned long arg2,
+       unsigned long arg3, unsigned long arg4)
+{
+       long res;
+       asm volatile(
+               "int $0x80"
+               : "=a" (res)
+               : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4));
+       return syscall_return(res);
+       
+}
+
+static struct syscall_result syscall5(unsigned long nr, unsigned long arg1, unsigned long arg2,
+       unsigned long arg3, unsigned long arg4, unsigned long arg5)
+{
+       long res;
+       asm volatile(
+               "int $0x80"
+               : "=a" (res)
+               : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3), 
+               "S" (arg4), "D" (arg5));
+       return syscall_return(res);
+       
+}
+
+#define NR_exit                 1
+#define NR_fork                 2
+#define NR_read                 3
+#define NR_write                4
+#define NR_open                 5
+#define NR_close                6
+#define NR_waitpid              7
+#define NR_creat                8
+#define NR_link                 9
+#define NR_unlink              10
+#define NR_execve              11
+#define NR_chdir               12
+#define NR_time                13
+#define NR_mknod               14
+#define NR_chmod               15
+#define NR_lchown              16
+#define NR_break               17
+#define NR_oldstat             18
+#define NR_lseek               19
+#define NR_getpid              20
+#define NR_mount               21
+#define NR_umount              22
+#define NR_setuid              23
+#define NR_getuid              24
+#define NR_stime               25
+#define NR_ptrace              26
+#define NR_alarm               27
+#define NR_oldfstat            28
+#define NR_pause               29
+#define NR_utime               30
+#define NR_stty                31
+#define NR_gtty                32
+#define NR_access              33
+#define NR_nice                34
+#define NR_ftime               35
+#define NR_sync                36
+#define NR_kill                37
+#define NR_rename              38
+#define NR_mkdir               39
+#define NR_rmdir               40
+#define NR_dup                 41
+#define NR_pipe                42
+#define NR_times               43
+#define NR_prof                44
+#define NR_brk                 45
+#define NR_setgid              46
+#define NR_getgid              47
+#define NR_signal              48
+#define NR_geteuid             49
+#define NR_getegid             50
+#define NR_acct                51
+#define NR_umount2             52
+#define NR_lock                53
+#define NR_ioctl               54
+#define NR_fcntl               55
+#define NR_mpx                 56
+#define NR_setpgid             57
+#define NR_ulimit              58
+#define NR_oldolduname         59
+#define NR_umask               60
+#define NR_chroot              61
+#define NR_ustat               62
+#define NR_dup2                63
+#define NR_getppid             64
+#define NR_getpgrp             65
+#define NR_setsid              66
+#define NR_sigaction           67
+#define NR_sgetmask            68
+#define NR_ssetmask            69
+#define NR_setreuid            70
+#define NR_setregid            71
+#define NR_sigsuspend          72
+#define NR_sigpending          73
+#define NR_sethostname         74
+#define NR_setrlimit           75
+#define NR_getrlimit           76
+#define NR_getrusage           77
+#define NR_gettimeofday        78
+#define NR_settimeofday        79
+#define NR_getgroups           80
+#define NR_setgroups           81
+#define NR_select              82
+#define NR_symlink             83
+#define NR_oldlstat            84
+#define NR_readlink            85
+#define NR_uselib              86
+#define NR_swapon              87
+#define NR_reboot              88
+#define NR_readdir             89
+#define NR_mmap                90
+#define NR_munmap              91
+#define NR_truncate            92
+#define NR_ftruncate           93
+#define NR_fchmod              94
+#define NR_fchown              95
+#define NR_getpriority         96
+#define NR_setpriority         97
+#define NR_profil              98
+#define NR_statfs              99
+#define NR_fstatfs            100
+#define NR_ioperm             101
+#define NR_socketcall         102
+#define NR_syslog             103
+#define NR_setitimer          104
+#define NR_getitimer          105
+#define NR_stat               106
+#define NR_lstat              107
+#define NR_fstat              108
+#define NR_olduname           109
+#define NR_iopl               110
+#define NR_vhangup            111
+#define NR_idle               112
+#define NR_vm86old            113
+#define NR_wait4              114
+#define NR_swapoff            115
+#define NR_sysinfo            116
+#define NR_ipc                117
+#define NR_fsync              118
+#define NR_sigreturn          119
+#define NR_clone              120
+#define NR_setdomainname      121
+#define NR_uname              122
+#define NR_modify_ldt         123
+#define NR_adjtimex           124
+#define NR_mprotect           125
+#define NR_sigprocmask        126
+#define NR_create_module      127
+#define NR_init_module        128
+#define NR_delete_module      129
+#define NR_get_kernel_syms    130
+#define NR_quotactl           131
+#define NR_getpgid            132
+#define NR_fchdir             133
+#define NR_bdflush            134
+#define NR_sysfs              135
+#define NR_personality        136
+#define NR_afs_syscall        137 /* Syscall for Andrew File System */
+#define NR_setfsuid           138
+#define NR_setfsgid           139
+#define NR__llseek            140
+#define NR_getdents           141
+#define NR__newselect         142
+#define NR_flock              143
+#define NR_msync              144
+#define NR_readv              145
+#define NR_writev             146
+#define NR_getsid             147
+#define NR_fdatasync          148
+#define NR__sysctl            149
+#define NR_mlock              150
+#define NR_munlock            151
+#define NR_mlockall           152
+#define NR_munlockall         153
+#define NR_sched_setparam             154
+#define NR_sched_getparam             155
+#define NR_sched_setscheduler         156
+#define NR_sched_getscheduler         157
+#define NR_sched_yield                158
+#define NR_sched_get_priority_max     159
+#define NR_sched_get_priority_min     160
+#define NR_sched_rr_get_interval      161
+#define NR_nanosleep          162
+#define NR_mremap             163
+#define NR_setresuid          164
+#define NR_getresuid          165
+#define NR_vm86               166
+#define NR_query_module       167
+#define NR_poll               168
+#define NR_nfsservctl         169
+#define NR_setresgid          170
+#define NR_getresgid          171
+#define NR_prctl              172
+#define NR_rt_sigreturn       173
+#define NR_rt_sigaction       174
+#define NR_rt_sigprocmask     175
+#define NR_rt_sigpending      176
+#define NR_rt_sigtimedwait    177
+#define NR_rt_sigqueueinfo    178
+#define NR_rt_sigsuspend      179
+#define NR_pread              180
+#define NR_pwrite             181
+#define NR_chown              182
+#define NR_getcwd             183
+#define NR_capget             184
+#define NR_capset             185
+#define NR_sigaltstack        186
+#define NR_sendfile           187
+#define NR_getpmsg            188     /* some people actually want streams */
+#define NR_putpmsg            189     /* some people actually want streams */
+#define NR_vfork              190
+
+/* Standard file descriptors */
+#define STDIN_FILENO    0  /* Standard input */
+#define STDOUT_FILENO   1  /* Standard output */
+#define STDERR_FILENO   2  /* Standard error output */
+
+typedef long ssize_t;
+typedef unsigned long size_t;
+
+static ssize_t write(int fd, const void *buf, size_t count)
+{
+       struct syscall_result res;
+       res = syscall3(NR_write, fd, (unsigned long)buf, count);
+       return res.val;
+}
+
+static void _exit(int status)
+{
+       struct syscall_result res;
+       res = syscall1(NR_exit, status);
+}
diff --git a/util/romcc/tests/raminit_test6.c b/util/romcc/tests/raminit_test6.c
new file mode 100644 (file)
index 0000000..a0c3f05
--- /dev/null
@@ -0,0 +1,2800 @@
+typedef unsigned char      uint8_t;
+typedef signed char        int8_t; 
+typedef unsigned short     uint16_t;
+typedef signed short       int16_t;
+typedef unsigned int       uint32_t;
+typedef signed int         int32_t;
+typedef unsigned char      uint_least8_t;
+typedef signed char        int_least8_t; 
+typedef unsigned short     uint_least16_t;
+typedef signed short       int_least16_t;
+typedef unsigned int       uint_least32_t;
+typedef signed int         int_least32_t;
+typedef unsigned char      uint_fast8_t;
+typedef signed char        int_fast8_t; 
+typedef unsigned int       uint_fast16_t;
+typedef signed int         int_fast16_t;
+typedef unsigned int       uint_fast32_t;
+typedef signed int         int_fast32_t;
+typedef int                intptr_t;
+typedef unsigned int       uintptr_t;
+typedef long int           intmax_t;
+typedef unsigned long int  uintmax_t;
+static inline unsigned long apic_read(unsigned long reg)
+{
+       return *((volatile unsigned long *)(0xfee00000 +reg));
+}
+static inline void apic_write(unsigned long reg, unsigned long v)
+{
+       *((volatile unsigned long *)(0xfee00000 +reg)) = v;
+}
+static inline void apic_wait_icr_idle(void)
+{
+       do { } while ( apic_read( 0x300  ) & 0x01000  );
+}
+static void outb(unsigned char value, unsigned short port)
+{
+       __builtin_outb(value, port);
+}
+static void outw(unsigned short value, unsigned short port)
+{
+       __builtin_outw(value, port);
+}
+static void outl(unsigned int value, unsigned short port)
+{
+       __builtin_outl(value, port);
+}
+static unsigned char inb(unsigned short port)
+{
+       return __builtin_inb(port);
+}
+static unsigned char inw(unsigned short port)
+{
+       return __builtin_inw(port);
+}
+static unsigned char inl(unsigned short port)
+{
+       return __builtin_inl(port);
+}
+static inline void outsb(uint16_t port, const void *addr, unsigned long count)
+{
+       __asm__ __volatile__ (
+               "cld ; rep ; outsb " 
+               : "=S" (addr), "=c" (count)
+               : "d"(port), "0"(addr), "1" (count)
+               );
+}
+static inline void outsw(uint16_t port, const void *addr, unsigned long count)
+{
+       __asm__ __volatile__ (
+               "cld ; rep ; outsw " 
+               : "=S" (addr), "=c" (count)
+               : "d"(port), "0"(addr), "1" (count)
+               );
+}
+static inline void outsl(uint16_t port, const void *addr, unsigned long count)
+{
+       __asm__ __volatile__ (
+               "cld ; rep ; outsl " 
+               : "=S" (addr), "=c" (count)
+               : "d"(port), "0"(addr), "1" (count)
+               );
+}
+static inline void insb(uint16_t port, void *addr, unsigned long count)
+{
+       __asm__ __volatile__ (
+               "cld ; rep ; insb " 
+               : "=D" (addr), "=c" (count)
+               : "d"(port), "0"(addr), "1" (count)
+               );
+}
+static inline void insw(uint16_t port, void *addr, unsigned long count)
+{
+       __asm__ __volatile__ (
+               "cld ; rep ; insw " 
+               : "=D" (addr), "=c" (count)
+               : "d"(port), "0"(addr), "1" (count)
+               );
+}
+static inline void insl(uint16_t port, void *addr, unsigned long count)
+{
+       __asm__ __volatile__ (
+               "cld ; rep ; insl " 
+               : "=D" (addr), "=c" (count)
+               : "d"(port), "0"(addr), "1" (count)
+               );
+}
+static inline void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg)
+{
+       outb(reg, port);
+       outb(value, port +1);
+}
+static inline unsigned char pnp_read_config(unsigned char port, unsigned char reg)
+{
+       outb(reg, port);
+       return inb(port +1);
+}
+static inline void pnp_set_logical_device(unsigned char port, int device)
+{
+       pnp_write_config(port, device, 0x07);
+}
+static inline void pnp_set_enable(unsigned char port, int enable)
+{
+       pnp_write_config(port, enable?0x1:0x0, 0x30);
+}
+static inline int pnp_read_enable(unsigned char port)
+{
+       return !!pnp_read_config(port, 0x30);
+}
+static inline void pnp_set_iobase0(unsigned char port, unsigned iobase)
+{
+       pnp_write_config(port, (iobase >> 8) & 0xff, 0x60);
+       pnp_write_config(port, iobase & 0xff, 0x61);
+}
+static inline void pnp_set_iobase1(unsigned char port, unsigned iobase)
+{
+       pnp_write_config(port, (iobase >> 8) & 0xff, 0x62);
+       pnp_write_config(port, iobase & 0xff, 0x63);
+}
+static inline void pnp_set_irq0(unsigned char port, unsigned irq)
+{
+       pnp_write_config(port, irq, 0x70);
+}
+static inline void pnp_set_irq1(unsigned char port, unsigned irq)
+{
+       pnp_write_config(port, irq, 0x72);
+}
+static inline void pnp_set_drq(unsigned char port, unsigned drq)
+{
+       pnp_write_config(port, drq & 0xff, 0x74);
+}
+static void hlt(void)
+{
+       __builtin_hlt();
+}
+typedef __builtin_div_t div_t;
+typedef __builtin_ldiv_t ldiv_t;
+typedef __builtin_udiv_t udiv_t;
+typedef __builtin_uldiv_t uldiv_t;
+static div_t div(int numer, int denom)
+{
+       return __builtin_div(numer, denom);
+}
+static ldiv_t ldiv(long numer, long denom)
+{
+       return __builtin_ldiv(numer, denom);
+}
+static udiv_t udiv(unsigned numer, unsigned denom)
+{
+       return __builtin_udiv(numer, denom);
+}
+static uldiv_t uldiv(unsigned long numer, unsigned long denom)
+{
+       return __builtin_uldiv(numer, denom);
+}
+int log2(int value)
+{
+        
+       return __builtin_bsr(value);
+}
+typedef unsigned device_t;
+static unsigned char pci_read_config8(device_t dev, unsigned where)
+{
+       unsigned addr;
+       addr = dev | where;
+       outl(0x80000000 | (addr & ~3), 0xCF8);
+       return inb(0xCFC + (addr & 3));
+}
+static unsigned short pci_read_config16(device_t dev, unsigned where)
+{
+       unsigned addr;
+       addr = dev | where;
+       outl(0x80000000 | (addr & ~3), 0xCF8);
+       return inw(0xCFC + (addr & 2));
+}
+static unsigned int pci_read_config32(device_t dev, unsigned where)
+{
+       unsigned addr;
+       addr = dev | where;
+       outl(0x80000000 | (addr & ~3), 0xCF8);
+       return inl(0xCFC);
+}
+static void pci_write_config8(device_t dev, unsigned where, unsigned char value)
+{
+       unsigned addr;
+       addr = dev | where;
+       outl(0x80000000 | (addr & ~3), 0xCF8);
+       outb(value, 0xCFC + (addr & 3));
+}
+static void pci_write_config16(device_t dev, unsigned where, unsigned short value)
+{
+       unsigned addr;
+       addr = dev | where;
+       outl(0x80000000 | (addr & ~3), 0xCF8);
+       outw(value, 0xCFC + (addr & 2));
+}
+static void pci_write_config32(device_t dev, unsigned where, unsigned int value)
+{
+       unsigned addr;
+       addr = dev | where;
+       outl(0x80000000 | (addr & ~3), 0xCF8);
+       outl(value, 0xCFC);
+}
+static device_t pci_locate_device(unsigned pci_id, device_t dev)
+{
+       for(; dev <= ( ((( 255 ) & 0xFF) << 16) | (((  31 ) & 0x1f) << 11) | (((  7 )  & 0x7) << 8)) ; dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8)) ) {
+               unsigned int id;
+               id = pci_read_config32(dev, 0);
+               if (id == pci_id) {
+                       return dev;
+               }
+       }
+       return (0xffffffffU) ;
+}
+static int uart_can_tx_byte(void)
+{
+       return inb(1016  + 0x05 ) & 0x20;
+}
+static void uart_wait_to_tx_byte(void)
+{
+       while(!uart_can_tx_byte())
+               ;
+}
+static void uart_wait_until_sent(void)
+{
+       while(!(inb(1016  + 0x05 ) & 0x40)) 
+               ;
+}
+static void uart_tx_byte(unsigned char data)
+{
+       uart_wait_to_tx_byte();
+       outb(data, 1016  + 0x00 );
+        
+       uart_wait_until_sent();
+}
+static void uart_init(void)
+{
+        
+       outb(0x0, 1016  + 0x01 );
+        
+       outb(0x01, 1016  + 0x02 );
+        
+       outb(0x80 | 3  , 1016  + 0x03 );
+       outb((115200/ 115200 )  & 0xFF,   1016  + 0x00 );
+       outb(((115200/ 115200 )  >> 8) & 0xFF,    1016  + 0x01 );
+       outb(3  , 1016  + 0x03 );
+}
+static void __console_tx_byte(unsigned char byte)
+{
+       uart_tx_byte(byte);
+}
+static void __console_tx_nibble(unsigned nibble)
+{
+       unsigned char digit;
+       digit = nibble + '0';
+       if (digit > '9') {
+               digit += 39;
+       }
+       __console_tx_byte(digit);
+}
+static void __console_tx_char(int loglevel, unsigned char byte)
+{
+       if (8   > loglevel) {
+               uart_tx_byte(byte);
+       }
+}
+static void __console_tx_hex8(int loglevel, unsigned char value)
+{
+       if (8   > loglevel) {
+               __console_tx_nibble((value >>  4U) & 0x0fU);
+               __console_tx_nibble(value & 0x0fU);
+       }
+}
+static void __console_tx_hex16(int loglevel, unsigned short value)
+{
+       if (8   > loglevel) {
+               __console_tx_nibble((value >> 12U) & 0x0fU);
+               __console_tx_nibble((value >>  8U) & 0x0fU);
+               __console_tx_nibble((value >>  4U) & 0x0fU);
+               __console_tx_nibble(value & 0x0fU);
+       }
+}
+static void __console_tx_hex32(int loglevel, unsigned int value)
+{
+       if (8   > loglevel) {
+               __console_tx_nibble((value >> 28U) & 0x0fU);
+               __console_tx_nibble((value >> 24U) & 0x0fU);
+               __console_tx_nibble((value >> 20U) & 0x0fU);
+               __console_tx_nibble((value >> 16U) & 0x0fU);
+               __console_tx_nibble((value >> 12U) & 0x0fU);
+               __console_tx_nibble((value >>  8U) & 0x0fU);
+               __console_tx_nibble((value >>  4U) & 0x0fU);
+               __console_tx_nibble(value & 0x0fU);
+       }
+}
+static void __console_tx_string(int loglevel, const char *str)
+{
+       if (8   > loglevel) {
+               unsigned char ch;
+               while((ch = *str++) != '\0') {
+                       __console_tx_byte(ch);
+               }
+       }
+}
+static void print_emerg_char(unsigned char byte) { __console_tx_char(0 , byte); }
+static void print_emerg_hex8(unsigned char value){ __console_tx_hex8(0 , value); }
+static void print_emerg_hex16(unsigned short value){ __console_tx_hex16(0 , value); }
+static void print_emerg_hex32(unsigned int value) { __console_tx_hex32(0 , value); }
+static void print_emerg(const char *str) { __console_tx_string(0 , str); }
+static void print_alert_char(unsigned char byte) { __console_tx_char(1 , byte); }
+static void print_alert_hex8(unsigned char value) { __console_tx_hex8(1 , value); }
+static void print_alert_hex16(unsigned short value){ __console_tx_hex16(1 , value); }
+static void print_alert_hex32(unsigned int value) { __console_tx_hex32(1 , value); }
+static void print_alert(const char *str) { __console_tx_string(1 , str); }
+static void print_crit_char(unsigned char byte) { __console_tx_char(2 , byte); }
+static void print_crit_hex8(unsigned char value) { __console_tx_hex8(2 , value); }
+static void print_crit_hex16(unsigned short value){ __console_tx_hex16(2 , value); }
+static void print_crit_hex32(unsigned int value) { __console_tx_hex32(2 , value); }
+static void print_crit(const char *str) { __console_tx_string(2 , str); }
+static void print_err_char(unsigned char byte) { __console_tx_char(3 , byte); }
+static void print_err_hex8(unsigned char value) { __console_tx_hex8(3 , value); }
+static void print_err_hex16(unsigned short value){ __console_tx_hex16(3 , value); }
+static void print_err_hex32(unsigned int value) { __console_tx_hex32(3 , value); }
+static void print_err(const char *str) { __console_tx_string(3 , str); }
+static void print_warning_char(unsigned char byte) { __console_tx_char(4 , byte); }
+static void print_warning_hex8(unsigned char value) { __console_tx_hex8(4 , value); }
+static void print_warning_hex16(unsigned short value){ __console_tx_hex16(4 , value); }
+static void print_warning_hex32(unsigned int value) { __console_tx_hex32(4 , value); }
+static void print_warning(const char *str) { __console_tx_string(4 , str); }
+static void print_notice_char(unsigned char byte) { __console_tx_char(5 , byte); }
+static void print_notice_hex8(unsigned char value) { __console_tx_hex8(5 , value); }
+static void print_notice_hex16(unsigned short value){ __console_tx_hex16(5 , value); }
+static void print_notice_hex32(unsigned int value) { __console_tx_hex32(5 , value); }
+static void print_notice(const char *str) { __console_tx_string(5 , str); }
+static void print_info_char(unsigned char byte) { __console_tx_char(6 , byte); }
+static void print_info_hex8(unsigned char value) { __console_tx_hex8(6 , value); }
+static void print_info_hex16(unsigned short value){ __console_tx_hex16(6 , value); }
+static void print_info_hex32(unsigned int value) { __console_tx_hex32(6 , value); }
+static void print_info(const char *str) { __console_tx_string(6 , str); }
+static void print_debug_char(unsigned char byte) { __console_tx_char(7 , byte); }
+static void print_debug_hex8(unsigned char value) { __console_tx_hex8(7 , value); }
+static void print_debug_hex16(unsigned short value){ __console_tx_hex16(7 , value); }
+static void print_debug_hex32(unsigned int value) { __console_tx_hex32(7 , value); }
+static void print_debug(const char *str) { __console_tx_string(7 , str); }
+static void print_spew_char(unsigned char byte) { __console_tx_char(8 , byte); }
+static void print_spew_hex8(unsigned char value) { __console_tx_hex8(8 , value); }
+static void print_spew_hex16(unsigned short value){ __console_tx_hex16(8 , value); }
+static void print_spew_hex32(unsigned int value) { __console_tx_hex32(8 , value); }
+static void print_spew(const char *str) { __console_tx_string(8 , str); }
+static void console_init(void)
+{
+       static const char console_test[] = 
+               "\r\n\r\nLinuxBIOS-"
+               "1.1.4"  
+               ".0Fallback"  
+               " "
+               "Thu Oct 9 20:29:48 MDT 2003"  
+               " starting...\r\n";
+       print_info(console_test);
+}
+static void die(const char *str)
+{
+       print_emerg(str);
+       do {
+               hlt();
+       } while(1);
+}
+static void write_phys(unsigned long addr, unsigned long value)
+{
+       asm volatile(
+               "movnti %1, (%0)"
+               :  
+               : "r" (addr), "r" (value)  
+               :  
+               );
+}
+static unsigned long read_phys(unsigned long addr)
+{
+       volatile unsigned long *ptr;
+       ptr = (void *)addr;
+       return *ptr;
+}
+static void ram_fill(unsigned long start, unsigned long stop)
+{
+       unsigned long addr;
+        
+       print_debug("DRAM fill: ");
+       print_debug_hex32(start);
+       print_debug("-");
+       print_debug_hex32(stop);
+       print_debug("\r\n");
+       for(addr = start; addr < stop ; addr += 4) {
+                
+               if (!(addr & 0xffff)) {
+                       print_debug_hex32(addr);
+                       print_debug("\r");
+               }
+               write_phys(addr, addr);
+       };
+        
+       print_debug_hex32(addr);
+       print_debug("\r\nDRAM filled\r\n");
+}
+static void ram_verify(unsigned long start, unsigned long stop)
+{
+       unsigned long addr;
+        
+       print_debug("DRAM verify: ");
+       print_debug_hex32(start);
+       print_debug_char('-');
+       print_debug_hex32(stop);
+       print_debug("\r\n");
+       for(addr = start; addr < stop ; addr += 4) {
+               unsigned long value;
+                
+               if (!(addr & 0xffff)) {
+                       print_debug_hex32(addr);
+                       print_debug("\r");
+               }
+               value = read_phys(addr);
+               if (value != addr) {
+                        
+                       print_err_hex32(addr);
+                       print_err_char(':');
+                       print_err_hex32(value);
+                       print_err("\r\n");
+               }
+       }
+        
+       print_debug_hex32(addr);
+       print_debug("\r\nDRAM verified\r\n");
+}
+void ram_check(unsigned long start, unsigned long stop)
+{
+       int result;
+        
+       print_debug("Testing DRAM : ");
+       print_debug_hex32(start);
+       print_debug("-");       
+       print_debug_hex32(stop);
+       print_debug("\r\n");
+       ram_fill(start, stop);
+       ram_verify(start, stop);
+       print_debug("Done.\r\n");
+}
+static int enumerate_ht_chain(unsigned link)
+{
+        
+       unsigned next_unitid, last_unitid;
+       int reset_needed = 0;
+       next_unitid = 1;
+       do {
+               uint32_t id;
+               uint8_t hdr_type, pos;
+               last_unitid = next_unitid;
+               id = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , 0x00 );
+                
+               if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+                       (((id >> 16) & 0xffff) == 0xffff) ||
+                       (((id >> 16) & 0xffff) == 0x0000)) {
+                       break;
+               }
+               hdr_type = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , 0x0e );
+               pos = 0;
+               hdr_type &= 0x7f;
+               if ((hdr_type == 0 ) ||
+                       (hdr_type == 1 )) {
+                       pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , 0x34 );
+               }
+               while(pos != 0) {
+                       uint8_t cap;
+                       cap = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , pos + 0 );
+                       if (cap == 0x08 ) {
+                               uint16_t flags;
+                               flags = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , pos + 2 );
+                               if ((flags >> 13) == 0) {
+                                       unsigned count;
+                                       flags &= ~0x1f;
+                                       flags |= next_unitid & 0x1f;
+                                       count = (flags >> 5) & 0x1f;
+                                       pci_write_config16(( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , pos + 2 , flags);
+                                       next_unitid += count;
+                                       break;
+                               }
+                       }
+                       pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , pos + 1 );
+               }
+       } while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
+       return reset_needed;
+}
+static void enable_smbus(void)
+{
+       device_t dev;
+       dev = pci_locate_device(((((  0x746b ) & 0xFFFF) << 16) | (( 0x1022 ) & 0xFFFF)) , 0);
+       if (dev == (0xffffffffU) ) {
+               die("SMBUS controller not found\r\n");
+       }
+       uint8_t enable;
+       print_debug("SMBus controller enabled\r\n");
+       pci_write_config32(dev, 0x58, 0x0f00  | 1);
+       enable = pci_read_config8(dev, 0x41);
+       pci_write_config8(dev, 0x41, enable | (1 << 7));
+        
+       outw(inw(0x0f00  + 0xe0 ), 0x0f00  + 0xe0 );
+}
+static inline void smbus_delay(void)
+{
+       outb(0x80, 0x80);
+}
+static int smbus_wait_until_ready(void)
+{
+       unsigned long loops;
+       loops = (100*1000*10) ;
+       do {
+               unsigned short val;
+               smbus_delay();
+               val = inw(0x0f00  + 0xe0 );
+               if ((val & 0x800) == 0) {
+                       break;
+               }
+               if(loops == ((100*1000*10)  / 2)) {
+                       outw(inw(0x0f00  + 0xe0 ), 
+                               0x0f00  + 0xe0 );
+               }
+       } while(--loops);
+       return loops?0:-2;
+}
+static int smbus_wait_until_done(void)
+{
+       unsigned long loops;
+       loops = (100*1000*10) ;
+       do {
+               unsigned short val;
+               smbus_delay();
+               
+               val = inw(0x0f00  + 0xe0 );
+               if (((val & 0x8) == 0) | ((val & 0x437) != 0)) {
+                       break;
+               }
+       } while(--loops);
+       return loops?0:-3;
+}
+static int smbus_read_byte(unsigned device, unsigned address)
+{
+       unsigned char global_control_register;
+       unsigned char global_status_register;
+       unsigned char byte;
+       if (smbus_wait_until_ready() < 0) {
+               return -2;
+       }
+       
+        
+        
+       outw(inw(0x0f00  + 0xe2 ) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), 0x0f00  + 0xe2 );
+        
+       outw(((device & 0x7f) << 1) | 1, 0x0f00  + 0xe4 );
+        
+       outb(address & 0xFF, 0x0f00  + 0xe8 );
+        
+       outw((inw(0x0f00  + 0xe2 ) & ~7) | (0x2), 0x0f00  + 0xe2 );
+        
+        
+       outw(inw(0x0f00  + 0xe0 ), 0x0f00  + 0xe0 );
+        
+       outw(0, 0x0f00  + 0xe6 );
+        
+       outw((inw(0x0f00  + 0xe2 ) | (1 << 3)), 0x0f00  + 0xe2 );
+        
+       if (smbus_wait_until_done() < 0) {
+               return -3;
+       }
+       global_status_register = inw(0x0f00  + 0xe0 );
+        
+       byte = inw(0x0f00  + 0xe6 ) & 0xff;
+       if (global_status_register != (1 << 4)) {
+               return -1;
+       }
+       return byte;
+}
+static void smbus_write_byte(unsigned device, unsigned address, unsigned char val)
+{
+       return;
+}
+struct mem_controller {
+       unsigned node_id;
+       device_t f0, f1, f2, f3;
+       uint8_t channel0[4];
+       uint8_t channel1[4];
+};
+typedef __builtin_msr_t msr_t;
+static msr_t rdmsr(unsigned long index)
+{
+       return __builtin_rdmsr(index);
+}
+static void wrmsr(unsigned long index, msr_t msr)
+{
+       __builtin_wrmsr(index, msr.lo, msr.hi);
+}
+struct tsc_struct {
+       unsigned lo;
+       unsigned hi;
+};
+typedef struct tsc_struct tsc_t;
+static tsc_t rdtsc(void)
+{
+       tsc_t res;
+       asm ("rdtsc"
+               : "=a" (res.lo), "=d"(res.hi)  
+               :  
+               :  
+               );
+       return res;
+}
+void init_timer(void)
+{
+        
+       apic_write(0x320 , (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0));
+        
+       apic_write(0x3E0 , 0xB );
+        
+       apic_write(0x380 , 0xffffffff);
+}
+void udelay(unsigned usecs)
+{
+       uint32_t start, value, ticks;
+        
+       ticks = usecs * 200;
+       start = apic_read(0x390 );
+       do {
+               value = apic_read(0x390 );
+       } while((start - value) < ticks);
+       
+}
+void mdelay(unsigned msecs)
+{
+       unsigned i;
+       for(i = 0; i < msecs; i++) {
+               udelay(1000);
+       }
+}
+void delay(unsigned secs)
+{
+       unsigned i;
+       for(i = 0; i < secs; i++) {
+               mdelay(1000);
+       }
+}
+int boot_cpu(void)
+{
+       volatile unsigned long *local_apic;
+       unsigned long apic_id;
+       int bsp;
+       msr_t msr;
+       msr = rdmsr(0x1b);
+       bsp = !!(msr.lo & (1 << 8));
+       return bsp;
+}
+static int cpu_init_detected(void)
+{
+       unsigned long htic;
+       htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
+       return !!(htic & (1<<6) );
+}
+static int bios_reset_detected(void)
+{
+       unsigned long htic;
+       htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
+       return (htic & (1<<4) ) && !(htic & (1<<5) );
+}
+static int cold_reset_detected(void)
+{
+       unsigned long htic;
+       htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
+       return !(htic & (1<<4) );
+}
+static void distinguish_cpu_resets(unsigned node_id)
+{
+       uint32_t htic;
+       device_t device;
+       device = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 + node_id ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ;
+       htic = pci_read_config32(device, 0x6c );
+       htic |= (1<<4)  | (1<<5)  | (1<<6) ;
+       pci_write_config32(device, 0x6c , htic);
+}
+static void set_bios_reset(void)
+{
+       unsigned long htic;
+       htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
+       htic &= ~(1<<5) ;
+       pci_write_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c , htic);
+}
+static void print_debug_pci_dev(unsigned dev)
+{
+       print_debug("PCI: ");
+       print_debug_hex8((dev >> 16) & 0xff);
+       print_debug_char(':');
+       print_debug_hex8((dev >> 11) & 0x1f);
+       print_debug_char('.');
+       print_debug_hex8((dev >> 8) & 7);
+}
+static void print_pci_devices(void)
+{
+       device_t dev;
+       for(dev = ( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ; 
+               dev <= ( ((( 0 ) & 0xFF) << 16) | (((  0x1f ) & 0x1f) << 11) | (((  0x7 )  & 0x7) << 8)) ; 
+               dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8)) ) {
+               uint32_t id;
+               id = pci_read_config32(dev, 0x00 );
+               if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+                       (((id >> 16) & 0xffff) == 0xffff) ||
+                       (((id >> 16) & 0xffff) == 0x0000)) {
+                       continue;
+               }
+               print_debug_pci_dev(dev);
+               print_debug("\r\n");
+       }
+}
+static void dump_pci_device(unsigned dev)
+{
+       int i;
+       print_debug_pci_dev(dev);
+       print_debug("\r\n");
+       
+       for(i = 0; i <= 255; i++) {
+               unsigned char val;
+               if ((i & 0x0f) == 0) {
+                       print_debug_hex8(i);
+                       print_debug_char(':');
+               }
+               val = pci_read_config8(dev, i);
+               print_debug_char(' ');
+               print_debug_hex8(val);
+               if ((i & 0x0f) == 0x0f) {
+                       print_debug("\r\n");
+               }
+       }
+}
+static void dump_pci_devices(void)
+{
+       device_t dev;
+       for(dev = ( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ; 
+               dev <= ( ((( 0 ) & 0xFF) << 16) | (((  0x1f ) & 0x1f) << 11) | (((  0x7 )  & 0x7) << 8)) ; 
+               dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8)) ) {
+               uint32_t id;
+               id = pci_read_config32(dev, 0x00 );
+               if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+                       (((id >> 16) & 0xffff) == 0xffff) ||
+                       (((id >> 16) & 0xffff) == 0x0000)) {
+                       continue;
+               }
+               dump_pci_device(dev);
+       }
+}
+static void dump_spd_registers(const struct mem_controller *ctrl)
+{
+       int i;
+       print_debug("\r\n");
+       for(i = 0; i < 4; i++) {
+               unsigned device;
+               device = ctrl->channel0[i];
+               if (device) {
+                       int j;
+                       print_debug("dimm: "); 
+                       print_debug_hex8(i); 
+                       print_debug(".0: ");
+                       print_debug_hex8(device);
+                       for(j = 0; j < 256; j++) {
+                               int status;
+                               unsigned char byte;
+                               if ((j & 0xf) == 0) {
+                                       print_debug("\r\n");
+                                       print_debug_hex8(j);
+                                       print_debug(": ");
+                               }
+                               status = smbus_read_byte(device, j);
+                               if (status < 0) {
+                                       print_debug("bad device\r\n");
+                                       break;
+                               }
+                               byte = status & 0xff;
+                               print_debug_hex8(byte);
+                               print_debug_char(' ');
+                       }
+                       print_debug("\r\n");
+               }
+               device = ctrl->channel1[i];
+               if (device) {
+                       int j;
+                       print_debug("dimm: "); 
+                       print_debug_hex8(i); 
+                       print_debug(".1: ");
+                       print_debug_hex8(device);
+                       for(j = 0; j < 256; j++) {
+                               int status;
+                               unsigned char byte;
+                               if ((j & 0xf) == 0) {
+                                       print_debug("\r\n");
+                                       print_debug_hex8(j);
+                                       print_debug(": ");
+                               }
+                               status = smbus_read_byte(device, j);
+                               if (status < 0) {
+                                       print_debug("bad device\r\n");
+                                       break;
+                               }
+                               byte = status & 0xff;
+                               print_debug_hex8(byte);
+                               print_debug_char(' ');
+                       }
+                       print_debug("\r\n");
+               }
+       }
+}
+static unsigned int cpuid(unsigned int op)
+{
+       unsigned int ret;
+       unsigned dummy2,dummy3,dummy4;
+       asm volatile ( 
+               "cpuid" 
+               : "=a" (ret), "=b" (dummy2), "=c" (dummy3), "=d" (dummy4)
+               : "a" (op)
+               );
+       return ret;
+}
+static int is_cpu_rev_a0(void)
+{
+       return (cpuid(1) & 0xffff) == 0x0f10;
+}
+static int is_cpu_pre_c0(void)
+{
+       return (cpuid(1) & 0xffef) < 0x0f48;
+}
+static void memreset_setup(void)
+{
+       if (is_cpu_pre_c0()) {
+                
+               outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00  + 0xc0 + 28);
+                
+               outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00  + 0xc0 + 29);
+       }
+       else {
+                
+               outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00  + 0xc0 + 29);
+       }
+}
+static void memreset(int controllers, const struct mem_controller *ctrl)
+{
+       if (is_cpu_pre_c0()) {
+               udelay(800);
+                
+               outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00  + 0xc0 + 28);
+               udelay(90);
+       }
+}
+static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes)
+{
+        
+       uint32_t ret=0x00010101;  
+       static const unsigned int rows_2p[2][2] = {
+               { 0x00050101, 0x00010404 },
+               { 0x00010404, 0x00050101 }
+       };
+       if(maxnodes>2) {
+               print_debug("this mainboard is only designed for 2 cpus\r\n");
+               maxnodes=2;
+       }
+       if (!(node>=maxnodes || row>=maxnodes)) {
+               ret=rows_2p[node][row];
+       }
+       return ret;
+}
+static inline int spd_read_byte(unsigned device, unsigned address)
+{
+       return smbus_read_byte(device, address);
+}
+static void coherent_ht_mainboard(unsigned cpus)
+{
+}
+void cpu_ldtstop(unsigned cpus)
+{
+       uint32_t tmp;
+       device_t dev;
+       unsigned cnt;
+       for(cnt=0; cnt<cpus; cnt++) {
+                
+               pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8)) ,0x81,0x23);
+                
+               pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8)) ,0xd4,0x00000701);
+                
+               pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8)) ,0xd8,0x00000000);
+                
+               tmp=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 )  & 0x7) << 8)) ,0x90);
+               pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 )  & 0x7) << 8)) ,0x90, tmp | (1<<24) );
+       }
+}
+static void setup_resource_map(const unsigned int *register_values, int max)
+{
+       int i;
+       print_debug("setting up resource map....\r\n");
+       for(i = 0; i < max; i += 3) {
+               device_t dev;
+               unsigned where;
+               unsigned long reg;
+               dev = register_values[i] & ~0xff;
+               where = register_values[i] & 0xff;
+               reg = pci_read_config32(dev, where);
+               reg &= register_values[i+1];
+               reg |= register_values[i+2];
+               pci_write_config32(dev, where, reg);
+       }
+       print_debug("done.\r\n");
+}
+static void setup_default_resource_map(void)
+{
+       static const unsigned int register_values[] = {
+        
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x84 ) & 0xFF)) , 0x00000048, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x8C ) & 0xFF)) , 0x00000048, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x94 ) & 0xFF)) , 0x00000048, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x9C ) & 0xFF)) , 0x00000048, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xA4 ) & 0xFF)) , 0x00000048, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xAC ) & 0xFF)) , 0x00000048, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xB4 ) & 0xFF)) , 0x00000048, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xBC ) & 0xFF)) , 0x00000048, 0x00ffff00,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x80 ) & 0xFF)) , 0x000000f0, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x88 ) & 0xFF)) , 0x000000f0, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x90 ) & 0xFF)) , 0x000000f0, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x98 ) & 0xFF)) , 0x000000f0, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xA0 ) & 0xFF)) , 0x000000f0, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xA8 ) & 0xFF)) , 0x000000f0, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xB0 ) & 0xFF)) , 0x000000f0, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xB8 ) & 0xFF)) , 0x000000f0, 0x00fc0003,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xC4 ) & 0xFF)) , 0xFE000FC8, 0x01fff000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xCC ) & 0xFF)) , 0xFE000FC8, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xD4 ) & 0xFF)) , 0xFE000FC8, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xDC ) & 0xFF)) , 0xFE000FC8, 0x00000000,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xC0 ) & 0xFF)) , 0xFE000FCC, 0x00000003,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xC8 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xD0 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xD8 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xE0 ) & 0xFF)) , 0x0000FC88, 0xff000003,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xE4 ) & 0xFF)) , 0x0000FC88, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xE8 ) & 0xFF)) , 0x0000FC88, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xEC ) & 0xFF)) , 0x0000FC88, 0x00000000,
+       };
+       int max;
+       max = sizeof(register_values)/sizeof(register_values[0]);
+       setup_resource_map(register_values, max);
+}
+static void sdram_set_registers(const struct mem_controller *ctrl)
+{
+       static const unsigned int register_values[] = {
+        
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x40 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x44 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x48 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x4C ) & 0xFF)) , 0x001f01fe, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x50 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x54 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x001f01fe, 0x00000000,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x64 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x68 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x6C ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x70 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x74 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x78 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x7C ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x80 ) & 0xFF)) , 0xffff8888, 0x00000000,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x88 ) & 0xFF)) , 0xe8088008, 0x02522001   ,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x8c ) & 0xFF)) , 0xff8fe08e, (0 << 20)|(0 << 8)|(0 << 4)|(0 << 0),
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x90 ) & 0xFF)) , 0xf0000000, 
+       (4 << 25)|(0 << 24)| 
+       (0 << 23)|(0 << 22)|(0 << 21)|(0 << 20)| 
+       (1 << 19)|(0 << 18)|(1 << 17)|(0 << 16)| 
+       (2 << 14)|(0 << 13)|(0 << 12)| 
+       (0 << 11)|(0 << 10)|(0 << 9)|(0 << 8)| 
+       (0 << 3) |(0 << 1) |(0 << 0),
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x94 ) & 0xFF)) , 0xc180f0f0,
+       (0 << 29)|(0 << 28)|(0 << 27)|(0 << 26)|(0 << 25)|
+       (0 << 20)|(0 << 19)|(3  << 16)|(0 << 8)|(0 << 0),
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x98 ) & 0xFF)) , 0xfc00ffff, 0x00000000,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0xffe0e0e0, 0x00000000,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x0000003e, 0x00000000,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0xffffff00, 0x00000000,
+        
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x94 ) & 0xFF)) , 0xffff8000, 0x00000f70,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x90 ) & 0xFF)) , 0xffffff80, 0x00000002,
+       ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x98 ) & 0xFF)) , 0x0000000f, 0x00068300,
+       };
+       int i;
+       int max;
+       print_debug("setting up CPU");
+       print_debug_hex8(ctrl->node_id);
+       print_debug(" northbridge registers\r\n");
+       max = sizeof(register_values)/sizeof(register_values[0]);
+       for(i = 0; i < max; i += 3) {
+               device_t dev;
+               unsigned where;
+               unsigned long reg;
+               dev = (register_values[i] & ~0xff) - ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8))  + ctrl->f0;
+               where = register_values[i] & 0xff;
+               reg = pci_read_config32(dev, where);
+               reg &= register_values[i+1];
+               reg |= register_values[i+2];
+               pci_write_config32(dev, where, reg);
+       }
+       print_debug("done.\r\n");
+}
+static int is_dual_channel(const struct mem_controller *ctrl)
+{
+       uint32_t dcl;
+       dcl = pci_read_config32(ctrl->f2, 0x90 );
+       return dcl & (1<<16) ;
+}
+static int is_opteron(const struct mem_controller *ctrl)
+{
+        
+       uint32_t nbcap;
+       nbcap = pci_read_config32(ctrl->f3, 0xE8 );
+       return !!(nbcap & 0x0001 );
+}
+static int is_registered(const struct mem_controller *ctrl)
+{
+        
+       uint32_t dcl;
+       dcl = pci_read_config32(ctrl->f2, 0x90 );
+       return !(dcl & (1<<18) );
+}
+struct dimm_size {
+       unsigned long side1;
+       unsigned long side2;
+};
+static struct dimm_size spd_get_dimm_size(unsigned device)
+{
+        
+       struct dimm_size sz;
+       int value, low;
+       sz.side1 = 0;
+       sz.side2 = 0;
+        
+       value = spd_read_byte(device, 3);        
+       if (value < 0) goto out;
+       sz.side1 += value & 0xf;
+       value = spd_read_byte(device, 4);        
+       if (value < 0) goto out;
+       sz.side1 += value & 0xf;
+       value = spd_read_byte(device, 17);       
+       if (value < 0) goto out;
+       sz.side1 += log2(value & 0xff);
+        
+       value = spd_read_byte(device, 7);        
+       if (value < 0) goto out;
+       value &= 0xff;
+       value <<= 8;
+       
+       low = spd_read_byte(device, 6);  
+       if (low < 0) goto out;
+       value = value | (low & 0xff);
+       sz.side1 += log2(value);
+        
+       value = spd_read_byte(device, 5);        
+       if (value <= 1) goto out;
+        
+       sz.side2 = sz.side1;
+       value = spd_read_byte(device, 3);        
+       if (value < 0) goto out;
+       if ((value & 0xf0) == 0) goto out;       
+       sz.side2 -= (value & 0x0f);              
+       sz.side2 += ((value >> 4) & 0x0f);       
+       value = spd_read_byte(device, 4);        
+       if (value < 0) goto out;
+       sz.side2 -= (value & 0x0f);              
+       sz.side2 += ((value >> 4) & 0x0f);       
+ out:
+       return sz;
+}
+static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz, unsigned index)
+{
+       uint32_t base0, base1, map;
+       uint32_t dch;
+       if (sz.side1 != sz.side2) {
+               sz.side2 = 0;
+       }
+       map = pci_read_config32(ctrl->f2, 0x80 );
+       map &= ~(0xf << (index + 4));
+        
+       
+       base0 = base1 = 0;
+        
+       if (sz.side1 >= (25 +3)) {
+               map |= (sz.side1 - (25 + 3)) << (index *4);
+               base0 = (1 << ((sz.side1 - (25 + 3)) + 21)) | 1;
+       }
+        
+       if (sz.side2 >= (25 + 3)) {
+               base1 = (1 << ((sz.side2 - (25 + 3)) + 21)) | 1;
+       }
+        
+       if (is_dual_channel(ctrl)) {
+               base0 = (base0 << 1) | (base0 & 1);
+               base1 = (base1 << 1) | (base1 & 1);
+       }
+        
+       base0 &= ~0x001ffffe;
+       base1 &= ~0x001ffffe;
+        
+       pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+0)<<2), base0);
+       pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+1)<<2), base1);
+       pci_write_config32(ctrl->f2, 0x80 , map);
+       
+        
+       if (base0) {
+               dch = pci_read_config32(ctrl->f2, 0x94 );
+               dch |= (1 << 26)  << index;
+               pci_write_config32(ctrl->f2, 0x94 , dch);
+       }
+}
+static void spd_set_ram_size(const struct mem_controller *ctrl)
+{
+       int i;
+       
+       for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+               struct dimm_size sz;
+               sz = spd_get_dimm_size(ctrl->channel0[i]);
+               set_dimm_size(ctrl, sz, i);
+       }
+}
+static void route_dram_accesses(const struct mem_controller *ctrl,
+       unsigned long base_k, unsigned long limit_k)
+{
+        
+       unsigned node_id;
+       unsigned limit;
+       unsigned base;
+       unsigned index;
+       unsigned limit_reg, base_reg;
+       device_t device;
+       node_id = ctrl->node_id;
+       index = (node_id << 3);
+       limit = (limit_k << 2);
+       limit &= 0xffff0000;
+       limit -= 0x00010000;
+       limit |= ( 0 << 8) | (node_id << 0);
+       base = (base_k << 2);
+       base &= 0xffff0000;
+       base |= (0 << 8) | (1<<1) | (1<<0);
+       limit_reg = 0x44 + index;
+       base_reg = 0x40 + index;
+       for(device = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ; device <= ( ((( 0 ) & 0xFF) << 16) | (((  0x1f ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ; device += ( ((( 0 ) & 0xFF) << 16) | (((  1 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ) {
+               pci_write_config32(device, limit_reg, limit);
+               pci_write_config32(device, base_reg, base);
+       }
+}
+static void set_top_mem(unsigned tom_k)
+{
+        
+       if (!tom_k) {
+               set_bios_reset();
+               print_debug("No memory - reset");
+                
+               pci_write_config8(( ((( 0 ) & 0xFF) << 16) | (((  0x04 ) & 0x1f) << 11) | (((  3 )  & 0x7) << 8)) , 0x41, 0xf1);
+                
+               outb(0x0e, 0x0cf9);
+       }
+        
+       print_debug("RAM: 0x");
+       print_debug_hex32(tom_k);
+       print_debug(" KB\r\n");
+        
+       msr_t msr;
+       msr.lo = (tom_k & 0x003fffff) << 10;
+       msr.hi = (tom_k & 0xffc00000) >> 22;
+       wrmsr(0xC001001D , msr);
+        
+       if (tom_k >= 0x003f0000) {
+               tom_k = 0x3f0000;
+       }
+       msr.lo = (tom_k & 0x003fffff) << 10;
+       msr.hi = (tom_k & 0xffc00000) >> 22;
+       wrmsr(0xC001001A , msr);
+}
+static unsigned long interleave_chip_selects(const struct mem_controller *ctrl)
+{
+        
+       static const uint32_t csbase_low[] = { 
+               (1 << (13 - 4)),
+               (1 << (14 - 4)),
+               (1 << (14 - 4)), 
+               (1 << (15 - 4)),
+               (1 << (15 - 4)),
+               (1 << (16 - 4)),
+               (1 << (16 - 4)), 
+       };
+       uint32_t csbase_inc;
+       int chip_selects, index;
+       int bits;
+       int dual_channel;
+       unsigned common_size;
+       uint32_t csbase, csmask;
+        
+       chip_selects = 0;
+       common_size = 0;
+       for(index = 0; index < 8; index++) {
+               unsigned size;
+               uint32_t value;
+               
+               value = pci_read_config32(ctrl->f2, 0x40  + (index << 2));
+               
+                
+               if (!(value & 1)) {
+                       continue;
+               }
+               chip_selects++;
+               size = value >> 21;
+               if (common_size == 0) {
+                       common_size = size;
+               }
+                
+               if (common_size != size) {
+                       return 0;
+               }
+       }
+        
+       bits = log2(chip_selects);
+       if (((1 << bits) != chip_selects) || (bits < 1) || (bits > 3)) {
+               return 0;
+               
+       }
+        
+       if ((bits == 3) && (common_size == (1 << (32 - 3)))) {
+               print_debug("8 4GB chip selects cannot be interleaved\r\n");
+               return 0;
+       }
+        
+       if (is_dual_channel(ctrl)) {
+               csbase_inc = csbase_low[log2(common_size) - 1] << 1;
+       } else {
+               csbase_inc = csbase_low[log2(common_size)];
+       }
+        
+       csbase = 0 | 1;
+       csmask = (((common_size  << bits) - 1) << 21);
+       csmask |= 0xfe00 & ~((csbase_inc << bits) - csbase_inc);
+       for(index = 0; index < 8; index++) {
+               uint32_t value;
+               value = pci_read_config32(ctrl->f2, 0x40  + (index << 2));
+                
+               if (!(value & 1)) {
+                       continue;
+               }
+               pci_write_config32(ctrl->f2, 0x40  + (index << 2), csbase);
+               pci_write_config32(ctrl->f2, 0x60  + (index << 2), csmask);
+               csbase += csbase_inc;
+       }
+       
+       print_debug("Interleaved\r\n");
+        
+       return common_size << (15 + bits);
+}
+static unsigned long order_chip_selects(const struct mem_controller *ctrl)
+{
+       unsigned long tom;
+       
+        
+       tom = 0;
+       for(;;) {
+                
+               unsigned index, canidate;
+               uint32_t csbase, csmask;
+               unsigned size;
+               csbase = 0;
+               canidate = 0;
+               for(index = 0; index < 8; index++) {
+                       uint32_t value;
+                       value = pci_read_config32(ctrl->f2, 0x40  + (index << 2));
+                        
+                       if (!(value & 1)) {
+                               continue;
+                       }
+                       
+                        
+                       if (value <= csbase) {
+                               continue;
+                       }
+                       
+                        
+                       if (tom & (1 << (index + 24))) {
+                               continue;
+                       }
+                        
+                       csbase = value;
+                       canidate = index;
+               }
+                
+               if (csbase == 0) {
+                       break;
+               }
+                
+               size = csbase >> 21;
+                
+               tom |= (1 << (canidate + 24));
+                
+               csbase = (tom << 21) | 1;
+                
+               tom += size;
+                
+               csmask = ((size -1) << 21);
+               csmask |= 0xfe00;                
+                
+               pci_write_config32(ctrl->f2, 0x40  + (canidate << 2), csbase);
+                
+               pci_write_config32(ctrl->f2, 0x60  + (canidate << 2), csmask);
+               
+       }
+        
+       return (tom & ~0xff000000) << 15;
+}
+static void order_dimms(const struct mem_controller *ctrl)
+{
+       unsigned long tom, tom_k, base_k;
+       unsigned node_id;
+       tom_k = interleave_chip_selects(ctrl);
+       if (!tom_k) {
+               tom_k = order_chip_selects(ctrl);
+       }
+        
+       base_k = 0;
+       for(node_id = 0; node_id < ctrl->node_id; node_id++) {
+               uint32_t limit, base;
+               unsigned index;
+               index = node_id << 3;
+               base = pci_read_config32(ctrl->f1, 0x40 + index);
+                
+               if ((base & 3) == 3) {
+                       limit = pci_read_config32(ctrl->f1, 0x44 + index);
+                       base_k = ((limit + 0x00010000) & 0xffff0000) >> 2;
+               }
+       }
+       tom_k += base_k;
+       route_dram_accesses(ctrl, base_k, tom_k);
+       set_top_mem(tom_k);
+}
+static void disable_dimm(const struct mem_controller *ctrl, unsigned index)
+{
+       print_debug("disabling dimm"); 
+       print_debug_hex8(index); 
+       print_debug("\r\n");
+       pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+0)<<2), 0);
+       pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+1)<<2), 0);
+}
+static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl)
+{
+       int i;
+       int registered;
+       int unbuffered;
+       uint32_t dcl;
+       unbuffered = 0;
+       registered = 0;
+       for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+               int value;
+               value = spd_read_byte(ctrl->channel0[i], 21);
+               if (value < 0) {
+                       disable_dimm(ctrl, i);
+                       continue;
+               }
+                
+               if (value & (1 << 1)) {
+                       registered = 1;
+               } 
+                
+               else {
+                       unbuffered = 1;
+               }
+       }
+       if (unbuffered && registered) {
+               die("Mixed buffered and registered dimms not supported");
+       }
+       if (unbuffered && is_opteron(ctrl)) {
+               die("Unbuffered Dimms not supported on Opteron");
+       }
+       dcl = pci_read_config32(ctrl->f2, 0x90 );
+       dcl &= ~(1<<18) ;
+       if (unbuffered) {
+               dcl |= (1<<18) ;
+       }
+       pci_write_config32(ctrl->f2, 0x90 , dcl);
+}
+static void spd_enable_2channels(const struct mem_controller *ctrl)
+{
+       int i;
+       uint32_t nbcap;
+        
+        
+       static const unsigned addresses[] = {
+               2,       
+               3,       
+               4,       
+               5,       
+               6,       
+               7,       
+               9,       
+               11,      
+               13,      
+               17,      
+               18,      
+               21,      
+               23,      
+               26,      
+               27,      
+               28,      
+               29,      
+               30,      
+               41,      
+               42,      
+       };
+       nbcap = pci_read_config32(ctrl->f3, 0xE8 );
+       if (!(nbcap & 0x0001 )) {
+               return;
+       }
+       for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+               unsigned device0, device1;
+               int value0, value1;
+               int j;
+               device0 = ctrl->channel0[i];
+               device1 = ctrl->channel1[i];
+               if (!device1)
+                       return;
+               for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) {
+                       unsigned addr;
+                       addr = addresses[j];
+                       value0 = spd_read_byte(device0, addr);
+                       if (value0 < 0) {
+                               break;
+                       }
+                       value1 = spd_read_byte(device1, addr);
+                       if (value1 < 0) {
+                               return;
+                       }
+                       if (value0 != value1) {
+                               return;
+                       }
+               }
+       }
+       print_debug("Enabling dual channel memory\r\n");
+       uint32_t dcl;
+       dcl = pci_read_config32(ctrl->f2, 0x90 );
+       dcl &= ~(1<<19) ;
+       dcl |= (1<<16) ;
+       pci_write_config32(ctrl->f2, 0x90 , dcl);
+}
+struct mem_param {
+       uint8_t cycle_time;
+       uint8_t divisor;  
+       uint8_t tRC;
+       uint8_t tRFC;
+       uint32_t dch_memclk;
+       uint16_t dch_tref4k, dch_tref8k;
+       uint8_t  dtl_twr;
+       char name[9];
+};
+static const struct mem_param *get_mem_param(unsigned min_cycle_time)
+{
+       static const struct mem_param speed[] = {
+               {
+                       .name       = "100Mhz\r\n",
+                       .cycle_time = 0xa0,
+                       .divisor    = (10 <<1),
+                       .tRC        = 0x46,
+                       .tRFC       = 0x50,
+                       .dch_memclk = 0  << 20 ,
+                       .dch_tref4k = 0x00 ,
+                       .dch_tref8k = 0x08 ,
+                       .dtl_twr    = 2,
+               },
+               {
+                       .name       = "133Mhz\r\n",
+                       .cycle_time = 0x75,
+                       .divisor    = (7<<1)+1,
+                       .tRC        = 0x41,
+                       .tRFC       = 0x4B,
+                       .dch_memclk = 2  << 20 ,
+                       .dch_tref4k = 0x01 ,
+                       .dch_tref8k = 0x09 ,
+                       .dtl_twr    = 2,
+               },
+               {
+                       .name       = "166Mhz\r\n",
+                       .cycle_time = 0x60,
+                       .divisor    = (6<<1),
+                       .tRC        = 0x3C,
+                       .tRFC       = 0x48,
+                       .dch_memclk = 5  << 20 ,
+                       .dch_tref4k = 0x02 ,
+                       .dch_tref8k = 0x0A ,
+                       .dtl_twr    = 3,
+               },
+               {
+                       .name       = "200Mhz\r\n",
+                       .cycle_time = 0x50,
+                       .divisor    = (5<<1),
+                       .tRC        = 0x37,
+                       .tRFC       = 0x46,
+                       .dch_memclk = 7  << 20 ,
+                       .dch_tref4k = 0x03 ,
+                       .dch_tref8k = 0x0B ,
+                       .dtl_twr    = 3,
+               },
+               {
+                       .cycle_time = 0x00,
+               },
+       };
+       const struct mem_param *param;
+       for(param = &speed[0]; param->cycle_time ; param++) {
+               if (min_cycle_time > (param+1)->cycle_time) {
+                       break;
+               }
+       }
+       if (!param->cycle_time) {
+               die("min_cycle_time to low");
+       }
+       print_debug(param->name);
+       return param;
+}
+static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
+{
+        
+       const struct mem_param *param;
+       unsigned min_cycle_time, min_latency;
+       int i;
+       uint32_t value;
+       static const int latency_indicies[] = { 26, 23, 9 };
+       static const unsigned char min_cycle_times[] = {
+               [0 ] = 0x50,  
+               [1 ] = 0x60,  
+               [2 ] = 0x75,  
+               [3 ] = 0xa0,  
+       };
+       value = pci_read_config32(ctrl->f3, 0xE8 );
+       min_cycle_time = min_cycle_times[(value >> 5 ) & 3 ];
+       min_latency = 2;
+        
+       for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+               int new_cycle_time, new_latency;
+               int index;
+               int latencies;
+               int latency;
+                
+               new_cycle_time = 0xa0;
+               new_latency = 5;
+               latencies = spd_read_byte(ctrl->channel0[i], 18);
+               if (latencies <= 0) continue;
+                
+               latency = log2(latencies) -2;
+                
+               for(index = 0; index < 3; index++, latency++) {
+                       int value;
+                       if ((latency < 2) || (latency > 4) ||
+                               (!(latencies & (1 << latency)))) {
+                               continue;
+                       }
+                       value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
+                       if (value < 0) {
+                               continue;
+                       }
+                        
+                       if ((value >= min_cycle_time) && (value < new_cycle_time)) {
+                               new_cycle_time = value;
+                               new_latency = latency;
+                       }
+               }
+               if (new_latency > 4){
+                       continue;
+               }
+                
+               if (new_cycle_time > min_cycle_time) {
+                       min_cycle_time = new_cycle_time;
+               }
+                
+               if (new_latency > min_latency) {
+                       min_latency = new_latency;
+               }
+       }
+        
+       
+       for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+               int latencies;
+               int latency;
+               int index;
+               int value;
+               int dimm;
+               latencies = spd_read_byte(ctrl->channel0[i], 18);
+               if (latencies <= 0) {
+                       goto dimm_err;
+               }
+                
+               latency = log2(latencies) -2;
+                
+               for(index = 0; index < 3; index++, latency++) {
+                       if (!(latencies & (1 << latency))) {
+                               continue;
+                       }
+                       if (latency == min_latency)
+                               break;
+               }
+                
+               if ((latency != min_latency) || (index >= 3)) {
+                       goto dimm_err;
+               }
+               
+                
+               value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
+               
+                
+               if (value <= min_cycle_time) {
+                       continue;
+               }
+                
+       dimm_err:
+               disable_dimm(ctrl, i);
+       }
+        
+       param = get_mem_param(min_cycle_time);
+        
+       value = pci_read_config32(ctrl->f2, 0x94 );
+       value &= ~(0x7  << 20 );
+       value |= param->dch_memclk;
+       pci_write_config32(ctrl->f2, 0x94 , value);
+       static const unsigned latencies[] = { 1 , 5 , 2  };
+        
+       value = pci_read_config32(ctrl->f2, 0x88 );
+       value &= ~(0x7  << 0 );
+       value |= latencies[min_latency - 2] << 0 ;
+       pci_write_config32(ctrl->f2, 0x88 , value);
+       
+       return param;
+}
+static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+       unsigned clocks, old_clocks;
+       uint32_t dtl;
+       int value;
+       value = spd_read_byte(ctrl->channel0[i], 41);
+       if (value < 0) return -1;
+       if ((value == 0) || (value == 0xff)) {
+               value = param->tRC;
+       }
+       clocks = ((value << 1) + param->divisor - 1)/param->divisor;
+       if (clocks < 7 ) {
+               clocks = 7 ;
+       }
+       if (clocks > 22 ) {
+               return -1;
+       }
+       dtl = pci_read_config32(ctrl->f2, 0x88 );
+       old_clocks = ((dtl >> 4 ) & 0xf ) + 7 ;
+       if (old_clocks > clocks) {
+               clocks = old_clocks;
+       }
+       dtl &= ~(0xf  << 4 );
+       dtl |=  ((clocks - 7 ) << 4 );
+       pci_write_config32(ctrl->f2, 0x88 , dtl);
+       return 0;
+}
+static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+       unsigned clocks, old_clocks;
+       uint32_t dtl;
+       int value;
+       value = spd_read_byte(ctrl->channel0[i], 42);
+       if (value < 0) return -1;
+       if ((value == 0) || (value == 0xff)) {
+               value = param->tRFC;
+       }
+       clocks = ((value << 1) + param->divisor - 1)/param->divisor;
+       if (clocks < 9 ) {
+               clocks = 9 ;
+       }
+       if (clocks > 24 ) {
+               return -1;
+       }
+       dtl = pci_read_config32(ctrl->f2, 0x88 );
+       old_clocks = ((dtl >> 8 ) & 0xf ) + 9 ;
+       if (old_clocks > clocks) {
+               clocks = old_clocks;
+       }
+       dtl &= ~(0xf  << 8 );
+       dtl |= ((clocks - 9 ) << 8 );
+       pci_write_config32(ctrl->f2, 0x88 , dtl);
+       return 0;
+}
+static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+       unsigned clocks, old_clocks;
+       uint32_t dtl;
+       int value;
+       value = spd_read_byte(ctrl->channel0[i], 29);
+       if (value < 0) return -1;
+       clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
+       if (clocks < 2 ) {
+               clocks = 2 ;
+       }
+       if (clocks > 6 ) {
+               return -1;
+       }
+       dtl = pci_read_config32(ctrl->f2, 0x88 );
+       old_clocks = ((dtl >> 12 ) & 0x7 ) + 0 ;
+       if (old_clocks > clocks) {
+               clocks = old_clocks;
+       }
+       dtl &= ~(0x7  << 12 );
+       dtl |= ((clocks - 0 ) << 12 );
+       pci_write_config32(ctrl->f2, 0x88 , dtl);
+       return 0;
+}
+static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+       unsigned clocks, old_clocks;
+       uint32_t dtl;
+       int value;
+       value = spd_read_byte(ctrl->channel0[i], 28);
+       if (value < 0) return -1;
+       clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
+       if (clocks < 2 ) {
+               clocks = 2 ;
+       }
+       if (clocks > 4 ) {
+               return -1;
+       }
+       dtl = pci_read_config32(ctrl->f2, 0x88 );
+       old_clocks = ((dtl >> 16 ) & 0x7 ) + 0 ;
+       if (old_clocks > clocks) {
+               clocks = old_clocks;
+       }
+       dtl &= ~(0x7  << 16 );
+       dtl |= ((clocks - 0 ) << 16 );
+       pci_write_config32(ctrl->f2, 0x88 , dtl);
+       return 0;
+}
+static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+       unsigned clocks, old_clocks;
+       uint32_t dtl;
+       int value;
+       value = spd_read_byte(ctrl->channel0[i], 30);
+       if (value < 0) return -1;
+       clocks = ((value << 1) + param->divisor - 1)/param->divisor;
+       if (clocks < 5 ) {
+               clocks = 5 ;
+       }
+       if (clocks > 15 ) {
+               return -1;
+       }
+       dtl = pci_read_config32(ctrl->f2, 0x88 );
+       old_clocks = ((dtl >> 20 ) & 0xf ) + 0 ;
+       if (old_clocks > clocks) {
+               clocks = old_clocks;
+       }
+       dtl &= ~(0xf  << 20 );
+       dtl |= ((clocks - 0 ) << 20 );
+       pci_write_config32(ctrl->f2, 0x88 , dtl);
+       return 0;
+}
+static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+       unsigned clocks, old_clocks;
+       uint32_t dtl;
+       int value;
+       value = spd_read_byte(ctrl->channel0[i], 27);
+       if (value < 0) return -1;
+       clocks = (value + ((param->divisor & 0xff) << 1) - 1)/((param->divisor & 0xff) << 1);
+       if (clocks < 2 ) {
+               clocks = 2 ;
+       }
+       if (clocks > 6 ) {
+               return -1;
+       }
+       dtl = pci_read_config32(ctrl->f2, 0x88 );
+       old_clocks = ((dtl >> 24 ) & 0x7 ) + 0 ;
+       if (old_clocks > clocks) {
+               clocks = old_clocks;
+       }
+       dtl &= ~(0x7  << 24 );
+       dtl |= ((clocks - 0 ) << 24 );
+       pci_write_config32(ctrl->f2, 0x88 , dtl);
+       return 0;
+}
+static void set_Twr(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+       uint32_t dtl;
+       dtl = pci_read_config32(ctrl->f2, 0x88 );
+       dtl &= ~(0x1  << 28 );
+       dtl |= (param->dtl_twr - 2 ) << 28 ;
+       pci_write_config32(ctrl->f2, 0x88 , dtl);
+}
+static void init_Tref(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+       uint32_t dth;
+       dth = pci_read_config32(ctrl->f2, 0x8c );
+       dth &= ~(0x1f  << 8 );
+       dth |= (param->dch_tref4k << 8 );
+       pci_write_config32(ctrl->f2, 0x8c , dth);
+}
+static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+       uint32_t dth;
+       int value;
+       unsigned tref, old_tref;
+       value = spd_read_byte(ctrl->channel0[i], 3);
+       if (value < 0) return -1;
+       value &= 0xf;
+       tref = param->dch_tref8k;
+       if (value == 12) {
+               tref = param->dch_tref4k;
+       }
+       dth = pci_read_config32(ctrl->f2, 0x8c );
+       old_tref = (dth >> 8 ) & 0x1f ;
+       if ((value == 12) && (old_tref == param->dch_tref4k)) {
+               tref = param->dch_tref4k;
+       } else {
+               tref = param->dch_tref8k;
+       }
+       dth &= ~(0x1f  << 8 );
+       dth |= (tref << 8 );
+       pci_write_config32(ctrl->f2, 0x8c , dth);
+       return 0;
+}
+static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+       uint32_t dcl;
+       int value;
+       int dimm;
+       value = spd_read_byte(ctrl->channel0[i], 13);
+       if (value < 0) {
+               return -1;
+       }
+       dimm = i;
+       dimm += 20 ;
+       dcl = pci_read_config32(ctrl->f2, 0x90 );
+       dcl &= ~(1 << dimm);
+       if (value == 4) {
+               dcl |= (1 << dimm);
+       }
+       pci_write_config32(ctrl->f2, 0x90 , dcl);
+       return 0;
+}
+static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+       uint32_t dcl;
+       int value;
+       value = spd_read_byte(ctrl->channel0[i], 11);
+       if (value < 0) {
+               return -1;
+       }
+       if (value != 2) {
+               dcl = pci_read_config32(ctrl->f2, 0x90 );
+               dcl &= ~(1<<17) ;
+               pci_write_config32(ctrl->f2, 0x90 , dcl);
+       }
+       return 0;
+}
+static int count_dimms(const struct mem_controller *ctrl)
+{
+       int dimms;
+       unsigned index;
+       dimms = 0;
+       for(index = 0; index < 8; index += 2) {
+               uint32_t csbase;
+               csbase = pci_read_config32(ctrl->f2, (0x40  + index << 2));
+               if (csbase & 1) {
+                       dimms += 1;
+               }
+       }
+       return dimms;
+}
+static void set_Twtr(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+       uint32_t dth;
+       unsigned clocks;
+       clocks = 1;  
+       dth = pci_read_config32(ctrl->f2, 0x8c );
+       dth &= ~(0x1  << 0 );
+       dth |= ((clocks - 1 ) << 0 );
+       pci_write_config32(ctrl->f2, 0x8c , dth);
+}
+static void set_Trwt(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+       uint32_t dth, dtl;
+       unsigned divisor;
+       unsigned latency;
+       unsigned clocks;
+       clocks = 0;
+       dtl = pci_read_config32(ctrl->f2, 0x88 );
+       latency = (dtl >> 0 ) & 0x7 ;
+       divisor = param->divisor;
+       if (is_opteron(ctrl)) {
+               if (latency == 1 ) {
+                       if (divisor == ((6 << 0) + 0)) {
+                                
+                               clocks = 3;
+                       }
+                       else if (divisor > ((6 << 0)+0)) {
+                                
+                               clocks = 2;
+                       }
+               }
+               else if (latency == 5 ) {
+                       clocks = 3;
+               }
+               else if (latency == 2 ) {
+                       if (divisor == ((6 << 0)+0)) {
+                                
+                               clocks = 4;
+                       }
+                       else if (divisor > ((6 << 0)+0)) {
+                                
+                               clocks = 3;
+                       }
+               }
+       }
+       else   {
+               if (is_registered(ctrl)) {
+                       if (latency == 1 ) {
+                               clocks = 2;
+                       }
+                       else if (latency == 5 ) {
+                               clocks = 3;
+                       }
+                       else if (latency == 2 ) {
+                               clocks = 3;
+                       }
+               }
+               else  {
+                       if (latency == 1 ) {
+                               clocks = 3;
+                       }
+                       else if (latency == 5 ) {
+                               clocks = 4;
+                       }
+                       else if (latency == 2 ) {
+                               clocks = 4;
+                       }
+               }
+       }
+       if ((clocks < 1 ) || (clocks > 6 )) {
+               die("Unknown Trwt");
+       }
+       
+       dth = pci_read_config32(ctrl->f2, 0x8c );
+       dth &= ~(0x7  << 4 );
+       dth |= ((clocks - 1 ) << 4 );
+       pci_write_config32(ctrl->f2, 0x8c , dth);
+       return;
+}
+static void set_Twcl(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+        
+       uint32_t dth;
+       unsigned clocks;
+       if (is_registered(ctrl)) {
+               clocks = 2;
+       } else {
+               clocks = 1;
+       }
+       dth = pci_read_config32(ctrl->f2, 0x8c );
+       dth &= ~(0x7  << 20 );
+       dth |= ((clocks - 1 ) << 20 );
+       pci_write_config32(ctrl->f2, 0x8c , dth);
+}
+static void set_read_preamble(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+       uint32_t dch;
+       unsigned divisor;
+       unsigned rdpreamble;
+       divisor = param->divisor;
+       dch = pci_read_config32(ctrl->f2, 0x94 );
+       dch &= ~(0xf  << 8 );
+       rdpreamble = 0;
+       if (is_registered(ctrl)) {
+               if (divisor == ((10 << 1)+0)) {
+                        
+                       rdpreamble = ((9 << 1)+ 0);
+               }
+               else if (divisor == ((7 << 1)+1)) {
+                        
+                       rdpreamble = ((8 << 1)+0);
+               }
+               else if (divisor == ((6 << 1)+0)) {
+                        
+                       rdpreamble = ((7 << 1)+1);
+               }
+               else if (divisor == ((5 << 1)+0)) {
+                        
+                       rdpreamble = ((7 << 1)+0);
+               }
+       }
+       else {
+               int slots;
+               int i;
+               slots = 0;
+               for(i = 0; i < 4; i++) {
+                       if (ctrl->channel0[i]) {
+                               slots += 1;
+                       }
+               }
+               if (divisor == ((10 << 1)+0)) {
+                        
+                       if (slots <= 2) {
+                                
+                               rdpreamble = ((9 << 1)+0);
+                       } else {
+                                
+                               rdpreamble = ((14 << 1)+0);
+                       }
+               }
+               else if (divisor == ((7 << 1)+1)) {
+                        
+                       if (slots <= 2) {
+                                
+                               rdpreamble = ((7 << 1)+0);
+                       } else {
+                                
+                               rdpreamble = ((11 << 1)+0);
+                       }
+               }
+               else if (divisor == ((6 << 1)+0)) {
+                        
+                       if (slots <= 2) {
+                                
+                               rdpreamble = ((7 << 1)+0);
+                       } else {
+                                
+                               rdpreamble = ((9 << 1)+0);
+                       }
+               }
+               else if (divisor == ((5 << 1)+0)) {
+                        
+                       if (slots <= 2) {
+                                
+                               rdpreamble = ((5 << 1)+0);
+                       } else {
+                                
+                               rdpreamble = ((7 << 1)+0);
+                       }
+               }
+       }
+       if ((rdpreamble < ((2<<1)+0) ) || (rdpreamble > ((9<<1)+1) )) {
+               die("Unknown rdpreamble");
+       }
+       dch |= (rdpreamble - ((2<<1)+0) ) << 8 ;
+       pci_write_config32(ctrl->f2, 0x94 , dch);
+}
+static void set_max_async_latency(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+       uint32_t dch;
+       int i;
+       unsigned async_lat;
+       int dimms;
+       dimms = count_dimms(ctrl);
+       dch = pci_read_config32(ctrl->f2, 0x94 );
+       dch &= ~(0xf  << 0 );
+       async_lat = 0;
+       if (is_registered(ctrl)) {
+               if (dimms == 4) {
+                        
+                       async_lat = 9;
+               } 
+               else {
+                        
+                       async_lat = 8;
+               }
+       }
+       else {
+               if (dimms > 3) {
+                       die("Too many unbuffered dimms");
+               }
+               else if (dimms == 3) {
+                        
+                       async_lat = 7;
+               }
+               else {
+                        
+                       async_lat = 6;
+               }
+       }
+       dch |= ((async_lat - 0 ) << 0 );
+       pci_write_config32(ctrl->f2, 0x94 , dch);
+}
+static void set_idle_cycle_limit(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+       uint32_t dch;
+        
+       dch = pci_read_config32(ctrl->f2, 0x94 );
+       dch &= ~(0x7  << 16 );
+       dch |= 3  << 16 ;
+       dch |= (1 << 19) ;
+       pci_write_config32(ctrl->f2, 0x94 , dch);
+}
+static void spd_set_dram_timing(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+       int dimms;
+       int i;
+       int rc;
+       
+       init_Tref(ctrl, param);
+       for(i = 0; (i < 4) && ctrl->channel0[i]; i++) {
+               int rc;
+                
+               if (update_dimm_Trc (ctrl, param, i) < 0) goto dimm_err;
+               if (update_dimm_Trfc(ctrl, param, i) < 0) goto dimm_err;
+               if (update_dimm_Trcd(ctrl, param, i) < 0) goto dimm_err;
+               if (update_dimm_Trrd(ctrl, param, i) < 0) goto dimm_err;
+               if (update_dimm_Tras(ctrl, param, i) < 0) goto dimm_err;
+               if (update_dimm_Trp (ctrl, param, i) < 0) goto dimm_err;
+                
+               if (update_dimm_Tref(ctrl, param, i) < 0) goto dimm_err;
+                
+               if (update_dimm_x4 (ctrl, param, i) < 0) goto dimm_err;
+               if (update_dimm_ecc(ctrl, param, i) < 0) goto dimm_err;
+               continue;
+       dimm_err:
+               disable_dimm(ctrl, i);
+               
+       }
+        
+       set_Twr(ctrl, param);
+        
+       set_Twtr(ctrl, param);
+       set_Trwt(ctrl, param);
+       set_Twcl(ctrl, param);
+        
+       set_read_preamble(ctrl, param);
+       set_max_async_latency(ctrl, param);
+       set_idle_cycle_limit(ctrl, param);
+}
+static void sdram_set_spd_registers(const struct mem_controller *ctrl) 
+{
+       const struct mem_param *param;
+       spd_enable_2channels(ctrl);
+       spd_set_ram_size(ctrl);
+       spd_handle_unbuffered_dimms(ctrl);
+       param = spd_set_memclk(ctrl);
+       spd_set_dram_timing(ctrl, param);
+       order_dimms(ctrl);
+}
+static void sdram_enable(int controllers, const struct mem_controller *ctrl)
+{
+       int i;
+        
+       for(i = 0; i < controllers; i++) {
+               uint32_t dch;
+               dch = pci_read_config32(ctrl[i].f2, 0x94 );
+               dch |= (1 << 25) ;
+               pci_write_config32(ctrl[i].f2, 0x94 , dch);
+       }
+        
+       memreset(controllers, ctrl);
+       for(i = 0; i < controllers; i++) {
+               uint32_t dcl;
+                
+               dcl = pci_read_config32(ctrl[i].f2, 0x90 );
+               if (dcl & (1<<17) ) {
+                       uint32_t mnc;
+                       print_debug("ECC enabled\r\n");
+                       mnc = pci_read_config32(ctrl[i].f3, 0x44 );
+                       mnc |= (1 << 22) ;
+                       if (dcl & (1<<16) ) {
+                               mnc |= (1 << 23) ;
+                       }
+                       pci_write_config32(ctrl[i].f3, 0x44 , mnc);
+               }
+               dcl |= (1<<3) ;
+               pci_write_config32(ctrl[i].f2, 0x90 , dcl);
+               dcl &= ~(1<<3) ;
+               dcl &= ~(1<<0) ;
+               dcl &= ~(1<<1) ;
+               dcl &= ~(1<<2) ;
+               dcl |= (1<<8) ;
+               pci_write_config32(ctrl[i].f2, 0x90 , dcl);
+       }
+       for(i = 0; i < controllers; i++) {
+               uint32_t dcl;
+               print_debug("Initializing memory: ");
+               int loops = 0;
+               do {
+                       dcl = pci_read_config32(ctrl[i].f2, 0x90 );
+                       loops += 1;
+                       if ((loops & 1023) == 0) {
+                               print_debug(".");
+                       }
+               } while(((dcl & (1<<8) ) != 0) && (loops < 300000 ));
+               if (loops >= 300000 ) {
+                       print_debug(" failed\r\n");
+               } else {
+                       print_debug(" done\r\n");
+               }
+               if (dcl & (1<<17) ) {
+                       print_debug("Clearing memory: ");
+                       if (!is_cpu_pre_c0()) {
+                                
+                               dcl &= ~((1<<11)  | (1<<10) );
+                               pci_write_config32(ctrl[i].f2, 0x90 , dcl);
+                               do {
+                                       dcl = pci_read_config32(ctrl[i].f2, 0x90 );
+                               } while(((dcl & (1<<11) ) == 0) || ((dcl & (1<<10) ) == 0) );
+                       }
+                       uint32_t base, last_scrub_k, scrub_k;
+                       uint32_t cnt,zstart,zend;
+                       msr_t msr,msr_201;
+                        
+                       pci_write_config32(ctrl[i].f3, 0x58 ,
+                               (0  << 16) | (0  << 8) | (0  << 0));
+                        
+                       msr_201 = rdmsr(0x201);
+                       zstart = pci_read_config32(ctrl[0].f1, 0x40 + (i*8));
+                       zend = pci_read_config32(ctrl[0].f1, 0x44 + (i*8));
+                       zstart >>= 16;
+                       zend >>=16;
+                       print_debug("addr ");
+                       print_debug_hex32(zstart);
+                       print_debug("-");
+                       print_debug_hex32(zend);
+                       print_debug("\r\n");
+                       
+                        
+                       msr = rdmsr(0x2ff );
+                       msr.lo &= ~(1<<10);
+                       wrmsr(0x2ff , msr);
+                        
+                       msr = rdmsr(0xc0010015);
+                       msr.lo |= (1<<17);
+                       wrmsr(0xc0010015,msr);
+                       for(;zstart<zend;zstart+=4) {
+                                
+                               if(zstart == 0x0fc)
+                                       continue;
+                               
+                                
+                               __asm__ volatile(
+                                       "movl  %%cr0, %0\n\t"
+                                       "orl  $0x40000000, %0\n\t"
+                                       "movl  %0, %%cr0\n\t"
+                                       :"=r" (cnt)
+                                       );
+                               
+                                
+                               msr.lo = 1 + ((zstart&0x0ff)<<24);
+                               msr.hi = (zstart&0x0ff00)>>8;
+                               wrmsr(0x200,msr);
+                                
+                               msr.hi = 0x000000ff;
+                               msr.lo = 0xfc000800;
+                               wrmsr(0x201,msr);
+                                
+                               __asm__ volatile(
+                                       "movl  %%cr0, %0\n\t"
+                                       "andl  $0x9fffffff, %0\n\t"
+                                       "movl  %0, %%cr0\n\t"   
+                                       :"=r" (cnt)     
+                                       );
+                                
+                               msr.lo = (zstart&0xff) << 24;
+                               msr.hi = (zstart&0xff00) >> 8;
+                               wrmsr(0xc0000100,msr);
+                               print_debug_char((zstart > 0x0ff)?'+':'-');     
+                                       
+                                
+                               __asm__ volatile(
+                                       "1: \n\t"
+                                       "movl %0, %%fs:(%1)\n\t"
+                                       "addl $4,%1\n\t"
+                                       "subl $1,%2\n\t"
+                                       "jnz 1b\n\t"
+                                       :
+                                       : "a" (0), "D" (0), "c" (0x01000000)
+                                       );                      
+                       }
+                       
+                        
+                       __asm__ volatile(
+                               "movl  %%cr0, %0\n\t"
+                               "orl  $0x40000000, %0\n\t"
+                               "movl  %0, %%cr0\n\t"
+                               :"=r" (cnt)     
+                               );
+               
+                               
+                       msr = rdmsr(0x2ff );
+                       msr.lo |= 0x0400;
+                       wrmsr(0x2ff , msr);
+                        
+                       msr.lo = 6;
+                       msr.hi = 0;
+                       wrmsr(0x200,msr);
+                       wrmsr(0x201,msr_201);
+                        
+                       msr.lo = 0;
+                       msr.hi = 0;
+                       wrmsr(0xc0000100,msr);
+                        
+                       __asm__ volatile(
+                               "movl  %%cr0, %0\n\t"
+                               "andl  $0x9fffffff, %0\n\t"
+                               "movl  %0, %%cr0\n\t"   
+                               :"=r" (cnt)     
+                               );
+                       
+                        
+                       msr = rdmsr(0xc0010015);
+                       msr.lo &= ~(1<<17);
+                       wrmsr(0xc0010015,msr);
+                        
+                       base = pci_read_config32(ctrl[i].f1, 0x40 + (ctrl[i].node_id << 3));
+                       base &= 0xffff0000;
+                        
+                       pci_write_config32(ctrl[i].f3, 0x5C , base << 8);
+                       pci_write_config32(ctrl[i].f3, 0x60 , base >> 24);
+                        
+                       pci_write_config32(ctrl[i].f3, 0x58 , 
+                               (22  << 16) | (22  << 8) | (22  << 0));
+                       print_debug("done\r\n");
+               }
+       }
+}
+typedef uint8_t u8;
+typedef uint32_t u32;
+typedef int8_t bool;
+static void disable_probes(void)
+{
+        
+        
+       u32 val;
+       print_debug("Disabling read/write/fill probes for UP... ");
+       val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x68);
+       val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0);
+       pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x68, val);
+       print_debug("done.\r\n");
+}
+static void wait_ap_stop(u8 node) 
+{
+       unsigned long reg;
+       unsigned long i;
+       for(i=0;i< 1000 ;i++) {
+               unsigned long regx;
+               regx = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x6c);
+               if((regx & (1<<4))==1) break;
+        }
+       reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x6c);
+        reg &= ~(1<<4);   
+        pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6c, reg);
+}
+static void notify_bsp_ap_is_stopped(void)
+{
+       unsigned long reg;
+       unsigned long apic_id;
+        apic_id = *((volatile unsigned long *)(0xfee00000 + 0x020 ));
+       apic_id >>= 24;
+        
+        if(apic_id != 0) {
+                
+                reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6C);
+                reg |= 1<<4;
+                pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6C, reg);
+        }
+}
+static void enable_routing(u8 node)
+{
+       u32 val;
+        
+        
+       print_debug("Enabling routing table for node ");
+       print_debug_hex32(node);
+       val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6c);
+       val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0));
+       pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6c, val);
+       if(node!=0) {
+               wait_ap_stop(node);
+       }
+       print_debug(" done.\r\n");
+}
+static void rename_temp_node(u8 node)
+{
+       uint32_t val;
+       print_debug("Renaming current temp node to ");
+       print_debug_hex32(node);
+       val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x60);
+       val &= (~7);   
+        val |= node;    
+       pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x60, val);
+       print_debug(" done.\r\n");
+}
+static bool check_connection(u8 src, u8 dest, u8 link)
+{
+        
+       u32 val;
+       
+        
+       val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ src  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x98+link);
+       if ( (val&0x17) != 0x03)
+               return 0;
+        
+        val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ dest  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0);
+       if(val != 0x11001022)
+               return 0;
+       return 1;
+}
+static void optimize_connection(u8 node1, u8 link1, u8 node2, u8 link2)
+{
+       static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
+       static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
+       uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask;
+       uint8_t width_cap1, width_cap2, width_cap, width, ln_width1, ln_width2;
+       uint8_t freq;
+        
+        
+       freq_cap1  = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link1 + 0x0a );
+       freq_cap2  = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link2 + 0x0a );
+        
+        
+       freq = log2(freq_cap1 & freq_cap2 & 0xff);
+        
+       pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link1 + 0x09 , freq);
+       pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link2 + 0x09 , freq);
+        
+       width_cap1 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,  0x80 + link1 + 6 );
+       width_cap2 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,  0x80 + link2 + 6 );
+        
+       ln_width1 = link_width_to_pow2[width_cap1 & 7];
+       ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7];
+       if (ln_width1 > ln_width2) {
+               ln_width1 = ln_width2;
+       }
+       width = pow2_to_link_width[ln_width1];
+        
+       ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7];
+       ln_width2 = link_width_to_pow2[width_cap2 & 7];
+       if (ln_width1 > ln_width2) {
+               ln_width1 = ln_width2;
+       }
+       width |= pow2_to_link_width[ln_width1] << 4;
+       
+        
+       pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link1 + 6  + 1, width);
+        
+       width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
+       pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link2 + 6  + 1, width);
+}
+static void fill_row(u8 node, u8 row, u32 value)
+{
+       pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x40+(row<<2), value);
+}
+static void setup_row(u8 source, u8 dest, u8 cpus)
+{
+       fill_row(source,dest,generate_row(source,dest,cpus));
+}
+static void setup_temp_row(u8 source, u8 dest, u8 cpus)
+{
+       fill_row(source,7,((generate_row( source,dest,cpus )&(~0x0f0000))|0x010000) );
+}
+static void setup_node(u8 node, u8 cpus)
+{
+       u8 row;
+       for(row=0; row<cpus; row++)
+               setup_row(node, row, cpus);
+}
+static void setup_remote_row(u8 source, u8 dest, u8 cpus)
+{
+       fill_row(7, dest, generate_row(source, dest, cpus));
+}
+static void setup_remote_node(u8 node, u8 cpus)
+{
+       static const uint8_t pci_reg[] = { 
+               0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c, 
+               0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
+               0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
+               0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
+               0xc4, 0xcc, 0xd4, 0xdc,
+               0xc0, 0xc8, 0xd0, 0xd8,
+               0xe0, 0xe4, 0xe8, 0xec,
+       };
+       uint8_t row;
+       int i;
+       print_debug("setup_remote_node\r\n");
+       for(row=0; row<cpus; row++)
+               setup_remote_row(node, row, cpus);
+        
+       for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
+               uint32_t value;
+               uint8_t reg;
+               reg = pci_reg[i];
+               value = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0  ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8))  , reg);
+               pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7  ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8))  , reg, value);
+       }
+       print_debug("setup_remote_done\r\n");
+}
+static u8 setup_uniprocessor(void)
+{
+       print_debug("Enabling UP settings\r\n");
+       disable_probes();
+       return 1;
+}
+static u8 setup_smp(void)
+{
+       u8 cpus=2;
+       print_debug("Enabling SMP settings\r\n");
+       setup_row(0,0,cpus);
+        
+       setup_temp_row(0,1,cpus);
+       
+       if (!check_connection(0, 7, 0x20  )) {
+               print_debug("No connection to Node 1.\r\n");
+               fill_row( 0 ,7,0x00010101 ) ;    
+               setup_uniprocessor();    
+               return 1;
+       }
+        
+       optimize_connection(0, 0x20 , 7, 0x20 );
+       setup_node(0, cpus);     
+       setup_remote_node(1, cpus);   
+        rename_temp_node(1);     
+        enable_routing(1);       
+       
+       fill_row( 0 ,7,0x00010101 ) ;    
+       
+       print_debug_hex32(cpus);
+       print_debug(" nodes initialized.\r\n");
+       return cpus;
+}
+static unsigned detect_mp_capabilities(unsigned cpus)
+{
+       unsigned node, row, mask;
+       bool mp_cap= (-1) ;
+       print_debug("detect_mp_capabilities: ");
+       print_debug_hex32(cpus);
+       print_debug("\r\n");
+       if (cpus>2)
+               mask=0x06;       
+       else
+               mask=0x02;       
+       for (node=0; node<cpus; node++) {
+               if ((pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8))  , 0xe8) & mask)!=mask)
+                       mp_cap= (0) ;
+       }
+       if (mp_cap)
+               return cpus;
+        
+       print_debug("One of the CPUs is not MP capable. Going back to UP\r\n");
+       for (node=cpus; node>0; node--)
+           for (row=cpus; row>0; row--)
+               fill_row(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node-1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , row-1, 0x00010101 );
+       
+       return setup_uniprocessor();
+}
+static void coherent_ht_finalize(unsigned cpus)
+{
+       int node;
+       bool rev_a0;
+       
+        
+       print_debug("coherent_ht_finalize\r\n");
+       rev_a0= is_cpu_rev_a0();
+       for (node=0; node<cpus; node++) {
+               u32 val;
+               val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x60);
+               val &= (~0x000F0070);
+               val |= ((cpus-1)<<16)|((cpus-1)<<4);
+               pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x60,val);
+               val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x68);
+               val |= 0x00008000;
+               pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x68,val);
+               if (rev_a0) {
+                       pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x94,0);
+                       pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0xb4,0);
+                       pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0xd4,0);
+               }
+       }
+       print_debug("done\r\n");
+}
+static int setup_coherent_ht_domain(void)
+{
+       unsigned cpus;
+       int reset_needed = 0;
+       enable_routing(0) ;
+       cpus=setup_smp();
+       cpus=detect_mp_capabilities(cpus);
+       coherent_ht_finalize(cpus);
+        
+       coherent_ht_mainboard(cpus);
+       return reset_needed;
+}
+void sdram_no_memory(void)
+{
+       print_err("No memory!!\r\n");
+       while(1) { 
+               hlt(); 
+       }
+}
+void sdram_initialize(int controllers, const struct mem_controller *ctrl)
+{
+       int i;
+        
+       for(i = 0; i < controllers; i++) {
+               print_debug("Ram1.");
+               print_debug_hex8(i);
+               print_debug("\r\n");
+               sdram_set_registers(ctrl + i);
+       }
+        
+       for(i = 0; i < controllers; i++) {
+               print_debug("Ram2.");
+               print_debug_hex8(i);
+               print_debug("\r\n");
+               sdram_set_spd_registers(ctrl + i);
+       }
+        
+       print_debug("Ram3\r\n");
+       sdram_enable(controllers, ctrl);
+       print_debug("Ram4\r\n");
+}
+static void enable_lapic(void)
+{
+       msr_t msr;
+       msr = rdmsr(0x1b);
+       msr.hi &= 0xffffff00;
+       msr.lo &= 0x000007ff;
+       msr.lo |= 0xfee00000  | (1 << 11);
+       wrmsr(0x1b, msr);
+}
+static void stop_this_cpu(void)
+{
+       unsigned apicid;
+       apicid = apic_read(0x020 ) >> 24;
+        
+       apic_write(0x310 , (( apicid )<<24) );
+       apic_write(0x300 , 0x08000  | 0x04000  | 0x00500 );
+        
+       apic_wait_icr_idle();
+        
+       apic_write(0x310 , (( apicid )<<24) );
+       apic_write(0x300 ,  0x08000  | 0x00500 );
+        
+       apic_wait_icr_idle();
+        
+       for(;;) {
+               hlt();
+       }
+}
+static void pc87360_enable_serial(void)
+{
+       pnp_set_logical_device(0x2e , 0x03 );
+       pnp_set_enable(0x2e , 1);
+       pnp_set_iobase0(0x2e , 0x3f8);
+}
+static void main(void)
+{
+        
+       static const struct mem_controller cpu[] = {
+               {
+                       .node_id = 0,
+                       .f0 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ,
+                       .f1 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ,
+                       .f2 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 )  & 0x7) << 8)) ,
+                       .f3 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 )  & 0x7) << 8)) ,
+                       .channel0 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 },
+                       .channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 },
+               },
+               {
+                       .node_id = 1,
+                       .f0 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ,
+                       .f1 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ,
+                       .f2 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  2 )  & 0x7) << 8)) ,
+                       .f3 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  3 )  & 0x7) << 8)) ,
+                       .channel0 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 },
+                       .channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 },
+               },
+       };
+       if (cpu_init_detected()) {
+               asm("jmp __cpu_reset");
+       }
+       enable_lapic();
+       init_timer();
+       if (!boot_cpu()) {
+               stop_this_cpu();
+       }
+       pc87360_enable_serial();
+       uart_init();
+       console_init();
+       setup_default_resource_map();
+       setup_coherent_ht_domain();
+       enumerate_ht_chain(0);
+       distinguish_cpu_resets(0);
+       
+       enable_smbus();
+       memreset_setup();
+       sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);
+        
+}
diff --git a/util/romcc/tests/simple_test57.c b/util/romcc/tests/simple_test57.c
new file mode 100644 (file)
index 0000000..47e2397
--- /dev/null
@@ -0,0 +1,5 @@
+static void main(void)
+{
+       for(;;) {
+       }
+}
diff --git a/util/romcc/tests/simple_test58.c b/util/romcc/tests/simple_test58.c
new file mode 100644 (file)
index 0000000..a5cd521
--- /dev/null
@@ -0,0 +1,9 @@
+static void main(void)
+{
+       const char *str;
+       unsigned char ch;
+       str = "one\r\n";
+       while((ch = *str++) != '\0') {
+               __builtin_outb(ch, 0x3f0);
+       }
+}
index 55a5f19389a639f528d1ba17070f6ec2cf5f17e0..d277c94dd3e7a0df506db8a26da8da579718e94a 100644 (file)
@@ -3,7 +3,7 @@ struct mem_param {
        unsigned char divisor;
        unsigned char tRC;
        unsigned char tRFC;
-       unsigned  dch_memclk;
+       unsigned dch_memclk;
        unsigned short dch_tref4k, dch_tref8k;
        unsigned char dtl_twr;
        char name[9];
diff --git a/util/romcc/tests/simple_test61.c b/util/romcc/tests/simple_test61.c
new file mode 100644 (file)
index 0000000..583a9db
--- /dev/null
@@ -0,0 +1,26 @@
+static void spd_set_nbxcfg(void)
+{
+       /*
+        * Effects:     Uses serial presence detect to set the
+        *              ECC support flags in the NBXCFG register
+        * FIXME:       Check for illegal/unsupported ram configurations and abort
+        */
+       unsigned device;
+
+       for(device = 0x50; device <= 0x53; device += 1) {
+               int byte;
+
+               byte = 0; /* Disable ECC */
+               /* 0 == None, 1 == Parity, 2 == ECC */
+               if (byte != 2) continue;
+
+               /* set the device I'm talking too */
+               __builtin_outb(device, 0x1004);
+               
+               /* poll for transaction completion */
+               byte = __builtin_inb(0x10);
+               while(byte == 0) {
+                       byte = __builtin_inb(0x10);
+               }
+       }
+}
diff --git a/util/romcc/tests/simple_test62.c b/util/romcc/tests/simple_test62.c
new file mode 100644 (file)
index 0000000..8fed660
--- /dev/null
@@ -0,0 +1,7 @@
+static const int foo = 1;
+
+static void main(void)
+{
+       int x;
+       x = foo;
+}
diff --git a/util/romcc/tests/simple_test63.c b/util/romcc/tests/simple_test63.c
new file mode 100644 (file)
index 0000000..b7df080
--- /dev/null
@@ -0,0 +1,8 @@
+static const int foo[] = { 1, 2 };
+
+static void main(void)
+{
+       int x, y;
+       x = foo[0];
+       y = foo[1];
+}
diff --git a/util/romcc/tests/simple_test64.c b/util/romcc/tests/simple_test64.c
new file mode 100644 (file)
index 0000000..389b1c1
--- /dev/null
@@ -0,0 +1,12 @@
+static void main(void)
+{
+       static const int foo = 2;
+       switch(foo) {
+       case 1:
+               break;
+       case 2:
+               break;
+       default:
+               break;
+       }
+}
diff --git a/util/romcc/tests/simple_test65.c b/util/romcc/tests/simple_test65.c
new file mode 100644 (file)
index 0000000..642882c
--- /dev/null
@@ -0,0 +1,10 @@
+enum tag {
+       X=1,
+       Y=2,
+};
+static void main(void)
+{
+       enum tag foo;
+       foo = Y;
+       
+}
diff --git a/util/romcc/tests/simple_test66.c b/util/romcc/tests/simple_test66.c
new file mode 100644 (file)
index 0000000..5857855
--- /dev/null
@@ -0,0 +1,25 @@
+typedef unsigned char uint8_t;
+static unsigned int generate_row(uint8_t row, uint8_t maxnodes)
+{
+        
+       unsigned int ret=0x00010101;  
+       static const unsigned int rows_2p[2][2] = {
+               { 0x00050101, 0x00010404 },
+               { 0x00010404, 0x00050101 }
+       };
+       if(maxnodes>2) {
+               maxnodes=2;
+       }
+       if (row < maxnodes) {
+               ret=rows_2p[0][row];
+       }
+       return ret;
+}
+
+static void setup_node(void)
+{
+       unsigned char row;
+       for(row=0; row< 2; row++) {
+               __builtin_outl(generate_row(row, 2), 0x1234);
+       }
+}
diff --git a/util/romcc/tests/simple_test67.c b/util/romcc/tests/simple_test67.c
new file mode 100644 (file)
index 0000000..3bfdc5a
--- /dev/null
@@ -0,0 +1,24 @@
+static void main(void)
+{
+       unsigned int dch, dcl;
+/* HERE I AM  async_lat */
+       unsigned async_lat;
+       int dimms;
+       dimms = 1;
+       async_lat = 0;
+       dch = 0x1234;
+       dcl = __builtin_inl(0x5678);
+       if (!(dcl & (1 << 8))) {
+               if (dimms == 4) {
+                       async_lat = 9;
+               } 
+               else {
+                       async_lat = 8;
+               }
+       }
+       else {
+               async_lat = 6;
+       }
+       dch |= async_lat;
+       __builtin_outl(dch, 0x9abc);
+}
diff --git a/util/romcc/tests/simple_test68.c b/util/romcc/tests/simple_test68.c
new file mode 100644 (file)
index 0000000..dd29658
--- /dev/null
@@ -0,0 +1,21 @@
+static void main(void)
+{
+       static const int cpu[] = { 0, 1, 2, 3 };
+       int i;
+       for(i = 0; i < sizeof(cpu)/sizeof(cpu[0]); i++) {
+               static const unsigned int register_values[] = {
+                       0x0000c144, 0x0000f8f8, 0x00000000,
+                       0x0000c14C, 0x0000f8f8, 0x00000001,
+                       0x0000c154, 0x0000f8f8, 0x00000002,
+                       0x0000c15C, 0x0000f8f8, 0x00000003,
+                       0x0000c164, 0x0000f8f8, 0x00000004,
+                       0x0000c16C, 0x0000f8f8, 0x00000005,
+                       0x0000c174, 0x0000f8f8, 0x00000006,
+                       0x0000c17C, 0x0000f8f8, 0x00000007,
+               };
+               int j;
+               int max = sizeof(register_values)/sizeof(register_values[0]);
+               for(j = 0; j < max; j += 3) {
+               }
+       }
+}