WinRing0 介绍
WinRing0 是一个完全免费开源的组件( BSD License ), 允许windows程序直接对I/O端口进行存取操作。
通过使用一种内核模式的设备驱动器和其它几种底层编程技巧,它绕过了Windows系统的保护机制。
这里简单写一个读取SIO芯片型号、CPU风扇转速的小程序作为例子
开发环境
开发工具:Visual studio 2017 Windows 10
WinRing0 请自行google下载
准备工作
新建项目,省略…
将下载好的WinRing0驱动文件放到项目/bin/Debug目录
将OpenLibSys.cs放到项目根目录
编码
代码太多这里只贴出一些关键点
创建一个TestByWinRing0类,用来调用WinRing0的接口,先初始化
1
2
3
4
5public bool Initialize()
{
MyOls = new OpenLibSys.Ols();
return MyOls.GetStatus() == (uint)OpenLibSys.Ols.Status.NO_ERROR;
}根据SuperIO(IT8786)芯片手册查找需要的IO端口
sio芯片入口地址(87,01,55,55)
1
2
3
4
5
6
7public void InitSuperIO()
{
MyOls.WriteIoPortByte(SuperIO.REG, 0x87);
MyOls.WriteIoPortByte(SuperIO.REG, 0x01);
MyOls.WriteIoPortByte(SuperIO.REG, 0x55);
MyOls.WriteIoPortByte(SuperIO.REG, 0x55);
}读取SIO芯片型号
芯片型号是16位,由两个字节组成地址20h,21h
1
2
3
4
5
6
7
8
9private static int SuperIo_Inw(byte data)
{
int val;
MyOls.WriteIoPortByte(0x2e, data++);
val = MyOls.ReadIoPortByte(0x2f) << 8;
MyOls.WriteIoPortByte(0x2e, data);
val |= MyOls.ReadIoPortByte(0x2f);
return val;
}配置风扇控制寄存器,风扇属于环境控制器,LDN=04h,控制器激活地址30h
EC控制器基地址是16位,两个字节,分别由高位60h,低位61h组成
配置寄存器地址Base+05h,配置寄存器数据地址Base+06h
配置风扇转速控制寄存器,地址0C
1
2
3
4
5
6
7
8
9
10
11
12public void InitEc()
{
MyOls.WriteIoPortByte(0x2e, 0x07);
MyOls.WriteIoPortByte(0x2f, 0x04);
MyOls.WriteIoPortByte(0x2e, 0x30);
MyOls.WriteIoPortByte(0x2f, 0x01);
ushort ec_base = (ushort)SuperIo_Inw(0x60);
ec_addr_port = (ushort)(ec_base + 0x05);
ec_data_port = (ushort)(ec_base + 0x06);
MyOls.WriteIoPortByte(ec_addr_port, 0x0c);
MyOls.WriteIoPortByte(ec_data_port, 0x00);
}读取风扇转速
风扇转速保存在16位数据里,由两个8位数据保存
上面提到转速控制寄存器,使用的第一组风扇,地址0e
风扇转速计算公式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public int GetFanRpm()
{
int fan_speed = 0;
int fan_rpm = 0;
//2-3 Reading Registers[7:0] (Index=0Eh-0Fh)
MyOls.WriteIoPortByte(ec_addr_port, 0x0e);
byte lval = MyOls.ReadIoPortByte(ec_data_port);
//2-3 Extended Reading Registers [15:8] (Index=19h-1Ah)
MyOls.WriteIoPortByte(ec_addr_port, 0x19);
byte mval = MyOls.ReadIoPortByte(ec_data_port);
fan_speed = (mval << 8) | lval;
Console.WriteLine("fan_speed:" + fan_speed);
fan_rpm = (int)(1.35 * Math.Pow(10, 6) / (fan_speed * 2));
return fan_rpm;
}程序运行效果如下