/*****************************************************************************
*
* Freescale Semiconductor Inc.
* (c) Copyright 2004-2005 Freescale Semiconductor, Inc.
* (c) Copyright 2001-2004 Motorola, Inc.
* ALL RIGHTS RESERVED.
*
******************************************************************************
*
* File Name: ucan_flex.h
*
* Description: uCAN driver for FlexCAN private .h -USED INTERNALLY BY THE DRIVER
*
* $Version: 2.0.12.0$
*
*****************************************************************************/

#ifndef __UCAN_FLEX_H
#define __UCAN_FLEX_H

#ifndef __UCAN_H
#error uCAN: do not include the ucan_flex.h directly (include ucan.h instead)
#endif

#include "fcan.h" 		// FlexCAN low level driver

/************************************************************
*  uCAN-FlexCAN settings
************************************************************/

/* default settings */
#ifndef UCAN_MSGBUFF_COUNT
#define UCAN_MSGBUFF_COUNT ARCH_FCAN_MBCOUNT
#endif
#ifndef UCAN_MSGBUFFEX_COUNT
#define UCAN_MSGBUFFEX_COUNT 2
#endif
#ifndef UCAN_DATA_LSBFIRST
#define UCAN_DATA_LSBFIRST 0
#endif
#ifndef UCAN_MODULE
#define UCAN_MODULE FCAN
#endif

/* configuration checks: */
#if UCAN_MSGBUFF_COUNT != ARCH_FCAN_MBCOUNT
#error FlexCAN buffers are implemented in hardware. UCAN_MSGBUFF_COUNT must be 16 or 32 in ucan_cfg.h (see ARCH_FCAN_MBCOUNT in arch.h)
#endif
#if UCAN_MSGBUFFEX_COUNT != 2
#error FlexCAN buffers are implemented in hardware. UCAN_MSGBUFFEX_COUNT must be 2 in ucan_cfg.h
#endif
#if UCAN_DATA_LSBFIRST
#error FlexCAN byte-ordering is implemented in hardware. UCAN_DATA_LSBFIRST must be 0 in ucan_cfg.h
#endif

/************************************************************
*  define "assert" macro for selected paranoia level
************************************************************/

#if UCAN_DEBUG == 0
#define UCAN_ASSERT(cond, retcode) /* empty */
#elif UCAN_DEBUG == 1
#define UCAN_ASSERT(cond, retcode) if(!(cond)) return retcode
#else
#define UCAN_ASSERT(cond, retcode) if(!(cond)) { archDebugHalt(); return retcode; }
#endif

/************************************************************
*  internal helper routines
************************************************************/

void UCAN_CopySwab(register UWord16* psrcBuff, register UWord16* pdestBuff);
void UCAN_CopySplit(register UWord16* psrcBuff, register UWord16* pdestBuff);
void UCAN_CopyBuild(register UWord16* psrcBuff, register UWord16* pdestBuff);
void UCAN_Copy(register UWord16* psrcBuff, register UWord16* pdestBuff);

/************************************************************
*  inline functions
************************************************************/

// abort any operation activated for given buffer

inline UCANRESULT UCAN_AbortMB(UWord16 bNum)
{
	register arch_sFlexCAN_MB* pmb;
	UCAN_ASSERT(bNum < UCAN_MSGBUFF_COUNT, UCAN_ERR_MB);

	// disable interrupt for given MB
	ioctl(UCAN_MODULE, FCAN_MBINT_DISABLE, 1 << bNum);

	// address of our message buffer
	pmb = ioctl(UCAN_MODULE, FCAN_GET_MB_MODULE, bNum);
	ioctl(pmb, FCANMB_SET_CODE, FCAN_MB_CODE_RXVOID);
	
	return UCAN_OK;
}

// enqueue buffer for transmission

inline UCANRESULT UCAN_TransmitOnceMB(UWord16 bNum)
{
	register arch_sFlexCAN_MB* pmb;

	UCAN_ASSERT(bNum < UCAN_MSGBUFF_COUNT, UCAN_ERR_MB);

	// address of our message buffer
	pmb = ioctl(UCAN_MODULE, FCAN_GET_MB_MODULE, bNum);
	ioctl(pmb, FCANMB_SET_CODE, FCAN_MB_CODE_TXONCE);

	return UCAN_OK;
}


#endif /* __UCAN_FLEX_H */
