Home PC Games Linux Windows Database Network Programming Server Mobile  
           
  Home \ Programming \ C language - Traverse pci device     - Use Ansible efficient delivery Docker container (Server)

- CentOS of NFS (Server)

- Find details block device with Linux blkid command (Linux)

- quotacheck command file can not be created aquota.user and aquota.group solutions (Linux)

- Bash Automated Customization Linux belongs to its own CentOS system (Linux)

- PostgreSQL procedural language learning (Database)

- How to manage your to-do list with the Go For It on Ubuntu (Linux)

- Linux / Raspberry Pi using the following command-line based web browser (Linux)

- socket busy poll of Linux kernel 3.11 to avoid sleep switch (Linux)

- Linux Getting Started tutorial: Experience VirtualBox Virtual Machine chapter (Linux)

- Installation of JDK and Tomcat under Linux (CentOS) (Linux)

- Web database security tips (Linux)

- Use Pylint regulate your Python code (Programming)

- The source code compiler installation Nginx 1.8.0 under Ubuntu 14.10 (Server)

- Use OpenSSL to generate a certificate (Linux)

- How to install open source ITIL portal iTOP on CentOS 7 (Server)

- Solve the compatibility problem between Linux and Java at the source in bold font (Linux)

- Android recyclerview cardview (Programming)

- Ubuntu15 core CLR (Server)

- Connect to the Oracle Database Help class (Database)

 
         
  C language - Traverse pci device
     
  Add Date : 2017-04-13      
         
         
         
  Table of Contents

Foreword
pci Profile
postscript
Foreword

Comparison of recent landlord hard to force ah, arranged a visit pci competent job, this job uses io mode can also be very waves will give everything to read it, although all of the information can not be read out pci-e devices, but or it may be 256 other things to read out.

This article will start with the io access mode is set to pci visit here includes the dos and Linux that I use, so you can see these two different systems code.

pci Profile

PCI bus is a high-performance 32-bit or 64-bit multiplexed address bus or data lines. Equivalent real-life road is called the signal path. It can transfer data in it, control signals and the like.

Role: its highly integrated peripheral control, the interconnection mechanism between the plug and the peripheral processor / memory systems.

If you want to access the PCI device, you must first determine the PCI device in the system of physical connection. Description of the connections of data is "bus number", "equipment" and the "function number." A system can have 256 PCI bus, you can have up to 32 devices on each bus, each device may have eight functions (each function as a PCI device). When these three data to determine when it can uniquely identify a PCI device in the system.

8-10: Function bit Sometimes a pci device corresponding to a plurality of functions will be separated from each functional unit, corresponds to a separate pci device..
11 to 15: number of devices on the bus should pci device number
16 to 23: number of bus lines through a bus No. 0.5 per traverse to lower the bus, the bus number +1

PCI topology

Bus structure, ethernet pci-pci bridge equipment and the same type of resources if the pci bus0 space must be a subset of

For example, pci bus I / O port resource is 0. 0x00CC ~ 0x01CC. Ethernet device I / O range is 0x00CC ~ 0x0xE0. So pci-pci bridge of the I / O port range must be between 0x0xE0 ~ 0x01CC.

Similarly, SCSI and VIDEO resources must be the same type if there is a subset of the pci_bus1 .pci bus1 a pci bridge, the corresponding resource is that it connect the bridge resources. That pci_bus-> self. That is, the resources of the lower bus it is a subset of the upper bus resources. Top bus resources is a superset of the lower bus resources.

In fact, each PCI device resources to start address is set by the operating system. On x86, set up by the bios.

pci configuration space

PCI configuration space is a capacity of 256 bytes of address space and having a specific record structure or model, through the configuration space, we can understand some of the configurations of the PCI device, thereby controlling the device, all devices other than the primary PCI bus bridge They are subject to prior configuration space.

The first 64 bytes of configuration space is called a header region, the header region is divided into two parts, the first part of the first 16 bytes, the types of devices are defined in the same, with each byte other equipment supported features differ, located at offset 0EH bid type field specifies what kind of layout, there are three types of headers, header for type 1 PCI-PCI bridge, the header for type 2 PCI- CARDBUS bridge, header type 0 for other PCI devices


Header region has five field involves identifying the device.

Supplier identification field (Vendor ID)
Offset: 00H. This field is used to identify the device maker. An effective vendor identification allocated by the PCI SIG to ensure its uniqueness. 0FFFFH is an invalid value for the field.

Device identification field (Device ID)
Offset: 02H. To indicate the specific device, the specific code allocated by the supplier.

Version identification field (Revision ID)
Offset: 08H. Is used to specify a device-specific version of the identification code, the value provided by the supplier, may be zero.

Type header field (Header Type)
Offset: 0EH. The field has two functions, one to represent the second part of the configuration space header region layout type; the second is to specify whether the device contains a multi-functional. Bit 7 is used to identify a multifunction device, bit 7 is 0 indicates a single-function devices, bit 7 to 1 indicates a multi-function device. Bit 0 Bit 6 indicates the type of header region.

Classification code field (Class Code)
Offset: 09H. The overall function of the device and identifies specific register-level programming interface. The byte divided into three parts, each part representing a byte, the first part is the basic classification code, located at offset 0BH, the second part is called the sub-classification code, located at offset 0AH, the third part of the register is used to identify a specific level programming interface.

io pci port access device

In the dos application related interfaces can get io port, read and traverse pci devices cf8 cfc mode.

#include < stdio.h>
typedef unsigned long DWORD;
typedef unsigned int WORD;
#define MK_PDI (bus, dev, func) (WORD) ((bus < < 8) | (dev < < 3) | (func))
#define MK_PCIaddr (bus, dev, func) (DWORD) (0xf8000000L | (DWORD) MK_PDI (bus, dev, func) < < 8)
#define PCI_CONFIG_ADDRESS 0xCF8
#define PCI_CONFIG_DATA 0xCFC
DWORD inpd (int inport)
{
DWORD data;
asm mov dx, inport;
asm lea bx, data;
__emit __ (
0x66,0x50,
0x66,0xED,
0x66,0x89,0x07,
0x66,0x58);
return data;
}

void outpd (int outport, DWORD addr)
{
asm mov dx, outport;
asm lea bx, addr;
__emit __ (
0x66,0x50,
0x66,0x8B, 0x07,
0x66,0xEF,
0x66,0x58);
}
DWORD GetData (DWORD addr)
{
DWORD data;
outpd (PCI_CONFIG_ADDRESS, addr);
data = inpd (PCI_CONFIG_DATA);
return data;
}
int main ()
{
int bus, dev, func;
DWORD addr, addr1, addr2, addr3;
DWORD data, data1, data2, data3;
printf ( "Bus # \ tDev # \ tFunc #");
printf ( "\ n");
for (bus = 0; bus < = 0x63; ++ bus)
{
for (dev = 0; dev < = 0x1F; ++ dev)
{
for (func = 0; func < = 0x7; ++ func)
{
addr = MK_PCIaddr (bus, dev, func);
data = GetData (addr);
if ((WORD) data! = 0xFFFF)
{
printf ( "% 2.2x \ t% 2.2x \ t% 2.2x \ t", bus, dev, func);
printf ( "\ n");
}
}
}
}
return 0;
}
In the Linux system is very simple, direct look at the code it!

#include < stdio.h>
#include < stdlib.h>
#include < unistd.h>
#include < sys / io.h>
#define PCI_MAX_BUS 255
#define PCI_MAX_DEV 31
#define PCI_MAX_FUN 7
#define PCI_BASE_ADDR 0x80000000L
#define CONFIG_ADDR 0xcf8
#define CONFIG_DATA 0xcfc

typedef unsigned long DWORD;
typedef unsigned int WORD;
typedef unsigned long DWORD;

int main ()
{
WORD bus, dev, fun;
DWORD addr, data;
int ret;
printf ( "bus # \ tdev # \ tfun # \ t");
printf ( "\ n");
ret = iopl (3);
if (ret < 0)
{
perror ( "iopl set error");
return -1;
}
for (bus = 0; bus < = PCI_MAX_BUS; bus ++)
for (dev = 0; dev < = PCI_MAX_DEV; dev ++)
for (fun = 0; fun < = PCI_MAX_FUN; fun ++)
{
addr = PCI_BASE_ADDR | (bus < < 16) | (dev < < 11) | (fun < < 8);
outl (addr, CONFIG_ADDR);
data = inl (CONFIG_DATA);
if ((data! = 0xffffffff) && (data! = 0))
{
printf ( "% 2x \ t% 2x \ t% 2x", bus, dev, fun);
printf ( "\ n");
}
}
ret = iopl (0);
if (ret < 0) {
perror ( "iopl set error");
return -1;
}
return 0;

}

table of Contents

Foreword
mmio
mmio way dos environment traversal pci-e
Linux environment
back to the top
Foreword

Today, the company in fact, I did not do anything, but mmio form yesterday put pcie traversing made out, praised the company's Taiwan server, at least I can come and go use google search I want information and answers, there is a big God in Taiwan on've posted a blog post, directed to a method mmio the dos environment in the country by Baidu, etc. the method is not accessible to the course, the most disappointing is that if I do not open proxy, directly enter the URL is inaccessible , there may be a lot of people think you traverse pcie why? Hey, that is to tell you how to access my computer inside the door at the bottom of the device through the code, which is a much-needed capability. Well, not passing the buck, and you Xiaobian dos environment and a variety of access methods into the Linux system by c language and compiled mode.

back to the top
mmio

There may be a lot of people have some questions about mmio access mode, now Xiao Bian gave you the popularity of it, of course, there are a lot of information from the network, small refer too much information, not one where thank a. Speaking mmio, Xiao Bian will give you some of the popularity of the concept, especially when some of the concepts 4gb address space, will help you to understand these concepts.

MMIO (Memory mapping I / O) that is memory-mapped I / O, it is part of the PCI specification, I / O devices are placed in memory space instead of I / O space. From the perspective of the processor, memory-mapped I / O devices to access the system memory and up the same. Such access to the frame buffer AGP / PCI-E graphics card, BIOS, PCI devices can be used to read and write the same memory complete assembly instructions, simplifying the complexity and difficulty of programming interfaces. A channel I / O CPU and peripherals to communicate, be divided into two types, one is the Port I / O, one is MMIO (Memory mapping I / O).

Then these mechanisms have to mention the memory map, memory mapping mechanism comes in we want to access the pci-e is very useful.

Memory map, in a nutshell is to map some memory area of the user space to kernel space, after mapping is successful, the user can modify this memory area directly reflected in kernel space. Similarly, changes to the kernel space of this region is also directly reflects the user space. Then the kernel space < ----> User space is required between the two, then the efficiency of large amounts of data transfer and other operations is very high.

mmio way dos environment traversal pci-e

In the dos environment, you need to open the protective mechanism, access to 32-bit data format is 16-bit access in dos, and then through the corresponding assembly and machine code, related operations, which is not very understanding of small series , you may wish to refer to the Great God of Taiwan blog, I also refer to the programming of his blog made under dos system.

#include < stdio.h>
#include < dos.h>
#define BaseAddr 0xF8000000
typedef unsigned long DWORD;
// Open
void openA20 ()
{While (inp (0x64) & 2); outp (0x64,0xd1);
while (inp (0x64) & 2); outp (0x60,0xdf);
while (inp (0x64) & 2); outp (0x64,0xff);
}
unsigned long GDT_def [] = {0,0,0x0000FFFF, 0x008F9200};
unsigned char GDT_Addr [6] = {0};
void set4gb ()
{Asm {
cli
push ds; push es
mov word ptr GDT_Addr [0], (2 * 8-1)
mov eax, ds
shl eax, 4
xor ebx, ebx
mov bx, offset GDT_def
add eax, ebx
mov dword ptr GDT_Addr [2], eax
lgdt fword ptr GDT_Addr
mov bx, 8
mov eax, cr0
or al, 1
mov cr0, eax
jmp flush1
}
flush1: asm {
mov ds, bx
mov es, bx
and al, 0feh
mov cr0, eax
jmp flush2
}
flush2: asm {
pop es; pop ds
sti
}
}
DWORD ReadMemByPM (DWORD addr)
{
    DWORD result;
    _asm {
push ds;
mov ax, 0;
mov ds, ax;
mov esi, addr;
mov eax, [esi];
mov result, eax;
pop ds;
    }
    return result;
}

DWORD ReadMem (DWORD mAddr)
{
#ifdef DEBUG
printf ( "this Memory is 0x% llX \ n", mAddr);
#endif
DWORD result = 0;
_asm {
push eax;
mov eax, [mAddr];
mov result, eax;
pop eax;
}
return result;
}
int main () {
DWORD busNum, devNum, funNum, result = 0, addr, CabID, mOffset, DevPortType;
DWORD vendorID, deviceID, LinkWidth, LinkSpeed;
char * PortType [] = { "PCI-E Endpoint", "Leg PCIE Endpoint", "Root Complex", "Upstream PCI-E Switch", "Downstream PCI-E Switch", "PCI-E to PCI Bridge", "PCI to PCI-E Bridge", "Igrd Endpoint", "Event Collector", "null"}, TypeIndex;
char * SpeedType [] = { "2.5G / S", "2.5G / S OR 5G / S", "2.5G / S OR 5G / S OR 8G / S", "NO Speed"}, SpeedIndex;
openA20 ();
set4gb ();
printf ( "busNum devNum funNum \ t vendorID deviceID type \ tWidth \ tSpeed \ n");
for (busNum = 0; busNum < 16; busNum ++)
for (devNum = 0x0; devNum < 32; devNum ++)
for (funNum = 0; funNum < 8; funNum ++)
{
addr = (0xF8000000) | (busNum < < 20) | (devNum < < 15) | (funNum < < 12);
result = ReadMemByPM (addr);
if (result! = 0xffffffff)
{
result = ReadMemByPM (addr | 0x34);
mOffset = result & 0x000000ff;
LinkWidth = 0;
LinkSpeed = 0;
while (1)
{
result = ReadMemByPM (addr | mOffset);
CabID = result & 0x000000ff;
if (CabID == 0x00000010) {
result = ReadMemByPM (addr);
vendorID = result & 0x0000ffff;
deviceID = (result & 0xffff0000) >> 16;
result = ReadMemByPM (addr | mOffset);
DevPortType = (result & 0x00f00000) >> 20;
switch (DevPortType)
{
case 0x0: TypeIndex = 0; break;
case 0x1: TypeIndex = 1; break;
case 0x4: TypeIndex = 2; break;
case 0x5: TypeIndex = 3; break;
case 0x6: TypeIndex = 4; break;
case 0x7: TypeIndex = 5; break;
case 0x8: TypeIndex = 6; break;
case 0x9: TypeIndex = 7; break;
case 0xa: TypeIndex = 8; break;
default: TypeIndex = 9; break;
}
result = ReadMemByPM (addr + mOffset + 0x0C);
LinkSpeed = (result & 0x0000000f);
switch (LinkSpeed) {
case 0x1: SpeedIndex = 0; break;
case 0x2: SpeedIndex = 1; break;
case 0x3: SpeedIndex = 2; break;
default: SpeedIndex = 3; break;
}
LinkWidth = (result & 0x000003f0) >> 4;
printf ( "% 2.2llx \ t% 2.2llx \ t% 2.2llx \ t% 4.4llx \ t% 4.4llx% s X% 2lu% s \ n", busNum, devNum, funNum, vendorID, deviceID, PortType [TypeIndex ], LinkWidth, SpeedType [SpeedIndex]);
break;
} Else {
mOffset = (result & 0x0000ff00) >> 8;
if (mOffset == 0x00000000)
break;
}
}
}
}
  return 0;
}
Here should be noted that the base address of your computer is not 0xF8000000.

Linux environment

Mentioned linux would have to say under a api Linux, mmap.

mmap system call

mmap a file or other object is mapped into memory. File is mapped onto multiple pages, if the size of the file size is not all pages and the last page is not used space will be cleared. munmap performs the reverse operation to delete a specific address area object mapping.
When using mmap mapping files to process, you can directly manipulate the virtual address this and other documents to read and write operations, without having to call the read, write and other system calls. But take note, the direct memory segment when writing is not written more than the contents of the current file size.

Uses shared memory communication is an obvious benefit of high efficiency, because the process can directly read and write memory, without the need to copy any data. For pipes and message queues as other means of communication, you need the kernel and user space to copy data four times, and the only copy of the shared memory data twice: once from the input file to a shared memory area, and another from the shared memory area to output file. In fact, when the shared memory between processes is not always a small amount of data read and write after the unmapped, new communication, re-create the shared memory area. But remain shared area, up until the communication is completed, so that the data content has been stored in the shared memory and not written back to the file. Shared memory content is often when you write the file is unmapped. Therefore, the use of shared memory communication efficiency is very high.

Mapping file based, and at any moment munmap mmap implementation process is mapped file st_atime may be updated. If st_atime field in the foregoing case has not been updated for the first time when the first index page mapping area will update the value of the field. Established by PROT_WRITE and MAP_SHARED logo file mapping, and its st_ctime st_mtime After the mapping area is written, but msync () will be updated prior to the adoption MS_SYNC and MS_ASYNC two flags calls.
usage:

void mmap (void start, size_t length, int prot, int flags, int fd, off_t offset);
int munmap (void * start, size_t length);
Back Description:
When successfully executed, mmap () returns a pointer to the mapped area, munmap () returns 0. Failure, mmap () returns MAP_FAILED [whose value (void *) - 1], munmap returns -1. errno is set to a value below

EACCES: Access Error
EAGAIN: file is locked, or too much memory has been locked
EBADF: fd is not a valid file descriptor
EINVAL: One or more parameters are invalid
ENFILE: system limit of open files has been reached
ENODEV: Specifies the file where the file system does not support memory mapping
ENOMEM: Insufficient memory or the process has exceeded the maximum number of memory map
EPERM: lack of power, the operation is not allowed
ETXTBSY: open the file has been written, specifying MAP_DENYWRITE flag
SIGSEGV: Try to write to read-only area
SIGBUS: try to access the memory area is not part of the process
parameter:
start: Start address mapping area.
length: length of the mapped area.
prot: the desired memory protection flag, can not conflict with the open mode of the file. The following is a value that can reasonably be grouped together or by operation
PROT_EXEC // page content can be executed
PROT_READ // pages can be read
PROT_WRITE // pages can be written
PROT_NONE // page inaccessible

flags: Specifies the type of object mapping, mapping options and whether the map pages can be shared. Its value can be one or more of the following bit combination

MAP_FIXED // use the specified mapping start address, if specified by start and len parameter memory area overlaps the existing mapping space, the overlapped portion will be discarded. If you specify a starting address is not available, the operation will fail. And the starting address must fall on page boundaries.
MAP_SHARED // mapping space shared with all other objects of this mapping process. To write to the shared area, equivalent to the output to a file. Until msync () or munmap () is called, the file will not actually be updated.
MAP_PRIVATE // build private mapped a written copy. Write memory area will not affect the original file. This flag and the flag above are mutually exclusive and can only use one of them.
MAP_DENYWRITE // This flag is ignored.
MAP_EXECUTABLE // Ibid.
MAP_NORESERVE // Do this mapping reserved swap space. When swap space is reserved to modify the mapping area may be ensured. When swap space is not reserved, while insufficient memory, modify the mapping area will cause violation signal segment.
MAP_LOCKED // lock mapping area of the page so as to prevent the page is swapped out.
MAP_GROWSDOWN // stack used to tell the kernel VM system that the mapping area can be extended downward.
MAP_ANONYMOUS // anonymous mapping, the area is not associated with any file.
MAP_ANON // MAP_ANONYMOUS nicknames are no longer used.
MAP_FILE // compatible flag is ignored.
MAP_32BIT // map the area on the lower 2GB of the process address space will be ignored MAP_FIXED specified. This flag is currently only supported on x86-64 platform.
MAP_POPULATE // file mapping prepared by pre-reading the page table good way. Subsequent access mapping zone is not blocked pages violation.
MAP_NONBLOCK // Only makes sense when used together and MAP_POPULATE. Do not read ahead, just as the establishment of a page table entry in memory page.

fd: a valid file descriptor. If MAP_ANONYMOUS is set to compatibility issues, and its value should be -1.

offset: the starting point is mapped contents of the object.

System call munmap ()

int munmap (void * addr, size_t len)
The call to lift in the process address space mapping relationship, addr is returned when you call to mmap () address, len is the size of the mapped region. After the dissolution of the mapping, mapping access to the original address will cause a segmentation fault occurs.

System call msync ()

int msync (void * addr, size_t len, int flags)
In general, the process of changing the mapping space of shared content is not directly written back to disk files, often calling munmap () after the operation. Content can be achieved with the contents of the file on the disk shared memory area unanimously by calling msync ().

System call mmap () for shared memory in two ways:

(1) using ordinary document provides memory mapping: apply between any process; In this case, you need to open or create a file, and then call mmap (); typical calling code as follows:

fd = open (name, flag, mode);
if (fd < 0)
...
ptr = mmap (NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Place) achieved by mmap (shared memory communication and has many features to be noted

(2) the use of special memory-mapped files provide anonymous: for having a genetic relationship between the process; the parent and child special relationship, the parent process first call mmap (), then call fork (). So after calling fork (), the child inherits the parent process anonymous mapped address space, also inherited mmap () return address, so that parent and child can communicate through the mapped region. Note that this is not an ordinary inheritance. In general, the child process maintained separately inherited from the parent process variables. The mmap () return address, but maintained by the parent and child.
For processes with genetic relationship of shared memory is the best way to achieve should be anonymous memory mapping method. At this time, do not specify a specific file, you can simply set the corresponding flag.

Principle mmap memory-mapped

The ultimate goal is to mmap system call, device or file mapped to the user process's virtual address space and the user process to read and write directly to the file, this task can be divided into the following three steps:

Looking for free to meet the requirements of a contiguous virtual address space in user virtual address space mapped to prepare (by the kernel mmap system call) for each user process has 3G bytes of virtual memory space. However, this does not mean that any user process can be used within the scope of this 3G, because virtual memory space is mapped to the final was a physical storage space (memory or disk space), you can really use.

So, how to manage the kernel virtual memory space for each process 3G it? In a nutshell, the user process compiled, image files link formed have a code and data segments (including data and bss segments), wherein the lower code segment, data segment on. Data segment includes all statically allocated data space, that all global variables and local variables declared as static, and these spaces are the basic requirements necessary for the process, these spaces are in the process of establishing a good run image allocated. In addition, the use of stack space is also a fundamental requirement, it is also in the process of establishing the allocation of good.

In the kernel, so that each region with a structure struct vm_area_struct to represent. It describes a contiguous, with the same virtual memory space access attributes, the size of the virtual memory space is an integer multiple of the physical memory pages. You can use the cat / proc // maps to see a process of memory usage, pid is the process ID of each line corresponds to a vm_area_struct which shows the structure of the process.
Here is the definition of struct vm_area_struct structure:

#include < linux / mm_types.h>

/ * This struct defines a memory VMM memory area. * /

struct vm_area_struct {
struct mm_struct * vm_mm; / * VM area parameters * /
unsigned long vm_start;
unsigned long vm_end;

/ * Linked list of VM areas per task, sorted by address * /
struct vm_area_struct * vm_next;
pgprot_t vm_page_prot;
unsigned long vm_flags;

/ * AVL tree of VM areas per task, sorted by address * /
short vm_avl_height;
struct vm_area_struct * vm_avl_left;
struct vm_area_struct * vm_avl_right;

/ * For areas with an address space and backing store,
vm_area_struct * vm_next_share;
struct vm_area_struct ** vm_pprev_share;
struct vm_operations_struct * vm_ops;
unsigned long vm_pgoff; / * offset in PAGE_SIZE units, * not * PAGE_CACHE_SIZE * /
struct file * vm_file;
unsigned long vm_raend;
void * vm_private_data; / * was vm_pte (shared mem) * /
};
Typically, the process used by the virtual memory space is not continuous, and each part of the virtual memory space access attributes can be different. So the virtual memory space of a process that requires multiple vm_area_struct to describe the structure. The number vm_area_struct structure less time, each vm_area_struct sorted in ascending order, in the form of a single list of organizational data (through vm_next vm_area_struct pointer to the next structure). However, when the data structure vm_area_struct more time, still using the list of organizations, it is bound to affect the search speed. To address this issue, vm_area_struct also added vm_avl_hight (height), vm_avl_left (left child), vm_avl_right (right child) three members to implement an AVL tree to improve vm_area_struct search speed.

If the vm_area_struct describes the virtual memory space of a file mapping, they point to the file structure members vm_file mapped files, vm_pgoff is the virtual memory address space starting at vm_file file inside the file offset in the physical page.

Therefore, mmap system call to complete the work is to prepare such a virtual memory space, and the establishment of vm_area_struct structure, which was passed to a specific device driver.
Here is what I wrote to share the linux mmio traversal.

#include < stdio.h>
#include < sys / types.h>
#include < sys / stat.h>
#include < fcntl.h>
#include < stdlib.h>
#include < unistd.h>
#include < sys / mman.h>
// # Include < linux / pci.h>

// # Define DEBUG1

#define PCI_MAX_BUS 2
#define PCI_MAX_DEV 31
#define PCI_MAX_FUN 7
#define PCI_BASE_ADDR 0xfc000000L
#define LEN_SIZE sizeof (unsigned long)
#define SIZE 4096


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


                    
                            
void typeshow (BYTE Type) {
    switch (Type) {
      case 0x0f: {
               printf ( "endpoint \ t");
               break;
                 }
      case 0x1f: {
             printf ( "legacy endpoint \ t");
                 break;
               }
      case 0x4f: {
             printf ( "root complex \ t");
                break;
              }
      case 0x5f: {
             printf ( "upstream pci-e switch \ t");
             break;
                }
      case 0x6f: {
             printf ( "downstream pci-e switch \ t");
             break;
             }
      case 0x7f: {
            printf ( "pci-e to pci bridge \ t");
             break;
              }
      case 0x8f: {
             printf ( "pci to pci-e bridge \ t");
             break;
              }
     case 0x9f: {
             printf ( "root co inte endpoint \ t");
             break;
               }
     case 0xaf: {
             printf ( "root co event endpoint \ t");
             break;
                }
     defult: {
             printf ( "b \ t");
             break;
            }
      }
       
}

void speedshow (int speed) {
    if (speed == 0x0) {
            printf ( "speed is 2.5G / s \ t");
         }
    else if (speed == 0x2) {
            printf ( "speed is 5G / s \ t");
         }
    else if (speed == 0x4) {
            printf ( "speed is 8G / s \ t");
         }
    else {
           printf ( "no speed \ t!");
        }
}
void linkspeedshow (int flag) {
     switch (flag) {
         case 0x1: {
            printf ( "link speed 0 \ t");
            break;
              }
         case 0x2: {
            printf ( "link speed 1 \ t");
            break;
              }
         case 0x3: {
            printf ( "link speed 2 \ t");
            break;
              }
         case 0x4: {
            printf ( "link speed 3 \ t");
            break;
              }
         case 0x5: {
            printf ( "link speed 4 \ t");
            break;
              }
         case 0x6: {
            printf ( "link speed 5 \ t");
            break;
              }
         case 0x7: {
            printf ( "link speed 6 \ t");
            break;
              }
         default:
               {
             printf ( "no speed \ t!");
              break;
              }
     }
}
void linkwidthshow (int flag) {
    printf ( "linkwidth:");
    switch (flag) {
           case 0x00: {
                   printf ( "reserved \ t");
                   break;
                 }
           case 0x01: {
                   printf ( "x1 \ t");
                   break;
                 }
           case 0x02: {
                   printf ( "x2 \ t");
                   break;
                 }
           case 0x04: {
                   printf ( "x4 \ t");
                   break;
                 }
           case 0x08: {
                   printf ( "x8 \ t");
                   break;
                 }
           case 0x0c: {
                   printf ( "x12 \ t");
                   break;
                 }
           case 0x10: {
                   printf ( "x16 \ t");
                   break;
                 }
           case 0x20: {
                   printf ( "x32 \ t");
                   break;
                 }
           default: {
                    printf ( "null \ t");
                 }
  }
}

int main ()
{
    DWORD addr = 0;
    WORD bus, dev, fun;
    WORD * DATA;
    WORD * dwDATA;
    BYTE nextPoint;
    int fd, i = 1;
    fd = open ( "/ dev / mem", O_RDWR);
    if (fd < 0)
    {
      printf ( "can not open port \ n!");
    }
#ifdef DEBUG
    printf ( "fd =% d \ n", fd);
#endif
     for (bus = 0; bus < = PCI_MAX_BUS; bus ++)
        for (dev = 0; dev < = PCI_MAX_DEV; dev ++)
           for (fun = 0; fun < = PCI_MAX_FUN; fun ++)
              {
                 addr = 0;
                 addr = PCI_BASE_ADDR | (bus < < 20) | (dev < < 15) | (fun < < 12);
                 DATA = mmap (NULL, LEN_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr);
                 if (DATA == (void *) - 1)
                 {
                     munmap (DATA, LEN_SIZE);
                     break;
                 }
                 if (* DATA! = 0xffffffff)
                 {
                    nextPoint = (BYTE) (* (DATA + 0x34 / 4));
                    dwDATA = DATA + nextPoint / 4;
                     #ifdef DEBUG1
                    printf ( "nextpoint =% x \ n", nextPoint);
                    printf ( "addr1 =% x \ n", * dwDATA);
                     #endif
                 while (1) {
                    if ((BYTE) * (dwDATA) == 0x10)
                     {
                             
                             printf ( "PCI-E:");
                             printf ( "bus # =% x, dev # =% x, fun # =% x \ t", bus, dev, fun);
                             printf ( ". vender id:% 4x \ t", * DATA & 0xffff);
                             printf ( ". device id:% 4x \ t", ((* DATA) >> 8) & 0XFFFF);
                             printf ( "\ ntype:");
                             typeshow ((BYTE) ((* dwDATA) >> 8) | 0x0f);
                             speedshow (* (dwDATA + 0x2c / 4) >> 1 & 0xf);
                          // Linkspeedshow (* (dwDATA + 0x0c / 4) & 0xf);
                             linkwidthshow ((* (dwDATA + 0x0c / 4) >> 4) & 0x3f);
                             printf ( "\ n");
                             break;
                     }
                     dwDATA = DATA + ((* (dwDATA) >> 8) & 0xff) / 4;
                     #ifdef DEBUG1
                     printf ( "dwDATA =% x \ n", * dwDATA);
                     #endif
    
                     if ((BYTE) (* (dwDATA)) == 0x00)
                     break;
                     }
                 #ifdef DEBUG
                    printf ( "bus =% x, dev =% x, fun =% x \ n", bus, dev, fun);
                    for (i = 0; i < 0; i ++)
                    {
                        printf ( "data% d:% x \ n", i, * (DATA + i));
                    }
                   printf ( "next Point:% x \ n", nextPoint);
                   printf ( "data:% x \ n", (BYTE) * (DATA + nextPoint / 4));
                 #endif
                    
                 
                 }
                  munmap (DATA, LEN_SIZE);
              }
    close (fd);
    return 0;
}
     
         
         
         
  More:      
 
- apt-get install openstack pkg Troubleshooting (Linux)
- Linux firewall iptables beginner tutorial (Linux)
- Share useful bash aliases and functions (Linux)
- Nginx version of helloworld (Server)
- How to Install SeaMonkey 2.25 for Ubuntu (Linux)
- GitLab upgrade to 8.2.0 (Linux)
- Linux systems dmesg command processing failures and system information collected seven usage (Linux)
- Nine artifact control disk partition under Linux (Linux)
- HAProxy performance under high concurrency (Server)
- SSH configuration under Linux (Linux)
- String JavaScript type system (Programming)
- Increase ssh security service under Linux (Linux)
- How to create a binary distribution with Bash (Linux)
- Linux Firewall Builder shorewall (Linux)
- About phpwind 5.01-5.3 0day analysis of the article (Linux)
- About Hibernate cache, you want the latest data have trouble even session.clear (Database)
- To install PostgreSQL 9.4 (Database)
- C ++ Supplements --new delete overload (Programming)
- Understanding Java classes (Programming)
- To restore the last time applications running when Ubuntu user log in again (Linux)
     
           
     
  CopyRight 2002-2020 newfreesoft.com, All Rights Reserved.