PCI设备驱动和相关知识

在研究黑苹果驱动时,经常会看到修改Info.plist中的IOPCIMatch字段。需要研究一下相关内容。

PCI是一种外设部件互连标准总线,和USB总线差不多,可以将不同类型的设备连接到同一条总线上。

常见的PCI设备有显卡,网卡,声卡,IDE控制器,AHCI控制器,USB控制器等。

符合PCI标准的设备,都必须有一个VID和DID,在Windows设备管理器中,可以很方便地查看设备的硬件ID。

下图以网卡为例:

PCI设备驱动和相关知识_第1张图片

设备ID以PCI开头,表示这是PCI设备,VEN_10EC&DEV_8168,表示设备的VID=0x10EC,DID=0x8168。

VID是标识厂商的唯一代码,不同厂商是不同的,由一个神秘组织维护这些VID。知道VID就知道厂商名称。

比如0x10EC是RealTek,0x10DE是Nvidia,0x8086是Intel。

DID是标识不同的设备代码,相同厂商有不同和设备,需要用DID来区分。

比如这里的0x8168就是Realtek的以太网卡设备,Realtek还有声卡等其它设备,具有不同的DID。

一般情况下用VID和DID就可以匹配设备驱动程序了。

除此之外,还有Subsystem ID和Revision ID和Class Code。

Subsystem ID是次要的设备识别码,作用与VID和DID相同,长度为4字节。

Revision ID是版本号,长度为1字节。

Class Code是设备类型代码,由神秘组织定义的设备类型代码,长度为3字节。

关于设备类型代码,在这里有说明:http://pci-ids.ucw.cz/read/PD

 

================================================

大概了解了PCI设备的知识后,再来看看Windows驱动程序,Windows驱动一般由一个sys文件和inf文件组成。

inf描述了设备驱动程序的安装过程,以及对应的设备ID。

我找来了刚才的网卡驱动,找到里面关于设备ID的字段如下(部分内容):

;8168B
%RTL8168.DeviceDesc%    = RTL8168.ndi,      PCI\VEN_10EC&DEV_8168&REV_01
%RTL8168.DeviceDesc%    = RTL8168.ndi,      PCI\VEN_10EC&DEV_8168&SUBSYS_816810EC&REV_01
;8112
%RTL8112.DeviceDesc%    = RTL8168.ndi,      PCI\VEN_10EC&DEV_8168&SUBSYS_83851043&REV_01

;8168D
%RTL8168D.DeviceDesc%   = RTL8168D.ndi,     PCI\VEN_10EC&DEV_8168&REV_03
%RTL8168D.DeviceDesc%   = RTL8168D.ndi,     PCI\VEN_10EC&DEV_8168&SUBSYS_816810EC&REV_03
;8112L
%RTL8112L.DeviceDesc%   = RTL8168D.ndi,     PCI\VEN_10EC&DEV_8168&SUBSYS_83A31043&REV_03

;8168E
%RTL8168E.DeviceDesc%   = RTL8168E.ndi,     PCI\VEN_10EC&DEV_8168&REV_06
%RTL8168E.DeviceDesc%   = RTL8168E.ndi,     PCI\VEN_10EC&DEV_8168&SUBSYS_816810EC&REV_06

从这里可以看出来,当设备的VID和DID是相同的时候,还需要由SUBSYS和REV来区分不同的版本。

Windows安装驱动程序的时候,会检测到我的网卡ID符合下面这条内容:

%RTL8168E.DeviceDesc%   = RTL8168E.ndi,     PCI\VEN_10EC&DEV_8168&REV_06

因此会为我的网卡安装这个驱动程序。

 

========================================================

那么再看看Mac OS X系统下面的驱动程序:

一个Mac系统的驱动程序是一个后缀为.kext的文件夹,里面有Content和Info.plist。

关于设备描述的内容在Info.plist里面,如何匹配设备标识,先看一下开发者文档吧。

苹果开发者文档里更具体的描述:https://developer.apple.com/documentation/kernel/iopcidevice?language=objc

IOPCIMatch:匹配设备VID和DID,或者子系统ID

IOPCIPrimaryMatch:匹配VID和DID

IOPCISecondaryMatch:匹配子系统ID

IOPCIClassMatch:匹配设备类型代码,默认掩码0xFFFFFF00

IONameMatch:匹配设备名称

我找来了几个驱动为参照:

IOPCIMatch
0x10EA8086 0x10EB8086 0x10EF8086 0x10F08086 0x15028086 0x15038086 0x153A8086 0x153B8086 0x155A8086 0x15598086 0x15A08086 0x15A18086 0x15A28086 0x15A38086 0x156F8086 0x15708086 0x15B78086 0x15B88086 0x15D78086 0x15D88086 0x15E38086 0x15D68086 0x15BD8086 0x15BE8086 0x15BB8086 0x15BC8086 0x15DF8086 0x15E08086 0x15E18086 0x15E28086

这里是IOPCIMatch方式,这个驱动支持的设备ID不止一个。

其中0x10EA8086表示VID=0x8060,DID=0x10EA的设备。

 

再来看这个AppleHDA驱动里的:

IOClass
AppleHDAController
IOPCIClassMatch
0x04020000&0xFFFE0000

IOPCIClassMatch匹配设备类型值:0x04020000&0xFFFE0000

表示掩码0xFFFE000表示用你的PCI设备类型值“按位与”计算出的结果等于0x04020000则匹配成功。

注意:0x0402&0xFFFE和0x0403&0xFFFE结果都是0x0402,所以这个HDA驱动对类型为0x0402和0x0403都有效。

从类型值表查到0x04表示多媒体设备,0x02/0x03表示Computer telephony device/Audio device

 

再来看设备名称匹配,比如这样的:

IONameMatch

EHC1
EHC2

这里的ECH1和EHC2就是表示USB 2.0控制器设备,这个名字从哪里来的呢?

我猜是DSDT吧,因为从导出的DSDT文件里有EHC1这个名字,还有对应的设备地址等信息。

 

除此之外还有这样匹配设备名的,看上去像VID和DID号:

IOClass
    BCM5701Enet
	IOMatchCategory
	IODefaultMatchCategory
	IONameMatch
	
		pci14e4,1641
		pci14e4,1642
		pci14e4,1643
		pci14e4,1644
		pci14e4,1645
    

kext驱动文件有两个标准目录一个是/L/E,另一个是/S/L/E,

/L/E目录是第三方驱动的存放路径,建议自己的驱动都放这里。

/S/L/E是苹果原生驱动的路径。

安装方法是把kext复制到/L/E目录,然后修复权限,参考命令如下:

sudo cp -R demo.kext /Library/Extensions/
sudo chown -R root:wheel /Library/Extensions/demo.kext
sudo touch /Library/Extensions/

 

你可能感兴趣的:(Windows,MacOS,学习笔记,PCI,设备驱动)