一直没弄明白“功能”这个参数代表啥,总算明白了。见下。好文章要存下来。。
Bus Number
Device Number
Function Number
Register Number
There are up to 256 available Buses on a PCI system, most commonly all the cards and chips will be located on Bus 0 and Bus 1.
When scanning for hardware, it's a good idea to scan all 256 buses as it won't take that much additional time.
A Device is a physical thing on the PCI bus. It could be a video card, an ethernet card, a Northbridge, anything. There is a software maximum of 32 devices that can exist on each bus. The physical hardware limit is much lower than this due to electrical loading issues, but we won't get into that.
Devices on a motherboard are typically scattered throughout the 32 devices, holes can and will exist. Your software must scan all 32 devices on each bus.
All devices have at least 1 function. Multi-function devices, such as a combination modem/soundcard will usually have 2 devices, typically numbered 0 and 1. There are 8 possible functions per device, numbered 0-7. Any device that has more than 1 function is (hey clever!) called a multi-function device. Functions start numbering at 0 and work up to 7.
Every function of a device has 256 eight-bit registers. Registers 0-3F are defined by the PCI specification and provide a wealth of information about the particular function. Registers 40-FF are vendor defined and control the properties of the function itself. Without vendor specific documentation, these registers should probably be left untouched.
A typical PCI function looks like this:
x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
00000000: B7 10 55 90 17 01 10 02 30 00 00 02 08 50 00 00
00000010: 81 10 00 00 00 00 00 0C 00 00 00 00 00 00 00 00
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 B7 10 55 90
00000030: 00 00 00 00 DC 00 00 00 00 00 00 00 0B 01 0A 0A
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000050: 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000D0: 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 F6
000000E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Registers 0 and 1 are defined by the PCI spec as being the vendor ID. The vendor ID is a 16bit value, in this case 10B7h
Register 2 and 3 are the device ID, 9055h in this example.
By looking up the vendor ID number 10b7 in the PCI vendor database you can see this is a 3COM card. The 9055h is a 3COM generated number which describes what model card this is.
Other registers can tell us it's an Ethernet controller, it's using IRQ 11, uses a base I/O address of 1080h and more. Refer to a pci specification to get all the details, as those are outside the scope of this document.
So, how do you get to all these registers in PCI space?
Accessing these registers is sorta like accessing CMOS memory in that you first send an index value (a pointer to the register you want to access) to the index port, then you read or write the data to/from the data port. The index is going to be a combination of all 4 above mentioned components, (bus, device, function, register)
In the x86 world, the index port always located at 0CF8h and the data port is always located at 0CFCh in I/O space. Most system BIOSes have software interfaces to abstract the index/data port access from you. I describe both methods below. Refer to Ralph Brown's interrupt list for details on the BIOS method of reading/writing PCI
Before you can get to any PCI function's registers, you should probably make sure the PCI interface exists first!
Detecting the PCI bus
you can detect the PCI bus a couple different ways. the easist one is to call the PCI BIOS interface directly and do an installation check.
note that you can also do a non-80386+ check by issuing this call and only check DX for "CP" (4350h), but when have you ever seen a 286 with a PCI bus?
.386
mov ax, 0b101h ; interrupt 1a function b101
int 1ah ; will tell us if there is a PCI
cmp edx," ICP" ; bus on the board.
jz yup ; EDX=20494350h
; nope
yup:
------------------------------------
You can also find the PCI bus using I/O by just doing a quick read to port CFCh.
mov dx, 0cfch ; config data port
in eax, dx
cmp eax, -1 ; FFFFFFFF?
jz nope ; something must exist in PCI land
; yup
nope:
you will simply receive the data from the last PCI operation that was completed. This is by no means a foolproof method, but can do the job for quick-n-dirty type applications.
finding a device on the PCI bus:
there are 2 ways of finding a PCI device on the bus. You can either use the PCI BIOS interface call, or direct hardware I/O.
Here's the BIOS way:
INTEL_VENDOR_ID EQU 8086h ; intel's unique sig #
INTEL_EXP_NIC EQU 1227h ; sample PCI device etherexpress 10/100 NIC
.386
mov ax, 0b102h ; interrupt 1a function b102
mov dx, INTEL_VENDOR_ID
mov cx, INTEL_EXP_NIC
xor si, si ; 0=1st device, 1=2nd etc.
int 1ah
jc nope
; once returned from this call, BH=bus number, BL=device/function #
nope:
----------------------------------------------------------------
in the above example, SI will normally be zero, unless you are trying to locate the 2nd or more instance of the same PCI device.
(ie, you had 3 PCI intel etherexpress cards installed)
an extremely handy utility for snooping through the PCI bus on your system is a DOS program called PCIVIEW.EXE. i was able to locate this utility on the net by simply searching for pciview.exe
--------------------------------------------------------------------------------------
the non-BIOS way:
locating a specific device on the PCI bus requires you to understand how the PCI configuration cycle is broken down.
it's a 32bit value that looks like this:
bit 31=1 (bit is always set for a PCI access)
bits30:24=0 (reserved)
bit 23:16=bus number (0-255)
bits15:11=device # (0-31)
bits10:8=function # (0-7)
bits7:0=register number (0-255)
you send the above bit-encoded value out to the index port (cf8h) and then do a 32bit read from the data port (cfch)
here's how to read the vendor and device ID from a device sitting at bus 0, device 7, function 3.
BUS EQU 0
DEV EQU 7
FN EQU 3
VEN_ID EQU 0 ; vendor ID=PCI regs 0,1
PCI_INDEX EQU 0CF8h
PCI_DATA EQU 0CFCh
.386
mov ax, 8000h ; set bit 31 (after shift)
or al, BUS ; add in bus number
shl eax, 16
mov ax, DEV
shl ax, 11 ; slide device # up to bits 15:11
mov al, FN
or ah, al ; add function into bits 10:8
mov al, VEN_ID
cli
mov dx, PCI_INDEX
out dx, eax ; send our request out
mov dx, PCI_DATA
in eax, dx ; read back 32bit value.
sti
Remember that PCI registers are 8 bit values. The above read from PCI_DATA reads a 32bit value, or 4 PCI registers. In the above example, after the read, EAX = device ID, AX = vendor ID.
Per the PCI specification, the vendor ID is always registers 0 and 1, and the device ID is registers 2 and 3.
Thus, AL=register 0, AH=register 1, EAL=register 2, EAH=register 3.
PCIe update:PCI express did some minor tweaks to the interface. Specifically, they changed the number of config registers from 255 to 4096. The 1st 255 registers still look and feel just like regular PCI registers-in fact, they are also readable and writable using the same methods described above.
The additional registers however, are only available through a memory mapped subsystem, and it's a total pain in the cheeks to get to them.
For PCIe, it turns out that the *ENTIRE* PCI subsystem has been mapped into a 256MB chunk of system memory. On the 2 machines that I had a chance to play with, this memory map started at phsyical address 0xe0000000. That's way up near the top of 4Gig of memory. I suggest you grab a memory browser/editor that allows you to poke around in memory out there and explore the area for yourself.
At 0xe0000000, you'll see a copy of every PCI(e) register from Bus 0, Device 0, Function 0.
Function 1 follows at 0xe0000100, Function 2 at 0xe0000200, etc, all the way up to Bus 255, Device 31, Function 7. (ok, this is guess. I'm not sure if each function is packed into memory as tightly as every 0x100 bytes-my machines didn't have multi-function PCI devices, but you can clearly see that all PCI registers are there in memory.)
Any time there was no PCI device, such as BUS 89, Device 9, Function 3, the memory just returns all FF's because nothing is there to respond to the read. To me, it seems like a HUGE waste of memory space, considering that there is already a perfectly good mechanism for accessing PCI, and all they'd need to do is use a couple of the reserved bits in the 32bit index port to allow access to all the extended PCIe registers, but I digress...
Changing any register value here in memory is just like changing them via I/O ports the old way; the memory map is just a mirror of whatever you see through the index and data ports and vice versa.
On your machine, your PCIe memory map might not be at 0xe0000000. How did I find this magic value? This is where the pain in the cheeks starts, with ACPI.
Tucked away in the ACPI Root System Description Table (RSDT) is an entry for the PCI Express memory mapped configuration space base address Description Table, or MCFG for short.
In order to get there, you have to parse the ACPI tables. Here's how to do it:
1) search in memory (real mode) in the BIOS segments 0xE000 or 0xF000 for the byte sequence:
"RSD PTR "
2) add 0x10 to the address that "RSD PTR " is found, to get a 32bit pointer to where the main ACPI RSDT tables are located.
3) You will need to be in protected mode, or unreal mode to access memory to do this next part.
Starting at the 32bit address of the RSDT tables (should be in high memory, my NVidia board put them at 0x7FEF3040) search for the keyword "MCFG" or parse through all the tables until you get to one labeled "MCFG". At offset 0x2c from "MCFG" will be another 32bit pointer to the PCIe memory map.
My Nvidia board's "MCFG" table looks like this:
4D434647 3C000000 012C4E76 69646961 MCFG<....,Nvidia
4E564441 41435049 312E3042 4E564441 NVDAACPI1.0BNVDA
00000000 00000000 00000000 000000E0 ...............á
00000000 000000FF 00000000 00000000 .......ÿ........
I've got an ACPI dump program (for DOS) here:
http://www.waste.org/~winkles/acpidump although it is out of date and won't dump out the MCFG table, it'll at least point you in the right direction of where to look.
It appeared to me that very few PCIe devices have any additional registers above the 255 that are available through the index and data ports, so getting to them this way appears to a bit of moot point, but I'm sure eventually something will come up, so now you know.
feel free to contact me with questions or comments.
相关推荐
PCI(Peripheral Component Interconnect)总线协议是一种广泛应用于个人计算机中的局部总线标准,由英特尔公司在1992年推出,旨在提高系统性能并统一不同硬件设备的接口。PCI总线协议详细说明涵盖了许多关键概念和...
通过实际的硬件搭建和软件调试,确保了PCI总线通信功能的正确性和稳定性。实验结果证明,该设计能够成功地完成单片机与上位机之间的数据传输,满足了PCI总线通信的需求。 六、总结与展望 基于单片机的PCI总线通信...
PCI(Peripheral Component Interconnect)总线协议是计算机系统中一种重要的接口标准,它定义了处理器与...同时,通过学习这个协议,开发者和工程师可以更好地设计和优化基于PCI接口的硬件设备,提升系统整体性能。
PCI总线协议V2.3是该标准的一个版本,旨在增强其功能性和兼容性,以适应不断发展的硬件技术。 PCI总线协议的核心特点是它直接连接到处理器,提供了高速数据传输能力。在V2.3版本中,PCI总线通常支持32位和64位的...
1. PCI总线:PCI(Peripheral Component Interconnect)是计算机系统中的一种扩展总线标准,它允许硬件设备直接与CPU通信,提高了数据传输的速度和效率。PCI总线具有高带宽、低延迟和兼容性强的特点,广泛应用于各种...
PCI(Peripheral Component Interconnect,外围组件互连)总线是一种高性能的局部总线标准,它在个人计算机系统中起到了至关重要的作用,连接了CPU与其他硬件设备。以下是对PCI总线结构及其相关知识点的详细说明: ...
这样的设计允许用户在FPGA中创建自己的PCI接口,从而能够实现与PCI总线兼容的设备。 描述中指出这是一份珍贵的PCI设计资料,意味着它可能包含详细的PCI总线协议解析、AHDL代码示例、设计流程以及可能的调试方法。这...
Altera的PCI核是一种高度集成的、用于实现PCI总线接口功能的硬件设计模块。通过使用Altera的PCI核,设计者可以快速地在FPGA中实现复杂的PCI接口逻辑,而无需从零开始设计。这极大地简化了PCI开发过程,提高了设计...
PCI总线允许高速数据传输,支持多种设备,如显卡、网卡、声卡等。在DOS环境下,由于操作系统本身并不直接提供对PCI设备的全面支持,因此开发者需要通过特定的编程手段来访问PCI设备。 标题中的"IOFUNC.zip_IOFunc_c...
4. 多功能性:PCI总线可支持多种类型的设备,并且能够同时处理多个设备的数据传输。 开发者指南中可能涵盖的内容包括: 1. PCI总线架构:包括总线的层次结构、地址空间分配、信号定义等。 2. PCI设备的配置:介绍...
"读取PCI插槽上的硬件配置信息" ...读取PCI插槽上的硬件配置信息是获取PCI设备的基本信息的重要步骤,需要了解PCI配置空间的物理地址和PCI设备的vendorID和deviceID,并使用VxD来实现读取PCI配置信息的功能。
标题中的"MEMFUNC.zip_MemfunC.zip_c dos pci _dos pci_pci_pci总线"提示我们这是一个关于在DOS环境下,使用C语言编写程序来访问32位PCI(Peripheral Component Interconnect)总线的示例代码。描述进一步确认了这...
基于CH365芯片的PCI总线控制卡的设计与实现的知识点包括: 1. CH365芯片的功能与特性: - CH365是一款通用的PCI接口芯片,用于连接PCI总线。 - 支持I/O端口映射、存储器映射、扩展ROM以及中断。 - 可以将32位的...
#### 二、PCI总线中的主设备与从设备 - **主设备**:取得总线控制权的设备,可以发起数据传输。 - **从设备**或**目标节点**:被主设备选中以进行通信的设备。 #### 三、PCI总线信号定义 PCI总线信号分为必备和可...
这个空间的存在使得PCI设备可以被系统自动识别和配置,极大地方便了硬件设备的安装。 在硬件设计部分,虽然不是文章的重点,但作者指出在设计过程中需要注意几个关键点,比如信号线的布局、电源供应以及信号完整性...
通过深入阅读和理解《雷赛DMC1000B PCI总线4轴运动控制卡硬件使用手册》,用户可以全面掌握该产品的各项功能,并在实际应用中实现高效、精准的运动控制。无论是在设备安装、调试还是后期维护中,此手册都将是不可或...
PCI Express(PCIe)是一种高速串行计算机扩展总线标准,旨在替代旧式的并行PCI总线。PCIe 3.0是PCIe总线规范的第三个主要版本,它在PCIe 2.0的基础上进行了显著的改进,提高了数据传输速率,扩展了协议的功能性,并...
《雷赛DMC2410B PCI总线4轴运动控制卡硬件使用手册》是针对该型号运动控制卡的详细技术指南,旨在帮助用户理解和操作这款设备。本手册涵盖了从安装、配置到实际应用的全方位指导,是技术人员进行设备调试和维护的...