📄 syslib.c
字号:
}/********************************************************************************* sysBusTas - test and set a location across the bus** The cPCI bridge chips do not support PCI target locking, therefore there is* no atomic RMW operation. This routine performs a software-based mutual* exclusion algorithm in place of a true test and set.** NOTE: This algorithm is performed through a PCI-to-PCI bridge to a shared* location that is subject to unprotected access by multiple simultaneous* processors. There is the possibility that the bridge will deliver a delayed* read completion to a PCI bus master which was not the original initiator of* the delayed read. The bridge delivers the delayed read completion to the new* requestor because it believes that the new delayed read request is actually* the original master performing a delayed read retry as required by the PCI* spec. When the original master comes back with the genuine retry, the bridge* treats it as a new request. When this "aliasing" occurs, a read performed* after a write can appear to complete ahead of the write, which is in violation* of PCI transaction ordering rules. Since this algorithm depends on a strict* time-ordered sequence of operations, it can deadlock under this condition.* To prevent the deadlock, a throw-away read must be performed after the initial* write. Since the bridge only remembers once instance of a queued delayed* read request, the throw-away read will "consume" the results of a* mis-directed read completion and subsequent read requests are guaranteed to* be queued and completed after the write.** RETURNS: TRUE if lock acquired.* FALSE if lock not acquired.** SEE ALSO: sysBusTasClear()*/BOOL sysBusTas ( char * adrs /* address to be tested and set */ ) { FAST int value; /* value to place in lock variable */ FAST int nChecks; /* number of times to re-check lock */ FAST int count; /* running count of re-checks */ int oldLvl; /* previous interrupt level */ volatile int * lockAdrs = (int *)adrs; if (sysSmUtilTasValue == 0) sysSmUtilTasValue = (TAS_CONST + sysProcNumGet ())<< 24; value = sysSmUtilTasValue; /* special value to write */ nChecks = DEFAULT_TAS_CHECKS; /* number of checks to do */ /* Lock out interrupts */ oldLvl = intLock (); /* Test that lock variable is initially empty */ if (*lockAdrs != 0) { intUnlock (oldLvl); return (FALSE); /* someone else has lock */ } /* Set lock value */ *lockAdrs = value; /* Perform a preliminary read due to PCI bridge issues */ count = *lockAdrs; /* Check that no one else is trying to take lock */ for (count = 0; count < nChecks; count++) { if (*lockAdrs != value) { intUnlock (oldLvl); return (FALSE); /* someone else stole lock */ } } intUnlock (oldLvl); return (TRUE); /* exclusive access obtained */ }/******************************************************************************** sysBusTasClear - clear a location set by sysBusTas()** This routine clears a bus test and set location. This routine is only* required if the sysBusTas() routine uses special semaphore techniques (such* as bus locking). Since the sysBusTas routine doesn't use any special* semaphore techniques, this routine is a no-op.** If used, the BSP activates this routine by placing its address into the* global variable 'smUtilTasClearRtn'.** RETURNS: N/A** SEE ALSO: sysBusTas()*/void sysBusTasClear ( volatile char * address /* address to be tested-and-cleared */ ) { }/******************************************************************************** sysNvRead - read one byte from NVRAM** This routine reads a single byte from a specified offset in NVRAM (User I2C* SROM).** RETURNS: The byte from the specified NVRAM offset.*/UCHAR sysNvRead ( ULONG offset /* NVRAM offset to read the byte from */ ) { UCHAR temp; (void) sysMotI2cRead(USR_SROM_ADRS, offset, &temp, I2C_ADDRESS_BYTES); return (temp); }/******************************************************************************** sysNvWrite - write one byte to NVRAM** This routine writes a single byte to a specified offset in NVRAM.(User I2C* SROM).** RETURNS: N/A*/void sysNvWrite ( ULONG offset, /* NVRAM offset to write the byte to */ UCHAR data /* datum byte */ ) { (void) sysMotI2cWrite (USR_SROM_ADRS, offset, &data, I2C_ADDRESS_BYTES); }/********************************************************************************* sysCpuCheck - confirm the CPU type** This routine validates the cpu type. If the wrong cpu type is discovered* a message is printed using the serial channel in polled mode.** RETURNS: N/A.*/void sysCpuCheck (void) { /* Check for a valid CPU type; If one is found, just return */#if (CPU == PPC603) if ((CPU_TYPE == CPU_TYPE_603) || (CPU_TYPE == CPU_TYPE_603E) || (CPU_TYPE == CPU_TYPE_603P)) { return; }#else /* (CPU == PPC604) */ if ((CPU_TYPE == CPU_TYPE_604) || (CPU_TYPE == CPU_TYPE_604E) || (CPU_TYPE == CPU_TYPE_604R) || (CPU_TYPE == CPU_TYPE_750) || (CPU_TYPE == CPU_TYPE_MAX) || (CPU_TYPE == CPU_TYPE_NITRO)) { return; }#endif /* (CPU == PPC604) */ /* Invalid CPU type; print error message and terminate */ sysDebugMsg (sysWrongCpuMsg, EXIT_TO_SYSTEM_MONITOR); /* does not return */ }/********************************************************************************* sysModeCheck - confirm the operating mode** This routine validates the operating mode. If the wrong mode is discovered* a message is printed using the serial channel in polled mode.** RETURNS: N/A.*/void sysModeCheck (void) { /* * If board status register indicates target mode (SYSCON bit set), * report the condition (for information only) and return. */ if (!sysMonarchMode) { sysDebugMsg( "sysModeCheck: SYSCON negated, Operating in Slave-Mode\r\n\n", CONTINUE_EXECUTION); } }/******************************************************************************** sysDelay - delay for approximately one millisecond** Delay for approximately one milli-second.** RETURNS: N/A*/void sysDelay (void) { sysUsDelay (1000); }/******************************************************************************** sysMemProbeTrap - trap handler for vxMemProbe exception** This routine is called from the excConnectCode stub if sysMemProbeSup* generates an exception. This code simply increments a static variable each* time an exception is generated and advances to the next instruction.*/LOCAL int sysMemProbeTrap ( ESFPPC * pEsf /* pointer to exception stack frame */ ) { REG_SET *pRegSet = &pEsf->regSet; pRegSet->pc += (_RType)4; /* advance to next instruction */ sysProbeFault++; /* indicate trap occurred */ return (0); }/******************************************************************************** sysPciWriteFlush - flush posted PCI writes from buffer** This routine flushes the posted write buffer in the Harrier and the Dec2155x if* it is present.** RETURNS: OK if flush succeeded or ERROR if an error occured.*/STATUS sysPciWriteFlush(void) { UINT16 devId;#ifdef INCLUDE_DEC2155X char * temp;#endif /* INCLUDE_DEC2155X */ /* * Flush Harrier posted write buffer by doing a dummy read of one * of its MPC registers */ devId = sysIn16 ((UINT16 *)(HARRIER_DEVICE_ID_REG));#ifdef INCLUDE_DEC2155X /* Flush the Dec2155x posted write buffer by reading from a cPCI location */ if (sysBusToLocalAdrs (PCI_SPACE_MEM_SEC, (char *) CPCI_FLUSH_ADDR, &temp) != OK) return (ERROR); temp = (char *)sysIn32 ((UINT32 *)temp);#endif /* INCLUDE_DEC2155X */ return (OK); }/******************************************************************************** sysMemProbeBus - probe an address on a bus.** This routine probes a specified address to see if it is readable or* writable, as specified by <mode>. The address will be read or written as* 1, 2, or 4 bytes as specified by <length> (values other than 1, 2, or 4* yield unpredictable results). If the probe is a VX_READ, the value read will* be copied to the location pointed to by <pVal>. If the probe is a VX_WRITE,* the value written will be taken from the location pointed to by <pVal>.* In either case, <pVal> should point to a value of 1, 2, or 4 bytes, as* specified by <length>.** This routine probes the specified address with interrupts disabled and* a special handler for Data Access and Alignment exceptions.** RETURNS: OK if probe succeeded or ERROR if an exception occured.*/LOCAL STATUS sysMemProbeBus ( char * adrs, /* address to be probed */ int mode, /* VX_READ or VX_WRITE */ int length, /* 1, 2 or 4 byte probe */ char * pVal /* address of value to write OR */ /* address of location to place value read */ ) { FUNCPTR oldVec; STATUS status; /* clear fault flag */ sysProbeFault = 0; /* * Handle Data Access Exceptions locally * * Data Access Exceptions will occur when trying to probe addresses * that have not been mapped by the MMU. */ oldVec = excVecGet ((FUNCPTR *) _EXC_OFF_DATA); excVecSet ((FUNCPTR *) _EXC_OFF_DATA, FUNCREF(sysMemProbeTrap)); /* do probe */ if (mode == VX_READ) { status = sysMemProbeSup (length, adrs, pVal); } else { status = sysMemProbeSup (length, pVal, adrs); } /* restore original vector */ excVecSet ((FUNCPTR *) _EXC_OFF_DATA, oldVec); if (status == OK) /* no parameter errors during probe */ { /* if a PCI write was performed, flush the write post buffer(s) */ if (mode == VX_WRITE) status = sysPciWriteFlush (); } /* check for MMU fault */ if (sysProbeFault != 0) return (ERROR); else return (status); }/******************************************************************************** sysProbeErrClr - clear errors associated with probing an address on a bus.** This routine clears the error flags and conditions in the DAR, DSISR, SRR0* and SRR1 PowerPC registers arising from probing addresses as well as the* Harrier MERST and PCI_CFG_STATUS registers and the Universe PCI_CSR and* V_AMERR registers.** RETURNS: N/A*/void sysProbeErrClr (void) {#ifdef INCLUDE_DEC2155X sysDec2155xErrClr ();#endif /* INCLUDE_DEC2155X */ /* Clear Harrier Error Exception Register */ *(UINT32 *)HARRIER_ERROR_EXCEPTION_CLEAR_REG = (HARRIER_EECL_PMA | HARRIER_EECL_PTA | HARRIER_EECL_PAP | HARRIER_EECL_PDP | HARRIER_EECL_PDT | HARRIER_EECL_PSE | HARRIER_EECL_PPE | HARRIER_EECL_POF); /* Clear Harrier's Cnfg Hdr Status Reg */ *(UINT32 *)HARRIER_PHB_STATUS_REG = (HARRIER_STAT_RCVPE | HARRIER_STAT_SIGSE | HARRIER_STAT_RCVMA | HARRIER_STAT_RCVTA | HARRIER_STAT_SIGTA | HARRIER_STAT_DPAR); /* Clear PowerPC Data Access Exception Registers */ vxDarSet (0); vxDsisrSet (0); vxSrr0Set (0); vxSrr1Set (0); }/******************************************************************************** sysPciProbe - probe a PCI bus address** This routine probes an address on the PCI bus. All probing is done with* interrupts disabled.** RETURNS: OK or ERROR if address cannot be probed*/LOCAL STATUS sysPciProbe ( char * adrs, /* address to be probed */ int mode, /* VX_READ or VX_WRITE */ int length, /* 1, 2 or 4 byte probe */ char * pVal /* address of value to write OR */ /* address of location to place value read */ ) { STATUS status
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -