之前接到过网友的询问,没有时间回复... 非常抱歉!真正创业的时候,才知道创来是如此不简单... 特别是再也没有这么多空余时间来钻研技术了...
还好,总是能收到网友讨论问题的邮件,让我偶尔还去看一下尘封以久的code, 或是再打开调试一下... 忙,没空写更多的费话,昨晚弄好code就睡了,贴一下出来...
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<dos.h>
#include<math.h>
//#define DEBUG
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;
#define READ_SPD 0x01
#define WRITE_SPD 0x00
struct SPD
{
WORD MHz;
BYTE tRAS;
BYTE tRCD;
BYTE tCL;
BYTE tRP;
BYTE BL;
};
WORD SMB_Base=0;
SPD spd[3];
//----------------------------------------------------------
//Get SMBus Base address
//----------------------------------------------------------
WORD getSMBase()
{
DWORD pciaddr;
// bus:0 dev:31 fun:3, register:20h
pciaddr = (1L << 31) + (0L << 16)+(31L << 11)+(3 << 8)+ (0x20 & 0xfc);
asm{
mov eax,pciaddr
mov dx,0CF8h
out dx,eax
mov dx,0CFCh
in eax, dx //read SMB Base
and ax, 0FFE0h
}
return _AX;
}
//----------------------------------------------------------
//Get SMBus Status
//----------------------------------------------------------
BYTE GetSMBusStatus()
{
return inportb(SMB_Base+0x00);
}
//----------------------------------------------------------
//Check SMBus Ready or not
//----------------------------------------------------------
WORD SMBusReady()
{
unsigned int m,n,s=0, check,i;
for(i=0;i<0x80;i++)
{
//m=inportb(SMB_Base); //read status
m=GetSMBusStatus();
delay(10);
outportb(SMB_Base, m);
delay(1);
n=m; //save
m=m&0x02; //BIT1:INTR is 1, ready
if(m!=0)
goto ret;
m=n; //restore
m=m&0xbf; //Bit6:INUSE_STS is 0, ready
if(m==0)
goto ret;
m=n; ///restore
m=m&0x04; //Bit2:DEV_ERR not 0, error
if(m)
break;
}
s=1;
ret:
return(s);
}
//----------------------------------------------------------
// Check Byte Done Status
//----------------------------------------------------------
WORD CheckByteDone()
{
unsigned int ss=0,st,i;
for(i=0;i<32;i++)
{
st=inportb(SMB_Base);
delay(1);
st=st&0x80; //Byte trans done...
if(st)
goto back;
}
ss=1;
back:
return(ss);
}
//----------------------------------------------------------
//Clear SMBus Status
//----------------------------------------------------------
void ClearSMBusStatus()
{
outportb(SMB_Base+0x00, 0xFE);
}
//----------------------------------------------------------
//Set Slave Address
//----------------------------------------------------------
void SetSlaveAddress(BYTE flag)
{
outportb(SMB_Base+0x04, 0xA0|flag);
}
//----------------------------------------------------------
//set command(index)
//----------------------------------------------------------
void SetCommand(BYTE index)
{
outportb(SMB_Base+0x03, index);
}
//----------------------------------------------------------
//init Byte read
//----------------------------------------------------------
void InitByteRead()
{
outportb(SMB_Base+0x02, 0x48);
}
//----------------------------------------------------------
//get data
//----------------------------------------------------------
BYTE GetData()
{
return inportb(SMB_Base+0x05);
}
//----------------------------------------------------------
//read SM Bus
//----------------------------------------------------------
BYTE ReadSMBus(BYTE index)
{
int sts;
BYTE dat;
//set slave address
SetSlaveAddress(READ_SPD);
delay(1);
//set command
SetCommand(index);
delay(1);
//init block read
InitByteRead();
delay(1);
sts=SMBusReady();
if(sts!=0)
{
return (0xff);
}
dat=GetData();
CheckByteDone();
#ifdef DEBUG
printf("\nData:%02x\n", dat);
#endif
return dat;
}
//----------------------------------------------
//BYTE to ns convert
//----------------------------------------------
float ByteToNs(BYTE dat)
{
float ns=0.0, ns1=0.0, ns2=0.0;
ns1=(float)(dat>>4);
//ns2
dat&=0x0f;
if(dat<=9)
{
ns2=(float)(dat/10);
}
else if(dat==10)
{
ns2=0.25;
}
else if(dat==11)
{
ns2=0.33;
}
else if(dat==12)
{
ns2=0.66;
}
else if(dat==13)
{
ns2=0.75;
}
ns=ns1+ns2;
return ns;
}
//----------------------------------------------
//BYTE to ns convert2
//----------------------------------------------
float ByteToNs2(BYTE dat)
{
float ns=0.0, ns1=0.0, ns2=0.0;
ns1=(float)(dat>>2);
//ns2
dat&=0x03;
ns2=dat*0.25; //0.0, 0.25, 0.50, 0.75
ns=ns1+ns2;
return ns;
}
//----------------------------------------------
// Show Memory Type
//----------------------------------------------
void ShowMemoryType(BYTE dat)
{
switch(dat)
{
case 2:
printf("EDO ");
break;
case 4:
printf("SDRAM ");
break;
case 6:
printf("DDR ");
break;
case 7:
printf("DDR ");
break;
case 8:
printf("DDR2 ");
break;
default:
printf("UNKNOWN ");
break;
}
}
//----------------------------------------------------------
// Get Memory Capacity
//----------------------------------------------------------
WORD getMemCap(BYTE dat, BYTE rank)
{
WORD cap;
switch(dat)
{
case 0x01:
cap=1024*rank;
break;
case 0x02:
cap=2048*rank;
break;
case 0x04:
cap=4096*rank;
break;
case 0x08:
cap=8192*rank;
break;
case 0x10:
cap=16384*rank;
break;
case 0x20:
cap=128*rank;
break;
case 0x40:
cap=256*rank;
break;
case 0x80:
cap=512*rank;
break;
default:
cap=0;
}
return cap;
}
//----------------------------------------------------------
// Main Program
//----------------------------------------------------------
void main()
{
int sts=0, i=0;
BYTE dat;
float ns[3], tRP, tRCD, tRAS;
WORD MHz, cap;
BYTE rank=0,DDR=1,BL=0,CLX=0;
//--------------------------------------------
//get SMB Base
//--------------------------------------------
SMB_Base =getSMBase();
#ifdef DEBUG
printf("SMB_Base:%04X\n", SMB_Base);
#endif
//--------------------------------------------
//sure SMBus Ready first
//--------------------------------------------
sts=SMBusReady();
if(sts!=0)
{
printf("SMBus not Ready0!\n");
goto Exit;
}
//--------------------------------------------
//read Memory Type
//--------------------------------------------
dat=ReadSMBus(0x02); //Byte 2
if (dat != 0xff)
{
printf("This DRAM is ");
if (dat==6 || dat==7)
DDR=1;
else if (dat==8)
DDR=2;
ShowMemoryType(dat);
}
else
{
printf("read SMB error1!\n");
goto Exit;
}
//--------------------------------------------
//read SDRAM Cycle Time
//--------------------------------------------
dat=ReadSMBus(0x09); //Byte 9
if (dat != 0xff)
{
ns[0]=ByteToNs(dat);
MHz= (WORD)(1.0 /(ns[0]*pow(10,-9)) /1000000.0 * DDR+0.5);
printf("%d,", MHz);
}
else
{
printf("read SMB error2!\n");
goto Exit;
}
//--------------------------------------------
//read Memory Rank information
//--------------------------------------------
dat=ReadSMBus(0x05); //Byte 5
if (dat != 0xff)
{
dat&=0x07;
rank=dat+1;
printf("%d Rank,", rank);
}
else
{
printf("read SMB error3!\n");
goto Exit;
}
//--------------------------------------------
//read Memory Size Information
//--------------------------------------------
dat=ReadSMBus(0x1F); //Byte 31
if (dat != 0xff)
{
cap=getMemCap(dat, rank);
printf("%d MB\n", cap);
}
else
{
printf("read SMB error4!\n");
goto Exit;
}
printf("--------------------------------------------\n");
//-------------------------------------------
//read min Clock X-1, 2
//-------------------------------------------
dat=ReadSMBus(0x17); //Byte 23
if (dat != 0xff)
{
ns[1]=ByteToNs(dat);
#ifdef DEBUG
printf("%.2f", ns[1]);
#endif
}
else
{
printf("read SMB error5!\n");
goto Exit;
}
dat=ReadSMBus(0x19); //Byte 25
if (dat != 0xff)
{
ns[2]=ByteToNs(dat);
#ifdef DEBUG
printf("%.2f", ns[2]);
#endif
}
else
{
printf("read SMB error6!\n");
goto Exit;
}
for(i=0; i<3; i++)
{
if (ns[i]>0)
spd[i].MHz = (WORD)(1.0 /(ns[i]*pow(10,-9)) /1000000.0 * DDR+0.5);
else
spd[i].MHz = 0;
}
//--------------------------------------------
//read tCL
//--------------------------------------------
dat=ReadSMBus(0x12); //Byte 18
if (dat != 0xff)
{
if (dat|0xDF == 0xFF)
CLX=5;
else if (dat|0xEF == 0xFF)
CLX=4;
else if (dat|0xF7 == 0xFF)
CLX=3;
else if (dat|0xFB == 0xFF)
CLX=2;
#ifdef DEBUG
printf("CLX=%d", CLX);
#endif
}
else
{
printf("read SMB error7!\n");
goto Exit;
}
for(i=0; i<3; i++)
{
spd[i].tCL = CLX-i;
}
//-------------------------------------------
//read Minimum Active to Precharge Time (tRAS)
//-------------------------------------------
dat=ReadSMBus(0x1E); //Byte 30
if (dat != 0xff)
{
tRAS=dat; //ns
}
else
{
printf("read SMB error8!\n");
goto Exit;
}
for(i=0; i<3; i++)
{
if (ns[i]>0)
spd[i].tRAS=(BYTE)(tRAS/ns[i])+1;
else
spd[i].tRAS=0;
}
//-------------------------------------------
//read Minimum RAS to CAS Delay (tRCD)
//-------------------------------------------
dat=ReadSMBus(0x1D); //Byte 29
if(dat != 0xff)
{
tRCD=ByteToNs2(dat);
#ifdef DEBUG
printf("tRCD=%.2f", tRCD);
#endif
}
else
{
printf("read SMB error9!\n");
goto Exit;
}
for(i=0; i<3; i++)
{
if (ns[i]>0)
spd[i].tRCD=(BYTE)(tRCD/ns[i])+1;
else
spd[i].tRCD=0;
}
//-------------------------------------------
//read Minimum Row Precharge Time(tRP)
//-------------------------------------------
dat=ReadSMBus(0x1B); //Byte 27
if(dat != 0xff)
{
tRP=ByteToNs2(dat);
#ifdef DEBUG
printf("tRP=%.2f", tRP);
#endif
}
else
{
printf("read SMB error10!\n");
goto Exit;
}
for(i=0; i<3; i++)
{
if (ns[i]>0)
spd[i].tRP= (BYTE)(tRP/ns[i])+1;
else
spd[i].tRP= 0;
}
//-------------------------------------------
//read BL
//-------------------------------------------
dat=ReadSMBus(0x16);
if (dat != 0xff)
{
if (dat|0x07 == 0x0F)
BL=8;
else if(dat|0x0B == 0x0F)
BL=4;
}
else
{
printf("read SMB error11!\n");
goto Exit;
}
for(i=0; i<3; i++)
{
spd[i].BL = BL;
}
//------------------------------------------
//Show result
//------------------------------------------
for(i=0;i<3;i++)
{
if (spd[i].MHz > 0)
{
printf("%d MHz, tCL=%d, tRAS=%d, tRCD=%d, tRP=%d, tBL=%d\n", spd[i].MHz, spd[i].tCL, spd[i].tRAS, spd[i].tRCD, spd[i].tRP, spd[i].BL);
}
}
Exit:
printf("Test End!\n");
}