mirror of https://github.com/F-Stack/f-stack.git
816 lines
28 KiB
C
816 lines
28 KiB
C
/******************************************************************************
|
|
|
|
© 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(uint32_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) && ... */
|