From:http://blog.csdn.net/zyl910/article/details/858349

如何在DOS中枚举PCI设备

分类: #All - 所有             微机原理、DOS、BIOS与硬件接口编程              2006-07-01 01:36     11313人阅读     评论(16)     收藏     举报    
dos function express byte class 编程

File:      zEnumPCI
Name:      如何在DOS中枚举PCI设备
Author:    zyl910
Blog:      http://blog.csdn.net/zyl910/
Version:   V1.0
Updata:    2006-6-30

下载(注意修改下载后的扩展名)

前言
~~~~

  学计算机这么多年了,PCI这个名词不知道叫了几百遍了。可是,我一直不知道PC机是如何使用PCI总线的、PCI总线设备到底是如何工作的。可是以前我从来没意识到这个问题,只是麻木的、带着虚伪的自信活着。
  直到前段时间在书店看到《PCI Express 系统体系结构标准教材》,才突然感受到——我对PCI还一无所知,可现在 PCI Express 的时代都快到来了。我很受震撼,所以毫不犹豫地买下了那本书。
  回家打开书一看,发现绝大东西看不太懂。当年学接口技术时,那时只有ISA。ISA很简单,是直接采用电路连线方式将设备与地址总线、各个IRQ及其他控制线路连接起来。而现在PCI-E就很复杂了,而我跳过了PCI,存在着知识断层。
  于是我又跑到书店,去查PCI或接口技术上面的书。后来发现,这十年来,接口技术的书的确更新了,但只为PCI写个寥寥几页简介,有的书甚至连引脚定义、配置空间等PCI最核心内容都没有。那样子还不如不说,浪费了纸张。典型只为了教学大纲,而不考虑学生是否能学会、理解。
  我费了好大功夫,才找了几本关于PCI的书,但主要是英文的。特别是找到了《PCI Express 系统体系结构标准教材》的英文版,这样就可以对照参考,理解那些英文资料。
  看了一段时间之后,发现那些书主要是讲硬件电气特性、通信协议细节,面向的读者是设计PCI设备的工程师。而我的学习目的是如果在PC机上编程控制PCI设备。还好在网络上找了一些关于PCI小程序,填补了知识空白。

正文
~~~~

一、PCI配置空间

  PCI设备有三个空间——内存地址空间、IO地址空间和配置空间。由于PCI支持即插即用,所以PCI设备不是占用固定的内存地址空间或I/O地址空间,而是可以由操作系统决定其映射的基址。怎么配置呢?这就是配置空间的作用。

DW |    Byte3    |    Byte2    |    Byte1    |     Byte0     | Addr
---+---------------------------------------------------------+-----
 0 |     Device ID     |     Vendor ID      | 00
---+---------------------------------------------------------+-----
 1 |      Status     |      Command      | 04
---+---------------------------------------------------------+-----
 2 |        Class Code        | Revision ID | 08
---+---------------------------------------------------------+-----
 3 |   BIST  | Header Type | Latency Timer | Cache Line  | 0C
---+---------------------------------------------------------+-----
 4 |           Base Address 0           | 10
---+---------------------------------------------------------+-----
 5 |           Base Address 1           | 14
---+---------------------------------------------------------+-----
 6 |           Base Address 2           | 18
---+---------------------------------------------------------+-----
 7 |           Base Address 3           | 1C
---+---------------------------------------------------------+-----
 8 |           Base Address 4           | 20
---+---------------------------------------------------------+-----
 9 |           Base Address 5           | 24
---+---------------------------------------------------------+-----
10 |          CardBus CIS pointer          | 28
---+---------------------------------------------------------+-----
11 |  Subsystem Device ID  |   Subsystem Vendor ID   | 2C
---+---------------------------------------------------------+-----
12 |        Expansion ROM Base Address        | 30
---+---------------------------------------------------------+-----
13 |        Reserved(Capability List)         | 34
---+---------------------------------------------------------+-----
14 |            Reserved             | 38
---+---------------------------------------------------------+-----
15 |  Max_Lat  |  Min_Gnt  |  IRQ Pin  |  IRQ Line  | 3C
-------------------------------------------------------------------

  配置空间中最重要的有:
Vendor ID:厂商ID。知名的设备厂商的ID。FFFFh是一个非法厂商ID,可它来判断PCI设备是否存在。
Device ID:设备ID。某厂商生产的设备的ID。操作系统就是凭着 Vendor ID和Device ID 找到对应驱动程序的。
Class Code:类代码。共三字节,分别是 类代码、子类代码、编程接口。类代码不仅用于区分设备类型,还是编程接口的规范,这就是为什么会有通用驱动程序。
IRQ Line:IRQ编号。PC机以前是靠两片8259芯片来管理16个硬件中断。现在为了支持对称多处理器,有了APIC(高级可编程中断控制器),它支持管理24个中断。
IRQ Pin:中断引脚。PCI有4个中断引脚,该寄存器表明该设备连接的是哪个引脚。

  关于配置空间的详细说明请参考《PCI Local Bus Specification》的第六章。

二、如何访问配置空间

  如何访问配置空间呢?可通过访问CF8h、CFCh端口来实现(《PCI Local Bus Specification》的3.2.2.3.2)。
CF8h: CONFIG_ADDRESS。PCI配置空间地址端口。
CFCh: CONFIG_DATA。PCI配置空间数据端口。

  CONFIG_ADDRESS寄存器格式:
 31 位:Enabled位。
23:16 位:总线编号。
15:11 位:设备编号。
10: 8 位:功能编号。
 7: 2 位:配置空间寄存器编号。
 1: 0 位:恒为“00”。这是因为CF8h、CFCh端口是32位端口。

  现在有个难题——CF8h、CFCh端口是32位端口,可像TurboC之类的16位C语言编译器都不支持32位端口访问。怎么办?我们可以使用__emit__在程序中插入机器码。每次都__emit__一下肯定很麻烦,所以我们应该将它封装成函数。代码如下(注意66h是32位指令前缀):

/* 读32位端口 */
DWORD   inpd(int    portid)
{DWORD  dwRet;asm mov dx, portid;asm lea bx, dwRet;__emit__(0x66,0x50,  // push EAX0x66,0xED,   // in EAX,DX0x66,0x89,0x07, // mov [BX],EAX0x66,0x58);  // pop EAXreturn dwRet;
}/* 写32位端口 */
void    outpd(int   portid, DWORD   dwVal)
{asm mov dx, portid;asm lea bx, dwVal;__emit__(0x66,0x50,   // push EAX0x66,0x8B,0x07,  // mov EAX,[BX]0x66,0xEF,   // out DX,EAX0x66,0x58);    // pop EAXreturn;
}

三、枚举PCI设备

  怎么枚举PCI设备呢?我们可以尝试所有的 bus/dev/func 组合,然后判断得到的厂商ID是否为FFFFh。
  下面这个程序就是使用该方法枚举PCI设备的。同时为了便于分析数据,将每个设备的配置空间信息保存到文件,这样可以慢慢分析。

/*
File:      epcip.c
Name:      访问CF8h、CFCh端口来枚举PCI设备
Author:    zyl910
Blog:      http://blog.csdn.net/zyl910/
Version:   V1.0
Updata:    2006-6-30
*/
#include <stdio.h>
#include <conio.h>
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;
/* PCI设备索引。bus/dev/func 共16位,为了方便处理可放在一个WORD中 */
#define PDI_BUS_SHIFT   8
#define PDI_BUS_SIZE    8
#define PDI_BUS_MAX     0xFF
#define PDI_BUS_MASK    0xFF00
#define PDI_DEVICE_SHIFT   3
#define PDI_DEVICE_SIZE    5
#define PDI_DEVICE_MAX     0x1F
#define PDI_DEVICE_MASK    0x00F8
#define PDI_FUNCTION_SHIFT   0
#define PDI_FUNCTION_SIZE    3
#define PDI_FUNCTION_MAX     0x7
#define PDI_FUNCTION_MASK    0x0007
#define MK_PDI(bus,dev,func) (WORD)((bus&PDI_BUS_MAX)<<PDI_BUS_SHIFT | (dev&PDI_DEVICE_MAX)<<PDI_DEVICE_SHIFT | (func&PDI_FUNCTION_MAX) )
/* PCI配置空间寄存器 */
#define PCI_CONFIG_ADDRESS      0xCF8
#define PCI_CONFIG_DATA         0xCFC
/* 填充PCI_CONFIG_ADDRESS */
#define MK_PCICFGADDR(bus,dev,func) (DWORD)(0x80000000L | (DWORD)MK_PDI(bus,dev,func)<<8)
/* 读32位端口 */
DWORD inpd(int portid)
{DWORD dwRet;asm mov dx, portid;asm lea bx, dwRet;__emit__(0x66,0x50, // push EAX0x66,0xED, // in EAX,DX0x66,0x89,0x07, // mov [BX],EAX0x66,0x58); // pop EAXreturn dwRet;
}
/* 写32位端口 */
void outpd(int portid, DWORD dwVal)
{asm mov dx, portid;asm lea bx, dwVal;__emit__(0x66,0x50, // push EAX0x66,0x8B,0x07, // mov EAX,[BX]0x66,0xEF, // out DX,EAX0x66,0x58); // pop EAXreturn;
}
int main(void)
{int bus, dev, func;int i;DWORD dwAddr;DWORD dwData;FILE* hF;char szFile[0x10];
 printf("/n");printf("Bus#/tDevice#/tFunc#/tVendor/tDevice/tClass/tIRQ/tIntPin/n");
 /* 枚举PCI设备 */for(bus = 0; bus <= PDI_BUS_MAX; ++bus) {for(dev = 0; dev <= PDI_DEVICE_MAX; ++dev) {for(func = 0; func <= PDI_FUNCTION_MAX; ++func) {/* 计算地址 */dwAddr = MK_PCICFGADDR(bus, dev, func);/* 获取厂商ID */outpd(PCI_CONFIG_ADDRESS, dwAddr);dwData = inpd(PCI_CONFIG_DATA);
    /* 判断设备是否存在。FFFFh是非法厂商ID */if ((WORD)dwData != 0xFFFF) {/* bus/dev/func */printf("%2.2X/t%2.2X/t%1X/t", bus, dev, func);
     /* Vendor/Device */printf("%4.4X/t%4.4X/t", (WORD)dwData, dwData>>16);
     /* Class Code */outpd(PCI_CONFIG_ADDRESS, dwAddr | 0x8);dwData = inpd(PCI_CONFIG_DATA);printf("%6.6lX/t", dwData>>8);
     /* IRQ/intPin */outpd(PCI_CONFIG_ADDRESS, dwAddr | 0x3C);dwData = inpd(PCI_CONFIG_DATA);printf("%d/t", (BYTE)dwData);printf("%d", (BYTE)(dwData>>8));
     printf("/n");
     /* 写文件 */sprintf(szFile, "PCI%2.2X%2.2X%X.bin", bus, dev, func);hF = fopen(szFile, "wb");if (hF != NULL) {/* 256字节的PCI配置空间 */for (i = 0; i < 0x100; i += 4) {/* Read */outpd(PCI_CONFIG_ADDRESS, dwAddr | i);dwData = inpd(PCI_CONFIG_DATA);
       /* Write */fwrite(&dwData, sizeof(dwData), 1, hF);}fclose(hF);}}}}}
 return 0;
}

  对于我的电脑的枚举结果是:

Bus# Device# Func# Vendor Device Class IRQ IntPin 类代码的说明
0 0 0 1106 3189 60000 0 0 Host bridge
0 1 0 1106 B168 60400 0 0 PCI-to-PCI bridge(实际上是PCI/AGP桥,AGP可看成一种特殊的PCI设备)
0 9 0 14F1 2013 78000 11 1 Simple communication controllers
0 9 1 14F1 2013 78000 11 1 Simple communication controllers
0 9 2 14F1 2013 78000 11 1 Simple communication controllers
0 9 3 14F1 2013 78000 11 1 Simple communication controllers
0 9 4 14F1 2013 78000 11 1 Simple communication controllers
0 9 5 14F1 2013 78000 11 1 Simple communication controllers
0 9 6 14F1 2013 78000 11 1 Simple communication controllers
0 9 7 14F1 2013 78000 11 1 Simple communication controllers
0 10 0 1106 3038 0C0300 11 1 USB controller: Universal Host Controller Specification
0 10 1 1106 3038 0C0300 5 2 USB controller: Universal Host Controller Specification
0 10 2 1106 3038 0C0300 5 3 USB controller: Universal Host Controller Specification
0 10 3 1106 3104 0C0320 11 4 USB2 controller: Intel Enhanced Host Controller Interface
0 11 0 1106 3177 60100 0 0 ISA bridge
0 11 1 1106 571 01018A 255 1 IDE controller
0 11 5 1106 3059 40100 5 3 Audio device
0 12 0 1106 3065 20000 11 1 Ethernet controller
1 0 0 10DE 110 30000 11 1 VGA-compatible controller

  总线编号为0的都是主板上固有的芯片(主要是南桥),非主板设备的典型是——显卡。
  WindowsXP的设备管理器中也可以看到PCI信息。启动“设备管理器”,最好将查看方式设为“依连接查看设备(V)”。找到我的显卡,双击查看属性。切换到“详细信息”页,定位组合框为“硬件 Id”。可看到其中一行为“PCI/VEN_10DE&DEV_0110&CC_030000”,表示厂商ID为“10DE”、设备ID为“0110”、类代码为“030000”,与程序得到的结果一致。
[Display.gif]

四、PCI BIOS

  直接访问CF8h、CFCh端口的方法太底层。为了提高兼容性,我们可以使用PCI BIOS。PCI BIOS的中断号是1Ah,AH为B1,AL为功能号。其功能列表为:

01h: INSTALLATION CHECK
02h: FIND PCI DEVICE
03h: FIND PCI CLASS CODE
06h: PCI BUS-SPECIFIC OPERATIONS
08h: READ CONFIGURATION BYTE
09h: READ CONFIGURATION WORD
0Ah: READ CONFIGURATION DWORD
0Bh: WRITE CONFIGURATION BYTE
0Ch: WRITE CONFIGURATION WORD
0Dh: WRITE CONFIGURATION DWORD
0Eh: GET IRQ ROUTING INFORMATION
0Fh: SET PCI IRQ
81h: INSTALLATION CHECK (32-bit)
82h: FIND PCI DEVICE (32-bit)
83h: FIND PCI CLASS CODE (32-bit)
86h: PCI BUS-SPECIFIC OPERATIONS (32-bit)
88h: READ CONFIGURATION BYTE (32-bit)
89h: READ CONFIGURATION WORD (32-bit)
8Ah: READ CONFIGURATION DWORD (32-bit)
8Bh: WRITE CONFIGURATION BYTE (32-bit)
8Ch: WRITE CONFIGURATION WORD (32-bit)
8Dh: WRITE CONFIGURATION DWORD (32-bit)
8Eh: GET IRQ ROUTING INFORMATION (32-bit)
8Fh: SET PCI IRQ (32-bit)

  由于像Turbo C这样的16位编译器访问32位寄存器很麻烦,所以建议使用WORD方式来访问PCI配置空间。以下是09h号功能的详细说明(摘自Ralf Brown's Interrupt List):

--------X-1AB109-----------------------------
INT 1A - PCI BIOS v2.0c+ - READ CONFIGURATION WORD
 AX = B109h
 BH = bus number
 BL = device/function number (bits 7-3 device, bits 2-0 function)
 DI = register number (0000h-00FFh, must be multiple of 2) (see #00878)
Return: CF clear if successful
     CX = word read
 CF set on error
 AH = status (00h,87h) (see #00729)
 EAX, EBX, ECX, and EDX may be modified
 all other flags (except IF) may be modified
Notes: this function may require up to 1024 byte of stack; it will not enable
   interrupts if they were disabled before making the call
 the meanings of BL and BH on entry were exchanged between the initial
   drafts of the specification and final implementation
BUG: the Award BIOS 4.51PG (dated 05/24/96) incorrectly returns FFFFh for
   register 00h if the PCI function number is nonzero
SeeAlso: AX=B108h,AX=B10Ah,AX=B189h,INT 2F/AX=1684h/BX=304Ch

  代码如下:

/*
File:      epcib.c
Name:      使用PCI BIOS来枚举PCI设备
Author:    zyl910
Blog:      http://blog.csdn.net/zyl910/
Version:   V1.0
Updata:    2006-6-30

*/

#include <stdio.h>
#include <conio.h>
#include <dos.h>

typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;

/* PCI设备索引。bus/dev/func 共16位,为了方便处理可放在一个WORD中 */
#define PDI_BUS_SHIFT   8
#define PDI_BUS_SIZE    8
#define PDI_BUS_MAX     0xFF
#define PDI_BUS_MASK    0xFF00

#define PDI_DEVICE_SHIFT   3
#define PDI_DEVICE_SIZE    5
#define PDI_DEVICE_MAX     0x1F
#define PDI_DEVICE_MASK    0x00F8

#define PDI_FUNCTION_SHIFT   0
#define PDI_FUNCTION_SIZE    3
#define PDI_FUNCTION_MAX     0x7
#define PDI_FUNCTION_MASK    0x0007

#define MK_PDI(bus,dev,func) (WORD)((bus&PDI_BUS_MAX)<<PDI_BUS_SHIFT | (dev&PDI_DEVICE_MAX)<<PDI_DEVICE_SHIFT | (func&PDI_FUNCTION_MAX) )

int main(void)
{
 int bus, dev, func;
 int i;
 union REGS regs;
 WORD wAddr;
 FILE* hF;
 char szFile[0x10];

printf("/n");
 printf("Bus#/tDevice#/tFunc#/tVendor/tDevice/tClass/tIRQ/tIntPin/n");

/* 枚举PCI设备 */
 for(bus = 0; bus <= PDI_BUS_MAX; ++bus) {
  for(dev = 0; dev <= PDI_DEVICE_MAX; ++dev) {
   for(func = 0; func <= PDI_FUNCTION_MAX; ++func) {
    /* 计算地址 */
    wAddr = MK_PDI(bus, dev, func);
    
    /* 获取厂商ID */
    regs.x.ax = 0xB109; // PCI BIOS v2.0c+ - READ CONFIGURATION WORD
    regs.x.bx = wAddr;
    regs.x.di = 0; // Vendor ID
    regs.x.cx = 0xFFFF; // 非法的Vendor ID
    int86(0x1A, &regs, &regs);

/* 判断设备是否存在。FFFFh是非法厂商ID */
    if (regs.x.cx != 0xFFFF) {
     /* bus/dev/func */
     printf("%2.2X/t%2.2X/t%1X/t", bus, dev, func);

/* Vendor */
     printf("%4.4X/t", regs.x.cx);

/* Device */
     regs.x.ax = 0xB109; // PCI BIOS v2.0c+ - READ CONFIGURATION WORD
     regs.x.bx = wAddr;
     regs.x.di = 2; // Device ID
     int86(0x1A, &regs, &regs);
     printf("%4.4X/t", regs.x.cx);

/* Class Code */
     regs.x.ax = 0xB109; // PCI BIOS v2.0c+ - READ CONFIGURATION WORD
     regs.x.bx = wAddr;
     regs.x.di = 0xA; // Class/SubClass
     int86(0x1A, &regs, &regs);
     printf("%4.4X/t", regs.x.cx);

/* IRQ/intPin */
     regs.x.ax = 0xB109; // PCI BIOS v2.0c+ - READ CONFIGURATION WORD
     regs.x.bx = wAddr;
     regs.x.di = 0x3C; // IRQ/IntPin
     int86(0x1A, &regs, &regs);
     printf("%d/t", (BYTE)regs.x.cx);
     printf("%d", (BYTE)(regs.x.cx>>8));

printf("/n");

/* 写文件 */
     sprintf(szFile, "PCI%2.2X%2.2X%X.bin", bus, dev, func);
     hF = fopen(szFile, "wb");
     if (hF != NULL) {
      /* 256字节的PCI配置空间 */
      for (i = 0; i < 0x100; i += 2) {
       /* Read */
       regs.x.ax = 0xB109; // PCI BIOS v2.0c+ - READ CONFIGURATION WORD
       regs.x.bx = wAddr;
       regs.x.di = i;
       int86(0x1A, &regs, &regs);

/* Write */
       fwrite(&regs.x.cx, 2, 1, hF);
      }
      fclose(hF);
     }
    }
   }
  }
 }

return 0;
}

五、保护模式下的PCI BIOS

  刚才所说的1Ah中断是实模式下的BIOS,保护模式下怎么办?
  在BIOS内存区(E0000h ~ FFFFFh)可以找到PCI BIOS保护模式入口。其格式为:

0h(dw): “_32_”标志
4h(dw): PCI BIOS保护模式入口
8h(by): Rev Level
9h(by): 长度
Ah(by): 校检和
Bh ~ Fh: 保留

  关于保护模式下PCI BIOS的具体用法可参考《PCI Bus Demystified》的第七章。

  由于切换到保护模式的代码比较复杂,所以就没有编程测试了。

六、总结

  本文章中的代码能在纯DOS下或Windows9X中正常运行,但是不能在WindowsXP等NT平台下运行:对于访问端口方式,厂商ID均返回FFFFh;对于调用 PCI BIOS 方式,貌似根本没有实现该功能。这可能与WindowsXP设计有关——不再使用V86方式执行DOS程序,而是专门做了个DOS虚拟机。而且还有许多这样的兼容性问题,比如VBE。我都有点怀疑这不是微软故意这么做,让我们不能接触底层,只能使用高层的.Net,这样不可能对像微软这样掌握核心技术的公司造成威胁。

参考文献
~~~~~~~~
[1] PCI-SIG. PCI Local Bus Specification Revision 3.0. 2002.8.12
[2] Doug Abbott. PCI Bus Demystified. LLH Technology Publishing, 2000
[3] 李贵山、戚德虎. PCI 局部总线开发者指南. 西安电子科技大学出版社, 1997.1
[4] MindShare, Inc , Ravi Budruk, Don Anderson, Tom Shanley. PCI Express System Architecture. Addison Wesley, 2003.9.4
[5] MindShare公司. 田玉敏,王崧,张波 译. PCI Express 系统体系结构标准教材. 电子工业出版社, 2005.11
[6] Ralf Brown's Interrupt List. http://www.cs.cmu.edu/~ralf/

更新
~~~~

[V1.0.0]2006-6-29
此项目开始。

如何在DOS中枚举PCI设备相关推荐

  1. 如何在DOS中枚举PCI设备(作者zyl910)

    File:      zEnumPCI Name:      如何在DOS中枚举PCI设备 Author:    zyl910 Blog:      http://blog.csdn.net/zyl9 ...

  2. 枚举PCI设备的讨论

    作者很明显不是做底层的,但是也研究出如何访问PCI设备. 可以借鉴和参考原作者的Source code. --------------------以下为转载内容-------------------- ...

  3. StratoVirt 中的 PCI 设备热插拔实现

    热插拔即带电插拔,在虚拟化场景下,热插拔就是在虚拟机运行过程中对磁盘网卡等设备进行动态调整. 常见的热插拔机制有 ACPI 机制的热插拔,PCIe-Native 机制的热插拔.ACPI 机制的热插拔依 ...

  4. UEFI中的PCI设备扫描及分配Mem/Io空间过程

    最近在调试解决PCI设备相关的问题,然后对UEFI下面的这部分实现有了初步的了解,为了防止后面慢慢的又忘记了,所以还是决定将最近的收获都记录起来,各位读者如果发现哪里记录或者总结的不对,欢迎留言指正. ...

  5. 如何在XenDesktop中映射USB设备

    许多用户在工作中经常会碰到一些USB外设无法映射的问题,在citrix官方的usb support list中列举的USB设备很少,但是被不是说不在列表中的就不被支持,我们可以尝试更多的方法来挂载一些 ...

  6. android蓝牙连接耳机分析,如何在android中获取蓝牙耳机设备的信息(特别是耳机设备名称)...

    我终于解决了这个问题 . 以前我从"BluetoothAdpter"类获得了所有绑定设备的"getBondedDevices()"方法 . 但我通过使用&quo ...

  7. Pci设备驱动:设备枚举

    有了设备模型基础及usb设备驱动的基础知识,来了解PCI设备驱动,就相对简单了,因为PCI设备驱动仍然套用了设备驱动模型的方式,用到的仍然是设备模型的相应函数,只是把相应的pci设备挂载到PCI总线的 ...

  8. BIOS实战之PCI设备枚举二

    上次说到了除了IO枚举PCI设备,还有另一种方式枚举PCI设备,那就是通过pciio,这也是UEFI代码中的常规操作(当然还有MMIO,不过不写了) UEFI BIOS 提供了两个主要的模块来支持PC ...

  9. PCIe配置空间和PCI设备中的寄存器

    1.访问PCI配置空间,PCI基本配置空间的读写使用下列函数: 原型定义在<linux/pci.h> int pci_read_config_byte(struct pci_dev *pd ...

最新文章

  1. Solr定时重建索引和增量更新
  2. [WC2013]平面图——平面图点定位
  3. c++ocx交互检测弹框_吉利几何C:2022杭州亚运会移动“明信片”!
  4. shell expect的简单用法
  5. ASP 三十二条精华代码
  6. 处理器映射器(HandlerMapping)及处理器适配器(HandlerAdapter)详解(一)
  7. Android中的动画有哪几类?各自的特点和区别是什么?
  8. 2019全球编程语言高薪排行榜登场;余承东正式宣布华为IFA2019 或发布麒麟990;OPPO、vivo和小米成立互传联盟…...
  9. ReactNative学习笔记(二)Flex布局
  10. 老子《道德经》第六章
  11. 文件管理器之字符和编码
  12. 野村证券分析师称微软不会收购雅虎和RIM
  13. uniapp使用web-view跳转外部链接
  14. 源代码开发的公司该如何选择加密软件?
  15. Android系统架构与系统源码目录
  16. 宏观经济判断指标-GDP、CPI、PPI、PMI
  17. 计算机专业类ppt背景图片,6种方法,教你做出高大上PPT及背景-ppt背景图片怎么设置...
  18. 2020信息系统项目管理师备战1--开篇(项目范围说明书Project Scope Statement)
  19. 《微信公众平台应用开发实战(第2版)》一1.1 微信公众账号的注册
  20. 【回溯】B043_LQ_36进制 瓷砖样式(暴搜+策略)

热门文章

  1. c++ winapi菜单函数示例
  2. 用命令行去发掘有趣的“前十”
  3. 使用禅道进行测试管理
  4. 加密算法五虎上将之DES
  5. java 发送图片邮件_JavaMail邮件发送-为你的邮件增加背景音乐和背景图片
  6. 2020年广东工业大学计算机专业初试考研,2020广东工业大学研究生分数线汇总(含2016-2020历年复试)...
  7. 安卓 控件的AttributeSet
  8. 全球与中国泳衣布料市场深度研究分析报告(2021)
  9. random.RandomState()
  10. Java用JNA调用dll : Invalid memory access