📄 pciconfiglib.c
字号:
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
.IP "Bus Number"
is the PCI bus of interest
.IP "Device Number"
is set to all 1's (01Fh)
.IP "Function Number"
is set to all 1's (07d)
.IP "Configuration Register Number"
is zeroed
.LP
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:
.IP "busNo"
bus on which Special Cycle is to be initiated
.IP "message"
data driven onto AD[31:0] during the Special Cycle
.LP
.SH PCI DEVICE CONFIGURATION SPACE ACCESS
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:
.IP "busNo"
bus segment number on which the device resides
.IP "deviceNo"
device ID of the device
.IP "funcNo"
function number of the device
.IP "offset"
offset into the device configuration space
.IP "pData"
where to return the data
.LP
Ouput routines:
.IP "busNo"
bus segment number on which the device resides
.IP "deviceNo"
device ID of the device
.IP "funcNo"
function number of the device
.IP "offset"
offset into the device configuration space
.IP "Data"
data to be written
.LP
.SH PCI CONFIG SPACE OFFSET CHECKING
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.
.SH PCI DEVICE CONFIGURATION
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:
.IP "pciBusNo"
PCI bus segment number
.IP "pciDevNo"
PCI device number
.IP "pciFuncNo"
PCI function number
.IP "devIoBaseAdrs"
base address of one IO-mapped resource
.IP "devMemBaseAdrs"
base address of one memory-mapped resource
.IP "command"
command to issue to device after configuration
.LP
.SH UNIFORM DEVICE ACCESS
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:
.IP "bus"
The bus segment to start with. This allows configuration on and below
a specific place in the bus hierarchy.
.IP "recurse"
A boolean argument specifying whether to do a recursive search or to
do just the specified bus.
.IP "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.
.IP "pArg"
The fourth argument to funcCheckRtn.
.SH SYSTEM RESET
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():
.IP "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.
.SH USAGE
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.
.CS
#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));
}
.CE
INCLUDE FILES:
pciConfigLib.h
SEE ALSO:
.I "PCI Local Bus Specification, Revision 2.1, June 1, 1996"
.I "PCI Local Bus PCI to PCI Bridge Architecture Specification, Revision 1.0,
April 5, 1994"
*/
#include "vxWorks.h"
#include "config.h"
#if defined(INCLUDE_PCI)
#include "dllLib.h"
#include "sysLib.h"
#include "intLib.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "config.h"
#include "drv/pci/pciConfigLib.h"
/* defines */
#define PCI_CMD_MASK 0xffff0000 /* mask to save status bits */
#define PCI_CONFIG_ABSENT_WORD_F 0xffff
#define PCI_CONFIG_ABSENT_WORD_0 0x0000
/*
*
* PCI configuration can be tested to some extent by using the PCI
* configuration simulator. The simulator includes the functions
* which access configuration space, e.g. pciConfigInWord(),
* pciConfigModifyLong() and so on. Normally, those are included
* in this file, but when using the simulator, they cannot be used
* here. Define the macro USE_PCI_SIMULATOR to cause those functions
* to be gotten from the simulator instead of from here.
*
* For normal operation, make sure it is undefined.
*
* It is recommended to define it in the project facility.
*/
/* #define USE_PCI_SIMULATOR */
/* globals */
STATUS pciLibInitStatus = NONE; /* initialization done */
int pciConfigMech = NONE; /* 1=mechanism-1, 2=mechanism-2 */
int pciMaxBus = PCI_MAX_BUS; /* Max number of sub-busses */
/* locals */
LOCAL int pciConfigAddr0; /* config-addr-reg, CSE-reg*/
LOCAL int pciConfigAddr1; /* config-data-reg, forward-reg */
LOCAL int pciConfigAddr2; /* not-used, base-addr */
LOCAL FUNCPTR pciConfigRead = NULL; /* user-defined config space read */
LOCAL FUNCPTR pciConfigWrite = NULL; /* user-defined config space write */
LOCAL FUNCPTR pciConfigSpcl = NULL; /* user-defined PCI special cycle*/
/*******************************************************************************
*
* pciConfigLibInit - initialize the configuration access-method and addresses
*
* 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:
*
* .IP" - "
* 32-bit configuration address port, at 0x0cf8
* .IP" - "
* 32-bit configuration data port, at 0x0cfc
* .LP
*
* Accessing a PCI function's configuration port is two step process.
*
* .IP" - "
* Write the bus number, physical device number, function number and
* register number to the configuration address port.
* .IP" - "
* Perform an IO read from or an write to the configuration data port.
* .LP
*
* Configuration mechanism two uses following two single-byte IO ports.
* .IP" - "
* Configuration space enable, or CSE, register, at 0x0cf8
* .IP" - "
* Forward register, at 0x0cfa
* .LP
*
* To generate a PCI configuration transaction, the following actions are
* performed.
*
* .IP " - "
* Write the target bus number into the forward register.
* .IP " - "
* 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.
* .IP " - "
* Perform a one, two or four byte IO read or write transaction within
* the IO range 0xc000 through 0xcfff.
* .LP
*
* 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.
*
* RETURNS:
* OK, or ERROR if a mechanism is not 0, 1, or 2.
*/
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 */
)
{
if (pciLibInitStatus != NONE)
return (pciLibInitStatus);
switch (mechanism)
{
case PCI_MECHANISM_0: /* non-standard interface */
if (addr0 == 0 || addr1 == 0)
{
pciLibInitStatus = ERROR;
}
else
{
pciConfigRead = (FUNCPTR) addr0;
pciConfigWrite = (FUNCPTR) addr1;
pciConfigSpcl = (FUNCPTR) addr2;
}
pciConfigMech = mechanism;
pciLibInitStatus = OK;
break;
case PCI_MECHANISM_1:
case PCI_MECHANISM_2:
pciConfigMech = mechanism;
pciConfigAddr0 = addr0;
pciConfigAddr1 = addr1;
pciConfigAddr2 = addr2;
pciLibInitStatus = OK;
break;
default:
pciLibInitStatus = ERROR;
break;
}
return (pciLibInitStatus);
}
/*******************************************************************************
*
* pciFindDevice - find the nth device with the given device & vendor ID
*
* This routine finds the nth device with the given device & vendor ID.
*
* RETURNS:
* OK, or ERROR if the deviceId and vendorId didn't match.
*/
STATUS pciFindDevice
(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -