pciba(7M)
pciba - User level PCI Bus Adapter interface.
As shipped in IRIX 6.5. First release of IRIX 6.5.
NAME pciba - User level PCI Bus Adapter interface. DESCRIPTION The pciba interface provides a mechanism to access the PCI bus address spaces, route PCI interrupts, and obtain PCI addresses for DMA from user programs. It is intended to provide a convenient mechanism for writing user level PCI device drivers. Activating the pciba driver The device driver that provides pciba services is a loadable device driver, which may or may not be automatically loaded during the boot of your system. The simplest way to find out if this driver is active in your system is to check the list of currently registered device drivers: % ml list | grep pciba If there is no output, then the driver is not present and must be loaded before use. To load the driver: # lboot -L pciba If the driver is not active for a while, the system will keep it registered but remove it from memory, reloading the driver when it is again needed. You can explicitly remove the driver from the system: # ml list | awk '/pciba/ { printf "lboot -U %d\n", $2; }' | sh Finding your device under /hw When the system boots, it builds a graph of all devices within the system; later, that graph is made available as a filesystem at the /hw mount point. Knowing the PCI ID word from your device, you can find where it sits under /hw fairly quickly by looking in one central location. There is a directory /hw/.id/pci/IDWORD/ where IDWORD is replaced by the eight-digit hexidecimal value from the ID word. For instance, look in the directory /hw/.id/pci/10A90003/ to find all the instances of SGI's standard IOC3 chip, which uses VENDOR 0x10A9 and DEVICE 0x0003. Inside this directory you will find symbolic links to the real locations within /hw where your device has been found. IOCTL Services Vertex /hw/.../pci/slot/config supports the following ioctl commands: PCIIOCCFGRD(type, register) - read a config register PCIIOCCFGWR(type, register) - write a config register In these macros, type is the data type being moved around (generally char, short or int) and register is the byte offset within the configuration space, generally obtained by using a macro supplied from the <sys/PCI/PCI_defs.h> header file. Some registers that are commonly accessed are wrapped up into single macros: PCIIOCGETID - read slot's PCI Identification register. PCIIOCSETCMD - write slot's PCI Command register. PCIIOCGETREV - read slot's PCI Device Revision register. PCIIOCGETHTYPE - read slot's PCI Device Header Type register PCIIOCGETBASE(n) - read slot's PCI BASE(n) register. Vertex /hw/.../pci/slot/dma supports the following ioctl commands: PCIIOCDMAALLOC - Allocate a buffer for User DMA. The parameter should be a pointer to a 64-bit variable containing either simply the size of the transfer, or the result of packing some PCIIO DMA flags with the size using the PCIIOCDMAALLOC_REQUEST_PACK(flags, size) macro (which just places the flags in the upper 32 bits of the value). All blocks allocated with PCIIOCDMAALLOC should be explicitly released with PCIIOCDMAFREE before the device is closed, after making sure that there is no longer any outstanding DMA to the target. PCIIOCDMAFREE - Destroy a User DMA buffer. The parameter is a pointer to a 64-bit variable containing the PCI address of a DMA buffer previously allocated by a PCIIOCDMAALLOC request. Vertex /hw/.../pci/slot/intr supports the following ioctl commands: PCIIOCSETULI(n) - set up a ULI The value n in the command is a bitmap of which interrupts are to be routed from the board, formed as the inclusive-or of one or more PCIIO_INTR_LINE macros. The parameter is a pointer to a struct uliargs appropriately filled in. Memory Mapping Services Memory mapping vertex /hw/.../pci/slot/base/bar returns a pointer that can be used to initiate PIO access to the PCI space and offset that the system expects the PCI device in slot to decode with its BASE address register bar. One such node is created for each BASE register that the system observes and sets up. Memory mapping vertex /hw/.../pci/slot/mem returns a pointer similar to the bar case above for the first BASE register that decodes PCI MEM space. If no BASE registers on this device decode PCI MEM space, this vertex will not be present. Memory mapping vertex /hw/.../pci/slot/io returns a pointer similar to the bar case above for the first BASE register that decodes PCI I/O space. If no BASE registers on this device decode PCI I/O space, this vertex will not be present. Memory mapping vertex /hw/.../pci/slot/rom returns a pointer that can be used to initiate PIO access to the PCI space and offset that the system expects the PCI device in slot to decode with its Expansion Rom BASE address register. If the card does not advertise an Expansion Rom, then this vertex will not be present. Memory mapping vertex /hw/.../pci/slot/dma using as offset the PCI address retured by an PCIIOCDMAALLOC ioctl command will provide an appropriate user mapping into the memory allocated for user-initiated DMA. Any mmap request that does not precisely match the PCI address and size of an allocated User DMA block will fail. Each such mmap call needs to be matched with a corresponding munmap call before the block is returned using PCIIOCDMAFREE or the device is explicitly closed. Memory mapping vertex /hw/.../pci/mem provides a PIO pointer that resolves to any arbitrary location within the PCI MEM address space. Memory mapping vertex /hw/.../pci/io provides a PIO pointer that resolves to any arbitrary location within the PCI I/O address space. BYTE SWAPPING ISSUES MIPS processors and the PCI bus disagree on the relative significance of the individual bytes in a multiple-byte data item. Like many modern RISC processors, the MIPS chips prefer to store the most significant byte at the first address in memory, with bytes of lower significance following it. The PCI bus follows the convention that the lowest-numbered byte has the lowest significance, and it is followed by bytes in increasing significance order. The upshot of this is, hardware implementers have a choice over how to interconnect the byte lanes of the PCI bus to the byte lanes of the system native bus. Do they connect them up by bits, so that data items the width of the PCI bus come across with the correct values, or do they connect them so that the address of each individual byte is invariant? In a configuration where 32-bit word values are preserved across the interface, the host processor must modify addresses for items smaller than a 32-bit word. Specifically, to access bytes, the address (or the byte offset from an aligned address, which is usually easier) must be XORed with 3, and to access 16-bit data, the address must be XORed with 2. SGI's PCI support codde gives this byte lane configuration the name WORD_VALUES. In a configuration where each byte's address is precisely maintained, every data item is at its correct address; and, unless the device is one of the rare big-endian PCI devices, the bytes of any multibyte quantity are in reversed significance and must be reversed before storing or after reading. SGI's PCI support codde gives this byte lane configuration the name BYTE_STREAM. When this driver is asked for mappings to devices, it provides mappings using WORD_VALUES, since it is more efficient to adjust the byte addresses of items than to swap bytes when accessing two and four byte quantities. There are currently no interfaces to pciba to request BYTE_STREAM mappings. NOTES If the system does not support ULI, the /hw/.../pci/slot/intr vertex will not be present. If a boot prom allocates PCI space and sets up a device's BASE registers, and the values are not page aligned, pciba is unable to provide direct mmap service for those windows, and the corresponding /hw/.../pci/slot/base/bar, /hw/.../pci/slot/mem and /hw/.../pci/slot/io verticies will not exist. Such missing windows can still be accessed, as can any area decoded by a BASE register, by the longer method of using a PCIIOCGETBASE(n) ioctl command on the /hw/.../pci/slot/config vertex to get the content of the BASE(n) register. If this value is odd, mask off the last two bits and use the resulting value as the offset for mmap of the /hw/.../pci/io vertex. If the value was even, mask off the last four bits and use the resulting value as the offset for mmap of the /hw/.../pci/mem vertex. Changes from the usrpci driver The most obvious change from the usrpci driver is that the location of nodes in the hardware graph have changed. A device on an IRIX 6.4 or older system that could be accessed using: /hw/module/..../pci/<slot>/usrpci will now be found at: /hw/module/..../pci/<slot> The mem32 and mem64 nodes have been renamed mem. The map size in the usrpci driver was either a big or little window space (16 or 128 MB) but the pciba interface checks the size argument to the mmap call against the addressable size set up by the card in the Base Address Register that defines a particular space.