📄 i80312pcilib.c
字号:
* i80312PciAbortsClear - clear primary or secondary PCI aborts** This routine clears the abort status bits either in the primary* or in the secondary.* * RETURNS : OK, or ERROR.**/LOCAL STATUS i80312PciAbortsClear ( int brNum ) { UINT32 atuPriStat; UINT32 atuSecStat; UINT16 atuStat; volatile ATU_CFG_SPACE * pAtuCfg = (ATU_CFG_SPACE *)I80312_ATU_CFG_BASE; STATUS rtnStatus = OK; if (brNum == i80312_BusNumbers[PRIMARY_BUS_INDEX]) { if ( (atuStat = *BRIDGE_PSR) & MASTER_ABORT) { *BRIDGE_PSR = MASTER_ABORT; rtnStatus = ERROR; } if ( (atuStat = *ATU_PATUSR) & MASTER_ABORT) { *ATU_PATUSR = MASTER_ABORT; rtnStatus = ERROR; } atuPriStat = *ATU_PATUISR; if (atuPriStat & (I80312_BRIDGE_TARGET_ABORT | I80312_BRIDGE_MASTER_TARGET_ABORT | I80312_BRIDGE_MASTER_ABORT)) { if (atuPriStat & I80312_BRIDGE_TARGET_ABORT) { *ATU_PATUISR |= I80312_BRIDGE_TARGET_ABORT; pAtuCfg->ATU_PrimaryStatus |= TARGET_ABORT; } if (atuPriStat & I80312_BRIDGE_MASTER_TARGET_ABORT) { *ATU_PATUISR |= I80312_BRIDGE_MASTER_TARGET_ABORT; pAtuCfg->ATU_PrimaryStatus |= MASTER_TARGET_ABORT; } if (atuPriStat & I80312_BRIDGE_MASTER_ABORT) { *ATU_PATUISR |= I80312_BRIDGE_MASTER_ABORT; pAtuCfg->ATU_PrimaryStatus |= MASTER_ABORT; } rtnStatus = ERROR; } } else if (brNum == i80312_BusNumbers[SECONDARY_BUS_INDEX]) { if ( (atuStat = *BRIDGE_SSR) & MASTER_ABORT) { *BRIDGE_SSR = MASTER_ABORT; rtnStatus = ERROR; } if ( (atuStat = *ATU_SATUSR) & MASTER_ABORT) { *ATU_SATUSR = MASTER_ABORT; rtnStatus = ERROR; } atuSecStat = *ATU_SATUISR; if (atuSecStat & (I80312_BRIDGE_TARGET_ABORT | I80312_BRIDGE_MASTER_TARGET_ABORT | I80312_BRIDGE_MASTER_ABORT)) { if (atuSecStat & I80312_BRIDGE_TARGET_ABORT) *ATU_SATUISR |= I80312_BRIDGE_TARGET_ABORT; if (atuSecStat & I80312_BRIDGE_MASTER_TARGET_ABORT) *ATU_SATUISR |= I80312_BRIDGE_MASTER_TARGET_ABORT; if (atuSecStat & I80312_BRIDGE_MASTER_ABORT) *ATU_SATUISR |= I80312_BRIDGE_MASTER_ABORT; rtnStatus = ERROR; } } return(rtnStatus); }/************************************************************************** i80312PciCfgWr - perform a configuration write* * This routine performs a configuration write using the primary or secondary * Address Translation Unit (ATU).** RETURNS: OK, or ERROR if the transaction fails.** SEE ALSO: i80312PciCfgRd()*/STATUS i80312PciCfgWr ( int brNum, /* Primary or Secondary */ PCI_CFG_ADDR cfgAddr, /* configuration address command format */ UINT32 val /* value writes to */ ) { volatile UINT32 idsel; int indexNum; int lockKey,status; int lowTwobits = cfgAddr.u.bit.regPos; int len = cfgAddr.u.bit.regLen; indexNum = (brNum >= i80312_BusNumbers[SECONDARY_BUS_INDEX])?1:0; /* highest possible number for RP */ if (cfgAddr.u.bit.devNum > I80312_PCI_DEVICE_MAX_NUM) return(ERROR); /* form either configuration type 0 or type 1 command */ if ( cfgAddr.u.bit.cfgType == PCI_CFG_TYP1) idsel = cfgAddr.u.whole & 0x0fffffff; /* mask off reserved area */ else { /* save pertinent part of the address */ idsel = (cfgAddr.u.whole & 0x000007ff); /* add device number to ID select */ idsel |= (1 << (cfgAddr.u.bit.devNum + 11)); } lockKey = intLock(); /* write cfg space data */ if (len == PCI_BYTE_ACCESS) { *(i80312CfgRegs[indexNum].addrReg) = idsel; *(volatile char *)(i80312CfgRegs[indexNum].dataReg + lowTwobits) = (char)val; } else if (len == PCI_UINT16_ACCESS) { *(i80312CfgRegs[indexNum].addrReg) = idsel; *(volatile UINT16 *)(i80312CfgRegs[indexNum].dataReg+lowTwobits) = (UINT16)val; } else { *(i80312CfgRegs[indexNum].addrReg) = idsel; *(volatile UINT32 *)(i80312CfgRegs[indexNum].dataReg) = val; } status = i80312PciAbortsClear(brNum); intUnlock(lockKey); return(status); }/********************************************************************* i80312PciCfgRd - perform a configuration read ** This routine performs a configuration read using the primary or secondary * Address Translation Unit (ATU).** RETURNS: OK, or ERROR if the transaction fails.** SEE ALSO: i80312PciCfgWr()*/STATUS i80312PciCfgRd ( int brNum, PCI_CFG_ADDR cfgAddr, /* configuration address command format */ UINT32* pVal /* store data read, must be a 32-bit pointer */ ) { volatile UINT32 data = 0xffffffff; int indexNum; int lockKey; int lowTwobits = cfgAddr.u.bit.regPos; int len = cfgAddr.u.bit.regLen; char * atu0ccdr; volatile UINT32 idsel; int status = ERROR; indexNum = (brNum >= i80312_BusNumbers[SECONDARY_BUS_INDEX])?1:0; /* highest possible number for RP */ if (cfgAddr.u.bit.devNum > I80312_PCI_DEVICE_MAX_NUM) return(ERROR); /* form either configuration type 0 or type 1 command */ if ( cfgAddr.u.bit.cfgType == PCI_CFG_TYP1) { /* form configuration type 1 command */ idsel = cfgAddr.u.whole & 0x0ffffff; /* mask off reserved area */ } else { /* form configuration type 0 command */ idsel = (cfgAddr.u.whole & 0x000007ff); /* add device number to ID select */ idsel |= (1 << (cfgAddr.u.bit.devNum + 11)); } /* Select Register Address to read data from */ if (len == PCI_BYTE_ACCESS || len == PCI_UINT16_ACCESS) { atu0ccdr = (char *)(i80312CfgRegs[indexNum].dataReg + lowTwobits); } else { atu0ccdr = (char *)(i80312CfgRegs[indexNum].dataReg); } /* have the exclusive access */ lockKey = intLock (); /* Select config space addr to read. */ *(i80312CfgRegs[indexNum].addrReg) = idsel; /* Coyanosa generates Data Aborts when non-responding addresses are read, so we must use MemProbe for PCI config space reads. */ status = vxMemProbe (atu0ccdr, VX_READ, len, (char *)&data); /* release the exclusive access */ intUnlock (lockKey); if (data == 0xffffffff) status = ERROR; if (status != ERROR) { switch(len) { case PCI_BYTE_ACCESS: *pVal = data & 0xff; /* writes to return field */ break; case PCI_UINT16_ACCESS: *pVal = data & 0xffff; /* writes to return field */ break; default: *pVal = data; /* writes to return field */ break; } } else *pVal = 0xffffffff; status = i80312PciAbortsClear(brNum); return(status); }/*************************************************************************** i80312PciFindDevice - find a PCI device by vendor and device ID** This routine finds a device on the PCI bus based on its vendor ID* (<vendorId>) and device ID (<deviceId>). The index number (<index>)* indicates the instance of the specified board: 0 meaning the first board,* 1 meaning the second, etc.** RETURNS: OK, or ERROR if no device is found.*/STATUS i80312PciFindDevice ( int vendorId, /* vendor ID */ int deviceId, /* device ID */ int index, /* desired instance of device */ UINT32 * pBusNo, /* bus number */ UINT32 * pDeviceNo, /* device number */ UINT32 * pFuncNo /* function number */ ) { int busNo, ebusNo; int deviceNo; int funcNo, configType; UINT32 device; UINT32 vendor; int maxFuncNum; PCI_CFG_ADDR cfgAddr; UINT8 rotary = I80310_ROT_STAT_REG_RD(); if (rotary != 0x7) /* rotary switch NOT in position 7 - stand-alone backplane */ { /* Start with the Primary Bus */ busNo = i80312PciChkBusNumbers(i80312_BusNumbers[PRIMARY_BUS_INDEX]); ebusNo = busNo + 2; } else { /* Start with the Secondary Bus */ busNo = i80312PciChkBusNumbers(i80312_BusNumbers[SECONDARY_BUS_INDEX]); ebusNo = busNo + 1; } for(; busNo <= ebusNo; busNo++) { if(busNo <= i80312_BusNumbers[SECONDARY_BUS_INDEX]) configType = PCI_CFG_TYP0; else configType = PCI_CFG_TYP1; for (deviceNo=0; deviceNo < 0x1f; deviceNo++) { cfgAddr.u.whole=CONFIG_WORD_PACK (configType,PCI_CFG_HEADER_TYPE,0,deviceNo, busNo,PCI_BYTE_ACCESS); maxFuncNum = i80312PciDeviceProbe (busNo,cfgAddr); for (funcNo=0; funcNo < maxFuncNum; funcNo++) { /* device found, set up PCI configuration address info */ cfgAddr.u.whole = CONFIG_WORD_PACK(configType, PCI_CFG_VENDOR_ID,funcNo,deviceNo,busNo,PCI_UINT16_ACCESS); /* find out the vendor id */ if (i80312PciCfgRd((int)busNo,cfgAddr,(UINT32 *)&vendor) != OK) break; cfgAddr.u.whole = CONFIG_WORD_PACK(configType, PCI_CFG_DEVICE_ID, funcNo,deviceNo,busNo,PCI_UINT16_ACCESS); /* find out the the device id */ i80312PciCfgRd((int)busNo,cfgAddr, (UINT32 *)&device); if ((vendor == vendorId) && (device == deviceId) && (index-- == 0)) { *pBusNo = busNo; *pDeviceNo = deviceNo; *pFuncNo = funcNo; return (OK); } } } } return (ERROR); }/****************************************************************************** i80312PciDeviceProbe - check if the device is in a PCI slot** This routine checks if there is a device in the specified PCI slot.* It returns one of the following macros:* .IP "NO_DEVICE (0)" 24* device not found* .IP "FUNC0_DEVICE (1)" 24* single-function device found* .IP "MULTI_FUNC_DEVICE" 24* multiple-function device found with a maximum of eight functions* .LP** RETURNS: The possible number of functions for this board.*/int i80312PciDeviceProbe ( int busMaster, /* which PCI interface Primary or Secondary */ PCI_CFG_ADDR cfgAddr /* configuration address word */ ) { UINT32 type; int status; /* read it */ status = i80312PciCfgRd(busMaster, cfgAddr, (UINT32 *)&type); if (status != OK || type == 0xffffffff) return (NO_DEVICE); /* no device found */ if (!(type & PCI_MULTI_FUNCTION) ) return (FUNC0_DEVICE); /* single function device found */ /* multifunction device */ return (MULTI_FUNC_DEVICE); /* assume maximum 8 functions for now */ }/*************************************************************************** pciBusScan - scan for a device on a PCI bus * * This routine scans both the primary and secondary PCI buses on the* I80312 in search of any device. It prints out the device ID * and vendor ID for any device is found.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -