📄 syslib.c
字号:
* Normally, the user specifies the amount of physical memory with the
* macro LOCAL_MEM_SIZE in config.h. If not defined, then LOCAL_MEM_SIZE
* is assumed to be, and must be, the true size of physical memory.
*
* NOTE: Do not 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;
if (physTop == NULL)
{
physTop = (char *)(LOCAL_MEM_LOCAL_ADRS + LOCAL_MEM_SIZE);
}
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 special circumstances, the user may wish to introduce a
* <startType> to enable special boot ROM facilities.
*
* RETURNS: Does not return.
*/
STATUS sysToMonitor
(
int startType /* parameter passed to ROM to tell it how to boot */
)
{
FUNCPTR pRom = (FUNCPTR) (ROM_TEXT_ADRS + 4); /* Warm reboot */
cacheDisable (0); /* disable icache */
cacheDisable (1); /* disable dcache */
sysDcrUicsrClear(0xffffffff); /* clear pending interrupts */
vxMsrSet (0); /* clear MSR */
(*pRom) (startType); /* jump to bootrom */
return (OK); /* in case we ever 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, always 0 (zero).
*
* SEE ALSO: sysProcNumSet()
*/
int sysProcNumGet (void)
{
return (0);
}
/*******************************************************************************
*
* sysProcNumSet - set the processor number
*
* This routine sets the processor number for the CPU board.
* Processor numbers should be unique on a single backplane.
*
* NOTE: This routine has no effect, since there is no VMEbus.
* RETURNS: N/A
*
* SEE ALSO: sysProcNumGet(),
*/
void sysProcNumSet
(
int procNum /* processor number (ignored in SBC405GP BSP) */
)
{
sysProcNum = sysProcNumGet();
}
/*******************************************************************************
*
* sysIntLockLevelSet - set the current interrupt lock-out level
*
* This routine sets the current interrupt lock-out level.
*
* NOTE: This routine has no effect, since the facility is currently not
* implemented.
*
* RETURNS: ERROR, always.
*/
int sysIntLockLevelSet
(
int newLvl /* new interrupt level */
)
{
return (ERROR);
}
/*******************************************************************************
*
* sysLocalDelay - delay of <ms_delay> milliseconds used before kernel is up
*
*
* RETURNS: N/A.
*/
void sysLocalDelay
(
UINT32 ms_delay
)
{
UINT32 start_upper;
UINT32 start_lower;
UINT32 end_upper;
UINT32 end_lower;
UINT32 upper;
UINT32 lower;
UINT32 delay;
BOOL timesup = FALSE;
/*
* Read the timebase twice to start
*/
vxTimeBaseGet (&start_upper, &start_lower);
vxTimeBaseGet (&end_upper, &end_lower);
while (timesup == FALSE)
{
/*
* 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 / sysTimerClkFreq);
delay += lower / (sysTimerClkFreq / 1000);
if (delay > ms_delay)
{
timesup = TRUE;
}
else
{
vxTimeBaseGet (&end_upper, &end_lower);
}
}
return;
}
/*******************************************************************************
*
* sysInfoGet - Determines system information (clock frequencies, etc.) based on
* Walnut board switch settings.
*
* This routine returns information about the current operating environment of
* the Walnut board. Optionally, it prints the information out.
*
* RETURNS: OK or ERROR.
*/
STATUS sysInfoGet
(
SYS_INFO * sysInfo,
int verbose
)
{
UINT32 pllmr;
UINT32 sysClkPeriodNs = ONE_BILLION / SYS_CLK_FREQ;
bzero((char *)sysInfo, sizeof(SYS_INFO));
/*
* Read PLL Mode register
*/
pllmr = sysDcrPllmrGet();
if (verbose)
printf("\n");
/*
* Determine FWD_DIV.
*/
switch (pllmr & PLLMR_FWD_DIV_MASK)
{
case PLLMR_FWD_DIV_BYPASS:
sysInfo->pllFwdDiv = 1;
break;
case PLLMR_FWD_DIV_3:
sysInfo->pllFwdDiv = 3;
break;
case PLLMR_FWD_DIV_4:
sysInfo->pllFwdDiv = 4;
break;
case PLLMR_FWD_DIV_6:
sysInfo->pllFwdDiv = 6;
break;
default:
if (verbose)
printf("Invalid FWDDIV bits in PLL Mode reg: %8.8x\a\n", pllmr);
return(ERROR);
break;
}
/*
* Determine FBK_DIV.
*/
switch (pllmr & PLLMR_FB_DIV_MASK)
{
case PLLMR_FB_DIV_1:
sysInfo->pllFbkDiv = 1;
break;
case PLLMR_FB_DIV_2:
sysInfo->pllFbkDiv = 2;
break;
case PLLMR_FB_DIV_3:
sysInfo->pllFbkDiv = 3;
break;
case PLLMR_FB_DIV_4:
sysInfo->pllFbkDiv = 4;
break;
}
/*
* Determine PLB_DIV.
*/
switch (pllmr & PLLMR_CPU_TO_PLB_MASK)
{
case PLLMR_CPU_PLB_DIV_1:
sysInfo->pllPlbDiv = 1;
break;
case PLLMR_CPU_PLB_DIV_2:
sysInfo->pllPlbDiv = 2;
break;
case PLLMR_CPU_PLB_DIV_3:
sysInfo->pllPlbDiv = 3;
break;
case PLLMR_CPU_PLB_DIV_4:
sysInfo->pllPlbDiv = 4;
break;
}
/*
* Determine PCI_DIV.
*/
switch (pllmr & PLLMR_PCI_TO_PLB_MASK)
{
case PLLMR_PCI_PLB_DIV_1:
sysInfo->pllPciDiv = 1;
break;
case PLLMR_PCI_PLB_DIV_2:
sysInfo->pllPciDiv = 2;
break;
case PLLMR_PCI_PLB_DIV_3:
sysInfo->pllPciDiv = 3;
break;
case PLLMR_PCI_PLB_DIV_4:
sysInfo->pllPciDiv = 4;
break;
}
/*
* Determine EXTBUS_DIV.
*/
switch (pllmr & PLLMR_EXB_TO_PLB_MASK)
{
case PLLMR_EXB_PLB_DIV_2:
sysInfo->pllExtBusDiv = 2;
break;
case PLLMR_EXB_PLB_DIV_3:
sysInfo->pllExtBusDiv = 3;
break;
case PLLMR_EXB_PLB_DIV_4:
sysInfo->pllExtBusDiv = 4;
break;
case PLLMR_EXB_PLB_DIV_5:
sysInfo->pllExtBusDiv = 5;
break;
}
/*
* Determine OPB_DIV.
*/
switch (pllmr & PLLMR_OPB_TO_PLB_MASK)
{
case PLLMR_OPB_PLB_DIV_1:
sysInfo->pllOpbDiv = 1;
break;
case PLLMR_OPB_PLB_DIV_2:
sysInfo->pllOpbDiv = 2;
break;
case PLLMR_OPB_PLB_DIV_3:
sysInfo->pllOpbDiv = 3;
break;
case PLLMR_OPB_PLB_DIV_4:
sysInfo->pllOpbDiv = 4;
break;
}
/*
* Check pllFwdDiv to see if running in bypass mode where the CPU speed
* is equal to the 405GP SYS_CLK_FREQ. If not in bypass mode, check VCO
* to make sure it is within the proper range.
* spec: VCO = SYS_CLOCK x FBKDIV x PLBDIV x FWDDIV
* Note freqVCO is calculated in Mhz to avoid errors introduced by rounding.
*/
if (sysInfo->pllFwdDiv == 1)
{
sysInfo->freqProcessor = SYS_CLK_FREQ;
sysInfo->freqPLB = SYS_CLK_FREQ/sysInfo->pllPlbDiv;
}
else
{
sysInfo->freqVCOMhz = (1000 * sysInfo->pllFwdDiv *
sysInfo->pllFbkDiv * sysInfo->pllPlbDiv)
/ sysClkPeriodNs;
if (sysInfo->freqVCOMhz >= VCO_MIN && sysInfo->freqVCOMhz <= VCO_MAX)
{
sysInfo->freqPLB = (ONE_BILLION /
((sysClkPeriodNs * 10) / sysInfo->pllFbkDiv)) * 10;
sysInfo->freqProcessor = sysInfo->freqPLB * sysInfo->pllPlbDiv;
}
else
{
if (verbose)
{
printf("Invalid VCO frequency calculated : %d MHz \a\n",
sysInfo->freqVCOMhz);
printf("It must be between %d-%d MHz \a\n", VCO_MIN, VCO_MAX);
printf("PLL Mode reg : %8.8x\a\n", pllmr);
}
return(ERROR);
}
}
return(OK);
}
/*******************************************************************************
*
* 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 */
switch(vxPvrGet())
{
case PVR_405GP_RA:
case PVR_405GP_RB:
case PVR_405GP_RC:
break;
case PVR_405GP_RD:
case PVR_405GP_RE:
return;
default:
break;
}
/* 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);
}
#ifdef INCLUDE_SHOW_ROUTINES
/*******************************************************************************
*
* sysInfoShow - Shows system information (clock frequencies, etc.) based on
* Walnut board switch settings.
*
* This routine displays information about the current operating environment of
* the Walnut board.
*
* RETURNS: OK or ERROR.
*/
STATUS sysInfoShow
(
)
{
SYS_INFO sysInfo;
return(sysInfoGet(&sysInfo, 1));
}
#endif /* INCLUDE_SHOW_ROUTINES */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -