Index: trunk/version =================================================================== --- trunk/version (revision 97) +++ trunk/version (revision 98) @@ -1 +1 @@ -2.0-RC5pre10 \ No newline at end of file +2.0-RC5pre11 \ No newline at end of file Index: trunk/i386/libsaio/spd.c =================================================================== --- trunk/i386/libsaio/spd.c (revision 97) +++ trunk/i386/libsaio/spd.c (revision 98) @@ -65,11 +65,12 @@ #define SMBHSTDAT 5 /** Get Vendor Name from spd, 2 cases handled DDR3 and DDR2, have different formats.*/ -const char * getVendorName(const char * spd) +const char * getVendorName(RamSlotInfo_t* slot) { - uint8_t code; - int i; - uint8_t bank=0; + uint8_t bank = 0; + uint8_t code = 0; + int i = 0; + const char * spd = slot->spd; if (spd[2]==0x0b) { // DDR3 bank = spd[0x75]; @@ -90,7 +91,9 @@ 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->Vendor,"GU332") == slot->Vendor) // Unifosa fingerprint + return "Unifosa"; return "NoName"; } @@ -178,92 +181,92 @@ return inb(base + SMBHSTDAT); } -int mapping []= {0,1,2,3,4,5}; // RAM_SLOT_ENUMERATOR; +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) { static int serialnum=0; - int i, x, ser; - uint8_t spd_size, spd_type; - uint32_t base; - bool dump = false; + int i, x, ser, 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 - for (i = 0; i < MAX_RAM_SLOTS; i++){ + for (i = 0; i < Platform.DMI.MaxMemorySlots; i++){ slot = &Platform.RAM.DIMM[i]; - Platform.DMI.DIMM[i]=mapping[i]; // for now no special mapping spd_size = smb_read_byte_intel(base, 0x50 + i, 0); // Check spd is present - if (spd_size && spd_size != 0xff) - { - slot->InUse = true; + if (spd_size && spd_size != 0xff) { + slot->InUse = true; + + slot->spd = malloc(spd_size); + if (slot->spd) { + bzero(slot->spd, spd_size); - slot->spd = malloc(spd_size); - if (slot->spd) { - 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); + + switch (slot->spd[SPD_MEMORY_TYPE]) { + case SPD_MEMORY_TYPE_SDRAM_DDR2: - // Copy spd data into buffer - for (x = 0; x < spd_size; x++) - slot->spd[x] = smb_read_byte_intel(base, 0x50 + i, x); + 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; - 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; - } + 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]; - strncpy(slot->PartNo, getDDRPartNum(slot->spd), 64); - strncpy(slot->Vendor, getVendorName(slot->spd), 64); - - ser = getDDRSerial(slot->spd); - if (ser==0) { - sprintf(slot->SerialNo, "10000000%d", serialnum); - serialnum++; - } - else - sprintf(slot->SerialNo, "%d", ser); - // determine speed - slot->Frequency = getDDRspeedMhz(slot->spd); - if(dump) { - printf("Slot %d Type %d %dMB (%s) %dMHz Vendor=%s, PartNo=%s SerialNo=%s\n", - i, - (int)slot->Type, - slot->ModuleSize, - spd_memory_types[spd_type], - slot->Frequency, - slot->Vendor, - slot->PartNo, - slot->SerialNo); + } + + spd_type = (slot->spd[SPD_MEMORY_TYPE] < ((char) 12) ? slot->spd[SPD_MEMORY_TYPE] : 0); + slot->Type = spd_mem_to_smbios[spd_type]; + strncpy(slot->PartNo, getDDRPartNum(slot->spd), 64); + strncpy(slot->Vendor, getVendorName(slot), 64); + + ser = getDDRSerial(slot->spd); + if (ser==0) { + sprintf(slot->SerialNo, "10000000%d", serialnum); + serialnum++; + } + else + sprintf(slot->SerialNo, "%d", ser); + // determine spd speed + speed = getDDRspeedMhz(slot->spd); + if (speed > slot->Frequency) slot->Frequency = speed; // just in case dmi wins on spd + if(dump) { + printf("Slot %d Type %d %dMB (%s) %dMHz Vendor=%s, PartNo=%s SerialNo=%s\n", + i, + (int)slot->Type, + slot->ModuleSize, + spd_memory_types[spd_type], + slot->Frequency, + slot->Vendor, + slot->PartNo, + slot->SerialNo); 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 } -#if DEBUG_SPD - printf("Press a key to continue\n"); - getc(); -#endif } static struct smbus_controllers_t smbus_controllers[] = { Index: trunk/i386/libsaio/SMBIOS.h =================================================================== --- trunk/i386/libsaio/SMBIOS.h (revision 97) +++ trunk/i386/libsaio/SMBIOS.h (revision 98) @@ -112,6 +112,7 @@ SMBByte bankLocator; SMBByte memoryType; SMBWord typeDetail; + SMBWord speed; } __attribute__((packed)); #endif /* !_LIBSAIO_SMBIOS_H */ Index: trunk/i386/libsaio/mem.c =================================================================== --- trunk/i386/libsaio/mem.c (revision 97) +++ trunk/i386/libsaio/mem.c (revision 98) @@ -63,6 +63,7 @@ } printf("%s\n",buffer); } + void dumpAllTablesOfType(int i) { char title[32]; @@ -71,59 +72,66 @@ dmihdr; dmihdr = FindNextDmiTableOfType(i, 4)) { sprintf(title,"Table (type %d) :" , i); - dumpPhysAddr(title, dmihdr, dmihdr->length); + dumpPhysAddr(title, dmihdr, dmihdr->length+16); } } + +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 && startAddrnumberOfMemorySlots : 0; - printf("Number of smbios detected Slots: %02d\n", Platform.DMI.MaxMemorySlots); - - Platform.DMI.MemoryModules = 0; + struct DMIMemoryModuleInfo* memInfo[MAX_RAM_SLOTS]; // 6 + struct DMIPhysicalMemoryArray* physMemArray; // 16 + struct DMIMemoryDevice* memDev[MAX_RAM_SLOTS]; //17 + + /* We mainly don't use obsolete tables 5,6 because most of computers don't handle it anymore */ + Platform.DMI.MemoryModules = 0; + /* Now lets peek info rom table 16,17 as for some bios, table 5 & 6 are not used */ + physMemArray = (struct DMIPhysicalMemoryArray*) FindFirstDmiTableOfType(16, 4); + Platform.DMI.MaxMemorySlots = physMemArray ? physMemArray->numberOfMemoryDevices : 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; - bc = memInfo[i]->bankConnections; - Platform.RAM.DIMM[i].BankConnCnt = 2; - if ((bc & 0x0F) == 0x0F) Platform.RAM.DIMM[i].BankConnCnt--; // 0xF nibble means no connection (3.3.7) - if ((bc & 0xF0) == 0xF0) Platform.RAM.DIMM[i].BankConnCnt--; // 0xF nibble means no connection (3.3.7) - printf("Bank Connection code for Slot %d is %02x, so %d bank connections per slot deducted.\n", - i+1, bc, Platform.RAM.DIMM[i].BankConnCnt); - - if ( memInfo[i]->installedSize < 0x7D) // >= 0x7D means error / not installed - Platform.DMI.MemoryModules++; + if (memInfo[i]->currentSpeed > Platform.RAM.DIMM[i].Frequency) + Platform.RAM.DIMM[i].Frequency = memInfo[i]->currentSpeed; // favor real overclocked speed if any i++; } - Platform.DMI.CntMemorySlots = i; - getc(); - /* - physMemArray = (struct DMIPhysicalMemoryArray*) getSmbiosTableStructure(smbios, 16, 0x1); - memDev = (struct DMIMemoryDevice*) getSmbiosTableStructure(smbios, 17, 0x1); - */ - /* - dumpAllTablesOfType(5); - dumpAllTablesOfType(6 ); - getc(); - dumpAllTablesOfType(16); - dumpAllTablesOfType(17); - getc(); - */ } Index: trunk/i386/libsaio/platform.c =================================================================== --- trunk/i386/libsaio/platform.c (revision 97) +++ trunk/i386/libsaio/platform.c (revision 98) @@ -41,5 +41,4 @@ scan_cpu(&Platform); scan_memory(&Platform); scan_spd(&Platform); - } Index: trunk/i386/libsaio/platform.h =================================================================== --- trunk/i386/libsaio/platform.h (revision 97) +++ trunk/i386/libsaio/platform.h (revision 98) @@ -77,6 +77,7 @@ typedef struct _RamSlotInfo_t { bool InUse; uint8_t Type; + uint8_t BankConnections; // table type 6, see (3.3.7) uint8_t BankConnCnt; uint32_t ModuleSize; // Size of Module in MB uint32_t Frequency; // in Mhz