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

📄 bsl_pcibus.c

📁 BSL64xx是一dsp的程序代码
💻 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 + -