TheLinux pci interface provides a mechanism to accessthe PCI bus address spaces from user programs.
Performing programmed I/O on pci devices on SGILinux systems involves the following steps:
Examine /proc/bus/pci/devices and obtain offsets for thebase address registers (BARs) of the devices that you want to map. Theformat of the lines is as follows (with field widths in the number ofhexadecimal characters shown, and line breaks added for readability):
bus:2x (slotnumber<<3_|_fn):2x vend:8x bar0 bar1 bar2 bar3 ... |
For example:
if ((fptr = fopen( "/proc/bus/pci/devices", "r")) == NULL) { printf( "Unable to open /proc/bus/pci/devices\n" ); } while(fgets(buf, sizeof(buf) - 1, fptr)) { sscanf( buf, "%2x%2x %8x %*x %lx %lx %lx %lx %lx %lx %lx %lx %*lx %*lx %*lx %*lx %*lx %*lx", &sbus, &sdevfn, &svend, &sbar[0], &sbar[1], &sbar[2], &sbar[3], &sbar[4], &sbar[5], &sbar[6], &sbar[7]); if(( sbus == bus ) && (sdevfn == devfn)) { /* This is the bus, slot and function we're looking for, * so save the base address register offset information. */ for(int i=0; i> 16; device = svend & 0xffff; } } fclose( fptr ); |
Open the appropriate device file for the bus,slot, and function in which you are interested. The device files are namedas follows:
/proc/bus/pci/bus/slot.function |
For example:
memfile = (char*) malloc( 32 ); sprintf( memfile, "/proc/bus/pci/%02d/%02d.%d", bus, slot, function ); fd = open( memfile, O_RDWR ); |
Set the memory map state for the file to MEM space using the PCIIOC_MMAP_IS_MEM requestto the ioctl() system call.
For example:
ioctl(fd, PCIIOC_MMAP_IS_MEM); |
Map the opened file, using the offset obtainedin step 1 as the offsetparameter.
For example:
tmpPtr = (char *) mmap( NULL, (size_t) len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t) offset[bar]); |
For a complete example, see Appendix D, “Reading MAC Addresses Sample Program”.
For details about kernel-level PCI device drivers, see the Linux Device Driver Programmer's Guide-Porting to SGI Altix Systems,
联系客服