Chameleon

Chameleon Commit Details

Date:2010-07-24 08:59:01 (13 years 8 months ago)
Author:mozo
Commit:214
Parents: 213
Message:Merged latest Rekursor's changes
Changes:
M/branches/mozodojo/i386/libsaio/acpi_patcher.c
M/branches/mozodojo/i386/libsaio/platform.c
M/branches/mozodojo/i386/libsaio/spd.c
M/branches/mozodojo/i386/libsaio/spd.h
M/branches/mozodojo/CHANGES

File differences

branches/mozodojo/CHANGES
1
12
23
34
- Optimized memory detection speed
- Added displaying source device and partition number for file read operations.
- Increased boot2's maximum size from 383.5k to 447.5k.
Updated stage 1 loaders for handling the new size limit.
branches/mozodojo/i386/libsaio/acpi_patcher.c
197197
198198
199199
200
200
201201
202202
203203
......
207207
208208
209209
210
210
211211
212212
213213
214214
215
215
216216
217217
218218
......
250250
251251
252252
253
253
254254
255255
256256
257257
258258
259259
260
260
261261
262262
263263
......
336336
337337
338338
339
340339
341340
342341
{
if (dsdt[i] == 0x5B && dsdt[i+1] == 0x83) // ProcessorOP
{
uint8_t offset = i+2+(dsdt[i+2] >> 6) + 1, j;
uint8_t offset = i+3+(dsdt[i+2] >> 6), j;
bool add_name = TRUE;
for (j=0; j<4; j++)
if (!aml_isvalidchar(c))
{
add_name = FALSE;
verbose("Invalid characters found in ProcessorOP!\n");
verbose("Invalid characters found in ProcessorOP 0x%x!\n", c);
break;
}
}
if (add_name && dsdt[offset+4] < 32 )
if (add_name)
{
acpi_cpu_name[acpi_cpu_count] = malloc(4);
memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4);
}
if (fadt == NULL) {
verbose ("FACP not exists: C-States not generated !!!\n");
verbose ("FACP not exists: C-States will not be generated !!!\n");
return NULL;
}
struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
if (dsdt == NULL) {
verbose ("DSDT not found: C-States not generated !!!\n");
verbose ("DSDT not found: C-States will not be generated !!!\n");
return NULL;
}
aml_add_alias(scop, "CST_", "_CST");
}
aml_calculate_size(root);
struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
branches/mozodojo/i386/libsaio/spd.c
11
22
3
3
4
5
6
47
58
69
......
8588
8689
8790
88
89
90
91
92
93
9194
9295
9396
9497
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
95123
96124
97
125
98126
99127
100128
101129
102
130
103131
104132
105
106
133
134
107135
108136
109137
110138
111139
112
113
140
141
142
143
144
145
114146
115147
116
148
117149
118150
119151
......
178210
179211
180212
181
213
182214
183215
184
185
216
186217
187218
188
219
189220
190221
191
222
192223
193224
194
195
196
197
198
199
200
201
202
203
204
205
225
226
227
228
229
230
231
232
233
234
235
236
237
206238
207239
208240
209241
210242
243
211244
212245
213246
214
247
215248
216249
217250
......
224257
225258
226259
260
261
227262
228263
229264
230
231265
232266
233
234
235267
268
236269
237270
238271
239272
240273
241
242
243274
275
276
277
244278
245279
246280
......
259293
260294
261295
262
263
296
297
264298
265299
266300
267301
268
269
270
302
303
271304
272305
273306
......
276309
277310
278311
279
312
313
280314
281315
282316
......
286320
287321
288322
289
290
291
292
323
293324
294325
295326
......
319350
320351
321352
322
353
323354
324355
325356
......
342373
343374
344375
376
345377
378
346379
/*
* spd.c - serial presence detect memory information
* (restored from pcefi10.5)
*
* Originally restored from pcefi10.5
* Dynamic mem detection original impl. by Rekursor
* System profiler fix and other fixes by Mozodojo.
*/
#include "libsaio.h"
while (!( inb(base + SMBHSTSTS) & 0x02))// wait til command finished
{
rdtsc(l2, h2);
t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / (Platform.CPU.TSCFrequency / 40);
if (t > 10)
break;// break after 10ms
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)
const char * getVendorName(RamSlotInfo_t* slot, uint32_t base, int slot_num)
{
uint8_t bank = 0;
uint8_t code = 0;
int i = 0;
const char * spd = slot->spd;
char * spd = slot->spd;
if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) { // DDR3
bank = spd[0x75];
code = spd[0x76];
bank = spd[SPD_DDR3_MEMORY_BANK];
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[0x40]==0x7f) {
for (i=0x40; i<0x48 && spd[i]==0x7f;i++) bank++;
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[0x40];
code = spd[64];
bank = 0;
}
for (i=0; i < VEN_MAP_SIZE; i++)
}
/** Get DDR3 or DDR2 Part Number, always return a valid ptr */
const char * getDDRPartNum(const char* spd)
const char * getDDRPartNum(char* spd, uint32_t base, int slot)
{
static char asciiPartNo[32];
const char * sPart = NULL;
int i, index = 0;
int i, start=0, index = 0;
if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) {
sPart = &spd[128];
start = 128;
}
else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) {
sPart = &spd[73];
start = 73;
}
if (sPart) { // Check that the spd part name is zero terminated and that it is ascii:
bzero(asciiPartNo, 32);
for (i=0; i<32; i++) {
char c = sPart[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);
}
// Check that the spd part name is zero terminated and that it is ascii:
bzero(asciiPartNo, 32);
char c;
for (i=start; i<start+32; 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, x, speed;
int i, speed;
uint8_t spd_size, spd_type;
uint32_t base;
bool dump = false;
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 = malloc(spd_size);
if (slot->spd == NULL) continue;
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);
//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:
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);
slot->Vendor = getVendorName(slot);
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 (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",
if (slot->Frequency<speed) slot->Frequency = speed; // should test the mem controller to get potential overclocking info ?
printf("Slot: %d Type %d %dMB (%s) %dMHz Vendor=%s\n PartNo=%s SerialNo=%s\n",
i,
(int)slot->Type,
slot->ModuleSize,
slot->Vendor,
slot->PartNo,
slot->SerialNo);
dumpPhysAddr("spd content: ",slot->spd, spd_size);
if(DEBUG_SPD) {
dumpPhysAddr("spd content: ",slot->spd, spd_size);
getc();
}
}
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 (slot->spd) {
free(slot->spd);
slot->spd = NULL;
}
slot->spd = NULL;
} // for
}
int i;
while (current) {
#if DEBUG_SPD
#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,
void scan_spd(PlatformInfo_t *p)
{
printf("\n--> Start of mem detect:\n");
find_and_read_smbus_controller(root_pci_dev);
printf("\n<-- End of mem detect.\n");
}
branches/mozodojo/i386/libsaio/spd.h
9494
9595
9696
97
98
9799
98100
99101
#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
branches/mozodojo/i386/libsaio/platform.c
3737
3838
3939
40
40
41
42
43
4144
4245
4346
44
47
4548
4649
50
4751
4852
4953
/** scan mem for memory autodection purpose */
void scan_mem() {
bool useAutodetection = false;
static bool done = false;
if (done) return;
bool useAutodetection = true;
getBoolForKey(kUseMemDetect, &useAutodetection, &bootInfo->bootConfig);
if (useAutodetection) {
scan_memory(&Platform);
scan_memory(&Platform); // unfortunately still necesary for some comp where spd cant read correct speed
scan_spd(&Platform);
}
done = true;
}
/**

Archive Download the corresponding diff file

Revision: 214