📄 nforcehosts.~inc
字号:
/////////////////////////////////////////////////////////////////////////////////////
// This file is a part of OSCI SMBus engine //
// Support nForce 2, nForce 3 and nForce 4 chipsets //
// //
// Copyright (c) 2005 by Dmitriy Arekhta aka Daemon <DaemonES@gmail.com)> //
// Originally written for LMSensors project by Hans-Frieder Vogt <hfvogt@arcor.de> // //
/////////////////////////////////////////////////////////////////////////////////////
const
PCI_VENDOR_ID_NVIDIA = $10de;
PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS = $0064;
PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS = $0084; PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS = $00D4; PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS = $00E4; PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS = $0052; //nVidia nForce2 SMBus control register definitions NFORCE_PCI_SMB1 = $50; NFORCE_PCI_SMB2 = $54; NVIDIA_SMB_STS_DONE = $80; NVIDIA_SMB_STS_ALRM = $40; NVIDIA_SMB_STS_RES = $20; NVIDIA_SMB_STS_STATUS = $1f; NVIDIA_SMB_PRTCL_WRITE = $00; NVIDIA_SMB_PRTCL_READ = $01; NVIDIA_SMB_PRTCL_QUICK = $02; NVIDIA_SMB_PRTCL_BYTE = $04; NVIDIA_SMB_PRTCL_BYTE_DATA = $06; NVIDIA_SMB_PRTCL_WORD_DATA = $08; NVIDIA_SMB_PRTCL_BLOCK_DATA = $0a; NVIDIA_SMB_PRTCL_PROC_CALL = $0c; NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL = $0d; NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA = $4a; NVIDIA_SMB_PRTCL_PEC = $80; //Other NF_MAX_TIMEOUT = 256;var
nforce2_ids: array[0..4] of tHostID =
(
(VendorID: PCI_VENDOR_ID_NVIDIA; DeviceID: PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS), (VendorID: PCI_VENDOR_ID_NVIDIA; DeviceID: PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS), (VendorID: PCI_VENDOR_ID_NVIDIA; DeviceID: PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS), (VendorID: PCI_VENDOR_ID_NVIDIA; DeviceID: PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS), (VendorID: PCI_VENDOR_ID_NVIDIA; DeviceID: PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) );
function NVIDIA_SMB_PRTCL(base: Word): DWord; //protocol, PEC
begin
result:=base+$00;
end;
function NVIDIA_SMB_STS(base: Word): DWord; //status
begin
result:=base+$01;
end;
function NVIDIA_SMB_ADDR(base: Word): DWord; //address
begin
result:=base+$02;
end;
function NVIDIA_SMB_CMD(base: Word): DWord; //command
begin
result:=base+$03;
end;
function NVIDIA_SMB_DATA(base: Word): DWord; //32 data registers
begin
result:=base+$04;
end;
function NVIDIA_SMB_BCNT(base: Word): DWord; //number of data bytes
begin
result:=base+$24;
end;
function NVIDIA_SMB_ALRM_A(base: Word): DWord; //alarm address
begin
result:=base+$25;
end;
function NVIDIA_SMB_ALRM_D(base: Word): DWord; //2 bytes alarm data
begin
result:=base+$26;
end;
function nforce2_access (var SMBusHost: tSMBusHost; addr, flags: Word; read_write: Byte;
command: Byte; size: DWord; var data: i2c_smbus_data): LongInt;
var
protocol, pec, temp: Byte;
len: Byte; //to keep the compiler quiet timeout, i: DWord;begin
timeout:=0;
if (read_write = I2C_SMBUS_READ) then protocol:=NVIDIA_SMB_PRTCL_READ
else protocol:=NVIDIA_SMB_PRTCL_WRITE;
if ((flags and I2C_CLIENT_PEC) <> 0) then pec:=NVIDIA_SMB_PRTCL_PEC
else pec:=0;
case size of
I2C_SMBUS_QUICK: begin
protocol:=protocol or NVIDIA_SMB_PRTCL_QUICK; read_write:=I2C_SMBUS_WRITE; end; I2C_SMBUS_BYTE: begin if (read_write = I2C_SMBUS_WRITE) then oHWIO.IPortIORef.B[NVIDIA_SMB_CMD(SMBusHost.base)]:=command; protocol:=protocol or NVIDIA_SMB_PRTCL_BYTE; end;
I2C_SMBUS_BYTE_DATA: begin
oHWIO.IPortIORef.B[NVIDIA_SMB_CMD(SMBusHost.base)]:=command; if (read_write = I2C_SMBUS_WRITE) then oHWIO.IPortIORef.B[NVIDIA_SMB_DATA(SMBusHost.base)]:=data.ByteData; protocol:=protocol or NVIDIA_SMB_PRTCL_BYTE_DATA; end; I2C_SMBUS_WORD_DATA: begin oHWIO.IPortIORef.B[NVIDIA_SMB_CMD(SMBusHost.base)]:=command; if (read_write = I2C_SMBUS_WRITE) then begin oHWIO.IPortIORef.B[NVIDIA_SMB_DATA(SMBusHost.base)]:=Byte(data.WordData); oHWIO.IPortIORef.B[NVIDIA_SMB_DATA(SMBusHost.base)+1]:=Byte(data.WordData shr 8); end; protocol:=protocol or NVIDIA_SMB_PRTCL_WORD_DATA or pec; end;
I2C_SMBUS_BLOCK_DATA: begin
result:=-1;
exit;
{oHWIO.IPortIORef.B[NVIDIA_SMB_CMD(SMBusHost.base)]:=command;
if (read_write = I2C_SMBUS_WRITE) then begin len = min_t(u8, data->block[0], 32); outb_p(len, NVIDIA_SMB_BCNT); for (i = 0; i < len; i++) outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i); end; protocol:=protocol or NVIDIA_SMB_PRTCL_BLOCK_DATA or pec;} end; I2C_SMBUS_I2C_BLOCK_DATA: begin result:=-1; exit; {len = min_t(u8, data->block[0], 32); outb_p(command, NVIDIA_SMB_CMD); outb_p(len, NVIDIA_SMB_BCNT); if (read_write = I2C_SMBUS_WRITE) then for (i = 0; i < len; i++) outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i); protocol:=protocol or NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA;} end;
else
result:=-1;
exit;
end;
oHWIO.IPortIORef.B[NVIDIA_SMB_ADDR(SMBusHost.base)]:=((addr and $7f) shl 1);
oHWIO.IPortIORef.B[NVIDIA_SMB_PRTCL(SMBusHost.base)]:=protocol;
temp:=oHWIO.IPortIORef.B[NVIDIA_SMB_STS(SMBusHost.base)];
{while (((temp and NVIDIA_SMB_STS_DONE) = 0) and (timeout <= MAX_TIMEOUT)) do
begin
inc(timeout);
temp:=oHWIO.IPortIORef.B[NVIDIA_SMB_STS(SMBusHost.base)];
end;}
if (not(temp) and NVIDIA_SMB_STS_DONE) <> 0 then
begin
sleep(10); temp:=oHWIO.IPortIORef.B[NVIDIA_SMB_STS(SMBusHost.base)]; end; if (not(temp) and NVIDIA_SMB_STS_DONE) <> 0 then begin sleep(10); //i2c_delay(trunc(HZ/100)); temp:=oHWIO.IPortIORef.B[NVIDIA_SMB_STS(SMBusHost.base)]; end;
if ((timeout >= NF_MAX_TIMEOUT) or ((not(temp) and NVIDIA_SMB_STS_DONE <> 0)) or ((temp and NVIDIA_SMB_STS_STATUS) <> 0)) then
begin
result:=-1;
exit;
end;
if (read_write = I2C_SMBUS_WRITE) then
begin
result:=0;
exit;
end;
case size of
I2C_SMBUS_BYTE, I2C_SMBUS_BYTE_DATA: begin data.ByteData:=oHWIO.IPortIORef.B[NVIDIA_SMB_DATA(SMBusHost.base)]; end; I2C_SMBUS_WORD_DATA: begin //case I2C_SMBUS_PROC_CALL: not supported data.WordData:=oHWIO.IPortIORef.B[NVIDIA_SMB_DATA(SMBusHost.base)] or (oHWIO.IPortIORef.B[NVIDIA_SMB_DATA(SMBusHost.base)+1] shl 8); end; I2C_SMBUS_BLOCK_DATA: begin result:=-1; exit; //case I2C_SMBUS_BLOCK_PROC_CALL: not supported {len:=oHWIO.IPortIORef.B[NVIDIA_SMB_BCNT(SMBusHost.base)]; data.Ptr:=data.Ptr+1; len = min_t(u8, len, 32);} end; I2C_SMBUS_I2C_BLOCK_DATA: begin result:=-1; exit; {for (i = 0; i < len; i++) data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i); data->block[0] = len;} end; end;
result:=0;
end;
function nForceGetHost(var SMBusHosts: tSMBusHosts; var HostsNum: Byte; HostDevice: tPCIDevice): boolean;
var
pdata: Word;
CurrentHost: DWord;
begin
inc(HostsNum);
SetLength(SMBusHosts, HostsNum); CurrentHost:=HostsNum-1; with SMBusHosts[CurrentHost] do begin device.dwBus:=HostDevice.dwBus; device.dwDev:=HostDevice.dwDev; device.dwFunc:=HostDevice.dwFunc; oHWIO.IPCIIORef.GetPCIRWord(device.dwBus, device.dwDev, device.dwFunc, NFORCE_PCI_SMB1, pdata); base:=pdata and $fffc; size:=8; end; inc(HostsNum); SetLength(SMBusHosts, HostsNum); CurrentHost:=HostsNum-1; with SMBusHosts[CurrentHost] do begin device.dwBus:=HostDevice.dwBus; device.dwDev:=HostDevice.dwDev; device.dwFunc:=HostDevice.dwFunc; oHWIO.IPCIIORef.GetPCIRWord(device.dwBus, device.dwDev, device.dwFunc, NFORCE_PCI_SMB2, pdata); base:=pdata and $fffc; size:=8; end;
end;
function nForceFillHostIds: tHostIDs;
var
i: byte;
begin
for i:=Low(nforce2_ids) to High(nforce2_ids) do
begin
SetLength(result, i+1);
result[i].VendorID := nforce2_ids[i].VendorID;
result[i].DeviceID := nforce2_ids[i].DeviceID;
end;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -