📄 syslib.c
字号:
* run-time update of the MMU entry for main RAM */ sysPhysMemDesc[1].len = (UINT)(sysPhysMemTop () - RAM_LOW_ADRS);#endif /* INCLUDE_MMU */#ifdef INCLUDE_PCI /* PCI initialization */ pciIntLibInit(); pciConfigLibInit(PCI_MECHANISM_1, PCICFGADR, PCICFGDATA, (int)NULL); sysPciInit();#endif#ifdef INCLUDE_NETWORK sysNetHwInit(); /* network interface */#endif#ifdef INCLUDE_SERIAL sysSerialHwInit(); /* serial devices */#endif }/********************************************************************************* sysHwInit2 - initialize additional system hardware** This routine connects system interrupt vectors and configures any* required features not configured by sysHwInit. It is called from usrRoot()* in usrConfig.c after the multitasking kernel has started.** RETURNS: N/A*/void sysHwInit2 ( void ) { static int initialized; /* must protect against double call! */ if (!initialized) { initialized = TRUE; /* connect external interrupt handler */ excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_INTR, sysCPC700IntHandler);#ifdef INCLUDE_NETWORK sysNetHwInit2 (); /* network interface */#endif#ifdef INCLUDE_SERIAL sysSerialHwInit2 (); /* connect serial interrupts */#endif /* * L2 Cache setup */#if defined(INCLUDE_CACHE_SUPPORT) && defined(INCLUDE_CACHE_L2) sysL2CacheInit();# ifdef USER_L2_CACHE_ENABLE sysL2CacheEnable();# endif#endif /*(INCLUDE_CACHE_SUPPORT) && (INCLUDE_CACHE_L2)*/ } }/********************************************************************************* sysPhysMemTop - get the address of the top of physical memory** This routine returns the address of the first missing byte of memory,* which indicates the top of memory.** Normally, the user specifies the amount of physical memory with the* macro LOCAL_MEM_SIZE in config.h. BSPs that support run-time* memory sizing do so only if the macro LOCAL_MEM_AUTOSIZE is defined.* If not defined, then LOCAL_MEM_SIZE is assumed to be, and must be, the* true size of physical memory.** NOTE: Do no adjust LOCAL_MEM_SIZE to reserve memory for application* use. See sysMemTop() for more information on reserving memory.** RETURNS: The address of the top of physical memory.** SEE ALSO: sysMemTop()*/char * sysPhysMemTop ( void ) { static char * physTop = NULL;#ifdef LOCAL_MEM_AUTOSIZE int memSize;#endif if (physTop == NULL) {#ifdef LOCAL_MEM_AUTOSIZE /* * Look at the CPC700 memory controller configuration to determine the * the total amount of SDRAM installed. SDRAM bank 1 is always * used on Spruce, and the starting address is always 0x00000000. * Read MB1EA and add 1MB to it to get the size of bank 1. * If the SDRAM DIMM is double sided, the bit in MBEN for bank 2 will * be set. If this is true just double the total SDRAM size. */ sysOutLong(MEMCFGADR, MB1EA); memSize = sysInLong(MEMCFGDATA); memSize += 0x100000; /* add 1MB */ sysOutLong(MEMCFGADR, MBEN); if (sysInLong(MEMCFGDATA) & MBEN_BANK2) memSize = memSize * 2; /* SDRAM bank 2 is enabled */ physTop = (char *)memSize;#else /* Don't do autosizing, if size is given */ physTop = (char *)(LOCAL_MEM_LOCAL_ADRS + LOCAL_MEM_SIZE);#endif /* LOCAL_MEM_AUTOSIZE */ } return physTop; }/********************************************************************************* sysMemTop - get the address of the top of VxWorks memory** This routine returns a pointer to the first byte of memory not* controlled or used by VxWorks.** The user can reserve memory space by defining the macro USER_RESERVED_MEM* in config.h. This routine returns the address of the reserved memory* area. The value of USER_RESERVED_MEM is in bytes.** RETURNS: The address of the top of VxWorks memory.*/char * sysMemTop ( void ) { static char * memTop = NULL; if (memTop == NULL) { memTop = sysPhysMemTop () - USER_RESERVED_MEM; } return memTop; }/********************************************************************************* sysToMonitor - transfer control to the ROM monitor** This routine transfers control to the ROM monitor. Normally, it is called* only by reboot()--which services ^X--and by bus errors at interrupt level.* However, in some circumstances, the user may wish to introduce a* <startType> to enable special boot ROM facilities.** The entry point for a warm boot is defined by the macro ROM_WARM_ADRS* in config.h. We do an absolute jump to this address to enter the* ROM code.** RETURNS: Does not return.*/STATUS sysToMonitor ( int startType /* parameter passed to ROM to tell it how to boot */ ) { FUNCPTR pRom = (FUNCPTR) (ROM_WARM_ADRS); intLock (); /* disable interrupts */ cacheDisable (0); /* Disable the Instruction Cache */ cacheDisable (1); /* Disable the Data Cache */ sysHwInit (); /* disable all sub systems to a quiet state */ vxMsrSet (0); /* Clear the MSR */ (*pRom) (startType); /* jump to romInit.s */ return (OK); /* in case we continue from ROM monitor */ }/******************************************************************************** sysProcNumGet - get the processor number** This routine returns the processor number for the CPU board, which is* set with sysProcNumSet().** RETURNS: The processor number for the CPU board.** SEE ALSO: sysProcNumSet()*/int sysProcNumGet ( void ) { return (sysProcNum); }/******************************************************************************** sysProcNumSet - set the processor number** This routine sets the processor number for the CPU board. Processor numbers* should be unique on a single backplane.** For bus systems, it is assumes that processor 0 is the bus master and* exports its memory to the bus.** RETURNS: N/A** SEE ALSO: sysProcNumGet()*/void sysProcNumSet ( int procNum /* processor number */ ) { sysProcNum = procNum; }/********************************************************************************* 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) {#if (CPU == PPC604) int msgSize; int msgIx; SIO_CHAN * pSioChan; /* serial I/O channel */ /* * Check for a valid CPU type; If one is found, just return. * 603 kernels run OK on 604's, but 604 kernels need to check. * Also prevent recursive loop with sysHwInit() and sysToMonitor(). */ if (sysInCpuCheck || (CPU_TYPE == CPU_TYPE_740_750) || (CPU_TYPE == CPU_TYPE_740L_750L) || (CPU_TYPE == CPU_TYPE_740L_750L_2) || (CPU_TYPE == CPU_TYPE_740L_750L_3) || (CPU_TYPE == CPU_TYPE_750CX) || (CPU_TYPE == CPU_TYPE_750FX) || (CPU_TYPE == CPU_TYPE_750FX_7K) || (((CPU_TYPE >> 16) & 0xfff0) == CPU_FAMILY_750FX)) { return; } sysInCpuCheck = TRUE; /* * Invalid CPU type; print error message and terminate. * Check size of wrongCpuPvr[] above if changing this. */ sprintf(wrongCpuPvr, "[PVR=%08x]!\r\n", vxPvrGet()); sysSerialHwInit (); pSioChan = sysSerialChanGet (0); sioIoctl (pSioChan, SIO_MODE_SET, (void *) SIO_MODE_POLL); msgSize = strlen (wrongCpuMsg); for (msgIx = 0; msgIx < msgSize; msgIx++) { while (sioPollOutput (pSioChan, wrongCpuMsg[msgIx]) == EAGAIN); } /* * Include the final NULL byte here, in case sysToMonitor() shuts * down the I/O before the last-written byte actually makes it * onto the line. (Such disappearances have been observed.) */ msgSize = strlen (wrongCpuPvr) + 1; for (msgIx = 0; msgIx < msgSize; msgIx++) { while (sioPollOutput (pSioChan, wrongCpuPvr[msgIx]) == EAGAIN); } sysToMonitor (BOOT_NO_AUTOBOOT);#endif /* CPU == PPC604 */ }/********************************************************************************* sysGetBusSpd - gets the speed of the 6xx/7xx bus** This routine uses the FPGA on the Spruce board to determine the speed at* which the Processor bus is operating.* If the FPGA reg says the Spruce board is using an external clock source,* we will assume it is an 83.33MHz source for faster rated CPC700s.* Otherwise, check to see if the bus speed is 66.66MHz or 60MHz.** RETURNS: N/A.*/int sysGetBusSpd ( void ) { UCHAR fpga_reg; UINT32 cpu_bus_freq; fpga_reg = sysInByte(FPGA_REG_A); if (fpga_reg & UART_CLK_EXT) cpu_bus_freq = 83333333; /* 83MHz */ else { if (fpga_reg & UART_CLK_33) cpu_bus_freq = 66666666; /* 66MHz */ else cpu_bus_freq = 60000000; /* 60MHz */ } return(cpu_bus_freq); }/********************************************************************************* sysLocalDelay - delay of <ms_delay> milliseconds used before kernel is up*** RETURNS: N/A.*/void sysLocalDelay ( UINT32 ms_delay ) { UINT32 timebase_freq; UINT32 start_upper; UINT32 start_lower; UINT32 end_upper; UINT32 end_lower; UINT32 upper; UINT32 lower; UINT32 delay; int timesup = 0; /* * get the frequency that the timebase operates at */ timebase_freq = sysGetBusSpd() / 4; /* * Read the timebase twice to start */ vxTimeBaseGet (&start_upper, &start_lower); vxTimeBaseGet (&end_upper, &end_lower); while (timesup == 0) { /* * Determine if the delay has been long enough */ upper = end_upper - start_upper; if (start_lower > end_lower) upper--; lower=end_lower - start_lower; delay = 1000 * upper * (0xFFFFFFFF / timebase_freq); delay += lower / (timebase_freq / 1000); if (delay > ms_delay) { timesup = 1; } else { vxTimeBaseGet (&end_upper, &end_lower); } } return; }void sysDelay(void) ;void sysMsDelay(UINT delay) ;/******************************************************************************** sysDelay - delay for approximately one millisecond** Delay for approximately one milli-second.** RETURNS: N/A*/void sysDelay (void) { sysLocalDelay(1);#if 0 sysMsDelay(1) ;#endif }#if 1/******************************************************************************** sysMsDelay - delay for the specified amount of time (MS)** This routine will delay for the specified amount of time by counting* decrementer ticks.** This routine is not dependent on a particular rollover value for* the decrementer, it should work no matter what the rollover* value is.** A small amount of count may be lost at the rollover point resulting in* the sysMsDelay() causing a slightly longer delay than requested.** This routine will produce incorrect results if the delay time requested* requires a count larger than 0xffffffff to hold the decrementer* elapsed tick count. For a System Bus Speed of 67 MHZ this amounts to* about 258 seconds.** RETURNS: N/A*//* ZZZZZZZZZZZZ */#define DELTA(a,b) (abs((int)a - (int)b))void sysMsDelay ( UINT delay /* length of time in MS to delay */ ) { register UINT oldval; /* decrementer value */ register UINT newval; /* decrementer value */ register UINT totalDelta; /* Dec. delta for entire delay period */ register UINT decElapsed; /* cumulative decrementer ticks */ /* * Calculate delta of decrementer ticks for desired elapsed time. * The macro DEC_CLOCK_FREQ MUST REFLECT THE PROPER 6xx BUS SPEED. */ totalDelta = ((DEC_CLOCK_FREQ / 4) / 1000) * delay; /* * Now keep grabbing decrementer value and incrementing "decElapsed" until * we hit the desired delay value. Compensate for the fact that we may * read the decrementer at 0xffffffff before the interrupt service * routine has a chance to set in the rollover value. */ decElapsed = 0; oldval = vxDecGet (); while (decElapsed < totalDelta) { newval = vxDecGet (); if ( DELTA(oldval,newval) < 1000 ) decElapsed += DELTA(oldval,newval); /* no rollover */ else if (newval > oldval) decElapsed += abs((int)oldval); /* rollover */ oldval = newval; } }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -