unit VIAProHosts;
interface
{$define OMCDrv}
//{$define ATTDrv}
uses
i2c_h, i2c_dev,
{$ifdef OMCDrv}
OMCDrv,
{$endif}
{$ifdef ATTDrv}
ATTDrv,
{$endif}
hPCI,
Windows,
SysUtils;
function VIAPro_access (
var SMBusHost: tSMBusHost; addr, flags: Word; read_write: Byte;
command: Byte; size: DWord;
var data: i2c_smbus_data): LongInt;
function VIAProGetHost(
var SMBInterfaces: tSMBInterfaces;
var HostsNum: Byte; HostDevice: tPCIDevice): boolean;
function VIAProFillHostIds: tHostIDs;
implementation
const
SMBBA1 = $90;
SMBBA2 = $80;
SMBBA3 = $D0;
//Other settings
MAX_TIMEOUT = 500;
ENABLE_INT9 = 0;
//VT82C596 constants
VT596_QUICK = $00;
VT596_BYTE = $04;
VT596_BYTE_DATA = $08;
VT596_WORD_DATA = $0C;
VT596_BLOCK_DATA = $14;
PCI_VENDOR_ID_VIA = $1106;
PCI_DEVICE_ID_VIA_82C596_3 = $3050;
PCI_DEVICE_ID_VIA_82C596B_3 = $3051;
PCI_DEVICE_ID_VIA_82C686_4 = $3057;
PCI_DEVICE_ID_VIA_8231_4 = $8235;
PCI_DEVICE_ID_VIA_8233_0 = $3074;
PCI_DEVICE_ID_VIA_8233A = $3147;
PCI_DEVICE_ID_VIA_8235 = $3177;
PCI_DEVICE_ID_VIA_8237 = $3227;
var
viapro_ids:
array[0..7]
of tHostID =
(
(VendorID: PCI_VENDOR_ID_VIA; DeviceID: PCI_DEVICE_ID_VIA_82C596_3),
(VendorID: PCI_VENDOR_ID_VIA; DeviceID: PCI_DEVICE_ID_VIA_82C596B_3),
(VendorID: PCI_VENDOR_ID_VIA; DeviceID: PCI_DEVICE_ID_VIA_82C686_4),
(VendorID: PCI_VENDOR_ID_VIA; DeviceID: PCI_DEVICE_ID_VIA_8231_4),
(VendorID: PCI_VENDOR_ID_VIA; DeviceID: PCI_DEVICE_ID_VIA_8233_0),
(VendorID: PCI_VENDOR_ID_VIA; DeviceID: PCI_DEVICE_ID_VIA_8233A),
(VendorID: PCI_VENDOR_ID_VIA; DeviceID: PCI_DEVICE_ID_VIA_8235),
(VendorID: PCI_VENDOR_ID_VIA; DeviceID: PCI_DEVICE_ID_VIA_8237)
);
//PCI Address Constants
//SMBus data in configuration space can be found in two places,
//We try to select the better one
smb_cf_hstcfg: Word;
function SMBHSTCFG(smb_cf_hstcfg: Word): Word;
begin
result:=smb_cf_hstcfg;
end;
function SMBSLVC(smb_cf_hstcfg: Word): Word;
begin
result:=smb_cf_hstcfg + 1;
end;
function SMBSHDW1(smb_cf_hstcfg: Word): Word;
begin
result:=smb_cf_hstcfg + 2;
end;
function SMBSHDW2(smb_cf_hstcfg: Word): Word;
begin
result:=smb_cf_hstcfg + 3;
end;
function SMBREV(smb_cf_hstcfg: Word): Word;
begin
result:=smb_cf_hstcfg + 4;
end;
//SMBus address offsets
function SMBHSTSTS(base: Word): DWord;
begin
result:=base+0;
end;
function SMBHSLVSTS(base: Word): DWord;
begin
result:=base+1;
end;
function SMBHSTCNT(base: Word): DWord;
begin
result:=base+2;
end;
function SMBHSTCMD(base: Word): DWord;
begin
result:=base+3;
end;
function SMBHSTADD(base: Word): DWord;
begin
result:=base+4;
end;
function SMBHSTDAT0(base: Word): DWord;
begin
result:=base+5;
end;
function SMBHSTDAT1(base: Word): DWord;
begin
result:=base+6;
end;
function SMBBLKDAT(base: Word): DWord;
begin
result:=base+7;
end;
function SMBSLVCNT(base: Word): DWord;
begin
result:=base+8;
end;
function SMBSHDWCMD(base: Word): DWord;
begin
result:=base+9;
end;
function SMBSLVEVT(base: Word): DWord;
begin
result:=base+$A;
end;
function SMBSLVDAT(base: Word): DWord;
begin
result:=base+$C;
end;
function vt596_transaction(Base: Word): LongInt;
var
tmp: Byte;
temp, res, timeout: integer;
begin
res:=0;
timeout:=0;
tmp:=GetInstance.IPortIORef.B[SMBHSTCNT(Base)];
tmp:=GetInstance.IPortIORef.B[SMBHSTCMD(Base)];
tmp:=GetInstance.IPortIORef.B[SMBHSTADD(Base)];
tmp:=GetInstance.IPortIORef.B[SMBHSTDAT0(Base)];
tmp:=GetInstance.IPortIORef.B[SMBHSTDAT1(Base)];
tmp:=0;
//Make sure the SMBus host is ready to start transmitting
temp:=GetInstance.IPortIORef.B[SMBHSTSTS(Base)];
//ShowMessage(format('%x', [temp]));
if (temp
and $1F) <> 0
then
begin
//ShowMessage('Here');
GetInstance.IPortIORef.B[SMBHSTSTS(Base)]:=temp;
temp:=GetInstance.IPortIORef.B[SMBHSTSTS(Base)];
if (temp
and $1F) <> 0
then
begin
result:=-1;
exit;
end;
end;
//start the transaction by setting bit 6
tmp:=GetInstance.IPortIORef.B[SMBHSTCNT(Base)];
GetInstance.IPortIORef.B[SMBHSTCNT(Base)]:=tmp
or $40;
//We will always wait for a fraction of a second!
//I don't know if VIA needs this, Intel did
repeat
sleep(1);
temp:=GetInstance.IPortIORef.B[SMBHSTSTS(Base)];
inc(timeout);
until not(((temp
and $01)<>0)
and (timeout < MAX_TIMEOUT));
//If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT)
then res:=-1;
if (temp
and $10) <> 0
then res:=-1;
if (temp
and $08) <>0
then res:=-1;
//Clock stops and slave is stuck in mid-transmission
if (temp
and $04) <> 0
then res:=-1;
temp:=GetInstance.IPortIORef.B[SMBHSTSTS(Base)];
if (temp
and $1F) <> 0
then
begin
GetInstance.IPortIORef.B[SMBHSTSTS(Base)]:=temp;
temp:=GetInstance.IPortIORef.B[SMBHSTSTS(Base)];
end;
tmp:=GetInstance.IPortIORef.B[SMBHSTCNT(Base)];
tmp:=GetInstance.IPortIORef.B[SMBHSTCMD(Base)];
tmp:=GetInstance.IPortIORef.B[SMBHSTADD(Base)];
tmp:=GetInstance.IPortIORef.B[SMBHSTDAT0(Base)];
tmp:=GetInstance.IPortIORef.B[SMBHSTDAT1(Base)];
result:=res;
end;
function VIAPro_access(
var SMBusHost: tSMBusHost; addr, flags: Word; read_write: Byte;
command: Byte; size: DWord;
var data: i2c_smbus_data): LongInt;
begin
case size
of
I2C_SMBUS_QUICK:
begin
GetInstance.IPortIORef.B[SMBHSTADD(SMBusHost.base)]:=((addr
and $7f)
shl 1)
or (read_write
and $01);
size:=VT596_QUICK;
end;
I2C_SMBUS_BYTE:
begin
GetInstance.IPortIORef.B[SMBHSTADD(SMBusHost.base)]:=((addr
and $7f)
shl 1)
or (read_write
and $01);
if (read_write = I2C_SMBUS_WRITE)
then GetInstance.IPortIORef.B[SMBHSTCMD(SMBusHost.base)]:=command;
size:=VT596_BYTE;
end;
I2C_SMBUS_BYTE_DATA:
begin
GetInstance.IPortIORef.B[SMBHSTADD(SMBusHost.base)]:=((addr
and $7f)
shl 1)
or (read_write
and $01);
GetInstance.IPortIORef.B[SMBHSTCMD(SMBusHost.base)]:=command;
if (read_write = I2C_SMBUS_WRITE)
then GetInstance.IPortIORef.B[SMBHSTDAT0(SMBusHost.base)]:=data.ByteData;
size:=VT596_BYTE_DATA;
end;
I2C_SMBUS_WORD_DATA:
begin
GetInstance.IPortIORef.B[SMBHSTADD(SMBusHost.base)]:=((addr
and $7f)
shl 1)
or (read_write
and $01);
GetInstance.IPortIORef.B[SMBHSTCMD(SMBusHost.base)]:=command;
if (read_write = I2C_SMBUS_WRITE)
then
begin
GetInstance.IPortIORef.B[SMBHSTDAT0(SMBusHost.base)]:=data.WordData
and $ff;
GetInstance.IPortIORef.B[SMBHSTDAT1(SMBusHost.base)]:=(data.WordData
and $ff00)
shr 8;
end;
size:=VT596_WORD_DATA;
end;
end;
GetInstance.IPortIORef.B[SMBHSTCNT(SMBusHost.base)]:=(size
and $1C) + (ENABLE_INT9
and 1);
if vt596_transaction(SMBusHost.base)=-1
then
begin
result:=-1;
exit;
end;
if ((read_write = I2C_SMBUS_WRITE)
or (size = VT596_QUICK))
then
begin
result:=0;
exit;
end;
case size
of
VT596_BYTE:
begin
//Where is the result put? I assume here it is in
//SMBHSTDAT0 but it might just as well be in the
//SMBHSTCMD. No clue in the docs
data.ByteData:=GetInstance.IPortIORef.B[SMBHSTDAT0(SMBusHost.base)];
end;
VT596_BYTE_DATA:
begin
data.ByteData:=GetInstance.IPortIORef.B[SMBHSTDAT0(SMBusHost.base)];
end;
VT596_WORD_DATA:
begin
data.WordData:=GetInstance.IPortIORef.B[SMBHSTDAT0(SMBusHost.base)]+(GetInstance.IPortIORef.B[SMBHSTDAT1(SMBusHost.base)]
shl 8);
end;
end;
end;
function VIAProGetHost(
var SMBInterfaces: tSMBInterfaces;
var HostsNum: Byte; HostDevice: tPCIDevice): boolean;
var
DeviceID, wdata: Word;
pdata: DWord;
BaseAddr: Byte;
CurrentHost: DWord;
begin
inc(HostsNum);
SetLength(SMBInterfaces, HostsNum);
CurrentHost:=HostsNum-1;
GetInstance.IPCIIORef.GetPCIRDWord(HostDevice.DevRegs.dwBus, HostDevice.DevRegs.dwDev, HostDevice.DevRegs.dwFunc, 0, pdata);
DeviceID:=Word(pdata
shr 16);
case DeviceID
of
PCI_DEVICE_ID_VIA_82C596_3: BaseAddr:=SMBBA1;
PCI_DEVICE_ID_VIA_82C596B_3: BaseAddr:=SMBBA1;
PCI_DEVICE_ID_VIA_82C686_4: BaseAddr:=SMBBA1;
PCI_DEVICE_ID_VIA_8233_0: BaseAddr:=SMBBA3;
PCI_DEVICE_ID_VIA_8233A: BaseAddr:=SMBBA3;
PCI_DEVICE_ID_VIA_8235: BaseAddr:=SMBBA3;
PCI_DEVICE_ID_VIA_8237: BaseAddr:=SMBBA3;
PCI_DEVICE_ID_VIA_8231_4: BaseAddr:=SMBBA1;
end;
GetInstance.IPCIIORef.GetPCIRWord(HostDevice.DevRegs.dwBus, HostDevice.DevRegs.dwDev, HostDevice.DevRegs.dwFunc, BaseAddr, wdata);
//if not (wdata and 1) <> 0) then
wdata:=wdata
and $fff0;
SMBInterfaces[CurrentHost].SMBusHosts.base:=wdata;
//ShowMessage(format('%x', [wdata]));
end;
function VIAProFillHostIds: tHostIDs;
var
i: byte;
begin
for i:=Low(viapro_ids)
to High(viapro_ids)
do
begin
SetLength(result, i+1);
result[i].VendorID := viapro_ids[i].VendorID;
result[i].DeviceID := viapro_ids[i].DeviceID;
end;
end;
end.