📄 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() mods02j,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 #6919702g,21jun01,rcs made documentation for pciFindClass() classcode arg clearer. 02f,18jun01,mil Cleaned up compiler warnings.02e,11apr00,gmk Merged from haft branch02d,29jan00,tm Added Extended Capabilities Pointer (ECP) support02c,28apr99,dat Merge from 2_0_002b,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 2193401x,29may98,tm added pciConfigModify{Byte,Word}; revised Modify* arguments01w,05may98,tm changed pciMaxDev, pciMaxFunc -> PCI_MAX_DEV, PCI_MAX_FUNC01v,09apr98,tm fixed pciConfigModifyLong: could return leaving ints locked added alignment checks to word and longword access routines01u,21mar98,tm added pciMaxDev, pciMaxFunc in support of autoconfiguration01t,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 pciConfigBdfPack01r,08mar98,tm merged new documentation; adapted ebsa285 BSP mechanism '3' to use mech '0' added in v01o01q,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 clarified01o,04mar98,dat added Mechanism 0, a non-standard config space access method.01n,26feb98,tm pciInt(), pciIntConnect() and pciIntDisconnect() moved to pciIntLib.c01m,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*//*DESCRIPTIONThis module contains routines to support accessing the PCI bus ConfigurationSpace. The library is PCI Revision 2.1 compliant.In general, functions in this library should not be called from the interruptlevel, (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 CONCEPTSThe PCI bus is an unterminated, high impedence CMOS bus using reflected wavesignalling as opposed to incident wave. Because of this, the PCI bus isphysically limited in length and the number of electrical loads that can besupported. Each device on the bus represents one load, including adaptersand bridges.To accomodate additional devices, the PCI standard allows multiple PCI busesto 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 abovelimitations.The bus segment accessible from the host bus adapter is designated the primarybus segment (see figure). Progressing outward from the primary bus (designatedsegment number zero from the PCI architecture point of view) are the secondaryand tertiary buses, numbered as segments one and two, respectively. Due toclock skew concerns and propagation delays, practical PCI bus architectures donot 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.CEFor further details, refer to the PCI to PCI Bridge Architecture Specification..SH I/O MACROS AND CPU ENDIANESSPCI bus I/O operations must adhere to little endian byte ordering. Thus ifan I/O operation larger than one byte is performed, the lower I/O addressescontain the least signficant bytes of the multi-byte quantity of interest.For architectures that adhere to big-endian byte ordering, byte-swappingmust 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.LPBy default, these macros call the appropriate PCI I/O routine, suchas sysPciInWord. For architectures that do not require byte swapping,these macros simply call the appropriate default I/O routine, such assysInWord. These macros may be redefined by the BSP if specialprocessing is required..SH INITIALIZATIONpciConfigLibInit() 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 Spaceby the 'geographic' specification of a Bus segment number, Device number, and aFunction number (BDF). The configuration registers of a PCI device arearranged 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 structuremember offset defined for the register. For further details, refer to thePCI Local Bus Specification, Revision 2.1. Refer to the header filepciConfigLib.h for the defined standard configuration register offsets.The maximum number of Type-1 Configuration Space buses supported in the 2.1Specifications is 256 (0x00 - 0xFF), far greater than most systems currentlysupport. Most buses are numbered sequentially from 0. An optional definecalled PCI_MAX_BUS may be declared in config.h to override the defaultdefinition of 256. Similarly, the default number of devices and functionsmay be overriden by defining PCI_MAX_DEV and/or PCI_MAX_FUNC. Note thatthe number of devices applies only to bus zero, all others being restrictedto 16 by the 2.1 spec.ACCESS MECHANISM 1:This is the preferred access mechanism for a PC-AT class machines. Ituses two standard PCI I/O registers to initiate a configuration cycle.The type of cycle is determined by the Host-bridge device based onthe devices primary bus number. If the configuration bus number matchesthe primary bus number then a type 0 configuration cycle occurs. Otherwisea type 1 cycle is generated. This is all transparent to the user.The two arguments used for mechanism 1 are the CAR register address whichby default is PCI_CONFIG_ADDR (0xCF8), and the CDR register address whichis normally PCI_CONFIG_DATA (0xCFC)..CS e.g. pciConfigLibInit (PCI_MECHANISM_1, PCI_CONFIG_ADDR, PCI_CONFIG_DATA, NULL);.CEACCESS 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 whichby default is PCI_CONFIG_CSE (0xCF8), and the Forward register address whichis normally PCI_CONFIG_FORWARD (0xCFA), and the configuration base addresswhich is normally PCI_CONFIG_BASE (0xC000)..CS e.g. pciConfigLibInit (PCI_MECHANISM_2, PCI_CONFIG_CSE, PCI_CONFIG_FORWARD, PCI_CONFIG_BASE);.CEACCESS MECHANISM 0:We have added a non-standard access method that we call method 0. Selectingmethod 0 installs user supplied read and write routines to actuallyhandle configuration read and writes (32 bit accesses only). The BSPwill supply pointers to these routines as arguments 2 and 3 (read routineis argument 2, write routine is argument 3). A user provided specialcycle routine is argument 4. The special cycle routine is optional and a NULL pointer should be used if the special cycle routine is not providedby the BSP.All accesses are expected to be 32 bit accesses with these routines.The code in this library will perform bit manipulation to emulatebyte and word operations. All routines return OK to indicate successfuloperation 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);.CEThe calling convention for the user read routine is:.CS STATUS myReadRtn (int bus, int dev, int func, int reg, int size, void * pResult);.CEThe calling convention for the user write routine is:.CS STATUS myWriteRtn (int bus, int dev, int func, int reg, int size, UINT32 data);.CEThe calling convention for the optional special cycle routine is:.CS STATUS mySpecialRtn (int bus, UINT32 data);.CEIn the Type-1 method, PCI Configuration Space accesses are made by thesequential access of two 32-bit hardware registers: the Configuration AddressRegister (CAR) and the Configuration Data Register (CDR). The CAR is writtento first with the 32-bit value designating the PCI bus number, the device onthat bus, and the offset to the configuration register being accessed in thedevice. The CDR is then read or written, depending on whether the registerof 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 topredefined 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 bytewindow of PCI I/O Space. In this method, any PCI I/O Space access within therange of 0xC000 to 0xCFFF will be translated to a Configuration Space access.This access method utilizes two 8-bit hardware registers: the ConfigurationSpace Enable register (CSE) and the Forward register (CFR). Like the CAR andCDR, these regiters occupy preassigned PCI I/O Space addresses: CSE = 0xCF8,CFR = 0xCFA. The CSE specifies the device to be accessed and the functionwithin the device. The CFR specifies the bus number on which the device ofinterest 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 startingat 0xC000. The offset specifies the configuration register within theconfiguration header which now appears in the 4K byte Configuration Spacewindow..SH SPECIAL STATUS BITSBe 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 writinga '1' to them. For each of the listed functions, it is possible that they willemulate 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 ifthe user tries to update the command bits. The user should insure that onlyfull 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 torewrite the Command/Status register. Use of pciConfigModifyLong is okay ifthe 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);.CEThe above warning applies to any configuration register containingwrite '1' to clear bits..SH PCI DEVICE LOCATIONAfter the library has been initialized, the Configuration Space of any PCIdevice may be accessed after first locating the device.Locating a device is accomplished using either pciFindDevice() orpciFindClass(). Both routines require an index parameter indicatingwhich instance of the device should be returned, since multiple instancesof the same device may be present in a system. The instance number iszero-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.LPpciFindClass() simply requires a class code and the index:.IP "classCode"the 24-bit class of the device.IP "index"the instance number.LPIn 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.LPThese 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 GENERATIONThe 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-basedsystems to broadcast to PCI devices that the system is about to go intoa halt or shutdown condition.The special cycle is initiated by software. Utilizing CSAM-1, a 32-bitwrite to the configuration address port specifying the following
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -