Chapter 7. PCI Devices

To perform programmed I/O on PCI devices on an SGI UV system, do the following to determine the resource filename (resourceN) and create an appropriate program to open the file and memory-map it:

  1. Examine the output of the lspci(8) command to determine which device you want to map:

    1. Record the domain, bus, slot, and function for the device (this information will help you locate the appropriate resource address file).

      For example:

      # lspci
      ...
      0000:00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev 90)
      0000:00:1f.0 ISA bridge: Intel Corporation 82801JIR (ICH10R) LPC Interface Controller
      0000:00:1f.3 SMBus: Intel Corporation 82801JI (ICH10 Family) SMBus Controller
      0000:01:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
      0000:01:00.1 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
      0000:04:00.0 SCSI storage controller: LSI Logic / Symbios Logic SAS1064ET PCI-Express Fusion-MPT SAS (rev 08)
      0000:05:00.0 VGA compatible controller: Matrox Graphics, Inc. MGA G200e [Pilot] ServerEngines (SEP1) (rev 02)
      ...

      The first field gives the information that is required to map the PCI registers into memory. The format is:

      Domain:Bus:Slot.Function 

      In the above example, the highlighted output of 0000:01:00.1 for the Intel Corporation 82576 Gigabit Network card equates to domain 0, bus 1, slot 0, and function 1.

    2. Determine the resource N numbers from the Region numbers in the lspci -vv output. The Region value corresponds directly to each resourceN value.

      In the following example, the Region N output (highlighted) indicates that there are four resource N values (resource0, resource1, resource2 and resource3 ):

      # lspci -n -s 0000:01:00.1 -vv
      0000:01:00.1 0200: 8086:10c9 (rev 01)
              Subsystem: 10a9:8028
              Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
              Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- SERR- <PERR- INTx-
              Latency: 0, Cache Line Size: 64 bytes
              Interrupt: pin B routed to IRQ 40
              Region 0: Memory at b2140000 (32-bit, non-prefetchable) [size=128K]
              Region 1: Memory at b2120000 (32-bit, non-prefetchable) [size=128K]
              Region 2: I/O ports at 2000 [size=32]
              Region 3: Memory at b2240000 (32-bit, non-prefetchable) [size=16K]
              Expansion ROM at b2100000 [disabled] [size=128K]
              Capabilities: [40] Power Management version 3
                      Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                      Status: D0 PME-Enable- DSel=0 DScale=1 PME-
      ...
      ...
              Kernel driver in use: igb
              Kernel modules: igb

      A device can have both 32-bit and 64-bit base address registers (BARs). If a BAR is mapping a 64-bit address space, then two 32-bit BARs are used to map that 64-bit Region. As a result, Region numbers may not be consecutive. For example, in the following lspci output, there are three Region values (Region 0, Region 1 and Region 3):

      # lspci -n -s 0000:04:00.0 -vv
      0000:04:00.0 0100: 1000:0056 (rev 08)
              Subsystem: 1000:1000
              Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
              Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
              Latency: 0
              Interrupt: pin A routed to IRQ 24
              Region 0: I/O ports at 1000 [size=256]
              Region 1: Memory at b2010000 (64-bit, non-prefetchable) [size=16K]
              Region 3: Memory at b2000000 (64-bit, non-prefetchable) [size=64K]
              Expansion ROM at b1c00000 [disabled] [size=4M]
              Capabilities: [50] Power Management version 2
                      Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
                      Status: D0 PME-Enable- DSel=0 DScale=0 PME-
      ...
      ...
              Kernel driver in use: mptsas
              Kernel modules: mptsas

      There is no Region 2 because the card's second BAR is mapping a 64-bit region and thus uses two 32-bit BARs to do so. In this example, there would be three corresponding resource numbers ( resource0, resource1, and resource3 ) that would be used to memory-map the PCI registers.


      Note: Only memory base-address registers (not I/O base-address registers) can be memory mapped. The base address must be page aligned.


  2. Based on the information in step 1, determine the resource address file that you want to open:

    /sys/bus/pci/devices/domain:bus:slot.function/resourceN

    For the Intel example above, the resource address files are:

    /sys/bus/pci/devices/0000:01:00.1/resource0
    /sys/bus/pci/devices/0000:01:00.1/resource1
    /sys/bus/pci/devices/0000:01:00.1/resource2
    /sys/bus/pci/devices/0000:01:00.1/resource3

    In the case of the LSI Logic® card example showing 64-bit Region values:

    /sys/bus/pci/devices/0000:04:00.0/resource0
    /sys/bus/pci/devices/0000:04:00.0/resource1
    /sys/bus/pci/devices/0000:04:00.0/resource3

  3. Create a program that opens the appropriate resource file for the domain, bus, slot, function, and resource in which you are interested. For example, the C program for the Intel card could include the following lines:

    sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.%x/%s",
           (unsigned)domain, (unsigned)bus, (unsigned)slot, (unsigned)function,
           "resource0");
    if ((fd = open(path, O_RDWR)) == -1) {
      perror("Couldn't open resource file");
      exit(1);
    }

  4. Add a line to the program that will memory-map the opened file from offset 0. For example, in C:

    ptr = mmap( NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    

For details about kernel-level PCI device drivers, see the Linux Device Driver Programmer's Guide,Porting to SGI Altix Systems.