转:SPD 读取

来源:互联网 发布:网络歌手初音真人照片 编辑:程序博客网 时间:2024/05/21 06:40

//COPY LEFT, EVERY LINE IS CHECK FOR LOGICAL RIGHT  
//IF FIND  PROBLEMS IN THIS CODE ,PLEASE LET ME KNOW  
//  
//  
//2009-11-13  
//V1.2  CHANGE AMD SMBus get method  
//v1.1.2 add "a-Data technology"  
//V1.1.1 ADD "Transcend"  
//V1.1 FORMAL RELEAS  
//SERIAL PRESENCE DETECTION OF SO-DIMM  DDRII ADN DDRII  
/*****************************************************************/
#include <stdio.h> 
#include <conio.h> 
#include <dos.h> 
 
#define INTEL  0 
#define NVIDIA 1 
#define AMD 2 
#define ATI 3 
#define Unknow 0xFF 
#define DDRII   0 
#define DDRIII  1  
/*****************************************************************/ 
unsigned char  Platform_flag;  
unsigned char Dimm_flag=0;  
unsigned int SMB_IO_PORT;  
 
struct{  
                unsigned char MType;//DDRII,DDRIII  
                unsigned char SerNum[4];  
                unsigned char ProTime[2];//year since 2000,weeks  
                unsigned char PartNum[19];  
                unsigned int size;  
                char *manu;  
                unsigned int speed;  
                unsigned char address;  
             }Dimm_Info[5];  
unsigned char Dimm_slave[5]={0xA0,0xA2,0xA4,0xA6,0xA8};  
/*****************************************************************/ 
 
unsigned long Get_Pci_Address(unsigned char bus,unsigned char dev,unsigned char fun,unsigned char reg);  
unsigned int Read_Pci_Word(unsigned long address);  
void Check_Platform(void);   //8086 for intel;for nvidia  
void Get_SMB_IO_Port(void );  //  
unsigned char Read_SMB_Byte(unsigned char offset);  
void Check_DDR_Type(void); //DDRII;DDRIII  
void Check_DDR_Size(void);  
void Check_DDR_Speed(void);  
void Check_DDR_Manu(void);  
void GetSerialNumber(void);  
void GetProduceTime(void);  
void GetPartNumber(void);  
void ManuName(unsigned char);  
/*****************************************************************/ 
unsigned long Get_Pci_Address(unsigned char bus,unsigned char dev,unsigned char fun,unsigned char reg)  
{  
    unsigned long address=0,temp=0;  
    address=bus;address<<=16;  
    dev<<=3;  
    fun&=7;  
    reg&=0xFC;  
    temp=dev|fun;temp<<=8;temp|=reg;  
    address=address|temp|0x80000000;  
    return address;  
 }  
/*****************************************************************/ 
unsigned int Read_Pci_Word(unsigned long address)  
{  
    unsigned int result=0;  
    __asm{  
                 mov eax,address  
                 mov dx,0x0CF8  
                 out dx,eax  
                 mov dx,0x0CFC  
                 in  eax,dx  
                 mov result,ax  
                }  
    return result;  
 }  
 /*****************************************************************/ 
unsigned int Write_Pci_Word(unsigned long address,unsigned int data)  
{  
    unsigned int result=0;  
    __asm{  
                 mov eax,address  
                 mov dx,0x0CF8  
                 out dx,eax  
                 mov dx,0x0CFC  
                 mov ax, data  
                 out dx,ax  
                  
                }  
    return result;  
 }  
 /**********************AMD SMBus base address************************************/ 
unsigned int Read_AMD_SMBB(void)  
{  
    //IO access , once a byte, read twice  
    __asm{  
                 mov ax,0X2C  //low byte  
                 mov dx,0x0CD6  
                 out dx,ax  
                 mov dx,0x0CD7  
                 in  al,dx  
                mov bl, al  
                  
                mov ax,0x2D  
                mov dx, 0x0CD6  
                out dx, ax  
                mov dx, 0x0CD7  
                in ah, dx  
                mov al, bl  
                }  
    return _AX;  
 }  
/*****************************************************************/ 
void Check_Platform()  
{  
    unsigned long address=0x80000000;  
    unsigned int VID= Read_Pci_Word(address);  
 
    if(VID==0x8086)  
         Platform_flag=INTEL;  
    else if(VID==0x10DE)  
         Platform_flag=NVIDIA;  
    else if(VID==0x1022)  
        Platform_flag=AMD;//2  
    else if( VID==0X1002)  
        Platform_flag=ATI;//3  
     else 
        {  
            printf("PLATFORM VENDOR ID IS :%04X/n",VID);  
            Platform_flag=Unknow;  
            }  
}  
        /****************************************************/ 
void Get_SMB_IO_Port()  
{//IO MAPPED ENABLED ,IF NOT THEN?  
    if(Platform_flag==INTEL)  
        SMB_IO_PORT=Read_Pci_Word(Get_Pci_Address(0,0x1F,3,0x20)) & 0xFFE0;  
    else if(Platform_flag==NVIDIA)  
        SMB_IO_PORT=Read_Pci_Word(Get_Pci_Address(0,3,2,0x24)) & 0xFFFE;  
    else if(Platform_flag==AMD||Platform_flag==ATI)  
    {  
        //printf("%0.8X/n",Get_Pci_Address(0,0x14,0,90));  
        //SMB_IO_PORT=Read_Pci_Word(Get_Pci_Address(0,0x14,0,0x90))&0xFFF0;//  
        //SMB_IO_PORT=Read_AMD_SMBB()&0xFFE0;//GET SMBus Base address through PM space.  
        SMB_IO_PORT=0xB00;  
        //printf("SMBus base addr. : %04X",SMB_IO_PORT);  
    }  
 }  
/*****************************************************************/ 
unsigned char Read_SMB_Byte(unsigned char offset)  
{  
    unsigned int result=0;  
    if(Platform_flag==INTEL||Platform_flag==AMD||Platform_flag==ATI)  
        {  
 
                         outportb(SMB_IO_PORT+4,Dimm_Info[Dimm_flag].address|1);  
                         outportb(SMB_IO_PORT+3,offset);  
                         outportb(SMB_IO_PORT,0xFE);  
                         outportb(SMB_IO_PORT+2,0x48);  
                         delay(10);  
                    // while(!(inportb(SMB_IO_PORT)&0x02))  
                    // {}  
                         result=inportb(SMB_IO_PORT+5);  
         }  
    else if(Platform_flag==NVIDIA)  
        {  
                         delay(10);  
                         outportb(SMB_IO_PORT+2,Dimm_Info[Dimm_flag].address);  
                         outportb(SMB_IO_PORT+3,offset);  
                         outportb(SMB_IO_PORT+1,0x80);  
                         outportb(SMB_IO_PORT,0x07);//CHECK  THAT DATA IS RETURNED  
                         delay(3);  
                    // while(!(inportb(SMB_IO_PORT)&0x02))  
                     // {}  
                         result=inportb(SMB_IO_PORT+4);  
         }  
    /* 
    else if(Platform_flag==AMD) 
        { 
 
                         outportb(SMB_IO_PORT+4,Dimm_Info[Dimm_flag].address|1); 
                         outportb(SMB_IO_PORT+3,offset); 
                         outportb(SMB_IO_PORT,0xFE); 
                         outportb(SMB_IO_PORT+2,0x48); 
                         delay(10); 
                     // while(!inportb(SMB_IO_PORT)&0x80) 
                        {} 
                         result=inportb(SMB_IO_PORT+5); 
        } 
        */ 
    return result;  
 }  
/*****************************************************************/ 
void Check_DDR_Type()  
{  
    unsigned char offset=0,type=0;  
    offset=0x02;  
    Read_SMB_Byte(offset);  
    type=Read_SMB_Byte(offset);  
    if(type==0x08)  
         Dimm_Info[Dimm_flag].MType=DDRII;  
    else if(type==0x0B)  
     Dimm_Info[Dimm_flag].MType=DDRIII;  
     else Dimm_Info[Dimm_flag].MType=Unknow;  
 }  
/*****************************************************************/ 
void Check_DDR_Size()  
{  
    unsigned char offset_rank,offset_density,offset_0x08;  
    unsigned char density,capacity,Width,BWidth,rank;  
    int value;  
 
    if(Dimm_Info[Dimm_flag].MType==DDRII)  
        {  
            offset_rank=0x05;   //rank  
            rank=(Read_SMB_Byte(offset_rank)&0xF);  
            rank++;  
 
            offset_density=0x1F;  
            density=Read_SMB_Byte(offset_density);//density is the size of each Rank(bitmap)  
            if(density==0x20)  
                 value=128;  
            else if(density==0x40)  
                 value=256;  
            else if(density==0x80)  
                 value=512;  
            else if(density==0x01)  
                 value=1024;  
            else if(density==0x02)  
                 value=2048;  
            else if(density==0x04)  
                 value=4096;  
            else 
                 value=0;  
 
 
            Dimm_Info[Dimm_flag].size=rank * value;  
 
         }  
 
        if(Dimm_Info[Dimm_flag].MType==DDRIII)  
         {  
            offset_density=0x04;//Capacity  
            capacity=Read_SMB_Byte(offset_density);  
            //Capacity  is the total capacity of SDRAM  
            //bank=density;  
            capacity&=0x0F;//b[0:3] at 0x04  
            if(capacity==1)  
                value=512;  
            else if(capacity==2)  
                value=1024;  
            else if(capacity==3)  
                value=2048;  
            else if(capacity==4)  
                value=4096;  
            else if(capacity==5)  
                value=8192;  
            else if(capacity==6)  
                value=16384;  
            else    value=256;  
            //printf("Value:   %d/n",value);//TEST PURPOSE  
            offset_rank=0x07;//Rank  
            rank=Read_SMB_Byte(offset_rank);  
            Width=rank;  
            Width&=0x07;//b[0:2] at 0x07  
            rank&=0x38;//00111000 , b[3:5] at 0x07  
            rank=rank>>3;  
            rank++;  
            /*if(rank==0) 
                    rank=1; 
            else if(rank==0x08) 
                    rank=2; 
            else if(rank==0x10) 
                    rank=3; 
            else if(rank==0x18) 
                    rank=4; 
            */ 
            switch(Width)  
            {  
                case 0:Width=4;   break;  
                case 1:Width=8; break;  
                case 2:Width=16;    break;  
                case 3:Width=32;    break;  
            }  
            offset_0x08=0x08;  
            BWidth=Read_SMB_Byte(offset_0x08);  
            BWidth&=0x07;//b[0:2] at 0x08  
            switch(BWidth)  
            {  
                case 0:BWidth=8;   break;  
                case 1:BWidth=16; break;  
                case 2:BWidth=32; break;  
                case 3:BWidth=64; break;  
            }  
            //printf("Rank:      0x%02X/nBWidth:        0x%02X/nWidth:         0x%02X/n",rank,BWidth,Width);//TEST  
            Dimm_Info[Dimm_flag].size=(value/8)*BWidth/Width*rank;  
            }  
 
 }  
/*****************************************************************/ 
void Check_DDR_Speed()  
{  
     unsigned char cycle=0,offset=0;  
 
     if(Dimm_Info[Dimm_flag].MType==DDRII)  
         {  
             offset=0x09;  
             cycle=Read_SMB_Byte(offset);  
             if(cycle==0x50)  
                 Dimm_Info[Dimm_flag].speed=400;  
             else if(cycle==0x3D)  
                 Dimm_Info[Dimm_flag].speed=533;  
             else if(cycle==0x30)  
                 Dimm_Info[Dimm_flag].speed=667;  
             else if(cycle==0x25)  
                 Dimm_Info[Dimm_flag].speed=800;  
            }  
else     if(Dimm_Info[Dimm_flag].MType==DDRIII)  
        {  
             offset=0x0C;  
             cycle=Read_SMB_Byte(offset);  
             if(cycle==0x14)  
                 Dimm_Info[Dimm_flag].speed=800;  
             else if(cycle==0x0F)  
                 Dimm_Info[Dimm_flag].speed=1066;  
             else if(cycle==0x0C)  
                 Dimm_Info[Dimm_flag].speed=1333;  
             else if(cycle==0x0A)  
                 Dimm_Info[Dimm_flag].speed=1600;  
         }  
 }  
/*****************************************************************/ 
void Check_DDR_Manu()  
{  
    unsigned char offset=0,manu=0;  
    if(Dimm_Info[Dimm_flag].MType==DDRII)  
    {  
         offset=0x40;  
         if((manu=Read_SMB_Byte(offset))==0x7F)  
            {//bank one  
                offset++;  
                if((manu=Read_SMB_Byte(offset))==0x7F)  
                    {//banktwo  
                        offset++;  
                        if((manu=Read_SMB_Byte(offset))==0x7F)  
                        {//bankthree  
                            offset++;  
                            if((manu=Read_SMB_Byte(offset))==0x7F)  
                            {//bankfour  
                                offset++;  
                                manu=Read_SMB_Byte(offset);  
                            }  
                        }  
                    }  
                }  
 
    }  
    if(Dimm_Info[Dimm_flag].MType==DDRIII)  
    {  
         offset=0x76;  
        manu=Read_SMB_Byte(offset);  
 
    }  
    ManuName(manu);  
 }  
 
/*****************************************************************/ 
void ManuName(unsigned char manu)  
{  
    //////////////////ID AND NAME ////////////////////  
    if(manu==0xAD)  
        Dimm_Info[Dimm_flag].manu="Hynix";  
    else if(manu==0xCE)  
        Dimm_Info[Dimm_flag].manu="SamSung";  
    else if(manu==0x0B)  
        Dimm_Info[Dimm_flag].manu="Nanya";  
    else if(manu==0xFE)  
        Dimm_Info[Dimm_flag].manu="Elpida";  
    else if(manu==0x2C)  
        Dimm_Info[Dimm_flag].manu="Micron";  
    else if(manu==0x98)  
        Dimm_Info[Dimm_flag].manu="Kingston";  
    else if(manu==0x25)  
        Dimm_Info[Dimm_flag].manu="Kingmax";  
    else if(manu==0x4f)  
        Dimm_Info[Dimm_flag].manu="Transcend";  
    else if(manu==0xCB)  
        Dimm_Info[Dimm_flag].manu="A-DATA Technology";  
    else 
    {  
        Dimm_Info[Dimm_flag].manu="Unknow";  
        printf("The Unknow Memory Vendor ID is %02X/n",manu);  
    }  
}  
void GetSerialNumber()  
{  
     unsigned char offset=0x5F,i;  
        Read_SMB_Byte(offset);  
     if(Dimm_Info[Dimm_flag].MType==DDRIII)  
        {  
            offset=0x7A;  
        }  
                 for(i=0;i<4;i++)  
                     {  
                         Dimm_Info[Dimm_flag].SerNum[i]=Read_SMB_Byte(offset);  
                        delay(10);  
                         offset++;  
                    }  
}  
 
void GetProduceTime()  
{  
    unsigned char offset=0x5D,i;  
     if(Dimm_Info[Dimm_flag].MType==DDRIII)  
     {  
        offset=0x78;  
     }  
        for(i=0;i<2;i++)  
        {  
            Dimm_Info[Dimm_flag].ProTime[i]=Read_SMB_Byte(offset);  
            delay(10);  
            offset++;  
        }  
 
}  
 
void GetPartNumber()  
{  
    unsigned char offset=0x49,i;  
    if(Dimm_Info[Dimm_flag].MType==DDRIII)  
    {  
        offset=0x80;  
    }  
    for(i=0;i<18;i++)  
    {  
        Dimm_Info[Dimm_flag].PartNum[i]=Read_SMB_Byte(offset);  
        delay(10);  
        offset++;  
    }  
    Dimm_Info[Dimm_flag].PartNum[i]='/0';  
}  
/*****************************************************************/ 
int main()  
{  
    unsigned char i;  
    unsigned int total_memory=0;  
    printf("********************************************************************/n");  
    printf("*                 READ  SO-DIMM MEMORY INFORMATION          v1.2   */n");  
    printf("*                                             BY     Claude Shi    */n");  
    printf("********************************************************************/n");  
    printf("                      Memory Information/n");  
 
    Check_Platform();  
    if(Platform_flag==INTEL)  
        printf("PlatForm  : INTEL     ");  
    else if(Platform_flag==NVIDIA)  
        printf("PlatForm  : NVIDIA    ");  
    else if(Platform_flag==AMD)  
        printf("Platform  : AMD       ");  
    else if(Platform_flag==ATI)  
        printf("Platform  : ATI       ");  
    else if(Platform_flag==Unknow)  
        printf("PlatForm  : Unknow/n");  
    Get_SMB_IO_Port();  
        printf("IO Address: 0x%0.4X/n",SMB_IO_PORT);  
 
/*************************************************************/ 
 
            for(Dimm_flag=0;Dimm_flag<5;Dimm_flag++)  
             {  
 
                Dimm_Info[Dimm_flag].address=Dimm_slave[Dimm_flag];  
                Check_DDR_Type(); //DDRII OR DDRIII  
                if(Dimm_Info[Dimm_flag].MType==Unknow) continue;  
                Check_DDR_Size();//memeory size  
 
                Check_DDR_Speed();//frequence  
                Check_DDR_Manu();  
                GetPartNumber();  
                GetSerialNumber();  
                GetProduceTime();  
            }  
 // getch();  
    printf("********************************************************************/n");  
    /************************************************/ 
    for(Dimm_flag=0;Dimm_flag<5;Dimm_flag++)  
    {  
        if(Dimm_Info[Dimm_flag].size!=0)  
            {  
                 printf("DIMM [0x%0.2X]:      ",Dimm_slave[Dimm_flag]);  
                if(Dimm_Info[Dimm_flag].MType==DDRII)  
                    printf("DDRII-");  
                else if(Dimm_Info[Dimm_flag].MType==DDRIII)  
                    printf("DDRIII-");  
                 printf("%-7s %dMhz %dM/n",Dimm_Info[Dimm_flag].manu,Dimm_Info[Dimm_flag].speed,Dimm_Info[Dimm_flag].size);  
                 total_memory+=Dimm_Info[Dimm_flag].size;  
                 /******Serial Number**********/ 
                 printf("Serial Number is: ");  
                 for(i=0;i<4;i++)  
                 {  
                    printf("%02X",Dimm_Info[Dimm_flag].SerNum[i]);  
                 }  
                 printf("/n");  
                /************** Produce Time *****************/ 
                printf("Produce Time is:  ");  
                printf("Year: 20%02x, Week: %x/n",  
                Dimm_Info[Dimm_flag].ProTime[0],Dimm_Info[Dimm_flag].ProTime[1]);  
                /*************** Part Number *****************************/ 
                printf("Part Number is:   ");  
                printf("%s/n",Dimm_Info[Dimm_flag].PartNum);  
                printf("********************************************************************/n");  
             }//if  
     }  
    printf("Total Size: %dM",total_memory);  
    return 0;  


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sxc_ujs/archive/2010/05/20/5611661.aspx