blob: f7d152712e3d6cdd1092ac322fcb3eba2141345c [file] [log] [blame]
/* eip202_cdr_dscr.c
*
* EIP-202 Ring Control Driver Library
* 1) Descriptor I/O Driver Library API implementation
* 2) Internal Command Descriptor interface implementation
*/
/* -------------------------------------------------------------------------- */
/* */
/* Module : ddk197 */
/* Version : 5.6.1 */
/* Configuration : DDK-197-GPL */
/* */
/* Date : 2022-Dec-16 */
/* */
/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries. */
/* */
/* This program is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation, either version 2 of the License, or */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* -------------------------------------------------------------------------- */
/*----------------------------------------------------------------------------
* This module implements (provides) the following interface(s):
*/
// Descriptor I/O Driver Library API implementation
#include "eip202_cdr.h"
// Internal Command Descriptor interface
#include "eip202_cdr_dscr.h"
/*----------------------------------------------------------------------------
* This module uses (requires) the following interface(s):
*/
// Default configuration
#include "c_eip202_ring.h"
// EIP-202 Ring Control Driver Library Internal interfaces
#include "eip202_ring_internal.h"
#include "eip202_cdr_level0.h" // EIP-202 Level 0 macros
#include "eip202_cdr_fsm.h" // CDR State machine
#include "eip202_cd_format.h" // CD Format API
// Driver Framework Basic Definitions API
#include "basic_defs.h" // IDENTIFIER_NOT_USED, bool, uint32_t
// Driver Framework DMA Resource API
#include "dmares_types.h" // types of the DMA resource API
#include "dmares_rw.h" // read/write of the DMA resource API.
/*----------------------------------------------------------------------------
* Definitions and macros
*/
/*----------------------------------------------------------------------------
* Local variables
*/
/*----------------------------------------------------------------------------
* EIP202Lib_CDR_FillLevel_Finalize
*
*/
static EIP202_Ring_Error_t
EIP202Lib_CDR_FillLevel_Finalize(
const unsigned int CDWordCount,
volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p,
unsigned int * const FillLevelDscrCount_p)
{
#ifdef EIP202_RING_DEBUG_FSM
EIP202_Ring_Error_t rv;
if(CDWordCount == 0)
// CD Ring is empty
rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
EIP202_CDR_STATE_INITIALIZED);
else if(CDWordCount > 0 &&
CDWordCount < (unsigned int)TrueIOArea_p->RingSizeWordCount)
// CD Ring is free
rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
EIP202_CDR_STATE_FREE);
else if(CDWordCount == (unsigned int)TrueIOArea_p->RingSizeWordCount)
// CD Ring is full
rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
EIP202_CDR_STATE_FULL);
else
rv = EIP202_RING_ILLEGAL_IN_STATE;
if(rv != EIP202_RING_NO_ERROR)
return EIP202_RING_ILLEGAL_IN_STATE;
#endif
// Store actual fill level
*FillLevelDscrCount_p = CDWordCount /
(unsigned int)TrueIOArea_p->DescOffsWordCount;
// Return actual fill level plus one descriptor to distinguish
// ring full from ring empty
if(CDWordCount < (unsigned int)TrueIOArea_p->RingSizeWordCount)
(*FillLevelDscrCount_p)++;
return EIP202_RING_NO_ERROR;
}
/*----------------------------------------------------------------------------
Internal Command Descriptor interface
---------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* EIP202_CDR_WriteCB
*/
int
EIP202_CDR_WriteCB(
void * const CallbackParam1_p,
const int CallbackParam2,
const unsigned int WriteIndex,
const unsigned int WriteCount,
const unsigned int TotalWriteLimit,
const void * Descriptors_p,
const int DescriptorCount,
const unsigned int DescriptorSkipCount)
{
Device_Handle_t Device;
unsigned int i, DescOffsetWordCount;
unsigned int nWritten = 0;
volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p =
CDRIOAREA(CallbackParam1_p);
if(CallbackParam1_p == NULL || Descriptors_p == NULL)
return -1;
IDENTIFIER_NOT_USED(CallbackParam2);
IDENTIFIER_NOT_USED(DescriptorCount);
IDENTIFIER_NOT_USED(TotalWriteLimit);
Device = TrueIOArea_p->Device;
DescOffsetWordCount = (unsigned int)TrueIOArea_p->DescOffsWordCount;
// Write descriptors to CDR
for(i = WriteIndex; i < WriteIndex + WriteCount; i++)
{
EIP202_CD_Write(
TrueIOArea_p->RingHandle,
i * DescOffsetWordCount,
((const EIP202_ARM_CommandDescriptor_t *)Descriptors_p) +
DescriptorSkipCount + nWritten,
TrueIOArea_p->fATP);
nWritten++;
}
if (nWritten > 0)
{
// Call PreDMA to prepared descriptors in Ring DMA buffer for handover
// to the Device (the EIP-202 DMA Master)
DMAResource_PreDMA(TrueIOArea_p->RingHandle,
WriteIndex * DescOffsetWordCount *
(unsigned int)sizeof(uint32_t),
nWritten * DescOffsetWordCount *
(unsigned int)sizeof(uint32_t));
// CDS point: hand over written Command Descriptors to the Device
EIP202_CDR_COUNT_WR(Device,
(uint16_t)(nWritten * DescOffsetWordCount),
false);
}
return (int) nWritten;
}
/*----------------------------------------------------------------------------
* EIP202_CDR_ReadCB
*/
int
EIP202_CDR_ReadCB(
void * const CallbackParam1_p,
const int CallbackParam2,
const unsigned int ReadIndex,
const unsigned int ReadLimit,
void * Descriptors_p,
const unsigned int DescriptorSkipCount)
{
IDENTIFIER_NOT_USED(CallbackParam1_p);
IDENTIFIER_NOT_USED(CallbackParam2);
IDENTIFIER_NOT_USED(ReadIndex);
IDENTIFIER_NOT_USED(ReadLimit);
IDENTIFIER_NOT_USED(Descriptors_p);
IDENTIFIER_NOT_USED(DescriptorSkipCount);
// Not used for CDR
return -1;
}
/*----------------------------------------------------------------------------
* EIP202_CDR_StatusCB
*/
int
EIP202_CDR_StatusCB(
void * const CallbackParam1_p,
const int CallbackParam2,
int * const DeviceReadPos_p)
{
IDENTIFIER_NOT_USED(CallbackParam1_p);
IDENTIFIER_NOT_USED(CallbackParam2);
*DeviceReadPos_p = -1; // not used
return 0;
}
/*----------------------------------------------------------------------------
Descriptor I/O Driver Library API implementation
---------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* EIP202_CDR_FillLevel_Get
*/
EIP202_Ring_Error_t
EIP202_CDR_FillLevel_Get(
EIP202_Ring_IOArea_t * const IOArea_p,
unsigned int * FillLevelDscrCount_p)
{
Device_Handle_t Device;
unsigned int CDWordCount;
volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
EIP202_RING_CHECK_POINTER(IOArea_p);
EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
Device = TrueIOArea_p->Device;
{
uint32_t Value32;
EIP202_CDR_COUNT_RD(Device, &Value32);
TrueIOArea_p->CountRD = Value32;
TrueIOArea_p->fValidCountRD = true;
CDWordCount = (unsigned int)Value32;
}
return EIP202Lib_CDR_FillLevel_Finalize(CDWordCount,
TrueIOArea_p,
FillLevelDscrCount_p);
}
/*----------------------------------------------------------------------------
* EIP202_CDR_Write_ControlWord
*/
uint32_t
EIP202_CDR_Write_ControlWord(
const EIP202_CDR_Control_t * const CommandCtrl_p)
{
return EIP202_CD_Make_ControlWord(CommandCtrl_p->TokenWordCount,
CommandCtrl_p->SegmentByteCount,
CommandCtrl_p->fFirstSegment,
CommandCtrl_p->fLastSegment,
CommandCtrl_p->fForceEngine,
CommandCtrl_p->EngineId);
}
/*----------------------------------------------------------------------------
* EIP202_CDR_Descriptor_Put
*
*/
EIP202_Ring_Error_t
EIP202_CDR_Descriptor_Put(
EIP202_Ring_IOArea_t * const IOArea_p,
const EIP202_ARM_CommandDescriptor_t * CommandDscr_p,
const unsigned int DscrRequestedCount,
unsigned int * const DscrDoneCount_p,
unsigned int * FillLevelDscrCount_p)
{
Device_Handle_t Device;
int res;
unsigned int CDWordCount, CDFreeCount, CDNewRequestedCount;
volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
EIP202_RING_CHECK_POINTER(IOArea_p);
EIP202_RING_CHECK_POINTER(CommandDscr_p);
EIP202_RING_CHECK_POINTER(DscrDoneCount_p);
EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
Device = TrueIOArea_p->Device;
// Check how many descriptors can be put
{
uint32_t Value32;
if (TrueIOArea_p->fValidCountRD)
{
Value32 = TrueIOArea_p->CountRD;
TrueIOArea_p->fValidCountRD = false;
}
else
{
EIP202_CDR_COUNT_RD(Device, &Value32);
TrueIOArea_p->CountRD = Value32;
}
CDWordCount = (unsigned int)Value32;
}
// Check if CDR is full
if(CDWordCount == (unsigned int)TrueIOArea_p->RingSizeWordCount)
{
// CD Ring is full
*FillLevelDscrCount_p = CDWordCount /
(unsigned int)TrueIOArea_p->DescOffsWordCount;
*DscrDoneCount_p = 0;
return EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
EIP202_CDR_STATE_FULL);
}
CDFreeCount =
((unsigned int)TrueIOArea_p->RingSizeWordCount - CDWordCount) /
(unsigned int)TrueIOArea_p->DescOffsWordCount;
CDNewRequestedCount = MIN(CDFreeCount, DscrRequestedCount);
// Put command descriptors to CDR
res = RingHelper_Put((volatile RingHelper_t*)&TrueIOArea_p->RingHelper,
CommandDscr_p,
(int)CDNewRequestedCount);
if(res >= 0)
*DscrDoneCount_p = (unsigned int)res;
else
return EIP202_RING_ARGUMENT_ERROR;
// Increase the fill level by the number of successfully put descriptors
CDWordCount += ((unsigned int)res *
(unsigned int)TrueIOArea_p->DescOffsWordCount);
return EIP202Lib_CDR_FillLevel_Finalize(CDWordCount,
TrueIOArea_p,
FillLevelDscrCount_p);
}
/* end of file eip202_cdr_dscr.c */