📄 pciiomaplib.c
字号:
/* pciIomapLib.c - Support for PCI drivers *//* Copyright 1984-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------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*//*DESCRIPTIONThis library is PCI Revision 2.1 compliant.This module contains routines to support PCI bus mapped on IO address spacefor x86 and PowerPC architecture. Functions in this library should not becalled from the interrupt level, except pciInt(), since it uses a mutualexclusion semaphore for consecutive register access. The functions addressed here include: - Initialize the library. - Locate the device by deviceID and vendorID. - Locate the device by classCode. - Generate the special cycle. - Access its configuration registers. - Connect a shared interrupt handler. - Disconnect a shared interrupt handler. - Master shared interrupt handler.There are functions to access the IO address space. In x86 architecture,they are sysInXXX() and sysOutXXX(). Macro PCI_IN_XXX() and PCI_OUT_XXX()are provided to use other IO address space functions.Shared PCI interrupt are supported by three functions: pciInt(),pciIntConnect(), pciIntDisconnect(). pciIntConnect() adds the specifiedinterrupt handler to the link list and pciIntDisconnect() removes it fromthe link list. Master interrupt handler pciInt() executes these interrupthandlers in the link list for a PCI interrupt. Each interrupt handler mustcheck the device dependent interrupt status bit to determine the source ofthe interrupt, since it simply execute all interrupt handlers in the linklist. pciInt() should be attached by intConnect() function in the BSP initialization with its parameter. The parameter is an IRQ associated to the PCI interrupt.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.*/#if defined(INCLUDE_PCI)#include "vxWorks.h"#include "config.h"#include "dllLib.h"#include "sysLib.h"#include "stdio.h"#include "stdlib.h"#include "string.h"#include "intLib.h"/* * We currently wish to include this from locally rather than from * there as that version is out-dated. However, as it has been included * in sysLib.c already, this will do no harm. */#include "drv/pci/pciIomapLib.h"/* defines */#ifndef PCI_IN_BYTE#define PCI_IN_BYTE(x) sysInByte (x)#endif#ifndef PCI_IN_WORD#define PCI_IN_WORD(x) sysInWord (x)#endif#ifndef PCI_IN_LONG#define PCI_IN_LONG(x) sysInLong (x)#endif#ifndef PCI_OUT_BYTE#define PCI_OUT_BYTE(x,y) sysOutByte (x,y)#endif#ifndef PCI_OUT_WORD#define PCI_OUT_WORD(x,y) sysOutWord (x,y)#endif#ifndef PCI_OUT_LONG#define PCI_OUT_LONG(x,y) sysOutLong (x,y)#endif/* * The following defines specify, by default, the maximum number of busses, * devices and functions allowed by the PCI 2.1 Specification. * * Any or all may be overriden by defining them in config.h. */#ifndef PCI_MAX_BUS# define PCI_MAX_BUS 256#endif /* PCI_MAX_BUS */#ifndef PCI_MAX_DEV# define PCI_MAX_DEV 21#endif /* PCI_MAX_DEV */#ifndef PCI_MAX_FUNC# define PCI_MAX_FUNC 8#endif /* PCI_MAX_FUNC */#define PCI_DELAY 500 /* XXXmas *//* * The following macro should be defined if IDSEL selection is not done using * the bits AD[31:11], but is done via access to a separate register. If it has * not been defined, then define it as a null macro doing nothing. */#ifndef IDSEL#define IDSEL(bus, device)#endif#ifndef CLR_IDSEL#define CLR_IDSEL#endif/* globals */STATUS pciLibInitStatus = NONE; /* initialization done */DL_LIST pciIntList[PCI_IRQ_LINES]; /* link list of int handlers */int pciConfigMech = NONE; /* 1=mechanism-1, 2=mechanism-2 *//* locals */LOCAL int pciConfigAddr0; /* config-addr-reg, CSE-reg*/LOCAL int pciConfigAddr1; /* config-data-reg, forward-reg */LOCAL int pciConfigAddr2; /* not-used, base-addr *//********************************************************************************* pciIomapLibInit - 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:* - 32-bit configuration address port, at 0x0cf8* - 32-bit configuration data port, at 0x0cfc* Accessing a PCI function's configuration port is two step process.* - Write the bus number, physical device number, function number and * register number to the configuration address port.* - Perform an IO read from or an write to the configuration data port.** Configuration mechanism two uses following two single-byte IO ports.* - Configuration space enable, or CSE, register, at 0x0cf8* - 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 three 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 1, 2 or 3.**/STATUS pciIomapLibInit ( int mechanism, /* configuration mechanism: 1, 2 or 3 */ int addr0, /* config-addr-reg / CSE-reg */ int addr1, /* config-data-reg / Forward-reg */ int addr2 /* none / Base-address */ ) { int ix; if (pciLibInitStatus != NONE) return (pciLibInitStatus); switch (mechanism) { case PCI_MECHANISM_1: case PCI_MECHANISM_2: case PCI_MECHANISM_3: pciConfigMech = mechanism; pciConfigAddr0 = addr0; pciConfigAddr1 = addr1; pciConfigAddr2 = addr2; pciLibInitStatus = OK; break; default: pciLibInitStatus = ERROR; break; } for (ix = 0; ix < PCI_IRQ_LINES; ix++) dllInit (&pciIntList[ix]); 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 ( 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 */ ) { STATUS status = ERROR; BOOL cont = TRUE; int busNo; int deviceNo; int funcNo; UINT32 device; UINT32 vendor; char header; if (pciLibInitStatus != OK) /* sanity check */ cont = FALSE; for (busNo = 0; cont == TRUE && busNo < PCI_MAX_BUS; busNo++) for (deviceNo = 0; cont == TRUE && deviceNo < ((busNo == 0) ? PCI_MAX_DEV : 16); ++deviceNo) for (funcNo = 0; cont == TRUE && funcNo < PCI_MAX_FUNC; funcNo++) {#if (PCI_MAX_DEV > 31) && (PCI_MAX_FUNC > 7) /* avoid a special bus cycle */ if ((deviceNo == 0x1f) && (funcNo == 0x07)) continue;#endif pciConfigInLong (busNo, deviceNo, funcNo, PCI_CFG_VENDOR_ID, &vendor); /* If nonexistent device, skip to next */ if ((vendor == 0xFFFFFFFF) && (funcNo == 0)) break; device = vendor >> 16; device &= 0x0000FFFF; vendor &= 0x0000FFFF; if ((vendor == (UINT32)vendorId) && (device == (UINT32)deviceId) && (index-- == 0)) { *pBusNo = busNo; *pDeviceNo = deviceNo; *pFuncNo = funcNo; status = OK; cont = FALSE; /* terminate all loops */ continue; } /* goto next if current device is single function */ pciConfigInByte (busNo, deviceNo, funcNo, PCI_CFG_HEADER_TYPE, &header); if ((header & PCI_HEADER_MULTI_FUNC) != PCI_HEADER_MULTI_FUNC && funcNo == 0) break; } return (status); }/********************************************************************************* pciFindClass - find the nth occurence of a device by PCI class code.** This routine finds the nth device with the given 24-bit PCI class code* (class subclass prog_if).** RETURNS:* OK, or ERROR if the class didn't match.**/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 */ ) { STATUS status = ERROR; BOOL cont = TRUE; int busNo; int deviceNo; int funcNo; int classCodeReg; char header; if (pciLibInitStatus != OK) /* sanity check */ cont = FALSE; for (busNo = 0; cont == TRUE && busNo < PCI_MAX_BUS; busNo++) for (deviceNo = 0; cont == TRUE && deviceNo < ((busNo == 0) ? PCI_MAX_DEV : 16); ++deviceNo) for (funcNo = 0; cont == TRUE && funcNo < PCI_MAX_FUNC; funcNo++) {#if (PCI_MAX_DEV > 31) && (PCI_MAX_FUNC > 7) /* avoid a special bus cycle */ if ((deviceNo == 0x1f) && (funcNo == 0x07)) continue;#endif pciConfigInLong (busNo, deviceNo, funcNo, PCI_CFG_REVISION, &classCodeReg); /* If nonexistent device, skip to next */ if (((UINT32)classCodeReg == 0xFFFFFFFF) && (funcNo == 0)) break; if ((((classCodeReg >> 8) & 0x00ffffff) == classCode) && (index-- == 0)) { *pBusNo = busNo;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -