转: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
- 转:SPD 读取
- smbus读取spd方法
- SPD
- WINDOWS下通过DRIVER方式直接读取内存条的SPD的实用程序
- SDRAM SPD
- SPD系统
- 如何读SPD 信息...(转自英布之剑的博客)
- 如何读SPD 信息...(转自英布之剑的博客)
- DDR2 DIMM SPD Definition
- SPD (SMBUS)
- DRAM SPD基础知识
- smbus访问SPD
- SPD工作流部署失败解决
- SPD之解CQ总结
- SAS9 技术 --SPD引擎
- 用好你的内存之SPD
- SPD中隐藏固定的行~
- 使用 ipsec-tools 设置 SAD 和 SPD
- 2010收获较大
- ubuntu9.04安装中文输入法
- 解决CreateProcess 路径带空格问题
- 当一名好的教师不容易
- Linux入门——不用安装就可以轻松学Linux
- 转:SPD 读取
- Graphviz介绍
- Valgrind使用简介
- linux命令小记1
- 【我所認知的BIOS】—>Super IO
- 【Android】获取手机中已安装apk文件信息(PackageInfo、ResolveInfo)(应用图片、应用名、包名等)
- Linux改变文件或目录的访问权限相关命令
- 利用Graphviz 画结构图
- Win7 多层路由器问题 -- 应急处理