📄 syslib.c
字号:
void sysNvWrite ( ULONG offset, /* NVRAM offset to write the byte to */ UCHAR data /* datum byte */ ) { sysOutByte (NVRAM_BASE + offset, data); }/********************************************************************************* 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) { int msgSize; int msgIx; SIO_CHAN * pSioChan; /* serial I/O channel */ /* Check for a valid CPU type; If one is found, just return */ if ((CPU_TYPE == CPU_TYPE_603) || (CPU_TYPE == CPU_TYPE_603E) || (CPU_TYPE == CPU_TYPE_603P) || (CPU_TYPE == CPU_TYPE_603EK)) { return; } /* Invalid CPU type; print error message and terminate */ msgSize = strlen (wrongCpuMsg); sysSerialHwInit (); pSioChan = sysSerialChanGet (0); sioIoctl (pSioChan, SIO_MODE_SET, (void *) SIO_MODE_POLL); for (msgIx = 0; msgIx < msgSize; msgIx++) { while (sioPollOutput (pSioChan, wrongCpuMsg[msgIx]) == EAGAIN); } sysToMonitor (BOOT_NO_AUTOBOOT); }#if defined(INCLUDE_PMC_SPAN) && !defined(INCLUDE_PCI_AUTOCONF)/******************************************************************************** sysPmcSpanConfig - configure the PMC Span (DEC21150 PCI-to-PCI Bridge)** This routine configures the DEC21150 PCI-to-PCI Bridge on the PMC Span.** RETURNS: OK or ERROR if pciConfigLib has not been initialized.*/STATUS sysPmcSpanConfig ( int pciBusNo, /* PCI bus number */ int pciDevNo, /* PCI device number */ int pciFuncNo, /* PCI function number */ PMC_SPAN * pmcSpan /* pointer to PMC Span config array */ ) { STATUS result = OK; FAST i; /* Write all parameters in pcmSpan in the order given */ for (i = 0; i < NUM_PMC_SPAN_PARMS && result == OK; ++i) { switch (pmcSpan[i].parmSize) { case 1: result = pciConfigOutByte (pciBusNo, pciDevNo, pciFuncNo, pmcSpan[i].parmOffset, pmcSpan[i].parmValue); break; case 2: result = pciConfigOutWord (pciBusNo, pciDevNo, pciFuncNo, pmcSpan[i].parmOffset, pmcSpan[i].parmValue); break; case 4: result = pciConfigOutLong (pciBusNo, pciDevNo, pciFuncNo, pmcSpan[i].parmOffset, pmcSpan[i].parmValue); break; } } return (result); }#endif /* INCLUDE_PMC_SPAN & !defined(INCLUDE_PCI_AUTOCONF) *//******************************************************************************** sysMemProbeTrap - trap handler for vxMemProbe exception** This routine is called from the excConnectCode stub if sysMemProbeSup* generates an exception. By default, sysMemProbeSup returns OK.* This code changes the PC value to "sysProbeExc" (within the sysMemProbeSup* routine), and sysProbeExc sets the return value to ERROR.** RETURNS: 0*/static int sysMemProbeTrap ( ESFPPC * pEsf /* pointer to exception stack frame */ ) { REG_SET *pRegSet = &pEsf->regSet; pRegSet->pc = (_RType)sysProbeExc; /* sysProbeExc forces an ERROR return */ return (0); }/******************************************************************************** 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 Machine Check, Data Access and Alignment exceptions.** RETURNS: OK if probe succeeded or ERROR if an exception occured.*/static 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 */ ) { int oldLevel; FUNCPTR oldVec1; FUNCPTR oldVec2; STATUS status; UINT32 ppcHid0; /* H/W Implementation Dependent reg (PPC60x) */ UINT32 ppcMsr; /* PPC Machine Status Reg */ UINT16 temp; /* Probes performed with interrupts disabled */ oldLevel = intLock (); /* Handle Machine Check Exceptions locally */ oldVec1 = excVecGet ((FUNCPTR *) _EXC_OFF_MACH); excVecSet ((FUNCPTR *) _EXC_OFF_MACH, FUNCREF(sysMemProbeTrap)); /* * Handle Data Access Exceptions locally * * Data Access Exceptions will occur when trying to probe addresses * that have not been mapped by the MMU. */ oldVec2 = excVecGet ((FUNCPTR *) _EXC_OFF_DATA); excVecSet ((FUNCPTR *) _EXC_OFF_DATA, FUNCREF(sysMemProbeTrap)); /* Enable Machine Check Pin (EMCP) */ ppcHid0 = vxHid0Get(); vxHid0Set(ppcHid0 | _PPC_HID0_EMCP); /* Enable Machine Check exception */ ppcMsr = vxMsrGet(); vxMsrSet(ppcMsr | _PPC_MSR_ME); /* clear the PCI abort bits in the PCI status word */ sysPciConfigOutWord((UINT16 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_STATUS), (KAHLUA_PCI_RCV_MSTR_ABORT | KAHLUA_PCI_RCV_TGT_ABORT)); /* do probe */ if (mode == VX_READ) { status = sysMemProbeSup (length, adrs, pVal); SYNC; } else { status = sysMemProbeSup (length, pVal, adrs); SYNC; } /* check for valid address */ temp = sysPciConfigInWord((UINT16 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_STATUS)); if (temp & (KAHLUA_PCI_RCV_MSTR_ABORT | KAHLUA_PCI_RCV_TGT_ABORT)) status = ERROR; /* clear the PCI status reg. bits */ sysPciConfigOutWord((UINT16 *)(CNFG_PCI_HOST_BRDG + KAHLUA_CFG_STATUS), (KAHLUA_PCI_RCV_MSTR_ABORT | KAHLUA_PCI_RCV_TGT_ABORT)); /* Disable Machine Check Exceptions */ vxMsrSet(ppcMsr); /* Disable Machine Check Pin (EMCP) */ vxHid0Set(ppcHid0); /* restore original vectors and unlock */ excVecSet ((FUNCPTR *) _EXC_OFF_DATA, oldVec2); excVecSet ((FUNCPTR *) _EXC_OFF_MACH, oldVec1); intUnlock (oldLevel); 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* PCI_CFG_STATUS registers and the Universe PCI_CSR and V_AMERR registers.** RETURNS: N/A*/void sysProbeErrClr (void) { UINT32 pciCsr; /* Get current status */ pciCsr = sysPciInLong ((UINT32)(UNIVERSE_PCI_CSR)); /* Clear PCI_CSR */ sysPciOutLong ((UINT32)(UNIVERSE_PCI_CSR), pciCsr); /* Clear any VME address error */ sysPciOutLong ((UINT32)UNIVERSE_V_AMERR, V_AMERR_V_STAT); /* Force write due to Write-Posting and get updated status */ pciCsr = sysPciInLong ((UINT32)(UNIVERSE_PCI_CSR)); /* Clear PowerPC Data Access Exception Registers */ vxDarSet (0); vxDsisrSet (0); vxSrr0Set (0); vxSrr1Set (0); }/******************************************************************************** sysVmeProbe - probe a VME bus address** This routine probes an address on the VME bus. The PCI bridge chip* must have a special setup to enable generation of Master Abort cycles on* write probes and reception of Target Abort cycles on read probes.* The CPU must be configured to enable Machine Check exceptions. In * addition, if the probe is a write, the Universe must be configured to* disable Posted Writes. All probing is done with interrupts disabled.** NOTE: This routine assumes that the Universe Local Control registers are* dedicated to these VME address spaces:** .CS* LSI0 - LM/SIG (mailbox)* LSI1 - A32* LSI2 - A24* LSI3 - A16* .CE** RETURNS: OK or ERROR if address cannot be probed*/STATUS sysVmeProbe ( 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 = ERROR; UINT32 lsiCtlReg; /* adress of Local Control register in Universe */ UINT32 pciSlv1Ctl; /* Universe PCI Slave Image Control reg */ /* Determine which Control register controls this address */ if ((VME_LM_MSTR_SIZE != 0) && ((UINT32)adrs >= VME_LM_MSTR_BUS) && ((UINT32)adrs <= (VME_LM_MSTR_BUS + VME_LM_MSTR_SIZE))) lsiCtlReg = (UINT32)(UNIVERSE_LSI0_CTL); else if ((VME_A32_MSTR_SIZE != 0) && ((UINT32)adrs >= VME_A32_MSTR_LOCAL) && ((UINT32)adrs <= (VME_A32_MSTR_LOCAL + VME_A32_MSTR_SIZE))) lsiCtlReg = (UINT32)(UNIVERSE_LSI1_CTL); else if ((VME_A24_MSTR_SIZE != 0) && ((UINT32)adrs >= VME_A24_MSTR_LOCAL) && ((UINT32)adrs <= (VME_A24_MSTR_LOCAL + VME_A24_MSTR_SIZE))) lsiCtlReg = (UINT32)(UNIVERSE_LSI2_CTL); else if ((VME_A16_MSTR_SIZE != 0) && ((UINT32)adrs >= VME_A16_MSTR_LOCAL) && ((UINT32)adrs <= (VME_A16_MSTR_LOCAL + VME_A16_MSTR_SIZE))) lsiCtlReg = (UINT32)(UNIVERSE_LSI3_CTL); else return (ERROR); /* If write probe, disable Posted Writes in Universe */ pciSlv1Ctl = sysPciInLong (lsiCtlReg); if (mode == VX_WRITE) { sysPciOutLong (lsiCtlReg, (pciSlv1Ctl & ~LSI_CTL_WP)); } /* Perform probe */ status = sysMemProbeBus (adrs, mode, length, pVal); /* Restore Posted Writes by Universe if previously enabled */ if ((mode == VX_WRITE) && (pciSlv1Ctl & LSI_CTL_WP)) { sysPciOutLong (lsiCtlReg, pciSlv1Ctl); } return (status); }/******************************************************************************** sysPciProbe - probe a PCI bus address** This routine probes an address on the PCI bus. The PCI bridge chip* must have a special setup to enable generation of Master Abort cycles on* write probes and reception of Target Abort cycles on read probes.* The CPU must be configured to enable Machine Check exceptions. In * addition, if the probe is a write, the Universe must be configured to* disable Posted Writes. All probing is done with interrupts disabled.** RETURNS: OK or ERROR if address cannot be probed*/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 = ERROR; /* Perform probe */ status = sysMemProbeBus (adrs, mode, length, pVal); return (status); }/******************************************************************************** sysBusProbe - probe a bus address based on bus type.** This routine is a function hook into vxMemProbe. It determines which bus,* VME, PCI or local is being probed based on the address to be probed.* If the VME bus is being probed, the sysVmeProbe() routine is called to do* the special VME probing. If the PCI bus is being probed, the sysPciProbe()* routine is called to do the special PCI probing. If the local bus is being* probed, the routine returns ERROR which indicates that the default local* bus probe in vxMemProbe() should be used.** RETURNS: ERROR if local bus is being probed, OK if VME or PCI bus.*/STATUS sysBusProbe ( 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; /* Clear any existing errors/exceptions */ sysProbeErrClr (); /* Handle VME bus in special manner */ if (IS_VME_ADDRESS(adrs)) status = sysVmeProbe (adrs, mode, length, pVal); /* Handle PCI bus in special manner */ else if (IS_PCI_ADDRESS(adrs)) status = sysPciProbe (adrs, mode, length, pVal); /* Handle local bus in architecture-specific manner */ else status = vxMemArchProbe (adrs, mode, length, pVal); /* Clear any errors/exceptions before exiting */ sysProbeErrClr (); return (status); }/******************************************************************************** sysUsDelay - delay at least the specified amount of time (in microseconds)** This routine will delay for at least the specified amount of time using the* lower 32 bit "word" of the Time Base register as the timer. The accuracy of* the delay increases as the requested delay increases due to a certain amount* of overhead. As an example, a requested delay of 10 microseconds is* accurate within approximately twenty percent, and a requested delay of 100* microseconds is accurate within approximately two percent.** NOTE: This routine will not relinquish the CPU; it is meant to perform a* busy loop delay. The minimum delay that this routine will provide is* approximately 10 microseconds. The maximum delay is approximately the* size of UINT32; however, there is no roll-over compensation for the total* delay time, so it is necessary to back off
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -