/*
* Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Implementation of the DEthernetFrameMemMngr class.
*
*/
/*
* %version: 24 %
*/
#include "WlLddWlanLddConfig.h"
#include "DataFrameMemMngr.h"
#include "MgmtFrameMemMngr.h"
#include "osachunk.h"
#include <kernel.h>
#include <kern_priv.h>
#include "EtherCardApi.h"
extern void os_free( const TAny* );
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
DEthernetFrameMemMngr* DEthernetFrameMemMngr::Init(
TInt aUnit,
DWlanLogicalChannel& aParent,
WlanChunk*& aRxFrameMemoryPool,
TBool aUseCachedMemory,
TInt aFrameBufAllocationUnit )
{
DEthernetFrameMemMngr* ret = NULL;
if ( aUnit == KUnitEthernet )
{
ret = new DataFrameMemMngr(
aParent,
aRxFrameMemoryPool,
aFrameBufAllocationUnit );
}
else if ( aUnit == KUnitWlan )
{
ret = new MgmtFrameMemMngr(
aParent,
aRxFrameMemoryPool,
aUseCachedMemory,
aFrameBufAllocationUnit );
}
else
{
TraceDump(ERROR_LEVEL,
(("WLANLDD: DEthernetFrameMemMngr::Init: ERROR: unknown unit: %d"),
aUnit));
// No action. NULL is returned
}
if ( ret )
{
TraceDump(MEMORY, (("WLANLDD: new FrameMemMngr: 0x%08x"),
reinterpret_cast<TUint32>(ret)));
}
return ret;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt DEthernetFrameMemMngr::OnInitialiseMemory(
DThread& aThread,
TSharedChunkInfo* aSharedChunkInfo,
TUint aVendorTxHdrLen,
TUint aVendorTxTrailerLen )
{
TraceDump( INIT_LEVEL,
(("WLANLDD: DEthernetFrameMemMngr::OnInitialiseMemory: aVendorTxHdrLen: %d"),
aVendorTxHdrLen ) );
TraceDump( INIT_LEVEL,
(("WLANLDD: aVendorTxTrailerLen: %d"),
aVendorTxTrailerLen ) );
TInt ret( KErrGeneral );
iVendorTxHdrLen = aVendorTxHdrLen;
iVendorTxTrailerLen = aVendorTxTrailerLen;
// Local info structure we will fill in
TSharedChunkInfo info;
if( !IsMemInUse() )
{
ret = DoAllocate( iParent.SharedMemoryChunk() );
if ( ret == KErrNone )
{
ret = DoOpenHandle( aThread, info, iParent.SharedMemoryChunk() );
if ( ret == KErrNone )
{
MarkMemInUSe(); // mark as in use
ret = KErrNone;
}
else
{
// handle creation & open failed
TraceDump( INIT_LEVEL,
(("WLANLDD: DEthernetFrameMemMngr::OnInitialiseMemory: Handle create & open error: status: %d"),
ret ) );
// zero contents of info structure.
// (Zero is usually a safe value to return on error for most data types,
// and for object handles this is same as KNullHandle)
memclr( &info, sizeof( info ) );
// need to enter critical section for chunk closing
NKern::ThreadEnterCS();
// schedule the shared memory chunk for destruction
Kern::ChunkClose( iParent.SharedMemoryChunk() );
// leave critical section
NKern::ThreadLeaveCS();
}
// write handle info to client memory
ret = Kern::ThreadRawWrite(
&aThread,
aSharedChunkInfo,
&info,
sizeof( info ) );
if ( ret != KErrNone )
{
TraceDump(ERROR_LEVEL, ("WLANLDD: ThreadRawWrite panic"));
TraceDump(ERROR_LEVEL, (("WLANLDD: ret: %d"), ret));
os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
}
}
else
{
// allocation failed; error code will be returned
}
}
else
{
ret = KErrAlreadyExists;
}
return ret;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
DEthernetFrameMemMngr::~DEthernetFrameMemMngr()
{
MarkMemFree();
iFrameXferBlock = NULL;
iTxDataBuffer = NULL;
iRxDataChunk = NULL;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TDataBuffer* DEthernetFrameMemMngr::OnWriteEthernetFrame() const
{
if ( iTxDataBuffer->GetLength() >= sizeof( SEthernetHeader ) )
{
return iTxDataBuffer;
}
else
{
os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
return NULL;
}
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TBool DEthernetFrameMemMngr::OnReadRequest()
{
TBool ret( EFalse );
if ( IsMemInUse() )
{
if ( iCountCompleted )
{
// free relevant buffers
DoFreeRxBuffers();
iCountCompleted = 0; // no buffers anymore in process in user mode
// make sure that the same buffers are not tried to be
// freed again thru the incremental freeing method
iFrameXferBlock->KeAllUserSideRxBuffersFreed();
}
if ( iCountTobeCompleted )
{
// there are Rx buffers to be completed
iFrameXferBlock->KeRxComplete( DoGetTobeCompletedBuffersStart(),
iCountTobeCompleted );
// mark the completed buffers
assign( DoGetTobeCompletedBuffersStart(),
DoGetCompletedBuffersStart(),
iCountTobeCompleted );
iCountCompleted = iCountTobeCompleted;
iCountTobeCompleted = 0;
ret = ETrue;
// the frame Rx request won't be pending as the callee shall
// complete it
iReadStatus = ENotPending;
}
else
{
// there are no Rx buffers to be completed. The Rx request is
// left pending
iReadStatus = EPending;
}
}
else
{
os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
}
return ret;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void DEthernetFrameMemMngr::DoMarkRxBufFree( TUint8* /*aBufferToFree*/ )
{
// not supported in default handler
os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void DEthernetFrameMemMngr::SetTxOffsets(
TUint32 aEthernetFrameTxOffset,
TUint32 aDot11FrameTxOffset,
TUint32 aSnapFrameTxOffset )
{
if ( IsMemInUse() )
{
iFrameXferBlock->KeSetTxOffsets(
aEthernetFrameTxOffset,
aDot11FrameTxOffset,
aSnapFrameTxOffset );
}
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TUint8* DEthernetFrameMemMngr::OnGetEthernetFrameRxBuffer(
TUint aLengthinBytes )
{
TUint8* buffer ( NULL );
if ( IsMemInUse() )
{
buffer = DoGetNextFreeRxBuffer( aLengthinBytes );
}
else
{
// we are trying to acquire an Rx buffer but our user mode client
// has not asked for the memorybuffer pool to be initialized. In this
// case NULL is returned, as no buffers are available
TraceDump(RX_FRAME,
("WLANLDD: DEthernetFrameMemMngr::OnGetEthernetFrameRxBuffer: not initialized => failed"));
}
return buffer;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TDataBuffer* DEthernetFrameMemMngr::GetRxFrameMetaHeader()
{
TDataBuffer* buffer ( NULL );
if ( IsMemInUse() )
{
buffer = reinterpret_cast<TDataBuffer*>(
iRxFrameMemoryPool->Alloc( sizeof( TDataBuffer ), ETrue ) );
TraceDump(RX_FRAME,
(("WLANLDD: DEthernetFrameMemMngr::GetRxFrameMetaHeader: addr: 0x%08x"),
reinterpret_cast<TUint32>(buffer)) );
}
else
{
// we are trying to acquire memory for Rx frame meta header but our
// user mode client has not asked for the memorybuffer pool to be
// initialized. In this case NULL is returned, as no memory is
// available
TraceDump(RX_FRAME,
("WLANLDD: DEthernetFrameMemMngr::GetRxFrameMetaHeader: not initialized => failed"));
}
return buffer;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void DEthernetFrameMemMngr::FreeRxFrameMetaHeader( TDataBuffer* aMetaHeader )
{
if ( IsMemInUse() )
{
iRxFrameMemoryPool->Free( aMetaHeader );
}
else
{
// the whole Rx memory pool - including aMetaHeader - has already
// been deallocated, so nothing is done in this case
TraceDump( RX_FRAME,
("WLANLDD: MgmtFrameMemMngr::FreeRxFrameMetaHeader: Rx memory pool already deallocated; no action needed") );
}
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TBool DEthernetFrameMemMngr::OnEthernetFrameRxComplete(
const TDataBuffer*& aBufferStart,
TUint32 aNumOfBuffers )
{
TBool ret( EFalse );
if ( IsMemInUse() &&
DoEthernetFrameRxComplete( aBufferStart, aNumOfBuffers ) )
{
iReadStatus = ENotPending;
ret = ETrue;
}
return ret;
}
// ---------------------------------------------------------------------------
// this default implementation always returns KErrNone
// ---------------------------------------------------------------------------
//
TInt DEthernetFrameMemMngr::DoAllocate( DChunk*& /*aSharedMemoryChunk*/ )
{
TraceDump( INIT_LEVEL,
("WLANLDD: DEthernetFrameMemMngr::DoAllocate") );
return KErrNone;
}
// ---------------------------------------------------------------------------
// this default implementation always returns NULL
// ---------------------------------------------------------------------------
//
TUint8* DEthernetFrameMemMngr::DoGetNextFreeRxBuffer(
TUint /*aLengthinBytes*/ )
{
TraceDump( RX_FRAME,
("WLANLDD: DEthernetFrameMemMngr::DoGetNextFreeRxBuffer") );
return NULL;
}
// ---------------------------------------------------------------------------
// This default implementation always returns NULL
// ---------------------------------------------------------------------------
//
TDataBuffer* DEthernetFrameMemMngr::AllocTxBuffer( TUint aLength )
{
return NULL;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TBool DEthernetFrameMemMngr::AddTxFrame(
TDataBuffer* aPacketInUserSpace,
TDataBuffer*& aPacketInKernSpace,
TBool aUserDataTxEnabled )
{
if ( IsMemInUse() )
{
return (static_cast<RFrameXferBlockProtocolStack*>(
iFrameXferBlock))->AddTxFrame(
aPacketInUserSpace,
aPacketInKernSpace,
aUserDataTxEnabled );
}
else
{
return EFalse;
}
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TDataBuffer* DEthernetFrameMemMngr::GetTxFrame(
const TWhaTxQueueState& aTxQueueState,
TBool& aMore )
{
if ( IsMemInUse() && iFrameXferBlock )
{
return (static_cast<RFrameXferBlockProtocolStack*>(
iFrameXferBlock))->GetTxFrame( aTxQueueState, aMore );
}
else
{
return NULL;
}
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void DEthernetFrameMemMngr::FreeTxPacket( TDataBuffer*& /*aPacket*/ )
{
// not suported in this default implementation
os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TBool DEthernetFrameMemMngr::ResumeClientTx( TBool aUserDataTxEnabled ) const
{
return (static_cast<RFrameXferBlockProtocolStack*>(
iFrameXferBlock))->ResumeClientTx( aUserDataTxEnabled );
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TBool DEthernetFrameMemMngr::AllTxQueuesEmpty() const
{
return (static_cast<RFrameXferBlockProtocolStack*>(
iFrameXferBlock))->AllTxQueuesEmpty();
}