Skip to content
Browse files

New pci mem detection handling oc speed

git-svn-id: http://forge.voodooprojects.org/svn/chameleon/trunk@226 b5af796a-00a8-11df-919b-ffff7a100b7d
  • Loading branch information...
1 parent 27c3b0b commit b6a9b847b38eae59c56588c266e4b6600b885103 rekursor committed
View
24 Chameleon.xcodeproj/project.pbxproj
@@ -7,16 +7,19 @@
objects = {
/* Begin PBXFileReference section */
- B0056CD611F3868000754B65 /* boot */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot; sourceTree = "<group>"; };
+ 0172D0DC11FB66820030222E /* dram_controllers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dram_controllers.h; sourceTree = "<group>"; };
+ 0172D0DD11FB66820030222E /* dram_controllers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dram_controllers.c; sourceTree = "<group>"; };
+ 019DFBAF11FB94090013E8CC /* MEMTEST86_LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MEMTEST86_LICENSE; sourceTree = "<group>"; };
+ B0056CD611F3868000754B65 /* boot */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot; sourceTree = "<group>"; };
B0056CD711F3868000754B65 /* boot.sys */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.preload"; path = boot.sys; sourceTree = "<group>"; };
- B0056CD811F3868000754B65 /* boot0 */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot0; sourceTree = "<group>"; };
- B0056CD911F3868000754B65 /* boot0hfs */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot0hfs; sourceTree = "<group>"; };
- B0056CDA11F3868000754B65 /* boot1f32 */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot1f32; sourceTree = "<group>"; };
- B0056CDB11F3868000754B65 /* boot1h */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot1h; sourceTree = "<group>"; };
- B0056CDC11F3868000754B65 /* boot1he */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot1he; sourceTree = "<group>"; };
- B0056CDD11F3868000754B65 /* boot1hp */ = {isa = PBXFileReference; lastKnownFileType = file; path = boot1hp; sourceTree = "<group>"; };
- B0056CDE11F3868000754B65 /* cdboot */ = {isa = PBXFileReference; lastKnownFileType = file; path = cdboot; sourceTree = "<group>"; };
- B0056CDF11F3868000754B65 /* chain0 */ = {isa = PBXFileReference; lastKnownFileType = file; path = chain0; sourceTree = "<group>"; };
+ B0056CD811F3868000754B65 /* boot0 */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot0; sourceTree = "<group>"; };
+ B0056CD911F3868000754B65 /* boot0hfs */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot0hfs; sourceTree = "<group>"; };
+ B0056CDA11F3868000754B65 /* boot1f32 */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot1f32; sourceTree = "<group>"; };
+ B0056CDB11F3868000754B65 /* boot1h */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot1h; sourceTree = "<group>"; };
+ B0056CDC11F3868000754B65 /* boot1he */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot1he; sourceTree = "<group>"; };
+ B0056CDD11F3868000754B65 /* boot1hp */ = {isa = PBXFileReference; lastKnownFileType = text; path = boot1hp; sourceTree = "<group>"; };
+ B0056CDE11F3868000754B65 /* cdboot */ = {isa = PBXFileReference; lastKnownFileType = text; path = cdboot; sourceTree = "<group>"; };
+ B0056CDF11F3868000754B65 /* chain0 */ = {isa = PBXFileReference; lastKnownFileType = text; path = chain0; sourceTree = "<group>"; };
B0056CE011F3868000754B65 /* embedded.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = embedded.h; sourceTree = "<group>"; };
B0056CE111F3868000754B65 /* libsa.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsa.a; sourceTree = "<group>"; };
B0056CE211F3868000754B65 /* libsaio.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsaio.a; sourceTree = "<group>"; };
@@ -313,6 +316,7 @@
B0056D8011F3868000754B65 /* coding_standards.txt */,
B0056D8111F3868000754B65 /* CHANGES */,
B0056D8211F3868000754B65 /* APPLE_LICENSE */,
+ 019DFBAF11FB94090013E8CC /* MEMTEST86_LICENSE */,
);
name = Chameleon;
sourceTree = "<group>";
@@ -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 */,
View
32 MEMTEST86_LICENSE
@@ -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.
View
2 i386/libsaio/Makefile
@@ -41,7 +41,7 @@ SAIO_OBJS = table.o asm.o bios.o biosfn.o \
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
View
582 i386/libsaio/dram_controllers.c
@@ -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
+ );
+
+ }
+}
View
31 i386/libsaio/dram_controllers.h
@@ -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 */
View
10 i386/libsaio/fake_efi.c
@@ -506,20 +506,16 @@ static void setupEfiConfigurationTable()
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();
View
6 i386/libsaio/pci_setup.c
@@ -9,6 +9,8 @@ extern void set_eth_builtin(pci_dt_t *eth_dev);
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 @@ void setup_pci_devs(pci_dt_t *pci_dt)
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);
View
9 i386/libsaio/platform.c
@@ -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 @@ void scan_mem() {
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 @@ void scan_platform(void)
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 ...
}
View
9 i386/libsaio/platform.h
@@ -111,6 +111,15 @@ typedef struct _PlatformInfo_t {
} 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;
View
19 i386/libsaio/spd.c
@@ -300,7 +300,22 @@ static void read_smb_intel(pci_dt_t *smbus_dev)
// determine spd speed
speed = getDDRspeedMhz(slot->spd);
- if (slot->Frequency<speed) slot->Frequency = speed; // should test the mem controller to get potential overclocking info ?
+ if (slot->Frequency<speed) slot->Frequency = 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 @@ bool find_and_read_smbus_controller(pci_dt_t* pci_dt)
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");
}

0 comments on commit b6a9b84

Please sign in to comment.
Something went wrong with that request. Please try again.