Index: trunk/Chameleon.xcodeproj/project.pbxproj =================================================================== --- trunk/Chameleon.xcodeproj/project.pbxproj (revision 225) +++ trunk/Chameleon.xcodeproj/project.pbxproj (revision 226) @@ -7,16 +7,19 @@ objects = { /* Begin PBXFileReference section */ - B0056CD611F3868000754B65 /* boot */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot; sourceTree = ""; }; + 0172D0DC11FB66820030222E /* dram_controllers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dram_controllers.h; sourceTree = ""; }; + 0172D0DD11FB66820030222E /* dram_controllers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dram_controllers.c; sourceTree = ""; }; + 019DFBAF11FB94090013E8CC /* MEMTEST86_LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MEMTEST86_LICENSE; sourceTree = ""; }; + B0056CD611F3868000754B65 /* boot */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot; sourceTree = ""; }; B0056CD711F3868000754B65 /* boot.sys */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.preload"; path = boot.sys; sourceTree = ""; }; - B0056CD811F3868000754B65 /* boot0 */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot0; sourceTree = ""; }; - B0056CD911F3868000754B65 /* boot0hfs */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot0hfs; sourceTree = ""; }; - B0056CDA11F3868000754B65 /* boot1f32 */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot1f32; sourceTree = ""; }; - B0056CDB11F3868000754B65 /* boot1h */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot1h; sourceTree = ""; }; - B0056CDC11F3868000754B65 /* boot1he */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot1he; sourceTree = ""; }; - B0056CDD11F3868000754B65 /* boot1hp */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot1hp; sourceTree = ""; }; - B0056CDE11F3868000754B65 /* cdboot */ = {isa = PBXFileReference; lastKnownFileType = file; path = cdboot; sourceTree = ""; }; - B0056CDF11F3868000754B65 /* chain0 */ = {isa = PBXFileReference; lastKnownFileType = file; path = chain0; sourceTree = ""; }; + B0056CD811F3868000754B65 /* boot0 */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot0; sourceTree = ""; }; + B0056CD911F3868000754B65 /* boot0hfs */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot0hfs; sourceTree = ""; }; + B0056CDA11F3868000754B65 /* boot1f32 */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot1f32; sourceTree = ""; }; + B0056CDB11F3868000754B65 /* boot1h */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot1h; sourceTree = ""; }; + B0056CDC11F3868000754B65 /* boot1he */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot1he; sourceTree = ""; }; + B0056CDD11F3868000754B65 /* boot1hp */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot1hp; sourceTree = ""; }; + B0056CDE11F3868000754B65 /* cdboot */ = {isa = PBXFileReference; lastKnownFileType = text; path = cdboot; sourceTree = ""; }; + B0056CDF11F3868000754B65 /* chain0 */ = {isa = PBXFileReference; lastKnownFileType = text; path = chain0; sourceTree = ""; }; B0056CE011F3868000754B65 /* embedded.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = embedded.h; sourceTree = ""; }; B0056CE111F3868000754B65 /* libsa.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsa.a; sourceTree = ""; }; B0056CE211F3868000754B65 /* libsaio.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsaio.a; sourceTree = ""; }; @@ -313,6 +316,7 @@ B0056D8011F3868000754B65 /* coding_standards.txt */, B0056D8111F3868000754B65 /* CHANGES */, B0056D8211F3868000754B65 /* APPLE_LICENSE */, + 019DFBAF11FB94090013E8CC /* MEMTEST86_LICENSE */, ); name = Chameleon; sourceTree = ""; @@ -491,6 +495,8 @@ B0056D3911F3868000754B65 /* device_tree.c */, B0056D3A11F3868000754B65 /* device_tree.h */, B0056D3B11F3868000754B65 /* disk.c */, + 0172D0DC11FB66820030222E /* dram_controllers.h */, + 0172D0DD11FB66820030222E /* dram_controllers.c */, B0056D3C11F3868000754B65 /* efi.h */, B0056D3D11F3868000754B65 /* ext2fs.c */, B0056D3E11F3868000754B65 /* ext2fs.h */, Index: trunk/i386/libsaio/spd.c =================================================================== --- trunk/i386/libsaio/spd.c (revision 225) +++ trunk/i386/libsaio/spd.c (revision 226) @@ -300,7 +300,22 @@ // determine spd speed speed = getDDRspeedMhz(slot->spd); - if (slot->FrequencyFrequency = speed; // should test the mem controller to get potential overclocking info ? + if (slot->FrequencyFrequency = speed; + + // pci memory controller if available, is more reliable + if (Platform.RAM.Frequency > 0) { + uint32_t freq = (uint32_t)Platform.RAM.Frequency / 500000; + // now round off special cases + uint32_t fmod100 = freq %100; + switch(fmod100) { + case 32: freq++; break; + case 65: freq++; break; + case 98: freq+=2;break; + case 99: freq++; break; + } + slot->Frequency = freq; + } + printf("Slot: %d Type %d %dMB (%s) %dMHz Vendor=%s\n PartNo=%s SerialNo=%s\n", i, (int)slot->Type, @@ -374,7 +389,5 @@ void scan_spd(PlatformInfo_t *p) { - printf("\n--> Start of mem detect:\n"); find_and_read_smbus_controller(root_pci_dev); - printf("\n<-- End of mem detect.\n"); } Index: trunk/i386/libsaio/Makefile =================================================================== --- trunk/i386/libsaio/Makefile (revision 225) +++ trunk/i386/libsaio/Makefile (revision 226) @@ -41,7 +41,7 @@ xml.o ntfs.o msdos.o md5c.o device_tree.o \ cpu.o platform.o acpi_patcher.o \ smbios_patcher.o fake_efi.o ext2fs.o \ - hpet.o spd.o usb.o pci_setup.o \ + hpet.o dram_controllers.o spd.o usb.o pci_setup.o \ device_inject.o nvidia.o ati.o pci_root.o \ convert.o mem.o aml_generator.o Index: trunk/i386/libsaio/dram_controllers.c =================================================================== --- trunk/i386/libsaio/dram_controllers.c (revision 0) +++ trunk/i386/libsaio/dram_controllers.c (revision 226) @@ -0,0 +1,582 @@ +/* + * dram controller access and scan from the pci host controller + * Integrated and adapted for chameleon 2.0 RC5 by Rekursor from original : + * + * memtest86 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady, cbrady@sgi.com + * ---------------------------------------------------- + * MemTest86+ V4.00 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + */ + +#include "libsaio.h" +#include "bootstruct.h" +#include "pci.h" +#include "platform.h" +#include "dram_controllers.h" + +#ifndef DEBUG_DRAM +#define DEBUG_DRAM 0 +#endif + +#if DEBUG_DRAM +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + +/* + * Initialise memory controller functions + */ + +// Setup P35 Memory Controller +static void setup_p35(pci_dt_t *dram_dev) +{ + uint32_t dev0; + + // Activate MMR I/O + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + if (!(dev0 & 0x1)) + pci_config_write8(dram_dev->dev.addr, 0x48, (dev0 | 1)); +} + +int nhm_bus = 0x3F; + +// Setup Nehalem Integrated Memory Controller +static void setup_nhm(pci_dt_t *dram_dev) +{ + static long possible_nhm_bus[] = {0xFF, 0x7F, 0x3F}; + unsigned long did, vid; + int i; + + // Nehalem supports Scrubbing + // First, locate the PCI bus where the MCH is located + for(i = 0; i < sizeof(possible_nhm_bus); i++) + { + vid = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x00); + did = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x02); + vid &= 0xFFFF; + did &= 0xFF00; + + if(vid == 0x8086 && did >= 0x2C00) + nhm_bus = possible_nhm_bus[i]; + } +} + +/* + * Retrieve memory controller fsb functions + */ + + +// Get i965 Memory Speed +static void get_fsb_i965(pci_dt_t *dram_dev) +{ + uint32_t dev0, mch_ratio, mch_cfg, mch_fsb; + + long *ptr; + + // Find Ratio + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + dev0 &= 0xFFFFC000; + ptr = (long*)(dev0 + 0xC00); + mch_cfg = *ptr & 0xFFFF; + + mch_ratio = 100000; + + switch (mch_cfg & 7) + { + case 0: mch_fsb = 1066; break; + case 1: mch_fsb = 533; break; + default: + case 2: mch_fsb = 800; break; + case 3: mch_fsb = 667; break; + case 4: mch_fsb = 1333; break; + case 6: mch_fsb = 1600; break; + } + + DBG("mch_fsb %d\n", mch_fsb); + + switch (mch_fsb) + { + case 533: + switch ((mch_cfg >> 4) & 7) + { + case 1: mch_ratio = 200000; break; + case 2: mch_ratio = 250000; break; + case 3: mch_ratio = 300000; break; + } + break; + + default: + case 800: + switch ((mch_cfg >> 4) & 7) + { + case 0: mch_ratio = 100000; break; + case 1: mch_ratio = 125000; break; + case 2: mch_ratio = 166667; break; // 1.666666667 + case 3: mch_ratio = 200000; break; + case 4: mch_ratio = 266667; break; // 2.666666667 + case 5: mch_ratio = 133553; break; // 1.333333333 + } + break; + + case 1066: + switch ((mch_cfg >> 4) & 7) + { + case 1: mch_ratio = 100000; break; + case 2: mch_ratio = 125000; break; + case 3: mch_ratio = 150000; break; + case 4: mch_ratio = 200000; break; + case 5: mch_ratio = 250000; break; + } + break; + + case 1333: + switch ((mch_cfg >> 4) & 7) + { + case 2: mch_ratio = 100000; break; + case 3: mch_ratio = 120000; break; + case 4: mch_ratio = 160000; break; + case 5: mch_ratio = 200000; break; + } + break; + + case 1600: + switch ((mch_cfg >> 4) & 7) + { + case 3: mch_ratio = 100000; break; + case 4: mch_ratio = 133333; break; // 1.333333333 + case 5: mch_ratio = 150000; break; + case 6: mch_ratio = 200000; break; + } + break; + } + + DBG("mch_ratio %d\n", mch_ratio); + + // Compute RAM Frequency + Platform.RAM.Frequency = (Platform.CPU.FSBFrequency * mch_ratio) / 100000; + + DBG("ram_fsb %d\n", Platform.RAM.Frequency); + +} + +// Get i965m Memory Speed +static void get_fsb_im965(pci_dt_t *dram_dev) +{ + uint32_t dev0, mch_ratio, mch_cfg, mch_fsb; + + long *ptr; + + // Find Ratio + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + dev0 &= 0xFFFFC000; + ptr = (long*)(dev0 + 0xC00); + mch_cfg = *ptr & 0xFFFF; + + mch_ratio = 100000; + + switch (mch_cfg & 7) + { + case 1: mch_fsb = 533; break; + default: + case 2: mch_fsb = 800; break; + case 3: mch_fsb = 667; break; + } + + switch (mch_fsb) + { + case 533: + switch ((mch_cfg >> 4) & 7) + { + case 1: mch_ratio = 125000; break; + case 2: mch_ratio = 150000; break; + case 3: mch_ratio = 200000; break; + } + break; + + case 667: + switch ((mch_cfg >> 4)& 7) + { + case 1: mch_ratio = 100000; break; + case 2: mch_ratio = 120000; break; + case 3: mch_ratio = 160000; break; + case 4: mch_ratio = 200000; break; + case 5: mch_ratio = 240000; break; + } + break; + + default: + case 800: + switch ((mch_cfg >> 4) & 7) + { + case 1: mch_ratio = 83000; break; // 0.833333333 + case 2: mch_ratio = 100000; break; + case 3: mch_ratio = 133333; break; // 1.333333333 + case 4: mch_ratio = 166667; break; // 1.666666667 + case 5: mch_ratio = 200000; break; + } + break; + + } + + // Compute RAM Frequency + Platform.RAM.Frequency = (Platform.CPU.FSBFrequency * mch_ratio) / 100000; +} + + +// Get iCore7 Memory Speed +static void get_fsb_nhm(pci_dt_t *dram_dev) +{ + uint32_t mch_ratio, mc_dimm_clk_ratio; + + // Get the clock ratio + mc_dimm_clk_ratio = pci_config_read16(PCIADDR(nhm_bus, 3, 4), 0x54 ); + mch_ratio = (mc_dimm_clk_ratio & 0x1F); + + // Compute RAM Frequency + Platform.RAM.Frequency = Platform.CPU.FSBFrequency * mch_ratio / 2; +} + +/* + * Retrieve memory controller info functions + */ + +// Get i965 Memory Timings +static void get_timings_i965(pci_dt_t *dram_dev) +{ + // Thanks for CDH optis + uint32_t dev0, c0ckectrl, c1ckectrl, offset; + uint32_t ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, Misc_Register; + + long *ptr; + + // Read MMR Base Address + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + dev0 &= 0xFFFFC000; + + ptr = (long*)(dev0 + 0x260); + c0ckectrl = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + 0x660); + c1ckectrl = *ptr & 0xFFFFFFFF; + + // If DIMM 0 not populated, check DIMM 1 + ((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x400); + + ptr = (long*)(dev0 + offset + 0x29C); + ODT_Control_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x250); + Precharge_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x252); + ACT_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x258); + Read_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x244); + Misc_Register = *ptr & 0xFFFFFFFF; + + // 965 Series only support DDR2 + Platform.RAM.Type = SMB_MEM_TYPE_DDR2; + + // CAS Latency (tCAS) + Platform.RAM.CAS = ((ODT_Control_Register >> 17) & 7) + 3; + + // RAS-To-CAS (tRCD) + Platform.RAM.TRC = (Read_Register >> 16) & 0xF; + + // RAS Precharge (tRP) + Platform.RAM.TRP = (ACT_Register >> 13) & 0xF; + + // RAS Active to precharge (tRAS) + Platform.RAM.RAS = (Precharge_Register >> 11) & 0x1F; + + if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) + Platform.RAM.Channels = SMB_MEM_CHANNEL_DUAL; + else + Platform.RAM.Channels = SMB_MEM_CHANNEL_SINGLE; +} + +// Get im965 Memory Timings +static void get_timings_im965(pci_dt_t *dram_dev) +{ + // Thanks for CDH optis + uint32_t dev0, c0ckectrl, c1ckectrl, offset, ODT_Control_Register, Precharge_Register; + long *ptr; + + // Read MMR Base Address + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + dev0 &= 0xFFFFC000; + + ptr = (long*)(dev0 + 0x1200); + c0ckectrl = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + 0x1300); + c1ckectrl = *ptr & 0xFFFFFFFF; + + // If DIMM 0 not populated, check DIMM 1 + ((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x100); + + ptr = (long*)(dev0 + offset + 0x121C); + ODT_Control_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x1214); + Precharge_Register = *ptr & 0xFFFFFFFF; + + // Series only support DDR2 + Platform.RAM.Type = SMB_MEM_TYPE_DDR2; + + // CAS Latency (tCAS) + Platform.RAM.CAS = ((ODT_Control_Register >> 23) & 7) + 3; + + // RAS-To-CAS (tRCD) + Platform.RAM.TRC = ((Precharge_Register >> 5) & 7) + 2; + + // RAS Precharge (tRP) + Platform.RAM.TRP= (Precharge_Register & 7) + 2; + + // RAS Active to precharge (tRAS) + Platform.RAM.RAS = (Precharge_Register >> 21) & 0x1F; + + if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) + Platform.RAM.Channels = SMB_MEM_CHANNEL_DUAL; + else + Platform.RAM.Channels = SMB_MEM_CHANNEL_SINGLE; +} + +// Get P35 Memory Timings +static void get_timings_p35(pci_dt_t *dram_dev) +{ + // Thanks for CDH optis + unsigned long dev0, Memory_Check, c0ckectrl, c1ckectrl, offset; + unsigned long ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, Misc_Register; + long *ptr; + + //Device_ID = pci_config_read16(dram_dev->dev.addr, 0x02); + //Device_ID &= 0xFFFF; + + // Now, read MMR Base Address + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + dev0 &= 0xFFFFC000; + + ptr = (long*)(dev0 + 0x260); + c0ckectrl = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + 0x660); + c1ckectrl = *ptr & 0xFFFFFFFF; + + // If DIMM 0 not populated, check DIMM 1 + ((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x400); + + ptr = (long*)(dev0 + offset + 0x265); + ODT_Control_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x25D); + Precharge_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x252); + ACT_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x258); + Read_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x244); + Misc_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x1E8); + Memory_Check = *ptr & 0xFFFFFFFF; + + // On P45, check 1A8 + if(dram_dev->device_id > 0x2E00) { + ptr = (long*)(dev0 + offset + 0x1A8); + Memory_Check = *ptr & 0xFFFFFFFF; + Memory_Check >>= 2; + Memory_Check &= 1; + Memory_Check = !Memory_Check; + } else { + ptr = (long*)(dev0 + offset + 0x1E8); + Memory_Check = *ptr & 0xFFFFFFFF; + } + + // Determine DDR-II or DDR-III + if (Memory_Check & 1) + Platform.RAM.Type = SMB_MEM_TYPE_DDR2; + else + Platform.RAM.Type = SMB_MEM_TYPE_DDR3; + + // CAS Latency (tCAS) + if(dram_dev->device_id > 0x2E00) + Platform.RAM.CAS = ((ODT_Control_Register >> 8) & 0x3F) - 6; + else + Platform.RAM.CAS = ((ODT_Control_Register >> 8) & 0x3F) - 9; + + // RAS-To-CAS (tRCD) + Platform.RAM.TRC = (Read_Register >> 17) & 0xF; + + // RAS Precharge (tRP) + Platform.RAM.TRP = (ACT_Register >> 13) & 0xF; + + // RAS Active to precharge (tRAS) + Platform.RAM.RAS = Precharge_Register & 0x3F; + + // Channel configuration + if (((c0ckectrl >> 20) & 0xF) && ((c1ckectrl >> 20) & 0xF)) + Platform.RAM.Channels = SMB_MEM_CHANNEL_DUAL; + else + Platform.RAM.Channels = SMB_MEM_CHANNEL_SINGLE; +} + +// Get Nehalem Memory Timings +static void get_timings_nhm(pci_dt_t *dram_dev) +{ + unsigned long mc_channel_bank_timing, mc_control, mc_channel_mrs_value; + int fvc_bn = 4; + + // Find which channels are populated + mc_control = pci_config_read16(PCIADDR(nhm_bus, 3, 0), 0x48); + mc_control = (mc_control >> 8) & 0x7; + + // DDR-III + Platform.RAM.Type = SMB_MEM_TYPE_DDR3; + + // Get the first valid channel + if(mc_control & 1) + fvc_bn = 4; + else if(mc_control & 2) + fvc_bn = 5; + else if(mc_control & 7) + fvc_bn = 6; + + // Now, detect timings + mc_channel_bank_timing = pci_config_read32(PCIADDR(nhm_bus, fvc_bn, 0), 0x88); + mc_channel_mrs_value = pci_config_read32(PCIADDR(nhm_bus, fvc_bn, 0), 0x70); + + // CAS Latency (tCAS) + Platform.RAM.CAS = ((mc_channel_mrs_value >> 4) & 0xF ) + 4; + + // RAS-To-CAS (tRCD) + Platform.RAM.TRC = (mc_channel_bank_timing >> 9) & 0xF; + + // RAS Precharge (tRP) + Platform.RAM.CAS = (mc_channel_bank_timing >> 4) & 0x1F; + + // RAS Active to precharge (tRAS) + Platform.RAM.TRP = mc_channel_bank_timing & 0xF; + + // Single , Dual or Triple Channels + if (mc_control == 1 || mc_control == 2 || mc_control == 4 ) + Platform.RAM.Channels = SMB_MEM_CHANNEL_SINGLE; + else if (mc_control == 7) + Platform.RAM.Channels = SMB_MEM_CHANNEL_TRIPLE; + else + Platform.RAM.Channels = SMB_MEM_CHANNEL_DUAL; +} + +static struct mem_controller_t dram_controllers[] = { + + // Default unknown chipset + { 0, 0, "", NULL, NULL, NULL }, + + // Intel + { 0x8086, 0x7190, "VMWare", NULL, NULL, NULL }, + + { 0x8086, 0x1A30, "i845", NULL, NULL, NULL }, + + { 0x8086, 0x2970, "i946PL/GZ", setup_p35, get_fsb_i965, get_timings_i965 }, + { 0x8086, 0x2990, "Q963/Q965", setup_p35, get_fsb_i965, get_timings_i965 }, + { 0x8086, 0x29A0, "P965/G965", setup_p35, get_fsb_i965, get_timings_i965 }, + + { 0x8086, 0x2A00, "GM965/GL960", setup_p35, get_fsb_im965, get_timings_im965 }, + { 0x8086, 0x2A10, "GME965/GLE960", setup_p35, get_fsb_im965, get_timings_im965 }, + { 0x8086, 0x2A40, "PM/GM45/47", setup_p35, get_fsb_im965, get_timings_im965 }, + + { 0x8086, 0x29B0, "Q35", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x29C0, "P35/G33", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x29D0, "Q33", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x29E0, "X38/X48", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x2E00, "Eaglelake", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x2E10, "Q45/Q43", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x2E20, "P45/G45", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x2E30, "G41", setup_p35, get_fsb_i965, get_timings_p35 }, + + { 0x8086, 0xD131, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0xD132, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3400, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3401, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3402, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3403, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + +}; + +static const char *memory_device_types[] = +{ + "RAM", /* 00h Undefined */ + "RAM", /* 01h Other */ + "RAM", /* 02h Unknown */ + "DRAM", /* 03h DRAM */ + "EDRAM", /* 04h EDRAM */ + "VRAM", /* 05h VRAM */ + "SRAM", /* 06h SRAM */ + "RAM", /* 07h RAM */ + "ROM", /* 08h ROM */ + "FLASH", /* 09h FLASH */ + "EEPROM", /* 0Ah EEPROM */ + "FEPROM", /* 0Bh FEPROM */ + "EPROM", /* 0Ch EPROM */ + "CDRAM", /* 0Dh CDRAM */ + "3DRAM", /* 0Eh 3DRAM */ + "SDRAM", /* 0Fh SDRAM */ + "SGRAM", /* 10h SGRAM */ + "RDRAM", /* 11h RDRAM */ + "DDR SDRAM", /* 12h DDR */ + "DDR2 SDRAM", /* 13h DDR2 */ + "DDR2 FB-DIMM" /* 14h DDR2 FB-DIMM */ + "", /* 15h RAM (Not Used) */ + "", /* 16h RAM (Not Used) */ + "", /* 17h RAM (Not Used) */ + "DDR3 SDRAM" /* 18h DDR3 (AppleSMBIOS 1.1.1+) */ +}; + +static const char *memory_channel_types[] = +{ + "Unknown", "Single", "Dual", "Triple" +}; + +void scan_dram_controller(pci_dt_t *dram_dev) +{ + int i; + for(i = 1; i < sizeof(dram_controllers) / sizeof(dram_controllers[0]); i++) + if ((dram_controllers[i].vendor == dram_dev->vendor_id) + && (dram_controllers[i].device == dram_dev->device_id)) + { + verbose("%s%s DRAM Controller [%4x:%4x] at %02x:%02x.%x\n", + (dram_dev->vendor_id == 0x8086) ? "Intel " : "" , + dram_controllers[i].name, dram_dev->vendor_id, dram_dev->device_id, + dram_dev->dev.bits.bus, dram_dev->dev.bits.dev, dram_dev->dev.bits.func + ); + + if(dram_controllers[i].initialise != NULL) + dram_controllers[i].initialise(dram_dev); + + if(dram_controllers[i].poll_timings != NULL) + dram_controllers[i].poll_timings(dram_dev); + + if(dram_controllers[i].poll_speed != NULL) + dram_controllers[i].poll_speed(dram_dev); + + printf("%s %d MHz (%d) %s Channel %d-%d-%d-%d\n", + memory_device_types[Platform.RAM.Type], + (uint32_t)Platform.RAM.Frequency / 1000000, + (uint32_t)Platform.RAM.Frequency / 500000, + memory_channel_types[Platform.RAM.Channels], + Platform.RAM.CAS, Platform.RAM.TRC, Platform.RAM.TRP, Platform.RAM.RAS + ); + + } +} Index: trunk/i386/libsaio/dram_controllers.h =================================================================== --- trunk/i386/libsaio/dram_controllers.h (revision 0) +++ trunk/i386/libsaio/dram_controllers.h (revision 226) @@ -0,0 +1,31 @@ +/* + * dram controller access and scan from the pci host controller + * Adapted for chameleon 2.0 RC5 by Rekursor from original : + * + * memtest86 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady, cbrady@sgi.com + * ---------------------------------------------------- + * MemTest86+ V4.00 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + */ + +#ifndef __LIBSAIO_DRAM_CONTROLLERS_H +#define __LIBSAIO_DRAM_CONTROLLERS_H + +#include "libsaio.h" + +void scan_dram_controller(); + +struct mem_controller_t { + uint16_t vendor; + uint16_t device; + char *name; + void (*initialise)(pci_dt_t *dram_dev); + void (*poll_speed)(pci_dt_t *dram_dev); + void (*poll_timings)(pci_dt_t *dram_dev); +}; + +#endif /* !__LIBSAIO_DRAM_CONTROLLERS_H */ Index: trunk/i386/libsaio/platform.c =================================================================== --- trunk/i386/libsaio/platform.c (revision 225) +++ trunk/i386/libsaio/platform.c (revision 226) @@ -12,6 +12,7 @@ #include "cpu.h" #include "mem.h" #include "spd.h" +#include "dram_controllers.h" #ifndef DEBUG_PLATFORM #define DEBUG_PLATFORM 0 @@ -24,6 +25,7 @@ #endif PlatformInfo_t Platform; +pci_dt_t * dram_controller_dev = NULL; /** Return if a CPU feature specified by feature is activated (true) or not (false) */ bool platformCPUFeature(uint32_t feature) @@ -44,8 +46,12 @@ getBoolForKey(kUseMemDetect, &useAutodetection, &bootInfo->bootConfig); if (useAutodetection) { + if (dram_controller_dev!=NULL) { + scan_dram_controller(dram_controller_dev); // Rek: pci dev ram controller direct and fully informative scan ... + } scan_memory(&Platform); // unfortunately still necesary for some comp where spd cant read correct speed scan_spd(&Platform); + getc(); } done = true; } @@ -59,6 +65,5 @@ memset(&Platform, 0, sizeof(Platform)); build_pci_dt(); scan_cpu(&Platform); - // It's working after some changes in strdup - scan_mem(); + //scan_mem(); Rek: called after pci devs init in fake_efi now ... } Index: trunk/i386/libsaio/platform.h =================================================================== --- trunk/i386/libsaio/platform.h (revision 225) +++ trunk/i386/libsaio/platform.h (revision 226) @@ -111,6 +111,15 @@ } CPU; struct RAM { + uint64_t Frequency; // Ram Frequency + uint32_t Divider; // Memory divider + uint8_t CAS; // CAS 1/2/2.5/3/4/5/6/7 + uint8_t TRC; + uint8_t TRP; + uint8_t RAS; + uint8_t Channels; // Channel Configuration Single,Dual or Triple + uint8_t NoSlots; // Maximum no of slots available + uint8_t Type; // Standard SMBIOS v2.5 Memory Type RamSlotInfo_t DIMM[MAX_RAM_SLOTS]; // Information about each slot } RAM; Index: trunk/i386/libsaio/pci_setup.c =================================================================== --- trunk/i386/libsaio/pci_setup.c (revision 225) +++ trunk/i386/libsaio/pci_setup.c (revision 226) @@ -9,6 +9,8 @@ extern void notify_usb_dev(pci_dt_t *pci_dev); extern void force_enable_hpet(pci_dt_t *lpc_dev); +extern pci_dt_t *dram_controller_dev; + void setup_pci_devs(pci_dt_t *pci_dt) { char *devicepath; @@ -27,6 +29,10 @@ switch (current->class_id) { + case PCI_CLASS_BRIDGE_HOST: + dram_controller_dev = current; + break; + case PCI_CLASS_NETWORK_ETHERNET: if (do_eth_devprop) set_eth_builtin(current); Index: trunk/i386/libsaio/fake_efi.c =================================================================== --- trunk/i386/libsaio/fake_efi.c (revision 225) +++ trunk/i386/libsaio/fake_efi.c (revision 226) @@ -506,20 +506,16 @@ fixupEfiSystemTableCRC32(gST); } -static void setupEfiDevices(setup) -{ - setup_pci_devs(root_pci_dev); -} /* Entrypoint from boot.c */ void setupFakeEfi(void) { + // Generate efi device strings + setup_pci_devs(root_pci_dev); + // load smbios.plist file if any setupSmbiosConfigFile(); - // Generate efi device strings - setupEfiDevices(); - // Initialize the base table setupEfiTables(); Index: trunk/MEMTEST86_LICENSE =================================================================== --- trunk/MEMTEST86_LICENSE (revision 0) +++ trunk/MEMTEST86_LICENSE (revision 226) @@ -0,0 +1,32 @@ +dram_controllers.c/h that scans from the pci host controller USES +an adaptation for chameleon 2.0 RC5 from original : + +======================== +memtest86 license notice +======================== + + Released under version 2 of the Gnu Public License. + By Chris Brady, cbrady@sgi.com + ---------------------------------------------------- + MemTest86+ V4.00 Specific code (GPL V2.0) + By Samuel DEMEULEMEESTER, sdemeule@memtest.org + http://www.canardpc.com - http://www.memtest.org + + +============================ +GPL version 2 license notice +============================ + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.