📄 pciconfiglib.c
字号:
int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT32 bitMask, /* Mask which defines field to alter */ UINT32 data /* data written to the offset */ ) { UINT32 temp; STATUS stat; int key; /* check for library initialization or unaligned access */#ifdef PCI_CONFIG_OFFSET_NOCHECK if (pciLibInitStatus != OK) { return (ERROR); }#else if ((pciLibInitStatus != OK) || ((offset & (int)0x3) > 0) ) { return (ERROR); }#endif key = intLock (); stat = pciConfigInLong (busNo, deviceNo, funcNo, offset, &temp); if (stat == OK) { temp = (temp & ~bitMask) | (data & bitMask); stat = pciConfigOutLong (busNo, deviceNo, funcNo, offset, temp); } intUnlock (key); return (stat); }/******************************************************************************* pciConfigModifyWord - Perform a masked longword register update** This function writes a field into a PCI configuration header without* altering any bits not present in the field. It does this by first* doing a PCI configuration read (into a temporary location) of the PCI* configuration header word which contains the field to be altered.* It then alters the bits in the temporary location to match the desired* value of the field. It then writes back the temporary location with* a configuration write. All configuration accesses are long and the* field to alter is specified by the "1" bits in the 'bitMask' parameter.** Do not use this routine to modify any register that contains 'write 1* to clear' type of status bits in the same longword. This specifically* applies to the command register. Modify byte operations could potentially* be implemented as longword operations with bit shifting and masking. This* could have the effect of clearing status bits in registers that aren't being* updated. Use pciConfigInLong and pciConfigOutLong, or pciModifyLong,* to read and update the entire longword.** RETURNS: OK if operation succeeds. ERROR if operation fails.*/STATUS pciConfigModifyWord ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT16 bitMask, /* Mask which defines field to alter */ UINT16 data /* data written to the offset */ ) { UINT16 temp; STATUS stat; int key; /* check for library initialization or unaligned access */#ifdef PCI_CONFIG_OFFSET_NOCHECK if (pciLibInitStatus != OK) { return (ERROR); }#else if ((pciLibInitStatus != OK) || ((offset & (int)0x1) > 0) ) { return (ERROR); }#endif key = intLock (); stat = pciConfigInWord (busNo, deviceNo, funcNo, offset, &temp); if (stat == OK) { temp = (temp & ~bitMask) | (data & bitMask); stat = pciConfigOutWord (busNo, deviceNo, funcNo, offset, temp); } intUnlock (key); return (stat); }/******************************************************************************* pciConfigModifyByte - Perform a masked longword register update** This function writes a field into a PCI configuration header without* altering any bits not present in the field. It does this by first* doing a PCI configuration read (into a temporary location) of the PCI* configuration header word which contains the field to be altered.* It then alters the bits in the temporary location to match the desired* value of the field. It then writes back the temporary location with* a configuration write. All configuration accesses are long and the* field to alter is specified by the "1" bits in the 'bitMask' parameter.** Do not use this routine to modify any register that contains 'write 1* to clear' type of status bits in the same longword. This specifically* applies to the command register. Modify byte operations could potentially* be implemented as longword operations with bit shifting and masking. This* could have the effect of clearing status bits in registers that aren't being* updated. Use pciConfigInLong and pciConfigOutLong, or pciModifyLong,* to read and update the entire longword.** RETURNS: OK if operation succeeds, ERROR if operation fails.*/STATUS pciConfigModifyByte ( int busNo, /* bus number */ int deviceNo, /* device number */ int funcNo, /* function number */ int offset, /* offset into the configuration space */ UINT8 bitMask, /* Mask which defines field to alter */ UINT8 data /* data written to the offset */ ) { UINT8 temp; STATUS stat; int key; /* check for library initialization or unaligned access */ if (pciLibInitStatus != OK) { return (ERROR); } key = intLock (); stat = pciConfigInByte (busNo, deviceNo, funcNo, offset, &temp); if (stat == OK) { temp = (temp & ~bitMask) | (data & bitMask); stat = pciConfigOutByte (busNo, deviceNo, funcNo, offset, temp); } intUnlock (key); return (stat); }/********************************************************************************* pciSpecialCycle - generate a special cycle with a message** This routine generates a special cycle with a message.** RETURNS: OK, or ERROR if this library is not initialized*/STATUS pciSpecialCycle ( int busNo, /* bus number */ UINT32 message /* data driven onto AD[31:0] */ ) { int deviceNo = 0x0000001f; int funcNo = 0x00000007; int key; if (pciLibInitStatus != OK) /* sanity check */ return (ERROR); key = intLock (); /* mutual exclusion start */ switch (pciConfigMech) { case PCI_MECHANISM_0: if (pciConfigSpcl != NULL) pciConfigSpcl (busNo, message); break; case PCI_MECHANISM_1: PCI_OUT_LONG (pciConfigAddr0, pciConfigBdfPack (busNo, deviceNo, funcNo) | 0x80000000); PCI_OUT_LONG (pciConfigAddr1, message); break; case PCI_MECHANISM_2: PCI_OUT_BYTE (pciConfigAddr0, 0xff); PCI_OUT_BYTE (pciConfigAddr1, 0x00); PCI_OUT_LONG ((pciConfigAddr2 | ((deviceNo & 0x000f) << 8)), message); PCI_OUT_BYTE (pciConfigAddr0, 0); break; default: break; } intUnlock (key); /* mutual exclusion stop */ return (OK); }#endif /* USE_PCI_SIMULATOR *//************************************************************************ pciConfigForeachFunc - check condition on specified bus** pciConfigForeachFunc() discovers the PCI functions present on the* bus and calls a specified C-function for each one. If the * function returns ERROR, further processing stops.** pciConfigForeachFunc() does not affect any HOST<->PCI* bridge on the system.** ERRNO: not set** RETURNS: OK normally, or ERROR if funcCheckRtn() doesn't return OK.*/STATUS pciConfigForeachFunc ( UINT8 bus, /* bus to start on */ BOOL recurse, /* if TRUE, do subordinate busses */ PCI_FOREACH_FUNC funcCheckRtn, /* routine to call for each PCI func */ void *pArg /* argument to funcCheckRtn */ ) { int pciLocBus; /* PCI bus/device/function structure */ int pciLocDevice; /* PCI bus/device/function structure */ int pciLocFunction; /* PCI bus/device/function structure */ int device; /* loop over devices */ int function; /* loop over functions */ UINT devVend; UINT16 pciClass; /* PCI class/subclass contents */ int status; UINT8 btemp; UINT8 secBus; /* secondary bus, for recursion */ UINT16 hostBridge = (PCI_CLASS_BRIDGE_CTLR<<8) | PCI_SUBCLASS_HOST_PCI_BRIDGE; /* Begin the scanning process at [bus,0,0] */ pciLocBus = (UINT8)bus; pciLocDevice = (UINT8)0; pciLocFunction = (UINT8)0; /* discover devices and perform check */ /* Locate each active function on the current bus */ for (device = 0; device < PCI_MAX_DEV; device++) { pciLocDevice = device; /* Check each function until an unused one is detected */ for (function = 0; function < PCI_MAX_FUNC; function++) { pciLocFunction = function; /* Check for a valid device/vendor number */ pciConfigInLong (pciLocBus, pciLocDevice, pciLocFunction, PCI_CFG_VENDOR_ID, &devVend); /* If function 0 then check next dev else check next function */ if ( ((devVend & 0x0ffff) == PCI_CONFIG_ABSENT_WORD_F) || ((devVend & 0x0ffff) == PCI_CONFIG_ABSENT_WORD_0) ) { if (function == 0) { break; /* non-existent device, goto next device */ } else { continue; /* function empty, try the next function */ } } /* Check to see if this function belongs to a PCI-PCI bridge */ pciConfigInWord (pciLocBus, pciLocDevice, pciLocFunction, PCI_CFG_SUBCLASS, &pciClass); if ( pciClass != hostBridge ) { /* call specified function */ status = (*funcCheckRtn)(pciLocBus, pciLocDevice, pciLocFunction, pArg); if ( status != OK ) return(ERROR); } if ( recurse ) { /* if P2P bridge, check that bus recursively */ if ( pciClass == ((PCI_CLASS_BRIDGE_CTLR << 8) + PCI_SUBCLASS_P2P_BRIDGE) ) { pciConfigInByte (pciLocBus, pciLocDevice, pciLocFunction, PCI_CFG_SECONDARY_BUS, &secBus); if ( secBus > 0 ) status = pciConfigForeachFunc(secBus, recurse, funcCheckRtn, pArg); else status = OK; if ( status != OK ) return(ERROR); } } /* Proceed to next device if this is a single function device */ if (function == 0) { pciConfigInByte (pciLocBus, pciLocDevice, pciLocFunction, PCI_CFG_HEADER_TYPE, &btemp); if ((btemp & PCI_HEADER_MULTI_FUNC) == 0) { break; /* No more functions - proceed to next PCI device */ } } } } return(OK); }/************************************************************************ pciFuncDisable - disable the specified function** pciFuncDisable() disables the function by turning off various* enable bits of the command register** ERRNO: not set** RETURNS: OK, always** NOMANUAL*/LOCAL STATUS pciFuncDisable ( UINT bus, /* bus */ UINT device, /* device */ UINT function, /* function */ void * pArg /* ignored */ ) { int mask; mask = PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE | PCI_CMD_MASTER_ENABLE; pciConfigModifyLong (bus, device, function, PCI_CFG_COMMAND, mask, 0); return(OK); }/************************************************************************ pciConfigReset - disable cards for warm boot** pciConfigReset() goes through the list of PCI functions* at the top-level bus and disables them, preventing them* from writing to memory while the system is trying to reboot.** ERRNO: Not set** RETURNS: OK, always*/STATUS pciConfigReset ( int startType /* for reboot hook, ignored */ ) { /* disable all functions on top-level bus */ pciConfigForeachFunc(0, 0, (PCI_FOREACH_FUNC)pciFuncDisable, NULL); return(OK); }#endif /* defined(INCLUDE_PCI) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -