f-stack/freebsd/contrib/ncsw/Peripherals/BM/bm.c

816 lines
28 KiB
C
Raw Normal View History

2017-04-21 10:43:26 +00:00
/******************************************************************************
<EFBFBD> 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc.
All rights reserved.
This is proprietary source code of Freescale Semiconductor Inc.,
and its use is subject to the NetComm Device Drivers EULA.
The copyright notice above does not evidence any actual or intended
publication of such source code.
ALTERNATIVELY, redistribution and use in source and binary forms, with
or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Freescale Semiconductor nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************/
/******************************************************************************
@File bm.c
@Description BM
*//***************************************************************************/
#include "error_ext.h"
#include "std_ext.h"
#include "string_ext.h"
#include "sprint_ext.h"
#include "debug_ext.h"
#include "mm_ext.h"
#include "bm.h"
t_Error BM_ConfigException(t_Handle h_Bm, e_BmExceptions exception, bool enable);
/****************************************/
/* static functions */
/****************************************/
static volatile bool blockingFlag = FALSE;
static void BmIpcMsgCompletionCB(t_Handle h_Module,
uint8_t *p_Msg,
uint8_t *p_Reply,
uint32_t replyLength,
t_Error status)
{
SANITY_CHECK_RETURN(h_Module, E_INVALID_HANDLE);
#ifdef DISABLE_SANITY_CHECKS
UNUSED(h_Module);
#endif /* DISABLE_SANITY_CHECKS */
UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status);
blockingFlag = FALSE;
}
static t_Error BmHandleIpcMsgCB(t_Handle h_Bm,
uint8_t *p_Msg,
uint32_t msgLength,
uint8_t *p_Reply,
uint32_t *p_ReplyLength)
{
t_Bm *p_Bm = (t_Bm*)h_Bm;
t_BmIpcMsg *p_IpcMsg = (t_BmIpcMsg*)p_Msg;
t_BmIpcReply *p_IpcReply = (t_BmIpcReply *)p_Reply;
SANITY_CHECK_RETURN_ERROR(p_Bm, E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE);
#ifdef DISABLE_SANITY_CHECKS
UNUSED(msgLength);
#endif /* DISABLE_SANITY_CHECKS */
ASSERT_COND(p_IpcMsg);
memset(p_IpcReply, 0, (sizeof(uint8_t) * BM_IPC_MAX_REPLY_SIZE));
*p_ReplyLength = 0;
switch(p_IpcMsg->msgId)
{
case (BM_MASTER_IS_ALIVE):
*(uint8_t*)p_IpcReply->replyBody = 1;
*p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
break;
case (BM_SET_POOL_THRESH):
{
t_Error err;
t_BmIpcPoolThreshParams ipcPoolThresh;
memcpy((uint8_t*)&ipcPoolThresh, p_IpcMsg->msgBody, sizeof(t_BmIpcPoolThreshParams));
if ((err = BmSetPoolThresholds(p_Bm,
ipcPoolThresh.bpid,
ipcPoolThresh.thresholds)) != E_OK)
REPORT_ERROR(MINOR, err, NO_MSG);
break;
}
case (BM_UNSET_POOL_THRESH):
{
t_Error err;
t_BmIpcPoolThreshParams ipcPoolThresh;
memcpy((uint8_t*)&ipcPoolThresh, p_IpcMsg->msgBody, sizeof(t_BmIpcPoolThreshParams));
if ((err = BmUnSetPoolThresholds(p_Bm,
ipcPoolThresh.bpid)) != E_OK)
REPORT_ERROR(MINOR, err, NO_MSG);
break;
}
case (BM_GET_COUNTER):
{
t_BmIpcGetCounter ipcCounter;
uint32_t count;
memcpy((uint8_t*)&ipcCounter, p_IpcMsg->msgBody, sizeof(t_BmIpcGetCounter));
count = BmGetCounter(p_Bm,
(e_BmInterModuleCounters)ipcCounter.enumId,
ipcCounter.bpid);
memcpy(p_IpcReply->replyBody, (uint8_t*)&count, sizeof(uint32_t));
*p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
break;
}
case (BM_GET_REVISION):
{
t_BmRevisionInfo revInfo;
t_BmIpcRevisionInfo ipcRevInfo;
p_IpcReply->error = (uint32_t)BmGetRevision(h_Bm, &revInfo);
ipcRevInfo.majorRev = revInfo.majorRev;
ipcRevInfo.minorRev = revInfo.minorRev;
memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcRevInfo, sizeof(t_BmIpcRevisionInfo));
*p_ReplyLength = sizeof(uint32_t) + sizeof(t_BmIpcRevisionInfo);
break;
}
case (BM_FORCE_BPID):
{
t_BmIpcBpidParams ipcBpid;
uint32_t tmp;
memcpy((uint8_t*)&ipcBpid, p_IpcMsg->msgBody, sizeof(t_BmIpcBpidParams));
tmp = BmBpidGet(p_Bm, TRUE, ipcBpid.bpid);
memcpy(p_IpcReply->replyBody, (uint8_t*)&tmp, sizeof(uint32_t));
*p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
break;
}
case (BM_PUT_BPID):
{
t_Error err;
t_BmIpcBpidParams ipcBpid;
memcpy((uint8_t*)&ipcBpid, p_IpcMsg->msgBody, sizeof(t_BmIpcBpidParams));
if ((err = BmBpidPut(p_Bm, ipcBpid.bpid)) != E_OK)
REPORT_ERROR(MINOR, err, NO_MSG);
break;
}
default:
*p_ReplyLength = 0;
RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!"));
}
return E_OK;
}
static t_Error CheckBmParameters(t_Bm *p_Bm)
{
if ((p_Bm->p_BmDriverParams->partBpidBase + p_Bm->p_BmDriverParams->partNumOfPools) > BM_MAX_NUM_OF_POOLS)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partBpidBase+partNumOfPools out of range!!!"));
if (p_Bm->guestId == NCSW_MASTER_ID)
{
if (!p_Bm->p_BmDriverParams->totalNumOfBuffers)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfBuffers must be larger than '0'!!!"));
if (p_Bm->p_BmDriverParams->totalNumOfBuffers > (128*MEGABYTE))
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfBuffers must be equal or smaller than 128M!!!"));
if(!p_Bm->f_Exception)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided"));
}
return E_OK;
}
static __inline__ uint32_t GenerateThresh(uint32_t val, int roundup)
{
uint32_t e = 0; /* co-efficient, exponent */
uint32_t oddbit = 0;
while(val > 0xff) {
oddbit = val & 1;
val >>= 1;
e++;
if(roundup && oddbit)
val++;
}
return (val | (e << 8));
}
static t_Error BmSetPool(t_Handle h_Bm,
uint8_t bpid,
uint32_t swdet,
uint32_t swdxt,
uint32_t hwdet,
uint32_t hwdxt)
{
t_Bm *p_Bm = (t_Bm*)h_Bm;
SANITY_CHECK_RETURN_ERROR(p_Bm, E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(bpid < BM_MAX_NUM_OF_POOLS, E_INVALID_VALUE);
WRITE_UINT32(p_Bm->p_BmRegs->swdet[bpid], GenerateThresh(swdet, 0));
WRITE_UINT32(p_Bm->p_BmRegs->swdxt[bpid], GenerateThresh(swdxt, 1));
WRITE_UINT32(p_Bm->p_BmRegs->hwdet[bpid], GenerateThresh(hwdet, 0));
WRITE_UINT32(p_Bm->p_BmRegs->hwdxt[bpid], GenerateThresh(hwdxt, 1));
return E_OK;
}
/****************************************/
/* Inter-Module functions */
/****************************************/
t_Error BmSetPoolThresholds(t_Handle h_Bm, uint8_t bpid, const uint32_t *thresholds)
{
t_Bm *p_Bm = (t_Bm*)h_Bm;
SANITY_CHECK_RETURN_ERROR(p_Bm, E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(bpid < BM_MAX_NUM_OF_POOLS, E_INVALID_VALUE);
if (p_Bm->guestId == NCSW_MASTER_ID)
{
return BmSetPool(h_Bm,
bpid,
thresholds[0],
thresholds[1],
thresholds[2],
thresholds[3]);
}
else if (p_Bm->h_Session)
{
t_BmIpcMsg msg;
t_BmIpcPoolThreshParams ipcPoolThresh;
t_Error errCode = E_OK;
memset(&msg, 0, sizeof(t_BmIpcMsg));
ipcPoolThresh.bpid = bpid;
memcpy(ipcPoolThresh.thresholds, thresholds, sizeof(uintptr_t) * MAX_DEPLETION_THRESHOLDS);
msg.msgId = BM_SET_POOL_THRESH;
memcpy(msg.msgBody, &ipcPoolThresh, sizeof(t_BmIpcPoolThreshParams));
if ((errCode = XX_IpcSendMessage(p_Bm->h_Session,
(uint8_t*)&msg,
sizeof(msg.msgId) + sizeof(t_BmIpcPoolThreshParams),
NULL,
NULL,
NULL,
NULL)) != E_OK)
RETURN_ERROR(MAJOR, errCode, NO_MSG);
return E_OK;
}
else
RETURN_ERROR(WARNING, E_NOT_SUPPORTED, ("IPC"));
}
t_Error BmUnSetPoolThresholds(t_Handle h_Bm, uint8_t bpid)
{
t_Bm *p_Bm = (t_Bm*)h_Bm;
SANITY_CHECK_RETURN_ERROR(p_Bm, E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(bpid < BM_MAX_NUM_OF_POOLS, E_INVALID_VALUE);
if (p_Bm->guestId == NCSW_MASTER_ID)
{
return BmSetPool(h_Bm,
bpid,
0,
0,
0,
0);
}
else if (p_Bm->h_Session)
{
t_BmIpcMsg msg;
t_BmIpcPoolThreshParams ipcPoolThresh;
t_Error errCode = E_OK;
memset(&msg, 0, sizeof(t_BmIpcMsg));
memset(&ipcPoolThresh, 0, sizeof(t_BmIpcPoolThreshParams));
ipcPoolThresh.bpid = bpid;
msg.msgId = BM_UNSET_POOL_THRESH;
memcpy(msg.msgBody, &ipcPoolThresh, sizeof(t_BmIpcPoolThreshParams));
if ((errCode = XX_IpcSendMessage(p_Bm->h_Session,
(uint8_t*)&msg,
sizeof(msg.msgId) + sizeof(t_BmIpcPoolThreshParams),
NULL,
NULL,
NULL,
NULL)) != E_OK)
RETURN_ERROR(MAJOR, errCode, NO_MSG);
return E_OK;
}
else
RETURN_ERROR(WARNING, E_NOT_SUPPORTED, ("IPC"));
}
uint32_t BmGetCounter(t_Handle h_Bm, e_BmInterModuleCounters counter, uint8_t bpid)
{
t_Bm *p_Bm = (t_Bm*)h_Bm;
SANITY_CHECK_RETURN_VALUE(p_Bm, E_INVALID_HANDLE, 0);
SANITY_CHECK_RETURN_VALUE(bpid < BM_MAX_NUM_OF_POOLS, E_INVALID_VALUE, 0);
SANITY_CHECK_RETURN_VALUE((((p_Bm->guestId == NCSW_MASTER_ID) && p_Bm->p_BmRegs) ||
(p_Bm->guestId != NCSW_MASTER_ID)), E_INVALID_STATE, 0);
if ((p_Bm->guestId == NCSW_MASTER_ID) ||
(!p_Bm->h_Session && p_Bm->p_BmRegs))
{
switch(counter)
{
case(e_BM_IM_COUNTERS_POOL_CONTENT):
return GET_UINT32(p_Bm->p_BmRegs->content[bpid]);
case(e_BM_IM_COUNTERS_POOL_SW_DEPLETION):
return GET_UINT32(p_Bm->p_BmRegs->sdcnt[bpid]);
case(e_BM_IM_COUNTERS_POOL_HW_DEPLETION):
return GET_UINT32(p_Bm->p_BmRegs->hdcnt[bpid]);
case(e_BM_IM_COUNTERS_FBPR):
return GET_UINT32(p_Bm->p_BmRegs->fbpr_fpc);
default:
break;
}
/* should never get here */
ASSERT_COND(FALSE);
}
else if (p_Bm->h_Session)
{
t_BmIpcMsg msg;
t_BmIpcReply reply;
t_BmIpcGetCounter ipcCounter;
uint32_t replyLength;
uint32_t count;
t_Error errCode = E_OK;
memset(&msg, 0, sizeof(t_BmIpcMsg));
memset(&reply, 0, sizeof(t_BmIpcReply));
ipcCounter.bpid = bpid;
ipcCounter.enumId = (uint32_t)counter;
msg.msgId = BM_GET_COUNTER;
memcpy(msg.msgBody, &ipcCounter, sizeof(t_BmIpcGetCounter));
replyLength = sizeof(uint32_t) + sizeof(uint32_t);
if ((errCode = XX_IpcSendMessage(p_Bm->h_Session,
(uint8_t*)&msg,
sizeof(msg.msgId) + sizeof(t_BmIpcGetCounter),
(uint8_t*)&reply,
&replyLength,
NULL,
NULL)) != E_OK)
REPORT_ERROR(MAJOR, errCode, NO_MSG);
if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t)))
{
REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
errCode = E_INVALID_VALUE;
}
if (errCode == E_OK)
{
memcpy((uint8_t*)&count, reply.replyBody, sizeof(uint32_t));
return count;
}
}
else
REPORT_ERROR(WARNING, E_NOT_SUPPORTED,
("In 'guest', either IPC or 'baseAddress' is required!"));
return 0;
}
t_Error BmGetRevision(t_Handle h_Bm, t_BmRevisionInfo *p_BmRevisionInfo)
{
t_Bm *p_Bm = (t_Bm*)h_Bm;
uint32_t tmpReg;
SANITY_CHECK_RETURN_ERROR(p_Bm, E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(p_BmRevisionInfo, E_NULL_POINTER);
SANITY_CHECK_RETURN_ERROR((((p_Bm->guestId == NCSW_MASTER_ID) && p_Bm->p_BmRegs) ||
(p_Bm->guestId != NCSW_MASTER_ID)), E_INVALID_STATE);
if ((p_Bm->guestId == NCSW_MASTER_ID) ||
(!p_Bm->h_Session && p_Bm->p_BmRegs))
{
/* read revision register 1 */
tmpReg = GET_UINT32(p_Bm->p_BmRegs->ip_rev_1);
p_BmRevisionInfo->majorRev = (uint8_t)((tmpReg & REV1_MAJOR_MASK) >> REV1_MAJOR_SHIFT);
p_BmRevisionInfo->minorRev = (uint8_t)((tmpReg & REV1_MINOR_MASK) >> REV1_MINOR_SHIFT);
}
else if (p_Bm->h_Session)
{
t_BmIpcMsg msg;
t_BmIpcReply reply;
t_BmIpcRevisionInfo ipcRevInfo;
uint32_t replyLength;
t_Error errCode = E_OK;
memset(&msg, 0, sizeof(t_BmIpcMsg));
memset(&reply, 0, sizeof(t_BmIpcReply));
msg.msgId = BM_GET_REVISION;
replyLength = sizeof(uint32_t) + sizeof(t_BmIpcRevisionInfo);
if ((errCode = XX_IpcSendMessage(p_Bm->h_Session,
(uint8_t*)&msg,
sizeof(msg.msgId),
(uint8_t*)&reply,
&replyLength,
NULL,
NULL)) != E_OK)
RETURN_ERROR(MAJOR, errCode, NO_MSG);
if (replyLength != (sizeof(uint32_t) + sizeof(t_BmIpcRevisionInfo)))
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
memcpy((uint8_t*)&ipcRevInfo, reply.replyBody, sizeof(t_BmIpcRevisionInfo));
p_BmRevisionInfo->majorRev = ipcRevInfo.majorRev;
p_BmRevisionInfo->minorRev = ipcRevInfo.minorRev;
return (t_Error)(reply.error);
}
else
RETURN_ERROR(WARNING, E_NOT_SUPPORTED,
("In 'guest', either IPC or 'baseAddress' is required!"));
return E_OK;
}
static void FreeInitResources(t_Bm *p_Bm)
{
if (p_Bm->p_FbprBase)
XX_FreeSmart(p_Bm->p_FbprBase);
if (p_Bm->h_Session)
XX_IpcFreeSession(p_Bm->h_Session);
if (p_Bm->h_BpidMm)
MM_Free(p_Bm->h_BpidMm);
}
/****************************************/
/* API Init unit functions */
/****************************************/
t_Handle BM_Config(t_BmParam *p_BmParam)
{
t_Bm *p_Bm;
SANITY_CHECK_RETURN_VALUE(p_BmParam, E_INVALID_HANDLE, NULL);
p_Bm = (t_Bm *)XX_Malloc(sizeof(t_Bm));
if (!p_Bm)
{
REPORT_ERROR(MAJOR, E_NO_MEMORY, ("BM obj!!!"));
return NULL;
}
memset(p_Bm, 0, sizeof(t_Bm));
p_Bm->p_BmDriverParams = (t_BmDriverParams *)XX_Malloc(sizeof(t_BmDriverParams));
if (!p_Bm->p_BmDriverParams)
{
XX_Free(p_Bm);
REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Bm driver parameters"));
return NULL;
}
memset(p_Bm->p_BmDriverParams, 0, sizeof(t_BmDriverParams));
p_Bm->guestId = p_BmParam->guestId;
p_Bm->p_BmDriverParams->partNumOfPools = p_BmParam->partNumOfPools;
p_Bm->p_BmDriverParams->partBpidBase = p_BmParam->partBpidBase;
p_Bm->p_BmRegs = (t_BmRegs *)UINT_TO_PTR(p_BmParam->baseAddress);
if (p_Bm->guestId == NCSW_MASTER_ID)
{
p_Bm->exceptions = DEFAULT_exceptions;
p_Bm->f_Exception = p_BmParam->f_Exception;
p_Bm->h_App = p_BmParam->h_App;
p_Bm->errIrq = p_BmParam->errIrq;
p_Bm->p_BmDriverParams->totalNumOfBuffers = p_BmParam->totalNumOfBuffers;
p_Bm->p_BmDriverParams->fbprMemPartitionId = p_BmParam->fbprMemPartitionId;
p_Bm->p_BmDriverParams->fbprThreshold = DEFAULT_fbprThreshold;
p_Bm->p_BmDriverParams->liodn = p_BmParam->liodn;
}
/* build the BM partition IPC address */
memset(p_Bm->moduleName, 0, MODULE_NAME_SIZE);
if(Sprint (p_Bm->moduleName, "BM_0_%d",p_Bm->guestId) != (p_Bm->guestId<10 ? 6:7))
{
XX_Free(p_Bm->p_BmDriverParams);
XX_Free(p_Bm);
REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
return NULL;
}
return p_Bm;
}
t_Error BM_Init(t_Handle h_Bm)
{
t_Bm *p_Bm = (t_Bm *)h_Bm;
t_Error err;
SANITY_CHECK_RETURN_ERROR(p_Bm, E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(p_Bm->p_BmDriverParams, E_INVALID_HANDLE);
CHECK_INIT_PARAMETERS(p_Bm, CheckBmParameters);
if (p_Bm->p_BmDriverParams->partNumOfPools)
if (MM_Init(&p_Bm->h_BpidMm, p_Bm->p_BmDriverParams->partBpidBase, p_Bm->p_BmDriverParams->partNumOfPools) != E_OK)
{
FreeInitResources(p_Bm);
RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("BM-BPIDS-MEM partition!!!"));
}
if (p_Bm->guestId == NCSW_MASTER_ID)
{
uint64_t phyAddr;
t_BmRevisionInfo revInfo;
uint32_t dsSize, exp;
BmGetRevision(p_Bm, &revInfo);
DBG(TRACE, ("Bman ver:%02x,%02x", revInfo.majorRev, revInfo.minorRev));
WRITE_UINT32(p_Bm->p_BmRegs->liodnr, (uint16_t)p_Bm->p_BmDriverParams->liodn);
/* FBPR memory */
dsSize = (uint32_t)(p_Bm->p_BmDriverParams->totalNumOfBuffers * (FBPR_ENTRY_SIZE / 8));
LOG2(dsSize, exp);
if (!POWER_OF_2(dsSize)) (exp++);
dsSize = (uint32_t)(1 << exp);
if (dsSize < (4*KILOBYTE))
{
dsSize = (4*KILOBYTE);
LOG2(dsSize, exp);
}
p_Bm->p_FbprBase = XX_MallocSmart(dsSize, (int)p_Bm->p_BmDriverParams->fbprMemPartitionId, dsSize);
if (!p_Bm->p_FbprBase)
{
FreeInitResources(p_Bm);
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FBPR obj!!!"));
}
phyAddr = XX_VirtToPhys(p_Bm->p_FbprBase);
WRITE_UINT32(p_Bm->p_BmRegs->fbpr_bare, ((uint32_t)(phyAddr >> 32) & 0xffff));
WRITE_UINT32(p_Bm->p_BmRegs->fbpr_bar, (uint32_t)phyAddr);
WRITE_UINT32(p_Bm->p_BmRegs->fbpr_ar, (exp - 1));
WRITE_UINT32(p_Bm->p_BmRegs->fbpr_fp_lwit, p_Bm->p_BmDriverParams->fbprThreshold);
WRITE_UINT32(p_Bm->p_BmRegs->err_isr, p_Bm->exceptions);
WRITE_UINT32(p_Bm->p_BmRegs->err_ier, p_Bm->exceptions);
WRITE_UINT32(p_Bm->p_BmRegs->err_isdr, 0x0);
if (p_Bm->errIrq != NO_IRQ)
{
XX_SetIntr(p_Bm->errIrq, BM_ErrorIsr, p_Bm);
XX_EnableIntr(p_Bm->errIrq);
}
if ((err = XX_IpcRegisterMsgHandler(p_Bm->moduleName, BmHandleIpcMsgCB, p_Bm, BM_IPC_MAX_REPLY_SIZE)) != E_OK)
{
FreeInitResources(p_Bm);
RETURN_ERROR(MAJOR, err, NO_MSG);
}
}
else /* guest mode */
{
char masterModuleName[MODULE_NAME_SIZE];
memset(masterModuleName, 0, MODULE_NAME_SIZE);
if(Sprint (masterModuleName, "BM_0_%d", NCSW_MASTER_ID) != (NCSW_MASTER_ID<10 ? 6:7))
{
FreeInitResources(p_Bm);
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
}
p_Bm->h_Session = XX_IpcInitSession(masterModuleName, p_Bm->moduleName);
if (p_Bm->h_Session)
{
t_BmIpcMsg msg;
uint8_t isMasterAlive = 0;
t_BmIpcReply reply;
uint32_t replyLength;
memset(&msg, 0, sizeof(t_BmIpcMsg));
memset(&reply, 0, sizeof(t_BmIpcReply));
msg.msgId = BM_MASTER_IS_ALIVE;
replyLength = sizeof(uint32_t) + sizeof(uint8_t);
do
{
blockingFlag = TRUE;
if ((err = XX_IpcSendMessage(p_Bm->h_Session,
(uint8_t*)&msg,
sizeof(msg.msgId),
(uint8_t*)&reply,
&replyLength,
BmIpcMsgCompletionCB,
p_Bm)) != E_OK)
REPORT_ERROR(MAJOR, err, NO_MSG);
while(blockingFlag) ;
if(replyLength != (sizeof(uint32_t) + sizeof(uint8_t)))
REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
isMasterAlive = *(uint8_t*)(reply.replyBody);
} while (!isMasterAlive);
}
}
XX_Free(p_Bm->p_BmDriverParams);
p_Bm->p_BmDriverParams = NULL;
return E_OK;
}
t_Error BM_Free(t_Handle h_Bm)
{
t_Bm *p_Bm = (t_Bm *)h_Bm;
if (!p_Bm)
return ERROR_CODE(E_INVALID_HANDLE);
if (p_Bm->guestId == NCSW_MASTER_ID)
{
XX_IpcUnregisterMsgHandler(p_Bm->moduleName);
if (p_Bm->errIrq != NO_IRQ)
{
XX_DisableIntr(p_Bm->errIrq);
XX_FreeIntr(p_Bm->errIrq);
}
}
FreeInitResources(p_Bm);
if(p_Bm->p_BmDriverParams)
XX_Free(p_Bm->p_BmDriverParams);
XX_Free(p_Bm);
return E_OK;
}
t_Error BM_ConfigException(t_Handle h_Bm, e_BmExceptions exception, bool enable)
{
t_Bm *p_Bm = (t_Bm*)h_Bm;
uint32_t bitMask = 0;
SANITY_CHECK_RETURN_ERROR(p_Bm, E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(p_Bm->p_BmDriverParams, E_INVALID_HANDLE);
GET_EXCEPTION_FLAG(bitMask, exception);
if(bitMask)
{
if (enable)
p_Bm->exceptions |= bitMask;
else
p_Bm->exceptions &= ~bitMask;
}
else
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
return E_OK;
}
t_Error BM_ConfigFbprThreshold(t_Handle h_Bm, uint32_t threshold)
{
t_Bm *p_Bm = (t_Bm *)h_Bm;
SANITY_CHECK_RETURN_ERROR(p_Bm, E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(p_Bm->p_BmDriverParams, E_INVALID_HANDLE);
p_Bm->p_BmDriverParams->fbprThreshold = threshold;
return E_OK;
}
void BM_ErrorIsr(t_Handle h_Bm)
{
t_Bm *p_Bm = (t_Bm *)h_Bm;
uint32_t tmpReg;
SANITY_CHECK_RETURN(p_Bm, E_INVALID_HANDLE);
if (p_Bm->guestId != NCSW_MASTER_ID)
{
REPORT_ERROR(WARNING, E_INVALID_OPERATION, ("Master Only"));
return;
}
tmpReg = GET_UINT32(p_Bm->p_BmRegs->err_isr);
tmpReg &= GET_UINT32(p_Bm->p_BmRegs->err_ier);
WRITE_UINT32(p_Bm->p_BmRegs->err_isr, tmpReg);
if (tmpReg & BM_EX_INVALID_COMMAND)
p_Bm->f_Exception(p_Bm->h_App, e_BM_EX_INVALID_COMMAND);
if (tmpReg & BM_EX_FBPR_THRESHOLD)
p_Bm->f_Exception(p_Bm->h_App, e_BM_EX_FBPR_THRESHOLD);
if (tmpReg & BM_EX_MULTI_ECC)
p_Bm->f_Exception(p_Bm->h_App, e_BM_EX_MULTI_ECC);
if (tmpReg & BM_EX_SINGLE_ECC)
p_Bm->f_Exception(p_Bm->h_App, e_BM_EX_SINGLE_ECC);
}
uint32_t BM_GetCounter(t_Handle h_Bm, e_BmCounters counter)
{
t_Bm *p_Bm = (t_Bm*)h_Bm;
SANITY_CHECK_RETURN_VALUE(p_Bm, E_INVALID_HANDLE, 0);
SANITY_CHECK_RETURN_VALUE(!p_Bm->p_BmDriverParams, E_INVALID_STATE, 0);
switch(counter)
{
case(e_BM_COUNTERS_FBPR):
return BmGetCounter(p_Bm, e_BM_IM_COUNTERS_FBPR, 0);
default:
break;
}
/* should never get here */
ASSERT_COND(FALSE);
return 0;
}
t_Error BM_SetException(t_Handle h_Bm, e_BmExceptions exception, bool enable)
{
t_Bm *p_Bm = (t_Bm*)h_Bm;
uint32_t tmpReg, bitMask = 0;
SANITY_CHECK_RETURN_ERROR(p_Bm, E_INVALID_HANDLE);
if (p_Bm->guestId != NCSW_MASTER_ID)
RETURN_ERROR(WARNING, E_INVALID_OPERATION, ("Master Only"));
BM_ConfigException(p_Bm, exception, enable);
tmpReg = GET_UINT32(p_Bm->p_BmRegs->err_ier);
if(enable)
tmpReg |= bitMask;
else
tmpReg &= ~bitMask;
WRITE_UINT32(p_Bm->p_BmRegs->err_ier, tmpReg);
return E_OK;
}
t_Error BM_GetRevision(t_Handle h_Bm, t_BmRevisionInfo *p_BmRevisionInfo)
{
t_Bm *p_Bm = (t_Bm*)h_Bm;
SANITY_CHECK_RETURN_ERROR(p_Bm, E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(p_BmRevisionInfo, E_NULL_POINTER);
return BmGetRevision(p_Bm, p_BmRevisionInfo);
}
#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
t_Error BM_DumpRegs(t_Handle h_Bm)
{
t_Bm *p_Bm = (t_Bm *)h_Bm;
DECLARE_DUMP;
if (p_Bm->guestId != NCSW_MASTER_ID)
RETURN_ERROR(WARNING, E_INVALID_OPERATION, ("Master Only"));
SANITY_CHECK_RETURN_ERROR(p_Bm, E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(!p_Bm->p_BmDriverParams, E_INVALID_STATE);
DUMP_SUBTITLE(("\n"));
DUMP_TITLE(p_Bm->p_BmRegs, ("BmRegs Regs"));
DUMP_ARR(p_Bm->p_BmRegs, swdet);
DUMP_ARR(p_Bm->p_BmRegs, hwdet);
DUMP_ARR(p_Bm->p_BmRegs, swdxt);
DUMP_ARR(p_Bm->p_BmRegs, hwdxt);
DUMP_ARR(p_Bm->p_BmRegs, sdcnt);
DUMP_ARR(p_Bm->p_BmRegs, hdcnt);
DUMP_ARR(p_Bm->p_BmRegs, content);
DUMP_ARR(p_Bm->p_BmRegs, hdptr);
DUMP_VAR(p_Bm->p_BmRegs,fbpr_fpc);
DUMP_VAR(p_Bm->p_BmRegs,fbpr_fp_lwit);
DUMP_ARR(p_Bm->p_BmRegs, cmd_pm_cfg);
DUMP_ARR(p_Bm->p_BmRegs, fl_pm_cfg);
DUMP_VAR(p_Bm->p_BmRegs, ecsr);
DUMP_VAR(p_Bm->p_BmRegs, ecir);
DUMP_VAR(p_Bm->p_BmRegs, eadr);
DUMP_ARR(p_Bm->p_BmRegs, edata);
DUMP_VAR(p_Bm->p_BmRegs,sbet);
DUMP_VAR(p_Bm->p_BmRegs,efcr);
DUMP_VAR(p_Bm->p_BmRegs,efar);
DUMP_VAR(p_Bm->p_BmRegs,sbec0);
DUMP_VAR(p_Bm->p_BmRegs,sbec1);
DUMP_VAR(p_Bm->p_BmRegs,ip_rev_1);
DUMP_VAR(p_Bm->p_BmRegs,ip_rev_2);
DUMP_VAR(p_Bm->p_BmRegs,fbpr_bare);
DUMP_VAR(p_Bm->p_BmRegs,fbpr_bar);
DUMP_VAR(p_Bm->p_BmRegs,fbpr_ar);
DUMP_VAR(p_Bm->p_BmRegs,srcidr);
DUMP_VAR(p_Bm->p_BmRegs,liodnr);
DUMP_VAR(p_Bm->p_BmRegs,err_isr);
DUMP_VAR(p_Bm->p_BmRegs,err_ier);
DUMP_VAR(p_Bm->p_BmRegs,err_isdr);
DUMP_VAR(p_Bm->p_BmRegs,err_iir);
DUMP_VAR(p_Bm->p_BmRegs,err_ifr);
return E_OK;
}
#endif /* (defined(DEBUG_ERRORS) && ... */