Index: branches/azimutz/Chazi/i386/libsaio/spd.c =================================================================== --- branches/azimutz/Chazi/i386/libsaio/spd.c (revision 525) +++ branches/azimutz/Chazi/i386/libsaio/spd.c (revision 526) @@ -1,394 +0,0 @@ -/* - * spd.c - serial presence detect memory information - * - * Originally restored from pcefi10.5 - * Dynamic mem detection original impl. by Rekursor - * System profiler fix and other fixes by Mozodojo. - */ - -//#include "libsaio.h" - included on the header. -//#include "saio_internal.h" - included on bootstruct.h -#include "bootstruct.h" -#include "pci.h" -#include "platform.h" -#include "spd.h" -#include "memvendors.h" - -#ifndef DEBUG_SPD -#define DEBUG_SPD 0 -#endif - -#if DEBUG_SPD -#define DBG(x...) printf(x) -#else -#define DBG(x...) -#endif - -static const char *spd_memory_types[] = -{ - "RAM", /* 00h Undefined */ - "FPM", /* 01h FPM */ - "EDO", /* 02h EDO */ - "", /* 03h PIPELINE NIBBLE */ - "SDRAM", /* 04h SDRAM */ - "", /* 05h MULTIPLEXED ROM */ - "DDR SGRAM", /* 06h SGRAM DDR */ - "DDR SDRAM", /* 07h SDRAM DDR */ - "DDR2 SDRAM", /* 08h SDRAM DDR 2 */ - "", /* 09h Undefined */ - "", /* 0Ah Undefined */ - "DDR3 SDRAM" /* 0Bh SDRAM DDR 3 */ -}; - -#define UNKNOWN_MEM_TYPE 2 -static uint8_t spd_mem_to_smbios[] = -{ - UNKNOWN_MEM_TYPE, /* 00h Undefined */ - UNKNOWN_MEM_TYPE, /* 01h FPM */ - UNKNOWN_MEM_TYPE, /* 02h EDO */ - UNKNOWN_MEM_TYPE, /* 03h PIPELINE NIBBLE */ - SMB_MEM_TYPE_SDRAM, /* 04h SDRAM */ - SMB_MEM_TYPE_ROM, /* 05h MULTIPLEXED ROM */ - SMB_MEM_TYPE_SGRAM, /* 06h SGRAM DDR */ - SMB_MEM_TYPE_DDR, /* 07h SDRAM DDR */ - SMB_MEM_TYPE_DDR2, /* 08h SDRAM DDR 2 */ - UNKNOWN_MEM_TYPE, /* 09h Undefined */ - UNKNOWN_MEM_TYPE, /* 0Ah Undefined */ - SMB_MEM_TYPE_DDR3 /* 0Bh SDRAM DDR 3 */ -}; -#define SPD_TO_SMBIOS_SIZE (sizeof(spd_mem_to_smbios)/sizeof(uint8_t)) - -#define rdtsc(low,high) \ -__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) - -#define SMBHSTSTS 0 -#define SMBHSTCNT 2 -#define SMBHSTCMD 3 -#define SMBHSTADD 4 -#define SMBHSTDAT 5 -#define SBMBLKDAT 7 - -/** Read one byte from the intel i2c, used for reading SPD on intel chipsets only. */ -unsigned char smb_read_byte_intel(uint32_t base, uint8_t adr, uint8_t cmd) -{ - int l1, h1, l2, h2; - unsigned long long t; - - outb(base + SMBHSTSTS, 0x1f); // reset SMBus Controller - outb(base + SMBHSTDAT, 0xff); - - while( inb(base + SMBHSTSTS) & 0x01); // wait until ready - - outb(base + SMBHSTCMD, cmd); - outb(base + SMBHSTADD, (adr << 1) | 0x01 ); - outb(base + SMBHSTCNT, 0x48 ); - - rdtsc(l1, h1); - - while (!( inb(base + SMBHSTSTS) & 0x02)) // wait til command finished - { - rdtsc(l2, h2); - t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / (Platform.CPU.TSCFrequency / 100); - if (t > 5) - break; // break after 5ms - } - return inb(base + SMBHSTDAT); -} - -/* SPD i2c read optimization: prefetch only what we need, read non prefetcheable bytes on the fly */ -#define READ_SPD(spd, base, slot, x) spd[x] = smb_read_byte_intel(base, 0x50 + slot, x) - -int spd_indexes[] = { - SPD_MEMORY_TYPE, - SPD_DDR3_MEMORY_BANK, - SPD_DDR3_MEMORY_CODE, - SPD_NUM_ROWS, - SPD_NUM_COLUMNS, - SPD_NUM_DIMM_BANKS, - SPD_NUM_BANKS_PER_SDRAM, - 4,7,8,9,12,64, /* TODO: give names to these values */ - 95,96,97,98, 122,123,124,125 /* UIS */ -}; -#define SPD_INDEXES_SIZE (sizeof(spd_indexes) / sizeof(int)) - -/** Read from spd *used* values only*/ -static void init_spd(char * spd, uint32_t base, int slot) -{ - int i; - for (i=0; i< SPD_INDEXES_SIZE; i++) { - READ_SPD(spd, base, slot, spd_indexes[i]); - } -} - -/** Get Vendor Name from spd, 2 cases handled DDR3 and DDR2, - have different formats, always return a valid ptr.*/ -const char * getVendorName(RamSlotInfo_t* slot, uint32_t base, int slot_num) -{ - uint8_t bank = 0; - uint8_t code = 0; - int i = 0; - uint8_t * spd = (uint8_t *) slot->spd; - - if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) { // DDR3 - bank = (spd[SPD_DDR3_MEMORY_BANK] & 0x07f); // constructors like Patriot use b7=1 - code = spd[SPD_DDR3_MEMORY_CODE]; - for (i=0; i < VEN_MAP_SIZE; i++) - if (bank==vendorMap[i].bank && code==vendorMap[i].code) - return vendorMap[i].name; - } - else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) { - if(spd[64]==0x7f) { - for (i=64; i<72 && spd[i]==0x7f;i++) { - bank++; - READ_SPD(spd, base, slot_num,i+1); // prefetch next spd byte to read for next loop - } - READ_SPD(spd, base, slot_num,i); - code = spd[i]; - } else { - code = spd[64]; - bank = 0; - } - for (i=0; i < VEN_MAP_SIZE; i++) - if (bank==vendorMap[i].bank && code==vendorMap[i].code) - return vendorMap[i].name; - } - /* OK there is no vendor id here lets try to match the partnum if it exists */ - if (strstr(slot->PartNo,"GU332") == slot->PartNo) // Unifosa fingerprint - return "Unifosa"; - return "NoName"; -} - -/** Get Default Memory Module Speed (no overclocking handled) */ -int getDDRspeedMhz(const char * spd) -{ - if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) { - switch(spd[12]) { - case 0x0f: - return 1066; - case 0x0c: - return 1333; - case 0x0a: - return 1600; - case 0x14: - default: - return 800; - } - } - else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) { - switch(spd[9]) { - case 0x50: - return 400; - case 0x3d: - return 533; - case 0x30: - return 667; - case 0x25: - default: - return 800; - } - } - return 800; // default freq for unknown types -} - -#define SMST(a) ((uint8_t)((spd[a] & 0xf0) >> 4)) -#define SLST(a) ((uint8_t)(spd[a] & 0x0f)) - -/** Get DDR3 or DDR2 serial number, 0 most of the times, always return a valid ptr */ -const char *getDDRSerial(const char* spd) -{ - static char asciiSerial[16]; - - if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) // DDR3 - { - sprintf(asciiSerial, "%X%X%X%X%X%X%X%X", SMST(122) /*& 0x7*/, SLST(122), SMST(123), SLST(123), SMST(124), SLST(124), SMST(125), SLST(125)); - } - else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) // DDR2 or DDR - { - sprintf(asciiSerial, "%X%X%X%X%X%X%X%X", SMST(95) /*& 0x7*/, SLST(95), SMST(96), SLST(96), SMST(97), SLST(97), SMST(98), SLST(98)); - } - - return strdup(asciiSerial); -} - -/** Get DDR3 or DDR2 Part Number, always return a valid ptr */ -const char * getDDRPartNum(char* spd, uint32_t base, int slot) -{ - static char asciiPartNo[32]; - int i, start=0, index = 0; - - if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) { - start = 128; - } - else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) { - start = 73; - } - - // Check that the spd part name is zero terminated and that it is ascii: - bzero(asciiPartNo, sizeof(asciiPartNo)); - char c; - for (i=start; i < start + sizeof(asciiPartNo); i++) { - READ_SPD(spd, base, slot, i); // only read once the corresponding model part (ddr3 or ddr2) - c = spd[i]; - if (isalpha(c) || isdigit(c) || ispunct(c)) // It seems that System Profiler likes only letters and digits... - asciiPartNo[index++] = c; - if (isspace(c)) //Azi: this is the way that works properly for me!! The other gives me extra characters. - break; - } - - return strdup(asciiPartNo); - return NULL; -} - -int mapping []= {0,2,1,3,4,6,5,7,8,10,9,11}; - - -/** Read from smbus the SPD content and interpret it for detecting memory attributes */ -static void read_smb_intel(pci_dt_t *smbus_dev) -{ - int i, speed; - uint8_t spd_size, spd_type; - uint32_t base; - bool dump = false; - RamSlotInfo_t* slot; - - base = pci_config_read16(smbus_dev->dev.addr, 0x20) & 0xFFFE; - DBG("Scanning smbus_dev <%04x, %04x> ...\n",smbus_dev->vendor_id, smbus_dev->device_id); - - getBoolForKey("DumpSPD", &dump, &bootInfo->bootConfig); - bool fullBanks = // needed at least for laptops - Platform.DMI.MemoryModules == Platform.DMI.MaxMemorySlots; - // Search MAX_RAM_SLOTS slots - char spdbuf[256]; - - for (i = 0; i < MAX_RAM_SLOTS; i++){ - slot = &Platform.RAM.DIMM[i]; - spd_size = smb_read_byte_intel(base, 0x50 + i, 0); - // Check spd is present - if (spd_size && (spd_size != 0xff) ) { - - slot->spd = spdbuf; - slot->InUse = true; - - bzero(slot->spd, spd_size); - - // Copy spd data into buffer - - //for (x = 0; x < spd_size; x++) slot->spd[x] = smb_read_byte_intel(base, 0x50 + i, x); - init_spd(slot->spd, base, i); - - switch (slot->spd[SPD_MEMORY_TYPE]) { - case SPD_MEMORY_TYPE_SDRAM_DDR2: - - slot->ModuleSize = ((1 << (slot->spd[SPD_NUM_ROWS] & 0x0f) + (slot->spd[SPD_NUM_COLUMNS] & 0x0f) - 17) * - ((slot->spd[SPD_NUM_DIMM_BANKS] & 0x7) + 1) * slot->spd[SPD_NUM_BANKS_PER_SDRAM]); - break; - - case SPD_MEMORY_TYPE_SDRAM_DDR3: - - slot->ModuleSize = ((slot->spd[4] & 0x0f) + 28 ) + ((slot->spd[8] & 0x7) + 3 ); - slot->ModuleSize -= (slot->spd[7] & 0x7) + 25; - slot->ModuleSize = ((1 << slot->ModuleSize) * (((slot->spd[7] >> 3) & 0x1f) + 1)); - - break; - } - - spd_type = (slot->spd[SPD_MEMORY_TYPE] < ((char) 12) ? slot->spd[SPD_MEMORY_TYPE] : 0); - slot->Type = spd_mem_to_smbios[spd_type]; - slot->PartNo = getDDRPartNum(slot->spd, base, i); - slot->Vendor = getVendorName(slot, base, i); - slot->SerialNo = getDDRSerial(slot->spd); - - // determine spd speed - speed = getDDRspeedMhz(slot->spd); - 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 1: freq--; break; - case 32: freq++; break; - case 65: freq++; break; - case 98: freq+=2;break; - case 99: freq++; break; - } - slot->Frequency = freq; - } - - verbose("Slot: %d Type %d %dMB (%s) %dMHz Vendor=%s\n PartNo=%s SerialNo=%s\n", - i, - (int)slot->Type, - slot->ModuleSize, - spd_memory_types[spd_type], - slot->Frequency, - slot->Vendor, - slot->PartNo, - slot->SerialNo); - if(DEBUG_SPD) { - dumpPhysAddr("spd content: ",slot->spd, spd_size); - getc(); - } - } - - // laptops sometimes show slot 0 and 2 with slot 1 empty when only 2 slots are presents so: - Platform.DMI.DIMM[i]= - i>0 && Platform.RAM.DIMM[1].InUse==false && fullBanks && Platform.DMI.MaxMemorySlots==2 ? - mapping[i] : i; // for laptops case, mapping setup would need to be more generic than this - - slot->spd = NULL; - - } // for -} - -static struct smbus_controllers_t smbus_controllers[] = { - - {0x8086, 0x269B, "ESB2", read_smb_intel }, - {0x8086, 0x25A4, "6300ESB", read_smb_intel }, - {0x8086, 0x24C3, "ICH4", read_smb_intel }, - {0x8086, 0x24D3, "ICH5", read_smb_intel }, - {0x8086, 0x266A, "ICH6", read_smb_intel }, - {0x8086, 0x27DA, "ICH7", read_smb_intel }, - {0x8086, 0x283E, "ICH8", read_smb_intel }, - {0x8086, 0x2930, "ICH9", read_smb_intel }, - {0x8086, 0x3A30, "ICH10R", read_smb_intel }, - {0x8086, 0x3A60, "ICH10B", read_smb_intel }, - {0x8086, 0x3B30, "P55", read_smb_intel }, - {0x8086, 0x5032, "EP80579", read_smb_intel } - -}; - -// initial call : pci_dt = root_pci_dev; -// find_and_read_smbus_controller(root_pci_dev); -bool find_and_read_smbus_controller(pci_dt_t* pci_dt) -{ - pci_dt_t *current = pci_dt; - int i; - - while (current) { -#if 0 - printf("%02x:%02x.%x [%04x] [%04x:%04x] :: %s\n", - current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func, - current->class_id, current->vendor_id, current->device_id, - get_pci_dev_path(current)); -#endif - for ( i = 0; i < sizeof(smbus_controllers) / sizeof(smbus_controllers[0]); i++ ) - { - if (current->vendor_id == smbus_controllers[i].vendor && - current->device_id == smbus_controllers[i].device) - { - smbus_controllers[i].read_smb(current); // read smb - return true; - } - } - find_and_read_smbus_controller(current->children); - current = current->next; - } - return false; // not found -} - -void scan_spd(PlatformInfo_t *p) -{ - find_and_read_smbus_controller(root_pci_dev); -} Index: branches/azimutz/Chazi/i386/libsaio/spd.h =================================================================== --- branches/azimutz/Chazi/i386/libsaio/spd.h (revision 525) +++ branches/azimutz/Chazi/i386/libsaio/spd.h (revision 526) @@ -1,161 +0,0 @@ -/* - * Copyright 2010 AsereBLN. All rights reserved. - * - * spd.h - */ - -#ifndef __LIBSAIO_SPD_H -#define __LIBSAIO_SPD_H - -//#include "libsaio.h" -#include "platform.h" -#include "io_inline.h" - -void scan_spd(PlatformInfo_t *p); - -struct smbus_controllers_t { - uint32_t vendor; - uint32_t device; - char *name; - void (*read_smb)(pci_dt_t *smbus_dev); -}; - - -/* - * Serial Presence Detect (SPD) data stored on SDRAM modules. - * - * Datasheet: - * - Name: PC SDRAM Serial Presence Detect (SPD) Specification - * Revision 1.2A, December, 1997 - * - PDF: http://www.intel.com/design/chipsets/memory/spdsd12a.pdf - * - * Datasheet (alternative): - * - Name: SERIAL PRESENCE DETECT STANDARD, General Standard - * JEDEC Standard No. 21-C - * - PDF: http://www.jedec.org/download/search/4_01_02_00R9.PDF - */ - - -/* Byte numbers. */ -#define SPD_NUM_MANUFACTURER_BYTES 0 /* Number of bytes used by module manufacturer */ -#define SPD_TOTAL_SPD_MEMORY_SIZE 1 /* Total SPD memory size */ -#define SPD_MEMORY_TYPE 2 /* (Fundamental) memory type */ -#define SPD_NUM_ROWS 3 /* Number of row address bits */ -#define SPD_NUM_COLUMNS 4 /* Number of column address bits */ -#define SPD_NUM_DIMM_BANKS 5 /* Number of module rows (banks) */ -#define SPD_MODULE_DATA_WIDTH_LSB 6 /* Module data width (LSB) */ -#define SPD_MODULE_DATA_WIDTH_MSB 7 /* Module data width (MSB) */ -#define SPD_MODULE_VOLTAGE 8 /* Module interface signal levels */ -#define SPD_MIN_CYCLE_TIME_AT_CAS_MAX 9 /* SDRAM cycle time (highest CAS latency), RAS access time (tRAC) */ -#define SPD_ACCESS_TIME_FROM_CLOCK 10 /* SDRAM access time from clock (highest CAS latency), CAS access time (Tac, tCAC) */ -#define SPD_DIMM_CONFIG_TYPE 11 /* Module configuration type */ -#define SPD_REFRESH 12 /* Refresh rate/type */ -#define SPD_PRIMARY_SDRAM_WIDTH 13 /* SDRAM width (primary SDRAM) */ -#define SPD_ERROR_CHECKING_SDRAM_WIDTH 14 /* Error checking SDRAM (data) width */ -#define SPD_MIN_CLOCK_DELAY_B2B_RAND_COLUMN 15 /* SDRAM device attributes, minimum clock delay for back to back random column */ -#define SPD_SUPPORTED_BURST_LENGTHS 16 /* SDRAM device attributes, burst lengths supported */ -#define SPD_NUM_BANKS_PER_SDRAM 17 /* SDRAM device attributes, number of banks on SDRAM device */ -#define SPD_ACCEPTABLE_CAS_LATENCIES 18 /* SDRAM device attributes, CAS latency */ -#define SPD_CS_LATENCY 19 /* SDRAM device attributes, CS latency */ -#define SPD_WE_LATENCY 20 /* SDRAM device attributes, WE latency */ -#define SPD_MODULE_ATTRIBUTES 21 /* SDRAM module attributes */ -#define SPD_DEVICE_ATTRIBUTES_GENERAL 22 /* SDRAM device attributes, general */ -#define SPD_SDRAM_CYCLE_TIME_2ND 23 /* SDRAM cycle time (2nd highest CAS latency) */ -#define SPD_ACCESS_TIME_FROM_CLOCK_2ND 24 /* SDRAM access from clock (2nd highest CAS latency) */ -#define SPD_SDRAM_CYCLE_TIME_3RD 25 /* SDRAM cycle time (3rd highest CAS latency) */ -#define SPD_ACCESS_TIME_FROM_CLOCK_3RD 26 /* SDRAM access from clock (3rd highest CAS latency) */ -#define SPD_MIN_ROW_PRECHARGE_TIME 27 /* Minimum row precharge time (Trp) */ -#define SPD_MIN_ROWACTIVE_TO_ROWACTIVE 28 /* Minimum row active to row active (Trrd) */ -#define SPD_MIN_RAS_TO_CAS_DELAY 29 /* Minimum RAS to CAS delay (Trcd) */ -#define SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY 30 /* Minimum RAS pulse width (Tras) */ -#define SPD_DENSITY_OF_EACH_ROW_ON_MODULE 31 /* Density of each row on module */ -#define SPD_CMD_SIGNAL_INPUT_SETUP_TIME 32 /* Command and address signal input setup time */ -#define SPD_CMD_SIGNAL_INPUT_HOLD_TIME 33 /* Command and address signal input hold time */ -#define SPD_DATA_SIGNAL_INPUT_SETUP_TIME 34 /* Data signal input setup time */ -#define SPD_DATA_SIGNAL_INPUT_HOLD_TIME 35 /* Data signal input hold time */ -#define SPD_WRITE_RECOVERY_TIME 36 /* Write recovery time (tWR) */ -#define SPD_INT_WRITE_TO_READ_DELAY 37 /* Internal write to read command delay (tWTR) */ -#define SPD_INT_READ_TO_PRECHARGE_DELAY 38 /* Internal read to precharge command delay (tRTP) */ -#define SPD_MEM_ANALYSIS_PROBE_PARAMS 39 /* Memory analysis probe characteristics */ -#define SPD_BYTE_41_42_EXTENSION 40 /* Extension of byte 41 (tRC) and byte 42 (tRFC) */ -#define SPD_MIN_ACT_TO_ACT_AUTO_REFRESH 41 /* Minimum active to active auto refresh (tRCmin) */ -#define SPD_MIN_AUTO_REFRESH_TO_ACT 42 /* Minimum auto refresh to active/auto refresh (tRFC) */ -#define SPD_MAX_DEVICE_CYCLE_TIME 43 /* Maximum device cycle time (tCKmax) */ -#define SPD_MAX_DQS_DQ_SKEW 44 /* Maximum skew between DQS and DQ (tDQSQ) */ -#define SPD_MAX_READ_DATAHOLD_SKEW 45 /* Maximum read data-hold skew factor (tQHS) */ -#define SPD_PLL_RELOCK_TIME 46 /* PLL relock time */ -#define SPD_SPD_DATA_REVISION_CODE 62 /* SPD data revision code */ -#define SPD_CHECKSUM_FOR_BYTES_0_TO_62 63 /* Checksum for bytes 0-62 */ -#define SPD_MANUFACTURER_JEDEC_ID_CODE 64 /* Manufacturer's JEDEC ID code, per EIA/JEP106 (bytes 64-71) */ -#define SPD_MANUFACTURING_LOCATION 72 /* Manufacturing location */ -#define SPD_MANUFACTURER_PART_NUMBER 73 /* Manufacturer's part number, in 6-bit ASCII (bytes 73-90) */ -#define SPD_REVISION_CODE 91 /* Revision code (bytes 91-92) */ -#define SPD_MANUFACTURING_DATE 93 /* Manufacturing date (byte 93: year, byte 94: week) */ -#define SPD_ASSEMBLY_SERIAL_NUMBER 95 /* Assembly serial number (bytes 95-98) */ -#define SPD_MANUFACTURER_SPECIFIC_DATA 99 /* Manufacturer specific data (bytes 99-125) */ -#define SPD_INTEL_SPEC_FOR_FREQUENCY 126 /* Intel specification for frequency */ -#define SPD_INTEL_SPEC_100_MHZ 127 /* Intel specification details for 100MHz support */ -#define SPD_DDR3_MEMORY_BANK 0x75 -#define SPD_DDR3_MEMORY_CODE 0x76 - -/* DRAM specifications use the following naming conventions for SPD locations */ -#define SPD_tRP SPD_MIN_ROW_PRECHARGE_TIME -#define SPD_tRRD SPD_MIN_ROWACTIVE_TO_ROWACTIVE -#define SPD_tRCD SPD_MIN_RAS_TO_CAS_DELAY -#define SPD_tRAS SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY -#define SPD_BANK_DENSITY SPD_DENSITY_OF_EACH_ROW_ON_MODULE -#define SPD_ADDRESS_CMD_HOLD SPD_CMD_SIGNAL_INPUT_HOLD_TIME -#define SPD_tRC 41 /* SDRAM Device Minimum Active to Active/Auto Refresh Time (tRC) */ -#define SPD_tRFC 42 /* SDRAM Device Minimum Auto Refresh to Active/Auto Refresh (tRFC) */ - - -/* SPD_MEMORY_TYPE values. */ -#define SPD_MEMORY_TYPE_FPM_DRAM 1 -#define SPD_MEMORY_TYPE_EDO 2 -#define SPD_MEMORY_TYPE_PIPELINED_NIBBLE 3 -#define SPD_MEMORY_TYPE_SDRAM 4 -#define SPD_MEMORY_TYPE_MULTIPLEXED_ROM 5 -#define SPD_MEMORY_TYPE_SGRAM_DDR 6 -#define SPD_MEMORY_TYPE_SDRAM_DDR 7 -#define SPD_MEMORY_TYPE_SDRAM_DDR2 8 -#define SPD_MEMORY_TYPE_SDRAM_DDR3 0xb - -/* SPD_MODULE_VOLTAGE values. */ -#define SPD_VOLTAGE_TTL 0 /* 5.0 Volt/TTL */ -#define SPD_VOLTAGE_LVTTL 1 /* LVTTL */ -#define SPD_VOLTAGE_HSTL 2 /* HSTL 1.5 */ -#define SPD_VOLTAGE_SSTL3 3 /* SSTL 3.3 */ -#define SPD_VOLTAGE_SSTL2 4 /* SSTL 2.5 */ - -/* SPD_DIMM_CONFIG_TYPE values. */ -#define ERROR_SCHEME_NONE 0 -#define ERROR_SCHEME_PARITY 1 -#define ERROR_SCHEME_ECC 2 - -/* SPD_ACCEPTABLE_CAS_LATENCIES values. */ -// TODO: Check values. -#define SPD_CAS_LATENCY_1_0 0x01 -#define SPD_CAS_LATENCY_1_5 0x02 -#define SPD_CAS_LATENCY_2_0 0x04 -#define SPD_CAS_LATENCY_2_5 0x08 -#define SPD_CAS_LATENCY_3_0 0x10 -#define SPD_CAS_LATENCY_3_5 0x20 -#define SPD_CAS_LATENCY_4_0 0x40 - -#define SPD_CAS_LATENCY_DDR2_3 (1 << 3) -#define SPD_CAS_LATENCY_DDR2_4 (1 << 4) -#define SPD_CAS_LATENCY_DDR2_5 (1 << 5) -#define SPD_CAS_LATENCY_DDR2_6 (1 << 6) - -/* SPD_SUPPORTED_BURST_LENGTHS values. */ -#define SPD_BURST_LENGTH_1 1 -#define SPD_BURST_LENGTH_2 2 -#define SPD_BURST_LENGTH_4 4 -#define SPD_BURST_LENGTH_8 8 -#define SPD_BURST_LENGTH_PAGE (1 << 7) - -/* SPD_MODULE_ATTRIBUTES values. */ -#define MODULE_BUFFERED 1 -#define MODULE_REGISTERED 2 - -#endif /* !__LIBSAIO_SPD_H */ Index: branches/azimutz/Chazi/i386/libsaio/mem.c =================================================================== --- branches/azimutz/Chazi/i386/libsaio/mem.c (revision 525) +++ branches/azimutz/Chazi/i386/libsaio/mem.c (revision 526) @@ -1,141 +0,0 @@ -/* - * Copyright 2010 AsereBLN. All rights reserved. - * - * mem.c - obtain system memory information - */ - -//#include "libsaio.h" - included on pci.h for now. -#include "pci.h" -#include "platform.h" -#include "cpu.h" -#include "mem.h" -#include "smbios_patcher.h" - -#ifndef DEBUG_MEM -#define DEBUG_MEM 0 -#endif - -#if DEBUG_MEM -#define DBG(x...) printf(x) -#else -#define DBG(x...) -#endif - -#define DC(c) (c >= 0x20 && c < 0x7f ? (char) c : '.') -#define STEP 16 - -void dumpPhysAddr(const char * title, void * a, int len) -{ - int i,j; - u_int8_t* ad = (u_int8_t*) a; - char buffer[80]; - char str[16]; - - if(ad==NULL) return; - - printf("%s addr=0x%08x len=%04d\n",title ? title : "Dump of ", a, len); - printf("Ofs-00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F ASCII\n"); - i = (len/STEP)*STEP; - for (j=0; j < i; j+=STEP) - { - printf("%02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", - j, - ad[j], ad[j+1], ad[j+2], ad[j+3] , ad[j+4], ad[j+5], ad[j+6], ad[j+7], - ad[j+8], ad[j+9], ad[j+10], ad[j+11] , ad[j+12], ad[j+13], ad[j+14], ad[j+15], - DC(ad[j]), DC(ad[j+1]), DC(ad[j+2]), DC(ad[j+3]) , DC(ad[j+4]), DC(ad[j+5]), DC(ad[j+6]), DC(ad[j+7]), - DC(ad[j+8]), DC(ad[j+9]), DC(ad[j+10]), DC(ad[j+11]) , DC(ad[j+12]), DC(ad[j+13]), DC(ad[j+14]), DC(ad[j+15]) - ); - } - - if (len%STEP==0) return; - sprintf(buffer,"%02x:", i); - for (j=0; j < STEP; j++) { - if (j<(len%STEP)) - sprintf(str, " %02x", ad[i+j]); - else - strcpy(str, " " ); - strncat(buffer, str, sizeof(buffer)); - } - strncat(buffer," ", sizeof(buffer)); - for (j=0; j < (len%STEP); j++) { - sprintf(str, "%c", DC(ad[i+j])); - strncat(buffer, str, sizeof(buffer)); - } - printf("%s\n",buffer); -} - -void dumpAllTablesOfType(int i) -{ - char title[32]; - struct DMIHeader * dmihdr; - for(dmihdr = FindFirstDmiTableOfType(i, 4); - dmihdr; - dmihdr = FindNextDmiTableOfType(i, 4)) { - sprintf(title,"Table (type %d) :" , i); - dumpPhysAddr(title, dmihdr, dmihdr->length+32); - } -} - -const char * getDMIString(struct DMIHeader * dmihdr, uint8_t strNum) -{ - const char * ret =NULL; - const char * startAddr = (const char *) dmihdr; - const char * limit = NULL; - - if (!dmihdr || dmihdr->length<4 || strNum==0) return NULL; - startAddr += dmihdr->length; - limit = startAddr + 256; - for(; strNum; strNum--) { - if ((*startAddr)==0 && *(startAddr+1)==0) break; - if (*startAddr && strNum<=1) { - ret = startAddr; // current str - break; - } - while(*startAddr && startAddrnumberOfMemoryDevices : 0; - - i = 0; - for(dmihdr = FindFirstDmiTableOfType(17, 4); - dmihdr; - dmihdr = FindNextDmiTableOfType(17, 4) ) { - memDev[i] = (struct DMIMemoryDevice*) dmihdr; - if (memDev[i]->size !=0 ) Platform.DMI.MemoryModules++; - if (memDev[i]->speed>0) Platform.RAM.DIMM[i].Frequency = memDev[i]->speed; // take it here for now but we'll check spd and dmi table 6 as well - i++; - } - // for table 6, we only have a look at the current speed - i = 0; - for(dmihdr = FindFirstDmiTableOfType(6, 4); - dmihdr; - dmihdr = FindNextDmiTableOfType(6, 4) ) { - memInfo[i] = (struct DMIMemoryModuleInfo*) dmihdr; - if (memInfo[i]->currentSpeed > Platform.RAM.DIMM[i].Frequency) - Platform.RAM.DIMM[i].Frequency = memInfo[i]->currentSpeed; // favor real overclocked speed if any - i++; - } -#if 0 - dumpAllTablesOfType(17); - getc(); -#endif -} Index: branches/azimutz/Chazi/i386/libsaio/mem.h =================================================================== --- branches/azimutz/Chazi/i386/libsaio/mem.h (revision 525) +++ branches/azimutz/Chazi/i386/libsaio/mem.h (revision 526) @@ -1,15 +0,0 @@ -/* - * Copyright 2010 AsereBLN. All rights reserved. - * - * mem.h - */ - -#ifndef __LIBSAIO_MEM_H -#define __LIBSAIO_MEM_H - -#include "platform.h" - -extern void scan_memory(PlatformInfo_t *); - - -#endif /* __LIBSAIO_MEM_H */ Index: branches/azimutz/Chazi/i386/libsaio/dram_controllers.c =================================================================== --- branches/azimutz/Chazi/i386/libsaio/dram_controllers.c (revision 525) +++ branches/azimutz/Chazi/i386/libsaio/dram_controllers.c (revision 526) @@ -1,562 +0,0 @@ -/* - * dram controller access and scan from the pci host controller - * Integrated and adapted for chameleon 2.0 RC5 by Rekursor from bs0d work - * original source comes from: - * - * 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" - included on the header. -#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 = 333333; break; // 3.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; - case 6: mch_fsb = 1066; 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 = 83333; 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; - case 1066: - switch ((mch_cfg >> 4)&7) { - case 5: mch_ratio = 150000; break; - case 6: mch_ratio = 200000; 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.TRP = mc_channel_bank_timing & 0xF; - - // RAS Active to precharge (tRAS) - Platform.RAM.RAS = (mc_channel_bank_timing >> 4) & 0x1F; - - // 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 }, - { 0x8086, 0x3404, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, - { 0x8086, 0x3405, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, - { 0x8086, 0x3406, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, - { 0x8086, 0x3407, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, - -}; - -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); - - verbose("Frequency detected: %d MHz (%d) %s Channel %d-%d-%d-%d\n", - (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: branches/azimutz/Chazi/i386/libsaio/dram_controllers.h =================================================================== --- branches/azimutz/Chazi/i386/libsaio/dram_controllers.h (revision 525) +++ branches/azimutz/Chazi/i386/libsaio/dram_controllers.h (revision 526) @@ -1,32 +0,0 @@ -/* - * dram controller access and scan from the pci host controller - * Integrated and adapted for chameleon 2.0 RC5 by Rekursor from bs0d work - * original source comes from: - * - * 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: branches/azimutz/Chazi/i386/libsaio/Makefile =================================================================== --- branches/azimutz/Chazi/i386/libsaio/Makefile (revision 525) +++ branches/azimutz/Chazi/i386/libsaio/Makefile (revision 526) @@ -41,8 +41,8 @@ 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 dram_controllers.o spd.o usb.o pci_setup.o \ - device_inject.o pci_root.o convert.o mem.o aml_generator.o \ + hpet.o usb.o pci_setup.o \ + device_inject.o pci_root.o convert.o aml_generator.o \ nvidia_resolution.o ati_resolution.o gma_resolution.o \ autoresolution.o edid.o Index: branches/azimutz/Chazi/i386/libsaio/platform.c =================================================================== --- branches/azimutz/Chazi/i386/libsaio/platform.c (revision 525) +++ branches/azimutz/Chazi/i386/libsaio/platform.c (revision 526) @@ -10,9 +10,7 @@ #include "pci.h" #include "platform.h" #include "cpu.h" -#include "mem.h" -#include "spd.h" -#include "dram_controllers.h" +#include "modules.h" #ifndef DEBUG_PLATFORM #define DEBUG_PLATFORM 0 @@ -38,21 +36,19 @@ } /** scan mem for memory autodection purpose */ -void scan_mem() { +void scan_mem() +{ static bool done = false; if (done) return; bool useAutodetection = true; getBoolForKey(kUseMemDetectKey, &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); + if (useAutodetection) + { + execute_hook("ScanMemory", NULL, NULL, NULL, NULL); //getc(); - } + } done = true; } Index: branches/azimutz/Chazi/i386/libsaio/pci_setup.c =================================================================== --- branches/azimutz/Chazi/i386/libsaio/pci_setup.c (revision 525) +++ branches/azimutz/Chazi/i386/libsaio/pci_setup.c (revision 526) @@ -12,8 +12,6 @@ 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) { bool do_eth_devprop, do_enable_hpet; @@ -26,22 +24,20 @@ while (current) { + execute_hook("PCIDevice", current, NULL, NULL, NULL); + 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); - break; + break;/* case PCI_CLASS_DISPLAY_VGA: execute_hook(kGraphicsEnablerKey, current, NULL, NULL, NULL); break; - case PCI_CLASS_SERIAL_USB: + */ case PCI_CLASS_SERIAL_USB: notify_usb_dev(current); break; Index: branches/azimutz/Chazi/i386/boot2/modules.c =================================================================== --- branches/azimutz/Chazi/i386/boot2/modules.c (revision 525) +++ branches/azimutz/Chazi/i386/boot2/modules.c (revision 526) @@ -175,8 +175,9 @@ { moduleHook_t* hooks = moduleCallbacks; - while(hooks != NULL && strcmp(name, hooks->name) < 0) + while(hooks != NULL && strcmp(name, hooks->name) != 0) //TOOD: fixme { + //DBG("%s cmp %s = %d\n", name, hooks->name, strcmp(name, hooks->name)); hooks = hooks->next; } Index: branches/azimutz/Chazi/i386/modules/Memory/dram_controllers.h =================================================================== --- branches/azimutz/Chazi/i386/modules/Memory/dram_controllers.h (revision 0) +++ branches/azimutz/Chazi/i386/modules/Memory/dram_controllers.h (revision 526) @@ -0,0 +1,32 @@ +/* + * dram controller access and scan from the pci host controller + * Integrated and adapted for chameleon 2.0 RC5 by Rekursor from bs0d work + * original source comes from: + * + * 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: branches/azimutz/Chazi/i386/modules/Memory/mem.c =================================================================== --- branches/azimutz/Chazi/i386/modules/Memory/mem.c (revision 0) +++ branches/azimutz/Chazi/i386/modules/Memory/mem.c (revision 526) @@ -0,0 +1,141 @@ +/* + * Copyright 2010 AsereBLN. All rights reserved. + * + * mem.c - obtain system memory information + */ + +#include "libsaio.h" +#include "pci.h" +#include "platform.h" +#include "cpu.h" +#include "mem.h" +#include "smbios_patcher.h" + +#ifndef DEBUG_MEM +#define DEBUG_MEM 0 +#endif + +#if DEBUG_MEM +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + +#define DC(c) (c >= 0x20 && c < 0x7f ? (char) c : '.') +#define STEP 16 + +void dumpPhysAddr(const char * title, void * a, int len) +{ + int i,j; + u_int8_t* ad = (u_int8_t*) a; + char buffer[80]; + char str[16]; + + if(ad==NULL) return; + + printf("%s addr=0x%08x len=%04d\n",title ? title : "Dump of ", a, len); + printf("Ofs-00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F ASCII\n"); + i = (len/STEP)*STEP; + for (j=0; j < i; j+=STEP) + { + printf("%02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", + j, + ad[j], ad[j+1], ad[j+2], ad[j+3] , ad[j+4], ad[j+5], ad[j+6], ad[j+7], + ad[j+8], ad[j+9], ad[j+10], ad[j+11] , ad[j+12], ad[j+13], ad[j+14], ad[j+15], + DC(ad[j]), DC(ad[j+1]), DC(ad[j+2]), DC(ad[j+3]) , DC(ad[j+4]), DC(ad[j+5]), DC(ad[j+6]), DC(ad[j+7]), + DC(ad[j+8]), DC(ad[j+9]), DC(ad[j+10]), DC(ad[j+11]) , DC(ad[j+12]), DC(ad[j+13]), DC(ad[j+14]), DC(ad[j+15]) + ); + } + + if (len%STEP==0) return; + sprintf(buffer,"%02x:", i); + for (j=0; j < STEP; j++) { + if (j<(len%STEP)) + sprintf(str, " %02x", ad[i+j]); + else + strcpy(str, " " ); + strncat(buffer, str, sizeof(buffer)); + } + strncat(buffer," ", sizeof(buffer)); + for (j=0; j < (len%STEP); j++) { + sprintf(str, "%c", DC(ad[i+j])); + strncat(buffer, str, sizeof(buffer)); + } + printf("%s\n",buffer); +} + +void dumpAllTablesOfType(int i) +{ + char title[32]; + struct DMIHeader * dmihdr; + for(dmihdr = FindFirstDmiTableOfType(i, 4); + dmihdr; + dmihdr = FindNextDmiTableOfType(i, 4)) { + sprintf(title,"Table (type %d) :" , i); + dumpPhysAddr(title, dmihdr, dmihdr->length+32); + } +} + +const char * getDMIString(struct DMIHeader * dmihdr, uint8_t strNum) +{ + const char * ret =NULL; + const char * startAddr = (const char *) dmihdr; + const char * limit = NULL; + + if (!dmihdr || dmihdr->length<4 || strNum==0) return NULL; + startAddr += dmihdr->length; + limit = startAddr + 256; + for(; strNum; strNum--) { + if ((*startAddr)==0 && *(startAddr+1)==0) break; + if (*startAddr && strNum<=1) { + ret = startAddr; // current str + break; + } + while(*startAddr && startAddrnumberOfMemoryDevices : 0; + + i = 0; + for(dmihdr = FindFirstDmiTableOfType(17, 4); + dmihdr; + dmihdr = FindNextDmiTableOfType(17, 4) ) { + memDev[i] = (struct DMIMemoryDevice*) dmihdr; + if (memDev[i]->size !=0 ) Platform.DMI.MemoryModules++; + if (memDev[i]->speed>0) Platform.RAM.DIMM[i].Frequency = memDev[i]->speed; // take it here for now but we'll check spd and dmi table 6 as well + i++; + } + // for table 6, we only have a look at the current speed + i = 0; + for(dmihdr = FindFirstDmiTableOfType(6, 4); + dmihdr; + dmihdr = FindNextDmiTableOfType(6, 4) ) { + memInfo[i] = (struct DMIMemoryModuleInfo*) dmihdr; + if (memInfo[i]->currentSpeed > Platform.RAM.DIMM[i].Frequency) + Platform.RAM.DIMM[i].Frequency = memInfo[i]->currentSpeed; // favor real overclocked speed if any + i++; + } +#if 0 + dumpAllTablesOfType(17); + getc(); +#endif +} Index: branches/azimutz/Chazi/i386/modules/Memory/mem.h =================================================================== --- branches/azimutz/Chazi/i386/modules/Memory/mem.h (revision 0) +++ branches/azimutz/Chazi/i386/modules/Memory/mem.h (revision 526) @@ -0,0 +1,15 @@ +/* + * Copyright 2010 AsereBLN. All rights reserved. + * + * mem.h + */ + +#ifndef __LIBSAIO_MEM_H +#define __LIBSAIO_MEM_H + +#include "platform.h" + +extern void scan_memory(PlatformInfo_t *); + + +#endif /* __LIBSAIO_MEM_H */ Index: branches/azimutz/Chazi/i386/modules/Memory/spd.c =================================================================== --- branches/azimutz/Chazi/i386/modules/Memory/spd.c (revision 0) +++ branches/azimutz/Chazi/i386/modules/Memory/spd.c (revision 526) @@ -0,0 +1,394 @@ +/* + * spd.c - serial presence detect memory information + * + * Originally restored from pcefi10.5 + * Dynamic mem detection original impl. by Rekursor + * System profiler fix and other fixes by Mozodojo. + */ + +#include "libsaio.h" +#include "pci.h" +#include "platform.h" +#include "spd.h" +#include "saio_internal.h" +#include "bootstruct.h" +#include "memvendors.h" + +#ifndef DEBUG_SPD +#define DEBUG_SPD 0 +#endif + +#if DEBUG_SPD +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + +static const char *spd_memory_types[] = +{ + "RAM", /* 00h Undefined */ + "FPM", /* 01h FPM */ + "EDO", /* 02h EDO */ + "", /* 03h PIPELINE NIBBLE */ + "SDRAM", /* 04h SDRAM */ + "", /* 05h MULTIPLEXED ROM */ + "DDR SGRAM", /* 06h SGRAM DDR */ + "DDR SDRAM", /* 07h SDRAM DDR */ + "DDR2 SDRAM", /* 08h SDRAM DDR 2 */ + "", /* 09h Undefined */ + "", /* 0Ah Undefined */ + "DDR3 SDRAM" /* 0Bh SDRAM DDR 3 */ +}; + +#define UNKNOWN_MEM_TYPE 2 +static uint8_t spd_mem_to_smbios[] = +{ + UNKNOWN_MEM_TYPE, /* 00h Undefined */ + UNKNOWN_MEM_TYPE, /* 01h FPM */ + UNKNOWN_MEM_TYPE, /* 02h EDO */ + UNKNOWN_MEM_TYPE, /* 03h PIPELINE NIBBLE */ + SMB_MEM_TYPE_SDRAM, /* 04h SDRAM */ + SMB_MEM_TYPE_ROM, /* 05h MULTIPLEXED ROM */ + SMB_MEM_TYPE_SGRAM, /* 06h SGRAM DDR */ + SMB_MEM_TYPE_DDR, /* 07h SDRAM DDR */ + SMB_MEM_TYPE_DDR2, /* 08h SDRAM DDR 2 */ + UNKNOWN_MEM_TYPE, /* 09h Undefined */ + UNKNOWN_MEM_TYPE, /* 0Ah Undefined */ + SMB_MEM_TYPE_DDR3 /* 0Bh SDRAM DDR 3 */ +}; +#define SPD_TO_SMBIOS_SIZE (sizeof(spd_mem_to_smbios)/sizeof(uint8_t)) + +#define rdtsc(low,high) \ +__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) + +#define SMBHSTSTS 0 +#define SMBHSTCNT 2 +#define SMBHSTCMD 3 +#define SMBHSTADD 4 +#define SMBHSTDAT 5 +#define SBMBLKDAT 7 + +/** Read one byte from the intel i2c, used for reading SPD on intel chipsets only. */ +unsigned char smb_read_byte_intel(uint32_t base, uint8_t adr, uint8_t cmd) +{ + int l1, h1, l2, h2; + unsigned long long t; + + outb(base + SMBHSTSTS, 0x1f); // reset SMBus Controller + outb(base + SMBHSTDAT, 0xff); + + while( inb(base + SMBHSTSTS) & 0x01); // wait until ready + + outb(base + SMBHSTCMD, cmd); + outb(base + SMBHSTADD, (adr << 1) | 0x01 ); + outb(base + SMBHSTCNT, 0x48 ); + + rdtsc(l1, h1); + + while (!( inb(base + SMBHSTSTS) & 0x02)) // wait til command finished + { + rdtsc(l2, h2); + t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / (Platform.CPU.TSCFrequency / 100); + if (t > 5) + break; // break after 5ms + } + return inb(base + SMBHSTDAT); +} + +/* SPD i2c read optimization: prefetch only what we need, read non prefetcheable bytes on the fly */ +#define READ_SPD(spd, base, slot, x) spd[x] = smb_read_byte_intel(base, 0x50 + slot, x) + +int spd_indexes[] = { + SPD_MEMORY_TYPE, + SPD_DDR3_MEMORY_BANK, + SPD_DDR3_MEMORY_CODE, + SPD_NUM_ROWS, + SPD_NUM_COLUMNS, + SPD_NUM_DIMM_BANKS, + SPD_NUM_BANKS_PER_SDRAM, + 4,7,8,9,12,64, /* TODO: give names to these values */ + 95,96,97,98, 122,123,124,125 /* UIS */ +}; +#define SPD_INDEXES_SIZE (sizeof(spd_indexes) / sizeof(int)) + +/** Read from spd *used* values only*/ +static void init_spd(char * spd, uint32_t base, int slot) +{ + int i; + for (i=0; i< SPD_INDEXES_SIZE; i++) { + READ_SPD(spd, base, slot, spd_indexes[i]); + } +} + +/** Get Vendor Name from spd, 2 cases handled DDR3 and DDR2, + have different formats, always return a valid ptr.*/ +const char * getVendorName(RamSlotInfo_t* slot, uint32_t base, int slot_num) +{ + uint8_t bank = 0; + uint8_t code = 0; + int i = 0; + uint8_t * spd = (uint8_t *) slot->spd; + + if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) { // DDR3 + bank = (spd[SPD_DDR3_MEMORY_BANK] & 0x07f); // constructors like Patriot use b7=1 + code = spd[SPD_DDR3_MEMORY_CODE]; + for (i=0; i < VEN_MAP_SIZE; i++) + if (bank==vendorMap[i].bank && code==vendorMap[i].code) + return vendorMap[i].name; + } + else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) { + if(spd[64]==0x7f) { + for (i=64; i<72 && spd[i]==0x7f;i++) { + bank++; + READ_SPD(spd, base, slot_num,i+1); // prefetch next spd byte to read for next loop + } + READ_SPD(spd, base, slot_num,i); + code = spd[i]; + } else { + code = spd[64]; + bank = 0; + } + for (i=0; i < VEN_MAP_SIZE; i++) + if (bank==vendorMap[i].bank && code==vendorMap[i].code) + return vendorMap[i].name; + } + /* OK there is no vendor id here lets try to match the partnum if it exists */ + if (strstr(slot->PartNo,"GU332") == slot->PartNo) // Unifosa fingerprint + return "Unifosa"; + return "NoName"; +} + +/** Get Default Memory Module Speed (no overclocking handled) */ +int getDDRspeedMhz(const char * spd) +{ + if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) { + switch(spd[12]) { + case 0x0f: + return 1066; + case 0x0c: + return 1333; + case 0x0a: + return 1600; + case 0x14: + default: + return 800; + } + } + else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) { + switch(spd[9]) { + case 0x50: + return 400; + case 0x3d: + return 533; + case 0x30: + return 667; + case 0x25: + default: + return 800; + } + } + return 800; // default freq for unknown types +} + +#define SMST(a) ((uint8_t)((spd[a] & 0xf0) >> 4)) +#define SLST(a) ((uint8_t)(spd[a] & 0x0f)) + +/** Get DDR3 or DDR2 serial number, 0 most of the times, always return a valid ptr */ +const char *getDDRSerial(const char* spd) +{ + static char asciiSerial[16]; + + if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) // DDR3 + { + sprintf(asciiSerial, "%X%X%X%X%X%X%X%X", SMST(122) /*& 0x7*/, SLST(122), SMST(123), SLST(123), SMST(124), SLST(124), SMST(125), SLST(125)); + } + else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) // DDR2 or DDR + { + sprintf(asciiSerial, "%X%X%X%X%X%X%X%X", SMST(95) /*& 0x7*/, SLST(95), SMST(96), SLST(96), SMST(97), SLST(97), SMST(98), SLST(98)); + } + + return strdup(asciiSerial); +} + +/** Get DDR3 or DDR2 Part Number, always return a valid ptr */ +const char * getDDRPartNum(char* spd, uint32_t base, int slot) +{ + static char asciiPartNo[32]; + int i, start=0, index = 0; + + if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) { + start = 128; + } + else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) { + start = 73; + } + + // Check that the spd part name is zero terminated and that it is ascii: + bzero(asciiPartNo, sizeof(asciiPartNo)); + char c; + for (i=start; i < start + sizeof(asciiPartNo); i++) { + READ_SPD(spd, base, slot, i); // only read once the corresponding model part (ddr3 or ddr2) + c = spd[i]; + if (isalpha(c) || isdigit(c) || ispunct(c)) // It seems that System Profiler likes only letters and digits... + asciiPartNo[index++] = c; + else if (!isascii(c)) + break; + } + + return strdup(asciiPartNo); + return NULL; +} + +int mapping []= {0,2,1,3,4,6,5,7,8,10,9,11}; + + +/** Read from smbus the SPD content and interpret it for detecting memory attributes */ +static void read_smb_intel(pci_dt_t *smbus_dev) +{ + int i, speed; + uint8_t spd_size, spd_type; + uint32_t base; + bool dump = false; + RamSlotInfo_t* slot; + + base = pci_config_read16(smbus_dev->dev.addr, 0x20) & 0xFFFE; + DBG("Scanning smbus_dev <%04x, %04x> ...\n",smbus_dev->vendor_id, smbus_dev->device_id); + + getBoolForKey("DumpSPD", &dump, &bootInfo->bootConfig); + bool fullBanks = // needed at least for laptops + Platform.DMI.MemoryModules == Platform.DMI.MaxMemorySlots; + // Search MAX_RAM_SLOTS slots + char spdbuf[256]; + + for (i = 0; i < MAX_RAM_SLOTS; i++){ + slot = &Platform.RAM.DIMM[i]; + spd_size = smb_read_byte_intel(base, 0x50 + i, 0); + // Check spd is present + if (spd_size && (spd_size != 0xff) ) { + + slot->spd = spdbuf; + slot->InUse = true; + + bzero(slot->spd, spd_size); + + // Copy spd data into buffer + + //for (x = 0; x < spd_size; x++) slot->spd[x] = smb_read_byte_intel(base, 0x50 + i, x); + init_spd(slot->spd, base, i); + + switch (slot->spd[SPD_MEMORY_TYPE]) { + case SPD_MEMORY_TYPE_SDRAM_DDR2: + + slot->ModuleSize = ((1 << (slot->spd[SPD_NUM_ROWS] & 0x0f) + (slot->spd[SPD_NUM_COLUMNS] & 0x0f) - 17) * + ((slot->spd[SPD_NUM_DIMM_BANKS] & 0x7) + 1) * slot->spd[SPD_NUM_BANKS_PER_SDRAM]); + break; + + case SPD_MEMORY_TYPE_SDRAM_DDR3: + + slot->ModuleSize = ((slot->spd[4] & 0x0f) + 28 ) + ((slot->spd[8] & 0x7) + 3 ); + slot->ModuleSize -= (slot->spd[7] & 0x7) + 25; + slot->ModuleSize = ((1 << slot->ModuleSize) * (((slot->spd[7] >> 3) & 0x1f) + 1)); + + break; + } + + spd_type = (slot->spd[SPD_MEMORY_TYPE] < ((char) 12) ? slot->spd[SPD_MEMORY_TYPE] : 0); + slot->Type = spd_mem_to_smbios[spd_type]; + slot->PartNo = getDDRPartNum(slot->spd, base, i); + slot->Vendor = getVendorName(slot, base, i); + slot->SerialNo = getDDRSerial(slot->spd); + + // determine spd speed + speed = getDDRspeedMhz(slot->spd); + 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 1: freq--; break; + case 32: freq++; break; + case 65: freq++; break; + case 98: freq+=2;break; + case 99: freq++; break; + } + slot->Frequency = freq; + } + + verbose("Slot: %d Type %d %dMB (%s) %dMHz Vendor=%s\n PartNo=%s SerialNo=%s\n", + i, + (int)slot->Type, + slot->ModuleSize, + spd_memory_types[spd_type], + slot->Frequency, + slot->Vendor, + slot->PartNo, + slot->SerialNo); + if(DEBUG_SPD) { + dumpPhysAddr("spd content: ",slot->spd, spd_size); + getc(); + } + } + + // laptops sometimes show slot 0 and 2 with slot 1 empty when only 2 slots are presents so: + Platform.DMI.DIMM[i]= + i>0 && Platform.RAM.DIMM[1].InUse==false && fullBanks && Platform.DMI.MaxMemorySlots==2 ? + mapping[i] : i; // for laptops case, mapping setup would need to be more generic than this + + slot->spd = NULL; + + } // for +} + +static struct smbus_controllers_t smbus_controllers[] = { + + {0x8086, 0x269B, "ESB2", read_smb_intel }, + {0x8086, 0x25A4, "6300ESB", read_smb_intel }, + {0x8086, 0x24C3, "ICH4", read_smb_intel }, + {0x8086, 0x24D3, "ICH5", read_smb_intel }, + {0x8086, 0x266A, "ICH6", read_smb_intel }, + {0x8086, 0x27DA, "ICH7", read_smb_intel }, + {0x8086, 0x283E, "ICH8", read_smb_intel }, + {0x8086, 0x2930, "ICH9", read_smb_intel }, + {0x8086, 0x3A30, "ICH10R", read_smb_intel }, + {0x8086, 0x3A60, "ICH10B", read_smb_intel }, + {0x8086, 0x3B30, "P55", read_smb_intel }, + {0x8086, 0x5032, "EP80579", read_smb_intel } + +}; + +// initial call : pci_dt = root_pci_dev; +// find_and_read_smbus_controller(root_pci_dev); +bool find_and_read_smbus_controller(pci_dt_t* pci_dt) +{ + pci_dt_t *current = pci_dt; + int i; + + while (current) { +#if 0 + printf("%02x:%02x.%x [%04x] [%04x:%04x] :: %s\n", + current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func, + current->class_id, current->vendor_id, current->device_id, + get_pci_dev_path(current)); +#endif + for ( i = 0; i < sizeof(smbus_controllers) / sizeof(smbus_controllers[0]); i++ ) + { + if (current->vendor_id == smbus_controllers[i].vendor && + current->device_id == smbus_controllers[i].device) + { + smbus_controllers[i].read_smb(current); // read smb + return true; + } + } + find_and_read_smbus_controller(current->children); + current = current->next; + } + return false; // not found +} + +void scan_spd(PlatformInfo_t *p) +{ + find_and_read_smbus_controller(root_pci_dev); +} Index: branches/azimutz/Chazi/i386/modules/Memory/Memory.c =================================================================== --- branches/azimutz/Chazi/i386/modules/Memory/Memory.c (revision 0) +++ branches/azimutz/Chazi/i386/modules/Memory/Memory.c (revision 526) @@ -0,0 +1,84 @@ +/* + * DRAM Controller Module + * Scans the dram controller and notifies OS X of the memory modules. + * This was converted from boot2 code to a boot2 module. + * + */ + +#include "libsaio.h" +#include "pci.h" +#include "platform.h" +#include "dram_controllers.h" +#include "spd.h" +#include "mem.h" +#include "modules.h" + +pci_dt_t *dram_controller_dev; + + +void Memory_hook(void* arg1, void* arg2, void* arg3, void* arg4); +void Memory_PCIDevice_hook(void* arg1, void* arg2, void* arg3, void* arg4); + + +void Memory_start() +{ + register_hook_callback("PCIDevice", &Memory_PCIDevice_hook); + register_hook_callback("ScanMemory", &Memory_hook); + +} + +void Memory_PCIDevice_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + pci_dt_t* current = arg1; + if(current->class_id == PCI_CLASS_BRIDGE_HOST) + { + dram_controller_dev = current; + } +} + +void Memory_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + 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); +} + + + +/* Nedded to devide 64bit numbers correctly. TODO: look into why the module needs this + * And why it isn't needed when compiled into boot2 + */ + +uint64_t __udivdi3(uint64_t numerator, uint64_t denominator) +{ + uint64_t quotient = 0, qbit = 1; + + if (denominator) + { + while ((int64_t) denominator >= 0) + { + denominator <<= 1; + qbit <<= 1; + } + + while (denominator) + { + if (denominator <= numerator) + { + numerator -= denominator; + quotient += qbit; + } + denominator >>= 1; + qbit >>= 1; + } + + return quotient; + } + else { + stop("Divide by 0"); + return 0; + } + +} Index: branches/azimutz/Chazi/i386/modules/Memory/dram_controllers.c =================================================================== --- branches/azimutz/Chazi/i386/modules/Memory/dram_controllers.c (revision 0) +++ branches/azimutz/Chazi/i386/modules/Memory/dram_controllers.c (revision 526) @@ -0,0 +1,562 @@ +/* + * dram controller access and scan from the pci host controller + * Integrated and adapted for chameleon 2.0 RC5 by Rekursor from bs0d work + * original source comes from: + * + * 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 = 333333; break; // 3.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; + case 6: mch_fsb = 1066; 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 = 83333; 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; + case 1066: + switch ((mch_cfg >> 4)&7) { + case 5: mch_ratio = 150000; break; + case 6: mch_ratio = 200000; 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 }, + { 0x8086, 0x3404, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3405, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3406, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3407, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + +}; + +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); + + verbose("Frequency detected: %d MHz (%d) %s Channel %d-%d-%d-%d\n", + (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: branches/azimutz/Chazi/i386/modules/Memory/spd.h =================================================================== --- branches/azimutz/Chazi/i386/modules/Memory/spd.h (revision 0) +++ branches/azimutz/Chazi/i386/modules/Memory/spd.h (revision 526) @@ -0,0 +1,160 @@ +/* + * Copyright 2010 AsereBLN. All rights reserved. + * + * spd.h + */ + +#ifndef __LIBSAIO_SPD_H +#define __LIBSAIO_SPD_H + +#include "platform.h" +#include "libsaio.h" + +void scan_spd(PlatformInfo_t *p); + +struct smbus_controllers_t { + uint32_t vendor; + uint32_t device; + char *name; + void (*read_smb)(pci_dt_t *smbus_dev); +}; + + +/* + * Serial Presence Detect (SPD) data stored on SDRAM modules. + * + * Datasheet: + * - Name: PC SDRAM Serial Presence Detect (SPD) Specification + * Revision 1.2A, December, 1997 + * - PDF: http://www.intel.com/design/chipsets/memory/spdsd12a.pdf + * + * Datasheet (alternative): + * - Name: SERIAL PRESENCE DETECT STANDARD, General Standard + * JEDEC Standard No. 21-C + * - PDF: http://www.jedec.org/download/search/4_01_02_00R9.PDF + */ + + +/* Byte numbers. */ +#define SPD_NUM_MANUFACTURER_BYTES 0 /* Number of bytes used by module manufacturer */ +#define SPD_TOTAL_SPD_MEMORY_SIZE 1 /* Total SPD memory size */ +#define SPD_MEMORY_TYPE 2 /* (Fundamental) memory type */ +#define SPD_NUM_ROWS 3 /* Number of row address bits */ +#define SPD_NUM_COLUMNS 4 /* Number of column address bits */ +#define SPD_NUM_DIMM_BANKS 5 /* Number of module rows (banks) */ +#define SPD_MODULE_DATA_WIDTH_LSB 6 /* Module data width (LSB) */ +#define SPD_MODULE_DATA_WIDTH_MSB 7 /* Module data width (MSB) */ +#define SPD_MODULE_VOLTAGE 8 /* Module interface signal levels */ +#define SPD_MIN_CYCLE_TIME_AT_CAS_MAX 9 /* SDRAM cycle time (highest CAS latency), RAS access time (tRAC) */ +#define SPD_ACCESS_TIME_FROM_CLOCK 10 /* SDRAM access time from clock (highest CAS latency), CAS access time (Tac, tCAC) */ +#define SPD_DIMM_CONFIG_TYPE 11 /* Module configuration type */ +#define SPD_REFRESH 12 /* Refresh rate/type */ +#define SPD_PRIMARY_SDRAM_WIDTH 13 /* SDRAM width (primary SDRAM) */ +#define SPD_ERROR_CHECKING_SDRAM_WIDTH 14 /* Error checking SDRAM (data) width */ +#define SPD_MIN_CLOCK_DELAY_B2B_RAND_COLUMN 15 /* SDRAM device attributes, minimum clock delay for back to back random column */ +#define SPD_SUPPORTED_BURST_LENGTHS 16 /* SDRAM device attributes, burst lengths supported */ +#define SPD_NUM_BANKS_PER_SDRAM 17 /* SDRAM device attributes, number of banks on SDRAM device */ +#define SPD_ACCEPTABLE_CAS_LATENCIES 18 /* SDRAM device attributes, CAS latency */ +#define SPD_CS_LATENCY 19 /* SDRAM device attributes, CS latency */ +#define SPD_WE_LATENCY 20 /* SDRAM device attributes, WE latency */ +#define SPD_MODULE_ATTRIBUTES 21 /* SDRAM module attributes */ +#define SPD_DEVICE_ATTRIBUTES_GENERAL 22 /* SDRAM device attributes, general */ +#define SPD_SDRAM_CYCLE_TIME_2ND 23 /* SDRAM cycle time (2nd highest CAS latency) */ +#define SPD_ACCESS_TIME_FROM_CLOCK_2ND 24 /* SDRAM access from clock (2nd highest CAS latency) */ +#define SPD_SDRAM_CYCLE_TIME_3RD 25 /* SDRAM cycle time (3rd highest CAS latency) */ +#define SPD_ACCESS_TIME_FROM_CLOCK_3RD 26 /* SDRAM access from clock (3rd highest CAS latency) */ +#define SPD_MIN_ROW_PRECHARGE_TIME 27 /* Minimum row precharge time (Trp) */ +#define SPD_MIN_ROWACTIVE_TO_ROWACTIVE 28 /* Minimum row active to row active (Trrd) */ +#define SPD_MIN_RAS_TO_CAS_DELAY 29 /* Minimum RAS to CAS delay (Trcd) */ +#define SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY 30 /* Minimum RAS pulse width (Tras) */ +#define SPD_DENSITY_OF_EACH_ROW_ON_MODULE 31 /* Density of each row on module */ +#define SPD_CMD_SIGNAL_INPUT_SETUP_TIME 32 /* Command and address signal input setup time */ +#define SPD_CMD_SIGNAL_INPUT_HOLD_TIME 33 /* Command and address signal input hold time */ +#define SPD_DATA_SIGNAL_INPUT_SETUP_TIME 34 /* Data signal input setup time */ +#define SPD_DATA_SIGNAL_INPUT_HOLD_TIME 35 /* Data signal input hold time */ +#define SPD_WRITE_RECOVERY_TIME 36 /* Write recovery time (tWR) */ +#define SPD_INT_WRITE_TO_READ_DELAY 37 /* Internal write to read command delay (tWTR) */ +#define SPD_INT_READ_TO_PRECHARGE_DELAY 38 /* Internal read to precharge command delay (tRTP) */ +#define SPD_MEM_ANALYSIS_PROBE_PARAMS 39 /* Memory analysis probe characteristics */ +#define SPD_BYTE_41_42_EXTENSION 40 /* Extension of byte 41 (tRC) and byte 42 (tRFC) */ +#define SPD_MIN_ACT_TO_ACT_AUTO_REFRESH 41 /* Minimum active to active auto refresh (tRCmin) */ +#define SPD_MIN_AUTO_REFRESH_TO_ACT 42 /* Minimum auto refresh to active/auto refresh (tRFC) */ +#define SPD_MAX_DEVICE_CYCLE_TIME 43 /* Maximum device cycle time (tCKmax) */ +#define SPD_MAX_DQS_DQ_SKEW 44 /* Maximum skew between DQS and DQ (tDQSQ) */ +#define SPD_MAX_READ_DATAHOLD_SKEW 45 /* Maximum read data-hold skew factor (tQHS) */ +#define SPD_PLL_RELOCK_TIME 46 /* PLL relock time */ +#define SPD_SPD_DATA_REVISION_CODE 62 /* SPD data revision code */ +#define SPD_CHECKSUM_FOR_BYTES_0_TO_62 63 /* Checksum for bytes 0-62 */ +#define SPD_MANUFACTURER_JEDEC_ID_CODE 64 /* Manufacturer's JEDEC ID code, per EIA/JEP106 (bytes 64-71) */ +#define SPD_MANUFACTURING_LOCATION 72 /* Manufacturing location */ +#define SPD_MANUFACTURER_PART_NUMBER 73 /* Manufacturer's part number, in 6-bit ASCII (bytes 73-90) */ +#define SPD_REVISION_CODE 91 /* Revision code (bytes 91-92) */ +#define SPD_MANUFACTURING_DATE 93 /* Manufacturing date (byte 93: year, byte 94: week) */ +#define SPD_ASSEMBLY_SERIAL_NUMBER 95 /* Assembly serial number (bytes 95-98) */ +#define SPD_MANUFACTURER_SPECIFIC_DATA 99 /* Manufacturer specific data (bytes 99-125) */ +#define SPD_INTEL_SPEC_FOR_FREQUENCY 126 /* Intel specification for frequency */ +#define SPD_INTEL_SPEC_100_MHZ 127 /* Intel specification details for 100MHz support */ +#define SPD_DDR3_MEMORY_BANK 0x75 +#define SPD_DDR3_MEMORY_CODE 0x76 + +/* DRAM specifications use the following naming conventions for SPD locations */ +#define SPD_tRP SPD_MIN_ROW_PRECHARGE_TIME +#define SPD_tRRD SPD_MIN_ROWACTIVE_TO_ROWACTIVE +#define SPD_tRCD SPD_MIN_RAS_TO_CAS_DELAY +#define SPD_tRAS SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY +#define SPD_BANK_DENSITY SPD_DENSITY_OF_EACH_ROW_ON_MODULE +#define SPD_ADDRESS_CMD_HOLD SPD_CMD_SIGNAL_INPUT_HOLD_TIME +#define SPD_tRC 41 /* SDRAM Device Minimum Active to Active/Auto Refresh Time (tRC) */ +#define SPD_tRFC 42 /* SDRAM Device Minimum Auto Refresh to Active/Auto Refresh (tRFC) */ + + +/* SPD_MEMORY_TYPE values. */ +#define SPD_MEMORY_TYPE_FPM_DRAM 1 +#define SPD_MEMORY_TYPE_EDO 2 +#define SPD_MEMORY_TYPE_PIPELINED_NIBBLE 3 +#define SPD_MEMORY_TYPE_SDRAM 4 +#define SPD_MEMORY_TYPE_MULTIPLEXED_ROM 5 +#define SPD_MEMORY_TYPE_SGRAM_DDR 6 +#define SPD_MEMORY_TYPE_SDRAM_DDR 7 +#define SPD_MEMORY_TYPE_SDRAM_DDR2 8 +#define SPD_MEMORY_TYPE_SDRAM_DDR3 0xb + +/* SPD_MODULE_VOLTAGE values. */ +#define SPD_VOLTAGE_TTL 0 /* 5.0 Volt/TTL */ +#define SPD_VOLTAGE_LVTTL 1 /* LVTTL */ +#define SPD_VOLTAGE_HSTL 2 /* HSTL 1.5 */ +#define SPD_VOLTAGE_SSTL3 3 /* SSTL 3.3 */ +#define SPD_VOLTAGE_SSTL2 4 /* SSTL 2.5 */ + +/* SPD_DIMM_CONFIG_TYPE values. */ +#define ERROR_SCHEME_NONE 0 +#define ERROR_SCHEME_PARITY 1 +#define ERROR_SCHEME_ECC 2 + +/* SPD_ACCEPTABLE_CAS_LATENCIES values. */ +// TODO: Check values. +#define SPD_CAS_LATENCY_1_0 0x01 +#define SPD_CAS_LATENCY_1_5 0x02 +#define SPD_CAS_LATENCY_2_0 0x04 +#define SPD_CAS_LATENCY_2_5 0x08 +#define SPD_CAS_LATENCY_3_0 0x10 +#define SPD_CAS_LATENCY_3_5 0x20 +#define SPD_CAS_LATENCY_4_0 0x40 + +#define SPD_CAS_LATENCY_DDR2_3 (1 << 3) +#define SPD_CAS_LATENCY_DDR2_4 (1 << 4) +#define SPD_CAS_LATENCY_DDR2_5 (1 << 5) +#define SPD_CAS_LATENCY_DDR2_6 (1 << 6) + +/* SPD_SUPPORTED_BURST_LENGTHS values. */ +#define SPD_BURST_LENGTH_1 1 +#define SPD_BURST_LENGTH_2 2 +#define SPD_BURST_LENGTH_4 4 +#define SPD_BURST_LENGTH_8 8 +#define SPD_BURST_LENGTH_PAGE (1 << 7) + +/* SPD_MODULE_ATTRIBUTES values. */ +#define MODULE_BUFFERED 1 +#define MODULE_REGISTERED 2 + +#endif /* !__LIBSAIO_SPD_H */ Index: branches/azimutz/Chazi/i386/modules/Memory/Makefile =================================================================== --- branches/azimutz/Chazi/i386/modules/Memory/Makefile (revision 0) +++ branches/azimutz/Chazi/i386/modules/Memory/Makefile (revision 526) @@ -0,0 +1,98 @@ + +MODULE_NAME = Memory +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = Memory + +include ../../MakePaths.dir + +OBJROOT=../../../obj/i386/modules/$(DIR) +SYMROOT=../../../sym/i386/modules/ +DSTROOT=../../../dst/i386/modules/ + + +UTILDIR = ../../util +LIBSADIR = ../../libsa +LIBSAIODIR = ../../libsaio +BOOT2DIR = ../../boot2 + +INSTALLDIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/standalone + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common -mdynamic-no-pic + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +ifneq "" "$(wildcard /bin/mkdirs)" + MKDIRS = /bin/mkdirs +else + MKDIRS = /bin/mkdir -p +endif +AS = as +LD = ld +# LIBS= -lc_static +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + +MEMORY_OBJS = dram_controllers.o mem.o spd.o Memory.o + + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: ${MEMORY_OBJS} dylib + + +dylib: ${GRAPHICS_ENABLER_OBJS} + ld -flat_namespace -arch i386 \ + -undefined suppress \ + -alias $(MODULE_START) start \ + -dylib -read_only_relocs suppress \ + -S -x -Z -dead_strip_dylibs \ + -no_uuid \ + -current_version $(MODULE_VERSION) -compatibility_version $(MODULE_COMPAT_VERSION) \ + -final_output $(MODULE_NAME) \ + $(OBJROOT)/dram_controllers.o \ + $(OBJROOT)/spd.o \ + $(OBJROOT)/mem.o \ + $(OBJROOT)/Memory.o \ + -o $(SYMROOT)/$(MODULE_NAME).dylib + + + +dram_controllers.o: + $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c "dram_controllers.c" $(INC) -o "$(OBJROOT)/dram_controllers.o" + +Memory.o: + $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c "Memory.c" $(INC) -o "$(OBJROOT)/Memory.o" + +spd.o: + $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c "spd.c" $(INC) -o "$(OBJROOT)/spd.o" + +mem.o: + $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c "mem.c" $(INC) -o "$(OBJROOT)/mem.o" + + +include ../../MakeInc.dir + +# dependencies +-include $(OBJROOT)/Makedep Index: branches/azimutz/Chazi/i386/modules/Symbols/Makefile =================================================================== --- branches/azimutz/Chazi/i386/modules/Symbols/Makefile (revision 525) +++ branches/azimutz/Chazi/i386/modules/Symbols/Makefile (revision 526) @@ -4,7 +4,7 @@ MODULE_COMPAT_VERSION = `ls ../../.svn &> /dev/null && (svn info ../../ | grep Revision | awk '{print $$2}') || echo 0` MODULE_START = _$(MODULE_NAME)_start MODULE_DEPENDENCIES = -DIR = HelloWorld +DIR = Symbols include ../../MakePaths.dir Index: branches/azimutz/Chazi/i386/modules/GraphicsEnabler/GraphicsEnabler.c =================================================================== --- branches/azimutz/Chazi/i386/modules/GraphicsEnabler/GraphicsEnabler.c (revision 525) +++ branches/azimutz/Chazi/i386/modules/GraphicsEnabler/GraphicsEnabler.c (revision 526) @@ -21,13 +21,16 @@ void GraphicsEnabler_start() { - register_hook_callback(kGraphicsEnablerKey, &GraphicsEnabler_hook); + register_hook_callback("PCIDevice", &GraphicsEnabler_hook); } void GraphicsEnabler_hook(void* arg1, void* arg2, void* arg3, void* arg4) { pci_dt_t* current = arg1; + + if(current->class_id != PCI_CLASS_DISPLAY_VGA) return; + char *devicepath = get_pci_dev_path(current); bool do_gfx_devprop = false; Index: branches/azimutz/Chazi/i386/modules/GraphicsEnabler/Makefile =================================================================== --- branches/azimutz/Chazi/i386/modules/GraphicsEnabler/Makefile (revision 525) +++ branches/azimutz/Chazi/i386/modules/GraphicsEnabler/Makefile (revision 526) @@ -5,7 +5,7 @@ MODULE_START = _$(MODULE_NAME)_start MODULE_DEPENDENCIES = -DIR = HelloWorld +DIR = GraphicsEnabler include ../../MakePaths.dir Index: branches/azimutz/Chazi/i386/modules/Makefile =================================================================== --- branches/azimutz/Chazi/i386/modules/Makefile (revision 525) +++ branches/azimutz/Chazi/i386/modules/Makefile (revision 526) @@ -26,6 +26,7 @@ VPATH = $(OBJROOT):$(SYMROOT) # The order of building is important. +# TODO: exclude Symbols from find so it isn't compiled twice SUBDIRS = Symbols `find ./ -type d -depth 1 -not -name ".*"` all embedtheme optionrom tags debug install installhdrs: