📄 pciconfiglib.c
字号:
/* pciConfigLib.c - PCI Configuration space access support for PCI drivers */
/* Copyright 1984-2002 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
02l,18mar02,dat Fixing doc builds. (SPR 74444)
02k,04dec01,tor Back out pciFindDevice() & pciFindClass() mods
02j,07nov01,tor reimplement pciFindDevice() & pciFindClass() using
pciConfigForeachFunc()
02i,16oct01,tor Added pciConfigReset() (SPR #8406) and pciConfigForeachFunc()
Added support for using pciConfigSimLib.c for testing.
02h,11oct01,tor type declaration fixes for SPR #69197
02g,21jun01,rcs made documentation for pciFindClass() classcode arg clearer.
02f,18jun01,mil Cleaned up compiler warnings.
02e,11apr00,gmk Merged from haft branch
02d,29jan00,tm Added Extended Capabilities Pointer (ECP) support
02c,28apr99,dat Merge from 2_0_0
02b,11nov98,dat changed mechanism 0 to include transfer size. Added warnings
about using byte and shortword operations for config registers
that contain 'write 1 to clear' status bits. Changed default
behaviour to check for offset errors (re 22981)
02a,04nov98,tm Offset check conditional on PCI_CONFIG_CHECK_OFFSET (SPR 22981)
01z,28jul98,tm PCI_MAX_BUS,.._DEV, .._FUNC moved to pciConfigLib.h and
config.h now included to allow BSP values to override
01y,20jul98,tm fixed extistence checks to look only at vendor ID SPR 21934
01x,29may98,tm added pciConfigModify{Byte,Word}; revised Modify* arguments
01w,05may98,tm changed pciMaxDev, pciMaxFunc -> PCI_MAX_DEV, PCI_MAX_FUNC
01v,09apr98,tm fixed pciConfigModifyLong: could return leaving ints locked
added alignment checks to word and longword access routines
01u,21mar98,tm added pciMaxDev, pciMaxFunc in support of autoconfiguration
01t,16mar98,tm documentation tweaking/cleanup
coding standard name tweak: pciConfigBDFPack() -> ..BdfPack()
changed non-bus-0 maximum devices from 16 -> 32;
01s,11mar98,tm renamed to pciConfigLib.c from pciIomapLib.c;
removed PCI_DELAY
pciPack scope/name changed: LOCAL int -> int pciConfigBdfPack
01r,08mar98,tm merged new documentation;
adapted ebsa285 BSP mechanism '3' to use mech '0' added in v01o
01q,06mar98,tm fixed pciConfigOut{Byte,Word} UINT32->UINT8/16 problem SPR?????
01p,04mar98,tm PCI_MAX_BUS is now a variable;
Configuration space I/O fn argument types clarified
01o,04mar98,dat added Mechanism 0, a non-standard config space access method.
01n,26feb98,tm pciInt(), pciIntConnect() and pciIntDisconnect() moved
to pciIntLib.c
01m,24nov97,jpd made conditional on INCLUDE_PCI.
01l,27oct97,kkk took out "EOF" line at end of file.
01k,26sep97,jpd make all config accesses 32-bit. Add Type 1 config addresses.
01j,02sep97,jpd added support for non-PC/PowerPC configuration.
01i,25apr97,mas tweaked DELAY loop for long read; no loop for long write.
01h,22apr97,mas added include of dllLib.h; added pciDevConfig; converted
semaphore-based exclusion to intLock-based exclusion; fixed
pciFindXxxx to skip nonexistant devices; limited bus scanning
to PCI_MAX_BUS, PCI_MAX_DEV and PCI_MAX_FUNC (SPR 8226).
01g,12jan97,hdn changed variable name "vender" to "vendor".
01f,12jan97,hdn changed variable name "class" to "classCodeReg".
01e,03dec96,hdn added single/multi function check.
01d,16sep96,dat made pciConfigMech global (for pciIomapShow).
01c,06aug96,hdn added pciInt(), pciIntConnect() and pciIntDisconnect().
01b,14mar96,hdn re-written. changed parameters of the functions.
removed BIOS dependent codes.
01a,25feb95,bcs written
*/
/*
DESCRIPTION
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:
.IP " -"
Initialization of the library.
.IP " -"
Locating a device by Device ID and Vendor ID.
.IP " -"
Locating a device by Class Code.
.IP " -"
Generation of Special Cycles.
.IP " -"
Accessing Configuration Space structures.
.LP
.SH PCI BUS CONCEPTS
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.
.CS
---------
| |
| 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 2
.CE
For further details, refer to the PCI to PCI Bridge Architecture Specification.
.SH 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:
.IP "PCI_IN_BYTE"
read a byte from PCI I/O Space
.IP "PCI_IN_WORD"
read a word from PCI I/O Space
.IP "PCI_IN_LONG"
read a longword from PCI I/O Space
.IP "PCI_OUT_BYTE"
write a byte from PCI I/O Space
.IP "PCI_OUT_WORD"
write a word from PCI I/O Space
.IP "PCI_OUT_LONG"
write a longword from PCI I/O Space
.LP
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.
.SH INITIALIZATION
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.
ACCESS MECHANISM 1:
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).
.CS
e.g.
pciConfigLibInit (PCI_MECHANISM_1, PCI_CONFIG_ADDR,
PCI_CONFIG_DATA, NULL);
.CE
ACCESS MECHANISM 2:
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).
.CS
e.g.
pciConfigLibInit (PCI_MECHANISM_2, PCI_CONFIG_CSE,
PCI_CONFIG_FORWARD, PCI_CONFIG_BASE);
.CE
ACCESS MECHANISM 0:
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:
.CS
pciConfigLibInit (PCI_MECHANISM_0, myReadRtn,
myWriteRtn, mySpecialRtn);
-or-
pciConfigLibInit (PCI_MECHANISM_0, myReadRtn,
myWriteRtn, NULL);
.CE
The calling convention for the user read routine is:
.CS
STATUS myReadRtn (int bus, int dev, int func,
int reg, int size, void * pResult);
.CE
The calling convention for the user write routine is:
.CS
STATUS myWriteRtn (int bus, int dev, int func,
int reg, int size, UINT32 data);
.CE
The calling convention for the optional special cycle routine is:
.CS
STATUS mySpecialRtn (int bus, UINT32 data);
.CE
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.
.SH SPECIAL STATUS BITS
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.
.CS
/@
* 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);
.CE
The above warning applies to any configuration register containing
write '1' to clear bits.
.SH PCI DEVICE LOCATION
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:
.IP "vendorId"
the vendor ID of the device
.IP "deviceId"
the device ID of the device
.IP "index"
the instance number
.LP
pciFindClass() simply requires a class code and the index:
.IP "classCode"
the 24-bit class of the device
.IP "index"
the instance number
.LP
In addition, both functions return the following parameters by reference:
.IP "pBusNo"
where to return bus segment number containing the device
.IP "pDeviceNo"
where to return the device ID of the device
.IP "pFuncNo"
where to return the function number of the device
.LP
These three parameters, Bus segment number, Device number, and Function number
(BDF), provide a means to access the Configuration Space of any PCI device.
.SH PCI BUS SPECIAL CYCLE GENERATION
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -