?? bsl_pcibus.c
字號:
/******************************************************************************\
* Copyright (C) 2004 by RTD Embedded Technologies, Inc. All rights reserved.
* Confidential and Proprietary, Not for Public Release
*------------------------------------------------------------------------------
* PROJECT.......... Board Support Library for SPM6420
* VERSION.......... (Defined in README.TXT)
*------------------------------------------------------------------------------
* CONTENT.......... C source file for API of peripheral PCI Bus
* FILENAME......... bsl_pcibus.c
\******************************************************************************/
#define _BSL_PCIBUS_MOD_
#include <bsl_pcibus.h>
#include <c6x.h> // for SAVE_AMR, RESTORE_AMR, SAVE_SAT, RESTORE_SAT
#if (BSL_PCIBUS_SUPPORT)
/******************************************************************************\
* L O C A L S E C T I O N
\******************************************************************************/
/******************************************************************************\
* static macro declarations
\******************************************************************************/
#if (C64_SUPPORT)
#define PCIBUS_PCIIS_ERROR_FLAGS ( \
_PCI_PCIIS_PCIMASTER_MASK \
| _PCI_PCIIS_PCITARGET_MASK )
#else
#define PCIBUS_PCIIS_ERROR_FLAGS ( \
_PCI_PCIIS_PCIMASTER_MASK \
| _PCI_PCIIS_PCITARGET_MASK \
| _PCI_PCIIS_DMAHALTED_MASK )
#endif
#define PCIBUS_PCIIS_SYSTEM_FLAGS \
( _PCI_PCIIS_MASTEROK_MASK | PCIBUS_PCIIS_ERROR_FLAGS )
#define PCIBUS_PCIIS_USER_PRST _PCI_PCIIS_PRST_MASK
#define PCIBUS_PCIIS_USER_EERDY _PCI_PCIIS_EERDY_MASK
#define PCIBUS_PCIIS_USER_CFGERR _PCI_PCIIS_CFGERR_MASK
#define PCIBUS_PCIIS_USER_CFGDONE _PCI_PCIIS_CFGDONE_MASK
#define PCIBUS_PCIIS_USER_PWRHL _PCI_PCIIS_PWRHL_MASK
#define PCIBUS_PCIIS_USER_PWRLH _PCI_PCIIS_PWRLH_MASK
#define PCIBUS_PCIIS_USER_HOSTSW _PCI_PCIIS_HOSTSW_MASK
#define PCIBUS_PCIIS_USER_PWRMGMT _PCI_PCIIS_PWRMGMT_MASK
#define PCIBUS_PCIIS_USER_FLAGS ( \
PCIBUS_PCIIS_USER_PRST \
| PCIBUS_PCIIS_USER_EERDY \
| PCIBUS_PCIIS_USER_CFGERR \
| PCIBUS_PCIIS_USER_CFGDONE \
| PCIBUS_PCIIS_USER_PWRHL \
| PCIBUS_PCIIS_USER_PWRLH \
| PCIBUS_PCIIS_USER_HOSTSW \
| PCIBUS_PCIIS_USER_PWRMGMT )
/******************************************************************************\
* static typedef declarations
\******************************************************************************/
/******************************************************************************\
* static function declarations
\******************************************************************************/
void PCIBUS_RDY_ISR_CB();
void PCIBUS_ERR_ISR_CB(Uint32 regPCIIS);
void PCIBUS_accessReqExec();
/******************************************************************************\
* static variable definitions
\******************************************************************************/
// PCI interrupt source mask of user
// Accoring to this mask, the PCIBUS_USER_ISR_CB() function will be called.
Uint32 PCIBUS_PCIIEN_UserMask = 0;
// Pointer to the user's ISR for PCI interrupts
VFxn PCIBUS_USER_ISR_CB = INVALID_VFXN;
volatile Uint32 PCIBUS_breakWait = 0;
volatile PCIBUS_AccessReqObj *PCIBUS_pCurrentAccessReqObj = 0;
/******************************************************************************\
* static function definitions
\******************************************************************************/
/*----------------------------------------------------------------------------*/
void PCIBUS_init()
{
// remove the flags of the BSL system interrupt sources
Uint32 Reg = PCI_RGET(PCIIS);
Reg |= PCIBUS_PCIIS_SYSTEM_FLAGS;
PCI_RSET(PCIIS,Reg);
//PCI_RSET( PCIIS, PCIBUS_PCIIS_SYSTEM_FLAGS );
// enable the proper intettupt sources
PCI_RSET( PCIIEN, PCIBUS_PCIIS_SYSTEM_FLAGS );
// init/abort PCI transfer
PCI_RSET( PCIMC, 0x00040000u ); // CNT is not 0 to enable START field write
PCI_RSET( PCIMC, 0x00040000u ); // writing START field by 0 --> transfer stop
}
/*----------------------------------------------------------------------------*/
interrupt void BSL_PCI_ISR_DISPATCHER()
{
// In this ISR, there are assembly instructions whose results depend on
// AMR and SAT. That is, the AMR and SAT have to be saved and restored.
Uint32 temp_AMR, temp_SAT; // to save the AMR and SAT
register Uint32 regPCIIS;
// save AMR and SAT
SAVE_AMR(temp_AMR);
SAVE_SAT(temp_SAT);
regPCIIS = PCI_RGET(PCIIS);
if( regPCIIS & _PCI_PCIIS_MASTEROK_MASK )
{
// data transfer has completed successfully
// there must be no MASTER/TARGET ABORT error
PCIBUS_RDY_ISR_CB();
}
else if( regPCIIS & PCIBUS_PCIIS_ERROR_FLAGS )
{
// there is MASTER/TARGET ABORT error
PCIBUS_ERR_ISR_CB(regPCIIS);
}
if( regPCIIS & PCIBUS_PCIIEN_UserMask )
{
if( PCIBUS_USER_ISR_CB != INVALID_VFXN ) PCIBUS_USER_ISR_CB();
}
// remove flags of all the enabled interrupt sources
PCI_RSET( PCIIS, PCI_RGET(PCIIEN) );
// restore AMR and SAT
RESTORE_AMR(temp_AMR);
RESTORE_SAT(temp_SAT);
}
/*----------------------------------------------------------------------------*/
// data transfer has completed successfully
void PCIBUS_RDY_ISR_CB()
{
// clear error flags
PCIBUS_pCurrentAccessReqObj->regPCIMC &= PCIBUS_TOE_MASK_INV;
// data transfer has completed
PCIBUS_pCurrentAccessReqObj->completed = TRUE;
// release the HW peripheral unit
PCIBUS_pCurrentAccessReqObj = 0;
}
/*----------------------------------------------------------------------------*/
// an error occured during data transfer
void PCIBUS_ERR_ISR_CB(Uint32 regPCIIS)
{
Uint32 err = 0;
// set error flags for user
if( regPCIIS & _PCI_PCIIS_PCIMASTER_MASK ) err |= PCIBUS_TOE_REC_TARGET_ABORT;
if( regPCIIS & _PCI_PCIIS_PCITARGET_MASK ) err |= PCIBUS_TOE_REC_MASTER_ABORT;
#if !(C64_SUPPORT)
if( regPCIIS & _PCI_PCIIS_DMAHALTED_MASK ) err |= PCIBUS_TOE_DMAHALTED;
#endif
PCIBUS_pCurrentAccessReqObj->regPCIMC =
(PCIBUS_pCurrentAccessReqObj->regPCIMC & PCIBUS_TOE_MASK_INV) | err;
// data transfer has completed
PCIBUS_pCurrentAccessReqObj->completed = TRUE;
// release the HW peripheral unit
PCIBUS_pCurrentAccessReqObj = 0;
}
/*----------------------------------------------------------------------------*/
/*
* There is no check whether the previous transfer has already completed !!!
*/
void PCIBUS_accessReqExec()
{
register Uint32 r0;
// assert internal address
PCI_RSET( DSPMA, PCIBUS_pCurrentAccessReqObj->regDSPMA );
// assert PCI address
PCI_RSET( PCIMA, PCIBUS_pCurrentAccessReqObj->regPCIMA );
// preload Master Control register
r0 = PCIBUS_pCurrentAccessReqObj->regPCIMC;
PCI_RSET( PCIMC, r0 & 0xFFFF0000u );
// start data transfer
PCI_RSET( PCIMC, r0 & 0xFFFF0007u ); // unnecessary to do bit-AND
//PCI_RSET( PCIMC, r0 );
}
/******************************************************************************\
* G L O B A L S E C T I O N
\******************************************************************************/
/******************************************************************************\
* global variable definitions
\******************************************************************************/
/******************************************************************************\
* global function definitions
\******************************************************************************/
/*----------------------------------------------------------------------------*/
void PCIBUS_makeReq_Mem( PCIBUS_AccessReqObj * pReqObj,
Uint32 * pInternalBuffer, Uint32 pciAddress,
Uint16 lengthIn32bWs, Uint32 trDir_autoIncr)
{
// fill up request object
if( trDir_autoIncr & PCIBUS_AUTOINCREMENT_OFF )
{
// Set bit 1 of DSPMA
pReqObj->regDSPMA = ((Uint32)(pInternalBuffer) & 0xFFFFFFFCu) | 0x02;
}
else
{
pReqObj->regDSPMA = ((Uint32)(pInternalBuffer) & 0xFFFFFFFCu);
}
pReqObj->regPCIMA = pciAddress;
pReqObj->regPCIMC =
((Uint32)(lengthIn32bWs) << 18) | // 16 (for upper 16 bits) + 2 (32-bit words)
(trDir_autoIncr & _PCI_PCIMC_START_MASK);
pReqObj->completed = FALSE;
}
/*----------------------------------------------------------------------------*/
void PCIBUS_makeReq_IO( PCIBUS_AccessReqObj * pReqObj,
Uint32 *val, Uint32 pciAddress, Uint32 trDir)
{
// fill up request object
pReqObj->regDSPMA = (Uint32)(val);
pReqObj->regPCIMA = pciAddress & 0x0000FFFFu; // 16-bit I/O address
if( trDir == PCIBUS_TRANSFER_FROM_DSP )
{
pReqObj->regPCIMC = 0x00040000u | PCI_PCIMC_START_IOWRITE;
}
else
{
pReqObj->regPCIMC = 0x00040000u | PCI_PCIMC_START_IOREAD;
}
pReqObj->completed = FALSE;
}
/*----------------------------------------------------------------------------*/
void PCIBUS_makeReq_Cfg( PCIBUS_AccessReqObj * pReqObj,
Uint32 reg, Uint32 func, Uint32 dev, Uint32 *val, Uint32 trDir)
{
// fill up request object
pReqObj->regDSPMA = (Uint32)(val);
pReqObj->regPCIMA =
(((Uint32)0x00010000u) << (dev & 0xF))
| ((func << 8) & 0xF00u)
| ((reg << 2) & 0xFFu);
if( (trDir & _PCI_PCIMC_START_MASK) == PCIBUS_TRANSFER_FROM_DSP )
{
pReqObj->regPCIMC = 0x00040000u | PCI_PCIMC_START_CONFIGWRITE;
}
else
{
pReqObj->regPCIMC = 0x00040000u | PCI_PCIMC_START_CONFIGREAD;
}
pReqObj->completed = FALSE;
}
/*----------------------------------------------------------------------------*/
BOOL PCIBUS_accessReq( PCIBUS_AccessReqObj * pReqObj)
{
Uint32 gie;
gie = IRQ_globalDisable();
if (PCIBUS_pCurrentAccessReqObj != 0)
{
IRQ_globalRestore(gie);
pReqObj->regPCIMC = (pReqObj->regPCIMC & PCIBUS_TOE_MASK_INV) | PCIBUS_TOE_HARDWARE_BUSY;
return FALSE;
}
// lock the HW peripheral unit
PCIBUS_pCurrentAccessReqObj = pReqObj;
// data transfer is in process
pReqObj->completed = FALSE;
pReqObj->regPCIMC = (pReqObj->regPCIMC & PCIBUS_TOE_MASK_INV) | PCIBUS_TOE_TRANSFER_IN_PROCESS;
IRQ_globalRestore(gie);
PCIBUS_accessReqExec();
return TRUE;
}
/*----------------------------------------------------------------------------*/
void PCIBUS_accessMoreReq(
PCIBUS_AccessReqObj * pReqObjArray, Uint32 numberOfReqs)
{
PCIBUS_AccessReqObj * pReqObj;
Uint32 req;
pReqObj = pReqObjArray;
while (!PCIBUS_accessReqWithWait(pReqObj));
pReqObj++;
for( req = numberOfReqs - 1; req != 0; req--, pReqObj++ )
{
PCIBUS_accessReqWithWait( pReqObj );
}
}
BOOL PCIBUS_accessReqWithWait( PCIBUS_AccessReqObj *reqObj )
{
if( !PCIBUS_accessReq(reqObj) ) return FALSE;
while( !(reqObj->completed) );
return TRUE;
}
#endif /* BSL_PCIBUS_SUPPORT */
/******************************************************************************\
* End of bsl_pcibus.c
\******************************************************************************/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -