diff -r 000000000000 -r c40eb8fe8501 wlan_bearer/wlanldd/wlan_symbian/wlanldd_symbian/src/WlanLogicalChannel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wlan_bearer/wlanldd/wlan_symbian/wlanldd_symbian/src/WlanLogicalChannel.cpp Tue Feb 02 02:03:13 2010 +0200 @@ -0,0 +1,2946 @@ +/* +* Copyright (c) 2005-2009 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 DWlanLogicalChannel class. +* +*/ + +/* +* %version: 56 % +*/ + +#include "WlLddWlanLddConfig.h" +#include "wlanlddcommon.h" +#include "WlanLogicalChannel.h" +#include "EthernetFrameMemMngr.h" +#include "EtherCardIoc.h" +#include "RWlanLogicalChannel.h" +#include "Umac.h" +#include "wllddoidmsgstorage.h" +#include "WlanLogicalDevice.h" +#include "osachunk.h" + +#ifdef RD_WLAN_DDK +#include "osa.h" +#include "wlanpddiface.h" +#endif + +extern TAny* os_alloc( const TUint32 ); +extern void os_free( const TAny* ); + +// Tx memory for frames created by UMAC +const TUint32 KDmaTxMemSize = 4096; // equals to 1 MMU page on most systems + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +#ifndef RD_WLAN_DDK +DWlanLogicalChannel::DWlanLogicalChannel( + DWlanLogicalDevice& aParent, + Umac& aUmac, + TDynamicDfcQue& aDfcQ, + DMutex& aMutex, + DChunk*& aSharedMemoryChunk, + WlanChunk*& aRxFrameMemoryPool ) +#else +DWlanLogicalChannel::DWlanLogicalChannel( + DWlanLogicalDevice& aParent, + Umac& aUmac, + TDynamicDfcQue& aDfcQ, + WlanOsa*& aOsa, + DChunk*& aSharedMemoryChunk, + WlanChunk*& aRxFrameMemoryPool ) +#endif + : + iClient( NULL ), + iUnit( KUnitMax ), + iUmac( aUmac ), + iDfcQ ( &aDfcQ ), + iParent( aParent ), + iWlanGeneralRequestStatus( NULL ), + iWlanRequestNotifyStatus( NULL ), + iWlanReceiveFrameStatus( NULL ), + iWlanSendFrameStatus( NULL ), + iIndicationBuffer( NULL ), + iIndicationListHead( NULL ), + iFreeIndicationListHead( NULL ), + iResumeTxStatus( NULL ), + iEthernetReceiveFrameStatus( NULL ), + iEthernetFrameMemMngr( NULL ), + iTimerDfc( TimerDfcDoToggle, this, 0 ), + iTimer( OnTimeOut, this ), + iVoiceCallEntryTimer( OnVoiceCallEntryTimerTimeOut, this ), + iVoiceCallEntryTimerDfc( VoiceCallEntryTimerDfcDoToggle, this, 0 ), + iNullTimer( OnNullTimerTimeOut, this ), + iNullTimerDfc( NullTimerDfcDoToggle, this, 0 ), + iNoVoiceTimer( OnNoVoiceTimerTimeOut, this ), + iNoVoiceTimerDfc( NoVoiceTimerDfcDoToggle, this, 0 ), + iKeepAliveTimer( OnKeepAliveTimerTimeOut, this ), + iKeepAliveTimerDfc( KeepAliveTimerDfcDoToggle, this, 0 ), + iActiveToLightPsTimer( OnActiveToLightPsTimerTimeOut, this ), + iActiveToLightPsTimerDfc( ActiveToLightPsTimerDfcDoToggle, this, 0 ), + iLightPsToActiveTimer( OnLightPsToActiveTimerTimeOut, this ), + iLightPsToActiveTimerDfc( LightPsToActiveTimerDfcDoToggle, this, 0 ), + iLightPsToDeepPsTimer( OnLightPsToDeepPsTimerTimeOut, this ), + iLightPsToDeepPsTimerDfc( LightPsToDeepPsTimerDfcDoToggle, this, 0 ), + iDfc( DfcDoToggle, this, 0 ), + iTxTriggerDfc( TxTriggerDfcDoToggle, this, 0 ), + iFlags( 0 ), + iPowerHandler( *this, aDfcQ ), + iPoweringDown( EFalse ), + iDfcCtx( NULL ), +#ifndef RD_WLAN_DDK + iMutex( aMutex ), +#else + iOsa( aOsa ), +#endif + iSharedMemoryChunk( aSharedMemoryChunk ), + iRxFrameMemoryPool( aRxFrameMemoryPool ), + iTxActive( EFalse ), + iAddTxFrameAllowed( ETrue ) + { + TraceDump(INIT_LEVEL, (("WLANLDD: DWlanLogicalChannel Ctor: 0x%08x"), this)); + + iTimerDfc.SetDfcQ( iDfcQ ); + iVoiceCallEntryTimerDfc.SetDfcQ( iDfcQ ); + iNullTimerDfc.SetDfcQ( iDfcQ ); + iNoVoiceTimerDfc.SetDfcQ( iDfcQ ); + iKeepAliveTimerDfc.SetDfcQ( iDfcQ ); + iActiveToLightPsTimerDfc.SetDfcQ( iDfcQ ); + iLightPsToActiveTimerDfc.SetDfcQ( iDfcQ ); + iLightPsToDeepPsTimerDfc.SetDfcQ( iDfcQ ); + iDfc.SetDfcQ( iDfcQ ); + iTxTriggerDfc.SetDfcQ( iDfcQ ); + + // store client thread ID + iClient = &Kern::CurrentThread(); + + TraceDump(INIT_LEVEL, (("WLANLDD: current thread 0x%08x"), iClient)); + + // open a refernce to client thread, so we don't get out of scope + ((DObject*)iClient)->Open(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +DWlanLogicalChannel::~DWlanLogicalChannel() + { + TraceDump(INIT_LEVEL, (("WLANLDD: DWlanLogicalChannel Dtor: 0x%08x"), this)); + + if ( iUnit == KUnitWlan ) + { + iTimerDfc.Cancel(); + iVoiceCallEntryTimerDfc.Cancel(); + iNullTimerDfc.Cancel(); + iNoVoiceTimerDfc.Cancel(); + iKeepAliveTimerDfc.Cancel(); + iActiveToLightPsTimerDfc.Cancel(); + iLightPsToActiveTimerDfc.Cancel(); + iLightPsToDeepPsTimerDfc.Cancel(); + iDfc.Cancel(); + + // if there are any indication items currently pending, free them by + // moving them to the free list + PurgeIndicationList(); + // delete all indication items from the free list + FreeIndicationList(); + // detach management side callback + TraceDump(INIT_LEVEL, ("WLANLDD: detach managemement side callback from UMAC")); + iUmac.Detach(); + + if ( iFlags & KPowerHandlerRegistered ) + { + // we have registered our power handler + + // if we stopping operations because of a power down request from power + // manager, acknowledge back to power manager that we are now done + if ( iPoweringDown ) + { + TraceDump(INIT_LEVEL, + (("WLANLDD: DWlanLogicalChannel::~DWlanLogicalChannel(): signalling powerDownDone"))); + iPowerHandler.OnPowerDownDone(); + } + + // de-register our power handler from the power manager + TraceDump(INIT_LEVEL, + (("WLANLDD: DWlanLogicalChannel::~DWlanLogicalChannel(): de-register our powerhandler"))); + iPowerHandler.Remove(); + + // destroy UMAC internal Tx memory buffer + iDmaTxMemory.Finit(); + } + } + else if ( iUnit == KUnitEthernet ) + { + iTxTriggerDfc.Cancel(); + + // detach protocol stack side callback + TraceDump(INIT_LEVEL, + ("WLANLDD: detach protocol stack side callback from UMAC")); + iUmac.DetachProtocolStackSideUmacCb(); + } + + if ( iEthernetFrameMemMngr ) + { + TraceDump(INIT_LEVEL, ("WLANLDD: deallocate ethernet frame memory pool")); + TraceDump(MEMORY, (("WLANLDD: delete DEthernetFrameMemMngr: 0x%08x"), + reinterpret_cast(iEthernetFrameMemMngr))); + + delete iEthernetFrameMemMngr; + iEthernetFrameMemMngr = NULL; + } + + iDfcQ = NULL; // destroyed elsewhere (by the owner) + + // close our refernce to client thread as the very last thing we do + Kern::SafeClose( reinterpret_cast(iClient), NULL); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +DChunk*& DWlanLogicalChannel::SharedMemoryChunk() + { + return iSharedMemoryChunk; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::SetRxBufAlignmentPadding( + TInt aRxBufAlignmentPadding ) + { + iParent.SetRxBufAlignmentPadding( aRxBufAlignmentPadding ); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TInt DWlanLogicalChannel::RxBufAlignmentPadding() const + { + return iParent.RxBufAlignmentPadding(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool DWlanLogicalChannel::InitIndicationListEntries() + { + // Initialize indication list entries + TBool ret( ETrue ); // true for success + + for ( TUint32 i = 0 ; i < KMaxIndicationListEntries; ++i ) + { + TIndicationListEntry* tmp = new TIndicationListEntry; + + if ( tmp ) + { + TraceDump(MEMORY, (("WLANLDD: new TIndicationListEntry: 0x%08x"), + reinterpret_cast(tmp))); + + // The ReleaseIndicationListEntry + // function can also be used for initialization + ReleaseIndicationListEntry( tmp ); + } + else + { + // alloc failed no use to continue + ret = EFalse; + break; + } + } + + return ret; + } + +// --------------------------------------------------------------------------- +// If an error occurs in this method, we set iPdd to NULL to prevent +// PDD object destruction in base class (DLogicalChannelBase) destructor. +// DLogicalChannelBase destructor gets called as this logical channel instance +// gets destoyed when this method returns with an error. +// The PDD object gets destructed elsewhere. +// --------------------------------------------------------------------------- +// +TInt DWlanLogicalChannel::DoCreate( + TInt aUnit, + const TDesC8* /*aInfo*/, + const TVersion& /*aVer*/ ) + { + TraceDump(INIT_LEVEL, ("WLANLDD: DWlanLogicalChannel::DoCreate")); + TraceDump(INIT_LEVEL, + (("WLANLDD: current thread 0x%08x"), &Kern::CurrentThread())); + TraceDump(INIT_LEVEL, (("WLANLDD: aUnit %d"), aUnit)); + + if ( !Kern::CurrentThreadHasCapability( + ECapabilityCommDD, + __PLATSEC_DIAGNOSTIC_STRING( "Checked by wlan.ldd"))) + { + iPdd = NULL; + return KErrPermissionDenied; + } + + // enable reception of requests from user mode + SetDfcQ(iDfcQ); + iMsgQ.Receive(); + + // length of the allocation unit to be used for OSA interconnect + // (DMA capable) memory and frame Rx/Tx buffers. + // If WLAN DDK is used and the WLAN PDD capabilities query below + // returns a non-NULL response and the PDD indicates support for + // cached memory, we use the length of the processor's cache line + // - returned in that response - as the allocation unit length. + // Otherwise we use this default value + TInt allocationUnit ( 32 ); + + iUnit = aUnit; // store the unit + + // PDD has been loaded and created by the framework at this point + + if ( iUnit == KUnitWlan ) + { + if ( !InitIndicationListEntries() ) + { + iPdd = NULL; + return KErrNoMemory; + } + + // attach management side callback + TraceDump(INIT_LEVEL, ("WLANLDD: attach managemement side callback to UMAC")); + iUmac.Attach( *this ); + +#ifndef RD_WLAN_DDK + WHA::Wha* wha( reinterpret_cast(iPdd) ); + // attach the WHA object to UMAC + TraceDump(INIT_LEVEL, ("WLANLDD: attach WHA object to UMAC")); + iUmac.AttachWsa( wha ); +#else + + MWlanPddIface* pdd( reinterpret_cast(iPdd) ); + + TraceDump(INIT_LEVEL, + (("WLANLDD: DWlanLogicalChannel::DoCreate: wlanpdd addr: 0x%08x"), + pdd)); + + // determine PDD capabilities + + MWlanPddIface::SCapabilities* pddCapabilities ( NULL ); + + pdd->GetCapabilities( pddCapabilities ); + + TraceDump(INIT_LEVEL, + (("WLANLDD: DWlanLogicalChannel::DoCreate: pddCapabilities ptr: 0x%08x"), + reinterpret_cast(pddCapabilities))); + + if ( pddCapabilities ) + { + TraceDump(INIT_LEVEL, + (("WLANLDD: DWlanLogicalChannel::DoCreate: wlanpdd iCapabilities: 0x%08x"), + pddCapabilities->iCapabilities)); + + if ( pddCapabilities->iCapabilities & + MWlanPddIface::SCapabilities::KCachedMemory ) + { + TraceDump(INIT_LEVEL, + ("WLANLDD: DWlanLogicalChannel::DoCreate: use cached memory")); + + iParent.UseCachedMemory( ETrue ); + + TraceDump(INIT_LEVEL, + (("WLANLDD: DWlanLogicalChannel::DoCreate: wlanpdd iCacheLineLength: %d"), + pddCapabilities->iCacheLineLength)); + + allocationUnit = pddCapabilities->iCacheLineLength; + } + delete pddCapabilities; + pddCapabilities = NULL; + } + + // initialize OSA + if ( !iOsa->Initialize( + iParent.UseCachedMemory(), + allocationUnit, + iDfcQ ) ) + { + // init failed. We cannot continue + + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::DoCreate: osa init failed, abort")); + + iPdd = NULL; + return KErrGeneral; + } + + TraceDump(INIT_LEVEL, + ("WLANLDD: DWlanLogicalChannel::DoCreate: attach osa and osaext to wlanpdd")); + TraceDump(INIT_LEVEL, + (("WLANLDD: DWlanLogicalChannel::DoCreate: osa and osaext addr: 0x%08x"), + reinterpret_cast(iOsa))); + + // pass interfaces to PDD + const TBool ret( pdd->Attach( *iOsa, *iOsa ) ); + if ( ret ) + { + TraceDump(INIT_LEVEL, + ("WLANLDD: DWlanLogicalChannel::DoCreate: extract WHA and attach it to UMAC")); + // extract wha and attach it to UMAC + iUmac.AttachWsa( &(pdd->Extract()) ); + } + else + { + // attach failure abort + TraceDump(WARNING_LEVEL, ("WLANLDD: PDD attach failure -> abort")); + iPdd = NULL; + return KErrNoMemory; + } +#endif + +#ifndef RD_WLAN_DDK + // pass the mutex to WHA + wha->Mutex( reinterpret_cast(&iMutex) ); +#endif + + // register our power handler with the power manager + TraceDump(INIT_LEVEL, + (("WLANLDD: DWlanLogicalChannel::DoCreate: register our powerhandler"))); + iPowerHandler.Add(); + iFlags |= KPowerHandlerRegistered; // note that we have registered + + // create UMAC internal Tx memory buffer + if ( iDmaTxMemory.Init( KDmaTxMemSize, iParent.UseCachedMemory() ) + == KDmaTxMemSize ) + { + // success; no further action needed + } + else + { + // failure + iPdd = NULL; + return KErrNoMemory; + } + } + else if ( iUnit == KUnitEthernet ) + { + // attach protocol stack side callbac + iUmac.AttachProtocolStackSideUmacCb( *this ); + } + else + { + // unknown unit + + TraceDump(ERROR_LEVEL, + (("WLANLDD: DWlanLogicalChannel::DoCreate: ERROR: unknown unit: %d"), + iUnit)); + iPdd = NULL; + return KErrPermissionDenied; + } + + // init ethernet frame memory pool manager + iEthernetFrameMemMngr = DEthernetFrameMemMngr::Init( + aUnit, + *this, + iRxFrameMemoryPool, + iParent.UseCachedMemory(), + allocationUnit ); + + if ( iEthernetFrameMemMngr ) + { + // init success -> continue + TraceDump(INIT_LEVEL, (("WLANLDD: ethernet memory pool allocated: 0x%08x"), + iEthernetFrameMemMngr)); + } + else + { + // init failure no use to continue + TraceDump(WARNING_LEVEL, + ("WLANLDD: ethernet memory pool allocation failure")); + + iPdd = NULL; + return KErrNoMemory; + } + + return KErrNone; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::HandleMsg(TMessageBase* aMsg) + { + TraceDump(WLM_CMD, ("WLANLDD: DWlanLogicalChannel::HandleMsg")); + + // we are now executing in a DFC thread context + // acquire mutex +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::HandleMsg: mutex acquired"))); + + TThreadMessage& m = *reinterpret_cast( aMsg ); + + TraceDump(WLM_CMD_DETAILS, (("WLANLDD: current thread 0x%08x"), + &Kern::CurrentThread())); + TraceDump(WLM_CMD_DETAILS, (("WLANLDD: client thread 0x%08x"), m.Client())); + TraceDump(WLM_CMD_DETAILS, (("WLANLDD: channel creator thread 0x%08x"), + iClient)); + + // Get message type + TInt id = m.iValue; + + TraceDump(WLM_CMD_DETAILS, (("WLANLDD: message id: %d"), id)); + + // Decode the message type and dispatch it to the relevent handler function... + + // A logical channel can be closed either explicitly by its user-side client, + // or implicitly if the client thread dies. In the latter case, the channel + // is closed in the context of the kernel supervisor thread. + if ( id == ECloseMsg ) + { + TraceDump(WLM_CMD_DETAILS, ("WLANLDD: close message")); + + if( m.Client() == iClient ) + { + // channel closed by client + + // trick to disable PDD object dealloc + // as this logical channel gets destoyed after this + // and iPdd is deallocated in DLogicalChannelBase + iPdd = NULL; + } + + // release mutex + // Note that in this case we release the mutex before completing the + // client message. Reason: When SMP is used, doing these actions in + // the reverse order could, in principle, lead to a situation where + // the channel instance has already been destroyed (by another thread) + // when the mutex is tried to be released. + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::HandleMsg: mutex released"))); + + m.Complete( KErrNone, EFalse ); + + return; + } + + // For all other message types, we check that the message is from the thread + // that created us. + if ( m.Client() != iClient ) + { + TraceDump(SERIOUS_LEVEL, (("WLANLDD: ERROR: requesting thread: 0x%08x"), + m.Client())); + TraceDump(SERIOUS_LEVEL, ("WLANLDD: ERROR: request from wrong thread")); + + m.Complete( KErrPermissionDenied, ETrue ); + } + else if ( id == KMaxTInt ) + { + TraceDump(WLM_CMD_DETAILS, ("WLANLDD: DoCancel")); + + // DoCancel + DoCancel( m.Int0() ); + m.Complete( KErrNone,ETrue ); + } + else if ( id < 0 ) + { + TraceDump(WLM_CMD_DETAILS, ("WLANLDD: DoRequest")); + + // DoRequest + TRequestStatus* req_status = reinterpret_cast( m.Ptr0() ); + const TInt r = DoRequest( ~id, req_status, m.Ptr1(), m.Ptr2() ); + if ( r != KErrNone) + { + // this branch means that an error of somekind has occurred + // we complete the request synchronously + Kern::RequestComplete( m.Client(), req_status, r ); + } + + m.Complete( KErrNone, ETrue ); + } + else + { + TraceDump(WLM_CMD_DETAILS, ("WLANLDD: DoControl")); + + // DoControl + const TInt r = DoControl( id, m.Ptr0(), m.Ptr1() ); + m.Complete( r, ETrue ); + } + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::HandleMsg: mutex released"))); + } + + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TAny* DWlanLogicalChannel::DoControlFast( TInt aFunction, TAny* param ) + { + TAny* ret( NULL ); + TBool triggerTx ( EFalse ); + + TraceDump(WLM_CMD_DETAILS, + (("WLANLDD: DWlanLogicalChannel::DoControlFast: current thread 0x%08x"), + &Kern::CurrentThread())); + TraceDump(WLM_CMD_DETAILS, (("WLANLDD: channel creator thread: 0x%08x"), + iClient)); + TraceDump(WLM_CMD_DETAILS, (("WLANLDD: function: 0x%x"), aFunction)); + + // Note! We are executing in the context of the client's thread, but + // in supervisor mode + + // acquire mutex +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::DoControlFast: mutex acquired"))); + + switch ( aFunction ) + { + case RPcmNetCardIf::EControlFastAllocTxBuffer: + ret = iEthernetFrameMemMngr->AllocTxBuffer( + reinterpret_cast(param) ); + + if ( !ret && iAddTxFrameAllowed ) + { + iAddTxFrameAllowed = EFalse; + + TraceDump( NWSA_TX, + ("WLANLDD: DWlanLogicalChannel::DoControlFast: stop flow from protocol stack") ); + } + break; + + case RPcmNetCardIf::EControlFastAddTxFrame: + { +#ifndef NDEBUG + if ( !iAddTxFrameAllowed ) + { + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::DoControlFast: WARNING: AddTxFrame req. when flow ctrl is on")); + } +#endif + if ( iEthernetFrameMemMngr->AllTxQueuesEmpty() ) + { + triggerTx = ETrue; + } + + TDataBuffer* discardFrame ( NULL ); + + ret = reinterpret_cast(iEthernetFrameMemMngr->AddTxFrame( + reinterpret_cast(param), + discardFrame, + iUmac.UserDataTxEnabled() )); + + if ( discardFrame ) + { + TraceDump( NWSA_TX_DETAILS, + (("WLANLDD: DWlanLogicalChannel::DoControlFast: have to drop tx frame of UP: %d"), + reinterpret_cast(param)->UserPriority()) ); + + iEthernetFrameMemMngr->FreeTxPacket( discardFrame ); + } + + if ( !ret ) + { + iAddTxFrameAllowed = EFalse; + + TraceDump( NWSA_TX, + ("WLANLDD: DWlanLogicalChannel::DoControlFast: stop flow from protocol stack") ); + } + break; + } + default: +#ifndef NDEBUG + TraceDump(ERROR_LEVEL, (("WLANLDD: unknown request: %d"), + aFunction)); + os_assert( + (TUint8*)("WLANLDD: panic"), + (TUint8*)(WLAN_FILE), + __LINE__ ); +#endif + break; + } + + // release mutex +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + ("WLANLDD: DWlanLogicalChannel::DoControlFast: mutex released")); + + if ( triggerTx ) + { + // Trigger a new Tx - via a DFC. + // Note that we do this outside of mutex protection, as this block of + // code is executed by a lower priority (user side) thread, and the + // DFC by a higher priority (kernel side) thread, and the latter will + // also need to acquire the same mutex before it can proceed. So, as + // the lower priority thread will get paused and the higher priority + // thread will get scheduled (to execute the DFC), we don't want the + // higher priority thread to need to wait for the mutex. So we + // released the mutex first in this code block and after that enque + // the DFC request. + if ( !( iFlags & KTxTriggerArmed ) ) + { + iFlags |= KTxTriggerArmed; + iTxTriggerDfc.Enque(); + } + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::DoCancel( TInt aMask ) + { + if ( iUnit == KUnitWlan ) + { + if ( aMask & ( 1 << EWlanRequestNotify ) ) + { + TraceDump(INFO_LEVEL, + ("WLANLDD: DWlanLogicalChannel::DoCancel: mgmt side notify cancel")); + + CancelIndicationRequest(); + Kern::RequestComplete( + iClient, iWlanRequestNotifyStatus, KErrServerTerminated ); + iWlanRequestNotifyStatus = NULL; + } + else if ( aMask & ( 1 << EWlanRequestFrame ) ) + { + TraceDump(INFO_LEVEL, + ("WLANLDD: DWlanLogicalChannel::DoCancel: mgmt side frame read cancel")); + + Kern::RequestComplete( + iClient, iWlanReceiveFrameStatus, KErrServerTerminated ); + iWlanReceiveFrameStatus = NULL; + } + else + { + TraceDump(ERROR_LEVEL, + (("WLANLDD: DWlanLogicalChannel::DoCancel: mgmt side unhandled mask panic: 0x%08x"), + aMask)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + } + else if ( iUnit == KUnitEthernet ) + { + if ( aMask & ( 1 << RPcmNetCardIf::EControlResumeTxCancel ) ) + { + TraceDump(INFO_LEVEL, + ("WLANLDD: DWlanLogicalChannel::DoCancel: user side resume Tx cancel")); + + Kern::RequestComplete( + iClient, iResumeTxStatus, KErrServerTerminated ); + iResumeTxStatus = NULL; + } + else if ( aMask & ( 1 << RPcmNetCardIf::EControlReadCancel ) ) + { + TraceDump(INFO_LEVEL, + ("WLANLDD: DWlanLogicalChannel::DoCancel: user side frame read cancel")); + + Kern::RequestComplete( + iClient, iEthernetReceiveFrameStatus, KErrServerTerminated ); + iEthernetReceiveFrameStatus = NULL; + } + else + { + TraceDump(ERROR_LEVEL, + (("WLANLDD: DWlanLogicalChannel::DoCancel: user side unhandled mask panic: 0x%08x"), + aMask)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + } + else + { + TraceDump(ERROR_LEVEL, (("WLANLDD: DoCancel unknown unit panic: %d"), + iUnit)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool DWlanLogicalChannel::ProtocolStackDataReceiveComplete( + const TDataBuffer*& aBufferStart, + TUint32 aNumOfBuffers ) + { + if ( iEthernetFrameMemMngr->OnEthernetFrameRxComplete( aBufferStart, + aNumOfBuffers ) ) + { + Kern::RequestComplete( iClient, iEthernetReceiveFrameStatus, KErrNone ); + iEthernetReceiveFrameStatus = NULL; + } + + return ETrue; // indicate always successful processing + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TBool DWlanLogicalChannel::ProtocolStackSideClientReady() const + { + TBool status ( EFalse ); + + if ( iEthernetFrameMemMngr && iEthernetFrameMemMngr->IsMemInUse() ) + { + status = ETrue; + } + + return status; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::UserDataReEnabled() + { + if ( !( iFlags & KTxTriggerArmed ) ) + { + iFlags |= KTxTriggerArmed; + iTxTriggerDfc.Enque(); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TUint8* DWlanLogicalChannel::DmaPrivateTxMemory() + { + return reinterpret_cast(iDmaTxMemory.Addr()); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::SetProtocolStackTxOffset( + TUint32 aEthernetFrameTxOffset ) + { + const TUint32 KNotRelevant ( 0 ); + + if ( iEthernetFrameMemMngr ) + { + TraceDump(NWSA_TX_DETAILS, + (("WLANLDD: DWlanLogicalChannel::SetProtocolStackTxOffset: aEthernetFrameTxOffset: %d"), + aEthernetFrameTxOffset )); + + iEthernetFrameMemMngr->SetTxOffsets( + aEthernetFrameTxOffset, + KNotRelevant, + KNotRelevant ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnTxProtocolStackDataComplete( + TInt aCompletionCode, + TDataBuffer* aMetaHeader ) + { + TraceDump(UMAC_PROTO_CALLBACK, + ("WLANLDD: DWlanLogicalChannel::OnTxProtocolStackDataComplete")); + TraceDump(UMAC_PROTO_CALLBACK, + (("WLANLDD: aCompletionCode: %d"), aCompletionCode)); + + iEthernetFrameMemMngr->FreeTxPacket( aMetaHeader ); + + TxProtocolStackData(); + + if ( !iAddTxFrameAllowed ) + { + if ( iResumeTxStatus && + iEthernetFrameMemMngr->ResumeClientTx( + iUmac.UserDataTxEnabled() ) ) + { + // resume Tx flow from protocol stack + + TraceDump(NWSA_TX_DETAILS, + ("WLANLDD: DWlanLogicalChannel::OnTxProtocolStackDataComplete: complete client Tx resume req")); + + // complete the pending request to user mode + Kern::RequestComplete( + iClient, iResumeTxStatus, aCompletionCode ); + // mark request as non-pending + iResumeTxStatus = NULL; + + iAddTxFrameAllowed = ETrue; + } + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnOtherTxDataComplete() + { + TraceDump(UMAC_PROTO_CALLBACK, + ("WLANLDD: DWlanLogicalChannel::OnOtherTxDataComplete")); + + // We try to submit Protocol Stack side frames also when this event occurs + // a) to speed up new Tx submission in the case that a frame submitted by + // someone else than the Protocol Stack Side Client unblocks the WHA Tx + // pipeline and + // b) to avoid the Tx pipe from getting stuck even temporarily + if ( !( iFlags & KTxTriggerArmed ) ) + { + iFlags |= KTxTriggerArmed; + iTxTriggerDfc.Enque(); // we do this via a DFC + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnTxDataSent() + { + TraceDump(UMAC_PROTO_CALLBACK, + ("WLANLDD: DWlanLogicalChannel::OnTxDataSent")); + + // We try to submit Protocol Stack side frames also when this event occurs + // a) to speed up new Tx submission in the case that a frame, submitted by + // someone else than the Protocol Stack Side Client, gets transmitted & + // makes a WHA Txqueue - for which there are packets pending in our Tx + // queues - non-full + // b) to avoid the Tx pipe from getting stuck even temporarily + if ( !( iFlags & KTxTriggerArmed ) ) + { + iFlags |= KTxTriggerArmed; + iTxTriggerDfc.Enque(); // we do this via a DFC + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::TxManagementData() + { + TDataBuffer* buffer = iEthernetFrameMemMngr->OnWriteEthernetFrame(); + + if ( !buffer ) + { + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::TxManagementData: " + "panic, no buffer")); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + else + { + iUmac.WriteMgmtFrame( *buffer ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::TxProtocolStackData() + { +#ifndef NDEBUG + TUint packetsSubmitted ( 0 ); +#endif + + if ( !iTxActive ) + { + TWhaTxQueueState txQueueState; + TBool morePackets ( EFalse ); + iTxActive = ETrue; + + while ( iUmac.TxPermitted( txQueueState ) ) + { + TDataBuffer* metaHeader = + iEthernetFrameMemMngr->GetTxFrame( txQueueState, morePackets ); + + if ( metaHeader ) + { + TraceDump( NWSA_TX_DETAILS, + (("WLANLDD: DWlanLogicalChannel::TxProtocolStackData: submitting packet %d"), + ++packetsSubmitted) ); + + iUmac.TxProtocolStackData( + *metaHeader, + morePackets ); + } + else + { + TraceDump(NWSA_TX_DETAILS, + ("WLANLDD: DWlanLogicalChannel::TxProtocolStackData: no packet that could be submitted")); + + break; + } + } + + iTxActive = EFalse; + } + + TraceDump( NWSA_TX_DETAILS, + (("WLANLDD: DWlanLogicalChannel::TxProtocolStackData: %d packet(s) submitted"), + packetsSubmitted) ); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool DWlanLogicalChannel::OnReadEthernetFrameRequest() + { + const TBool ret = iEthernetFrameMemMngr->OnReadRequest(); + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TInt DWlanLogicalChannel::OnEthernetSideRequest( + TInt aReqNo, + TRequestStatus* aStatus, + TAny* /*a1*/, + TAny* /*a2*/ ) + { + const TInt ret( KErrNone ); + + switch (aReqNo) + { + case RPcmNetCardIf::ERequestRead: + // Read request + if ( OnReadEthernetFrameRequest() ) + { + // rx data to be completed exists + // complete it directly + Kern::RequestComplete( + iClient, + aStatus, + KErrNone ); + } + else + { + // no rx data for completion exists + // store the pending request + iEthernetReceiveFrameStatus = aStatus; + } + break; + case RPcmNetCardIf::EResumeTx: + // request to get notified once Tx can again be resumed + iResumeTxStatus = aStatus; + break; + default: + // unknown request + + TraceDump(ERROR_LEVEL, + ("WLANLDD: unknown protocol stack request")); + TraceDump(ERROR_LEVEL, (("WLANLDD: request id: %d"), aReqNo)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + break; + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::FinitSystem() + { + TraceDump(INIT_LEVEL, ("WLANLDD * finit system")); + iUmac.FinitSystem(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::InitSystem( + TAny* aInputBuffer, + TUint aInputLength ) + { + // read the USER mode parameters to internal storage + TInt ret = Kern::ThreadRawRead( + iClient, + aInputBuffer, + &iOpenParam, + aInputLength ); + if ( ret != KErrNone ) + { + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::InitSystem(): ThreadRawRead panic")); + TraceDump(ERROR_LEVEL, (("WLANLDD: ret: %d"), ret)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + // backup pointers + const TAny* pda( iOpenParam.iPda ); + const TAny* fw( iOpenParam.iFirmWare ); + + // allocate kernel memory for the pda and firmware + iOpenParam.iPda = os_alloc( iOpenParam.iPdaLength ); + iOpenParam.iFirmWare = os_alloc( iOpenParam.iFirmWareLength ); + + if ( iOpenParam.iPda && iOpenParam.iFirmWare ) + { + // allocation success + // read the parameters to allocated storage + ret = Kern::ThreadRawRead( + iClient, + pda, + iOpenParam.iPda, + iOpenParam.iPdaLength ); + if ( ret != KErrNone ) + { + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::InitSystem(): ThreadRawRead panic")); + TraceDump(ERROR_LEVEL, (("WLANLDD: ret: %d"), ret)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + ret = Kern::ThreadRawRead( + iClient, + fw, + iOpenParam.iFirmWare, + iOpenParam.iFirmWareLength ); + if ( ret != KErrNone ) + { + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::InitSystem(): ThreadRawRead panic")); + TraceDump(ERROR_LEVEL, (("WLANLDD: ret: %d"), ret)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + // check this in completion method + iFlags |= KFreeOpenParamsMask; + + iUmac.BootUp( + static_cast(iOpenParam.iPda), + iOpenParam.iPdaLength, + static_cast(iOpenParam.iFirmWare), + iOpenParam.iFirmWareLength ); + } + else + { + // allocation failure + // make sure all is released + os_free( iOpenParam.iPda ); + os_free( iOpenParam.iFirmWare ); + + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::InitSystem: ERROR: PDA and/or firmware memory allocation failure")); + + // complete the pending request with error code to user mode + Kern::RequestComplete( + iClient, + iWlanGeneralRequestStatus, + KErrNoMemory ); + // mark request as non pending + iWlanGeneralRequestStatus = NULL; + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool DWlanLogicalChannel::HandlePointerParameters() + { + TraceDump(WLM_CMD_DETAILS, + (("WLANLDD: DWlanLogicalChannel::HandlePointerParameters"))); + + if ( !HandleScanResponseFrameBodyCase() ) + { + // memory allocation failure + + return EFalse; + } + + if ( !CheckAndHandleIeDataCase() ) + { + // memory allocation failure + + // free memory allocated in the previous step + FreeScanResponseFramebody(); + + return EFalse; + } + + return ETrue; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool DWlanLogicalChannel::HandleScanResponseFrameBodyCase() + { + TBool ret( ETrue ); + + // handle scan response frame body case + if ( (reinterpret_cast + (&iOidMsgStorage))->oid_id == E802_11_CONNECT ) + { + if ( iOidMsgStorage.iOidMsgs.iConnectMsg.scanResponseFrameBody ) + { + // scan response frame body exists + // we must allocate kernel storage for it here + + TraceDump(WLM_CMD_DETAILS, + (("WLANLDD: DWlanLogicalChannel::HandleScanResponseFrameBodyCase: allocate memory & copy data; length: %d"), + iOidMsgStorage.iOidMsgs + .iConnectMsg.scanResponseFrameBodyLength )); + + const TUint8* user_mode_address( + iOidMsgStorage.iOidMsgs.iConnectMsg.scanResponseFrameBody ); + + iOidMsgStorage.iOidMsgs.iConnectMsg.scanResponseFrameBody + = static_cast(os_alloc( + iOidMsgStorage.iOidMsgs + .iConnectMsg.scanResponseFrameBodyLength )); + + if ( iOidMsgStorage.iOidMsgs.iConnectMsg.scanResponseFrameBody ) + { + // allocation success + // read the parameters to the allocated storage + const TInt local( Kern::ThreadRawRead( + iClient, + user_mode_address, + const_cast(iOidMsgStorage.iOidMsgs + .iConnectMsg.scanResponseFrameBody), + iOidMsgStorage.iOidMsgs + .iConnectMsg.scanResponseFrameBodyLength ) ); + + if ( local != KErrNone ) + { + TraceDump(ERROR_LEVEL, + ("WLANLDD: ThreadRawRead panic")); + TraceDump(ERROR_LEVEL, (("WLANLDD: local: %d"), ret)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + // mark memory deallocation event + iFlags |= KFreeScanResponseFramebodyMask; + } + else + { + // allocation failure + ret = EFalse; + } + } + else // --- scan response frame body does not exist --- + { + // this is a usage error + + TraceDump(ERROR_LEVEL, + ("WLANLDD: scan response frame body is null in connect OID")); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + } + else // --- connect not issued --- + { + // do nothing + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool DWlanLogicalChannel::CheckAndHandleIeDataCase() + { + TBool ret( ETrue ); + + // handle Tx IE case + if ( (reinterpret_cast + (&iOidMsgStorage))->oid_id == E802_11_CONNECT ) + { + if ( iOidMsgStorage.iOidMsgs.iConnectMsg.ieData ) + { + // Tx IE exists + // we must allocate kernel storage for it here + + TraceDump(WLM_CMD_DETAILS, + (("WLANLDD: DWlanLogicalChannel::CheckAndHandleIeDataCase: allocate memory & copy data; length: %d"), + iOidMsgStorage.iOidMsgs.iConnectMsg.ieDataLength )); + + const TUint8* user_mode_address( + iOidMsgStorage.iOidMsgs.iConnectMsg.ieData ); + + iOidMsgStorage.iOidMsgs.iConnectMsg.ieData + = static_cast(os_alloc( + iOidMsgStorage.iOidMsgs.iConnectMsg.ieDataLength )); + + if ( iOidMsgStorage.iOidMsgs.iConnectMsg.ieData ) + { + // allocation success + // read the parameters to the allocated storage + const TInt local( Kern::ThreadRawRead( + iClient, + user_mode_address, + const_cast(iOidMsgStorage.iOidMsgs + .iConnectMsg.ieData), + iOidMsgStorage.iOidMsgs + .iConnectMsg.ieDataLength ) ); + + if ( local != KErrNone ) + { + TraceDump(ERROR_LEVEL, + ("WLANLDD: ThreadRawRead panic")); + TraceDump(ERROR_LEVEL, (("WLANLDD: local: %d"), ret)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + // mark memory deallocation event + iFlags |= KFreeIeDataMask; + } + else + { + // allocation failure + ret = EFalse; + } + } + else // --- RSN IE does not exists --- + { + // do nothing + } + } + else // --- connect not issued --- + { + // do nothing + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::FreeScanResponseFramebody() + { + if ( iFlags & KFreeScanResponseFramebodyMask ) + { + // free scan response frame + + TraceDump(WLM_CMD_DETAILS, + (("WLANLDD: DWlanLogicalChannel::FreeScanResponseFramebody: freeing memory"))); + + os_free( iOidMsgStorage.iOidMsgs.iConnectMsg.scanResponseFrameBody ); + iOidMsgStorage.iOidMsgs.iConnectMsg.scanResponseFrameBody = NULL; + iFlags &= ~KFreeScanResponseFramebodyMask; + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::FreeIeData() + { + if ( iFlags & KFreeIeDataMask ) + { + // free Tx IE + + TraceDump(WLM_CMD_DETAILS, + (("WLANLDD: DWlanLogicalChannel::FreeIeData: freeing memory"))); + + os_free( iOidMsgStorage.iOidMsgs.iConnectMsg.ieData ); + iOidMsgStorage.iOidMsgs.iConnectMsg.ieData = NULL; + iFlags &= ~KFreeIeDataMask; + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TInt DWlanLogicalChannel::OnMgmtSideDoRequest( + TInt aReqNo, + TRequestStatus* aStatus, + TAny* a1, + TAny* a2 ) + { + TraceDump(WLM_CMD, + (("WLANLDD: DWlanLogicalChannel::OnMgmtSideDoRequest(): request: %d"), + aReqNo)); + TraceDump(WLM_CMD_DETAILS, (("WLANLDD: a1 0x%08x"), a1)); + TraceDump(WLM_CMD_DETAILS, (("WLANLDD: a2 0x%08x"), a2)); + + TInt ret( KErrNone ); + + SOutputBuffer output_buffer = { NULL, 0 }; + if ( a2 ) + { + // read the USER mode output parameters to internal storage + ret = Kern::ThreadRawRead( + iClient, + a2, + &output_buffer, + sizeof(output_buffer) ); + if ( ret != KErrNone ) + { + TraceDump(ERROR_LEVEL, + ("WLANLDD: OnMgmtSideDoRequest(): ThreadRawRead panic")); + TraceDump(ERROR_LEVEL, (("WLANLDD: ret: %d"), ret)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + } + + switch ( aReqNo ) + { + case EWlanInitSystem: + // bootup the chip and the system + iWlanGeneralRequestStatus = aStatus; + InitSystem( a1, sizeof(TOpenParam) ); + break; + case EWlanFinitSystem: + // power down the chip and the system + iWlanGeneralRequestStatus = aStatus; + FinitSystem(); + break; + case EWlanCommand: + // management command + iWlanGeneralRequestStatus = aStatus; + + // read the USER mode parameters to internal storage + ret = Kern::ThreadRawRead( + iClient, + a1, + &iOidMsgStorage, + sizeof(iOidMsgStorage) ); + if ( ret != KErrNone ) + { + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::OnMgmtSideDoRequest(): ThreadRawRead panic")); + TraceDump(ERROR_LEVEL, (("WLANLDD: ret: %d"), ret)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + // read also parameters pointed to by pointers from USER mode to + // internal storage; when such parameters exist + if ( !HandlePointerParameters() ) + { + // memory allocation failure + // complete the pending request with error code to user mode + Kern::RequestComplete( + iClient, + iWlanGeneralRequestStatus, + KErrNoMemory ); + // mark request as non pending + iWlanGeneralRequestStatus = NULL; + break; + } + + iUmac.HandleOid( + reinterpret_cast(&iOidMsgStorage), + // we can pass output buffer pointer as is + // because it is not accessed by UMAC and the + // actual user mode writing is done by OnOidCompleted method + output_buffer.iData, + output_buffer.iLen ); + break; + case EWlanRequestNotify: + // store the USER mode indication address; + iIndicationBuffer = static_cast(a1); + iWlanRequestNotifyStatus = aStatus; + IndicationRequest( static_cast(a1) ); + break; + case EWlanRequestFrame: + if ( OnReadEthernetFrameRequest() ) + { + // rx data to be completed exists + // complete it directly + Kern::RequestComplete( + iClient, + aStatus, + KErrNone ); + } + else + { + // no rx data for completion exists + // store the pending request + iWlanReceiveFrameStatus = aStatus; + } + break; + case EWlanRequestSend: + iWlanSendFrameStatus = aStatus; + + TxManagementData(); + break; + default: + // unknown request + TraceDump(ERROR_LEVEL, + ("WLANLDD: unhandled management request panic")); + TraceDump(ERROR_LEVEL, (("WLANLDD: request id: %d"), aReqNo)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + break; + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TInt DWlanLogicalChannel::DoRequest( + TInt aReqNo, + TRequestStatus* aStatus, + TAny* a1, + TAny* a2 ) + { + TInt ret( KErrNone ); + if ( iUnit == KUnitWlan ) + { + ret = OnMgmtSideDoRequest( aReqNo, aStatus, a1, a2 ); + } + else if ( iUnit == KUnitEthernet ) + { + ret = OnEthernetSideRequest( aReqNo, aStatus, a1, a2 ); + } + else + { + // unknown unit + + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::DoRequest(): unknown request unit panic")); + TraceDump(ERROR_LEVEL, (("WLANLDD: request id: %d"), aReqNo)); + TraceDump(ERROR_LEVEL, (("WLANLDD: unit: %d"), iUnit)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TInt DWlanLogicalChannel::OnInitialiseEthernetFrameBuffers( + TSharedChunkInfo* aSharedChunkInfo ) + { + TInt ret( KErrNoMemory ); + + if ( iEthernetFrameMemMngr ) + { + TUint8 notRelevant( 0 ); + TUint8 vendorTxHdrLen ( 0 ); + TUint8 vendorTxTrailerLen ( 0 ); + + iUmac.GetFrameExtraSpaceForVendor( + notRelevant, + vendorTxHdrLen, + vendorTxTrailerLen ); + + ret = iEthernetFrameMemMngr->OnInitialiseMemory( + *iClient, + aSharedChunkInfo, + vendorTxHdrLen, + vendorTxTrailerLen ); + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnReleaseEthernetFrameBuffers() + { + if ( iEthernetFrameMemMngr ) + { + iEthernetFrameMemMngr->OnReleaseMemory(); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TInt DWlanLogicalChannel::OnEthernetSideControl( + TInt aFunction, + TAny* a1, + TAny* /*a2*/ ) + { + TInt ret(KErrNone); + + switch (aFunction) + { + case RPcmNetCardIf::EControlGetConfig: + { + const TMacAddress& mac = iUmac.StationId(); + TEtherConfig ethercfg = { NULL }; + + // 0x00 - card is ready, 0xff - card not ready. + ethercfg.iStatus = 0; + // Speed setting (0x00 to 0x03). + ethercfg.iEthSpeed = 0; + // Duplex setting (0x00 to 0x03) + ethercfg.iEthDuplex = 0; + + // set STA MAC + os_memcpy( ethercfg.iEthAddress, &mac, KMacAddressLength ); + + // write config to USER mode + ret = Kern::ThreadRawWrite( + iClient, + a1, + ðercfg, + sizeof(ethercfg) ); + 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__ ); + } + break; + } + case RPcmNetCardIf::ESvControlInitBuffers: + // instruct initiliaze buffers for data xfer + if ( a1 ) + { + // call + TraceDump(INIT_LEVEL, + ("WLANLDD * init protocol shared IO-buffer memory pool")); + + TraceDump(INIT_LEVEL, + (("WLANLDD: DWlanLogicalChannel::OnEthernetSideControl: chunk info addr: 0x%08x"), + a1)); + ret = OnInitialiseEthernetFrameBuffers( + static_cast(a1) ); + + // set frame Tx offset for protocol stack side + iUmac.SetTxOffset(); + } + else + { + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::OnEthernetSideControl(): init protocol stack buffer pool panic")); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + break; + case RPcmNetCardIf::ESvControlFreeBuffers: + { + // instruct free buffers for data xfer + OnReleaseEthernetFrameBuffers(); + break; + } + default: + // unhadled panic + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::OnEthernetSideControl(): protocol stack side control panic")); + TraceDump(ERROR_LEVEL, (("function id: %d"), aFunction)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + break; + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TInt DWlanLogicalChannel::OnMgmtSideControl( + TInt aFunction, + TAny* a1, + TAny* /*a2*/ ) + { + TInt ret( KErrNone ); + if ( aFunction == EWlanSvControlInitBuffers ) + { + // initiliaze buffers for wlan mgmt client data xfer + if ( a1 ) + { + TraceDump(INIT_LEVEL, + ("WLANLDD: DWlanLogicalChannel::OnMgmtSideControl(): init management client shared IO-buffer memory pool")); + + TraceDump(INIT_LEVEL, + (("WLANLDD: DWlanLogicalChannel::OnMgmtSideControl: chunk info addr: 0x%08x"), + a1)); + ret = OnInitialiseEthernetFrameBuffers( + static_cast(a1) ); + } + else + { + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::OnMgmtSideControl(): init management client buffer pool panic")); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + } + else if ( aFunction == EWlanSvControlFreeBuffers ) + { + // free wlan mgmt client data xfer buffers + OnReleaseEthernetFrameBuffers(); + } + else + { + // unknown request + + TraceDump(ERROR_LEVEL, + ("WLANLDD: DWlanLogicalChannel::OnMgmtSideControl(): management side control panic")); + TraceDump(ERROR_LEVEL, (("WLANLDD: function id: %d"), aFunction)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TInt DWlanLogicalChannel::DoControl( TInt aFunction, TAny* a1, TAny* a2) + { + TInt ret( KErrNone ); + if ( iUnit == KUnitWlan ) + { + ret = OnMgmtSideControl( aFunction, a1, a2 ); + } + else if ( iUnit == KUnitEthernet ) + { + ret = OnEthernetSideControl( aFunction, a1, a2 ); + } + else + { + // unknown unit + + TraceDump(ERROR_LEVEL, ("WLANLDD: unhandled control unit panic")); + TraceDump(ERROR_LEVEL, (("WLANLDD: function id: %d"), aFunction)); + TraceDump(ERROR_LEVEL, (("WLANLDD: unit: %d"), iUnit)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnOidCompleted( + TInt aReason, + SOidOutputData& OidOutputData ) + { + if ( iFlags & KFreeOpenParamsMask ) + { + // free open params + os_free( iOpenParam.iPda ); + iOpenParam.iPda = NULL; + os_free( iOpenParam.iFirmWare ); + iOpenParam.iFirmWare = NULL; + iFlags &= ~KFreeOpenParamsMask; + } + else + { + // check if there are other command parameter related memory blocks + // to be released + // Note! We check the flags already here to avoid unnecessary + // FreeXXX function calls + + if ( iFlags & KFreeScanResponseFramebodyMask ) + { + // free scan response frame body + FreeScanResponseFramebody(); + + // the following flags can be set only at the same time with + // KFreeScanResponseFramebodyMask + + if ( iFlags & KFreeIeDataMask ) + { + // free IE(s) + FreeIeData(); + } + } + } + + TraceDump(UMAC_MGMT_CALLBACK, + ("WLANLDD: DWlanLogicalChannel::OnOidCompleted()")); + TraceDump(UMAC_MGMT_CALLBACK, (("WLANLDD: OID: 0x%08x"), + OidOutputData.iOidId)); + TraceDump(UMAC_MGMT_CALLBACK, (("WLANLDD: aReason: %d"), aReason)); + + if ( iWlanGeneralRequestStatus ) + { + // write data to user mode if this happened to be a read request + if ( OidOutputData.iOidData ) + { + TraceDump(UMAC_MGMT_CALLBACK, ("WLANLDD: write data to USER mode")); + TraceDump(UMAC_MGMT_CALLBACK, (("WLANLDD: length: %d"), + OidOutputData.iLengthOfDataInBytes)); + + const TInt ret + = Kern::ThreadRawWrite( + iClient, + OidOutputData.iBufferSupplied, + OidOutputData.iOidData, + OidOutputData.iLengthOfDataInBytes ); + + 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__ ); + } + } + + // complete the pending request to user mode + Kern::RequestComplete( iClient, iWlanGeneralRequestStatus, aReason ); + // mark request as non pending + iWlanGeneralRequestStatus = NULL; + } + else // iReqStatus + { + // no pending request exists, so it must have been cancelled + // Nothing more to do here + TraceDump(UMAC_MGMT_CALLBACK, + ("WLANLDD: DWlanLogicalChannel::OnOidCompleted(): no pending request")); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::SetMgmtSideTxOffsets( + TUint32 aEthernetFrameTxOffset, + TUint32 aDot11FrameTxOffset, + TUint32 aSnapFrameTxOffset ) + { + if ( iEthernetFrameMemMngr ) + { + TraceDump(NWSA_TX_DETAILS, + (("WLANLDD: DWlanLogicalChannel::SetMgmtSideTxOffsets: aEthernetFrameTxOffset: %d"), + aEthernetFrameTxOffset )); + TraceDump(NWSA_TX_DETAILS, + (("WLANLDD: DWlanLogicalChannel::SetMgmtSideTxOffsets: aDot11FrameTxOffset: %d"), + aDot11FrameTxOffset )); + TraceDump(NWSA_TX_DETAILS, + (("WLANLDD: DWlanLogicalChannel::SetMgmtSideTxOffsets: aSnapFrameTxOffset: %d"), + aSnapFrameTxOffset )); + + iEthernetFrameMemMngr->SetTxOffsets( + aEthernetFrameTxOffset, + aDot11FrameTxOffset, + aSnapFrameTxOffset ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TUint8* DWlanLogicalChannel::GetBufferForRxData( + TUint aLengthinBytes ) + { + TUint8* ret ( NULL ); + if ( iEthernetFrameMemMngr ) + { + ret = iEthernetFrameMemMngr->OnGetEthernetFrameRxBuffer( + aLengthinBytes ); + } + else + { + TraceDump(RX_FRAME | WARNING_LEVEL, + ("WLANLDD: DWlanLogicalChannel::GetBufferForRxData: WARNING: no frame mgr => failed")); + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::MgmtDataReceiveComplete( + const TDataBuffer*& aBufferStart, + TUint32 aNumOfBuffers ) + { + if ( iEthernetFrameMemMngr->OnEthernetFrameRxComplete( + aBufferStart, + aNumOfBuffers ) ) + { + Kern::RequestComplete( iClient, iWlanReceiveFrameStatus, KErrNone ); + iWlanReceiveFrameStatus = NULL; + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::MgmtPathWriteComplete( TInt aErr ) + { + TraceDump(UMAC_MGMT_CALLBACK, + ("WLANLDD: DWlanLogicalChannel::MgmtPathWriteComplete()")); + TraceDump(UMAC_MGMT_CALLBACK, + (("WLANLDD: aCompletionCode: %d"), aErr)); + + if ( iWlanSendFrameStatus ) + { + // complete the pending request to user mode + Kern::RequestComplete( + iClient, iWlanSendFrameStatus, aErr ); + // mark request as non pending + iWlanSendFrameStatus = NULL; + } + else // iReqStatus + { + // no pending request exists, so it must have been cancelled + // Nothing to do here + TraceDump(UMAC_MGMT_CALLBACK, + ("WLANLDD: DWlanLogicalChannel::MgmtPathWriteComplete(): no pending request")); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +DWlanLogicalChannel::TIndicationListEntry* +DWlanLogicalChannel::GetFreeIndicationListEntry() + { + TIndicationListEntry* newEntry = NULL; + + if ( iFreeIndicationListHead ) + { + newEntry = iFreeIndicationListHead; + iFreeIndicationListHead = newEntry->next; + newEntry->next = NULL; + } + + return newEntry; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::StoreIndication( TIndication aIndication ) + { + TIndicationListEntry* newEntry = GetFreeIndicationListEntry(); + + if ( !newEntry ) + { + return; + } + + newEntry->indication = aIndication; + newEntry->next = NULL; + + if ( !iIndicationListHead ) + { + iIndicationListHead = newEntry; + } + else + { + TIndicationListEntry *tmp = iIndicationListHead; + + while ( tmp->next ) + { + tmp = tmp->next; + } + + tmp->next = newEntry; + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::IndicationComplete() + { + Kern::RequestComplete( + iClient, iWlanRequestNotifyStatus, KErrNone ); + iWlanRequestNotifyStatus = NULL; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool DWlanLogicalChannel::GetStoredIndication() + { + TIndicationListEntry *tmp = NULL; + + if ( !iIndicationListHead ) + { + return EFalse; + } + + TraceDump(WLM_INDICATION, + (("WLANLDD: DWlanLogicalChannel::GetStoredIndication(): indication complete: %d"), + iIndicationListHead->indication)); + + const TInt ret = Kern::ThreadRawWrite( iClient, iIndicationBuffer, + &( iIndicationListHead->indication ), + sizeof(iIndicationListHead->indication) ); + + 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__ ); + } + + tmp = iIndicationListHead; + iIndicationListHead = tmp->next; + + ReleaseIndicationListEntry( tmp ); + + return ETrue; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::TryToCompleteIndicationRequest() + { + if ( iIndicationBuffer ) + { + if ( GetStoredIndication() ) + { + IndicationComplete(); + iIndicationBuffer = NULL; + } + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnInDicationEvent( TIndication aIndication ) + { + StoreIndication( aIndication ); + TryToCompleteIndicationRequest(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::FreeIndicationList() + { + // Free the indication list entries + TIndicationListEntry *iter = iFreeIndicationListHead; + TIndicationListEntry *next = NULL; + + while ( iter ) + { + next = iter->next; + + TraceDump(MEMORY, (("WLANLDD: delete TIndicationListEntry: 0x%08x"), + reinterpret_cast(iter))); + + delete iter; + + iter = next; + } + + iFreeIndicationListHead = NULL; + iIndicationListHead = NULL; + iIndicationBuffer = NULL; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::CancelIndicationRequest() + { + iIndicationBuffer = NULL; + PurgeIndicationList(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::PurgeIndicationList() + { + TIndicationListEntry* iter = iIndicationListHead; + TIndicationListEntry* next = NULL; + + while ( iter ) + { + next = iter->next; + + ReleaseIndicationListEntry( iter ); + + iter = next; + } + + iIndicationListHead = NULL; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::IndicationRequest( TIndication* aBuffer ) + { + iIndicationBuffer = aBuffer; + TryToCompleteIndicationRequest(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::ReleaseIndicationListEntry( + TIndicationListEntry* aEntry ) + { + aEntry->next = NULL; + + if ( !iFreeIndicationListHead ) + { + iFreeIndicationListHead = aEntry; + } + else + { + TIndicationListEntry* tmp = iFreeIndicationListHead; + + while ( tmp->next ) + { + tmp = tmp->next; + } + + tmp->next = aEntry; + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::MarkRxBufFree( TUint8* aBufferToFree ) + { + if ( iEthernetFrameMemMngr ) + { + iEthernetFrameMemMngr->DoMarkRxBufFree( aBufferToFree ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RealTimerDfc() + { + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealTimerDfc(): mutex acquired"))); + + iUmac.OnTimeout( EWlanDefaultTimer ); + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealTimerDfc(): mutex released"))); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::TimerDfcDoToggle( TAny* aPtr ) + { + DWlanLogicalChannel* ptr = static_cast(aPtr); + ptr->RealTimerDfc(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RealDfc() + { + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealDfc: mutex acquired"))); + + if ( !(iFlags & KDfcCancelledMask) ) + { + iUmac.OnDfc( iDfcCtx ); + } + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealDfc: mutex released"))); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::DfcDoToggle( TAny* aPtr ) + { + DWlanLogicalChannel* ptr( static_cast(aPtr) ); + ptr->RealDfc(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnTimeOut( TAny *aPtr ) + { + DWlanLogicalChannel* p = static_cast(aPtr); + + // queue to a DFC for completion + p->iTimerDfc.Add(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RealVoiceCallEntryTimerDfc() + { + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealVoiceCallEntryTimerDfc(): mutex acquired"))); + + iUmac.OnTimeout( EWlanVoiceCallEntryTimer ); + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealVoiceCallEntryTimerDfc(): mutex released"))); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::VoiceCallEntryTimerDfcDoToggle( TAny* aPtr ) + { + DWlanLogicalChannel* ptr = static_cast(aPtr); + ptr->RealVoiceCallEntryTimerDfc(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnVoiceCallEntryTimerTimeOut( TAny *aPtr ) + { + DWlanLogicalChannel* p = static_cast(aPtr); + + // queue to a DFC for completion + p->iVoiceCallEntryTimerDfc.Add(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RealNullTimerDfc() + { + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealNullTimerDfc(): mutex acquired"))); + + iUmac.OnTimeout( EWlanNullTimer ); + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealNullTimerDfc(): mutex released"))); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::NullTimerDfcDoToggle( TAny* aPtr ) + { + DWlanLogicalChannel* ptr = static_cast(aPtr); + ptr->RealNullTimerDfc(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnNullTimerTimeOut( TAny *aPtr ) + { + DWlanLogicalChannel* p = static_cast(aPtr); + + // queue to a DFC for completion + p->iNullTimerDfc.Add(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RealNoVoiceTimerDfc() + { + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealNoVoiceTimerDfc: mutex acquired"))); + + iUmac.OnTimeout( EWlanNoVoiceTimer ); + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealNoVoiceTimerDfc: mutex released"))); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::NoVoiceTimerDfcDoToggle( TAny* aPtr ) + { + DWlanLogicalChannel* ptr = static_cast(aPtr); + ptr->RealNoVoiceTimerDfc(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnNoVoiceTimerTimeOut( TAny *aPtr ) + { + DWlanLogicalChannel* p = static_cast(aPtr); + + // queue to a DFC for completion + p->iNoVoiceTimerDfc.Add(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RealKeepAliveTimerDfc() + { + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealKeepAliveTimerDfc: mutex acquired"))); + + iUmac.OnTimeout( EWlanKeepAliveTimer ); + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealKeepAliveTimerDfc: mutex released"))); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::KeepAliveTimerDfcDoToggle( TAny* aPtr ) + { + DWlanLogicalChannel* ptr = static_cast(aPtr); + ptr->RealKeepAliveTimerDfc(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnKeepAliveTimerTimeOut( TAny *aPtr ) + { + DWlanLogicalChannel* p = static_cast(aPtr); + + // queue to a DFC for completion + p->iKeepAliveTimerDfc.Add(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RealActiveToLightPsTimerDfc() + { + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealActiveToLightPsTimerDfc: mutex acquired"))); + + iUmac.OnTimeout( EWlanActiveToLightPsTimer ); + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealActiveToLightPsTimerDfc: mutex released"))); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::ActiveToLightPsTimerDfcDoToggle( TAny* aPtr ) + { + DWlanLogicalChannel* ptr = static_cast(aPtr); + ptr->RealActiveToLightPsTimerDfc(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnActiveToLightPsTimerTimeOut( TAny *aPtr ) + { + DWlanLogicalChannel* p = static_cast(aPtr); + + // queue to a DFC for completion + p->iActiveToLightPsTimerDfc.Add(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RealLightPsToActiveTimerDfc() + { + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealLightPsToActiveTimerDfc: mutex acquired"))); + + iUmac.OnTimeout( EWlanLightPsToActiveTimer ); + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealLightPsToActiveTimerDfc: mutex released"))); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::LightPsToActiveTimerDfcDoToggle( TAny* aPtr ) + { + DWlanLogicalChannel* ptr = static_cast(aPtr); + ptr->RealLightPsToActiveTimerDfc(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnLightPsToActiveTimerTimeOut( TAny *aPtr ) + { + DWlanLogicalChannel* p = static_cast(aPtr); + + // queue to a DFC for completion + p->iLightPsToActiveTimerDfc.Add(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RealLightPsToDeepPsTimerDfc() + { + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealLightPsToDeepPsTimerDfc: mutex acquired"))); + + iUmac.OnTimeout( EWlanLightPsToDeepPsTimer ); + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::RealLightPsToDeepPsTimerDfc: mutex released"))); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::LightPsToDeepPsTimerDfcDoToggle( TAny* aPtr ) + { + DWlanLogicalChannel* ptr = static_cast(aPtr); + ptr->RealLightPsToDeepPsTimerDfc(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnLightPsToDeepPsTimerTimeOut( TAny *aPtr ) + { + DWlanLogicalChannel* p = static_cast(aPtr); + + // queue to a DFC for completion + p->iLightPsToDeepPsTimerDfc.Add(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RegisterTimeout( + TUint32 aTimeoutInMicroSeconds, + TWlanTimer aTimer ) + { + TraceDump(INFO_LEVEL, + (("WLANLDD: DWlanLogicalChannel::RegisterTimeout: timer: %d"), + aTimer)); + TraceDump(INFO_LEVEL, + (("WLANLDD: DWlanLogicalChannel::RegisterTimeout: aTimeoutInMicroSeconds: %d"), + aTimeoutInMicroSeconds)); + + const TInt KThousand = 1000; + + switch ( aTimer ) + { + case EWlanDefaultTimer: + iTimer.OneShot( + // convert timeout 1st to milliseconds & then to NKern ticks + NKern::TimerTicks( aTimeoutInMicroSeconds / KThousand ), + // request completion in ISR context + EFalse ); + break; + case EWlanVoiceCallEntryTimer: + iVoiceCallEntryTimer.OneShot( + // convert timeout 1st to milliseconds & then to NKern ticks + NKern::TimerTicks( aTimeoutInMicroSeconds / KThousand ), + // request completion in ISR context + EFalse ); + break; + case EWlanNullTimer: + iNullTimer.OneShot( + // convert timeout 1st to milliseconds & then to NKern ticks + NKern::TimerTicks( aTimeoutInMicroSeconds / KThousand ), + // request completion in ISR context + EFalse ); + break; + case EWlanNoVoiceTimer: + iNoVoiceTimer.OneShot( + // convert timeout 1st to milliseconds & then to NKern ticks + NKern::TimerTicks( aTimeoutInMicroSeconds / KThousand ), + // request completion in ISR context + EFalse ); + break; + case EWlanKeepAliveTimer: + iKeepAliveTimer.OneShot( + // convert timeout 1st to milliseconds & then to NKern ticks + NKern::TimerTicks( aTimeoutInMicroSeconds / KThousand ), + // request completion in ISR context + EFalse ); + break; + case EWlanActiveToLightPsTimer: + iActiveToLightPsTimer.OneShot( + // convert timeout 1st to milliseconds & then to NKern ticks + NKern::TimerTicks( aTimeoutInMicroSeconds / KThousand ), + // request completion in ISR context + EFalse ); + break; + case EWlanLightPsToActiveTimer: + iLightPsToActiveTimer.OneShot( + // convert timeout 1st to milliseconds & then to NKern ticks + NKern::TimerTicks( aTimeoutInMicroSeconds / KThousand ), + // request completion in ISR context + EFalse ); + break; + case EWlanLightPsToDeepPsTimer: + iLightPsToDeepPsTimer.OneShot( + // convert timeout 1st to milliseconds & then to NKern ticks + NKern::TimerTicks( aTimeoutInMicroSeconds / KThousand ), + // request completion in ISR context + EFalse ); + break; + default: + TraceDump(ERROR_LEVEL, + (("WLANLDD: DWlanLogicalChannel::RegisterTimeout: panic, unknown timer: %d"), + aTimer)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::CancelTimeout( TWlanTimer aTimer ) + { + TraceDump(INFO_LEVEL, + (("WLANLDD: DWlanLogicalChannel::CancelTimeout: timer: %d"), + aTimer)); + + switch ( aTimer ) + { + case EWlanDefaultTimer: + iTimer.Cancel(); + iTimerDfc.Cancel(); + break; + case EWlanVoiceCallEntryTimer: + iVoiceCallEntryTimer.Cancel(); + iVoiceCallEntryTimerDfc.Cancel(); + break; + case EWlanNullTimer: + iNullTimer.Cancel(); + iNullTimerDfc.Cancel(); + break; + case EWlanNoVoiceTimer: + iNoVoiceTimer.Cancel(); + iNoVoiceTimerDfc.Cancel(); + break; + case EWlanKeepAliveTimer: + iKeepAliveTimer.Cancel(); + iKeepAliveTimerDfc.Cancel(); + break; + case EWlanActiveToLightPsTimer: + iActiveToLightPsTimer.Cancel(); + iActiveToLightPsTimerDfc.Cancel(); + break; + case EWlanLightPsToActiveTimer: + iLightPsToActiveTimer.Cancel(); + iLightPsToActiveTimerDfc.Cancel(); + break; + case EWlanLightPsToDeepPsTimer: + iLightPsToDeepPsTimer.Cancel(); + iLightPsToDeepPsTimerDfc.Cancel(); + break; + default: + TraceDump(ERROR_LEVEL, + (("WLANLDD: DWlanLogicalChannel::CancelTimeout: panic, unknown timer: %d"), + aTimer)); + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RegisterDfc( TAny* aCntx ) + { + iFlags &= ~KDfcCancelledMask; + iDfcCtx = aCntx; + iDfc.Enque(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::CancelDfc() + { + iFlags |= KDfcCancelledMask; + iDfc.Cancel(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::RealTxTriggerDfc() + { + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + ("WLANLDD: DWlanLogicalChannel::RealTxTriggerDfc: mutex acquired")); + + iFlags &= ~KTxTriggerArmed; + TxProtocolStackData(); + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + ("WLANLDD: DWlanLogicalChannel::RealTxTriggerDfc: mutex released")); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::TxTriggerDfcDoToggle( TAny* aPtr ) + { + DWlanLogicalChannel* ptr( static_cast(aPtr) ); + ptr->RealTxTriggerDfc(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TDataBuffer* DWlanLogicalChannel::GetRxFrameMetaHeader() + { + TDataBuffer* metaHdr ( NULL ); + if ( iEthernetFrameMemMngr ) + { + metaHdr = iEthernetFrameMemMngr->GetRxFrameMetaHeader(); + } + else + { + TraceDump(RX_FRAME | WARNING_LEVEL, + ("WLANLDD: DWlanLogicalChannel::GetRxFrameMetaHeader: WARNING: no frame mgr => failed")); + } + + return metaHdr; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::FreeRxFrameMetaHeader( TDataBuffer* aMetaHeader ) + { + if ( iEthernetFrameMemMngr ) + { + iEthernetFrameMemMngr->FreeRxFrameMetaHeader( aMetaHeader ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnPowerUp() + { + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::OnPowerUp: mutex acquired"))); + + // No real action in this case; so just inform that we are done + iPowerHandler.OnPowerUpDone(); + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::OnPowerUp: mutex released"))); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void DWlanLogicalChannel::OnPowerDown() + { + TraceDump(INIT_LEVEL, + (("WLANLDD: DWlanLogicalChannel::OnPowerDown"))); + + iPoweringDown = ETrue; + + // acquire mutex + +#ifndef RD_WLAN_DDK + Kern::MutexWait( iMutex ); +#else + iOsa->MutexAcquire(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::OnPowerDown: mutex acquired"))); + + // Trigger power down indication to wlanengine + iUmac.OnInDicationEvent( EOsPowerStandby ); + + // release mutex + +#ifndef RD_WLAN_DDK + Kern::MutexSignal( iMutex ); +#else + iOsa->MutexRelease(); +#endif + + TraceDump(MUTEX, + (("WLANLDD: DWlanLogicalChannel::OnPowerDown: mutex released"))); + }