如何读SPD 信息...(转自英布之剑的博客)

51 篇文章 0 订阅
40 篇文章 2 订阅

之前接到过网友的询问,没有时间回复... 非常抱歉!真正创业的时候,才知道创来是如此不简单... 特别是再也没有这么多空余时间来钻研技术了...

还好,总是能收到网友讨论问题的邮件,让我偶尔还去看一下尘封以久的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");
}

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值