|
...(轉自英布之劍的博客)
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<dos.h>
#define DEBUG
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;
#define READ_CLOCK_GEN 0x01
#define WRITE_CLOCK_GEN 0x00
WORD SMB_Base=0;
//----------------------------------------------------------
//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);
}
//----------------------------------------------------------
//Enable 32-Byte buffer
//----------------------------------------------------------
void Enable32ByteBuffer()
{
outportb(SMB_Base+0x0d, inportb(SMB_Base+0x0d)|0x02);
}
//----------------------------------------------------------
//Clear SMBus Status
//----------------------------------------------------------
void ClearSMBusStatus()
{
outportb(SMB_Base+0x00, 0xFE);
}
//----------------------------------------------------------
//Set Slave Address
//----------------------------------------------------------
void SetSlaveAddress(BYTE flag)
{
outportb(SMB_Base+0x04, 0xD2|flag);
}
//----------------------------------------------------------
//set command(index)
//----------------------------------------------------------
void SetCommand(BYTE index)
{
#ifdef DEBUG
printf("Command:%02x\n", index);
#endif
outportb(SMB_Base+0x03, index);
}
//----------------------------------------------------------
//reset index point of 32 Bytes buffer
//----------------------------------------------------------
void ResetIndexPoint()
{
inportb(SMB_Base+0x02);
}
//----------------------------------------------------------
//init block read
//----------------------------------------------------------
void InitBlockReadWrite()
{
outportb(SMB_Base+0x02, 0x54);
}
//----------------------------------------------------------
//write byte count
//----------------------------------------------------------
void SetWriteByteCount(BYTE Count)
{
outportb(SMB_Base+0x05, Count);
}
//----------------------------------------------------------
//set data
//----------------------------------------------------------
void SetData(BYTE data)
{
outportb(SMB_Base+0x07, data);
}
//----------------------------------------------------------
//get byte count
//----------------------------------------------------------
BYTE GetByteCount()
{
return inportb(SMB_Base+0x05);
}
//----------------------------------------------------------
//get data
//----------------------------------------------------------
BYTE GetData()
{
return inportb(SMB_Base+0x07);
}
//----------------------------------------------------------
//read SM Bus
//----------------------------------------------------------
int ReadSMBus(BYTE index)
{
int sts, j;
int count;
//set slave address
SetSlaveAddress(READ_CLOCK_GEN);
delay(1);
//set command
SetCommand(index);
delay(2);
//reset index point
ResetIndexPoint();
delay(1);
//init block read
InitBlockReadWrite();
delay(1);
sts=SMBusReady();
if(sts!=0)
{
return (-1);
}
count=GetByteCount();
printf("Count=%d\n", count);
for(j=0;j<count;j++)
{
printf("%02x ", GetData());
CheckByteDone();
}
printf("\n\n");
return 0;
}
//----------------------------------------------------------
//Write SM Bus
//----------------------------------------------------------
int WriteSMBus(BYTE index, BYTE count)
{
int sts;
//set slave address
SetSlaveAddress(WRITE_CLOCK_GEN);
delay(1);
//set command
SetCommand(index);
delay(2);
//set write byte count
SetWriteByteCount(count);
delay(1);
//reset index point
ResetIndexPoint();
delay(1);
//init block read
InitBlockReadWrite();
delay(1);
sts=SMBusReady();
if(sts!=0)
{
return (-1);
}
return 0;
}
//----------------------------------------------------------
// Main Program
//----------------------------------------------------------
void main()
{
int sts=0;
//--------------------------------------------
//get SMB Base
//--------------------------------------------
SMB_Base =getSMBase();
printf("SMB_Base:%04X\n", SMB_Base);
//--------------------------------------------
//enable 32 byte buffer
//--------------------------------------------
Enable32ByteBuffer();
delay(3);
sts=SMBusReady();
if(sts!=0)
{
printf("SMBus not Ready0!\n");
exit(0);
}
//============================================
//Enable M/N mode (1.read first)
//============================================
if (ReadSMBus(0x1f)==-1)
{
printf("SMBus not Ready1!\n");
exit(1);
}
//---------------- 2. Enable M/N -------------
ResetIndexPoint();
delay(1);
SetData(0x61); //Bit0 set 1 enable
delay(1);
sts=SMBusReady();
if(sts!=0)
{
printf("SMBus not Ready2!\n");
exit(2);
}
// write change value
if (WriteSMBus(0x1f, 1)==-1)
{
printf("SMBus not Ready3!\n");
exit(3);
}
//---------------- 3. read again --------------
if (ReadSMBus(0x1f)==-1)
{
printf("SMBus not Ready4!\n");
exit(4);
}
//============================================
//Change clock (1. read frist)
//============================================
if (ReadSMBus(0x11)==-1)
{
printf("SMBus not Ready5!\n");
exit(5);
}
//---------------- 2. Change it --------------
//reset index point
ResetIndexPoint();
delay(1);
GetData(); //11h
CheckByteDone();
GetData(); //12h
CheckByteDone();
SetData(0xa0); //13h (80*10+0)/6=133.33 -> (80*10+10)/6=135
delay(1);
sts=SMBusReady();
if(sts!=0)
{
printf("SMBus not Ready6!\n");
exit(1);
}
//write change value
if (WriteSMBus(0x11, 3)==-1)
{
printf("SMBus not Ready7!\n\n");
exit(7);
}
//-------------- 3. Read again ---------------
if (ReadSMBus(0x11)==-1)
{
printf("SMBus not Ready8!\n");
exit(5);
}
//============================================
// double check Enable M/N mode (1.read first)
//============================================
if (ReadSMBus(0x1f)==-1)
{
printf("SMBus not Ready9!\n");
exit(1);
}
//---------------- 2. Enable M/N -------------
ResetIndexPoint();
delay(1);
SetData(0x61);
delay(1);
sts=SMBusReady();
if(sts!=0)
{
printf("SMBus not Ready10!\n");
exit(2);
}
//write change value
if (WriteSMBus(0x1f, 1)==-1)
{
printf("SMBus not Ready11!\n");
exit(3);
}
//---------------- 3. read again --------------
if (ReadSMBus(0x1f)==-1)
{
printf("SMBus not Ready12!\n");
exit(4);
}
}
|
|