?? ixp425pciconfiglib.c
字號:
/* ixp425PciConfigLib.c - PCI Configuration driver for the IXP425 *//* Copyright 2002 Wind River Systems, Inc. *//*modification history--------------------01a,05jun02,jb initial version...*//*DESCRIPTIONThis module provides services to enable the generation of configuration cycles on the PCI bus. PCI device drivers will use this code to configure and manage the devices they control. The standard configuration routines are pciConfigInxxx and pciConfigOutxxx. In addition to these we have provided routines for generating IO reads and writes and memory reads and writes.In order for the functionality defined herein to be available, INCLUDE_PCI must be defined in config.h.SH INITIALIZATIONThe function sysPciInit() should be called fromsysHwInit() to initialize the PCI unit on the IXP425.The function sysPciAssignAddrs() should be called from sysHwInit() after the call to sysPciInit to initialise devices on the PCI bus.INCLUDE FILES:ixp425Pci.h ixp425Pci_p.hSEE ALSO:.I "PCI Local Bus Specification, Revision 2.2, December 18, 1998"ixp425Pci.c*/#include "vxWorks.h"#include "config.h" #include "ixp425Pci.h"#include "ixp425Pci_p.h"extern STATUS pciLibInitStatus; /******************************************************************************** pciDeviceExists - checks whether a device is present** This function checks the specified bus, device and function number* to verify whether a device is actually present on the PCI bus at that* location** RETURNS: TRUE if a device is found, FALSE otherwise*/BOOL pciDeviceExists (UINT32 busNo, UINT32 deviceNo, UINT32 funcNo){ UINT32 vendorId; UINT32 regval; UINT32 key; /*we need to lock interrupts here because if we do not, the PCC internal ISR (if enabled) will be invoked in the event that we try to read from a non-existent device, the ISR will clear the PFE indicator before we get to read it.*/ key=intLock(); pciConfigInLong (busNo, deviceNo, funcNo, PCI_CFG_VENDOR_ID, &vendorId); /* There are two ways to find out an empty device. * 1. check Master Abort bit after the access. * 2. check whether the vendor id read back is 0x0. */ REG_READ (PCI_CSR_BASE, PCI_ISR_OFFSET, regval); if ( (vendorId != 0x0) && ((regval & PCI_ISR_PFE)==0)) { intUnlock(key); return TRUE; } /*no device present, make sure that the master abort bit is reset*/ REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PFE ); intUnlock(key); return FALSE;}/******************************************************************************** pciInfoGet - Retrieves PCI device information** This function retrieves the PCI assignments of the specified device. * It returns a pointer to a PciDevice structure.** RETURNS: Pointer to PCI device information, or NULL*/PciDevice *pciInfoGet (UINT16 device){ if (device >= nDevices) { return (NULL); } return (&devices[device]);}/******************************************************************************** pciDeviceGet - Retrieves PCI device information** This function returns a pointer to the n'th instance of a specified device.* If the entry is not found, NULL is returned. Devices are numbered starting* at zero.** RETURNS: Pointer to PCI device information, or NULL*/PciDevice *pciDeviceGet (UINT32 vendor_id, UINT32 device_id, UINT32 count){ UINT32 ix; UINT32 cnt = 0; for (ix = 0; ix < IXP425_PCI_MAX_FUNC_ON_BUS; ix++) { if (devices[ix].vendor_id == vendor_id && devices[ix].device_id == device_id) { if (cnt == count) { return (&devices[ix]); } else { cnt++; } } } return ((PciDevice *)NULL);}/********************************************************************************* 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 (UINT32 vendorId, UINT32 deviceId, UINT32 index, UINT32 * pBusNo, UINT32 * pDeviceNo, UINT32 * pFuncNo){ UINT32 busNo; UINT32 deviceNo; UINT32 funcNo; UINT32 devdidvid; UINT32 didvid; UINT32 cnt=0; if (pciLibInitStatus != OK) { return ERROR; } didvid = ((deviceId << 16 ) & IXP425_PCI_TOP_WORD_OF_LONG_MASK) | (vendorId & IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK); for (busNo = 0; busNo < IXP425_PCI_MAX_BUS; busNo++) { for (deviceNo = 0; deviceNo < IXP425_PCI_MAX_DEV; deviceNo++) { for (funcNo = 0; funcNo < IXP425_PCI_MAX_FUNC; funcNo++) { pciConfigInLong (busNo, deviceNo, funcNo, PCI_CFG_VENDOR_ID, &devdidvid); if (devdidvid == didvid) { if (cnt == index) { *pBusNo = busNo; *pDeviceNo = deviceNo; *pFuncNo = funcNo; return OK; } else { cnt++; } } } } } return ERROR;}/********************************************************************************* 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** RETURNS:* OK, or ERROR if the class didn't match.**/STATUS pciFindClass (UINT32 classCode, UINT32 index, UINT32 *pBusNo, UINT32 *pDeviceNo, UINT32 *pFuncNo) { UINT32 busNo; UINT32 deviceNo; UINT32 funcNo; UINT32 classCodeReg; UINT32 cnt=0; if (pciLibInitStatus != OK) { return ERROR; } for (busNo = 0; busNo < IXP425_PCI_MAX_BUS; busNo++) { for (deviceNo = 0; deviceNo < IXP425_PCI_MAX_DEV; deviceNo++) { for (funcNo = 0; funcNo < IXP425_PCI_MAX_FUNC; funcNo++) { pciConfigInLong (busNo, deviceNo, funcNo, PCI_CFG_REVISION, &classCodeReg); if ((((classCodeReg >> 8) & IXP425_PCI_BOTTOM_TRIBYTES_OF_LONG_MASK) == classCode)) { if (cnt == index) { *pBusNo = busNo; *pDeviceNo = deviceNo; *pFuncNo = funcNo; return OK; } else { cnt++; } } } } } return ERROR;}/* All PCI non-prefetch (single data phase) reads and writes go * through the following access functions.*/LOCAL void nonPrefetchRead (UINT32 addr, UINT32 cmd, UINT32 *data){ UINT32 key; key = intLock (); /* mutual exclusion start */ REG_WRITE (PCI_CSR_BASE, PCI_NP_AD_OFFSET, addr); /*set up and execute the read*/ REG_WRITE (PCI_CSR_BASE, PCI_NP_CBE_OFFSET, cmd); /*The result of the read is now in np_rdata*/ REG_READ (PCI_CSR_BASE, PCI_NP_RDATA_OFFSET, *data); intUnlock (key); /* mutual exclusion stop */ return;}LOCAL void nonPrefetchWrite (UINT32 addr, UINT32 cmd, UINT32 data){ UINT32 key; key = intLock (); /* mutual exclusion start */ REG_WRITE (PCI_CSR_BASE, PCI_NP_AD_OFFSET, addr); /*set up the write*/ REG_WRITE (PCI_CSR_BASE, PCI_NP_CBE_OFFSET, cmd); /*Execute the write by writing to NP_WDATA*/ REG_WRITE (PCI_CSR_BASE, PCI_NP_WDATA_OFFSET, data); intUnlock (key); /* mutual exclusion stop */ return;}/********************************************************************************* pciConfigInByte - read one byte from the PCI configuration space** This routine reads one byte from the PCI configuration space** RETURNS:* OK, or ERROR if this library is not initialized.**/STATUS pciConfigInByte (UINT32 busNo, /* bus number */ UINT32 deviceNo, /* device number */ UINT32 funcNo, /* function number */ UINT32 offset, /* offset into the configuration space */ UINT8 * pData) /* data read from the offset */ { UINT32 retval; UINT32 n; UINT32 byteEnables; UINT32 addr; if (pciLibInitStatus != OK) { return (ERROR); } n = offset % 4; /*byte enables are 4 bits, active low, the position of each bit maps to the byte that it enables*/ byteEnables = (~BIT (n)) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; byteEnables = byteEnables << PCI_NP_CBE_BESL; /*address bits 31:28 specify the device, 10:8 specify the function*/ /*Set the address to be read*/ addr = BIT ((31 - deviceNo)) | (funcNo << PCI_NP_AD_FUNCSL) | (offset & ~3); nonPrefetchRead (addr, byteEnables | NP_CMD_CONFIGREAD, &retval); /*Pick out the byte we are interested in*/ *pData = (retval >> (8*n)); return (OK);}/********************************************************************************* pciConfigInWord - read one word from the PCI configuration space** This routine reads one word from the PCI configuration space** RETURNS:* OK, or ERROR if this library is not initialized.**/STATUS pciConfigInWord (UINT32 busNo, /* bus number */ UINT32 deviceNo, /* device number */ UINT32 funcNo, /* function number */ UINT32 offset, /* offset into configuration space */ UINT16 *pData) /* data read from the offset */ { UINT32 n; UINT32 retval; UINT32 addr; UINT32 byteEnables; if (pciLibInitStatus != OK) { return (ERROR); } n = offset % 4; /*byte enables are 4 bits active low, the position of each bit maps to the byte that it enables*/ byteEnables = (~(BIT (n) | BIT ((n+1)))) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; byteEnables = byteEnables << PCI_NP_CBE_BESL; /*address bits 31:28 specify the device 10:8 specify the function*/ /*Set the address to be read*/ addr = BIT ((31 - deviceNo)) | (funcNo << PCI_NP_AD_FUNCSL) | (offset & ~3); nonPrefetchRead (addr, byteEnables | NP_CMD_CONFIGREAD, &retval); /*Pick out the word we are interested in*/ *pData = (retval >> (8*n)); return (OK);}/********************************************************************************* pciConfigInLong - read one longword from the PCI configuration space** This routine reads one longword from the PCI configuration space** RETURNS:* OK, or ERROR if this library is not initialized.**/STATUS pciConfigInLong (UINT32 busNo, /* bus number */ UINT32 deviceNo, /* device number */ UINT32 funcNo, /* function number */ UINT32 offset, /* offset into configuration space */ UINT32 *pData) /* data read from the offset */ { UINT32 retval; UINT32 addr; if (pciLibInitStatus != OK) { return (ERROR); } /*address bits 31:28 specify the device 10:8 specify the function*/ /*Set the address to be read*/ addr = BIT ((31 - deviceNo)) | (funcNo << PCI_NP_AD_FUNCSL) | (offset & ~3); nonPrefetchRead (addr, NP_CMD_CONFIGREAD, &retval); *pData = retval; return (OK);}/********************************************************************************* pciConfigOutByte - write one byte to the PCI configuration space** This routine writes one byte to the PCI configuration space.** RETURNS:* OK, or ERROR if this library is not initialized.**/STATUS pciConfigOutByte (UINT32 busNo, /* bus number */ UINT32 deviceNo, /* device number */ UINT32 funcNo, /* function number */ UINT32 offset, /* offset into configuration space */ UINT8 data) /* data written to the offset */ { UINT32 addr; UINT32 byteEnables; UINT32 n; UINT32 ldata; if (pciLibInitStatus != OK) { return (ERROR); } n = offset % 4; /*byte enables are 4 bits active low, the position of each bit maps to the byte that it enables*/ byteEnables = (~BIT (n)) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; byteEnables = byteEnables << PCI_NP_CBE_BESL; ldata = data << (8*n); /*address bits 31:28 specify the device 10:8 specify the function*/ /*Set the address to be written*/ addr = BIT ((31 - deviceNo)) | (funcNo << PCI_NP_AD_FUNCSL) | (offset & ~3); nonPrefetchWrite (addr, byteEnables | NP_CMD_CONFIGWRITE, ldata ); return (OK);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -