⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syslib.c

📁 MPC8241:本程序是freescale的824*系列的BSP源程序
💻 C
📖 第 1 页 / 共 5 页
字号:
#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 + -