📄 pciiomaplib.c
字号:
*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); }/******************************************************************************** pciDevConfig - configure a device on a PCI bus** This routine configures a device that is on a Peripheral Component* Interconnect (PCI) bus by writing to the configuration header of the* selected device.* It first disables the device by clearing the command register in the* configuration header. It then sets the I/O and/or memory space base* address registers, the latency timer value and the cache line size.* Finally, it re-enables the device by loading the command register with* the specified command.** NOTE: This routine is designed for Type 0 PCI Configuration Headers ONLY.* It is NOT usable for configuring, for example, a PCI-to-PCI bridge.** RETURNS: OK always.*/STATUS pciDevConfig ( int pciBusNo, /* PCI bus number */ int pciDevNo, /* PCI device number */ int pciFuncNo, /* PCI function number */ ULONG devIoBaseAdrs, /* device IO base address */ ULONG devMemBaseAdrs, /* device memory base address */ ULONG command /* command to issue */ ) { INT32 ix; UINT32 tmp32; /* * Disable device by clearing its command register field in its * configuration header. */ pciConfigOutWord (pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_COMMAND, 0); /* * Due to system constraints, this is a partial implementation * of enabling the Base Address Registers (BARs). * It is hoped that all PCI devices only require at most one * I/O space and/or one memory space. * If not, this code will re-allocate the device's memory to * each BAR implemented. Sounds like future trouble! */ for (ix = PCI_CFG_BASE_ADDRESS_0; ix <= PCI_CFG_BASE_ADDRESS_5; ix+=4) { /* Write all f's and read back value */ pciConfigOutLong (pciBusNo, pciDevNo, pciFuncNo, ix, 0xffffffff); pciConfigInLong (pciBusNo, pciDevNo, pciFuncNo, ix, &tmp32); /* BAR implemented? */ if (tmp32 == 0) { /* * No! According to the spec, BARs must be implemented * in sequence starting at BAR 0. So, all done. */ break; } /* I/O space requested? */ /* Yes, set specified I/O space base address */ if (tmp32 & 0x1) { pciConfigOutLong (pciBusNo, pciDevNo, pciFuncNo, ix, devIoBaseAdrs | 0x1); } /* No, memory space required, set specified base address */ else { pciConfigOutLong (pciBusNo, pciDevNo, pciFuncNo, ix, devMemBaseAdrs & ~0x1); } } /* Configure Cache Line Size Register */ pciConfigOutByte (pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_CACHE_LINE_SIZE, PCI_CLINE_SZ); /* Configure Latency Timer */ pciConfigOutByte (pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_LATENCY_TIMER, PCI_LAT_TIMER); /* Enable the device's capabilities as specified */ pciConfigOutWord (pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_COMMAND, (UINT16)command); return (OK); }/********************************************************************************* pciPack - pack parameters for the Configuration Address Register** This routine packs three parameters into one integer for accessing the* Configuration Address Register** RETURNS:* packed integer.**/LOCAL int pciPack ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo /* function number */ ) { return (((busNo << 16) & 0x00ff0000) | ((deviceNo << 11) & 0x0000f800) | ((funcNo << 8) & 0x00000700)); }/********************************************************************************* 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 ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ char * pData /* data read from the offset */ ) { int retval = 0; int key; int n; UINT32 w; if (pciLibInitStatus != OK) /* sanity check */ return (ERROR); key = intLock (); /* mutual exclusion start */ switch (pciConfigMech) { case PCI_MECHANISM_1: PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) | (offset & 0xfc) | 0x80000000); retval = PCI_IN_BYTE (pciConfigAddr1 + (offset & 0x3)); break; case PCI_MECHANISM_2: PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1)); PCI_OUT_BYTE (pciConfigAddr1, busNo); retval = PCI_IN_LONG (pciConfigAddr2 | ((deviceNo & 0x000f) << 8) | (offset & 0xfc)); PCI_OUT_BYTE (pciConfigAddr0, 0); retval >>= (offset & 0x03) * 8; break; case PCI_MECHANISM_3: /* * There are reports of hardware (both target and bridge) * that do not cope well with non-32-bit-aligned accesses, * particularly non-32-bit-word accesses. We may be overreacting * here, but restricting all the accesses to 32-bits should be * safer. Efficiency should not be an issue during PCI * configuration. In any case, this code is in the BSP and can be * changed, if required. */ n = offset % 4; IDSEL(busNo, deviceNo); /* Setup IDSEL Lines */ w = PCI_IN_LONG (((busNo == 0) ? pciConfigAddr0 : pciConfigAddr1) | MAKE_CFG_ADDR(busNo, deviceNo, funcNo, (offset & ~3))); retval = (w >> (8 * n)) & 0xFF; CLR_IDSEL; /* Clear IDSEL Lines */ break; default: break; } intUnlock (key); /* mutual exclusion stop */ *pData = (char)retval; 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 ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ short * pData /* data read from the offset */ ) { int retval = 0; int key; int n; UINT32 w; if (pciLibInitStatus != OK) /* sanity check */ return (ERROR); key = intLock (); /* mutual exclusion start */ switch (pciConfigMech) { case PCI_MECHANISM_1: PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) | (offset & 0xfc) | 0x80000000); retval = PCI_IN_WORD (pciConfigAddr1 + (offset & 0x2)); break; case PCI_MECHANISM_2: PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1)); PCI_OUT_BYTE (pciConfigAddr1, busNo); retval = PCI_IN_LONG (pciConfigAddr2 | ((deviceNo & 0x000f) << 8) | (offset & 0xfc)); PCI_OUT_BYTE (pciConfigAddr0, 0); retval >>= (offset & 0x02) * 8; break; case PCI_MECHANISM_3: n = offset % 4; IDSEL(busNo, deviceNo); /* Setup IDSEL Lines */ w = PCI_IN_LONG (((busNo == 0) ? pciConfigAddr0 : pciConfigAddr1) | MAKE_CFG_ADDR(busNo, deviceNo, funcNo, (offset & ~3))); retval = (w >> (8 * n)) & 0xFFFF; CLR_IDSEL; /* Clear IDSEL Lines */ break; default: break; } intUnlock (key); /* mutual exclusion stop */ *pData = retval; 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 ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ int * pData /* data read from the offset */ ) { int key; volatile int retval = 0; FAST int ix; if (pciLibInitStatus != OK) /* sanity check */ return (ERROR); key = intLock (); /* mutual exclusion start */ switch (pciConfigMech) { case PCI_MECHANISM_1: PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) | (offset & 0xfc) | 0x80000000); for (ix = 0; ix < PCI_DELAY; ++ix) /* XXXmas */ ; retval = PCI_IN_LONG (pciConfigAddr1); break; case PCI_MECHANISM_2: PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1)); PCI_OUT_BYTE (pciConfigAddr1, busNo); retval = PCI_IN_LONG (pciConfigAddr2 | ((deviceNo & 0x000f) << 8) | (offset & 0xfc)); PCI_OUT_BYTE (pciConfigAddr0, 0); break; case PCI_MECHANISM_3: IDSEL(busNo, deviceNo); /* Setup IDSEL Lines */ retval = PCI_IN_LONG (((busNo == 0) ? pciConfigAddr0 : pciConfigAddr1) | MAKE_CFG_ADDR(busNo, deviceNo, funcNo, offset)); CLR_IDSEL; /* Clear IDSEL Lines */ break; default: break; } intUnlock (key); /* mutual exclusion stop */ *pData = retval; return (OK); }/********************************************************************************* pciConfigOutByte - write one byte to the PCI configuration space** This routine writes one byte to the PCI configuration space.*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -