FIXED Reading SPD data from DDR2 and DDR3 RAM memory modules

Share your advanced PureBasic knowledge/code with the community.
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by doctorized »

I found an app, RW - Read & Write: http://rweverything.phpnet.us/index.htm that reads the data from the spd at address $A0 from SB750 and Nvidia 750. I also tried this:

Code: Select all

Procedure.l smbCallBus(BaseAddr.l, Cmd.b, Slave.b, RW.b)
	status.b = ReadIOPortWord(BaseAddr)
	Debug "Status = " + Hex(status)
	smbWaitForFree(BaseAddr)
	For i=0 To 19
		For ii= 0 To 19
			For iii = 0 To 19
				For iv=0 To $20
					status = ReadIOPortWord(BaseAddr)
					smbWaitForFree(BaseAddr);
					WriteIoPortByte(BaseAddr + i, Slave);((Slave * 2) | RW)-1)
					WriteIoPortByte(BaseAddr + ii, Cmd)
					WriteIoPortByte(BaseAddr + iii, iv)
					smbWaitForEnd(BaseAddr)
					If (ReadIOPortWord(BaseAddr) & $FF) = $92
						Debug Str(i) + " / " + Str(ii) + " / " + Str(iii) + " / " + Str(iv)
					EndIf
				Next
			Next
		Next
	Next
	Debug "OK"
EndProcedure
with no success. This make me think that BaseAddr may be wrong. Maybe for some chips we need different address to read the data.
Helle
Enthusiast
Enthusiast
Posts: 178
Joined: Wed Apr 12, 2006 7:59 pm
Location: Germany
Contact:

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by Helle »

No, BaseAddress is right! Take a look at the file "rw.ini". For "my" SB950 (=Hudson) see "[SMBUS7]". If PCI-Read at $90 = 0 then read the phys.memory (DWord) at $FED8032C; an and with $FFF0 gives the BaseAddress $B00! This is also for SB700/750. Nvidia see other points.
For Read-Memory in Win7/64 I use ATSIV.
Helle
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by doctorized »

Helle wrote:No, BaseAddress is right! Take a look at the file "rw.ini". For "my" SB950 (=Hudson) see "[SMBUS7]". If PCI-Read at $90 = 0 then read the phys.memory (DWord) at $FED8032C; an and with $FFF0 gives the BaseAddress $B00! This is also for SB700/750. Nvidia see other points.
For Read-Memory in Win7/64 I use ATSIV.
Helle
Did you succeed to use these info to read you spd? Can you traslate them to PB?
Helle
Enthusiast
Enthusiast
Posts: 178
Joined: Wed Apr 12, 2006 7:59 pm
Location: Germany
Contact:

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by Helle »

Yes!
By hand:

Code: Select all

...
SMBusBaseAddress = $B00;GetSMBusBaseAddress();search pci devices to find smbus controller and get the base address
...
Result (dump):

Code: Select all

DIMM # 0

   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00 92 10 0B 02 03 19 00 09 03 52 01 08 0C 00 7E 00 
10 6C 78 6C 30 6C 11 20 89 00 05 3C 3C 00 F0 82 01 
20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
30 00 00 00 00 00 00 00 00 00 00 00 00 0F 11 01 01 
40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
70 00 00 00 00 00 83 13 01 10 28 00 00 00 00 FE 21 
80 43 4C 39 2D 39 2D 39 20 44 44 52 33 2D 31 33 33 
90 33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
Helle
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by doctorized »

Helle wrote:Yes!
By hand:

Code: Select all

...
SMBusBaseAddress = $B00;GetSMBusBaseAddress();search pci devices to find smbus controller and get the base address
Helle[/quote]
What did GetSMBusBaseAddress() returned?
Wait a little, I will send you new code to test.
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by doctorized »

I uploaded new code. Please try it and tell me.
http://kc2000labs.shadowtavern.com/pb/zips/SPD.rar

Can you send me a dump of your SMBus controller from CPU-Z or any similar program?
It may help me find out $B00.
Helle
Enthusiast
Enthusiast
Posts: 178
Joined: Wed Apr 12, 2006 7:59 pm
Location: Germany
Contact:

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by Helle »

Sorry, the AMD-PC is at my office, not at home.
No, your code don´t work for SB950. CPU-Z wrote: Southbridge AMD SB910/950.
This works (like RW, without check for class $0C05):

Code: Select all

Datas.l
Config_Address.l              = $0CF8
Config_Data.l                 = $0CFC
#PROCESSOR_ARCHITECTURE_AMD64 = $9

SI.SYSTEM_INFO                              ;Structure System_Info
GetSystemInfo_(@SI)

If SI\wProcessorArchitecture = #PROCESSOR_ARCHITECTURE_AMD64
  DLLOK0 = OpenLibrary(0, "WinRing0x64.dll") ;64-Bit-Version
  DLLOK1 = OpenLibrary(1, "WinIo64.dll")
  WinIo$ = "WinIo64.sys"
 Else
  DLLOK0 = OpenLibrary(0, "WinRing0.dll")    ;32-Bit-Version
  DLLOK1 = OpenLibrary(1, "WinIo32.dll")
EndIf 

If DLLOK0 And DLLOK1
  Prototype.i ProtoWinRing0_0()
  WR0_InitializeOls.ProtoWinRing0_0   = GetFunction(0, "InitializeOls")
  WR0_DeinitializeOls.ProtoWinRing0_0 = GetFunction(0, "DeinitializeOls")

  Prototype.i ProtoWinRing0_2(V1.l, V2.l)
  WR0_ReadIoPortDword.ProtoWinRing0_2 = GetFunction(0, "ReadIoPortDwordEx")  
  WR0_WriteIoPortDword.ProtoWinRing0_2 = GetFunction(0, "WriteIoPortDwordEx")

  Prototype.i ProtoWinIo_0()
  WIO_InitializeWinIo.ProtoWinIo_0   = GetFunction(1, "InitializeWinIo")
  WIO_ShutdownWinIo.ProtoWinIo_0 = GetFunction(1, "ShutdownWinIo")

  Prototype.i ProtoWinIo_2(physAddr.l, physVal.l)
  WIO_GetPhysLong.ProtoWinIo_2 = GetFunction(1, "GetPhysLong")

  If WR0_InitializeOls()
    Reg_Address.l = $80000000                                   ;set Bit31 
    For Device = 0 To 31
      Reg_Address & $FFFFF8FF                                   ;set Functions=0 
      For Function = 0 To 7
        WR0_WriteIoPortDword(Config_Address, Reg_Address)       ;Vendor and Device-ID 
        WR0_ReadIoPortDword(Config_Data, @Datas)
        If Datas & $FFFFFFFF <> $FFFFFFFF
          Select (Datas & $FFFFFFFF)
            ;... Case... 
            Case $43721002, $780B1022, $43851002                ;[SMBUS7] or check device-nr. etc., there are many ways... now without class 0C05
              WR0_WriteIoPortDword(Config_Address, Reg_Address + $90)
              WR0_ReadIoPortDword(Config_Data, @Datas)
              If Datas = 0
                If SI\wProcessorArchitecture = #PROCESSOR_ARCHITECTURE_AMD64
                  RunProgram("Atsiv.exe" ," -u " + WinIo$, "", #PB_Program_Hide)    ;better, you use an another prog for reading memory... 
                  RunProgram("Atsiv.exe" ," -f " + WinIo$, "", #PB_Program_Hide)
                EndIf
                WIO_InitializeWinIo()
                WIO_GetPhysLong($FED8032C, @Datas)              ;read the phys.memory
                WIO_ShutdownWinIo()
              EndIf
              Datas & $FFF0
              Break 2
            ;... Case...
          EndSelect
        EndIf
        Reg_Address + $100 
      Next    
    Next 

    WR0_DeinitializeOls()
    CloseLibrary(0)
    CloseLibrary(1)

    MessageRequester("SMB Base-Address", "$" + Hex(Datas))
   Else 
    MessageRequester("Error!", "No WinRing0!") 
  EndIf 
EndIf 
The result is $B00.
For reading phys.memory I use WINIO32/64 and for 64-bit with Atsiv.

Helle
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by doctorized »

Helle wrote:This works (like RW, without check for class $0C05): The result is $B00.
For reading phys.memory I use WINIO32/64 and for 64-bit with Atsiv.

Helle
WR0_InitializeOls() fails to me.
Helle
Enthusiast
Enthusiast
Posts: 178
Joined: Wed Apr 12, 2006 7:59 pm
Location: Germany
Contact:

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by Helle »

Compiler-Options -> make temporary Exe.
All Files in the folder (+WinIo)?
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by doctorized »

Helle wrote:Compiler-Options -> make temporary Exe.
All Files in the folder (+WinIo)?
It was the temp file. Shame on me! :oops:

For the second pc error still exists.
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by doctorized »

Your code gives me the base address for the ATI SMBus but InitializeOls() keeps failing at the second pc with the NVidia bus (create temp exe in the source dir is checked, all dll and sys files are in the folder). Yesterday I did a small google search for "cpu-z txt report 0x1002 0x4385". Page:http://us.battle.net/wow/en/forum/topic ... 747?page=2 gave me this dump:

Code: Select all

	  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
00	02 10 85 43 03 04 30 02 3C 00 05 0C 00 00 80 00 
10	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
20	00 00 00 00 00 00 00 00 00 00 00 00 43 10 4E 83 
30	00 00 00 00 B0 00 00 00 00 00 00 00 00 00 00 00 
40	44 EB 00 FD 00 00 00 00 0F FF 00 00 00 00 00 80 
50	F2 0B F0 0E F0 0E F0 0B 21 0B F0 0F 00 00 00 00 
60	01 00 24 20 BF FC DE 03 FF 90 00 00 20 00 00 00 
70	00 00 00 00 08 00 C0 FE FF 6E 00 00 00 00 F2 07 
80	E0 0A F0 0F 00 00 00 00 00 00 00 00 00 00 00 00 
90	01 0B 00 00 F9 CE FF 00 00 00 00 00 00 00 00 00 
A0	00 00 FF FF 7F FF F0 09 00 FF 10 02 02 59 20 18 
B0	08 00 02 A8 00 00 D0 FE 00 00 00 00 F0 0F 08 1A 
C0	09 60 E0 DF 00 00 00 00 00 00 00 00 00 00 00 00 
D0	00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 
E0	20 99 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
F0	D8 0C 00 00 00 00 44 00 00 00 00 00 AA 00 30 00 
As you can see, $B00 is at $90.
From site: http://www.tomshardware.co.uk/forum/364 ... performing I took this dump:

Code: Select all

   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00 02 10 85 43 03 00 30 02 3A 00 05 0C 00 00 80 00
10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20 00 00 00 00 00 00 00 00 00 00 00 00 25 10 06 02
30 00 00 00 00 B0 00 00 00 00 00 00 00 00 00 00 00
40 44 69 00 FC 00 00 00 00 0F FF 00 00 00 00 00 C0
50 F0 01 F0 0F F0 0F F0 0F 61 80 E0 1E 00 00 00 00
60 01 00 A5 20 BF FC DE 03 5F 90 00 00 20 00 00 00
70 00 00 00 00 08 00 C0 FE FF 6E 00 00 00 00 F0 0F
80 F0 0B E1 1F 00 00 00 00 00 00 00 00 00 00 00 00
90 41 80 00 00 F9 CE FF 00 00 00 00 00 00 00 00 00
A0 00 00 FF FF 00 00 F0 09 00 FF 00 05 06 69 28 18
B0 08 00 02 A8 00 00 D0 FE 00 00 00 00 B0 4B 08 1A
C0 FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00
D0 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00
E0 20 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 00
F0 D8 0C 00 00 7F 08 00 00 00 00 00 00 AA 00 10 00 
None of the four registers contain the value we need. Instead of $B00, $8040 and $CEF0 is taken ($90 and $94).
Even worse, from site: http://extreme.pcgameshardware.de/attac ... -cpu-z.pdf the pdf file gave me this dump:

Code: Select all

   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00 02 10 85 43 03 04 20 02 42 00 05 0C 00 00 80 00
10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
no data except some basics!
From the other hand, my code on the Nvidia chipset, takes the correct address ($2D00, the same address refers SpeedFan) but fails to read the spd data. So, I do need two things:
1) find a 100% reliable way to read the address, as the chip data may not always contain it,
2) find a 100% reliable way to read the data from the address.
I have no idea how to achive them. :(
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: Reading SPD data from DDR2 and DDR3 RAM memory modules

Post by doctorized »

I tried your code and works fine under both pcs. I do not want to use winring0 dlls. I would like to use only the driver (too many depedencies). I tried to "marry" your code (the first one) with mine with no success. I cannot even find the Class, even if I copied/pasted your code. The only thing that I didn't use is InitializeOls(). Here what I have writen (Request Administrator mode is checked in the compiler):

Code: Select all

IncludeFile "Driver.pb"
LoadDeviceDriver()

Reg_Address.l = $80000000                                   ;set Bit31
For Device = 0 To 31
	Reg_Address & $FFFFF8FF                                   ;set Functions=0
	For Function = 0 To 7
		WriteIoPortDword($0CF8, Reg_Address + $A)  ;$A=Sub Class, $B=Base Class
		Datas = ReadIoPortDword($0CFC)
		Datas = (Datas >> 16) & $FFFF
		If Datas = $0C05                                        ;SMB is Class $0C05
			;Debug "Config_Address = " + Hex(Config_Address) + " " + "Reg_Address = " + Hex(Reg_Address)
			WriteIoPortDword($0CF8, Reg_Address + $20) ;$20=Base Address Register (4) ...
			Datas = ReadIoPortDword($0CFC)
			Break 2
		EndIf
		Reg_Address + $100
	Next   
Next
Debug "Address = " + Hex(Datas & $FFFFFFFC)
   
   
UnloadDriver(DRIVER_FILE_NAME)
And driver.pb has these:

Code: Select all

Global handle.l
Global DRIVER_NAME.s = "WinRing0_1_2_0"
Global DRIVER_FILE_NAME.s 
Global DRIVER_NAME_FULL.s = "\\.\WinRing0_1_2_0"

Structure PCIDEBUG_CONFREAD_INPUT
pci_address.l
pci_offset.l
EndStructure

Structure PCIDEBUG_MEMREAD_INPUT
address.q;l
unitsize.l
count.l
EndStructure

Import ""
  GetNativeSystemInfo(*info)
EndImport

Structure OLS_WRITE_IO_PORT_INPUT
	PortNumber.l
	StructureUnion
		LongData.l
		ShortData.w
		CharData.b
	EndStructureUnion
EndStructure

Procedure.l ctl_code(DeviceType, Function, Method, Access)
    ProcedureReturn ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)
EndProcedure

Procedure WriteIoPortDWord(port.l, value.l)
	returnedLength.w= 0;
	result.l = #False;
	length.l = 0;
   inputBuffer.OLS_WRITE_IO_PORT_INPUT
	inputBuffer\ShortData = value;
	inputBuffer\PortNumber = port;
	IOCTL_OLS_WRITE_IO_PORT_DWORD = ctl_code(40000,$838,0,1)
	length = OffsetOf(OLS_WRITE_IO_PORT_INPUT\CharData) + SizeOf(inputBuffer\ShortData);

	result = DeviceIoControl_(handle,IOCTL_OLS_WRITE_IO_PORT_DWORD, @inputBuffer, length,#Null,0, @returnedLength,#Null);
EndProcedure

Procedure.l ReadIoPortDWord(port.l)
	If handle = #INVALID_HANDLE_VALUE
		ProcedureReturn 101;
	EndIf
	IOCTL_OLS_READ_IO_PORT_DWORD.l = ctl_code(40000,$835,0,1)
	returnedLength.l = 0;
	result.l = #False;
	value.l = 0;

	result = DeviceIoControl_(handle, IOCTL_OLS_READ_IO_PORT_DWORD, @port, SizeOf(port), @value, SizeOf(value), @returnedLength, #Null)
	ProcedureReturn value & $FFFF
EndProcedure

Procedure.l OpenDriver()
	handle = CreateFile_(@DRIVER_NAME_FULL, #GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE, 0, #OPEN_EXISTING, #FILE_ATTRIBUTE_NORMAL, 0)
	If handle = #INVALID_HANDLE_VALUE
        ProcedureReturn 0
    EndIf
	ProcedureReturn 1
EndProcedure

Procedure.l LoadDriver(filename.s, drivername.s)
    hSCManager.l
    hService.l
    serviceStatus.SERVICE_STATUS
	ret.l


	hSCManager = OpenSCManager_(0, 0, #SC_MANAGER_ALL_ACCESS)
	If Not hSCManager
		ProcedureReturn 0
	EndIf

	hService = OpenService_(hSCManager, @drivername, #SERVICE_ALL_ACCESS)
	If hService
		ControlService_(hService, #SERVICE_CONTROL_STOP, @ServiceStatus)
		DeleteService_(hService)
		CloseServiceHandle_(hService)
	EndIf

	hService = CreateService_(hSCManager, @drivername, @drivername, #SERVICE_ALL_ACCESS, #SERVICE_KERNEL_DRIVER, #SERVICE_DEMAND_START, #SERVICE_ERROR_NORMAL, @filename, #Null, #Null, #Null, #Null, #Null)
	ret = 0
    If hService
		ret = StartService_(hService, 0, 0)
		CloseServiceHandle_(hService)
	EndIf
	CloseServiceHandle_(hSCManager)
	ProcedureReturn ret
EndProcedure


Procedure.l UnloadDriver(drivername.s)
	;SC_HANDLE	
	hSCManager.l
	hService.l
	serviceStatus.SERVICE_STATUS
	ret.l = 0
	
    hSCManager = OpenSCManager_(0, 0, #SC_MANAGER_ALL_ACCESS)
	If hSCManager
		ProcedureReturn 0
	EndIf
    
    hService = OpenService_(hSCManager, @drivername, #SERVICE_ALL_ACCESS)
	If hService
	    ret = ControlService_(hService, #SERVICE_CONTROL_STOP, @serviceStatus)
	    If ret = 1
	        ret = DeleteService_(hService)
		EndIf
	    CloseServiceHandle_(hService)
	EndIf

    CloseServiceHandle_(hSCManager)

    ProcedureReturn ret
EndProcedure

Procedure.l GetRefCount(hHandle.l)
	dwRefCount.l = -1
	ReturnedLength.l: IoctlResult.l
	IOCTL_GET_REFCONT.l = ctl_code(40000,$999,0,0)

	If hHandle
		IoctlResult = DeviceIoControl_(hHandle, IOCTL_GET_REFCONT, #Null, 0, @dwRefCount, SizeOf(dwRefCount), @ReturnedLength, #Null)
		If Not IoctlResult
			dwRefCount = -1
		EndIf
	EndIf

	ProcedureReturn dwRefCount
EndProcedure

Procedure close()
	dwRefCount.l = GetRefCount(handle)

	If handle
		CloseHandle_(handle)
	EndIf
	If dwRefCount = 1
		UnloadDriver(DRIVER_NAME)
	EndIf
	handle = 0
EndProcedure


Procedure.l initialize(DRIVER_FILE_NAME.s)
	ret.l
	path.s
	If OpenDriver()
		ProcedureReturn 0; no error
	EndIf
	path = GetPathPart(ProgramFilename()) + DRIVER_FILE_NAME
	ret = LoadDriver(path, DRIVER_NAME)
	If ret = 0
		ProcedureReturn 2; error
	EndIf

	If OpenDriver()
		ProcedureReturn 0;no error
	EndIf

	ProcedureReturn 3;error
EndProcedure

Procedure.l LoadSYS()
	ii.l: res.l
	For ii=0 To 16
		res = initialize(DRIVER_FILE_NAME)
		If res = 0
			;Debug "handle = " + Str(handle)
			ProcedureReturn 1	;Success
		EndIf
		Sleep_(100)
	Next
	msg.s = "An  error  occured  when  opening  the  driver  " + DRIVER_FILE_NAME + " ."+Chr(10)+"The  program  will  not  run  properly."
	MessageRequester("Error",msg)
	ProcedureReturn 0
EndProcedure

Procedure IsWin64(); is the OS 64;
  Protected Info.SYSTEM_INFO
  GetNativeSystemInfo(Info)
  If info\wProcessorArchitecture
    ProcedureReturn #True
  EndIf
EndProcedure 

Procedure LoadDeviceDriver()
Select OSVersion()
	Case #PB_OS_Windows_95, #PB_OS_Windows_98, #PB_OS_Windows_ME
		MessageRequester("Unsupported OS","Your OS is not supported.")
	Default
		If IsWin64() = 1
			DRIVER_FILE_NAME = "WinRing0x64.sys"
		Else
			DRIVER_FILE_NAME = "WinRing0.sys"
		EndIf
		DrvStatus = LoadSYS()
EndSelect
EndProcedure
Any help to make it work would be appreciated.
I am wondering what InitializeOls() does more than me.... I wish I had the source code...
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Reading SPD data from DDR2 and DDR3 RAM memory modules - FIX

Post by doctorized »

The code has been fixed. It works fine with ATI and NVidia chipset mobos and must work fine with INTEL chipset mobos too.
Give it a test and tell me: http://kc2000labs.shadowtavern.com/pb/zips/SPD.rar
Post Reply