VxWorks API Reference : Driver Libraries
pciConfigLib - PCI Configuration space access support for PCI drivers
pciConfigLibInit( ) - initialize the configuration access-method and addresses
pciFindDevice( ) - find the nth device with the given device & vendor ID
pciFindClass( ) - find the nth occurence of a device by PCI class code.
pciDevConfig( ) - configure a device on a PCI bus
pciConfigBdfPack( ) - pack parameters for the Configuration Address Register
pciConfigExtCapFind( ) - find extended capability in ECP linked list
pciConfigInByte( ) - read one byte from the PCI configuration space
pciConfigInWord( ) - read one word from the PCI configuration space
pciConfigInLong( ) - read one longword from the PCI configuration space
pciConfigOutByte( ) - write one byte to the PCI configuration space
pciConfigOutWord( ) - write one 16-bit word to the PCI configuration space
pciConfigOutLong( ) - write one longword to the PCI configuration space
pciConfigModifyLong( ) - Perform a masked longword register update
pciConfigModifyWord( ) - Perform a masked longword register update
pciConfigModifyByte( ) - Perform a masked longword register update
pciSpecialCycle( ) - generate a special cycle with a message
pciConfigForeachFunc( ) - check condition on specified bus
pciConfigReset( ) - disable cards for warm boot
This module contains routines to support accessing the PCI bus Configuration Space. The library is PCI Revision 2.1 compliant.
In general, functions in this library should not be called from the interrupt level, (except pciInt( )) because Configuration Space access, which is slow, should be limited to initialization only.
The functions addressed here include:
\i - Initialization of the library. \i - Locating a device by Device ID and Vendor ID. \i - Locating a device by Class Code. \i - Generation of Special Cycles. \i - Accessing Configuration Space structures.
The PCI bus is an unterminated, high impedence CMOS bus using reflected wave signalling as opposed to incident wave. Because of this, the PCI bus is physically limited in length and the number of electrical loads that can be supported. Each device on the bus represents one load, including adapters and bridges.
To accomodate additional devices, the PCI standard allows multiple PCI buses to be interconnected via PCI-to-PCI bridge (PPB) devices to form one large bus. Each constituent bus is refered to as a bus segment and is subject to the above limitations.
The bus segment accessible from the host bus adapter is designated the primary bus segment (see figure). Progressing outward from the primary bus (designated segment number zero from the PCI architecture point of view) are the secondary and tertiary buses, numbered as segments one and two, respectively. Due to clock skew concerns and propagation delays, practical PCI bus architectures do not implement bus segments beyond the tertiary level.
--------- | | | CPU | | | --------- | Host bus | ----------------------+-------------------------- ... | ------------ | Bridge 0 | | (host | | adapter) | ------------ | PCI bus segment 0 | (primary bus segment) ----------------------+-------------------------- ... | | | | dev 0 | dev 1 dev 2 | ------------ | | | Bridge 1 | | (P2P) | ------------ | PCI bus segment 1 | (secondary bus segment) ----------------------+-------------------------- ... | | | | dev 0 | dev 1 dev 2 | ------------ | | | Bridge 2 | | (P2P) | ------------ | PCI bus segment 2 | (tertiary bus segment) ----------------------+-------------------------- ... | | | dev 0 dev 1 dev 2For further details, refer to the PCI to PCI Bridge Architecture Specification.I/O MACROS AND CPU ENDIANESS
PCI bus I/O operations must adhere to little endian byte ordering. Thus if an I/O operation larger than one byte is performed, the lower I/O addresses contain the least signficant bytes of the multi-byte quantity of interest.
For architectures that adhere to big-endian byte ordering, byte-swapping must be performed. The architecture-specific byte-order translation is done as part of the I/O operation in the following routines: sysPciInByte, sysPciInWord, sysPciInLong, sysOutPciByte, sysPciOutWord, sysPciOutLong. The interface to these routines is mediated by the following macros:
By default, these macros call the appropriate PCI I/O routine, such as sysPciInWord. For architectures that do not require byte swapping, these macros simply call the appropriate default I/O routine, such as sysInWord. These macros may be redefined by the BSP if special processing is required.
- PCI_IN_BYTE
- read a byte from PCI I/O Space
- PCI_IN_WORD
- read a word from PCI I/O Space
- PCI_IN_LONG
- read a longword from PCI I/O Space
- PCI_OUT_BYTE
- write a byte from PCI I/O Space
- PCI_OUT_WORD
- write a word from PCI I/O Space
- PCI_OUT_LONG
- write a longword from PCI I/O Space
pciConfigLibInit( ) should be called before any other pciConfigLib functions. Generally, this is performed by sysHwInit( ).
After the library has been initialized, it may be utilized to find devices, and access PCI configuration space.
Any PCI device can be uniquely addressed within Configuration Space by the geographic specification of a Bus segment number, Device number, and a Function number (BDF). The configuration registers of a PCI device are arranged by the PCI standard according to a Configuration Header structure. The BDF triplet specifies the location of the header structure of one device. To access a configuration register, its location in the header must be given. The location of a configuration register of interest is simply the structure member offset defined for the register. For further details, refer to the PCI Local Bus Specification, Revision 2.1. Refer to the header file pciConfigLib.h for the defined standard configuration register offsets.
The maximum number of Type-1 Configuration Space buses supported in the 2.1 Specifications is 256 (0x00 - 0xFF), far greater than most systems currently support. Most buses are numbered sequentially from 0. An optional define called PCI_MAX_BUS may be declared in config.h to override the default definition of 256. Similarly, the default number of devices and functions may be overriden by defining PCI_MAX_DEV and/or PCI_MAX_FUNC. Note that the number of devices applies only to bus zero, all others being restricted to 16 by the 2.1 spec.
This is the preferred access mechanism for a PC-AT class machines. It uses two standard PCI I/O registers to initiate a configuration cycle. The type of cycle is determined by the Host-bridge device based on the devices primary bus number. If the configuration bus number matches the primary bus number then a type 0 configuration cycle occurs. Otherwise a type 1 cycle is generated. This is all transparent to the user.
The two arguments used for mechanism 1 are the CAR register address which by default is PCI_CONFIG_ADDR (0xCF8), and the CDR register address which is normally PCI_CONFIG_DATA (0xCFC).
e.g. pciConfigLibInit (PCI_MECHANISM_1, PCI_CONFIG_ADDR, PCI_CONFIG_DATA, NULL);
This is the non-preferred legacy mechanism for PC-AT class machines. The three arguments used for mechanism 2 are the CSE register address which by default is PCI_CONFIG_CSE (0xCF8), and the Forward register address which is normally PCI_CONFIG_FORWARD (0xCFA), and the configuration base address which is normally PCI_CONFIG_BASE (0xC000).
e.g. pciConfigLibInit (PCI_MECHANISM_2, PCI_CONFIG_CSE, PCI_CONFIG_FORWARD, PCI_CONFIG_BASE);
We have added a non-standard access method that we call method 0. Selecting method 0 installs user supplied read and write routines to actually handle configuration read and writes (32 bit accesses only). The BSP will supply pointers to these routines as arguments 2 and 3 (read routine is argument 2, write routine is argument 3). A user provided special cycle routine is argument 4. The special cycle routine is optional and a NULL pointer should be used if the special cycle routine is not provided by the BSP.
All accesses are expected to be 32 bit accesses with these routines. The code in this library will perform bit manipulation to emulate byte and word operations. All routines return OK to indicate successful operation and ERROR to indicate failure.
Initialization examples using special access method 0:
pciConfigLibInit (PCI_MECHANISM_0, myReadRtn, myWriteRtn, mySpecialRtn); -or- pciConfigLibInit (PCI_MECHANISM_0, myReadRtn, myWriteRtn, NULL);The calling convention for the user read routine is:
STATUS myReadRtn (int bus, int dev, int func, int reg, int size, void * pResult);The calling convention for the user write routine is:
STATUS myWriteRtn (int bus, int dev, int func, int reg, int size, UINT32 data);The calling convention for the optional special cycle routine is:
STATUS mySpecialRtn (int bus, UINT32 data);In the Type-1 method, PCI Configuration Space accesses are made by the sequential access of two 32-bit hardware registers: the Configuration Address Register (CAR) and the Configuration Data Register (CDR). The CAR is written to first with the 32-bit value designating the PCI bus number, the device on that bus, and the offset to the configuration register being accessed in the device. The CDR is then read or written, depending on whether the register of interest is to be read or written. The CDR access may be 8-bits, 16-bits, or 32-bits in size. Both the CAR and CDR are mapped by the standard to predefined addresses in the PCI I/O Space: CAR = 0xCF8 and CDR = 0xCFC.The Type-2 access method maps any one configuration header into a fixed 4K byte window of PCI I/O Space. In this method, any PCI I/O Space access within the range of 0xC000 to 0xCFFF will be translated to a Configuration Space access. This access method utilizes two 8-bit hardware registers: the Configuration Space Enable register (CSE) and the Forward register (CFR). Like the CAR and CDR, these regiters occupy preassigned PCI I/O Space addresses: CSE = 0xCF8, CFR = 0xCFA. The CSE specifies the device to be accessed and the function within the device. The CFR specifies the bus number on which the device of interest resides. The access sequence is 1) write the bus number to CFR, 2) write the device location information to CSE, and 3) perform an 8-bit, 16-bit, or 32-bit read or write at an offset into the PCI I/O Space starting at 0xC000. The offset specifies the configuration register within the configuration header which now appears in the 4K byte Configuration Space window.
Be careful to not use pciConfigOutWord, pciConfigOutByte, pciConfigModifyWord, or pciConfigModifyByte for modifying the Command and status register (PCI_CFG_COMMAND). The bits in the status register are reset by writing a 1 to them. For each of the listed functions, it is possible that they will emulate the operation by reading a 32 bit quantity, shifting the new data into the proper byte lane and writing back a 32 bit value.
Improper use may inadvertently clear all error conditions indications if the user tries to update the command bits. The user should insure that only full 32 bit operations are performed on the command/status register. Use pciConfigInLong to read the Command/Status reg, mask off the status bits, mask or insert the command bit changes and then use pciConfigOutLong to rewrite the Command/Status register. Use of pciConfigModifyLong is okay if the status bits are rewritten as zeroes.
/* * This example turns on the write invalidate enable bit in the Command * register without clearing the status bits or disturbing other * command bits. */ pciConfigInLong (bus, dev, func, PCI_CFG_COMMAND, &temp); temp &= 0x0000ffff; temp |= PCI_CMD_WI_ENABLE; pciConfigOutLong (bus, dev, func, PCI_CFG_COMMAND, temp); /* -or- include 0xffff0000 in the bit mask for ModifyLong */ pciConfigModifyLong (bus, dev, func, PCI_CFG_COMMAND, (0xffff0000 | PCI_CMD_WI_ENABLE), PCI_CMD_WI_ENABLE);The above warning applies to any configuration register containing write 1 to clear bits.
After the library has been initialized, the Configuration Space of any PCI device may be accessed after first locating the device.
Locating a device is accomplished using either pciFindDevice( ) or pciFindClass( ). Both routines require an index parameter indicating which instance of the device should be returned, since multiple instances of the same device may be present in a system. The instance number is zero-based.
pciFindDevice( ) accepts the following parameters:
pciFindClass( ) simply requires a class code and the index:
- vendorId
- the vendor ID of the device
- deviceId
- the device ID of the device
- index
- the instance number
In addition, both functions return the following parameters by reference:
- classCode
- the 24-bit class of the device
- index
- the instance number
These three parameters, Bus segment number, Device number, and Function number (BDF), provide a means to access the Configuration Space of any PCI device.
- pBusNo
- where to return bus segment number containing the device
- pDeviceNo
- where to return the device ID of the device
- pFuncNo
- where to return the function number of the device
The PCIbus Special Cycle is a cycle used to broadcast data to one or many devices on a target PCI bus. It is common, for example, for Intel x86-based systems to broadcast to PCI devices that the system is about to go into a halt or shutdown condition.
The special cycle is initiated by software. Utilizing CSAM-1, a 32-bit write to the configuration address port specifying the following
The pciSpecialCycle( ) function facilitates generation of a Special Cycle by generating the correct address data noted above. The data passed to the function is driven onto the bus during the Special Cycle's data phase. The parameters to the pciSpecialCycle( ) function are:
- Bus Number
- is the PCI bus of interest
- Device Number
- is set to all 1's (01Fh)
- Function Number
- is set to all 1's (07d)
- Configuration Register Number
- is zeroed
- busNo
- bus on which Special Cycle is to be initiated
- message
- data driven onto AD[31:0] during the Special Cycle
The routines pciConfigInByte( ), pciConfigInWord( ), pciConfigInLong( ), pciConfigOutByte( ), pciConfigOutWord( ), and pciConfigOutLong( ) may be used to access the Configuration Space of any PCI device, once the library has been properly initialized. It should be noted that, if no device exists at the given BDF address, the resultant behavior of the Configuration Space access routines is to return a value with all bits set, as set forth in the PCI bus standard.
In addition to the BDF numbers obtained from the pciFindXxx functions, an additional parameter specifying an offset into the PCI Configuration Space must be specified when using the access routines. VxWorks includes defined offsets for all of the standard PCI Configuration Space structure members as set forth in the PCI Local Bus Specification 2.1 and the PCI Local Bus PCI to PCI Bridge Architecture Specification 1.0. The defined offsets are all prefixed by "PCI_CFG_". For example, if Vendor ID information is required, PCI_CFG_VENDOR_ID would be passed as the offset argument to the access routines.
In summary, the pci configuration space access functions described above accept the following parameters.
Input routines:
Ouput routines:
- busNo
- bus segment number on which the device resides
- deviceNo
- device ID of the device
- funcNo
- function number of the device
- offset
- offset into the device configuration space
- pData
- where to return the data
- busNo
- bus segment number on which the device resides
- deviceNo
- device ID of the device
- funcNo
- function number of the device
- offset
- offset into the device configuration space
- Data
- data to be written
PciConfigWordIn( ), pciConfigWordOut( ), pciConfigLongIn( ), and pciConfigLongOut( ) check the offset parameter for proper offset alignment. Offsets should be multiples of 4 for longword accesses and multiples of 2 for word accesses. Misaligned accesses will not be performed and ERROR will be returned.
The previous default behaviour for this library was to not check for valid offset values. This has been changed and checks are now done by default. These checks exist to insure that the user gets the correct data using the correct configuration address offsets. The user should define PCI_CONFIG_OFFSET_NOCHECK to achieve the older behaviour. If user code behaviour changes, the user should investigate why and fix the code that is calling into this library with invalid offset values.
The function pciDevConfig( ) is used to configure PCI devices that require no more than one Memory Space and one I/O Space. According to the PCI standard, a device may have up to six 32-bit Base Address Registers (BARs) each of which can have either a Memory Space or I/O Space base address. In 64-bit PCI devices, the registers double up to give a maximum of three 64-bit BARs. The 64-bit BARs are not supported by this function nor are more than one 32-bit BAR of each type, Memory or I/O.
The pciDevConfig( ) function sets up one PCI Memory Space and/or one I/O Space BAR and issues a specified command to the device to enable it. It takes the following parameters:
- pciBusNo
- PCI bus segment number
- pciDevNo
- PCI device number
- pciFuncNo
- PCI function number
- devIoBaseAdrs
- base address of one IO-mapped resource
- devMemBaseAdrs
- base address of one memory-mapped resource
- command
- command to issue to device after configuration
The function pciConfigForeachFunc( ) is used to perform some action on every device on the bus. This does a depth-first recursive search of the bus and calls a specified routine for each function it finds. It takes the following parameters:
- bus
- The bus segment to start with. This allows configuration on and below a specific place in the bus hierarchy.
- recurse
- A boolean argument specifying whether to do a recursive search or to do just the specified bus.
- funcCheckRtn
- A user supplied function which will be called for each PCI function found. It must return STATUS. It takes four arguments: "bus", "device", "function", and a user-supplied arg "pArg". The typedef PCI_FOREACH_FUNC is defined in pciConfigLib.h for these routines. Note that it is possible to apply "funcCheckRtn" only to devices of a specific type by querying the device type for the class code. Similarly, it is possible to exclude bridges or any other device type using the same mechanism.
- pArg
- The fourth argument to funcCheckRtn.
The function pciConfigReset( ) is useful at the time of a system reset. When doing a system reset, the devices on the system should be disabled so that they do not write to RAM while the system is trying to reboot. The function pciConfigReset( ) can be installed using rebootHookAdd( ), or it can be called directly from sysToMonitor( ) or elsewhere in the BSP. It accepts one argument for compatibility with rebootHookAdd( ):
- startType
- Ignored.
Note that this function disables all access to the PCI bus except for the use of PCI config space. If there are devices on the PCI bus which are required to reboot, then those devices must be re-enabled after the call to pciConfigReset( ) or the system will not be able to reboot.
The following code sample illustrates the usage of this library. Initializa- tion of the library is performed first, then a sample device is found and initialized.
#include "drv/pci/pciConfigLib.h" #define PCI_ID_LN_DEC21140 0x00091011 IMPORT pciInt(); LOCAL VOID deviceIsr(int); int param; STATUS result; int pciBusNo; /* PCI bus number */ int pciDevNo; /* PCI device number */ int pciFuncNo; /* PCI function number */ /* * Initialize module to use CSAM-1 * (if not performed in sysHwInit()) * */ if (pciConfigLibInit (PCI_MECHANISM_1, PCI_PRIMARY_CAR, PCI_PRIMARY_CDR, 0) != OK) { sysToMonitor (BOOT_NO_AUTOBOOT); } /* * Find a device by its device ID, and use the * Bus, Device, and Function number of the found * device to configure it, using pciDevConfig(). In * this case, the first instance of a DEC 21040 * Ethernet NIC is searched for. If the device * is found, the Bus, Device Number, and Function * Number are fed to pciDevConfig, along with the * constant PCI_IO_LN2_ADRS, which defines the start * of the I/O space utilized by the device. The * device and its I/O space is then enabled. * */ if (pciFindDevice (PCI_ID_LN_DEC21040 & 0xFFFF, (PCI_ID_LN_DEC21040 >> 16) & 0xFFFF, 0, &pciBusNo, &pciDevNo, &pciFuncNo) != ERROR) { (void)pciDevConfig (pciBusNo, pciDevNo, pciFuncNo, PCI_IO_LN2_ADRS, NULL, (PCI_CMD_MASTER_ENABLE | PCI_CMD_IO_ENABLE)); }
pciConfigLib.h
PCI Local Bus Specification, Revision 2.1, June 1, 1996 PCI Local Bus PCI to PCI Bridge Architecture Specification, Revision 1.0, April 5, 1994"
pciConfigLibInit( ) - initialize the configuration access-method and addresses
STATUS pciConfigLibInit ( int mechanism, /* configuration mechanism: 0, 1, 2 */ ULONG addr0, /* config-addr-reg / CSE-reg */ ULONG addr1, /* config-data-reg / Forward-reg */ ULONG addr2 /* none / Base-address */ )
This routine initializes the configuration access-method and addresses.
Configuration mechanism one utilizes two 32-bit IO ports located at addresses 0x0cf8 and 0x0cfc. These two ports are:
- P"
- 32-bit configuration address port, at 0x0cf8
- P"
- 32-bit configuration data port, at 0x0cfc
Accessing a PCI function's configuration port is two step process.
- P"
- Write the bus number, physical device number, function number and register number to the configuration address port.
- P"
- Perform an IO read from or an write to the configuration data port.
Configuration mechanism two uses following two single-byte IO ports.
- P"
- Configuration space enable, or CSE, register, at 0x0cf8
- P"
- Forward register, at 0x0cfa
To generate a PCI configuration transaction, the following actions are performed.
- -
- Write the target bus number into the forward register.
- -
- Write a one byte value to the CSE register at 0x0cf8. The bit pattern written to this register has three effects: disables the generation of special cycles; enables the generation of configuration transactions; specifies the target PCI functional device.
- -
- Perform a one, two or four byte IO read or write transaction within the IO range 0xc000 through 0xcfff.
Configuration mechanism zero is for non-PC/PowerPC environments where an area of address space produces PCI configuration transactions. No support for special cycles is included.
OK, or ERROR if a mechanism is not 0, 1, or 2.
pciFindDevice( ) - find the nth device with the given device & vendor ID
STATUS pciFindDevice ( int vendorId, /* vendor ID */ int deviceId, /* device ID */ int index, /* desired instance of device */ int * pBusNo, /* bus number */ int * pDeviceNo, /* device number */ int * pFuncNo /* function number */ )
This routine finds the nth device with the given device & vendor ID.
OK, or ERROR if the deviceId and vendorId didn't match.
pciFindClass( ) - find the nth occurence of a device by PCI class code.
STATUS pciFindClass ( int classCode, /* 24-bit class code */ int index, /* desired instance of device */ int * pBusNo, /* bus number */ int * pDeviceNo, /* device number */ int * pFuncNo /* function number */ )
This routine finds the nth device with the given 24-bit PCI class code (class subclass prog_if).
The classcode arg of must be carfully constructed from class and sub-class macros.
Example : To find an ethernet class device, construct the classcode arg as follows:
((PCI_CLASS_NETWORK_CTLR << 16 | PCI_SUBCLASS_NET_ETHERNET << 8))
OK, or ERROR if the class didn't match.
pciDevConfig( ) - configure a device on a PCI bus
STATUS pciDevConfig ( int pciBusNo, /* PCI bus number */ int pciDevNo, /* PCI device number */ int pciFuncNo, /* PCI function number */ UINT32 devIoBaseAdrs, /* device IO base address */ UINT32 devMemBaseAdrs, /* device memory base address */ UINT32 command /* command to issue */ )
This routine configures a device that is on a Peripheral Component Interconnect (PCI) bus by writing to the configuration header of the selected device.
It first disables the device by clearing the command register in the configuration header. It then sets the I/O and/or memory space base address registers, the latency timer value and the cache line size. Finally, it re-enables the device by loading the command register with the specified command.
This routine is designed for Type 0 PCI Configuration Headers ONLY. It is NOT usable for configuring, for example, a PCI-to-PCI bridge.
OK always.
pciConfigBdfPack( ) - pack parameters for the Configuration Address Register
int pciConfigBdfPack ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo /* function number */ )
This routine packs three parameters into one integer for accessing the Configuration Address Register
packed integer encoded version of bus, device, and function numbers.
pciConfigExtCapFind( ) - find extended capability in ECP linked list
STATUS pciConfigExtCapFind ( UINT8 extCapFindId, /* Extended capabilities ID to search for */ int bus, /* PCI bus number */ int device, /* PCI device number */ int function, /* PCI function number */ UINT8 * pOffset /* returned config space offset */ )
This routine searches for an extended capability in the linked list of capabilities in config space. If found, the offset of the first byte of the capability of interest in config space is returned via pOffset.
OK if Extended Capability found, ERROR otherwise
pciConfigInByte( ) - read one byte from the PCI configuration space
STATUS pciConfigInByte ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT8 * pData /* data read from the offset */ )
This routine reads one byte from the PCI configuration space
OK, or ERROR if this library is not initialized
pciConfigInWord( ) - read one word from the PCI configuration space
STATUS pciConfigInWord ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT16 * pData /* data read from the offset */ )
This routine reads one word from the PCI configuration space
OK, or ERROR if this library is not initialized
pciConfigInLong( ) - read one longword from the PCI configuration space
STATUS pciConfigInLong ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT32 * pData /* data read from the offset */ )
This routine reads one longword from the PCI configuration space
OK, or ERROR if this library is not initialized
pciConfigOutByte( ) - write one byte to the PCI configuration space
STATUS pciConfigOutByte ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT8 data /* data written to the offset */ )
This routine writes one byte to the PCI configuration space.
OK, or ERROR if this library is not initialized
pciConfigOutWord( ) - write one 16-bit word to the PCI configuration space
STATUS pciConfigOutWord ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT16 data /* data written to the offset */ )
This routine writes one 16-bit word to the PCI configuration space.
OK, or ERROR if this library is not initialized
pciConfigOutLong( ) - write one longword to the PCI configuration space
STATUS pciConfigOutLong ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT32 data /* data written to the offset */ )
This routine writes one longword to the PCI configuration space.
OK, or ERROR if this library is not initialized
pciConfigModifyLong( ) - Perform a masked longword register update
STATUS pciConfigModifyLong ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT32 bitMask, /* Mask which defines field to alter */ UINT32 data /* data written to the offset */ )
This function writes a field into a PCI configuration header without altering any bits not present in the field. It does this by first doing a PCI configuration read (into a temporary location) of the PCI configuration header word which contains the field to be altered. It then alters the bits in the temporary location to match the desired value of the field. It then writes back the temporary location with a configuration write. All configuration accesses are long and the field to alter is specified by the "1" bits in the bitMask parameter.
Be careful to using pciConfigModifyLong for updating the Command and status register. The status bits must be written back as zeroes, else they will be cleared. Proper use involves including the status bits in the mask value, but setting their value to zero in the data value.
The following example will set the PCI_CMD_IO_ENABLE bit without clearing any status bits. The macro PCI_CMD_MASK includes all the status bits as part of the mask. The fact that PCI_CMD_MASTER doesn't include these bits, causes them to be written back as zeroes, therefore they aren't cleared.
pciConfigModifyLong (b,d,f,PCI_CFG_COMMAND, (PCI_CMD_MASK | PCI_CMD_IO_ENABLE), PCI_CMD_IO_ENABLE);Use of explicit longword read and write operations for dealing with any register containing "write 1 to clear" bits is sound policy.
OK if operation succeeds, ERROR if operation fails.
pciConfigModifyWord( ) - Perform a masked longword register update
STATUS pciConfigModifyWord ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT16 bitMask, /* Mask which defines field to alter */ UINT16 data /* data written to the offset */ )
This function writes a field into a PCI configuration header without altering any bits not present in the field. It does this by first doing a PCI configuration read (into a temporary location) of the PCI configuration header word which contains the field to be altered. It then alters the bits in the temporary location to match the desired value of the field. It then writes back the temporary location with a configuration write. All configuration accesses are long and the field to alter is specified by the "1" bits in the bitMask parameter.
Do not use this routine to modify any register that contains write 1 to clear type of status bits in the same longword. This specifically applies to the command register. Modify byte operations could potentially be implemented as longword operations with bit shifting and masking. This could have the effect of clearing status bits in registers that aren't being updated. Use pciConfigInLong and pciConfigOutLong, or pciModifyLong, to read and update the entire longword.
OK if operation succeeds. ERROR if operation fails.
pciConfigModifyByte( ) - Perform a masked longword register update
STATUS pciConfigModifyByte ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT8 bitMask, /* Mask which defines field to alter */ UINT8 data /* data written to the offset */ )
This function writes a field into a PCI configuration header without altering any bits not present in the field. It does this by first doing a PCI configuration read (into a temporary location) of the PCI configuration header word which contains the field to be altered. It then alters the bits in the temporary location to match the desired value of the field. It then writes back the temporary location with a configuration write. All configuration accesses are long and the field to alter is specified by the "1" bits in the bitMask parameter.
Do not use this routine to modify any register that contains write 1 to clear type of status bits in the same longword. This specifically applies to the command register. Modify byte operations could potentially be implemented as longword operations with bit shifting and masking. This could have the effect of clearing status bits in registers that aren't being updated. Use pciConfigInLong and pciConfigOutLong, or pciModifyLong, to read and update the entire longword.
OK if operation succeeds, ERROR if operation fails.
pciSpecialCycle( ) - generate a special cycle with a message
STATUS pciSpecialCycle ( int busNo, /* bus number */ UINT32 message /* data driven onto AD[31:0] */ )
This routine generates a special cycle with a message.
OK, or ERROR if this library is not initialized
pciConfigForeachFunc( ) - check condition on specified bus
STATUS pciConfigForeachFunc ( UINT8 bus, /* bus to start on */ BOOL recurse, /* if TRUE, do subordinate busses */ PCI_FOREACH_FUNC funcCheckRtn, /* routine to call for each PCI func */ void * pArg /* argument to funcCheckRtn */ )
pciConfigForeachFunc( ) discovers the PCI functions present on the bus and calls a specified C-function for each one. If the function returns ERROR, further processing stops.
pciConfigForeachFunc( ) does not affect any HOST<->PCI bridge on the system.
not set
OK normally, or ERROR if funcCheckRtn( ) doesn't return OK.
pciConfigReset( ) - disable cards for warm boot
STATUS pciConfigReset ( int startType /* for reboot hook, ignored */ )
pciConfigReset( ) goes through the list of PCI functions at the top-level bus and disables them, preventing them from writing to memory while the system is trying to reboot.
Not set
OK, always