📄 syslib.c
字号:
#ifdef INCLUDE_DEC2155X
/*
* translate from compact PCI address space to local PCI address
* space.
*/
if ( sysCpciToPciAdrs (PCI_BAR_SPACE_IO, busAdrs, &busAdrs) != OK )
return (ERROR);
/* fall through */
#endif /* INCLUDE_DEC2155X */
case PCI_SPACE_IO_PRI:
/*
* translate from local PCI address space to CPU address
* space.
*/
return ( sysPciToCpuAdrs (PCI_BAR_SPACE_IO, busAdrs, pLocalAdrs) );
break;
case PCI_SPACE_MEMIO_SEC:
case PCI_SPACE_MEM_SEC:
#ifdef INCLUDE_DEC2155X
/*
* translate from compact PCI address space to local PCI address
* space.
*/
if ( sysCpciToPciAdrs (PCI_BAR_SPACE_MEM, busAdrs, &busAdrs) != OK)
return (ERROR);
/* fall through */
#endif /* INCLUDE_DEC2155X */
case PCI_SPACE_MEMIO_PRI:
case PCI_SPACE_MEM_PRI:
/*
* translate from local PCI address space to CPU address
* space.
*/
return (sysPciToCpuAdrs (PCI_BAR_SPACE_MEM, busAdrs, pLocalAdrs) );
break;
default:
return (ERROR);
break;
}
}
/*******************************************************************************
*
* 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 */
)
{
}
/******************************************************************************
*
* sysSpuriousIntHandler - spurious interrupt handler
*
* This is the entry point for spurious interrupts.
*
* NOTE: This routine has no effect.
*
* This routine catches all spurious interrupts. It does nothing at all.
*
* RETURNS: N/A.
*
* RETURNS: N/A
*
* NOMANUAL
*/
void sysSpuriousIntHandler (void)
{
}
/*******************************************************************************
*
* 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_8245)||
(CPU_TYPE == CPU_TYPE_603P) || (CPU_TYPE == CPU_TYPE_603EK)||(CPU_TYPE == CPU_TYPE_750))
{
/*flashled(2,2);*/
return;
}
/* Invalid CPU type; print error message and terminate */
msgSize = strlen (wrongCpuMsg);
/* flashled(2,5);*/
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);
}
/******************************************************************************
*
* 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.
*/
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 + MPC8240_CFG_STATUS),
(MPC8240_PCI_RCV_MSTR_ABORT | MPC8240_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 +
MPC8240_CFG_STATUS));
if (temp & (MPC8240_PCI_RCV_MSTR_ABORT | MPC8240_PCI_RCV_TGT_ABORT))
status = ERROR;
/* clear the PCI status reg. bits */
sysPciConfigOutWord((UINT16 *)(CNFG_PCI_HOST_BRDG + MPC8240_CFG_STATUS),
(MPC8240_PCI_RCV_MSTR_ABORT | MPC8240_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)
{
/* 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. 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -