i tried another approach, looks way nicer now. any comments? let me know :) Holger
/* IN RAMINIT.H */ enum E_DRAM_TYPE { DRT_SYMMETRIC = 0, DRT_ASYMMETRIC = 1 };
struct S_DRAMTechnology { uint8_t row_address; uint8_t column_address; uint16_t row_size; enum E_DRAM_TYPE type; };
static const struct S_DRAMTechnology dram_technology[] = { { 0, 24, 32, DRT_SYMMETRIC}, {24, 22, 32, DRT_ASYMMETRIC}, {23, 22, 16, DRT_ASYMMETRIC}, { 0, 22, 8, DRT_SYMMETRIC}, {21, 11, 4, DRT_ASYMMETRIC}, { 0, 0, 0, DRT_SYMMETRIC} };
/* IN RAMINIT.C */ static void detect_size(const struct mem_controller* ctrl, uint8_t* dram_size, const uint8_t row) { uint32_t address0 = 0x0; uint32_t address8 = 1; uint32_t data1 = 0x55555555UL; uint32_t data2 = 0xAAAAAAAAUL; uint32_t data3 = 0xFEDCBA98UL; uint32_t data4 = 0; uint8_t detected = 0; uint8_t index = 0;
do { /* FIXME: Not sure if this is really needed */ pci_write_config8(ctrl->d0, CR_DRAM_ROW_BOUNDARY_BASE + row, dram_technology[index].row_size / SIMM_GRANULARITY);
/* Write some data */ dimm_write32(address0, data1);
/* Prepare the first address */ address8 = (1 << dram_technology[index].column_address);
/* Write some more data */ dimm_write32(address8, data2);
/* Write even more data to yet another address for asymmetric DRAM */ if(dram_technology[index].type == DRT_ASYMMETRIC) { /* Prepare the second address */ address8 = (1 << dram_technology[index].row_address);
/* Write even more data */ dimm_write32(address8, data3); }
/* Read data back */ dimm_read32(address0, data4);
if(data1 == data4) { /* Found DRAM with correct size and technology */ dram_size[row] = dram_technology[index].row_address / SIMM_GRANULARITY; detected = 1; break; } else { /* No RAM found yet. Try next addressing scheme. */ index++; } } while(detected == 0 || dram_technology[index].row_size != 0);
if(detected == 0) { dram_size[row] = DRAM_EMPTY; } }