kernel/eka/drivers/pbus/pbusmedia.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 14 5d2844f35677
child 19 4a8fed1c0ef6
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 1998-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:
// e32\drivers\pbus\pbusmedia.cpp
// 
//

#include <drivers/pbusmedia.h>
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "locmedia_ost.h"
#ifdef __VC32__
#pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
#endif
#include "pbusmediaTraces.h"
#endif

void mediaCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2)
	{
	OstTraceFunctionEntry0( MEDIACALLBACK_ENTRY );
	DPBusPrimaryMedia* pM=(DPBusPrimaryMedia*)aPtr;
	__KTRACE_OPT(KLOCDRV,Kern::Printf("mediaCallBack media %d, reason %d, a1=0x%x, a2=0x%x",pM->iMediaId,aReason,a1,a2));
	OstTraceExt4( TRACE_INTERNALS, MEDIACALLBACK, "aPtr=0x%x; aReason=%d; a1=0x%x; a2=0x%x", ( TUint )( aPtr ), aReason, ( TUint )( a1 ), ( TUint )( a2 ) );
	
	switch (aReason)
		{
		case TPBusCallBack::EPBusStateChange:
			pM->PBusStateChange((TInt)a1,(TInt)a2);
			break;
		}
	OstTraceFunctionExit0( MEDIACALLBACK_EXIT );
	}

/**
  Constructor for DPBusPrimaryMedia. Initializes the iSocket with aSocket.
  @param aSocket	Pointer to DPBusSocket object
  @see DPBusPrimaryMedia::iSocket
  */

DPBusPrimaryMedia::DPBusPrimaryMedia(DPBusSocket* aSocket)
	:	iSocket(aSocket)
	{
	OstTraceFunctionEntryExt( DPBUSPRIMARYMEDIA_DPBUSPRIMARYMEDIA_ENTRY, this );
	}
/**
  This function install a media call back for a removable media device.
  @param aDevice	Local media ID.
  @param aMediaId	Media Id (unique for a media subsystem)
  @param aLastMediaId	This indicates number of used media ids+ number of DMedia objects to be associated with the media driver
  @return KErrNone if successful,
          otherwise one of the other system wide error codes.
  @see DPrimaryMediaBase::Create()
  */
TInt DPBusPrimaryMedia::Create(TMediaDevice aDevice, TInt aMediaId, TInt aLastMediaId)
	{
	OstTraceExt4(TRACE_FLOW, DPBUSPRIMARYMEDIA_CREATE_ENTRY ,"DPBusPrimaryMedia::Create;aDevice=%d;aMediaId=%d;aLastMediaId=%d;this=%x", (TInt) aDevice, aMediaId, aLastMediaId, (TUint) this);
	
	// Permanently install a media call back if for a removable media device
	TInt r=KErrArgument;
	iPBusState=EPBusCardAbsent;
	if (__IS_REMOVABLE(aDevice))
		{
		iBusCallBack.iFunction=mediaCallBack;
		iBusCallBack.iPtr=this;
		iBusCallBack.SetSocket(iSocket->iSocketNumber);
		iDfcQ=&iSocket->iDfcQ;
		r=DPrimaryMediaBase::Create(aDevice,aMediaId,aLastMediaId);
		if (r==KErrNone)
			{
			iBusCallBack.Add();
			iPBusState=iSocket->State();
			iMsgQ.Receive();
			}
		}
	OstTraceFunctionExitExt( DPBUSPRIMARYMEDIA_CREATE_EXIT, this, r );
	return r;
	}

/**
  Checks the PBUS state.
  @return KErrNone if successful,
          KErrNotReady if card is absent.
  @see TPBusState
  */
TInt DPBusPrimaryMedia::QuickCheckStatus()
	{
	OstTraceFunctionEntry1( DPBUSPRIMARYMEDIA_QUICKCHECKSTATUS_ENTRY, this );
	TInt r=KErrNone;
	if (iSocket && iSocket->State()==EPBusCardAbsent)
		r=KErrNotReady;
	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPBusPrimaryMedia::QuickCheckStatus media %d returns %d",iMediaId,r));
	OstTraceExt2(TRACE_INTERNALS, DPBUSPRIMARYMEDIA_QUICKCHECKSTATUS, "iMediaId=%d; retval=%d",iMediaId,r);
	OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_QUICKCHECKSTATUS_EXIT, this );
	return r;
	}

/**
  This function is called by the local media device driver to force a remount of the media device.
  @param  aFlags	Corresponds to force media change.
  @return KErrNone if successful, 
		  otherwise one of the other system wide error codes. 
  @see TForceMediaChangeFlags
  */
TInt DPBusPrimaryMedia::ForceMediaChange(TInt aFlags)
	{
	OstTraceFunctionEntryExt( DPBUSPRIMARYMEDIA_FORCEMEDIACHANGE_ENTRY, this );
	if ((aFlags != KMediaRemountForceMediaChange) || (iPBusState == EPBusCardAbsent))
		{
		TInt pbusState = iPBusState;
		
		// This should ensure NotifyMediaChange() is called for ALL primary media attached to this socket
		iSocket->ChangeState(EPBusCardAbsent, KErrNotReady);

		// If a request was cancelled it's possible that the socket controller has been left in an 
		// unusable state which might cause the next request to fail, so power down the socket to be safe
		iSocket->ResetSocket(EFalse);

		iSocket->ChangeState(pbusState == EPBusCardAbsent ? EPBusCardAbsent : EPBusOff, KErrNotReady);

		OstTraceFunctionExitExt( DPBUSPRIMARYMEDIA_FORCEMEDIACHANGE_EXIT1, this, KErrCompletion );
		return KErrCompletion;
		}
	
	iSocket->ForceMediaChange();
	OstTraceFunctionExitExt( DPBUSPRIMARYMEDIA_FORCEMEDIACHANGE_EXIT2, this, KErrNone );
	return KErrNone;
	}

/**
  Called by clients to power up the PBUS.
  @return KErrNone if successful,
  		  otherwise one of the other system wide error codes.
  @see  DPBusSocket::PowerUp()
  */
TInt DPBusPrimaryMedia::InitiatePowerUp()
	{
	OstTraceFunctionEntry1( DPBUSPRIMARYMEDIA_INITIATEPOWERUP_ENTRY, this );
	TInt r = iSocket->PowerUp();  
	OstTraceFunctionExitExt( DPBUSPRIMARYMEDIA_INITIATEPOWERUP_EXIT, this, r );
	return r;
	}

/**
  Flags the media driver as entering a critical part of its processing.
  @return KErrNone if successful,
  		  otherwise one of the other system wide error codes.
  @see DPBusSocket::InCritical()
  */
TInt DPBusPrimaryMedia::DoInCritical()
	{
	OstTraceFunctionEntry1( DPBUSPRIMARYMEDIA_DOINCRITICAL_ENTRY, this );
	TInt r = iSocket->InCritical(); 
	OstTraceFunctionExitExt( DPBUSPRIMARYMEDIA_DOINCRITICAL_EXIT, this, r );
	return r;
	}

/**
  Flags the media driver as leaving a critical part of its processing.
  @return KErrNone if successful, 
  		  otherwise one of the other system wide error codes.
  @see DPBusSocket::EndInCritical()
  */
void DPBusPrimaryMedia::DoEndInCritical()
	{
	OstTraceFunctionEntry1( DPBUSPRIMARYMEDIA_DOENDINCRITICAL_ENTRY, this );
	iSocket->EndInCritical();
	OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_DOENDINCRITICAL_EXIT, this );
	}

/**
  Sets the incremental value of current consumption to aCurrent.
  @param aCurrent Delta Current in Milliamps.
  @see DPBusSocket::DeltaCurrentConsumption()
  */
void DPBusPrimaryMedia::DeltaCurrentConsumption(TInt aCurrent)
	{
	OstTraceFunctionEntryExt( DPBUSPRIMARYMEDIA_DELTACURRENTCONSUMPTION_ENTRY, this );
	iSocket->DeltaCurrentConsumption(aCurrent);
	OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_DELTACURRENTCONSUMPTION_EXIT, this );
	}

/**
  Gets the default drive capability/attributes.
  @param aCaps	A reference to a client-supplied TLocalDriveCapsV2 class to be filled by this function.
  @see TLocalDriveCapsV2
  @see TMediaType
  */
void DPBusPrimaryMedia::DefaultDriveCaps(TLocalDriveCapsV2& aCaps)
	{
	OstTraceFunctionEntry1( DPBUSPRIMARYMEDIA_DEFAULTDRIVECAPS_ENTRY, this );
	// aCaps is zeroed beforehand
	aCaps.iType = EMediaNotPresent;
	aCaps.iDriveAtt = KDriveAttLocal|KDriveAttRemovable;
	OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_DEFAULTDRIVECAPS_EXIT, this );
	}

/**
  Checks whether it is a removable media device or not.
  @param aSocketNum	This will be updated with socket number
  @return ETrue if Removable Device, EFalse if the device is Non-Removable.
  */
TBool DPBusPrimaryMedia::IsRemovableDevice(TInt& aSocketNum)
	{
	OstTraceFunctionEntryExt( DPBUSPRIMARYMEDIA_ISREMOVABLEDEVICE_ENTRY, this );
	aSocketNum=iSocket->iSocketNumber;
	OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_ISREMOVABLEDEVICE_EXIT, this );
	return(ETrue);
	}
	
void DPBusPrimaryMedia::PBusStateChange(TInt aState, TInt anError)
	{
	OstTraceFunctionEntryExt( DPBUSPRIMARYMEDIA_PBUSSTATECHANGE_ENTRY, this );
	// receive power down and media change notifications
	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPBusPrimaryMedia(%d)::PBusStateChange state %d, err %d",iMediaId,aState,anError));
	OstTraceExt3(TRACE_INTERNALS, DPBUSPRIMARYMEDIA_PBUSSTATECHANGE, "iMediaId=%d; aState=%d; anError=%d", iMediaId,aState,anError);
	if (aState!=iPBusState)
		{
		TInt oldState = iPBusState;
		iPBusState=aState;
		switch (aState)
			{
			case EPBusCardAbsent:
				NotifyMediaChange();
				break;
			case EPBusOff:
				switch (anError)
					{
					case KErrNone:
						// machine power down
						NotifyPowerDown();
						break;
					case KErrTimedOut:					
						// machine power down
						NotifyPowerDown();
						if(oldState == EPBusCardAbsent)
							{
							// powering down after power up with no card present.
							// ...to prevent the bus powering up again, maintain
							//    the card state as absent.  A media change will
							//    update the status to allow the bus to power up.
							iPBusState = EPBusCardAbsent;
							}
						break;
					case KErrNotReady:
						// card detected following door close
						NotifyMediaPresent();
						break;
					case KErrAbort:
						NotifyEmergencyPowerDown();
						break;
					default:
						if (iState==EPoweringUp1 || iState==EPoweringUp2)
							PowerUpComplete(anError);
						break;
					}
			case EPBusPoweringUp:
				// no action required
				break;
			case EPBusOn:
				// bus is now powered up
				if (iState==EPoweringUp1 || iState==EPoweringUp2)
					PowerUpComplete(anError);
				break;
			case EPBusPsuFault:
				NotifyPsuFault(anError);
				break;
			case EPBusPowerUpPending:
				// no action required
				break;
			default:
				break;
			}
		}
	OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_PBUSSTATECHANGE_EXIT, this );
	}