201041_01
authorhgs
Mon, 11 Oct 2010 19:11:06 +0100
changeset 287 ddfd5aa0d58f
parent 286 48e57fb1237e
child 289 55a0a1279a7e
201041_01
kernel/eka/bld.inf
kernel/eka/bmarm/epbusmu.def
kernel/eka/bmarm/rpmbextu.def
kernel/eka/bwins/epbusmu.def
kernel/eka/bwins/rpmbextu.def
kernel/eka/bx86/epbusmu.def
kernel/eka/bx86/rpmbextu.def
kernel/eka/drivers/media/base_e32_drivers_media.mrp
kernel/eka/drivers/media/bld.inf
kernel/eka/drivers/medmmc/bgahsmmcptn.cpp
kernel/eka/drivers/medmmc/bgahsmmcptn.mmp
kernel/eka/drivers/medmmc/bmarm/medmmcu.def
kernel/eka/drivers/medmmc/bwins/medmmcu.def
kernel/eka/drivers/medmmc/bx86/medmmcu.def
kernel/eka/drivers/medmmc/eabi/medmmcu.def
kernel/eka/drivers/medmmc/medmmc.cpp
kernel/eka/drivers/medmmc/medmmc.h
kernel/eka/drivers/medmmc/medmmc.mmp
kernel/eka/drivers/medmmc/medmmcpatchdata.cpp
kernel/eka/drivers/medmmc/mmcdp.h
kernel/eka/drivers/pbus/mmc/epbusm.mmh
kernel/eka/drivers/pbus/mmc/mmccd_init.cpp
kernel/eka/drivers/pbus/mmc/rpmbstack.cpp
kernel/eka/drivers/pbus/mmc/sdcard/bmarm/sdcard3c/epbusmu.def
kernel/eka/drivers/pbus/mmc/sdcard/bmarm/sdcard3c/sdio/epbusmu.def
kernel/eka/drivers/pbus/mmc/sdcard/bwins/sdcard3c/epbusmu.def
kernel/eka/drivers/pbus/mmc/sdcard/bwins/sdcard3c/sdio/epbusmu.def
kernel/eka/drivers/pbus/mmc/sdcard/bx86/sdcard3c/epbusmu.def
kernel/eka/drivers/pbus/mmc/sdcard/bx86/sdcard3c/sdio/epbusmu.def
kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/epbusmu.def
kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/sdio/epbusmu.def
kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdcard.cpp
kernel/eka/drivers/pbus/mmc/session.cpp
kernel/eka/drivers/pbus/mmc/stack.cpp
kernel/eka/drivers/pbus/mmc/stackdebug.h
kernel/eka/drivers/rpmb/rpmbdevice.cpp
kernel/eka/drivers/rpmb/rpmbext.mmp
kernel/eka/drivers/rpmb/traces/OstTraceDefinitions.h
kernel/eka/eabi/epbusmu.def
kernel/eka/eabi/rpmbextu.def
kernel/eka/include/drivers/mmc.h
kernel/eka/include/drivers/mmc.inl
kernel/eka/include/drivers/rpmbdevice.h
kernel/eka/include/drivers/rpmbpacket.h
kernel/eka/include/e32ver.h
kernel/eka/release.txt
kernel/eka/rombuild/rpmbtest.oby
kerneltest/e32test/group/t_mmcdrv.mmp
kerneltest/e32test/pccd/t_mmcdrv.cpp
kerneltest/e32test/rpmb/bld.inf
kerneltest/e32test/rpmb/driver/bld.inf
kerneltest/e32test/rpmb/driver/d_rpmb.cpp
kerneltest/e32test/rpmb/driver/d_rpmb.h
kerneltest/e32test/rpmb/driver/d_rpmb.mmp
kerneltest/e32test/rpmb/rpmbtestautoexec.bat
kerneltest/e32test/rpmb/t_rpmb.cpp
kerneltest/e32test/rpmb/t_rpmb.h
kerneltest/e32test/rpmb/t_rpmb.mmp
kerneltest/f32test/bench/t_trimbm.cpp
kerneltest/f32test/group/bld.inf
kerneltest/f32test/group/t_trimbm.mmp
--- a/kernel/eka/bld.inf	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/bld.inf	Mon Oct 11 19:11:06 2010 +0100
@@ -264,9 +264,13 @@
 include/drivers/resmanus_trace.h				SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
 
 include/drivers/i2s.h							SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
-						//
+					
 include/drivers/display.h						SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
 
+include/drivers/rpmbdevice.h					SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
+include/drivers/rpmbpacket.h					SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
+
+
 // Real Time Clock SHAI API
 include/drivers/rtclock.h						SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
 
--- a/kernel/eka/bmarm/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/bmarm/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
 	InitStackAfterUnlockSM__9DMMCStack @ 94 NONAME ; DMMCStack::InitStackAfterUnlockSM(void)
 	RegisterMediaDevices__26TMMCardControllerInterfacei @ 95 NONAME ; TMMCardControllerInterface::RegisterMediaDevices(int)
 	ModifyCardCapabilitySM__9DMMCStack @ 96 NONAME R3UNUSED ; DMMCStack::ModifyCardCapabilitySM(void)
-	Dummy1__9DMMCStack @ 97 NONAME R3UNUSED ; DMMCStack::Dummy1(void)
+	MMCGetExtInterface__F18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 97 NONAME
 	GetInterface__9DMMCStackQ29DMMCStack12TInterfaceIdRPQ29DMMCStack10MInterface @ 98 NONAME R3UNUSED ; DMMCStack::GetInterface(DMMCStack::TInterfaceId, DMMCStack::MInterface *&)
 	MachineInfo__9DMMCStackR5TDes8 @ 99 NONAME R3UNUSED ; DMMCStack::MachineInfo(TDes8 &)
 	SetBusWidth__9DMMCStackUl @ 100 NONAME R3UNUSED ; DMMCStack::SetBusWidth(unsigned long)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/bmarm/rpmbextu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,7 @@
+EXPORTS
+	Close__11DRpmbDevice @ 1 NONAME R3UNUSED ; DRpmbDevice::Close(void)
+	Open__11DRpmbDeviceUi @ 2 NONAME R3UNUSED ; DRpmbDevice::Open(unsigned int)
+	SendAccessRequest__11DRpmbDeviceR5TDes8T1 @ 3 NONAME R3UNUSED ; DRpmbDevice::SendAccessRequest(TDes8 &, TDes8 &)
+	"_._11DRpmbDevice" @ 4 NONAME R3UNUSED ; DRpmbDevice::~DRpmbDevice(void)
+	__11DRpmbDevice @ 5 NONAME R3UNUSED ; DRpmbDevice::DRpmbDevice(void)
+
--- a/kernel/eka/bwins/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/bwins/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
 	?InitStackAfterUnlockSM@DMMCStack@@MAEKXZ @ 94 NONAME ; protected: virtual unsigned long __thiscall DMMCStack::InitStackAfterUnlockSM(void)
 	?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 95 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
 	?ModifyCardCapabilitySM@DMMCStack@@MAEKXZ @ 96 NONAME ; unsigned long DMMCStack::ModifyCardCapabilitySM(void)
-	?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; void DMMCStack::Dummy1(void)
+	?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME ; int MMCGetExtInterface(enum TMMCExtInterfaceId, class MMCMExtInterface * &, void *)
 	?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
 	?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99  NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
 	?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/bwins/rpmbextu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,7 @@
+EXPORTS
+	?SendAccessRequest@DRpmbDevice@@QAEHAAVTDes8@@0@Z @ 1 NONAME ; int DRpmbDevice::SendAccessRequest(class TDes8 &, class TDes8 &)
+	??1DRpmbDevice@@UAE@XZ @ 2 NONAME ; DRpmbDevice::~DRpmbDevice(void)
+	?Close@DRpmbDevice@@QAEXXZ @ 3 NONAME ; void DRpmbDevice::Close(void)
+	??0DRpmbDevice@@QAE@XZ @ 4 NONAME ; DRpmbDevice::DRpmbDevice(void)
+	?Open@DRpmbDevice@@QAEHI@Z @ 5 NONAME ; int DRpmbDevice::Open(unsigned int)
+
--- a/kernel/eka/bx86/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/bx86/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
 	?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 94 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
 	?RequestAsyncPowerDown@DPBusSocket@@QAEXXZ @ 95 NONAME ; public: void __thiscall DPBusSocket::RequestAsyncPowerDown(void)
 	?ControlIO@DPBusSocket@@UAEHHPAX0@Z @ 96 NONAME ; public: virtual int __thiscall DPBusSocket::ControlIO(int,void *,void *)
-	?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; private: virtual void __thiscall DMMCStack::Dummy1(void)
+	?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME
 	?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
 	?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99  NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
 	?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/bx86/rpmbextu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,7 @@
+EXPORTS
+	??0DRpmbDevice@@QAE@XZ @ 1 NONAME ; public: __thiscall DRpmbDevice::DRpmbDevice(void)
+	??1DRpmbDevice@@UAE@XZ @ 2 NONAME ; public: virtual __thiscall DRpmbDevice::~DRpmbDevice(void)
+	?Close@DRpmbDevice@@QAEXXZ @ 3 NONAME ; public: void __thiscall DRpmbDevice::Close(void)
+	?Open@DRpmbDevice@@QAEHI@Z @ 4 NONAME ; public: int __thiscall DRpmbDevice::Open(unsigned int)
+	?SendAccessRequest@DRpmbDevice@@QAEHAAVTDes8@@0@Z @ 5 NONAME ; public: int __thiscall DRpmbDevice::SendAccessRequest(class TDes8 &,class TDes8 &)
+
--- a/kernel/eka/drivers/media/base_e32_drivers_media.mrp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/media/base_e32_drivers_media.mrp	Mon Oct 11 19:11:06 2010 +0100
@@ -44,6 +44,7 @@
 source	\sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\eabi\sdcard3c\sdio\epbusmu.def
 source	\sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\eabi\sdcard3c\sdio\distribution.policy.s60
 source	\sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\sdcard3c\sdio
+source	\sf\os\kernelhwsrv\kernel\eka\drivers\rpmb
 
 source	\sf\os\kernelhwsrv\kernel\eka\drivers\media
 
--- a/kernel/eka/drivers/media/bld.inf	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/media/bld.inf	Mon Oct 11 19:11:06 2010 +0100
@@ -56,6 +56,7 @@
 ../../drivers/medmmc/bgahsmmcptn
 ../../drivers/pbus/mmc/epbusmmc
 ../../drivers/medmmc/medmmc
+../../drivers/rpmb/rpmbext
 
 #if !defined(WINS) && !defined(GENERIC_X86)
 ../../drivers/pbus/mmc/sdcard/sdcard3c/epbussd
--- a/kernel/eka/drivers/medmmc/bgahsmmcptn.cpp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/medmmc/bgahsmmcptn.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -16,11 +16,13 @@
 //
 
 #include <emmcptn.h>
+#include "mmc.h"
 #include "bgahsmmcptn.h"
+#include "medmmc.h"
 #include "toc.h"
+
 //#define __DEBUG_PARTITIONS_
 //#define __DEBUG_CHECK_PARTITION_
-const TInt    KDiskSectorShift          = 9;
 
 class DBB5PartitionInfo : public DEMMCPartitionInfo
 	{
@@ -39,8 +41,11 @@
 private:
 	virtual TInt ReadPartition(TUint32 aPtOffset);
 	static void SessionEndCallBack(TAny* aSelf);
-		   void DoSessionEndCallBack();
+	void DoSessionEndCallBack();
 	virtual TInt DecodePartitionInfo();
+	TInt GetPartitionSizeInSectors(TUint aPartition, TUint32& aSize);
+	TInt GetPartitionOffset(TUint32& aPtOffset);
+	TInt SelectNextPartition();
 
 protected:
 	DMediaDriver*	iDriver;
@@ -53,6 +58,7 @@
 	TUint32 		iPartitionAttributes[KMaxLocalDrives];
 	TBool           iCheckTOC;
 	Toc*            iTocPtr;
+	TUint32			iSelectedPartition;	
 	};
 
 DBB5PartitionInfo::DBB5PartitionInfo()
@@ -88,19 +94,169 @@
 	TInt bufLen, minorBufLen;
 	stack->BufferInfo(iIntBuf, bufLen, minorBufLen);
 
+	iSelectedPartition = TExtendedCSD::ESelectUserArea;
+	
 	return(KErrNone);
 	}
 
 TInt DBB5PartitionInfo::PartitionInfo(TPartitionInfo& aInfo, const TMMCCallBack& aCallBack)
 	{
 	iPartitionInfo = &aInfo;
+	iPartitionInfo->iPartitionCount = 0;
 	iCallBack = aCallBack;
 
+	// Always check the user partition first
+	iSelectedPartition = TExtendedCSD::ESelectUserArea;
+	iSession->SetPartition(iSelectedPartition);
+
 	// Preferred partition scheme is BB5, which is located in the last block of the media.
-    const TUint32 ptiOffset = (I64LOW(iCard->DeviceSize64() >> KDiskSectorShift)) - KPIOffsetFromMediaEnd;
-	return ReadPartition(ptiOffset);
+    TUint32 ptiOffset;
+    TInt r;
+    do
+    	{
+	    r = GetPartitionOffset(ptiOffset);
+
+	    if(r == KErrNone)
+	    	{
+		    r = ReadPartition(ptiOffset);
+		    return r;
+	    	}
+
+	    r = SelectNextPartition();
+    	}
+    while(r != KErrNotFound);
+
+	return r;
 	}
 	
+// retrieves size in terms of sectors
+TInt DBB5PartitionInfo::GetPartitionSizeInSectors(TUint aPartition, TUint32& aSize)
+	{
+	TInt r = KErrNone;
+	
+	TUint32 size = 0;
+	
+	const TExtendedCSD& extCsd = iCard->ExtendedCSD();
+	
+	switch(aPartition)
+		{
+		case TExtendedCSD::ESelectUserArea:
+			{
+			size = (TUint32)(iCard->DeviceSize64() / KSectorSize);
+			
+			if(extCsd.ExtendedCSDRev() >= TExtendedCSD::EExtendedCSDRev1_5)
+				{
+				TUint32 otherPartitionsSize = 
+					extCsd.GeneralPurposePartition1SizeInSectors()
+					+ extCsd.GeneralPurposePartition2SizeInSectors()
+					+ extCsd.GeneralPurposePartition3SizeInSectors()
+					+ extCsd.GeneralPurposePartition4SizeInSectors();
+					
+					__ASSERT_DEBUG(size >= otherPartitionsSize, Kern::Fault("DBB5PartitionInfo size mismatch", __LINE__));
+					size -= otherPartitionsSize;
+				}
+			}
+			break;
+		case TExtendedCSD::ESelectBootPartition1:
+		case TExtendedCSD::ESelectBootPartition2:
+			size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_3) ? 
+				0 : extCsd.BootSizeInSectors();
+			break;
+		case TExtendedCSD::ESelectRPMB:
+			size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ? 
+				0 : extCsd.RpmbSizeInSectors();
+			break;
+		case TExtendedCSD::ESelectGPAPartition1:
+			size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ? 
+				0 : extCsd.GeneralPurposePartition1SizeInSectors();
+			break;
+		case TExtendedCSD::ESelectGPAPartition2:
+			size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ? 
+				0 : extCsd.GeneralPurposePartition2SizeInSectors();
+			break;
+		case TExtendedCSD::ESelectGPAPartition3:
+			size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ? 
+				0 : extCsd.GeneralPurposePartition3SizeInSectors();
+			break;
+		case TExtendedCSD::ESelectGPAPartition4:
+			size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ? 
+				0 : extCsd.GeneralPurposePartition4SizeInSectors();
+			break;
+		default:
+			// unknown partition
+			size = 0;
+			r = KErrNotSupported;
+			break;
+		}
+
+	aSize = size;	
+	return r;
+	}
+	
+TInt DBB5PartitionInfo::GetPartitionOffset(TUint32& aPtiOffset)
+	{
+	TInt r = GetPartitionSizeInSectors(iSelectedPartition, aPtiOffset);
+		
+	if((r != KErrNone) || (aPtiOffset == 0))
+		{
+		// error reading or partition not supported, skip
+		r = KErrNotSupported;
+		}
+	else
+		{			
+		// need to determine correct end of the partition
+		aPtiOffset -= KPIOffsetFromMediaEnd;
+		}
+		
+	return r;
+	}
+	
+TInt DBB5PartitionInfo::SelectNextPartition()
+	{
+	TExtendedCSD extCsd = iCard->ExtendedCSD();
+	TUint maxPartition = TExtendedCSD::ESelectUserArea;
+	
+	if(extCsd.ExtendedCSDRev() >= TExtendedCSD::EExtendedCSDRev1_5)
+		{
+		// v4.4 supports UDA, 2x BOOT, RPMB and 4x GPAP partitions
+		maxPartition = TExtendedCSD::ESelectGPAPartition4;
+		}
+#ifdef EMMC_BOOT_PARTITION_ACCESS_ENABLED
+	else if(extCsd.ExtendedCSDRev() >= TExtendedCSD::EExtendedCSDRev1_3)
+		{
+		// v4.3 supports up to two BOOT partitions
+		maxPartition = TExtendedCSD::ESelectBootPartition2;
+		}
+#endif // EMMC_BOOT_PARTITION_ACCESS_ENABLED
+
+	++iSelectedPartition;
+	
+	// skip through to GPAP1 if either the currently selected partition is RPMB or
+	// if it is one of the BOOT partitions and boot partition access is not enabled
+	if((iSelectedPartition == TExtendedCSD::ESelectRPMB)
+#ifndef EMMC_BOOT_PARTITION_ACCESS_ENABLED 
+		|| (iSelectedPartition == TExtendedCSD::ESelectBootPartition1)
+		|| (iSelectedPartition == TExtendedCSD::ESelectBootPartition2)
+#endif	   
+		)
+		{
+		iSelectedPartition = TExtendedCSD::ESelectGPAPartition1;
+		}
+
+	TInt r = KErrNone;
+	if(iSelectedPartition > maxPartition)
+		{
+		r = KErrNotFound; // no more partitions to be checked
+		}
+	else
+		{
+		iSession->SetPartition(iSelectedPartition);
+		}
+		
+	return r;	
+	}	
+	
+// returns KErrCompletion on success after having checked all partitions
 TInt DBB5PartitionInfo::ReadPartition(TUint32 aPtOffset)
     {
 	// If media driver is persistent (see EMediaDriverPersistent)
@@ -167,24 +323,82 @@
 
 	TInt r = iSession->EpocErrorCode();
 
+	
+	TInt& partitionCount = iPartitionInfo->iPartitionCount;
+
 	if (r == KErrNone)
 		r = DecodePartitionInfo();
 
-	if (!iCheckTOC)
-	    {        
-	    iDriver->PartitionInfoComplete(r == KErrNone ? r : KErrNotReady);
-	    }
+	if (iCheckTOC)
+		{
+		//BB5 table not found need to check for TOC in this partition before continuing
+		if (r!=KErrNone)
+			{
+			iDriver->PartitionInfoComplete(KErrNotReady);
+			}
+		return;
+		}
+
+
+	if(r == KErrNone)
+		{
+		// check next partition(s) for BB5
+		TUint32 ptiOffset = 0;
+	
+		r = SelectNextPartition();
+		while(r != KErrNotFound)
+			{
+			if(r == KErrNone)
+				r = GetPartitionOffset(ptiOffset);
+				
+			if(r == KErrNone)
+				{
+				r = ReadPartition(ptiOffset);
+				if(r != KErrNone)
+					break;
+
+
+				return;
+				}
+
+			r = SelectNextPartition();
+			}
+
+		
+		// end of partitions - reinterpret error code
+		if(r != KErrNotFound)
+			{
+			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc:dsc: ReadPartition() failed r=%d!", r));
+			r = KErrCorrupt;
+			}
+		else if(partitionCount == 0)
+			{
+			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc:dsc: No supported partitions found!"));
+			r = KErrCorrupt;
+			}
+		else
+			r = KErrCompletion;
+		}
+
+	// Notify medmmc that partitioninfo is complete
+	iCallBack.CallBack();
+
+	// All potential partitions checked - KErrCompletion
+	// indicates that there are no more partitions to check
+	r = (r == KErrCompletion) ? KErrNone : KErrNotReady;
+	iDriver->PartitionInfoComplete(r);
 	}
 
+
 TInt DBB5PartitionInfo::DecodePartitionInfo()
 //
 // Decode partition info that was read into internal buffer
 //
 	{
 	__KTRACE_OPT(KPBUSDRV, Kern::Printf(">Mmc:PartitionInfo()"));
-	TUint partitionCount = iPartitionInfo->iPartitionCount = 0;
+	TInt& partitionCount = iPartitionInfo->iPartitionCount;
+    TInt r = KErrNone;
 
-	
 	if (iCheckTOC)
 	    {
         // Try utilising the TOC (Table Of Contents) partitioning scheme 
@@ -199,7 +413,6 @@
         STocItem item;
         iTocPtr = reinterpret_cast<Toc*>(&iIntBuf[0]);
         iTocPtr->iTocStartSector = KTocStartSector;
-        TInt r = KErrNone;
 
 // USER Drive - Only 1        
         r = iTocPtr->GetItemByName(KTocUserName, item); 
@@ -262,7 +475,7 @@
             }
         
 // SWAP Partition - Only 1        
-        r = iTocPtr->GetItemByName(KTocSwap, item); 
+        r = iTocPtr->GetItemByName(KTocSwap, item);
         if (KErrNone == r)
             {
             __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%X  Size = 0x%X", item.iFileName, item.iStart, item.iSize));
@@ -283,6 +496,7 @@
             }
 #endif //__DEBUG_PARTITIONS_
         
+		r = KErrNone;
         iCheckTOC = EFalse;
 	    }
 	else
@@ -324,12 +538,12 @@
                         {                   
                         iPartitionInfo->iEntry[partitionCount].iPartitionType	  = partitionType;
                         iPartitionAttributes[partitionCount]                      = partitionTable->iPartitions[index].iPartition_attributes;
-                        
+	                    static_cast<DMmcMediaDriverFlash *>(iDriver)->SetEMmcPartitionMapping(partitionCount, iSelectedPartition);
                         // ROM/ROFS partitions have a BB5 checksum header that must be offset for the Symbian OS.
-                        const TUint32 KstartOffset = ((KPartitionTypeROM == partitionType) || (KPartitionTypeRofs == partitionType) || (KPartitionTypeEmpty == partitionType)) ? KBB5HeaderSizeInSectors : 0;
+						const TUint32 KStartOffset = ((KPartitionTypeROM == partitionType) || (KPartitionTypeRofs == partitionType) || (KPartitionTypeEmpty == partitionType)) ? KBB5HeaderSizeInSectors : 0;
                         
-                        iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = ((Int64) partitionTable->iPartitions[index].iStart_sector + KstartOffset) << KDiskSectorShift;
-                        iPartitionInfo->iEntry[partitionCount].iPartitionLen      = ((Int64) partitionTable->iPartitions[index].iSize - KstartOffset) << KDiskSectorShift;
+                        iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = ((Int64) partitionTable->iPartitions[index].iStart_sector + KStartOffset) << KDiskSectorShift;
+                        iPartitionInfo->iEntry[partitionCount].iPartitionLen      = ((Int64) partitionTable->iPartitions[index].iSize - KStartOffset) << KDiskSectorShift;
         
                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("Registering partition #%d:", partitionCount));
                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionCount....: %d", partitionCount));
@@ -339,6 +553,7 @@
                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionLen.....: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionLen, iPartitionInfo->iEntry[partitionCount].iPartitionLen >> KDiskSectorShift));
                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionType....: %d", iPartitionInfo->iEntry[partitionCount].iPartitionType));
                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionAttribs.: 0x%x", iPartitionAttributes[partitionCount]));
+						__KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionMapping.: 0x%x", static_cast<DMmcMediaDriverFlash *>(iDriver)->GetEMmcPartitionMapping(partitionCount)));
                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf(" "));
         
                         partitionCount++;
@@ -361,24 +576,43 @@
 	if(partitionCount == 0)
 		{
 		__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: No supported partitions found!"));
-		return KErrCorrupt;
+		// No Supported partitions found on this physical partition
+		return KErrNone;
 		}
-#ifdef __DEBUG_CHECK_PARTITION_	
-	else
+		
+#ifdef __DEBUG_CHECK_PARTITION_			
+	// Validate partition address boundaries
+	TUint32 eMmcPartitionSizeInSectors = 0;
+	if(r == KErrNone)
 		{
-		// at least one entry for a supported partition found
-		const TInt64 deviceSize = iCard->DeviceSize64();
+		// At least one entry for a supported partition found
+		r = GetPartitionSizeInSectors(iSelectedPartition, eMmcPartitionSizeInSectors);
+		
+		if(r != KErrNone)
+			{
+			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Could not retrieve size for eMMC partition 0x%02X", iSelectedPartition));
+			r = KErrCorrupt;
+			}
+		}
+		
+	if(r == KErrNone)
+		{
+		TUint64 eMmcPartitionSize = eMmcPartitionSizeInSectors * KSectorSize;
+		
 		TPartitionEntry& part = iPartitionInfo->iEntry[partitionCount - 1];
-
-		// Check that the card address space boundary is not exceeded by the last partition
-		if(part.iPartitionBaseAddr + part.iPartitionLen > deviceSize)
+	
+		// Check that the eMmcPartition address space boundary is not exceeded by the last partition
+		if(part.iPartitionBaseAddr + part.iPartitionLen > eMmcPartitionSize)
 			{
-			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: MBR partition exceeds card memory space"));
-			return KErrCorrupt;
+			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Partition #%d exceeds eMmc address space", partitionCount));
+			r = KErrCorrupt;
 			}
-
-		// Go through all partition entries and check boundaries
-		for(TInt i = partitionCount - 1; i > 0; i--)
+		}
+		
+	if(r == KErrNone)
+		{
+		// Go through all BB5 partition entries on this eMMC partition and check boundaries
+		for(TInt i = partitionCount - 1; i > iPartitionInfo->iPartitionCount; i--)
 			{
 			const TPartitionEntry& curr = iPartitionInfo->iEntry[i];
 			TPartitionEntry& prev = iPartitionInfo->iEntry[i-1];
@@ -387,20 +621,20 @@
 			if(curr.iPartitionBaseAddr < (prev.iPartitionBaseAddr + prev.iPartitionLen))
 				{
 				__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Overlapping partitions - check #%d", i));
-				return KErrCorrupt;
+				r = KErrCorrupt;
 				}
 			}
 		}
 #endif // _DEBUG_CHECK_PARTITION_
-
-	iPartitionInfo->iPartitionCount = partitionCount;
-	iPartitionInfo->iMediaSizeInBytes = iCard->DeviceSize64();
-
-	//Notify medmmc that partitioninfo is complete.
-	iCallBack.CallBack();
+		
+	if(r == KErrNone)
+		{
+		iPartitionInfo->iPartitionCount = partitionCount;
+		iPartitionInfo->iMediaSizeInBytes = iCard->DeviceSize64();
+		}
 
 	__KTRACE_OPT(KPBUSDRV, Kern::Printf("<Mmc:PartitionInfo (C:%d)", partitionCount));
-	return KErrNone;
+	return r;
 	}
 
 
--- a/kernel/eka/drivers/medmmc/bgahsmmcptn.mmp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/medmmc/bgahsmmcptn.mmp	Mon Oct 11 19:11:06 2010 +0100
@@ -15,11 +15,17 @@
 // 
 //
 
+// Define this macro to enable access to eMMC BOOT partitions (v4.3 and higher)
+//macro EMMC_BOOT_PARTITION_ACCESS_ENABLED
+
+#include "drivers/elocd.mmh"
+
 target			bgahsmmcptn.dll
 targettype		kext
 
 #include 		"../../kernel/kern_ext.mmh"
 systeminclude	../../include/drivers
+userinclude	traces
 
 source			bgahsmmcptn.cpp
 source			toc.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/bmarm/medmmcu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,4 @@
+EXPORTS
+	CreatePhysicalDevice__Fv @ 1 NONAME R3UNUSED ; CreatePhysicalDevice(void)
+	KTRIMEnabled @ 2 NONAME ; (null)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/bwins/medmmcu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,4 @@
+EXPORTS
+	?CreatePhysicalDevice@@YAPAVDPhysicalDevice@@XZ @ 1 NONAME ; class DPhysicalDevice * CreatePhysicalDevice(void)
+	?KTRIMEnabled@@3IB @ 2 NONAME ; unsigned int const KTRIMEnabled
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/bx86/medmmcu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,4 @@
+EXPORTS
+	?CreatePhysicalDevice@@YAPAVDPhysicalDevice@@XZ @ 1 NONAME ; class DPhysicalDevice * CreatePhysicalDevice(void)
+	?KTRIMEnabled@@3IB @ 2 NONAME ; unsigned int const KTRIMEnabled
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/eabi/medmmcu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,8 @@
+EXPORTS
+	_Z20CreatePhysicalDevicev @ 1 NONAME
+	KTRIMEnabled @ 2 NONAME DATA 4
+	_ZTI20DMmcMediaDriverFlash @ 3 NONAME
+	_ZTI28DPhysicalDeviceMediaMmcFlash @ 4 NONAME
+	_ZTV20DMmcMediaDriverFlash @ 5 NONAME
+	_ZTV28DPhysicalDeviceMediaMmcFlash @ 6 NONAME
+
--- a/kernel/eka/drivers/medmmc/medmmc.cpp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/medmmc/medmmc.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1999-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"
@@ -50,6 +50,7 @@
 #define __ASSERT_CACHE(c,p)
 #endif
 
+#include "medmmc.h"
 
 GLREF_C TInt GetMediaDefaultPartitionInfo(TMBRPartitionEntry& aPartitionEntry, TUint16& aReservedSectors, const TMMCard* aCardP);
 GLREF_C TBool MBRMandatory(const TMMCard* aCardP);
@@ -59,11 +60,10 @@
 extern  TInt GetCardFormatInfo(const TMMCard* aCardP, TLocalDriveCapsV5& aCaps);
 
 
+IMPORT_C extern const TUint KTRIMEnabled;
+
 const TInt KStackNumber = 0;
 
-const TInt KDiskSectorSize=512;
-const TInt KDiskSectorShift=9;
-
 const TInt KIdleCurrentInMilliAmps = 1;
 
 const TInt KMBRFirstPartitionEntry=0x1BE;
@@ -90,237 +90,6 @@
 const TInt64 KInvalidBlock = -1;
 const TInt KNoCacheBlock = -1;
 
-class DMmcMediaDriverFlash : public DMediaDriver
-	{
-public:
-	DMmcMediaDriverFlash(TInt aMediaId);
-	~DMmcMediaDriverFlash();
-	// ...from DMediaDriver
-	virtual void Close();
-	// replacing pure virtual
-	virtual void Disconnect(DLocalDrive* aLocalDrive, TThreadMessage*);
-	virtual TInt Request(TLocDrvRequest& aRequest);
-	virtual TInt PartitionInfo(TPartitionInfo& anInfo);
-	virtual void NotifyPowerDown();
-	virtual void NotifyEmergencyPowerDown();
-	// For creation by DPhysicalDeviceMediaMmcFlash
-	TInt DoCreate(TInt aMediaId);
-
-private:
-	enum TPanic
-		{
-		EDRInUse		= 0x0000,	EDRStart, EDRNotPositive, EDREnd,
-		ELRRequest		= 0x0010,	ELRStart, ELRNotPositive, ELREnd, ELRCached,
-		EDWInUse		= 0x0020,	EDWStart, EDWNotPositive, EDWEnd,
-		EDFInUse		= 0x0030,	EDFStart, EDFNotPositive, EDFEnd, ENotMmcSocket,
-		ELWRequest		= 0x0040,	ELWStart, ELWFmtStAlign, ELWNotPositive, ELWEnd, ELWFmtEndAlign, 
-									ELWLength, ELFStart, ELFEnd, ELFNotPositive,
-		ERPIInUse		= 0x0050,
-		EPCInUse		= 0x0060,	EPCFunc,
-		ESECBQueued		= 0x0070,
-		EDSEDRequest	= 0x0080,	EDSEDNotErrComplete,
-		ECRReqIdle		= 0x0090,	ECRRequest,
-		ERRBStAlign		= 0x00a0,	ERRBStPos, ERRBNotPositive, ERRBEndAlign, ERRBEndPos,
-									ERRBOverflow, ERRBCchInv, ERRBExist,
-		ERWBStPos		= 0x00b0,	ERWBNotPositive, ERWBEndPos, ERWBOverflow, ERWBCchInv,
-		EMBStPos		= 0x00c0,	EMBStAlign, EMBNotPositive, EMBEndPos, EMBEndAlign,
-									EMBOverflow, EMBCchInvPre, EMBCchInvPost,
-		EBGAStPos		= 0x00d0,	EBGAStAlign, EBGANotPositive, EBGAEndPos, EBGAEndAlign,
-									EBGAOverflow, EBGACchInv,
-		EICMNegative	= 0x00e0,	EICMOverflow, ECMIOverflow,
-		EGCBAlign		= 0x00f0,	EGCBPos, EGCBCchInv,
-		
-		ECFSessPtrNull	= 0x0100,	// Code Fault - session pointer NULL
-
-		EDBNotEven		= 0x0110,	// Not and even number of blocks in the buffer cache
-		EDBCBQueued		= 0x0111,	// The data transfer callback is already queued
-		EDBLength		= 0x0112,	// The length of data to transfer in data transfer callback is not positive
-		EDBLengthTooBig	= 0x0113,	// The length of data to transfer in data transfer callback is too big
-		EDBOffsetTooBig = 0x0114,	// The Offset into the user data buffer is too big
-		EDBCacheInvalid	= 0x0115,	// The cache is invalid at the end of data transfer
-		EDBNotOptimal	= 0x0116,	// Due to Cache size DB functionality will never be utilised
-		ENoDBSupport	= 0x0120,	// DMA request arrived but PSL does not support double buffering
-		ENotDMAAligned  = 0x0121,
-		};
-	static void Panic(TPanic aPnc);
-
-	enum TMediaRequest
-		{
-		EMReqRead = 0,
-		EMReqWrite = 1,
-		EMReqFormat = 2,
-		EMReqPtnInfo,
-		EMReqPswdCtrl,
-		EMReqForceErase,
-		EMReqUpdatePtnInfo,
-		EMReqWritePasswordData,
-		EMReqIdle,
-		EMReqEMMCPtnInfo,
-		};
-	enum TMediaReqType {EMReqTypeNormalRd,EMReqTypeNormalWr,EMReqTypeUnlockPswd,EMReqTypeChangePswd};
-
-	enum {KWtRBMFst = 0x00000001, 	// iWtRBM - Read First Block only
-		  KWtRBMLst = 0x00000002,	// iWtRBM - Read Last Block only
-		  KWtMinFst = 0x00000004,	// iWtRBM - Write First Block only
-		  KWtMinLst = 0x00000008,	// iWtRBM - Write Last Block only
-		  KIPCSetup = 0x00000010,	// iRdROB - IPC Setup Next Iteration
-		  KIPCWrite = 0x00000020};	// iRdROB - IPC Write Next Iteration
-
-private:
-	// MMC device specific stuff
-	TInt DoRead();
-	TInt DoWrite();
-	TInt DoFormat();
-	TInt Caps(TLocDrv& aDrive, TLocalDriveCapsV6& aInfo);
-
-	inline DMMCStack& Stack() const;
-	inline TInt CardNum() const;
-	inline TMediaRequest CurrentRequest() const;
-
-	TInt LaunchRead(TInt64 aStart, TUint32 aLength);
-	TInt LaunchDBRead();
-	TInt LaunchPhysRead(TInt64 aStart, TUint32 aLength);
-	
-	TInt LaunchWrite(TInt64 aStart, TUint32 aLength, TMediaRequest aMedReq);
-	TInt LaunchFormat(TInt64 aStart, TUint32 aLength);
-
-	TInt LaunchRPIUnlock(TLocalDrivePasswordData& aData);
-	TInt LaunchRPIRead();
-	TInt LaunchRPIErase();
-	TInt DecodePartitionInfo();
-	TInt WritePartitionInfo();
-	TInt GetDefaultPartitionInfo(TMBRPartitionEntry& aPartitionEntry);
-	TInt CreateDefaultPartition();
-
-
-#if defined __TEST_PAGING_MEDIA_DRIVER__
-	TInt HandleControlIORequest();
-#endif
-
-	static void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors);
-
-	TInt CheckDevice(TMediaReqType aReqType);
-
-	static void SessionEndCallBack(TAny* aMediaDriver);
-	static void SessionEndDfc(TAny* aMediaDriver);
-	void DoSessionEndDfc();
-
-	static void DataTransferCallBack(TAny* aMediaDriver);
-	static void DataTransferCallBackDfc(TAny* aMediaDriver);
-
-	void DoReadDataTransferCallBack();
-	void DoWriteDataTransferCallBack();
-	void DoPhysReadDataTransferCallBack();
-	void DoPhysWriteDataTransferCallBack();
-	
-	TInt AdjustPhysicalFragment(TPhysAddr &physAddr, TInt &physLength);
-	TInt PrepareFirstPhysicalFragment(TPhysAddr &aPhysAddr, TInt &aPhysLength, TUint32 aLength);
-	void PrepareNextPhysicalFragment();
-
-	TInt EngageAndSetReadRequest(TMediaRequest aRequest);
-	TInt EngageAndSetWriteRequest(TMediaRequest aRequest);
-	TInt EngageAndSetRequest(TMediaRequest aRequest, TInt aCurrent);
-	void CompleteRequest(TInt aReason);
-
-	TInt ReadDataUntilCacheExhausted(TBool* aAllDone);
-	TInt WriteDataToUser(TUint8* aBufPtr);
-	TInt ReadDataFromUser(TDes8& aDes, TInt aOffset);
-	TUint8* ReserveReadBlocks(TInt64 aStart, TInt64 aEnd, TUint32* aLength);
-	TUint8* ReserveWriteBlocks(TInt64 aMedStart, TInt64 aMedEnd, TUint* aRBM);
-	void MarkBlocks(TInt64 aStart, TInt64 aEnd, TInt aStartIndex);
-	void BuildGammaArray(TInt64 aStart, TInt64 aEnd);
-	void InvalidateCache();
-	void InvalidateCache(TInt64 aStart, TInt64 aEnd);
-	TUint8* IdxToCchMem(TInt aIdx) const;
-	TInt CchMemToIdx(TUint8* aMemP) const;
-
-	TInt DoPasswordOp();
-	void PasswordControl(TInt aFunc, TLocalDrivePasswordData& aData);
-	void Reset();
-	TInt AllocateSession();  
-
-#ifdef _DEBUG_CACHE
-	TBool CacheInvariant();
-	TUint8* GetCachedBlock(TInt64 aAddr);
-#endif
-private:
-	DMMCStack* iStack;			 				// controller objects
-	TMMCard* iCard;
-	DMMCSession* iSession;
-	DMMCSocket* iSocket;
-
-	TInt iCardNumber;
-
-	TUint iBlkLenLog2;							// cached CSD data
-	TUint32 iBlkLen;
-	TInt64 iBlkMsk;
-	TBool iReadBlPartial;
-	TUint32 iPrWtGpLen;							// preferred write group size in bytes,
-	TInt64 iPrWtGpMsk;
-
-	TInt iReadCurrentInMilliAmps;				// power management
-	TInt iWriteCurrentInMilliAmps;
-
-	TUint8* iMinorBuf;							// MBR, CMD42, partial read
-	TUint8* iCacheBuf;							// cached buffer
-	TUint32 iMaxBufSize;
-	TInt iBlocksInBuffer;
-	TInt64* iCachedBlocks;
-	TInt* iGamma;								// B lookup, ReserveReadBlocks()
-	TUint8* iIntBuf;							// start of current buffer region
-	TInt iLstUsdCchEnt;							// index of last used cache entry
-
-	TLocDrvRequest* iCurrentReq;				// Current Request
-	TMediaRequest iMedReq;
-	
-	TInt64 iReqStart;							// user-requested start region
-	TInt64 iReqCur;								// Currently requested start region
-	TInt64 iReqEnd;							    // user-requested end region
-	TInt64 iPhysStart;							// physical region for one operation
-	TInt64 iPhysEnd;						    // physical end point for one operation
-	TInt64 iDbEnd;								// Double buffer end point for one operation
-
-	TUint64 iEraseUnitMsk;
-
-	TUint iWtRBM;								// Write - Read Before Modify Flags
-	TUint iRdROB;								// Read  - Read Odd Blocks Flags
-	
-	TInt iFragOfset;			
-	TUint32 iIPCLen;
-	TUint32 iNxtIPCLen;
-	TUint32 iBufOfset;
-	
-	TUint iHiddenSectors;						// bootup / password
-
-	TMMCCallBack iSessionEndCallBack;
-	TDfc iSessionEndDfc;
-
-	TPartitionInfo* iPartitionInfo;
-	TMMCMediaTypeEnum iMediaType;
-	TMMCEraseInfo iEraseInfo;
-	TBool iMbrMissing;
-	TInt iMediaId;
-
-	DMMCStack::TDemandPagingInfo iDemandPagingInfo;
-
-#if defined(__TEST_PAGING_MEDIA_DRIVER__)
-	SMmcStats iMmcStats;
-#endif // __TEST_PAGING_MEDIA_DRIVER__
-
-	TMMCCallBack iDataTransferCallBack;	// Callback registered with the MMC stack to perform double-buffering
-	TDfc iDataTransferCallBackDfc;		// ...and the associated DFC queue.
-
-	TBool iSecondBuffer;				// Specified the currently active buffer
-	TBool iDoLastRMW;					// ETrue if the last double-buffer transfer requires RMW modification
-	TBool iDoDoubleBuffer;				// ETrue if double-buffering is currently active
-	TBool iDoPhysicalAddress;			// ETrue if Physical Addressing is currently active
-	TBool iCreateMbr;
-	TBool iReadToEndOfCard;				// {Read Only} ETrue if Reading to end of Card
-
-	TBool iInternalSlot;
-
-	DEMMCPartitionInfo* iMmcPartitionInfo;  // Responsible for decoding partitions for embedded devices
-	};
 	
 // ======== DPhysicalDeviceMediaMmcFlash ========
 
@@ -471,6 +240,10 @@
 	// NB aMedia Id = the media ID of the primary media, iMediaId = the media ID of this media
 	__KTRACE_OPT(KPBUSDRV, Kern::Printf("DMmcMediaDriverFlash(), iMediaId %d, aMediaId %d\n", iMediaId, aMediaId));
 	OstTraceExt2( TRACE_FLOW, DMMCMEDIADRIVERFLASH_DMMCMEDIADRIVERFLASH, "> DMmcMediaDriverFlash::DMmcMediaDriverFlash;aMediaId=%d;iMediaId=%d", (TInt) aMediaId, (TInt) iMediaId );
+	for(TInt drv = 0; drv < KMaxLocalDrives; drv++)
+		{
+		SetEMmcPartitionMapping(drv, TExtendedCSD::ESelectUserArea);
+		}
 	
 	}
 
@@ -540,12 +313,13 @@
 
 	iMinorBuf = buf;
 	
+	// reserve KRpmbOneFramePacketLength bytes after the minor buffer for RPMB requests / responses
 	// cache buffer can use rest of blocks in buffer.  Does not have to be power of 2.
-	iCacheBuf = iMinorBuf + minorBufLen;
+	iCacheBuf = iMinorBuf + minorBufLen + KRpmbOneFramePacketLength;
 
 	// We need to devide up the buffer space between the media drivers.
 	// The number of buffer sub-areas = number of physical card slots * number of media
-	bufLen-= minorBufLen;
+	bufLen-= (minorBufLen + KRpmbOneFramePacketLength);
 	DPBusPrimaryMedia* primaryMedia = (DPBusPrimaryMedia*) iPrimaryMedia;
 	TInt physicalCardSlots = iStack->iMaxCardsInStack;
 	TInt numMedia = primaryMedia->iLastMediaId - primaryMedia->iMediaId + 1;
@@ -1160,7 +934,8 @@
 				}
 
 			// Now, if the erase start/end points are aligned to a min. erase unit boundary, we can use an erase cmd.
-			if ((iPhysStart & minEraseSecMsk) == 0 && (iPhysEnd & minEraseSecMsk) == 0)
+			if ((iPhysStart & minEraseSecMsk) == 0 && (iPhysEnd & minEraseSecMsk) == 0 ||
+			      (iCurrentReq->Id() == DLocalDrive::EDeleteNotify && (iPhysStart - iPhysEnd) % KMMCardHighCapBlockSize == 0 )) // handle TRIM case where erase is aligned to 512 blocks
 				{
 				// Aligned erase
 				//  Check that erase commands are supported prior to issuing an erase command
@@ -1174,6 +949,10 @@
 					iSession->SetupCIMEraseMSector(I64LOW(iPhysStart >> KMMCardHighCapBlockSizeLog2),
 												   I64LOW((iPhysEnd - iPhysStart) >> KMMCardHighCapBlockSizeLog2)); // Use ACMD32/33/38 (Erase Sector)
 					}
+		        if(iCurrentReq->Id() == DLocalDrive::EDeleteNotify)   
+		            {
+		            iSession->Command().iFlags|= KMMCCmdFlagDeleteNotify;  //set flags for Trim
+		            }
 				}
 			else
 				{
@@ -1200,7 +979,7 @@
 			memset (iCacheBuf, 0x00, writeLen);
 			iSession->SetupCIMWriteBlock(I64LOW(iPhysStart >> KMMCardHighCapBlockSizeLog2), iCacheBuf, writeLen >> KMMCardHighCapBlockSizeLog2);
 			}
-		
+			
 		r = EngageAndSetWriteRequest(EMReqFormat);
 		}
 		OstTraceFunctionExitExt( DMMCMEDIADRIVERFLASH_LAUNCHFORMAT_EXIT, this, r );
@@ -2307,6 +2086,10 @@
 					{
 					iReqCur = iPhysEnd;
 					}
+				else if(iCurrentReq->Id() == DLocalDrive::EDeleteNotify) //handle DeleteNotify case
+				    {
+                    iReqCur = iPhysEnd;
+				    }
 				else
 					{
 					// Formating to a mis-aligned boundary, so we can't make best use of
@@ -2727,9 +2510,25 @@
 	iMedReq = aRequest;
 	SetCurrentConsumption(aCurrent);
 
+#ifdef EMMC_PARTITION_TEST_MODE_ENABLED
+	if((iSession->Partition() & TExtendedCSD::EPartitionTestMode) != 0)
+		{
+		// driver in test mode, target partition must be set by ControlIO() KMmcSwitchPartition
+		}
+	else
+#endif // EMMC_PARTITION_TEST_MODE_ENABLED	
+		if (iCurrentReq)
+			// if iCurrentReq is NULL then  it is assuned to be a request for a removable drive 
+			// multiple physical partitions are not supported on removable drives hence partition settting is not requied
+			{
+			TInt ptn = iCurrentReq->Drive()->iPartitionNumber;
+			TInt eMmcPtn = GetEMmcPartitionMapping(ptn);
+			iSession->SetPartition(eMmcPtn);
+			}
+	
 	// Reset the card pointer just in case the stack has changed it.
 	iSession->SetCard(iCard);
-
+		
 	TInt r = InCritical();
 	if (r == KErrNone)
 		{
@@ -2783,6 +2582,9 @@
 	aInfo.iConnectionBusType = EConnectionBusInternal;
 	aInfo.iDriveAtt = KDriveAttLocal;
 	aInfo.iMediaAtt	= KMediaAttFormattable;
+	   
+	if(iCard->ExtendedCSD().ExtendedCSDRev() >= 5 && KTRIMEnabled)   //TRIM support for v4.4+
+	   aInfo.iMediaAtt |= KMediaAttDeleteNotify;
 
 	if(iCard->iFlags & KMMCardIsLockable)
 		aInfo.iMediaAtt |= KMediaAttLockable;
@@ -2899,6 +2701,8 @@
 #if defined(__DEMAND_PAGING__) && !defined(__WINS__)
 	     || DMediaPagingDevice::PageInRequest(*iCurrentReq)
 #endif //DEMAND_PAGING 
+		// partition switching
+		|| (GetEMmcPartitionMapping(iCurrentReq->Drive()->iPartitionNumber) != iSession->Partition())
         )
 		{
 		*aAllDone = EFalse;
@@ -3745,6 +3549,12 @@
 				    }
 				r=DoWrite();
 				break;
+			case DLocalDrive::EDeleteNotify:
+			  if(iCard->ExtendedCSD().ExtendedCSDRev() <5)
+			      {
+			      r=KErrNotSupported;
+			      break;
+			      }
 			case DLocalDrive::EFormat:
 				if (readOnly)
 				    {
@@ -3908,6 +3718,13 @@
 				
 			break; 
 			}
+#ifdef EMMC_PARTITION_TEST_MODE_ENABLED			
+		case KMmcSwitchPartition:
+			__ASSERT_DEBUG(iSession != NULL, Panic(ECFSessPtrNull));
+			InvalidateCache();
+			iSession->SetPartition((TInt) aParam1);
+			break;
+#endif // EMMC_PARTITION_TEST_MODE_ENABLED
 		default:
 			r=KErrNotSupported;
 			break;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/medmmc.h	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,295 @@
+// Copyright (c) 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:
+// drivers/medmmc/medmmc.h
+//
+//
+
+#ifndef MEDMMC_H
+#define MEDMMC_H
+
+#include <drivers/locmedia.h>
+#include <e32const.h>
+
+#if defined(__DEMAND_PAGING__)
+	// If in debug mode, enable paging stats and their retrieval using DLocalDrive::EControlIO
+	#if defined( _DEBUG)
+		#define __TEST_PAGING_MEDIA_DRIVER__
+	#endif
+	#include "mmcdp.h"
+#endif
+
+// Enable this macro to debug cache: 
+// NB The greater the number of blocks, the slower this is...
+//#define _DEBUG_CACHE
+#ifdef _DEBUG_CACHE
+#define __ASSERT_CACHE(c,p) (void)((c)||(p,0))
+#else
+#define __ASSERT_CACHE(c,p)
+#endif
+
+const TInt KDiskSectorSize  = 512;
+const TInt KDiskSectorShift =   9;
+
+
+class DMmcMediaDriverFlash : public DMediaDriver
+	{
+public:
+	DMmcMediaDriverFlash(TInt aMediaId);
+	~DMmcMediaDriverFlash();
+	// ...from DMediaDriver
+	virtual void Close();
+	// replacing pure virtual
+	virtual void Disconnect(DLocalDrive* aLocalDrive, TThreadMessage*);
+	virtual TInt Request(TLocDrvRequest& aRequest);
+	virtual TInt PartitionInfo(TPartitionInfo& anInfo);
+	virtual void NotifyPowerDown();
+	virtual void NotifyEmergencyPowerDown();
+	// For creation by DPhysicalDeviceMediaMmcFlash
+	TInt DoCreate(TInt aMediaId);
+	
+		
+private:
+	enum TPanic
+		{
+		EDRInUse		= 0x0000,	EDRStart, EDRNotPositive, EDREnd,
+		ELRRequest		= 0x0010,	ELRStart, ELRNotPositive, ELREnd, ELRCached,
+		EDWInUse		= 0x0020,	EDWStart, EDWNotPositive, EDWEnd,
+		EDFInUse		= 0x0030,	EDFStart, EDFNotPositive, EDFEnd, ENotMmcSocket,
+		ELWRequest		= 0x0040,	ELWStart, ELWFmtStAlign, ELWNotPositive, ELWEnd, ELWFmtEndAlign, 
+									ELWLength, ELFStart, ELFEnd, ELFNotPositive,
+		ERPIInUse		= 0x0050,
+		EPCInUse		= 0x0060,	EPCFunc,
+		ESECBQueued		= 0x0070,
+		EDSEDRequest	= 0x0080,	EDSEDNotErrComplete,
+		ECRReqIdle		= 0x0090,	ECRRequest,
+		ERRBStAlign		= 0x00a0,	ERRBStPos, ERRBNotPositive, ERRBEndAlign, ERRBEndPos,
+									ERRBOverflow, ERRBCchInv, ERRBExist,
+		ERWBStPos		= 0x00b0,	ERWBNotPositive, ERWBEndPos, ERWBOverflow, ERWBCchInv,
+		EMBStPos		= 0x00c0,	EMBStAlign, EMBNotPositive, EMBEndPos, EMBEndAlign,
+									EMBOverflow, EMBCchInvPre, EMBCchInvPost,
+		EBGAStPos		= 0x00d0,	EBGAStAlign, EBGANotPositive, EBGAEndPos, EBGAEndAlign,
+									EBGAOverflow, EBGACchInv,
+		EICMNegative	= 0x00e0,	EICMOverflow, ECMIOverflow,
+		EGCBAlign		= 0x00f0,	EGCBPos, EGCBCchInv,
+		
+		ECFSessPtrNull	= 0x0100,	// Code Fault - session pointer NULL
+
+		EDBNotEven		= 0x0110,	// Not and even number of blocks in the buffer cache
+		EDBCBQueued		= 0x0111,	// The data transfer callback is already queued
+		EDBLength		= 0x0112,	// The length of data to transfer in data transfer callback is not positive
+		EDBLengthTooBig	= 0x0113,	// The length of data to transfer in data transfer callback is too big
+		EDBOffsetTooBig = 0x0114,	// The Offset into the user data buffer is too big
+		EDBCacheInvalid	= 0x0115,	// The cache is invalid at the end of data transfer
+		EDBNotOptimal	= 0x0116,	// Due to Cache size DB functionality will never be utilised
+		ENoDBSupport	= 0x0120,	// DMA request arrived but PSL does not support double buffering
+		ENotDMAAligned  = 0x0121,
+		EArrayBoundsExc = 0x0122	// Array bounds exceeded (either too small or too large)
+		};
+	static void Panic(TPanic aPnc);
+
+	enum TMediaRequest
+		{
+		EMReqRead = 0,
+		EMReqWrite = 1,
+		EMReqFormat = 2,
+		EMReqPtnInfo,
+		EMReqPswdCtrl,
+		EMReqForceErase,
+		EMReqUpdatePtnInfo,
+		EMReqWritePasswordData,
+		EMReqIdle,
+		EMReqEMMCPtnInfo,
+		};
+	enum TMediaReqType {EMReqTypeNormalRd,EMReqTypeNormalWr,EMReqTypeUnlockPswd,EMReqTypeChangePswd};
+
+	enum {KWtRBMFst = 0x00000001, 	// iWtRBM - Read First Block only
+		  KWtRBMLst = 0x00000002,	// iWtRBM - Read Last Block only
+		  KWtMinFst = 0x00000004,	// iWtRBM - Write First Block only
+		  KWtMinLst = 0x00000008,	// iWtRBM - Write Last Block only
+		  KIPCSetup = 0x00000010,	// iRdROB - IPC Setup Next Iteration
+		  KIPCWrite = 0x00000020};	// iRdROB - IPC Write Next Iteration
+
+public:
+	inline void SetEMmcPartitionMapping(TInt aLocalPtn, TInt aEMmcPtn) 
+		{
+		__ASSERT_DEBUG((aLocalPtn >= 0) && (aLocalPtn < KMaxLocalDrives), Kern::Fault("Mmc: Array bounds exception", __LINE__));
+		iEMmcPartitionMappings[aLocalPtn] = aEMmcPtn;
+		};
+	
+	inline TInt GetEMmcPartitionMapping(TInt aLocalPtn) const
+		{
+		__ASSERT_DEBUG((aLocalPtn >= 0) && (aLocalPtn < KMaxLocalDrives), Kern::Fault("Mmc: Array bounds exception", __LINE__));
+		return iEMmcPartitionMappings[aLocalPtn];
+		};
+
+
+private:
+	// MMC device specific stuff
+	TInt DoRead();
+	TInt DoWrite();
+	TInt DoFormat();
+	TInt Caps(TLocDrv& aDrive, TLocalDriveCapsV6& aInfo);
+
+	inline DMMCStack& Stack() const;
+	inline TInt CardNum() const;
+	inline TMediaRequest CurrentRequest() const;
+
+	TInt LaunchRead(TInt64 aStart, TUint32 aLength);
+	TInt LaunchDBRead();
+	TInt LaunchPhysRead(TInt64 aStart, TUint32 aLength);
+	
+	TInt LaunchWrite(TInt64 aStart, TUint32 aLength, TMediaRequest aMedReq);
+	TInt LaunchFormat(TInt64 aStart, TUint32 aLength);
+
+	TInt LaunchRPIUnlock(TLocalDrivePasswordData& aData);
+	TInt LaunchRPIRead();
+	TInt LaunchRPIErase();
+	TInt DecodePartitionInfo();
+	TInt WritePartitionInfo();
+	TInt GetDefaultPartitionInfo(TMBRPartitionEntry& aPartitionEntry);
+	TInt CreateDefaultPartition();
+
+
+#if defined __TEST_PAGING_MEDIA_DRIVER__
+	TInt HandleControlIORequest();
+#endif
+
+	static void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors);
+
+	TInt CheckDevice(TMediaReqType aReqType);
+
+	static void SessionEndCallBack(TAny* aMediaDriver);
+	static void SessionEndDfc(TAny* aMediaDriver);
+	void DoSessionEndDfc();
+
+	static void DataTransferCallBack(TAny* aMediaDriver);
+	static void DataTransferCallBackDfc(TAny* aMediaDriver);
+
+	void DoReadDataTransferCallBack();
+	void DoWriteDataTransferCallBack();
+	void DoPhysReadDataTransferCallBack();
+	void DoPhysWriteDataTransferCallBack();
+	
+	TInt AdjustPhysicalFragment(TPhysAddr &physAddr, TInt &physLength);
+	TInt PrepareFirstPhysicalFragment(TPhysAddr &aPhysAddr, TInt &aPhysLength, TUint32 aLength);
+	void PrepareNextPhysicalFragment();
+
+	TInt EngageAndSetReadRequest(TMediaRequest aRequest);
+	TInt EngageAndSetWriteRequest(TMediaRequest aRequest);
+	TInt EngageAndSetRequest(TMediaRequest aRequest, TInt aCurrent);
+	void CompleteRequest(TInt aReason);
+
+	TInt ReadDataUntilCacheExhausted(TBool* aAllDone);
+	TInt WriteDataToUser(TUint8* aBufPtr);
+	TInt ReadDataFromUser(TDes8& aDes, TInt aOffset);
+	TUint8* ReserveReadBlocks(TInt64 aStart, TInt64 aEnd, TUint32* aLength);
+	TUint8* ReserveWriteBlocks(TInt64 aMedStart, TInt64 aMedEnd, TUint* aRBM);
+	void MarkBlocks(TInt64 aStart, TInt64 aEnd, TInt aStartIndex);
+	void BuildGammaArray(TInt64 aStart, TInt64 aEnd);
+	void InvalidateCache();
+	void InvalidateCache(TInt64 aStart, TInt64 aEnd);
+	TUint8* IdxToCchMem(TInt aIdx) const;
+	TInt CchMemToIdx(TUint8* aMemP) const;
+
+	TInt DoPasswordOp();
+	void PasswordControl(TInt aFunc, TLocalDrivePasswordData& aData);
+	void Reset();
+	TInt AllocateSession();  
+
+#ifdef _DEBUG_CACHE
+	TBool CacheInvariant();
+	TUint8* GetCachedBlock(TInt64 aAddr);
+#endif
+private:
+	DMMCStack* iStack;			 				// controller objects
+	TMMCard* iCard;
+	DMMCSession* iSession;
+	DMMCSocket* iSocket;
+
+	TInt iCardNumber;
+
+	TUint iBlkLenLog2;							// cached CSD data
+	TUint32 iBlkLen;
+	TInt64 iBlkMsk;
+	TBool iReadBlPartial;
+	TUint32 iPrWtGpLen;							// preferred write group size in bytes,
+	TInt64 iPrWtGpMsk;
+
+	TInt iReadCurrentInMilliAmps;				// power management
+	TInt iWriteCurrentInMilliAmps;
+
+	TUint8* iMinorBuf;							// MBR, CMD42, partial read
+	TUint8* iCacheBuf;							// cached buffer
+	TUint32 iMaxBufSize;
+	TInt iBlocksInBuffer;
+	TInt64* iCachedBlocks;
+	TInt* iGamma;								// B lookup, ReserveReadBlocks()
+	TUint8* iIntBuf;							// start of current buffer region
+	TInt iLstUsdCchEnt;							// index of last used cache entry
+
+	TLocDrvRequest* iCurrentReq;				// Current Request
+	TMediaRequest iMedReq;
+	
+	TInt64 iReqStart;							// user-requested start region
+	TInt64 iReqCur;								// Currently requested start region
+	TInt64 iReqEnd;							    // user-requested end region
+	TInt64 iPhysStart;							// physical region for one operation
+	TInt64 iPhysEnd;						    // physical end point for one operation
+	TInt64 iDbEnd;								// Double buffer end point for one operation
+
+	TUint64 iEraseUnitMsk;
+
+	TUint iWtRBM;								// Write - Read Before Modify Flags
+	TUint iRdROB;								// Read  - Read Odd Blocks Flags
+	
+	TInt iFragOfset;			
+	TUint32 iIPCLen;
+	TUint32 iNxtIPCLen;
+	TUint32 iBufOfset;
+	
+	TUint iHiddenSectors;						// bootup / password
+
+	TMMCCallBack iSessionEndCallBack;
+	TDfc iSessionEndDfc;
+
+	TPartitionInfo* iPartitionInfo;
+	TMMCMediaTypeEnum iMediaType;
+	TMMCEraseInfo iEraseInfo;
+	TBool iMbrMissing;
+	TInt iMediaId;
+
+	DMMCStack::TDemandPagingInfo iDemandPagingInfo;
+
+#if defined(__TEST_PAGING_MEDIA_DRIVER__)
+	SMmcStats iMmcStats;
+#endif // __TEST_PAGING_MEDIA_DRIVER__
+
+	TMMCCallBack iDataTransferCallBack;	// Callback registered with the MMC stack to perform double-buffering
+	TDfc iDataTransferCallBackDfc;		// ...and the associated DFC queue.
+
+	TBool iSecondBuffer;				// Specified the currently active buffer
+	TBool iDoLastRMW;					// ETrue if the last double-buffer transfer requires RMW modification
+	TBool iDoDoubleBuffer;				// ETrue if double-buffering is currently active
+	TBool iDoPhysicalAddress;			// ETrue if Physical Addressing is currently active
+	TBool iCreateMbr;
+	TBool iReadToEndOfCard;				// {Read Only} ETrue if Reading to end of Card
+
+	TBool iInternalSlot;
+
+	DEMMCPartitionInfo* iMmcPartitionInfo;  // Responsible for decoding partitions for embedded devices
+	TInt iEMmcPartitionMappings[KMaxLocalDrives]; // holds the mapping of emmc partitions
+	};
+	
+#endif
+
--- a/kernel/eka/drivers/medmmc/medmmc.mmp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/medmmc/medmmc.mmp	Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1998-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"
@@ -28,13 +28,20 @@
 //Define this macro to create an MBR when formatting low-capacity MMC cards :
 //macro			SYMBIAN_CREATE_MBR_ON_LOW_CAPACITY_MMC
 
+// Define this macro to bypass automatic partition switching - in this case 
+// switching can also be done by HandleControlIORequest()
+// macro		EMMC_PARTITION_TEST_MODE_ENABLED
+
 source			medmmc.cpp
 source			mmcptn.cpp
+source			medmmcpatchdata.cpp
 
 library			epbusmmc.lib
 library			elocd.lib
 library			emmcptn.lib
 
+DEFFILE             	~/medmmc.def
+
 linkas			medmmc.pdd
 
 start wins
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/medmmcpatchdata.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,21 @@
+// Copyright (c) 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:
+// Media driver for MultiMediaCard Flash device, patchable constants
+// 
+//
+
+#include <e32def.h>
+
+// Patchable constant used to enable TRIM. The feature is enabled by default.
+EXPORT_C extern const TUint KTRIMEnabled = 1;
--- a/kernel/eka/drivers/medmmc/mmcdp.h	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/medmmc/mmcdp.h	Mon Oct 11 19:11:06 2010 +0100
@@ -21,7 +21,8 @@
 
 
 #ifdef __TEST_PAGING_MEDIA_DRIVER__
-const TInt KMmcGetStats	= 0x00000001;
+const TInt KMmcGetStats			= 0x00000001;
+const TInt KMmcSwitchPartition	= 0x00000002;
 struct SMmcStats
 	{
 	TInt iReqPage;
--- a/kernel/eka/drivers/pbus/mmc/epbusm.mmh	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/epbusm.mmh	Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1998-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"
@@ -37,6 +37,7 @@
 source				stackbody.cpp
 source				session.cpp
 source				mmccd_init.cpp
+source				rpmbstack.cpp
 
 library				elocd.lib
 
@@ -48,4 +49,4 @@
 
 uid 				0x1000008d 0x10004087
 
-capability			all
\ No newline at end of file
+capability			all
--- a/kernel/eka/drivers/pbus/mmc/mmccd_init.cpp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/mmccd_init.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1995-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"
@@ -17,8 +17,7 @@
 
 #include <drivers/mmccd_ifc.h>
 #include <drivers/pbusmedia.h>
-
-
+#include <drivers/mmc.h>
 
 
 /**
@@ -207,6 +206,10 @@
 		else
 			__KTRACE_OPT(KPBUS1,Kern::Printf("Socket %d not MMC card",i));
 		}
+
+	// set RpmbConfigRead to true and ensure that changes to RpmbConfigRead, NumberOfRpmbs 
+	// and TheRpmbs are flushed at the same time
+	__e32_atomic_store_ord32(&RpmbParmsPopulated, ETrue);
 		
 	__KTRACE_OPT(KPBUS1,Kern::Printf("<TMMCardControllerInterface::Create, ret %d",r));
 	return r;
@@ -230,8 +233,29 @@
 	if(pS == NULL)
 		return(KErrNoMemory);
 
-	TMMCMachineInfo mi;
-	pS->iStack->MachineInfo(mi);
+	// Retrieve RPMB specific information from the PSL layer
+	__KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Begin registering RPMB information from PSL layer"));
+	
+	TMMCMachineInfoV44 mi;
+    TMMCMachineInfoV44Pckg machineInfoPckg(mi);
+    pS->iStack->MachineInfo(machineInfoPckg);
+
+	// Register each slot marked as being RPMB capable
+	// Code won't write beyond the end of TheRpmbs[] because 4 slots are reserved 
+	// for each pbus socket and only 4 slots are processed for each socket
+	TInt rpmbSlots = (mi.iRpmbSlotCount <= 4) ? mi.iRpmbSlotCount : 4;
+
+	// if baseport set up so that iRpmbSlotList==NULL assert now
+	__ASSERT_ALWAYS((((rpmbSlots>0)&&(mi.iRpmbSlotList!=NULL))||(rpmbSlots==0)), Kern::Fault(__FILE__, __LINE__));
+	TInt i;
+	for ( i=0; i<rpmbSlots; i++)
+		{
+			TheRpmbs[NumberOfRpmbs].iSocketPtr = pS;
+			TheRpmbs[NumberOfRpmbs].iCardNumber = mi.iRpmbSlotList[i];
+			__KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: TheRpmbs[%d]: socketPtr %x: CardNumber %d", NumberOfRpmbs, pS, mi.iRpmbSlotList[i]));
+			NumberOfRpmbs++;
+		}
+	__KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Registering of RPMB information from PSL layer complete"));
 	
 	// There may be more than one physical card slot for this socket/stack;
 	// if this is the case, then we have to create a separate DPBusPrimaryMedia 
@@ -258,7 +282,7 @@
 #endif // __WINS__
 
 
-	for (TInt i=0; i<physicalCardSlots ; i++)	
+	for (i=0; i<physicalCardSlots ; i++)	
 		{
 		DPBusPrimaryMedia* pMedia = new DPBusPrimaryMedia(pS);
 		if (pMedia == NULL)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/pbus/mmc/rpmbstack.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,356 @@
+// Copyright (c) 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:
+//
+
+/**
+ @file
+ @internalComponent
+ @prototype
+*/
+
+#include <drivers/mmc.h>
+#include <drivers/rpmbpacket.h>
+
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "../../../include/drivers/locmedia_ost.h"
+#ifdef __VC32__
+#pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
+#endif
+#include "rpmbstackTraces.h"
+#endif
+
+TMMCErr DMMCStack::CIMRpmbAccessSM()
+    {
+enum TStates
+        {
+        EStBegin,
+        EStEnd
+        };
+
+    DMMCSession& s=Session();
+
+    //Extract the RPMB request type from the command. JEDEC specify this to be situated
+    //at offset 0 in the packet. When accessing the hardware, this is reversed and is 
+    //at offset 511
+	TUint8 requestType = * (s.Command().iDataMemoryP + KRpmbRequestLsbOffset);
+	
+	//There are 5 possible rpmb request types that can be passed through the state machines:
+	//
+	//Authentication Key programming request:     KRpmbRequestWriteKey = 0x001
+	//Reading of the write counter value request: KRpmbRequestReadWriteCounter = 0x0002;
+	//Authenticated data write request:           KRpmbRequestWriteData = 0x0003;
+	//Authenticated data read request:            KRpmbRequestReadData = 0x0004;
+	//Result read request:                        KRpmbRequestReadResultRegister = 0x0005;
+	//
+
+	SMF_BEGIN
+	
+    switch (requestType)
+        {
+        case KRpmbRequestWriteKey:
+			SMF_INVOKES(CIMRpmbWriteAuthenticationKeySMST, EStEnd);
+        case KRpmbRequestReadWriteCounter:
+			SMF_INVOKES(CIMRpmbReadWrCounterSMST, EStEnd);
+        case KRpmbRequestWriteData:
+			SMF_INVOKES(CIMRpmbWriteSMST, EStEnd);
+        case KRpmbRequestReadData:
+ 			SMF_INVOKES(CIMRpmbReadSMST, EStEnd);
+        default:
+            break;   
+        }
+
+    SMF_END
+}
+
+
+TMMCErr DMMCStack::CIMRpmbWriteAuthenticationKeySM()
+    {
+    enum TStates
+        {
+        EStBegin,   // Write key request
+        EStSetupReadRequest,
+        EStReadResult,
+        EStError,
+        EStEnd
+        };
+
+    DMMCSession& s=Session();
+
+	SMF_BEGIN
+
+        //
+        // Setup write request
+        // CMD23 Reliable Write = 1 Block Count = 1
+        // CMD25
+        // 
+        s.SetupRpmbSendRequest(ETrue);
+		//
+        // KMMCErrByPass is routinely thrown in the ReadWriteBlocks state machine. 
+        // It is thrown to indicate that the current command in the state machine is not CMD42(lock/unlock)
+        // We need to trap this error here to stop the RPMB state machines from unravelling and passing
+        // the error upwards. 
+        //	
+		m.SetTraps(KMMCErrBypass);
+		
+		OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM1, "RPMB: Write Key State Machine - send write key request packet");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - send write key request packet"));
+        
+        SMF_INVOKES(CIMReadWriteBlocksSMST, EStSetupReadRequest);
+
+    SMF_STATE(EStSetupReadRequest)
+
+        OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM2, "RPMB: Write Key State Machine - sent write key request packet");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - sent write key request packet"));
+    
+		if (err != KMMCErrNone)
+			{
+		    OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM3, "RPMB: Write Key State Machine - sent write key request packet error = %d", err);
+		    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - sent write key request packet error = %d", err));
+			SMF_GOTOS(EStError);
+			}
+		// 
+        // Setup read result register request
+        // CMD23 Reliable Write = 0 Block Count = 1
+        // CMD25
+        //
+		s.SetupRpmbSendReadResultRegisterRequest();
+		OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM4, "RPMB: Write Key State Machine - send read result register request packet");
+		__KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - send read result register request packet"));
+        SMF_INVOKES(CIMReadWriteBlocksSMST, EStReadResult)
+
+    SMF_STATE(EStReadResult)
+
+        OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM5, "RPMB: Write Key State Machine - sent read result register request packet");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - sent read result register request packet"));
+
+        if (err != KMMCErrNone)
+            {
+            OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM6, "RPMB: Write Key State Machine - sent read result register request packet error = %d", err);
+            __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - sent read result register request packet error = %d", err));
+            SMF_GOTOS(EStError);
+            }
+        //
+        // Setup read response
+        // CMD23 Reliable Write = 0 Block Count = 1
+        // CMD18
+        //        
+        s.SetupRpmbReceiveResponse();
+        OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM7, "RPMB: Write Key State Machine - get read packet");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - get read packet"));
+        SMF_INVOKES(CIMReadWriteBlocksSMST, EStEnd);
+
+    SMF_STATE(EStError)
+        SMF_RETURN(err);
+
+    SMF_END
+    }
+
+
+TMMCErr DMMCStack::CIMRpmbReadWrCounterSM()
+    {
+    enum TStates
+        {
+        EStBegin,   // Read counter request
+        EStReadResult,
+        EStError,
+        EStEnd
+        };
+
+    DMMCSession& s=Session();
+
+	SMF_BEGIN
+	
+        //
+        // Setup write request
+        // CMD23 Reliable Write = 0 Block Count = 1
+        // CMD25
+        // 
+        s.SetupRpmbSendRequest(EFalse);
+        m.SetTraps(KMMCErrBypass);
+        
+        OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADWRCOUNTERSM1, "RPMB: Read Write Counter State Machine - send read counter request packet");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read Write Counter State Machine - send read counter request packet"));
+ 
+        SMF_INVOKES(CIMReadWriteBlocksSMST, EStReadResult)
+
+    SMF_STATE(EStReadResult)
+
+        OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADWRCOUNTERSM2, "RPMB: Read Write Counter State Machine - sent read counter request packet");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read Write Counter State Machine - sent read counter request packet"));
+
+        if (err != KMMCErrNone)
+            {
+            OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBREADWRCOUNTERSM3, "RPMB: Read Write Counter State Machine - sent read counter request packet error = %d", err);
+            __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read Write Counter State Machine - sent read counter request packet error = %d", err));
+            SMF_GOTOS(EStError);
+            }
+        //
+        // Setup read response
+        // CMD23 Reliable Write = 0 Block Count = 1
+        // CMD18
+        //        
+        s.SetupRpmbReceiveResponse();
+        OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADWRCOUNTERSM4, "RPMB: Read Write Counter State Machine - get read packet");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read Write Counter State Machine - get read packet"));
+       SMF_INVOKES(CIMReadWriteBlocksSMST, EStEnd);
+
+    SMF_STATE(EStError)
+        SMF_RETURN(err);
+
+    SMF_END
+    }
+
+
+TMMCErr DMMCStack::CIMRpmbWriteSM()
+    {
+    enum TStates
+        {
+        EStBegin,   // Write data request
+        EStSetupReadRequest,
+        EStReadResult,
+        EStError,
+        EStEnd
+        };
+
+    DMMCSession& s=Session();
+
+	SMF_BEGIN
+
+        //
+        // Setup write request
+        // CMD23 Reliable Write = 1 Block Count = 1
+        // CMD25
+        // 
+        s.SetupRpmbSendRequest(ETrue);
+	    m.SetTraps(KMMCErrBypass);
+	    
+	    OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM1, "RPMB: Write State Machine - send write request packet");
+	    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - send write request packet"));
+
+	    SMF_INVOKES(CIMReadWriteBlocksSMST, EStSetupReadRequest);
+
+    SMF_STATE(EStSetupReadRequest)
+	    
+	    OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM2, "RPMB: Write State Machine - sent write request packet");
+	    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - sent write request packet"));
+
+		if (err != KMMCErrNone)
+			{
+		    OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM3, "RPMB: Write State Machine - sent write request packet error = %d", err);
+		    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - sent write request packet error = %d", err));
+			SMF_GOTOS(EStError);
+			}	
+        // 
+        // Setup read result register request
+        // CMD23 Reliable Write = 0 Block Count = 1
+        // CMD25
+        //
+        s.SetupRpmbSendReadResultRegisterRequest();
+        OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM4, "RPMB: Write State Machine - send read result register request packet");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - send read result register request packet"));
+        SMF_INVOKES(CIMReadWriteBlocksSMST, EStReadResult)
+
+    SMF_STATE(EStReadResult)
+        
+        OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM5, "RPMB: Write State Machine - sent read result register request packet");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - sent read result register request packet"));
+
+        if (err != KMMCErrNone)
+            {
+            OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM6, "RPMB: Write State Machine - sent read result register request packet error = %d", err);
+            __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - sent read result register request packet error = %d", err));
+            SMF_GOTOS(EStError);
+            }
+        //
+        // Setup read response
+        // CMD23 Reliable Write = 0 Block Count = 1
+        // CMD18
+        //        
+        s.SetupRpmbReceiveResponse();
+        OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM7, "RPMB: Write State Machine - get read packet");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - get read packet"));
+        SMF_INVOKES(CIMReadWriteBlocksSMST, EStEnd);
+
+    SMF_STATE(EStError)
+       SMF_RETURN(err);
+
+    SMF_END
+    }
+
+
+TMMCErr DMMCStack::CIMRpmbReadSM()
+    {
+    enum TStates
+        {
+        EStBegin,   // Read data request
+        EStReadResult,
+        EStError,
+        EStEnd
+        };
+
+    DMMCSession& s=Session();
+
+    SMF_BEGIN
+         
+        //
+        // Setup write request
+        // CMD23 Reliable Write = 0 Block Count = 1
+        // CMD25
+        // 
+        s.SetupRpmbSendRequest(EFalse);
+        m.SetTraps(KMMCErrBypass);
+        
+        OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADSM1, "RPMB: Read State Machine - send read request packet");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read State Machine - send read request packet"));
+
+		SMF_INVOKES(CIMReadWriteBlocksSMST, EStReadResult)
+
+    SMF_STATE(EStReadResult)
+        
+        OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADSM2, "RPMB: Read State Machine - sent read request packet");
+		__KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read State Machine - sent read request packet"));
+		
+		if (err != KMMCErrNone)
+           {
+           OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBREADSM3, "RPMB: Read State Machine - sent read request packet error = %d", err);
+           __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read State Machine - sent read request packet error = %d", err));
+           SMF_GOTOS(EStError);
+           }
+        //
+        // Setup read response
+        // CMD23 Reliable Write = 0 Block Count = 1
+        // CMD18
+        //        
+		s.SetupRpmbReceiveResponse();
+		OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADSM4, "RPMB: Read State Machine - get read packet");
+		__KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read State Machine - get read packet"));
+		SMF_INVOKES(CIMReadWriteBlocksSMST, EStEnd);
+
+    SMF_STATE(EStError)
+        SMF_RETURN(err);
+
+    SMF_END
+    }
+
+TMMCErr DMMCStack::CIMRpmbAccessSMST(TAny* aStackP)
+	{return(static_cast<DMMCStack*>(aStackP)->CIMRpmbAccessSM());}
+TMMCErr DMMCStack::CIMRpmbWriteAuthenticationKeySMST(TAny* aStackP)
+	{return(static_cast<DMMCStack*>(aStackP)->CIMRpmbWriteAuthenticationKeySM());}
+TMMCErr DMMCStack::CIMRpmbReadWrCounterSMST(TAny* aStackP)
+	{return(static_cast<DMMCStack*>(aStackP)->CIMRpmbReadWrCounterSM());}
+TMMCErr DMMCStack::CIMRpmbWriteSMST(TAny* aStackP)
+	{return(static_cast<DMMCStack*>(aStackP)->CIMRpmbWriteSM());}
+TMMCErr DMMCStack::CIMRpmbReadSMST(TAny* aStackP)
+	{return(static_cast<DMMCStack*>(aStackP)->CIMRpmbReadSM());}
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bmarm/sdcard3c/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bmarm/sdcard3c/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
 	InitStackAfterUnlockSM__9DMMCStack @ 94 NONAME ; DMMCStack::InitStackAfterUnlockSM(void)
 	RegisterMediaDevices__26TMMCardControllerInterfacei @ 95 NONAME ; TMMCardControllerInterface::RegisterMediaDevices(int)
 	ModifyCardCapabilitySM__9DMMCStack @ 96 NONAME R3UNUSED ; DMMCStack::ModifyCardCapabilitySM(void)
-	Dummy1__9DMMCStack @ 97 NONAME R3UNUSED ; DMMCStack::Dummy1(void)
+	MMCGetExtInterface__F18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 97 NONAME
 	GetInterface__9DMMCStackQ29DMMCStack12TInterfaceIdRPQ29DMMCStack10MInterface @ 98 NONAME R3UNUSED ; DMMCStack::GetInterface(DMMCStack::TInterfaceId, DMMCStack::MInterface *&)
 	MachineInfo__9DMMCStackR5TDes8 @ 99 NONAME R3UNUSED ; DMMCStack::MachineInfo(TDes8 &)
 	SetBusWidth__9DMMCStackUl @ 100 NONAME R3UNUSED ; DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bmarm/sdcard3c/sdio/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bmarm/sdcard3c/sdio/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
 	InitStackAfterUnlockSM__9DMMCStack @ 94 NONAME ; DMMCStack::InitStackAfterUnlockSM(void)
 	RegisterMediaDevices__26TMMCardControllerInterfacei @ 95 NONAME ; TMMCardControllerInterface::RegisterMediaDevices(int)
 	ModifyCardCapabilitySM__9DMMCStack @ 96 NONAME R3UNUSED ; DMMCStack::ModifyCardCapabilitySM(void)
-	Dummy1__9DMMCStack @ 97 NONAME R3UNUSED ; DMMCStack::Dummy1(void)
+	MMCGetExtInterface__F18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 97 NONAME
 	GetInterface__9DMMCStackQ29DMMCStack12TInterfaceIdRPQ29DMMCStack10MInterface @ 98 NONAME R3UNUSED ; DMMCStack::GetInterface(DMMCStack::TInterfaceId, DMMCStack::MInterface *&)
 	MachineInfo__9DMMCStackR5TDes8 @ 99 NONAME R3UNUSED ; DMMCStack::MachineInfo(TDes8 &)
 	SetBusWidth__9DMMCStackUl @ 100 NONAME R3UNUSED ; DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bwins/sdcard3c/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bwins/sdcard3c/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
 	?InitStackAfterUnlockSM@DMMCStack@@MAEKXZ @ 94 NONAME ; protected: virtual unsigned long __thiscall DMMCStack::InitStackAfterUnlockSM(void)
 	?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 95 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
 	?ModifyCardCapabilitySM@DMMCStack@@MAEKXZ @ 96 NONAME ; unsigned long DMMCStack::ModifyCardCapabilitySM(void)
-	?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; void DMMCStack::Dummy1(void)
+	?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME ; int MMCGetExtInterface(enum TMMCExtInterfaceId, class MMCMExtInterface * &, void *)
 	?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
 	?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99 NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
 	?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bwins/sdcard3c/sdio/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bwins/sdcard3c/sdio/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
 	?InitStackAfterUnlockSM@DMMCStack@@MAEKXZ @ 94 NONAME ; protected: virtual unsigned long __thiscall DMMCStack::InitStackAfterUnlockSM(void)
 	?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 95 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
 	?ModifyCardCapabilitySM@DMMCStack@@MAEKXZ @ 96 NONAME ; unsigned long DMMCStack::ModifyCardCapabilitySM(void)
-	?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; void DMMCStack::Dummy1(void)
+	?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME ; int MMCGetExtInterface(enum TMMCExtInterfaceId, class MMCMExtInterface * &, void *)
 	?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
 	?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99 NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
 	?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bx86/sdcard3c/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bx86/sdcard3c/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
 	?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 94 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
 	?RequestAsyncPowerDown@DPBusSocket@@QAEXXZ @ 95 NONAME ; public: void __thiscall DPBusSocket::RequestAsyncPowerDown(void)
 	?ControlIO@DPBusSocket@@UAEHHPAX0@Z @ 96 NONAME ; public: virtual int __thiscall DPBusSocket::ControlIO(int,void *,void *)
-	?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; private: virtual void __thiscall DMMCStack::Dummy1(void)
+	?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME
 	?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
 	?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99 NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
 	?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bx86/sdcard3c/sdio/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bx86/sdcard3c/sdio/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
 	?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 94 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
 	?RequestAsyncPowerDown@DPBusSocket@@QAEXXZ @ 95 NONAME ; public: void __thiscall DPBusSocket::RequestAsyncPowerDown(void)
 	?ControlIO@DPBusSocket@@UAEHHPAX0@Z @ 96 NONAME ; public: virtual int __thiscall DPBusSocket::ControlIO(int,void *,void *)
-	?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; private: virtual void __thiscall DMMCStack::Dummy1(void)
+	?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME
 	?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
 	?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99 NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
 	?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -120,7 +120,7 @@
 	_ZTV7DMMCPsu @ 119 NONAME ; vtable for DMMCPsu
 	_ZTV9DMMCStack @ 120 NONAME ; vtable for DMMCStack
 	_ZN9DMMCStack22ModifyCardCapabilitySMEv @ 121 NONAME ; DMMCStack::ModifyCardCapabilitySM()
-	_ZN9DMMCStack6Dummy1Ev @ 122 NONAME
+	_Z18MMCGetExtInterface18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 122 NONAME
 	_ZN9DMMCStack12GetInterfaceENS_12TInterfaceIdERPNS_10MInterfaceE @ 123 NONAME
 	_ZN9DMMCStack11MachineInfoER5TDes8 @ 124 NONAME
 	_ZN9DMMCStack11SetBusWidthEm @ 125 NONAME
--- a/kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/sdio/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/sdio/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -120,7 +120,7 @@
 	_ZTV7DMMCPsu @ 119 NONAME ; vtable for DMMCPsu
 	_ZTV9DMMCStack @ 120 NONAME ; vtable for DMMCStack
 	_ZN9DMMCStack22ModifyCardCapabilitySMEv @ 121 NONAME ; DMMCStack::ModifyCardCapabilitySM()
-	_ZN9DMMCStack6Dummy1Ev @ 122 NONAME
+	_Z18MMCGetExtInterface18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 122 NONAME
 	_ZN9DMMCStack12GetInterfaceENS_12TInterfaceIdERPNS_10MInterfaceE @ 123 NONAME
 	_ZN9DMMCStack11MachineInfoER5TDes8 @ 124 NONAME
 	_ZN9DMMCStack11SetBusWidthEm @ 125 NONAME
--- a/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdcard.cpp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdcard.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -1482,8 +1482,8 @@
 	SMF_STATE(EstCheckController) 	
         OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM2, "EstCheckController");
 	  	// Get the clock speed supported by the controller
-		TMMCMachineInfoV4 machineInfo;
-		TMMCMachineInfoV4Pckg machineInfoPckg(machineInfo);
+		TMMCMachineInfoV44 machineInfo;
+		TMMCMachineInfoV44Pckg machineInfoPckg(machineInfo);
 		MachineInfo(machineInfoPckg);
 		
 		if (machineInfo.iVersion >= TMMCMachineInfoV4::EVersion4)
--- a/kernel/eka/drivers/pbus/mmc/session.cpp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/session.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -36,6 +36,7 @@
  * @param aCallBack reference to a TMMCCallback object to be called upon completion.
  */
 	: iCallBack(aCallBack),
+	iPartition(TExtendedCSD::ESelectUserArea), // UDA is the hardware default
 #ifdef __EPOC32__
 	iPollTimer(DMMCSession::PollTimerCallBack, this),
 	iRetryTimer(DMMCSession::RetryTimerCallBack, this),
@@ -419,7 +420,8 @@
 		DMMCStack::NoSessionSMST,					// CIMLockStack is never really executed as a session
 		DMMCStack::InitStackAfterUnlockSMST,
 		DMMCStack::CIMAutoUnlockSMST,
-		DMMCStack::ExecSleepCommandSMST				// CIMSleep
+		DMMCStack::ExecSleepCommandSMST,			// CIMSleep
+		DMMCStack::CIMRpmbAccessSMST				// CIMRpmbAccess
 		};
 
 	if (aSessNum >= 0 && aSessNum < (TInt) KMMCMaxSessionTypeNumber)
--- a/kernel/eka/drivers/pbus/mmc/stack.cpp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/stack.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -20,6 +20,23 @@
 #include <drivers/locmedia.h>
 #include "stackbody.h"
 
+/*
+ Global helper object shared by all stacks to hold device specific RPMB information
+ */
+ static MRpmbInfo rpmbInfo;
+
+/*
+ Global counter for number or RPMB partitions. Only one partition per device
+*/
+
+GLDEF_D TUint NumberOfRpmbs = 0;
+/*
+ Global holder for RPMB parameters
+ */
+GLDEF_D TRpmbDeviceParms TheRpmbs[KMaxPBusSockets*4];
+
+GLDEF_D TBool RpmbParmsPopulated = EFalse;
+
 #include "OstTraceDefinitions.h"
 #ifdef OST_TRACE_COMPILER_IN_USE
 #include "../../../include/drivers/locmedia_ost.h"
@@ -3007,6 +3024,79 @@
 	}
 
 
+TMMCErr DMMCStack::SwitchPartitionSM()
+/**
+ * This SM function must be invoked before execution of any partition-specific command.
+ *
+ * @return MMC error code
+ */
+	{
+	__KTRACE_OPT(KPBUS1,Kern::Printf("=mst:sp"));
+
+		enum states
+			{
+			EStBegin=0,
+			EStPartitionSelected,
+			EStEnd
+			};
+
+		DMMCSession& s=Session();
+		OstTrace1( TRACE_INTERNALS, DMMCSTACK_SWITCHPARTITIONSM1, "Current session=0x%x", &s );
+
+	SMF_BEGIN
+
+		OstTrace0( TRACE_INTERNALS, DMMCSTACK_SWITCHPARTITIONSM2, "EStBegin" );
+
+		TMMCard *cardP = s.CardP();
+		if(cardP)
+			{
+			TInt curPtn = cardP->ExtendedCSD().BootConfig() & KMMCSelectPartitionMask;
+			TInt tgtPtn = s.Partition() & KMMCSelectPartitionMask;
+
+	 		if(curPtn != tgtPtn)
+	 			{
+				OstTraceExt2( TRACE_INTERNALS, DMMCSTACK_SWITCHPARTITIONSM3,
+					"EStSelectPartition: Switching partitions from 0x%02X to 0x%02X", 
+					(TUint32) curPtn, (TUint32) tgtPtn);
+					
+				// need to preserve the non-partition related bits
+				tgtPtn |= cardP->ExtendedCSD().BootConfig() & ~KMMCSelectPartitionMask;
+	
+	 			TMMCArgument arg = TExtendedCSD::GetWriteArg(
+	 				TExtendedCSD::EWriteByte, TExtendedCSD::EBootConfigIndex, tgtPtn, 0);
+	 				
+	 			CurrentSessPushCmdStack();	
+	 			s.FillCommandDesc(ECmdSwitch, arg);
+	 			SMF_INVOKES(ExecSwitchCommandST, EStPartitionSelected)
+				}
+ 			}
+ 			
+ 		// no switching required
+		SMF_GOTOS( EStEnd )
+
+ 	SMF_STATE(EStPartitionSelected)
+ 	
+		OstTrace0( TRACE_INTERNALS, DMMCSTACK_SWITCHPARTITIONSM4, "EStPartitionSelected" );
+		const TMMCStatus status(s.ResponseP());
+		CurrentSessPopCmdStack();
+		if (status.Error())
+			{
+            OstTraceFunctionExitExt( DMMCSTACK_SWITCHPARTITIONSM_EXIT1, this, (TInt) KMMCErrStatus );
+			return KMMCErrStatus;
+			}
+		else
+			{ // update extended CSD
+			TInt ptn = (s.CardP()->ExtendedCSD().BootConfig() & ~KMMCSelectPartitionMask) | (s.Partition() & KMMCSelectPartitionMask);
+			memset( s.CardP()->iExtendedCSD.Ptr() + TExtendedCSD::EBootConfigIndex, ptn, 1);
+			OstTrace1( TRACE_INTERNALS, DMMCSTACK_SWITCHPARTITIONSM5, 
+				"EStPartitionSelected: Switched to partition 0x%02X", ptn );
+			}
+		
+	SMF_END
+		
+	}
+
+
 inline TMMCErr DMMCStack::AttachCardSM()
 /**
  * This SM function must be invoked by every session which is CardControlled.
@@ -3045,7 +3135,6 @@
 			s.SynchBlock( KMMCBlockOnCardInUse );
 			SMF_WAIT
 			}
-
 		if( s.iCardP->IsPresent() && s.iCardP->iCID == s.iCID )
 			s.iCardP->iUsingSessionP = &s;
 		else
@@ -3070,6 +3159,7 @@
 
 	SMF_STATE(EStAttStatus)
 
+
 		OstTrace0( TRACE_INTERNALS, DMMCSTACK_ATTACHCARDSM3, "EStAttStatus" );
 		CurrentSessPopCmdStack();
 		OstTraceFunctionExitExt( DMMCSTACK_ATTACHCARDSM_EXIT3, this, (TInt) err );
@@ -3357,53 +3447,101 @@
 			SMF_GOTOS(EStExit);
 			}
 
+
+
 		memcpy(s.CardP()->iExtendedCSD.Ptr(), iPSLBuf, KMMCExtendedCSDLength);
 
+
+
 		// Call a licencee-specific state machine to allow the Extended CSD register to be modified.
 		SMF_INVOKES( ModifyCardCapabilitySMST, EStGotModifiedExtendedCSD )
 
 	SMF_STATE(EStGotModifiedExtendedCSD)
 
 		OstTrace0( TRACE_INTERNALS, DMMCSTACK_INITSTACKAFTERUNLOCKSM7, "EStGotExtendedCSD" );
+
+        const TExtendedCSD& extendedCSD = s.CardP()->ExtendedCSD();
 	
 		__KTRACE_OPT(KPBUS1, Kern::Printf("Extended CSD"));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("CSDStructureVer:            %u", s.CardP()->ExtendedCSD().CSDStructureVer()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("ExtendedCSDRev:             %u", s.CardP()->ExtendedCSD().ExtendedCSDRev()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("CSDStructureVer:            %u", extendedCSD.CSDStructureVer()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("ExtendedCSDRev:             %u", extendedCSD.ExtendedCSDRev()));
 		__KTRACE_OPT(KPBUS1, Kern::Printf("-------------------------------"));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("SupportedCmdSet:            %u", s.CardP()->ExtendedCSD().SupportedCmdSet()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass26Mhz360V:        0x%02X", s.CardP()->ExtendedCSD().PowerClass26Mhz360V()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass52Mhz360V:        0x%02X", s.CardP()->ExtendedCSD().PowerClass52Mhz360V()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass26Mhz195V:        0x%02X", s.CardP()->ExtendedCSD().PowerClass26Mhz195V()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass52Mhz195V:        0x%02X", s.CardP()->ExtendedCSD().PowerClass52Mhz195V()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("CardType:                   %u", s.CardP()->ExtendedCSD().CardType()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("CmdSet:                     %u", s.CardP()->ExtendedCSD().CmdSet()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("CmdSetRev:                  %u", s.CardP()->ExtendedCSD().CmdSetRev()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass:                 %u", s.CardP()->ExtendedCSD().PowerClass()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("HighSpeedTiming:            %u", s.CardP()->ExtendedCSD().HighSpeedTiming()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("HighCapacityEraseGroupSize: %u", s.CardP()->ExtendedCSD().HighCapacityEraseGroupSize()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("AccessSize:                 %u", s.CardP()->ExtendedCSD().AccessSize()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("BootInfo:                   %u", s.CardP()->ExtendedCSD().BootInfo() ));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("BootSizeMultiple:           %u", s.CardP()->ExtendedCSD().BootSizeMultiple() ));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("EraseTimeoutMultiple:       %u", s.CardP()->ExtendedCSD().EraseTimeoutMultiple() ));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("ReliableWriteSector:        %u", s.CardP()->ExtendedCSD().ReliableWriteSector() ));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("HighCapWriteProtGroupSize:  %u", s.CardP()->ExtendedCSD().HighCapacityWriteProtectGroupSize() ));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("SleepCurrentVcc:            %u", s.CardP()->ExtendedCSD().SleepCurrentVcc() ));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("SleepCurrentVccQ:           %u", s.CardP()->ExtendedCSD().SleepCurrentVccQ()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("SleepAwakeTimeout:          %u", s.CardP()->ExtendedCSD().SleepAwakeTimeout()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("BootConfig:                 %u", s.CardP()->ExtendedCSD().BootConfig()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("BootBusWidth:               %u", s.CardP()->ExtendedCSD().BootBusWidth()));
-		__KTRACE_OPT(KPBUS1, Kern::Printf("EraseGroupDef:              %u", s.CardP()->ExtendedCSD().EraseGroupDef()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("SupportedCmdSet:            %u", extendedCSD.SupportedCmdSet()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass26Mhz360V:        0x%02X", extendedCSD.PowerClass26Mhz360V()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass52Mhz360V:        0x%02X", extendedCSD.PowerClass52Mhz360V()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass26Mhz195V:        0x%02X", extendedCSD.PowerClass26Mhz195V()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass52Mhz195V:        0x%02X", extendedCSD.PowerClass52Mhz195V()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("CardType:                   %u", extendedCSD.CardType()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("CmdSet:                     %u", extendedCSD.CmdSet()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("CmdSetRev:                  %u", extendedCSD.CmdSetRev()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass:                 %u", extendedCSD.PowerClass()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("HighSpeedTiming:            %u", extendedCSD.HighSpeedTiming()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("HighCapacityEraseGroupSize: %u", extendedCSD.HighCapacityEraseGroupSize()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("AccessSize:                 %u", extendedCSD.AccessSize()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("BootInfo:                   %u", extendedCSD.BootInfo() ));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("BootSizeMultiple:           %u", extendedCSD.BootSizeMultiple() ));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("EraseTimeoutMultiple:       %u", extendedCSD.EraseTimeoutMultiple() ));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("ReliableWriteSector:        %u", extendedCSD.ReliableWriteSector() ));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("HighCapWriteProtGroupSize:  %u", extendedCSD.HighCapacityWriteProtectGroupSize() ));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("SleepCurrentVcc:            %u", extendedCSD.SleepCurrentVcc() ));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("SleepCurrentVccQ:           %u", extendedCSD.SleepCurrentVccQ()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("SleepAwakeTimeout:          %u", extendedCSD.SleepAwakeTimeout()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("BootConfig:                 %u", extendedCSD.BootConfig()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("BootBusWidth:               %u", extendedCSD.BootBusWidth()));
+		__KTRACE_OPT(KPBUS1, Kern::Printf("EraseGroupDef:              %u", extendedCSD.EraseGroupDef()));
+
+        // 4.4 extensions
+		__KTRACE_OPT(KPBUS1, Kern::Printf("ErasedMemoryContent:        0x%02X", extendedCSD.ErasedMemoryContent()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("BootConfigProtection:       0x%02X", extendedCSD.BootConfigProt()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("BootAreaWriteProtectionReg: 0x%02X", extendedCSD.BootAreaWriteProtectionReg()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("UserAreaWriteProtectionReg: 0x%02X", extendedCSD.UserAreaWriteProtectionReg()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("FWConfiguration:            0x%02X", extendedCSD.FwConfiguration()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMBSize:                   0x%04X", extendedCSD.RpmbSize()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("HwResetFunction:            0x%02X", extendedCSD.HwResetFunction()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("PartitioningSupport:        0x%02X", extendedCSD.PartitioningSupport()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("MaxEnhancedAreaSize:        0x%04X", extendedCSD.MaxEnhancedAreaSize()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("PartitionsAttribute:        0x%02X", extendedCSD.PartitionsAttribute()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("PartitioningSetting:        0x%02X", extendedCSD.PartitioningSetting()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("GPP1:                       0x%04X", extendedCSD.GeneralPurposePartition1Size()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("GPP2:                       0x%04X", extendedCSD.GeneralPurposePartition2Size()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("GPP3:                       0x%04X", extendedCSD.GeneralPurposePartition3Size()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("GPP4:                       0x%04X", extendedCSD.GeneralPurposePartition4Size()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("EnhancedUserDataSize:       0x%04X", extendedCSD.EnhancedUserDataAreaSize()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("EnhancedUserDataStartAddr:  0x%04X", extendedCSD.EnhancedUserDataStartAddress()));
+        __KTRACE_OPT(KPBUS1, Kern::Printf("BadBlockManagementMode:     0x%04X", extendedCSD.BadBlockManagementMode()));
+
+
+		OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM8, "CSDStructureVer=%u; ExtendedCSDRev=%u; SupportedCmdSet=%u", extendedCSD.CSDStructureVer(), extendedCSD.ExtendedCSDRev(), extendedCSD.SupportedCmdSet() );
+		OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM9, "PowerClass26Mhz360V=0x%02x; PowerClass52Mhz360V=0x%02x; PowerClass26Mhz195V=0x%02x; PowerClass52Mhz195V=0x%02x", extendedCSD.PowerClass26Mhz360V(), extendedCSD.PowerClass52Mhz360V(), extendedCSD.PowerClass26Mhz195V(), extendedCSD.PowerClass52Mhz195V() );
+		OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM10, "CardType=%u; CmdSet=%u; CmdSetRev=%u; PowerClass=%u; HighSpeedTiming=%u", extendedCSD.CardType(), extendedCSD.CmdSet(), extendedCSD.CmdSetRev(), extendedCSD.PowerClass(), extendedCSD.HighSpeedTiming() );
+		OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM11, "HighCapacityEraseGroupSize=%u; AccessSize=%u; BootInfo=%u; BootSizeMultiple=%u; EraseTimeoutMultiple=%u", extendedCSD.HighCapacityEraseGroupSize(), extendedCSD.AccessSize(), extendedCSD.BootInfo(), extendedCSD.BootSizeMultiple(), extendedCSD.EraseTimeoutMultiple() );
+		OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM12, "ReliableWriteSector=%u; HighCapWriteProtGroupSize=%u; SleepCurrentVcc=%u; SleepCurrentVccQ=%u; SleepAwakeTimeout=%u", extendedCSD.ReliableWriteSector(), extendedCSD.HighCapacityWriteProtectGroupSize(), extendedCSD.SleepCurrentVcc(), extendedCSD.SleepCurrentVccQ(), extendedCSD.SleepAwakeTimeout() );
+		OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM13, "BootConfig=%u; BootBusWidth=%u; EraseGroupDef=%u", extendedCSD.BootConfig(), extendedCSD.BootBusWidth(), extendedCSD.EraseGroupDef() );
+
+        // 4.4 extensions
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx1, "ErasedMemoryContent:        0x%02X", extendedCSD.ErasedMemoryContent());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx2, "BootConfigProtection:       0x%02X", extendedCSD.BootConfigProt());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx3, "BootAreaWriteProtectionReg: 0x%02X", extendedCSD.BootAreaWriteProtectionReg());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx4, "UserAreaWriteProtectionReg: 0x%02X", extendedCSD.UserAreaWriteProtectionReg());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx5, "FWConfiguration:            0x%02X", extendedCSD.FwConfiguration());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx6, "RPMBSize:                   0x%04X", extendedCSD.RpmbSize());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx7, "HwResetFunction:            0x%02X", extendedCSD.HwResetFunction());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx8, "PartitioningSupport:        0x%02X", extendedCSD.PartitioningSupport());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx9, "MaxEnhancedAreaSize:        0x%04X", extendedCSD.MaxEnhancedAreaSize());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx10, "PartitionsAttribute:        0x%02X", extendedCSD.PartitionsAttribute());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx11, "PartitioningSetting:        0x%02X", extendedCSD.PartitioningSetting());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx12, "GPP1:                       0x%04X", extendedCSD.GeneralPurposePartition1Size());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx13, "GPP2:                       0x%04X", extendedCSD.GeneralPurposePartition2Size());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx14, "GPP3:                       0x%04X", extendedCSD.GeneralPurposePartition3Size());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx15, "GPP4:                       0x%04X", extendedCSD.GeneralPurposePartition4Size());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx16, "EnhancedUserDataSize:       0x%04X", extendedCSD.EnhancedUserDataAreaSize());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx17, "EnhancedUserDataStartAddr:  0x%04X", extendedCSD.EnhancedUserDataStartAddress());
+        OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx18, "BadBlockManagementMode:     0x%04X", extendedCSD.BadBlockManagementMode());
+
 		
-		OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM8, "CSDStructureVer=%u; ExtendedCSDRev=%u; SupportedCmdSet=%u", s.CardP()->ExtendedCSD().CSDStructureVer(), s.CardP()->ExtendedCSD().ExtendedCSDRev(), s.CardP()->ExtendedCSD().SupportedCmdSet() );
-		OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM9, "PowerClass26Mhz360V=0x%02x; PowerClass52Mhz360V=0x%02x; PowerClass26Mhz195V=0x%02x; PowerClass52Mhz195V=0x%02x", s.CardP()->ExtendedCSD().PowerClass26Mhz360V(), s.CardP()->ExtendedCSD().PowerClass52Mhz360V(), s.CardP()->ExtendedCSD().PowerClass26Mhz195V(), s.CardP()->ExtendedCSD().PowerClass52Mhz195V() );
-		OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM10, "CardType=%u; CmdSet=%u; CmdSetRev=%u; PowerClass=%u; HighSpeedTiming=%u", s.CardP()->ExtendedCSD().CardType(), s.CardP()->ExtendedCSD().CmdSet(), s.CardP()->ExtendedCSD().CmdSetRev(), s.CardP()->ExtendedCSD().PowerClass(), s.CardP()->ExtendedCSD().HighSpeedTiming() );
-		OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM11, "HighCapacityEraseGroupSize=%u; AccessSize=%u; BootInfo=%u; BootSizeMultiple=%u; EraseTimeoutMultiple=%u", s.CardP()->ExtendedCSD().HighCapacityEraseGroupSize(), s.CardP()->ExtendedCSD().AccessSize(), s.CardP()->ExtendedCSD().BootInfo(), s.CardP()->ExtendedCSD().BootSizeMultiple(), s.CardP()->ExtendedCSD().EraseTimeoutMultiple() );
-		OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM12, "ReliableWriteSector=%u; HighCapWriteProtGroupSize=%u; SleepCurrentVcc=%u; SleepCurrentVccQ=%u; SleepAwakeTimeout=%u", s.CardP()->ExtendedCSD().ReliableWriteSector(), s.CardP()->ExtendedCSD().HighCapacityWriteProtectGroupSize(), s.CardP()->ExtendedCSD().SleepCurrentVcc(), s.CardP()->ExtendedCSD().SleepCurrentVccQ(), s.CardP()->ExtendedCSD().SleepAwakeTimeout() );
-		OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM13, "BootConfig=%u; BootBusWidth=%u; EraseGroupDef=%u", s.CardP()->ExtendedCSD().BootConfig(), s.CardP()->ExtendedCSD().BootBusWidth(), s.CardP()->ExtendedCSD().EraseGroupDef() );
-		
-		if (s.CardP()->ExtendedCSD().ExtendedCSDRev() >= 3)
-			{
-			if (!(s.CardP()->ExtendedCSD().EraseGroupDef()) && s.CardP()->ExtendedCSD().HighCapacityEraseGroupSize())
+		if (extendedCSD.ExtendedCSDRev() >= 3)
+			{
+			if (!(extendedCSD.EraseGroupDef()) && extendedCSD.HighCapacityEraseGroupSize())
 				{
 				// Need to ensure that media is using correct erase group sizes.
 				TMMCArgument arg = TExtendedCSD::GetWriteArg(
@@ -3429,7 +3567,7 @@
 	
 		if (err == KMMCErrNone)
 			{
-			// EEraseGroupDef has been updated succussfully, 
+			// EEraseGroupDef has been updated successfully, 
 			// update the Extended CSD to reflect this			
 			memset( s.CardP()->iExtendedCSD.Ptr()+TExtendedCSD::EEraseGroupDefIndex, TExtendedCSD::EEraseGrpDefEnableHighCapSizes, 1);
 			}
@@ -3948,8 +4086,8 @@
 
 	// Get the bus widths & clocks supported by the controller
 	// NB If the PSL doesn not support TMMCMachineInfoV4, return
-	TMMCMachineInfoV4 machineInfo;
-	TMMCMachineInfoV4Pckg machineInfoPckg(machineInfo);
+	TMMCMachineInfoV44 machineInfo;
+	TMMCMachineInfoV44Pckg machineInfoPckg(machineInfo);
 	MachineInfo(machineInfoPckg);
 	if (machineInfo.iVersion < TMMCMachineInfoV4::EVersion4)
 	    {
@@ -5724,6 +5862,7 @@
 			EStBegin=0,
 			EStRestart,
 			EStAttached,
+			EStLength,
 			EStLength1,
 			EStLengthSet,
 			EStIssueBlockCount,
@@ -5755,7 +5894,6 @@
 				return KMMCErrNotSupported;
 			    }
 			}
-
 		s.iState |= KMMCSessStateInProgress;
 		m.SetTraps(KMMCErrInitContext);
 
@@ -5770,9 +5908,15 @@
 			SMF_INVOKES( AttachCardSMST, EStAttached )	// attachment is mandatory here
 			}
 
+
 	SMF_BPOINT(EStAttached)
 
 		OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM4, "EStAttached" );
+		SMF_INVOKES( SwitchPartitionSMST, EStLength ) // may have to switch partitions
+		
+	SMF_STATE(EStLength)
+
+		OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM16, "EStLength" );
 		TMMCCommandDesc& cmd = s.Command();
 
 		const TUint32 blockLength = cmd.BlockLength();
@@ -5809,7 +5953,7 @@
 
 	SMF_STATE(EStLength1)
 
-		OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM5, "EStAttached" );
+		OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM5, "EStLength" );
 		const TMMCStatus status(s.ResponseP());
 		CurrentSessPopCmdStack();
 		if (status.Error())
@@ -5851,17 +5995,19 @@
 
   		const TUint blocks = cmd.NumBlocks();
 
-		SMF_NEXTS(EStBpoint1)
+	SMF_NEXTS(EStBpoint1)
+		
 		if ( !(opType & kTypeSpecial) )	// A special session has already set its command descriptor
 			{
 			
+
 			if (cmd.iFlags & KMMCCmdFlagReliableWrite)
 				//ensure multiple block commands are used for reliable writing
 				opType |= kTypeMultiple;
 			
-			if ( (blocks==1) && !(cmd.iFlags & KMMCCmdFlagReliableWrite) )
+			if ( (blocks==1) && !(cmd.iFlags & KMMCCmdFlagReliableWrite) && !(cmd.iFlags & KMMCCmdFlagRpmbIO))
 				{
-				// Reliable Write requires that Multi-Block command is used.
+				// Reliable Write & RPMB require that Multi-Block command is used.
 				opType &= ~kTypeMultiple;
 				}
 
@@ -6005,7 +6151,7 @@
 		// Fall through if CURRENT_STATE is not PGM or DATA
 	SMF_STATE(EStRWFinish)
 
-		OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM15, "EStRWFinish" );
+	OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM15, "EStRWFinish" );
 		if (TMMCStatus(s.ResponseP()).Error() != 0)
 		    {
 		    OstTraceFunctionExitExt( DMMCSTACK_CIMREADWRITEBLOCKSSM_EXIT8, this, (TInt) KMMCErrStatus );
@@ -6034,6 +6180,7 @@
 			EStBegin=0,
 			EStRestart,
 			EStAttached,
+			EStLength,
 			EStStartTagged,
 			EStEndTagged,
 			EStErased,
@@ -6069,13 +6216,21 @@
 
 		OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMERASESM3, "EStRestart" );
 		SMF_CALLMEWR(EStRestart) // Create a recursive call entry to recover from Init
-
-		s.ResetCommandStack();
+        
+        CurrentSessPushCmdStack(); //Push stack pointer to preserve flags for TRIM
+		
 		SMF_INVOKES( AttachCardSMST, EStAttached )		// attachment is mandatory
 
 	SMF_BPOINT(EStAttached)
 
 		OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMERASESM4, "EStAttached" );
+		SMF_INVOKES( SwitchPartitionSMST, EStLength )  // may have to switch partitions
+			
+	SMF_STATE(EStLength)
+	
+		OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMERASESM13, "EStLength" );
+
+		CurrentSessPopCmdStack();
 		TMMCCommandDesc& cmd = s.Command();
 
 		if(cmd.iTotalLength == 0)
@@ -6095,6 +6250,14 @@
 				break;
 			case ECIMEraseGroup:
 				OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMERASESM6, "ECIMEraseGroup" );
+				
+				if(cmd.iFlags & KMMCCmdFlagDeleteNotify)
+				    {
+				    cmd.iBlockLength = KMMCardHighCapBlockSize; //TRIM cmd blocklength
+				    cmd.iCommand = ECmdTagEraseGroupStart;
+				    break;
+				    }
+				
 				cmd.iBlockLength = s.iCardP->iCSD.EraseGroupSize();
 				if(cmd.iBlockLength == 0 || cmd.iTotalLength % cmd.iBlockLength != 0)
 				    {
@@ -6123,7 +6286,7 @@
 	SMF_STATE(EStStartTagged)
 
 		OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMERASESM7, "EStStartTagged" );
-		const TMMCCommandDesc& cmd = s.Command();
+		TMMCCommandDesc& cmd = s.Command();
 
 		TMMCCommandEnum command;
 		TUint endAddr = cmd.iArgument;
@@ -6134,20 +6297,29 @@
 			}
 		else
 			{
-			if(cmd.IsBlockCmd())
-				{
-				endAddr += (cmd.iTotalLength - cmd.iBlockLength) >> KMMCardHighCapBlockSizeLog2;
-				}
-			else
-				{
-				endAddr += cmd.iTotalLength - cmd.iBlockLength;
-				}
+            if(cmd.iFlags & KMMCCmdFlagDeleteNotify)
+                {
+                endAddr += cmd.IsBlockCmd() ? (cmd.iTotalLength / cmd.iBlockLength - 1) : (cmd.iTotalLength - cmd.iBlockLength);
+                command = ECmdTagEraseGroupEnd;
+                }
+                else
+                    {
+                    if(cmd.IsBlockCmd())
+                    {
+                    endAddr += (cmd.iTotalLength - cmd.iBlockLength) >> KMMCardHighCapBlockSizeLog2;
+                    }
+                    else
+                        {
+                        endAddr += cmd.iTotalLength - cmd.iBlockLength;
+                        }
 	
-			command = ECmdTagEraseGroupEnd;
-			}
-
-		CurrentSessPushCmdStack();
+                    command = ECmdTagEraseGroupEnd;
+                    }
+			} 
+
+		const TUint flags = cmd.iFlags;
 		s.FillCommandDesc( command, endAddr );
+		cmd.iFlags = flags;                                   //Preserving current flags for TRIM
 		SMF_INVOKES( ExecCommandSMST, EStEndTagged )
 
 	SMF_STATE(EStEndTagged)
@@ -6159,7 +6331,16 @@
 		const TInt KMaxEraseTimeoutInSeconds = 30;
 		iBody->SetInactivityTimeout(KMaxEraseTimeoutInSeconds);
 		m.SetTraps(KMMCErrAll);
-		s.FillCommandDesc( ECmdErase, 0 );
+		
+		TMMCCommandDesc& cmd = s.Command();
+		
+		if(cmd.iFlags & KMMCCmdFlagDeleteNotify)
+		    {
+            s.FillCommandDesc(ECmdErase, KMMCCmdTrim);
+		    }
+		else
+		    s.FillCommandDesc( ECmdErase, 0 );
+		
 		SMF_INVOKES( ExecCommandSMST, EStErased )
 
 	SMF_STATE(EStErased)
@@ -6602,6 +6783,9 @@
 TMMCErr DMMCStack::AttachCardSMST( TAny* aStackP )
 	{ return( static_cast<DMMCStack *>(aStackP)->AttachCardSM() ); }
 
+TMMCErr DMMCStack::SwitchPartitionSMST( TAny* aStackP )
+	{ return( static_cast<DMMCStack *>(aStackP)->SwitchPartitionSM() ); }
+
 TMMCErr DMMCStack::ExecCommandSMST( TAny* aStackP )
 	{ return( static_cast<DMMCStack *>(aStackP)->ExecCommandSM() ); }
 
@@ -6689,8 +6873,6 @@
 	return new DMMCSession(aCallBack);
 	}
 
-EXPORT_C void DMMCStack::Dummy1() {}
-
 /**
  * Calls the PSL-implemented function SetBusWidth() if the bus width has changed
  *
@@ -6743,8 +6925,14 @@
 	{
 	}
 
-EXPORT_C void DMMCStack::MachineInfo(TDes8& /*aMachineInfo*/)
-	{
+EXPORT_C void DMMCStack::MachineInfo(TDes8& aMachineInfo)
+/**
+ * Default implementation of method. Calls 
+ * DMMCStack::MachineInfo(TMMCMachineInfo& aMachineInfo)
+ */
+	{
+    TMMCMachineInfoV44Pckg& mi = static_cast<TMMCMachineInfoV44Pckg&> (aMachineInfo);
+    MachineInfo(mi());
 	}
 
 TBusWidth DMMCStack::BusWidthEncoding(TInt aBusWidth) const
@@ -7560,3 +7748,39 @@
 	return r;
 	}
 
+/**
+ A generic adapter function for returning an interface of specified type
+ The caller should set aInterfacePtr to NULL before calling
+ @aInterfaceId Denotes the required interface to be returned
+ @aInterfacePtr On completion contains an interface of type specified by aInterfaceId
+ @aThis Extends the interface to provide further access to DMMCSession
+ */
+
+EXPORT_C TInt MMCGetExtInterface(TMMCExtInterfaceId aInterfaceId, MMCMExtInterface*& aInterfacePtr, TAny* /*aThis*/)
+    {
+    OstTrace1(TRACE_FLOW, MMCGETEXTINTERFACE_ENTRY, ">MMCGetExtInterface InterfaceId=%d", aInterfaceId );
+    TInt r = KErrNone;
+	switch(aInterfaceId)
+        {
+        case KInterfaceRpmb:
+            {   
+            if (RpmbParmsPopulated)
+				{
+				aInterfacePtr = (MMCMExtInterface*)(&rpmbInfo);
+				}
+			else
+				{
+				// don't hand out interface if not ready to use
+				aInterfacePtr = NULL;
+				r = KErrNotReady;
+				}
+            break;
+            }
+        default:
+            aInterfacePtr = NULL;
+            break;
+        }
+    OstTrace0(TRACE_FLOW, MMCGETEXTINTERFACE_EXIT, "<MMCGetExtInterface" );
+    return r;
+    }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/pbus/mmc/stackdebug.h	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,56 @@
+// Copyright (c) 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:
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#define _STACK_DEBUG_PRINT_ 
+
+#if defined(_STACK_DEBUG_PRINT_) && (defined(_DEBUG) || defined(_DEBUG_RELEASE))
+/** Trace - format string  */
+#define __PRINT(t) {Kern::Printf(t);}
+/** Trace - format string with 1 param */
+#define __PRINT1(t,a) {Kern::Printf(t,a);}
+/** Trace - format string with 2 params */
+#define __PRINT2(t,a,b) {Kern::Printf(t,a,b);}
+/** Trace - format string with 3 params */
+#define __PRINT3(t,a,b,c) {Kern::Printf(t,a,b,c);}
+/** Trace - format string with 4 params */
+#define __PRINT4(t,a,b,c,d) {Kern::Printf(t,a,b,c,d);}
+/** Trace - format string with 5 params */
+#define __PRINT5(t,a,b,c,d,e) {Kern::Printf(t,a,b,c,d,e);}
+
+#else
+
+/** NULL definition */
+#define __PRINT(t)
+/** NULL definition */
+#define __PRINT1(t,a)
+/** NULL definition */
+#define __PRINT2(t,a,b)
+/** NULL definition */
+#define __PRINT3(t,a,b,c)
+/** NULL definition */
+#define __PRINT4(t,a,b,c,d)
+/** NULL definition */
+#define __PRINT5(t,a,b,c,d,e)
+#endif
+
+#endif // DEBUG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/rpmb/rpmbdevice.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,434 @@
+// Copyright (c) 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:
+// /os/kernelhwsrv/kernel/eka/drivers/rpmb/rpmbdevice.cpp
+// Kernel extension entry point for RPMB driver.
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "../../include/drivers/locmedia_ost.h"
+#ifdef __VC32__
+#pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
+#endif
+#include "rpmbdeviceTraces.h"
+#endif
+
+#include <kernel/kernel.h>
+#include <drivers/rpmbdevice.h>
+#include <drivers/sdcard.h>
+#include <drivers/sdio/sdio.h>
+#include <drivers/mmc.h>
+
+DRpmbDevice * DRpmbDevice::DRpmbDevicePtrs[KMaxPBusSockets*4] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL};
+
+EXPORT_C DRpmbDevice::DRpmbDevice():
+	iSessionEndCallBack(DRpmbDevice::SessionEndCallBack, this),
+	iDeviceIndex(KIndexNotAssigned)
+    {
+	}
+
+EXPORT_C DRpmbDevice::~DRpmbDevice()
+    {
+    Close();
+	}
+
+void DRpmbDevice::SessionEndCallBack(TAny* aSelf)
+    {
+    DRpmbDevice& self = *static_cast<DRpmbDevice*>(aSelf);
+    self.DoSessionEndCallBack();
+    }
+
+void DRpmbDevice::DoSessionEndCallBack()
+    {   
+    iSocket->EndInCritical();
+    Kern::SemaphoreSignal(*iRequestSemaphore);
+    }
+
+void DRpmbDevice::BusCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2)
+{
+    DRpmbDevice* device = (DRpmbDevice*)aPtr;
+    TPBusState busState = (TPBusState) (TInt) a1;
+	TInt busError = (TInt) a2;
+
+    if(aReason == TPBusCallBack::EPBusStateChange 
+		&& busState == EPBusOn && busError == KErrNone)
+		{
+		Kern::SemaphoreSignal(*(device->iPowerUpSemaphore));
+        }
+}
+
+TInt DRpmbDevice::PowerUpStack()
+    {
+    //
+    // Power up the socket - This ensures that the socket is powered up 
+    // and the functions are re-enumerated.
+    //  
+    iBusCallBack.iFunction = BusCallBack;
+    iBusCallBack.iPtr=this;
+    iBusCallBack.SetSocket(iSocket->iSocketNumber);
+    iBusCallBack.Add();
+	NKern::ThreadEnterCS();
+    TInt r = Kern::SemaphoreCreate(iPowerUpSemaphore,_L("RPMBPowerUpSem"), 0);
+    if(r == KErrNone)
+        {
+		TInt r = iSocket->PowerUp();
+        if(r==KErrNone)
+            {
+            Kern::SemaphoreWait(*iPowerUpSemaphore);
+            }
+        }
+	NKern::ThreadLeaveCS();
+    return r;
+    }
+
+void DRpmbDevice::SetSynchronisationParms(TUint8 aDeviceIndex)
+	{
+	// Mark this instance as being associated with the requested index 
+	iDeviceIndex = aDeviceIndex;
+	// Mark the requested index as being associated with this instance
+	// Atomic operation ensures store is flushed from cache and committed 
+	// to global memory
+	__e32_atomic_store_ord_ptr(&(DRpmbDevicePtrs[iDeviceIndex]),this);
+	}
+
+
+void DRpmbDevice::ClearSynchronisationParms()
+	{
+	// Serialise access to global pointer array and it's local index
+	NKern::FMWait(&iSynchronisationParmsMutex);
+	if (iDeviceIndex < KMaxPBusSockets*4)
+		{
+		// Atomic operation for load from global memory and not from cache
+		DRpmbDevice * ptrTableEntry = 
+			(DRpmbDevice *)__e32_atomic_load_acq_ptr(&(DRpmbDevicePtrs[iDeviceIndex]));
+		// This instance of DRpmbDevice is associated with an index
+		// The associated index MUST be associated with this instance
+		__ASSERT_ALWAYS((ptrTableEntry == this), Kern::Fault(__FILE__, __LINE__));
+		// Disassociate index and instance
+		// Atomic operation ensures store is flushed from cache and committed 
+		// to global memory
+		__e32_atomic_store_ord_ptr(&(DRpmbDevicePtrs[iDeviceIndex]),NULL);
+		iDeviceIndex = KIndexNotAssigned;
+		}
+	// Serialise access to global pointer array and it's local index
+	NKern::FMSignal(&iSynchronisationParmsMutex);
+	}
+
+EXPORT_C TInt DRpmbDevice::Open(TUint aDeviceIndex)
+    {
+    //
+    //eMMC4.4+ devices have RPMB partitions and each MMC device may be configured as having an RPMB 
+	//partition in the baseport
+	//This function creates an MMC stack session for device aDeviceIndex
+	//This is used to access the RPMB partition on that device
+	//Extensions that use this interface during system startup should be located AFTER the RPMB and MMC
+	//extesnions in the system ROM and should not call this interface synchronously from a system
+	//startup initialisation routine
+	//aDeviceIndex the index of the device supporting the RPMB partition
+	//Returns KerrNone if successful
+	//Returns KErrNotReady if the baseport configuration hasn't been read yet
+    //Returns KErrNotSupported if the baseport configuration does not have a valid RPMB partition 
+	//or RPMB is not supported by the media device
+	//Otherwise retruns a systemwide error code
+    //
+    OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_1, "RPMB: >DrpmbDevice::Open");
+    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: >DrpmbDevice::Open"));
+	
+	TRpmbDeviceParms params;
+	params.iCardNumber = 0;
+	params.iSocketPtr = NULL;	
+    MRpmbInfo* rpmbInterface = NULL;
+	
+	TInt r = MMCGetExtInterface(KInterfaceRpmb, (MMCMExtInterface*&) rpmbInterface);
+	// MMCGetExtInterface currently returns KErrNotReady with rpmbInterface == NULL if the RPMB parameters 
+	// haven't yet been populated
+	// proveided any calling extension is located AFTER the RPMB and MMC extesnions in the system ROM and 
+	// does not call this interface synchronously from a system initialisation routine the following 
+	// shouldn't be asserted 
+	OstTrace1(TRACE_FLOW, DRPMBDEVICE_OPEN_2, "RPMB: DrpmbDevice Get Interface err = %d", r);
+	__KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice Get Interface err = %d", r));
+	__ASSERT_ALWAYS(r == KErrNone, Kern::Fault(__FILE__, __LINE__));
+		
+	if (rpmbInterface == NULL)
+		{
+		// unexpected error since MMCGetExtInterface didn't return an error
+	    OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_3, "RPMB: DrpmbDevice Null rpmbInterface");
+	    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice Null rpmbInterface"));
+		return KErrGeneral;
+		}
+		
+	// Interface currently supports a single device, device index = 0   
+	r = rpmbInterface->RpmbInfo(aDeviceIndex, params);
+    if(r != KErrNone)
+        {
+		// requested index non zero or baseport not configured with RPMB capable MMC device
+        OstTrace1(TRACE_FLOW, DRPMBDEVICE_OPEN_4, "RPMB: DrpmbDevice requested index non zero or baseport not configured, err = %d", r);
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice requested index non zero or baseport not configured, err = %d", r));
+		return r;
+		}
+   
+    iSocket = params.iSocketPtr;
+	// iSocket cannot be NULL 
+	// TMMCardControllerInterface::RegisterMediaDevices ensures that the assigned value is not NULL
+	__ASSERT_ALWAYS((iSocket!=NULL), Kern::Fault(__FILE__, __LINE__));
+    
+	// Serialise access to global pointer array and it's local index
+	NKern::FMWait(&iSynchronisationParmsMutex);
+
+	if (iDeviceIndex != KIndexNotAssigned)
+		{
+		// This instance of DRpmbDevice is already open
+		if (iDeviceIndex == aDeviceIndex)
+			{
+			// Serialise access to global pointer array and it's local index
+			NKern::FMSignal(&iSynchronisationParmsMutex);
+			// Already open with requested index
+		    OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_5, "RPMB: DrpmbDevice already open with requested index");
+		    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice already open with requested index"));
+			return KErrNone;
+			}
+		else
+			{
+			// Serialise access to global pointer array and it's local index
+			NKern::FMSignal(&iSynchronisationParmsMutex);
+			// Already open with other index
+	        OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_6, "RPMB: DrpmbDevice already open with other index");
+	        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice already open with other index"));
+			return KErrInUse;
+			}
+		}
+	else
+		{
+		// This instance of DRpmbDevice is not open
+
+		// Atomic operation for load from global memory and not from cache
+		DRpmbDevice * ptrTableEntry = 
+			(DRpmbDevice *)__e32_atomic_load_acq_ptr(&(DRpmbDevicePtrs[aDeviceIndex]));
+
+		if (ptrTableEntry == NULL)
+			{
+			SetSynchronisationParms((TUint8)(aDeviceIndex));
+			}
+		else
+			{
+			// Requested index cannot be associated with this instance of DRpmbdevice  
+			__ASSERT_ALWAYS(ptrTableEntry != this, Kern::Fault(__FILE__, __LINE__));
+			// Serialise access to global pointer array and it's local index
+			NKern::FMSignal(&iSynchronisationParmsMutex);
+			// Requested index already associated with a different instance of DRpmbDevice
+	        OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_7, "RPMB: DrpmbDevice requested index already associated with a different instance of DrpmbDevice");
+	        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice requested index already associated with a different instance of DrpmbDevice"));
+			return KErrInUse;
+			}
+		}
+	NKern::FMSignal(&iSynchronisationParmsMutex);
+
+	r = PowerUpStack();
+    if (r != KErrNone && r != KErrCompletion)
+        {
+        // Stack wasn't already powered up and failed to power up
+		ClearSynchronisationParms();
+	    OstTrace1(TRACE_FLOW, DRPMBDEVICE_OPEN_8, "RPMB: DrpmbDevice wasn't already powered up and failed with err = %d", r);
+	    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice wasn't already powered up and failed with err = %d", r));
+		return r;
+        }
+    
+    DMMCStack* stack = iSocket->Stack(KBusNumber);
+    if(stack == NULL)
+        {
+		// KBusNumber = 0 so iSocket->Stack() returns iSocket->iStack 
+		// Expect this to have been pre-assigned
+		// Expect a socket to be bound to a stack
+        ClearSynchronisationParms();
+        OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_9, "RPMB: stack is NULL");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: stack is NULL"));
+        return KErrNoMemory;
+        }
+    
+    iCard = stack->CardP(params.iCardNumber);
+    if(iCard == NULL) 
+        {
+		// stack->CardP() returns stack->iCardArray->CardP(params.iCardNumber)
+		// Expect this to have been pre-assigned
+		// Expect card array to point to a card
+        ClearSynchronisationParms();
+        OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_10, "RPMB: card pointer is NULL");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: card pointer is NULL"));
+        return KErrNoMemory;
+        }
+    
+	NKern::ThreadEnterCS(); 
+    iSession = stack->AllocSession(iSessionEndCallBack);
+	NKern::ThreadLeaveCS(); 
+    if (iSession == NULL)
+        {
+		// DMMCStack::AllocSession() failed to create a new instance off DMMCSession
+        OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_11, "RPMB: failed to create a new instance of DMMCSession");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: failed to create a new instance of DMMCSession"));
+        return KErrNoMemory; 
+        }
+
+    iSession->SetStack(stack);
+    iSession->SetCard(iCard);
+    
+    TInt bufLen, minorBufLen;
+    stack->BufferInfo(iIntBuf, bufLen, minorBufLen);
+	// mmc media driver reserved the first KRpmbOneFramePacketLength bytes of the 
+	// PSL buffer to be used for RPMB requests / responses
+	iIntBuf += minorBufLen;
+    
+    if(iCard->ExtendedCSD().ExtendedCSDRev() < 5 || iCard->ExtendedCSD().RpmbSize() == 0)
+        {
+		// RPMB is not supported on selected hardware
+        ClearSynchronisationParms();
+        OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_12, "RPMB: feature is not supported on selected hardware");
+        __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: feature is not supported on selected hardware"));
+        return KErrNotSupported;
+        }
+    OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_13, "RPMB: <DrpmbDevice::Open");
+    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: <DrpmbDevice::Open"));
+    return KErrNone;
+    }
+
+EXPORT_C void DRpmbDevice::Close()
+    {
+	//
+    //Closes an interaction with an RPMB configured device 
+    //
+    OstTrace0(TRACE_FLOW, DRPMBDEVICE_CLOSE_1, "RPMB: >DrpmbDevice::Close");
+    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: >DrpmbDevice::Close"));
+ 	
+	ClearSynchronisationParms();
+    
+	iBusCallBack.Remove();
+
+	NKern::ThreadEnterCS();
+
+    if(iPowerUpSemaphore)
+		{
+        iPowerUpSemaphore->Close(NULL);
+		iPowerUpSemaphore = NULL;
+		}
+
+	if (iSession)
+		{
+		delete iSession;
+		iSession = NULL;
+		}
+
+	if(iRequestSemaphore)
+		{
+        iRequestSemaphore->Close(NULL);
+		iRequestSemaphore = NULL;
+		}
+   
+	NKern::ThreadLeaveCS();
+	OstTrace0(TRACE_FLOW, DRPMBDEVICE_CLOSE_2, "RPMB: <DrpmbDevice::Close");
+	__KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: <DrpmbDevice::Close"));
+    }
+
+EXPORT_C TInt DRpmbDevice::SendAccessRequest(TDes8& aRpmbRequest, TDes8& aRpmbResponse)
+    {
+    //
+    //sends a request to be handled by the RPMB partition
+    //aRpmbRequest - the physically contiguous region of memory containg the request to be handled
+    //aRpmbResponse - the physically contiguous region memory to where the response from the hardware will be written
+	//returns KErrNone if successful
+	//returns system wide epoc error code if set on call back from stack
+	//returns KErrArgument for invalid descriptor argument length
+	//returns KErrNotReady if not opened
+	//retruns KErrNotready if MMC stack is processing a posponed power down or a postponed media change event
+	//otherwise returns system wide error code 
+	//
+    
+    OstTrace0(TRACE_FLOW, DRPMBDEVICE_SENDACCESSREQUEST_1, "RPMB: >DrpmbDevice::SendAccessRequest");
+    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: >DrpmbDevice::SendAccessRequest"));
+
+	if ((aRpmbRequest.Length() != KRpmbOneFramePacketLength) || (aRpmbResponse.Length() != KRpmbOneFramePacketLength))
+		{
+		// insist on single frame access as mutiple read and multiple write (reliable write) notb yet supported
+		return KErrArgument;
+		}
+
+	if (iSession == NULL)
+        {
+		// DRpmbDevice::Open not called at all
+		// or not called after DRpmbDevice::Close
+	    OstTrace0(TRACE_FLOW, DRPMBDEVICE_SENDACCESSREQUEST_2, "RPMB: DMMCSession is NULL");
+	    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DMMCSession is NULL"));
+        return KErrNotReady;
+        }
+
+	if (iRequestSemaphore == NULL)
+		{
+		// iRequestSemaphore zero filled prior to contruction
+		// create semaphore for waiting on stack
+		NKern::ThreadEnterCS();
+		TInt r = Kern::SemaphoreCreate(iRequestSemaphore,_L("RPMBRequestSemaphore"), 0);
+		NKern::ThreadLeaveCS();
+		if (r != KErrNone)
+			{
+			// failed to create semaphore 
+		    OstTrace1(TRACE_FLOW, DRPMBDEVICE_SENDACCESSREQUEST_3, "RPMB: failed to create semaphore err = %d", r);
+		    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: failed to create semaphore err = %d", r));
+			return r;
+			}
+		}
+
+    memcpy(iIntBuf, aRpmbRequest.Ptr(), KRpmbOneFramePacketLength);
+     
+    TInt r = iSocket->InCritical();
+	// may be KErrNotready if MMC stack is processing a posponed power down event or a postponed media change event
+	if (r == KErrNone)
+       {
+    iSession->SetPartition(TExtendedCSD::ESelectRPMB);            //Set RPMB Partition
+    iSession->ResetCommandStack();
+    iSession->FillCommandArgs(KDeviceAddress, KRpmbOneFramePacketLength, iIntBuf, KRpmbOneFramePacketLength);
+    iSession->iSessionID = ECIMRpmbAccess;
+
+        r = iSession->Engage();
+        if(r == KErrNone)
+            {
+			Kern::SemaphoreWait(*iRequestSemaphore);
+			memcpy((TUint8 *)aRpmbResponse.Ptr(), iIntBuf, KRpmbOneFramePacketLength);
+		    OstTrace1(TRACE_FLOW, DRPMBDEVICE_SENDACCESSREQUEST_4, "RPMB: request complete with %d", iSession->EpocErrorCode());
+		    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: request complete with %d", iSession->EpocErrorCode()));
+			return iSession->EpocErrorCode();  
+            }
+        }
+ 
+    iSocket->EndInCritical();
+    
+    OstTrace1(TRACE_FLOW, DRPMBDEVICE_SENDACCESSREQUEST_5, "RPMB: <DrpmbDevice::SendAccessRequest complete %d", r);
+    __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: <DrpmbDevice::SendAccessRequest complete %d", r));
+    
+    return r;
+    }
+
+DECLARE_STANDARD_EXTENSION()
+    {
+    __KTRACE_OPT(KBOOT,Kern::Printf("RPMBEXT.DLL DECLARE_STANDARD_EXTENSION entry point"));      
+	return KErrNone;
+    }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/rpmb/rpmbext.mmp	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,55 @@
+// Copyright (c) 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:
+// /os/kernelhwsrv/kernel/eka/drivers/rpmb/rpmbext.mmp
+// rpmbext.dll RPMB driver
+// 
+//
+
+/**
+ @file
+*/
+
+#include	"../../kernel/kern_ext.mmh"
+
+target		rpmbext.dll
+targettype	kext
+linkas		rpmbext.dll
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+#ifdef SYMBIAN_OLD_EXPORT_LOCATION
+systeminclude		../../../include
+systeminclude		../../../include/drivers
+#endif
+
+USERINCLUDE		traces
+
+source		rpmbdevice.cpp
+
+library		epbusmmc.lib
+
+capability	all
+
+epocallowdlldata
+
+uid		0x1000008d 0x2003301C
+
+DEFFILE		../../~/rpmbext.def
+
+VENDORID	0x70000001
+
+start wins
+win32_headers
+end
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/rpmb/traces/OstTraceDefinitions.h	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,21 @@
+// Copyright (c) 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:
+
+#ifndef __OSTTRACEDEFINITIONS_H__
+#define __OSTTRACEDEFINITIONS_H__
+// OST_TRACE_COMPILER_IN_USE flag has been added by Trace Compiler
+// REMOVE BEFORE CHECK-IN TO VERSION CONTROL
+//#define OST_TRACE_COMPILER_IN_USE
+#include <opensystemtrace.h>
+#endif
--- a/kernel/eka/eabi/epbusmu.def	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/eabi/epbusmu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -120,7 +120,7 @@
 	_ZTV7DMMCPsu @ 119 NONAME ; vtable for DMMCPsu
 	_ZTV9DMMCStack @ 120 NONAME ; vtable for DMMCStack
 	_ZN9DMMCStack22ModifyCardCapabilitySMEv @ 121 NONAME ; DMMCStack::ModifyCardCapabilitySM()
-	_ZN9DMMCStack6Dummy1Ev @ 122 NONAME
+	_Z18MMCGetExtInterface18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 122 NONAME
 	_ZN9DMMCStack12GetInterfaceENS_12TInterfaceIdERPNS_10MInterfaceE @ 123 NONAME
 	_ZN9DMMCStack11MachineInfoER5TDes8 @ 124 NONAME
 	_ZN9DMMCStack11SetBusWidthEm @ 125 NONAME
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/eabi/rpmbextu.def	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,12 @@
+EXPORTS
+	_ZN11DRpmbDevice17SendAccessRequestER5TDes8S1_ @ 1 NONAME
+	_ZN11DRpmbDevice4OpenEj @ 2 NONAME
+	_ZN11DRpmbDevice5CloseEv @ 3 NONAME
+	_ZN11DRpmbDeviceC1Ev @ 4 NONAME
+	_ZN11DRpmbDeviceC2Ev @ 5 NONAME
+	_ZN11DRpmbDeviceD0Ev @ 6 NONAME
+	_ZN11DRpmbDeviceD1Ev @ 7 NONAME
+	_ZN11DRpmbDeviceD2Ev @ 8 NONAME
+	_ZTI11DRpmbDevice @ 9 NONAME
+	_ZTV11DRpmbDevice @ 10 NONAME
+
--- a/kernel/eka/include/drivers/mmc.h	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/include/drivers/mmc.h	Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1999-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"
@@ -12,7 +12,7 @@
 //
 // Description:
 // Generic MMC controller types and standard classes for MMC manipulation
-// This controller follows MMC spec V2.1
+// This controller follows MMC spec V4.4+
 // 
 //
 
@@ -26,6 +26,7 @@
 
 #include <drivers/pbus.h>
 #include <d32locd.h>
+#include <drivers/rpmbpacket.h>
 
 // MMC Card maximum system settings
 
@@ -56,7 +57,10 @@
 class TMMCPasswordStore;
 class TMMCEraseInfo;
 class TMMCMachineInfoV4;
+class TMMCMachineInfoV44;
+typedef TPckg<TMMCMachineInfo> TMMCardMachineInfoPckg;
 typedef TPckg<TMMCMachineInfoV4> TMMCMachineInfoV4Pckg;
+typedef TPckg<TMMCMachineInfoV44> TMMCMachineInfoV44Pckg;
 
 enum TMMCAppCommand {EMMCNormalCmd,EMMCApplicationCmd};
 
@@ -104,10 +108,36 @@
 */
 typedef TUint32 TMMCErr;
 
-//		MMC Enums and inline functions
-
-
-
+/**
+A structure to define global parameters for the initialisation of an RPMB object.
+This is required for devices with emmc4.4+
+@internalComponent
+*/
+struct TRpmbDeviceParms
+    {
+    DMMCSocket* iSocketPtr;
+    TUint iCardNumber;
+    };
+
+/*
+ Global counter for number or RPMB partitions. Only one partition per device 
+ */
+GLREF_D TUint NumberOfRpmbs;
+/*
+ Global holder for RPMB parameters
+ */
+GLREF_D TRpmbDeviceParms TheRpmbs[KMaxPBusSockets*4];
+
+GLREF_D TBool RpmbParmsPopulated;
+
+/**
+Max number of RPMB devices
+*/
+const TUint MaxIndexRpmb = 0;
+
+/**
+MMC Enums and inline functions
+*/
 
 /**
 @publishedPartner
@@ -570,6 +600,43 @@
 
 
 /**
+ * Client InterfaceIDs for GetExtInterface
+ * @publishedPartner
+ * 
+ */
+enum TMMCExtInterfaceId
+    {
+    KInterfaceRpmb
+    };
+
+class MMCMExtInterface
+    {
+public:
+    virtual TInt Func() = 0;
+    };
+
+/**
+Interface class to return information for an RPMB capable device.
+Used for emmc v4.4+
+*/
+
+class MRpmbInfo
+    {
+public:
+    virtual inline TInt RpmbInfo(TUint aDeviceIndex, TRpmbDeviceParms& aParams);
+    };
+
+/**
+ A generic adapter function for returning an interface of specified type
+ The caller should set aInterfacePtr to NULL before calling
+ @aInterfaceId Denotes the required interface to be returned
+ @aInterfacePtr On completion contains an interface of type specified by aInterfaceId
+ @aThis Extends the interface to provide further access to DMMCSession
+ */
+ 
+IMPORT_C TInt MMCGetExtInterface(TMMCExtInterfaceId aInterfaceId, MMCMExtInterface*& aInterfacePtr, TAny* aThis = NULL);
+
+/**
 @publishedPartner
 @released
 
@@ -626,10 +693,11 @@
 	ECIMLockStack			 =14,
 	ECIMInitStackAfterUnlock =15,
 	ECIMAutoUnlock			 =16,
-	ECIMSleep				 =17
+	ECIMSleep				 =17,
+    ECIMRpmbAccess           =18
 	};
 
-const TUint KMMCMaxSessionTypeNumber  = 18;
+const TUint KMMCMaxSessionTypeNumber  = 19;
 const TUint KMMCMinCustomSession	  = 1024;
 
 const TUint KMMCCmdDirDirBitPosition=	KBit0;			//fixed - dont change it
@@ -639,7 +707,7 @@
 const TUint KMMCCmdDirWBitDirect=		KBit7;
 
 const TUint KMMCCmdReliableWrite	=	KBit31;
-
+const TUint KMMCCmdTrim             =   KBit0;			//Trim command arg
 
 /**
 @publishedPartner
@@ -1463,7 +1531,7 @@
 /**
 	Extended CSD register class.
 	For more information about this register, see the MultimediaCard System 
-	Specification, Version 4.1+
+	Specification, Version 4.4
 
 	@publishedPartner
 	@released
@@ -1503,10 +1571,28 @@
 		EBusWidthModeIndex = 183,
 		/** Offset of the BOOT_CONFIG field */
 		EBootConfigIndex = 179,
+        /** Offset of the BOOT_CONFIG_PROT field */
+        EBootConfigProtectionIndex = 178,
 		/** Offset of the BOOT_BUS_WIDTH field */
 		EBootBusWidthIndex = 177,
 		/** Offset of the ERASE_GROUP_DEF field */
-		EEraseGroupDefIndex = 175
+		EEraseGroupDefIndex = 175,
+        /** Offset of the BOOT_WP field */
+        EBootAreaWriteProtectionIndex = 173,
+        /** Offset of the USER_WP field */
+        EUserAreaWriteProtectionIndex = 171,
+        /** Offset of the FW_CONFIG field */
+        EFwConfigIndex = 169,
+        /** Offset of the RST_n_FUNCTION field */
+        EHardwareResetFunctionIndex = 162,
+        /** Offset of the PARTITIONS_ATTRIBUTE field */
+        EPartitionsAttributeIndex = 156,
+        /** Offset of the PARTITION_SETTING_COMPLETED field */
+        EPartitionSettingIndex = 155,
+        /** Offset of the GP_SIZE_MULT field */
+
+
+
 		};
 
 	/** 
@@ -1524,6 +1610,17 @@
 		/** Offset of the HC_ERASE_GRP_SIZE field */
 		EHighCapacityEraseGroupSizeIndex = 224
 		};
+		
+	/**	This enum defines the values for the Extended CSD Revision register	*/
+	enum TExtendedCSDRev
+		{
+		EExtendedCSDRev1_0 = 0,
+		EExtendedCSDRev1_1 = 1,
+		EExtendedCSDRev1_2 = 2,
+		EExtendedCSDRev1_3 = 3,
+		EExtendedCSDRev1_4 = 4,
+		EExtendedCSDRev1_5 = 5
+		};
 
 	/** This enum defines the bus width encoding used by the BUS_WIDTH field */
 	enum TExtCSDBusWidths
@@ -1547,15 +1644,21 @@
 	/**
 	This enum defines the boot config encoding used by the BOOT_CONFIG field
 	*/
-	enum TExtCSDBootConfig
+	enum TExtCSDBootConfig // in v4.4 this is now called PARTITION_CONFIG
 		{
 		ESelectUserArea	 				= 0x00,
 		ESelectBootPartition1 			= 0x01,
 		ESelectBootPartition2 			= 0x02,
+		ESelectRPMB						= 0x03, // R/W Replay Protected Memory Block (RPMB)
+		ESelectGPAPartition1			= 0x04, // Access to General Purpose Area partition 1
+		ESelectGPAPartition2			= 0x05, // Access to General Purpose Area partition 2
+		ESelectGPAPartition3 			= 0x06, // Access to General Purpose Area partition 3
+		ESelectGPAPartition4 			= 0x07, // Access to General Purpose Area partition 4		
 		EEnableBootPartition1forBoot 	= 0x08,
 		EEnableBootPartition2forBoot 	= 0x10,
 		EEnableUserAreaforBoot			= 0x38,
-		EEnableBootAck  				= 0x40
+		EEnableBootAck  				= 0x40,
+		EPartitionTestMode              = 0x100 // Indicates test mode for eMMC partitions
 		};
 
 	/**
@@ -1698,6 +1801,9 @@
 	/** returns the contents of the BOOT_SIZE_MUTLI field */
 	inline TUint BootSizeMultiple() const;
 	
+	/** returns the size of the boot partitions in sectors */
+	inline TUint32 BootSizeInSectors() const;
+	
 	/** returns the contents of the ERASE_TIMEOUT_MULT field */
 	inline TUint EraseTimeoutMultiple() const;
 	
@@ -1719,13 +1825,77 @@
 	/** returns True if the CARD_TYPE field conatains a valid value **/
 	inline TBool IsSupportedCardType() const;
 
+    /** returns the contents of the ERASED_MEM_CONT field */
+    inline TUint ErasedMemoryContent() const;
+
+    /** returns the contents of the BOOT_CONFIG_PROT field */
+    inline TUint BootConfigProt() const;
+
+    /** returns the contents of the BOOT_WP field */
+    inline TUint BootAreaWriteProtectionReg() const;
+
+    /** returns the contents of the USER_WP field */
+    inline TUint UserAreaWriteProtectionReg() const;
+
+    /** returns the contents of the FW_CONFIG field */
+    inline TUint FwConfiguration() const;
+
+    /** returns the RPMB size based on contents of the RPMB_SIZE_MULT field */
+    inline TUint32 RpmbSize() const;
+    
+    /** returns the RPMB size in sectors */
+    inline TUint32 RpmbSizeInSectors() const;
+
+    /** returns the contents of the RST_n_FUNCTION field */
+    inline TUint HwResetFunction() const;
+
+    /** returns the contents of the PARTITIONING_SUPPORT field */
+    inline TUint PartitioningSupport() const;
+
+    /** returns the Max Enhanced Area Size base on the contents of the
+        MAX_ENH_SIZE_MULT field */
+    inline TUint32 MaxEnhancedAreaSize() const;
+
+    /** returns the contents of the PARTITIONS_ATTRIBUTE field */
+    inline TUint PartitionsAttribute() const;
+
+    /** returns the contents of the PARTITION_SETTING_COMPLETED field */
+    inline TUint PartitioningSetting() const;
+
+    /** returns the General purpose partition sizes based on contents of the
+        GP_SIZE_MULT fields */
+    inline TUint64 GeneralPurposePartition1Size() const;
+    inline TUint64 GeneralPurposePartition2Size() const;
+    inline TUint64 GeneralPurposePartition3Size() const;
+    inline TUint64 GeneralPurposePartition4Size() const;
+    
+    /** returns the General Purpose Partition sizes in sectors */
+    inline TUint32 GeneralPurposePartition1SizeInSectors() const;
+    inline TUint32 GeneralPurposePartition2SizeInSectors() const;
+    inline TUint32 GeneralPurposePartition3SizeInSectors() const;
+    inline TUint32 GeneralPurposePartition4SizeInSectors() const;
+
+    /** returns the Enhanced User Data Area Size based on thec contents of the
+        ENH_SIZE_MULT fields */
+    inline TUint64 EnhancedUserDataAreaSize() const;
+
+    /** returns the Enhanced User Data Start Address based on the contents of
+        the ENH_START_ADDR fields */
+    inline TUint32 EnhancedUserDataStartAddress() const;
+
+    /** returns the contents of the SEC_BAD_BLK_MGMNT field */
+    inline TUint BadBlockManagementMode() const;
+
 private:
+    inline TUint64 PartitionSize(TUint8 aMult0, TUint8 aMult1, TUint8 aMult2, TUint32 aMultiplier) const;
+
 	/** 
 	@internalComponent little endian 512 byte field representing extended CSD	
 	*/
 	TUint8 iData[KMMCExtendedCSDLength];
 	};
 
+const TInt KMMCSelectPartitionMask		= KBit0 | KBit1 | KBit2;
 
 //	32 bit MMC card status field (response R1)
 
@@ -1754,6 +1924,7 @@
 const TUint32 KMMCStatErrOutOfRange=	KBit31;
 
 const TUint32 KMMCStatErrorMask=		KMMCStatErrOutOfRange	|
+										KMMCStatSwitchError		|
 										KMMCStatErrAddressError	|
 										KMMCStatErrBlockLenError|
 										KMMCStatErrEraseSeqError|
@@ -2113,6 +2284,8 @@
 const TUint32 KMMCCmdFlagDoubleBuffer=  KBit7;  // The current DT command is double-buffered
 const TUint32 KMMCCmdFlagPhysAddr=		KBit8;  // Address is a physical address
 const TUint32 KMMCCmdFlagReliableWrite=	KBit9;  // Current command is Reliable Write
+const TUint32 KMMCCmdFlagDeleteNotify=  KBit10; // Current command is Delete Notify
+const TUint32 KMMCCmdFlagRpmbIO=        KBit11; // Current command is of RPMB type
 
 const TUint32 KMMCCmdFlagASSPFlags=	KMMCCmdFlagBytesValid	|
 									KMMCCmdFlagTransStopped	|
@@ -2948,6 +3121,11 @@
 	inline void SetupCIMWriteBlock(TMMCArgument aBlockAddr, TUint8* aMemoryP, TUint32 aBlocks = 1);
 	inline void SetupCIMEraseMSector(TMMCArgument aBlockAddr, TUint32 aBlocks = 1);
 	inline void SetupCIMEraseMGroup(TMMCArgument aBlockAddr, TUint32 aBlocks = 1);
+	
+	// RPMB access macros setup
+	inline void SetupRpmbSendRequest(TBool aSetReliableWrite);
+    inline void SetupRpmbReceiveResponse();
+    inline void SetupRpmbSendReadResultRegisterRequest();
 		
 	// Raw commands (must be used in the locked bus state only)
 	// Known commands with or without (with a default) argument
@@ -3008,6 +3186,9 @@
 	
 	inline void PushCommandStack();
 	inline void PopCommandStack();
+	
+	inline void SetPartition(TInt aPartition);
+	inline TInt Partition() const;
 
 	// Methods for double-buffered data transfer:
 	inline TBool RequestMoreData();
@@ -3061,8 +3242,10 @@
 	
 	TMMCCallBack iDataTransferCallback;	// A callback function, used to request more data when performing double-buffering
 
-	TUint32 iSpare[21];				// Spare data (stolen from iCommand)
-
+	TUint32 iSpare[20];					// Spare data (stolen from iCommand)
+	
+	TUint32 iPartition;					// The targetted partition
+	
 	TMMCard* iSavedCardP;			// Saved copy of iCardP
 
 	TMMCStateMachine iMachine;		// State Machine context
@@ -3496,6 +3679,8 @@
 	inline   TMMCErr ProgramTimerSM();
 	static   TMMCErr GoIdleSMST(TAny* aStackP);
 	inline	 TMMCErr GoIdleSM();
+	static   TMMCErr SwitchPartitionSMST(TAny* aStackP);
+	inline	 TMMCErr SwitchPartitionSM();
 
 	static   TMMCErr SwitchToLowVoltageSMST(TAny* aStackP);
 	
@@ -3524,6 +3709,21 @@
 	static   TMMCErr ExecBusTestSMST(TAny* aStackP);
 	inline	 TMMCErr ExecBusTestSM();
 
+	static TMMCErr CIMRpmbAccessSMST(TAny* aStackP);
+    TMMCErr CIMRpmbAccessSM();
+
+	static TMMCErr  CIMRpmbWriteAuthenticationKeySMST(TAny* aStackP);
+    TMMCErr CIMRpmbWriteAuthenticationKeySM();
+
+	static TMMCErr CIMRpmbReadWrCounterSMST(TAny* aStackP);
+    TMMCErr CIMRpmbReadWrCounterSM();
+
+	static TMMCErr CIMRpmbWriteSMST(TAny* aStackP);
+    TMMCErr CIMRpmbWriteSM();
+
+	static TMMCErr CIMRpmbReadSMST(TAny* aStackP);
+    TMMCErr CIMRpmbReadSM();
+
 	enum TBusWidthAndClock
 		{
 		E1Bit20Mhz  = 0x0000,
@@ -3616,11 +3816,6 @@
 	friend class DMMCSession;
 	friend class TMMCardArray;
 
-private:
-    //
-    // Dummy functions to maintain binary compatibility
-    IMPORT_C virtual void Dummy1();
-
 protected:
 	/** 
 	Gets an interface from a derived class
@@ -3651,8 +3846,8 @@
 
 
 
-
 class TMMCMachineInfo
+
 /**
 	Platform-specific configuration information for the 
 	MultiMediaCard stack.
@@ -3814,9 +4009,6 @@
 
 
 
-
-typedef TPckg<TMMCMachineInfo> TMMCardMachineInfoPckg;
-
 /**
 	Platform-specific configuration information for the 
 	MultiMediaCard stack. Contains information pertinent to 
@@ -3874,6 +4066,43 @@
 	};
 
 
+
+/**
+	Platform-specific configuration information for the 
+	MultiMediaCard stack. Contains information pertinent to 
+	MMC specification version 4.4
+	
+	An object of this type is passed to the Variant implementation
+	of DMMCStack::MachineInfo(), which should fill the public data
+	members with appropriate information and values.
+
+@internalComponent
+*/
+class TMMCMachineInfoV44 : public TMMCMachineInfoV4
+	{
+public:
+	inline TMMCMachineInfoV44() {memclr(this, sizeof(*this));}
+
+	/**
+	The version of the structure returned by the PSL in a call to 
+	DMMStack::MachineInfo()
+	The fields defined in TMMCMachineInfoV44 are only valid if the 
+	version is EVersion44 or higher
+	*/
+	enum TVersion {EVersion3, EVersion4, EVersion44};
+
+    /**
+    Use iRpmbSlotCount and iRpmbSlotList to define a list of up to
+	four slots for devices containing an RPMB partitions to be 
+	exposed
+    */
+	TUint iRpmbSlotCount;
+	TUint * iRpmbSlotList;
+	
+	TUint8 iSpare[14];
+	};
+
+
 class DMMCPsu : public DPBusPsuBase 
 /**
 	DPBusPsuBase derived abstract class to control the MMC socket's power supply.
@@ -4130,6 +4359,7 @@
 		EMMCInvalidCardNumber			=19,
 		EMMCNotInDfcContext				=20,
 		EMMCAddressCardNotSupported		=21,
+		EMMCInvalidPartitionNumber      =22
 		};
     IMPORT_C static void Panic(TMMCPanic aPanic);
 	friend class DMMCStack;
--- a/kernel/eka/include/drivers/mmc.inl	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/include/drivers/mmc.inl	Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1999-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"
@@ -17,6 +17,9 @@
 //          outside the Kernel and Hardware Services package.
 //
 
+const TInt KOneKiloByte = 1024;
+const TInt KSectorSize  = 512;
+
 /**
  
  A static function that takes the 4 bytes that are stored in a memory location
@@ -180,6 +183,132 @@
 inline TUint TExtendedCSD::SleepCurrentVccQ() const {return iData[219];}
 inline TUint TExtendedCSD::SleepAwakeTimeout() const {return iData[217];}
 
+inline TUint TExtendedCSD::ErasedMemoryContent() const {return iData[181];}
+inline TUint TExtendedCSD::BootConfigProt() const {return iData[EBootConfigProtectionIndex];}
+inline TUint TExtendedCSD::BootAreaWriteProtectionReg() const {return iData[EBootAreaWriteProtectionIndex];}
+inline TUint TExtendedCSD::UserAreaWriteProtectionReg() const {return iData[EUserAreaWriteProtectionIndex];}
+inline TUint TExtendedCSD::FwConfiguration() const {return iData[EFwConfigIndex];}
+
+
+inline TUint32 TExtendedCSD::BootSizeInSectors() const
+	{
+		
+	return BootSizeMultiple() * 128 * KOneKiloByte / KSectorSize;
+	}
+
+inline TUint32 TExtendedCSD::RpmbSize() const 
+    {
+    return static_cast<TUint32>(iData[168]);
+    }
+    
+inline TUint32 TExtendedCSD::RpmbSizeInSectors() const 
+	{
+	
+	return RpmbSize() * 128 * KOneKiloByte / KSectorSize;
+	}
+
+inline TUint TExtendedCSD::HwResetFunction() const {return iData[EHardwareResetFunctionIndex];}
+inline TUint TExtendedCSD::PartitioningSupport() const {return iData[160];}
+
+inline TUint32 TExtendedCSD::MaxEnhancedAreaSize() const 
+    {
+    return(iData[157] | 
+           (static_cast<TUint32>(iData[158]) << 8) | 
+           (static_cast<TUint32>(iData[159]) << 16) * 
+           HighCapacityWriteProtectGroupSize());
+    }
+
+inline TUint TExtendedCSD::PartitionsAttribute() const {return iData[EPartitionsAttributeIndex];}
+inline TUint TExtendedCSD::PartitioningSetting() const {return iData[EPartitionSettingIndex];}
+
+inline TUint64 TExtendedCSD::PartitionSize(TUint8 aMult0, TUint8 aMult1, TUint8 aMult2, TUint32 aMultiplier) const
+    {
+    TUint64 size = static_cast<TUint64>(aMult2) * 8 * 8;
+    size +=  static_cast<TUint64>(aMult1) * 8;
+    size += static_cast<TUint64>(aMult0);
+    
+    size *= aMultiplier;
+    return size;
+    }
+
+inline TUint64 TExtendedCSD::GeneralPurposePartition1Size() const 
+    {
+    return PartitionSize(iData[143], 
+                         iData[144], 
+                         iData[145], 
+                         (HighCapacityWriteProtectGroupSize() * HighCapacityEraseGroupSize() * 512 * 1024)
+                        );            
+    }
+    
+inline TUint32 TExtendedCSD::GeneralPurposePartition1SizeInSectors() const 
+	{
+	return I64LOW(GeneralPurposePartition1Size() / KSectorSize);
+	}
+
+inline TUint64 TExtendedCSD::GeneralPurposePartition2Size() const 
+    {
+    return PartitionSize(iData[146], 
+                         iData[147], 
+                         iData[148], 
+                         (HighCapacityWriteProtectGroupSize() * HighCapacityEraseGroupSize() * 512 * 1024)
+                        );
+    }
+    
+inline TUint32 TExtendedCSD::GeneralPurposePartition2SizeInSectors() const 
+	{
+	return I64LOW(GeneralPurposePartition2Size() / KSectorSize);
+	}
+
+    
+inline TUint64 TExtendedCSD::GeneralPurposePartition3Size() const 
+    {
+    return PartitionSize(iData[149], 
+                         iData[150], 
+                         iData[151], 
+                         (HighCapacityWriteProtectGroupSize() * HighCapacityEraseGroupSize() * 512 * 1024)
+                        );
+    }
+
+inline TUint32 TExtendedCSD::GeneralPurposePartition3SizeInSectors() const 
+	{
+	return I64LOW(GeneralPurposePartition3Size() / KSectorSize);
+	}
+
+inline TUint64 TExtendedCSD::GeneralPurposePartition4Size() const 
+    {
+    return PartitionSize(iData[152], 
+                         iData[153], 
+                         iData[154], 
+                         (HighCapacityWriteProtectGroupSize() * HighCapacityEraseGroupSize() * 512 * 1024)
+                        );
+
+    }
+
+inline TUint32 TExtendedCSD::GeneralPurposePartition4SizeInSectors() const 
+	{
+	return I64LOW(GeneralPurposePartition4Size() / KSectorSize);
+	}
+
+inline TUint64 TExtendedCSD::EnhancedUserDataAreaSize() const 
+    {
+    return PartitionSize(iData[140],
+                         iData[141],
+                         iData[142],
+                         HighCapacityWriteProtectGroupSize()
+                        );
+    }
+
+inline TUint32 TExtendedCSD::EnhancedUserDataStartAddress() const 
+    {
+	// note, for HC devices this is in sectors, otherwise in bytes
+    return(iData[136] | 
+           (static_cast<TUint32>(iData[137]) << 8) | 
+           (static_cast<TUint32>(iData[138]) << 16) | 
+           (static_cast<TUint32>(iData[139]) << 24));
+    }
+
+inline TUint TExtendedCSD::BadBlockManagementMode() const {return iData[134];}
+
 // "Modes Segment" of Extended CSD - i.e. modifiable fields
 inline TUint TExtendedCSD::CmdSet() const {return iData[ECmdSetIndex];}
 inline TUint TExtendedCSD::CmdSetRev() const {return iData[ECmdSetRevIndex];}
@@ -944,6 +1073,33 @@
 		DMMCSocket::Panic(DMMCSocket::EMMCCommandStack));
 	}
 
+
+/**
+Sets the target partition access bits
+*/	
+inline void DMMCSession::SetPartition(TInt aPartition) 
+	{
+	TInt partition = aPartition & ~TExtendedCSD::EPartitionTestMode;
+	__ASSERT_DEBUG( 
+		partition >= TExtendedCSD::ESelectUserArea && 
+		partition <= TExtendedCSD::ESelectGPAPartition4, 
+		DMMCSocket::Panic(DMMCSocket::EMMCInvalidPartitionNumber));
+		
+		iPartition = partition;
+		iPartition |= aPartition & TExtendedCSD::EPartitionTestMode;
+	}
+
+
+/**
+ * Returns the target partition
+ * @return The partition access identifier for which this session is destined
+*/	
+inline TInt DMMCSession::Partition() const
+	{
+	return iPartition;
+	}
+
+
 inline TMMCCommandDesc& DMMCSession::Command()
 /**
  * Returns the current command, as referred to by the stack pointer.
@@ -1041,6 +1197,66 @@
 	iSessionID = ECIMEraseGroup;
 	}
 
+inline void DMMCSession::SetupRpmbSendReadResultRegisterRequest()
+    {
+/**
+ * Sets the session to send an RPMB read result register request to the RPMB partition.
+ *  
+ * Having set-up the session for this operation, the client must invoke, SMF_INVOKES. the 
+ * read write state machine. CIMReadWriteBlocksSM, and the operation will commence. The read
+ * write state machine initiates the result register read sequence by issuing the Write Multiple 
+ * command, CMD25. Prior to this the state machine has issued CMD23 with the block count set 
+ * to 1.
+ *  
+ *  
+ * All other RPMB request packets initiate an RPMB access and are constructed in the security code 
+ * and sent to the stack via the security driver and the RPMB kernel extension DLL. The result 
+ * register read request is used part ways through the program key and data write accesses to find 
+ * out about the success of the particular operation. It is not sent via the RPMB kernel extension 
+ * DLL so it is constructed here. Luckily it is easy to make.
+ */
+    TUint8* readRequestPtr = Command().iDataMemoryP;
+    memset(readRequestPtr, 0, KRpmbOneFramePacketLength);
+    * (readRequestPtr + KRpmbRequestLsbOffset) = KRpmbRequestReadResultRegister;
+    SetupRpmbSendRequest(EFalse);
+    }
+
+inline void DMMCSession::SetupRpmbSendRequest(TBool aSetReliableWrite)
+/**
+ * Sets the session to send an RPMB request to the RPMB partition.
+ *  
+ * Having set-up the session for this operation, the client must invoke, SMF_INVOKES, the 
+ * read write state machine, CIMReadWriteBlocksSM, and the operation will commence. The read
+ * write state machine initiates the result read sequence by issuing the Write Multiple 
+ * command, CMD25. Prior to this the state machine has issued CMD23 with the block count set 
+ * to 1 and optionally, if aSetReliableWrite is TRUE, with the arguement bit (31) set to 1. 
+ */
+    {
+    iSessionID=ECIMWriteMBlock;
+    Command().iCommand = ECmdWriteMultipleBlock;
+    Command().iFlags |= KMMCCmdFlagRpmbIO;
+    if (aSetReliableWrite)
+        {
+        Command().iFlags |= KMMCCmdFlagReliableWrite;
+        }
+    }
+
+inline void DMMCSession::SetupRpmbReceiveResponse()
+/**
+ * Sets the session to receive an RPMB resposne from the RPMB partition.
+ * 
+ * Having set-up the session for this operation, the client must invoke ,SMF_INVOKES. the 
+ * read write state machine, CIMReadWriteBlocksSM, and the operation will commence. The read
+ * write state machine initiates the result read sequence by issuing the Read Multiple 
+ * command, CMD18. Prior to this the state machine has issued CMD23 with the block count set 
+ * to 1.
+ */
+    {
+    iSessionID=ECIMReadMBlock;
+    Command().iCommand = ECmdReadMultipleBlock;
+    Command().iFlags |= KMMCCmdFlagRpmbIO;
+    }
+
 inline void DMMCSession::EnableDoubleBuffering(TUint32 aNumBlocks)
 /**
  * When called before a data transfer operation is engaged, specifies that the data 
@@ -1555,3 +1771,34 @@
  * @return ETrue if Erase Group commands are supported.
  */
 	{return(iEraseFlags&KMMCEraseGroupCmdsSupported);}
+
+/**
+Return RPMB information.
+@param aDeviceIndex The RPMB specific device index. Must be zero in current implementation
+@param aParams Retrieves the RPMB specific information required for initialisation
+*/
+
+inline TInt MRpmbInfo::RpmbInfo(TUint aDeviceIndex, TRpmbDeviceParms& aParams)
+    {
+	// note that MMCGetExtInterface doesn't hand out an instance of MRpmbInfo until
+	// RpmbParmsPopulated is true so baseport configuration has been read and any 
+	// changes to NumberOfRpmbs and TheRpmbs are flushed
+	if (aDeviceIndex>MaxIndexRpmb)
+		{
+		// currently support just one RPMB capable device at index 0
+		return KErrGeneral;
+		}
+	else
+		{
+		if (NumberOfRpmbs==0)
+			{
+			// baseport configuration doesn't include an RPMB partition
+			return KErrNotSupported;
+			}
+		else
+			{	
+			aParams = TheRpmbs[0];
+			return KErrNone;
+			}
+		}
+	}	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/include/drivers/rpmbdevice.h	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,66 @@
+// Copyright (c) 1994-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:
+// eka\include\drivers\rpmb\rpmbdevice.h
+
+/**
+ @file
+ @internalTechnology
+*/
+
+
+#include <drivers/mmc.h>
+#include <e32cmn.h>
+
+const TUint KBusNumber = 0;
+const TUint KDeviceAddress = 0; //Address on card is not applicable to RPMB. This is handled on media device.
+const TUint8 KIndexNotAssigned = 0xFF;
+
+class DRpmbDevice : public DBase
+    {
+   public:
+    
+    IMPORT_C DRpmbDevice();
+    IMPORT_C ~DRpmbDevice();
+    IMPORT_C TInt Open(TUint aDeviceIndex);
+    IMPORT_C TInt SendAccessRequest(TDes8 &aRpmbRequest, TDes8 &aRpmbResponse);
+    IMPORT_C void Close();
+        
+   private:
+   
+    static void SessionEndCallBack(TAny* aSelf);
+    static void BusCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2);
+    void DoSessionEndCallBack();
+    TInt PowerUpStack();
+	void SetSynchronisationParms(TUint8 aDeviceIndex);
+	void ClearSynchronisationParms();
+    
+    DSemaphore* iPowerUpSemaphore;
+	DSemaphore* iRequestSemaphore;
+	NFastMutex iSynchronisationParmsMutex;
+
+	DMMCSession* iSession;
+    TMMCard* iCard;
+    DMMCSocket* iSocket;
+
+	TPBusCallBack iBusCallBack;     
+	TMMCCallBack iSessionEndCallBack;
+
+	TUint8* iIntBuf;	
+
+	TUint8 iDeviceIndex;
+	static DRpmbDevice* DRpmbDevicePtrs[KMaxPBusSockets*4];
+	
+	TUint8 iSpare[10]; //for future use
+    
+    };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/include/drivers/rpmbpacket.h	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,73 @@
+// Copyright (c) 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:
+// eka\include\drivers\rpmb\rpmbpacket.h
+
+/**
+ @file
+ @internalTechnology
+ @prototype
+*/
+
+#ifndef RPMBPACKET_H
+#define RPMBPACKET_H
+
+// RPMB packet constants
+
+const TInt KRpmbOneFramePacketLength = 512;
+
+// request field offsets
+const TUint KRpmbRequestLsbOffset = 511;
+const TUint KRpmbRequestMsbOffset = 510;
+// request field values
+const TUint KRpmbRequestWriteKey = 0x0001;
+const TUint KRpmbRequestReadWriteCounter = 0x0002;
+const TUint KRpmbRequestWriteData = 0x0003;
+const TUint KRpmbRequestReadData = 0x0004;
+const TUint KRpmbRequestReadResultRegister = 0x0005;
+
+// response field offsets
+const TUint KRpmbResponseLsbOffset = 511;
+const TUint KRpmbResponseMsbOffset = 510;
+// response field values
+const TUint KRpmbResponseWriteKey = 0x0100;
+const TUint KRpmbResponseReadWriteCounter = 0x0200;
+const TUint KRpmbResponseWriteData = 0x0300;
+const TUint KRpmbResponseReadData = 0x0400;
+
+// result field offsets
+const TUint KRpmbResultLsbOffset = 509;
+const TUint KRpmbResultMsbOffset = 508;
+// result field counter expired mask
+const TUint KRpmbResultCounterExpiredMask = 0x007F;
+// result field values
+const TUint KRpmbResultOk = 0x0000;
+const TUint KRpmbResultGeneralFailure = 0x0001;
+const TUint KRpmbResultAuthenticationFailure = 0x0002;
+const TUint KRpmbResultKeyNotProgrammed = 0x0007;
+
+// counter field offsets
+const TUint	KRpmbCounterByteOneOffset = 503;
+const TUint KRpmbCounterByteTwoOffset  = 502;
+const TUint KRpmbCounterByteThreeOffset = 501;
+const TUint KRpmbCounterByteFourOffset = 500;
+
+// key field
+const TUint KRpmbKeyLength = 32;
+const TUint KRpmbKeyOffset = 196;
+
+// data field
+const TUint KRpmbDataLength = 256;
+const TUint KRpmbDataOffset = 228;
+
+#endif /* #ifndef RPMBPACKET_H */
\ No newline at end of file
--- a/kernel/eka/include/e32ver.h	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/include/e32ver.h	Mon Oct 11 19:11:06 2010 +0100
@@ -28,7 +28,7 @@
 
 const TInt KE32MajorVersionNumber=2;
 const TInt KE32MinorVersionNumber=0;
-const TInt KE32BuildVersionNumber=4008;
+const TInt KE32BuildVersionNumber=4009;
 
 const TInt KMachineConfigurationMajorVersionNumber=1;
 const TInt KMachineConfigurationMinorVersionNumber=0;
--- a/kernel/eka/release.txt	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/release.txt	Mon Oct 11 19:11:06 2010 +0100
@@ -1,3 +1,20 @@
+Version 2.00.4009
+=================
+(Made by fadhliM 07/10/2010)
+
+1.	hengrant
+	1.	RP 531855	eMMC 4.4 User Data Partitions
+		REQ 417-54821	MMC v4.4 support for eMMC (Bridge M4)
+		SUB 417-73300	eMMC V4.4
+		SUB 417-73303	eMMC v4.4 - User-Data partitions with Enhanced Attributes Support
+	2.	RP 529139	eMMC 4.4 RPMB
+		REQ 417-75165	MMC v4.4 support for eMMC (Bridge M5)
+		SUB 417-59932	eMMC v4.4 - Replay Protected Memory Block (RPMB) support 
+	3.	RP 543420
+		REQ 417-75165	MMC v4.4 support for eMMC (Bridge M5)
+		SUB 417-73302	eMMC v4.4 - TRIM Support
+
+
 Version 2.00.4008
 =================
 (Made by fadhliM 05/10/2010)
@@ -38,7 +55,9 @@
 (Made by vfebvre 27/09/2010)
 
 1.	erifung
-	1.	RP540323 REQ:405-4716 kernel side device driver staged shutdown feature
+	1.	RP 540346
+		REQ 405-4716 Staged shutdown server monitor
+		SUB 417-75212 Staged shutdown server monitor - kernel-side component
 
 
 Version 2.00.4005
@@ -49,7 +68,10 @@
 	1.	ou1cimx1#584587 PRM RBusDevResManUs::ChangeResourceState() to set a resource level to "0", causes FAULT: RESMANUS 0x000001e3 (483)
 
 2.	seolney
-	1.	ou1cimx1#553109 REQ 405-4716, Feature 405-5174: Staged shutdown server monitor
+	1.	RP 506754
+		REQ 405-4716	Staged shutdown server monitor
+		SUB 417-75146	Shutdown Monitor: Domain Manager
+		ou1cimx1#553109 REQ 405-4716, Feature 405-5174: Staged shutdown server monitor
 
 3.	necliffo
 	1.	ou1cimx1#584508 Improve Code Coverage for LocalMedia Subsystem and MMC Stack
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/rombuild/rpmbtest.oby	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,30 @@
+/*
+* Copyright (c) 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:
+*
+*/
+#define BASE_ROM
+#include <rom\##VARIANT##\header.iby>
+
+files=
+
+#include <rom\##VARIANT##\kernel.iby>
+#include "user.iby"
+#include <rom\hal\hal.iby>
+#include <rom\f32\f32.iby>
+
+// And now the t_rpmb test
+#include <rom##E32PATH##\kernelhwsrv\kerneltest\e32test\rpmb\##MAIN##test.iby>
+
+data=\epoc32\rom\e32test\rpmb\autoexec.bat				\autoexec.bat
\ No newline at end of file
--- a/kerneltest/e32test/group/t_mmcdrv.mmp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kerneltest/e32test/group/t_mmcdrv.mmp	Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1995-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"
@@ -17,6 +17,7 @@
 
 TARGET         t_mmcdrv.exe        
 TARGETTYPE     EXE
+USERINCLUDE    ../../../kernel/eka/drivers/medmmc
 SOURCEPATH	../pccd
 SOURCE         t_mmcdrv.cpp
 LIBRARY        euser.lib
--- a/kerneltest/e32test/pccd/t_mmcdrv.cpp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kerneltest/e32test/pccd/t_mmcdrv.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1996-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"
@@ -13,10 +13,12 @@
 // Description:
 // e32test\pccd\t_mmcdrv.cpp
 // Test the MultiMediaCard (MMC) media driver
-// Spare Test case Numbers 0513-0519
+// Spare Test case Numbers 0515-0519
 // 
 //
 
+#define __E32TEST_EXTENSION__
+
 #include "../mmu/d_sharedchunk.h"
 #include <e32test.h>
 #include <e32svr.h>
@@ -1860,8 +1862,122 @@
 	test(SecThreadChangeFlag==EFalse); // Closed 2nd thread so shouldn't have been updated
 	}
 	
+// Helper function for eMMC partition switching test - writes test data
+TInt EMmcPartitionWriteTestData(const TInt aDriveNumber, const TChar aDataPattern)
+	{
+	TBusLocalDrive drv;
+	TBool chg(EFalse);
+
+	TInt r = drv.Connect(aDriveNumber, chg);
+	test(r == KErrNone);
+
+	TBuf8<KDiskSectorSize> buffer;
+
+	// write pattern to sector 0
+	buffer.Fill(aDataPattern, KDiskSectorSize);
+	r = drv.Write((TInt64) 0, buffer);
+	
+	return r;
+	}
+	
+// Helper function for eMMC partition switching test - reads test data
+TInt EMmcPartitionReadTestData(const TInt aDriveNumber, TDes8& aData)
+	{
+	// read pattern from sector 0
+	TBusLocalDrive drv;
+	TBool chg(EFalse);
+	
+	TInt r = drv.Connect(aDriveNumber, chg);	
+	test(r == KErrNone);
+	
+	aData.Fill(0x00, aData.MaxSize());
+	r = drv.Read((TInt64) 0, aData.MaxSize(), aData);
+
+    drv.Disconnect();
+    return r;
+	}
+	
+// Helper function for eMMC partition switching test - compares data to expected pattern
+TInt EMmcPartitionReadAndCompareTestData(const TInt aDriveNumber, const TChar aExpectedPattern)
+	{	
+	TBuf8<KDiskSectorSize> actual;
+	TBuf8<KDiskSectorSize> expected;
+	TInt r = EMmcPartitionReadTestData(aDriveNumber, actual);
+	test(r == KErrNone);
+	
+	expected.Fill(aExpectedPattern, KDiskSectorSize);
+	
+	if(expected.Compare(actual) != 0)
+		{
+		test.Printf(_L("ERROR: Comparison failed. Expected:\n"));
+		DumpBuffer(expected);			
+		test.Printf(_L("\nActual:\n"));
+		DumpBuffer(actual);
+		r = KErrGeneral;
+		}
+		
+	return r;
+	}
+	
+
+		
+/**
+@SYMTestCaseID 0514 (taken from spare test case IDs)
+@SYMTestCaseDesc Test low-level partition switching capability
+@SYMTestPriority normal
+
+@SYMTestActions
+	a) Precondition: Valid partitions have been flashed to BOOT 1 and BOOT 2, 
+	   these have to be mapped correctly in variantmediadef.h
+	b) Write Data Pattern 1 to BOOT 1
+	c) Write Data Pattern 2 to BOOT 2
+	d) Read data from BOOT 1 and compare to DP1 - test passes if data matches
+	e) Write Data Pattern 3 to BOOT 1, at the same offset as in b)
+	f) Read data from BOOT 2 and compare to DP2 - test passes if data matches
+
+@SYMTestExpectedResults All tests must pass	
+*/
+void TestPartitionSwitching()
+	{
+	const TInt  KDriveBoot1      = 4; // see variantmediadef.h
+	const TInt  KDriveBoot2      = 5;
+	const TChar KDataPattern1    = 0xD1;
+	const TChar KDataPattern2    = 0xD2;
+	const TChar KDataPattern3    = 0xD3;
+	
+	test.Start(_L("eMMC partition switching"));
+
+	// Write data data pattern 1 to boot1
+	test.Printf(_L("Writing Data Pattern 1 to BOOT 1\n"));
+	TInt r = EMmcPartitionWriteTestData(KDriveBoot1, KDataPattern1);
+	test(r == KErrNone);
+
+	// Write data data pattern 2 to boot2
+	test.Printf(_L("Writing Data Pattern 2 to BOOT 2\n"));
+	r = EMmcPartitionWriteTestData(KDriveBoot2, KDataPattern2);
+	test(r == KErrNone);
+
+	// Read back data from boot 1 and compare it to previously written pattern
+	test.Printf(_L("Reading from BOOT 1\n"));
+	r = EMmcPartitionReadAndCompareTestData(KDriveBoot1, KDataPattern1);
+	test(r == KErrNone);
+
+	// Write data data pattern 3 to boot1
+	test.Printf(_L("Writing Data Pattern 3 to BOOT 1\n"));
+	r = EMmcPartitionWriteTestData(KDriveBoot1, KDataPattern3);
+	test(r == KErrNone);
+	
+	// Read back data from boot 2 and compare it to previously written pattern
+	test.Printf(_L("Reading from BOOT 2\n"));
+	r = EMmcPartitionReadAndCompareTestData(KDriveBoot2, KDataPattern2);
+	test(r == KErrNone);
+	
+	test.End();
+	}
 
 //// End of Test 
+
+
 void Format()
 //
 // Format current drive
@@ -2203,39 +2319,53 @@
 	goto doorTest;
 #endif
 	
+	if(ManualMode)
+		{
+		// Only test in manual mode, as the rom needs special prep anyway (drive registration 
+		// in variantmediadef.h and flashing of BB5 partition info structures using mmcloader)
+		// It is possible that as a result of the changes to variantmediadef.h the 
+		// drive-number-to-letter mapping in the appropriate estart.txt may have to be adjusted 
+		// as well
+		TestPartitionSwitching();
+		}
+	
 	for(TInt pass = 0; pass < TMMCDrive::EMaxTestModes; pass++) 
 		{
 		TInt r = KErrNone;
+		
 		switch (pass)
 			{			
-			case 0 : r = TheMmcDrive.SetTestMode(TMMCDrive::ETestPartition); break;
-			case 1 : 
+			case TMMCDrive::ETestPartition : 
+				r = TheMmcDrive.SetTestMode(TMMCDrive::ETestPartition); 
+				break;
+				
+			case TMMCDrive::ETestWholeMedia : 
 				// don't trash partition table in automated mode because...
 				// cards in test rigs have often got deliberately small partition sizes to testing (!)
 				if (!ManualMode)
 					continue;
 				r = TheMmcDrive.SetTestMode(TMMCDrive::ETestWholeMedia); 
 				break; 
-			case 2 : {
-						r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemory);
-						AllocateSharedBuffers(EFalse,EFalse);
-						break;
-					 }
-			case 3 : {
-						r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryCache); 
-						AllocateSharedBuffers(EFalse, ETrue);
-						break;
-					 }
-			case 4 : {
-						r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryFrag);
-						AllocateSharedBuffers(ETrue, EFalse);
-						break;
-			         }
-			default: {
-						r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryFragCache);
-						AllocateSharedBuffers(ETrue, ETrue);
-						break;
-			         }
+				
+			case TMMCDrive::ETestSharedMemory :
+				r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemory);
+				AllocateSharedBuffers(EFalse,EFalse);
+				break;
+				
+			case TMMCDrive::ETestSharedMemoryCache :
+				r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryCache); 
+				AllocateSharedBuffers(EFalse, ETrue);
+				break;
+				
+			case TMMCDrive::ETestSharedMemoryFrag :
+				r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryFrag);
+				AllocateSharedBuffers(ETrue, EFalse);
+				break;
+				
+			default:
+				r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryFragCache);
+				AllocateSharedBuffers(ETrue, ETrue);
+				break;
 			}
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/bld.inf	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,36 @@
+// Copyright (c) 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:
+// e32test/rpmb/bld.inf
+// Kernel and User library test code
+// 
+//
+
+/**
+ @file
+*/
+
+
+PRJ_PLATFORMS
+
+BASEDEFAULT
+
+PRJ_EXPORTS
+
+PRJ_TESTEXPORTS
+
+rpmbtestautoexec.bat \epoc32\rom\e32test\rpmb\autoexec.bat
+
+PRJ_TESTMMPFILES
+
+t_rpmb
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/driver/bld.inf	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,34 @@
+// Copyright (c) 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:
+// e32test/rpmb/driver/bld.inf
+// Kernel and User library test code
+// 
+//
+
+/**
+ @file
+*/
+
+
+PRJ_PLATFORMS
+
+BASEDEFAULT
+
+PRJ_EXPORTS
+
+PRJ_TESTEXPORTS
+
+PRJ_TESTMMPFILES
+
+d_rpmb support
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/driver/d_rpmb.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,1225 @@
+// Copyright (c) 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:
+// e32test/rpmb/d_rpmb.cpp
+// LDD for testing RPMB kernel extension
+// 
+//
+
+/**
+ @file
+ @internalComponent
+ @prototype
+*/
+
+#include "d_rpmb.h"
+#include "../t_rpmb.h"
+
+_LIT(KRpmbTestThreadName,"RpmbTestThread");
+const TInt KRpmbTestPriority = 24;
+
+TDfcQue RpmbTestDfcQ;
+TDfc* DfcPtr;
+
+// please read this before uncommenting out #define RPMBTESTS_TRY_TO_WRITE_KEY:
+// Don't want to write key 'pre production' on real device as this will lock 
+// the system out of the RPMB partition (the key should be preprogrammed as 
+// part of the production process so that the system has access to the key - 
+// if the key has already been written it can't be written again).
+// #define RPMBTESTS_TRY_TO_WRITE_KEY
+
+
+/****************************************
+ Implementation of DRpmbTestFactory class
+*****************************************/
+
+DRpmbTestFactory::DRpmbTestFactory()
+	{
+	}
+
+DRpmbTestFactory::~DRpmbTestFactory()
+	{
+	}
+
+TInt DRpmbTestFactory::Create(DLogicalChannelBase*& aChannel)
+	{
+	aChannel = new DRpmbTest;
+	return KErrNone;
+	}
+
+TInt DRpmbTestFactory::Install()
+	{
+	return SetName(&KRpmbTestLddName);
+	}
+
+void DRpmbTestFactory::GetCaps(TDes8& /*aDes*/) const
+// implementation required since DLogicalDevice::GetCaps is pure virtual
+	{
+	// do nothing 
+	}
+
+
+static void RpmbTestDfcFunction(TAny* /*aPtr*/)
+	{
+	DRpmbDevice * rpmb;
+	rpmb = new DRpmbDevice;
+	TInt r = rpmb->Open(0);
+	Kern::Printf("%S Early on DRpmbDevice::Open test returned %d",&KDRpmbTestBanner, r);
+	// ASSERT to indicate test failure if DRpmbDevice::Open() returned error
+	__ASSERT_ALWAYS((r==KErrNone), Kern::Fault(__FILE__, __LINE__));
+	rpmb->Close();
+	delete rpmb;
+	// run more extensive tests early on 
+	// note the unconventional use of a class derived from DLogicalChannelBase which is justified
+	// in the current context to provide more startup test coverage
+	DRpmbTest * test;
+	test = new DRpmbTest;
+	// while a call to DRpmbTest::DRpmbDeviceTests() works in this context
+	// a call to DRpmbTest::RpmbStackTests() would fail as DRpmbTest::DoCreate() wouldn't be
+	// called so that DRpmbTest::iStackSemPtr wouldn't get set up properly so that when it 
+	// was uaed an exception would be generated
+	r = test->DRpmbDeviceTests();
+	Kern::Printf("%S Early on DRpmbTest::DRpmbDeviceTests() returned %d",&KDRpmbTestBanner, r);
+	// ASSERT to indicate test failure
+	__ASSERT_ALWAYS((r==KErrNone), Kern::Fault(__FILE__, __LINE__));
+	// not safe to delete test as  not setup conventionally DRpmbTest::DoCreate() wasn't called 
+	// at setup and DLogicalChannelBase::~DLogicalChannelBase__sub_object() would generate an 
+	// exception
+	}
+
+
+/********************************
+ Entry point for RPMB test driver
+*********************************/
+
+DECLARE_STANDARD_EXTENSION()
+    {     
+	TInt r = Kern::DfcQInit(&RpmbTestDfcQ,KRpmbTestPriority,&KRpmbTestThreadName);;      
+	if (r != KErrNone)
+		return r;
+	DfcPtr = new TDfc(RpmbTestDfcFunction,NULL, &RpmbTestDfcQ, KMaxDfcPriority-7);
+	DfcPtr->Enque();     
+	return KErrNone;
+    }
+
+DECLARE_EXTENSION_LDD()
+	{
+	return new DRpmbTestFactory;
+	}
+
+/*********************************
+ Implementation of DRpmbTest class
+**********************************/
+
+DRpmbTest::DRpmbTest():
+// initialise parameters
+	iStackSemPtr(NULL),
+	iPowerSemPtr(NULL),
+	iSessionEndCallBack(DRpmbTest::StackCallBack, this)
+	{
+	}
+
+DRpmbTest::~DRpmbTest()
+	{
+	
+	iBusCallBack.Remove();
+		
+	if (iPowerSemPtr)
+		{
+		iPowerSemPtr->Close(NULL);
+		}
+	if (iStackSemPtr)
+		{
+		iStackSemPtr->Close(NULL);
+		}
+	if (iSession)
+		{
+		delete iSession;
+		}
+	}
+
+TInt DRpmbTest::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
+	{
+	TInt r = KErrNone;
+	r = Kern::SemaphoreCreate(iStackSemPtr, _L("DRpmbStackSem"), 0);
+	return r;
+	}
+
+TInt DRpmbTest::Request(TInt aFunction, TAny* /*a1*/, TAny* /*a2*/)
+	{
+	TInt r = KErrNotSupported;
+	switch (aFunction)
+		{
+		case RTestRpmb::ERunTests:
+			{
+			// respond to user side request 
+			// execute tests for RPMB kernel extension
+			// run standatd tests that use the DRpmbDevice interface
+            Kern::Printf("	");
+            Kern::Printf("%S << START DRpmbDevice TESTS >>", &KDRpmbTestBanner);
+			r = DRpmbDeviceTests();
+            if (r != KErrNone)
+                {
+                Kern::Printf("%S DPrmbDevice test FAILED", &KDRpmbTestBanner);
+                break;
+                }
+            Kern::Printf("%S >> ALL DRpmbDevice TESTS PASSED", &KDRpmbTestBanner);
+			// run tests that use the MMC stack bypassing the RPMB kernel extension
+            Kern::Printf("	");
+	        Kern::Printf("%S << START STACK TESTS >>", &KDRpmbTestBanner);
+			r = RpmbStackTests();
+			if (r != KErrNone)
+			    {
+                Kern::Printf("%S stack test FAILED", &KDRpmbTestBanner);
+                break;
+			    }
+            Kern::Printf("%S >> ALL STACK TESTS PASSED", &KDRpmbTestBanner);
+			break;
+			}
+		default:
+			break;
+		}
+	return r;
+	}
+
+
+// test RPMB using the DRpmbDevice interface
+TInt DRpmbTest::DRpmbDeviceTests()
+// open interface and make data write, ket write, counter read and data write accesses
+	{				
+	TInt size = (TInt)(2*KRpmbOneFramePacketLength);
+
+	NKern::ThreadEnterCS();
+	iRequest = (TUint8 *)Kern::Alloc(size);
+	NKern::ThreadLeaveCS();
+
+	iResponse = iRequest + KRpmbOneFramePacketLength;
+
+	TInt r = SendAccessRequestNotOpen();
+	
+	if (r==KErrNone)
+		{
+		r = OpenWithBadIndex();
+		}
+
+	if (r==KErrNone)
+		{
+		r = MultipleOpen();
+		}
+	
+	if (r==KErrNone)
+		{
+		r = iRpmb.Open(0);
+		}
+	
+	if (r!=KErrNone)
+		{
+		Kern::Printf("%S DRpmbTest::DRpmbDeviceTest DRpmbDevice open error = %d", 
+		        &KDRpmbTestBanner, r);
+		}
+	else
+		{
+		r  = SendAccessRequestBadParms();
+		}
+
+	if (r==KErrNone)
+		{
+		r = InvalidRequestId();
+		}   
+	
+	if (r==KErrNone)
+		{
+		r = IsKeyProgrammed();
+		}   
+	
+// Don't want to write key 'pre production' on real device as this will lock 
+// the system out of the RPMB partition (the key should be preprogrammed as 
+// part of the production process so that the system has access to the key - 
+// if the key has already been written it can't be written again)
+#ifdef RPMBTESTS_TRY_TO_WRITE_KEY
+	if (r==KErrNone)
+		{
+		r = WriteKey();
+		}
+#endif
+
+	if (r==KErrNone)
+		{  
+		r = ReadWriteCounter();
+		}
+
+	if (r==KErrNone)
+		{
+		r = ReadData();
+		}
+
+	iRpmb.Close();
+	
+	NKern::ThreadEnterCS();	
+
+	Kern::Free(iRequest);
+	
+	NKern::ThreadLeaveCS();
+	
+	return r;
+}
+
+TInt DRpmbTest::SendAccessRequestNotOpen()
+// test cases where DRpmbDevice::SendAccessRequest() is called 
+// 1.) before DRpmbDevice::Open() is ever called
+// 2,) after DRpmbDevice::Close() has been called but before DRpmbDevice::Open() is called
+	{	
+	Kern::Printf("%S DRpmbDevice::SendAccessRequest not open test", &KDRpmbTestBanner);     
+	// wrap up IO buffers in descriptors to pass across interface
+
+	TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+	TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+
+	// test call DRpmbDevice::SendAccessRequest before EVER calling open
+
+	TInt r = iRpmb.SendAccessRequest(request, response);
+	if (r != KErrNotReady)
+		{
+        Kern::Printf("%S SendAccessRequest not open test, before EVER opening, unexpected error = %d", 
+                &KDRpmbTestBanner, r);     
+		return KErrGeneral;
+		}
+
+	// test open and close and call again
+	r = iRpmb.Open(0);
+	if (r != KErrNone)
+		{
+        Kern::Printf("%S SendAccessRequest not open test, opening, unexpected error = %d", 
+                &KDRpmbTestBanner, r);     
+		return KErrGeneral;
+		}
+	iRpmb.Close();
+
+	r = iRpmb.SendAccessRequest(request, response);
+	if (r != KErrNotReady)
+		{
+        Kern::Printf("%S SendAccessRequest not open test, before opening AFTER closing, unexpected error = %d", 
+                &KDRpmbTestBanner, r);     
+		return KErrGeneral;
+		}
+	
+	Kern::Printf("%S DRpmbDevice::SendAccessRequest not open test PASS", &KDRpmbTestBanner);     
+	return KErrNone;
+}
+
+
+TInt DRpmbTest::OpenWithBadIndex()
+// test case where DRpmbDevice::Open() is called with a device index of more than zero
+	{
+	Kern::Printf("%S DRpmbDevice::Open bad index test", &KDRpmbTestBanner);     
+	
+	// test index > 0
+	TInt r = iRpmb.Open(1);
+	if (r != KErrGeneral)
+		{
+        Kern::Printf("%S RpmbDevice::Open bad index test, unexpected error = %d", 
+                &KDRpmbTestBanner, r);     
+		return KErrGeneral;
+		}
+	
+	Kern::Printf("%S DRpmbDevice::Open bad index test PASS", &KDRpmbTestBanner);     
+	return KErrNone;
+}
+
+
+TInt DRpmbTest::MultipleOpen()
+// test case where DRpmbDevice::Open() is called twice with the same index parameter and
+// the same instance of DRpmbDevice
+// test case where DRpmbDevice::Open() is called twice with the same index parameter and
+// a different instance of DRpmbDevice
+	{
+	Kern::Printf("%S DRpmbDevice::Open use more than once test", &KDRpmbTestBanner);     
+	
+	TInt r = iRpmb.Open(0);
+	if (r != KErrNone)
+		{
+        Kern::Printf("%S RpmbDevice::Open use more than once test first open, unexpected error = %d", 
+                &KDRpmbTestBanner, r);     
+		return KErrGeneral;
+		}
+
+	r = iRpmb.Open(0);
+	if (r != KErrNone)
+		{
+        Kern::Printf("%S RpmbDevice::Open use more than once test second open, unexpected error = %d", 
+                &KDRpmbTestBanner, r);     
+		return KErrGeneral;	
+		}
+
+	r = iRpmbSecondInstance.Open(0);
+	if (r != KErrInUse)
+		{
+        Kern::Printf("%S RpmbDevice::Open use more than once test third open, unexpected error = %d", 
+                &KDRpmbTestBanner, r);     
+		return KErrGeneral;	
+		}
+
+	iRpmb.Close();
+	iRpmbSecondInstance.Close();
+
+	Kern::Printf("%S DRpmbDevice::Open use more than once test PASS", &KDRpmbTestBanner);     
+
+	return KErrNone;
+	}
+
+
+TInt DRpmbTest::SendAccessRequestBadParms()
+// test cases where DRpmbDevice::SendAccessRequest is called with secriptor arguments with invalid lengths
+	{
+	Kern::Printf("%S DRpmbDevice::SendAccessRequest bad parms test", &KDRpmbTestBanner);     
+	
+	// test both lengths !=	KRpmbOneFramePacketLength
+	TBuf<KRpmbOneFramePacketLength-1> request;
+	TBuf<KRpmbOneFramePacketLength+1> response;
+	request.SetLength(KRpmbOneFramePacketLength-1);
+	response.SetLength(KRpmbOneFramePacketLength+1);
+
+	TInt r = iRpmb.SendAccessRequest(request, response);
+	if (r != KErrArgument)
+		{
+        Kern::Printf("%S SendAccessRequest bad parms test, both params bad, unexpected error = %d", 
+                &KDRpmbTestBanner, r);     
+		return KErrGeneral;
+		}
+
+	// test request length != KRpmbOneFramePacketLength
+	TBuf<KRpmbOneFramePacketLength+1> request1;
+	TBuf<KRpmbOneFramePacketLength> response1;
+	request1.SetLength(KRpmbOneFramePacketLength+1);
+	response1.SetLength(KRpmbOneFramePacketLength);
+
+	r = iRpmb.SendAccessRequest(request1, response1);
+	if (r != KErrArgument)
+		{
+        Kern::Printf("%S SendAccessRequest bad parms test, request param bad, unexpected error = %d", 
+                &KDRpmbTestBanner, r);     
+		return KErrGeneral;
+		}
+
+	// test response length !=KRpmbOneFramePacketLength
+	TBuf<KRpmbOneFramePacketLength> request2;
+	TBuf<KRpmbOneFramePacketLength-1> response2;
+	request2.SetLength(KRpmbOneFramePacketLength);
+	response2.SetLength(KRpmbOneFramePacketLength-1);
+
+	r = iRpmb.SendAccessRequest(request1, response1);
+	if (r != KErrArgument)
+		{
+        Kern::Printf("%S SendAccessRequest bad parms test, response param bad, unexpected error = %d", 
+                &KDRpmbTestBanner, r);     
+		return KErrGeneral;
+		}
+	
+	
+	Kern::Printf("%S DRpmbDevice::SendAccessRequest bad parms test PASS", &KDRpmbTestBanner);     
+	return KErrNone;
+}
+
+TInt DRpmbTest::InvalidRequestId()
+// send a request with an invalid request ID to the RPMB partition
+// when SendAccessRequest returns iResponse should not have reponse or result fields filled in
+	{
+    Kern::Printf("%S invalid request ID test", &KDRpmbTestBanner);     
+    
+	// set up write request packet with blank MAC
+	memset(iRequest, 0, KRpmbOneFramePacketLength);
+	* (iRequest + KRpmbRequestLsbOffset) = KRpmbRequestReadResultRegister + 1;
+   
+	// wrap up IO buffers in descriptors to pass across interface
+	TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+	TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+	TInt r = iRpmb.SendAccessRequest(request, response);
+	if (r != KErrNone)
+		{
+        Kern::Printf("%S invalid request ID test, send request error = %d", 
+                &KDRpmbTestBanner, r);     
+		return r;
+		}
+
+	// check that response or result fields have not been set in response
+	TUint resp = DecodeResponse(iResponse);
+	TUint result = DecodeResult(iResponse);
+
+	if (resp != 0x0006)
+		{
+        Kern::Printf("%S invalid request ID test, unexpected response = %d error", 
+                &KDRpmbTestBanner, resp);
+		return KErrGeneral;
+		}
+
+	if (result != 0x0000)
+		{
+		Kern::Printf("%S invalid request ID test, unexpected result = %d error", 
+                &KDRpmbTestBanner, result);
+		return KErrGeneral;
+		}
+
+	Kern::Printf("%S invalid requeset ID test PASS", &KDRpmbTestBanner);     
+	return KErrNone;
+	}
+
+
+TInt DRpmbTest::IsKeyProgrammed()
+// send a data write request to the RPMB partition
+// because the request has a blank MAC (not authenticated) 
+// the partition returns operation result authentication failure if the key is programmed
+// else the partition returns authentication key not programmed
+	{
+    Kern::Printf("%S data write test", &KDRpmbTestBanner);     
+    
+	// set up write request packet with blank MAC
+	memset(iRequest, 0, KRpmbOneFramePacketLength);
+	* (iRequest + KRpmbRequestLsbOffset) = KRpmbRequestWriteData;
+   
+	// wrap up IO buffers in descriptors to pass across interface
+	TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+	TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+	TInt r = iRpmb.SendAccessRequest(request, response);
+	if (r != KErrNone)
+		{
+        Kern::Printf("%S data write test, send request error = %d", 
+                &KDRpmbTestBanner, r);     
+		return r;
+		}
+		
+	TUint resp = DecodeResponse(iResponse);
+	TUint result = DecodeResult(iResponse);
+
+	if (resp != KRpmbResponseWriteData)
+		{
+        Kern::Printf("%S data write test, unexpected response = %d error", 
+                &KDRpmbTestBanner, resp);
+		return KErrGeneral;
+		}
+
+	if (result == KRpmbResultKeyNotProgrammed)
+		{
+		iKeySet = EFalse;
+	    Kern::Printf("%S data write test, key NOT programmed", 
+	            &KDRpmbTestBanner);     
+		}
+	else if (result == KRpmbResultAuthenticationFailure)
+		{
+		iKeySet = ETrue;
+	    Kern::Printf("%S data write test, key ALREADY programmed", 
+	            &KDRpmbTestBanner);     
+		}
+	else
+		{
+        Kern::Printf("%S data write test, unexpected result = %d error", 
+                &KDRpmbTestBanner, result);
+		return KErrGeneral;
+		}
+	Kern::Printf("%S data write test PASS", &KDRpmbTestBanner);     
+	return KErrNone;
+	}
+
+TInt DRpmbTest::WriteKey()
+	{
+    Kern::Printf("%S write key test", &KDRpmbTestBanner);     
+
+    // set up write key request
+	memset(iRequest, 0, KRpmbOneFramePacketLength);
+	* (iRequest + KRpmbRequestLsbOffset) = KRpmbRequestWriteKey;
+    // key = 0x0101010101010101010101010101010101010101010101010101010101010101
+	memset(iRequest+KRpmbKeyOffset,1, KRpmbKeyLength); 
+
+	// wrap up IO buffers in descriptors to pass across interface
+	TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+	TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+	TInt r = iRpmb.SendAccessRequest(request, response);
+	if (r != KErrNone)
+		{
+        Kern::Printf("%S write key test, send request error = %d", 
+                &KDRpmbTestBanner, r);     
+		return r;
+		}
+
+	TUint resp = DecodeResponse(iResponse);
+	TUint result = DecodeResult(iResponse);
+
+	if (resp != KRpmbResponseWriteKey)
+		{
+        Kern::Printf("%S write key test, unexpected repsponse = %d error", 
+             &KDRpmbTestBanner, resp);
+		return KErrGeneral;
+		}
+
+	if (iKeySet)
+		{
+		if (result == KRpmbResultGeneralFailure)
+			{
+            Kern::Printf("%S write key test, key ALREADY written", 
+                    &KDRpmbTestBanner);     
+            Kern::Printf("%S write key test PASS", 
+                    &KDRpmbTestBanner);     
+			return KErrNone;
+			}
+		else
+			{
+            Kern::Printf("%S write key test, unexpected result = %d error", 
+                    &KDRpmbTestBanner, result);
+			return KErrGeneral; 
+			}
+		}
+	else
+		{
+		if(result == KRpmbResultOk)
+			{
+            Kern::Printf("%S write key test, key JUST written", 
+		            &KDRpmbTestBanner);     
+            Kern::Printf("%S write key test PASS", &KDRpmbTestBanner);     
+			return KErrNone;
+			}
+		else
+			{
+	       Kern::Printf("%S write key test unexpected result = %d error", 
+	                &KDRpmbTestBanner, result);
+			return KErrGeneral;
+			}
+		}
+	}
+
+TInt DRpmbTest::ReadWriteCounter()
+	{
+    Kern::Printf("%S read write counter test", &KDRpmbTestBanner);     
+
+	// set up read write counter request packet
+	memset(iRequest, 0, KRpmbOneFramePacketLength);
+	* (iRequest + KRpmbRequestLsbOffset) = KRpmbRequestReadWriteCounter;
+   
+	// wrap up IO buffers in descriptors to pass across interface
+	TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+	TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+	TInt r = iRpmb.SendAccessRequest(request, response);
+	if (r!=KErrNone)
+		{
+        Kern::Printf("%S read write counter test, send request error = %d", 
+                &KDRpmbTestBanner, r);     
+		return r;
+		}
+
+	TUint resp = DecodeResponse(iResponse);
+	TUint result = DecodeResult(iResponse);
+	TUint32 counter = DecodeCounter(iResponse);
+
+	if (resp != KRpmbResponseReadWriteCounter)
+		{
+        Kern::Printf("%S read write counter test, unexpected repsponse = %d error", 
+                &KDRpmbTestBanner, resp);
+		return KErrGeneral;
+		}
+
+#ifdef  RPMBTESTS_TRY_TO_WRITE_KEY
+	if (result == KRpmbResultOk)
+#else
+	if (result == KRpmbResultOk || result == KRpmbResultKeyNotProgrammed)
+#endif
+		{
+		Kern::Printf("%S read write counter test write counter = %d", 
+			&KDRpmbTestBanner, counter);     
+        Kern::Printf("%S read write counter test PASS", &KDRpmbTestBanner);     
+		return KErrNone;
+		}
+	else
+		{
+        Kern::Printf("%S read write counter test, unexpected result = %d error", 
+                &KDRpmbTestBanner, result);
+		return KErrGeneral;
+		}	
+	}
+
+TInt DRpmbTest::ReadData()
+	{
+    Kern::Printf("%S read data test", &KDRpmbTestBanner);     
+    
+	// set up read request packet
+	memset(iRequest, 0, KRpmbOneFramePacketLength);
+	* (iRequest + KRpmbRequestLsbOffset) = KRpmbRequestReadData;
+   
+	// wrap up IO buffers in descriptors to pass across interface
+	TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+	TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+	TInt r=iRpmb.SendAccessRequest(request, response);
+	if (r!=KErrNone)
+		{
+        Kern::Printf("%S read data test, send request error = %d", 
+                &KDRpmbTestBanner, r);     
+		return r;
+		}
+
+	TUint resp = DecodeResponse(iResponse);
+	TUint result = DecodeResult(iResponse);
+
+	if (resp != KRpmbResponseReadData)
+		{
+        Kern::Printf("%S read data test, unexpected repsponse = %d error", 
+                &KDRpmbTestBanner, resp);
+		return KErrGeneral;
+		}
+
+#ifdef  RPMBTESTS_TRY_TO_WRITE_KEY
+	if (result == KRpmbResultOk)
+#else
+	if (result == KRpmbResultOk || result == KRpmbResultKeyNotProgrammed)
+#endif
+		{
+ 		DisplayReadData(iResponse);
+        Kern::Printf("%S read data test PASS", &KDRpmbTestBanner);     
+		return KErrNone;
+		}
+	else
+		{
+        Kern::Printf("%S read data test, unexpected result = %d error", 
+             &KDRpmbTestBanner, result);
+        return KErrGeneral;
+		}		
+	}
+
+TUint DRpmbTest::DecodeResponse(TUint8 * aResp)
+	{
+	return (* (aResp + KRpmbResponseLsbOffset) + ((* (aResp + KRpmbResponseMsbOffset)) << 8));
+	}
+
+TUint DRpmbTest::DecodeResult(TUint8 * aResp)
+	{
+	return ((* (aResp + KRpmbResultLsbOffset) + ((* (aResp + KRpmbResultMsbOffset)) << 8)) 
+	        & KRpmbResultCounterExpiredMask);
+	}
+
+TUint32 DRpmbTest::DecodeCounter(TUint8 * aResp)
+	{
+
+	return ((* (aResp + KRpmbCounterByteOneOffset)) + ((* (aResp + KRpmbCounterByteTwoOffset)) << 8)
+		+ ((* (aResp + KRpmbCounterByteThreeOffset)) << 16) + ((* (aResp + KRpmbCounterByteFourOffset)) << 24));
+	}
+
+void DRpmbTest::DisplayReadData(TUint8 * aResp)
+	{
+	TUint8 * displayPtr = aResp + KRpmbDataOffset;
+    Kern::Printf("%S data field:", &KDRpmbTestBanner);
+	for (TInt i=0; i<8; i++)
+		{
+		Kern::Printf("%x%x%x%x %x%x%x%x %x%x%x%x %x%x%x%x %x%x%x%x %x%x%x%x %x%x%x%x %x%x%x%x",
+			* displayPtr       , * (displayPtr +  1), * (displayPtr +  2), * (displayPtr +  3),
+			* (displayPtr +  4), * (displayPtr +  5), * (displayPtr +  6), * (displayPtr +  7),
+			* (displayPtr +  8), * (displayPtr +  9), * (displayPtr + 10), * (displayPtr + 11),
+			* (displayPtr + 12), * (displayPtr + 13), * (displayPtr + 14), * (displayPtr + 15),
+			* (displayPtr + 16), * (displayPtr + 17), * (displayPtr + 18), * (displayPtr + 19),
+			* (displayPtr + 20), * (displayPtr + 21), * (displayPtr + 22), * (displayPtr + 23),
+			* (displayPtr + 24), * (displayPtr + 25), * (displayPtr + 26), * (displayPtr + 27),
+			* (displayPtr + 28), * (displayPtr + 29), * (displayPtr + 30), * (displayPtr + 31));
+		displayPtr +=32;
+		}
+	}
+
+void DRpmbTest::StackCallBack(TAny * aSelf)
+// call back from MMC stack session 
+    {
+	// dereference any pointer
+	DRpmbTest& self = *static_cast<DRpmbTest*>(aSelf);
+	// signal semaphore so that calling code progresses
+	Kern::SemaphoreSignal(*(self.iStackSemPtr));
+	}
+
+TInt DRpmbTest::RpmbStackTests()
+// Test code verfies all four access types through a direct connection to the MMC protocol stack 
+	{
+	TInt r = SetupForStackTests();
+	if (r == KErrNone)
+		{
+		r = StackBadIndex();
+		}
+	if (r == KErrNone)
+		{
+		r = StackIsKeyProgrammed();
+		}
+// Don't want to write key 'pre production' on a real device as this will lock 
+// the system out of the RPMB partition (the key should be preprogrammed as 
+// part of the production process so that the system has access to the key - 
+// if the key has already been written it can't be written again)
+#ifdef RPMBTESTS_TRY_TO_WRITE_KEY
+	if (r == KErrNone)
+		{
+		r = StackWriteKey();
+		}
+#endif
+	if (r == KErrNone)
+		{
+		r = StackReadWriteCounter();
+		}
+	if (r == KErrNone)
+		{
+		r = StackReadData();
+		}
+	return r;
+	}
+
+
+TInt DRpmbTest::StackBadIndex()
+// Call MMCGetExtInterface with invalid device id
+//   - don't expect params to be returned
+//   - expect KErrGeneral return code
+	{
+	Kern::Printf("%S stack device index test", &KDRpmbTestBanner);     
+
+	MRpmbInfo* rpmbInterface = NULL;
+	TRpmbDeviceParms parms;
+
+	TInt r = MMCGetExtInterface(KInterfaceRpmb, (MMCMExtInterface*&) rpmbInterface, this); //this pointer not used in the case of Rpmb
+    if (r!=KErrNone)
+        {
+        Kern::Printf("%S stack device index, MMCGetInterface returned error = %d",
+             &KDRpmbTestBanner, r);
+        return KErrGeneral;
+        }
+	if (rpmbInterface == NULL)
+		{
+		// unexpected error since MMCGetExtInterface didn't return an error
+        Kern::Printf("%S stack device index, MMCGetInterface returned NULL interface pointer",
+             &KDRpmbTestBanner, r);
+		return KErrGeneral;
+		}
+
+    else
+        {
+		r = rpmbInterface->RpmbInfo(1, parms);
+		if (r == KErrNone)
+			{
+			Kern::Printf("%S stack device index test, parmas returned for index 1 error",
+				&KDRpmbTestBanner, r);
+			return KErrGeneral;
+			}
+		else if (r != KErrGeneral)
+			{
+			Kern::Printf("%S stack device index test, unexpected rc for index 1 error",
+				&KDRpmbTestBanner, r);
+			return KErrGeneral;
+			}
+		}
+    Kern::Printf("%S stack device index test PASS", &KDRpmbTestBanner);     
+	return KErrNone;
+}
+
+
+void DRpmbTest::BusCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2)
+{
+    DRpmbTest* lddPtr = (DRpmbTest*)aPtr;
+    TPBusState busState = (TPBusState) (TInt) a1;
+	TInt busError = (TInt) a2;
+
+    if(aReason == TPBusCallBack::EPBusStateChange 
+		&& busState == EPBusOn && busError == KErrNone)
+		{
+		Kern::SemaphoreSignal(*(lddPtr->iPowerSemPtr));
+        }
+}
+
+TInt DRpmbTest::SetupForStackTests()
+	{
+	Kern::Printf("%S setup for stack tests", &KDRpmbTestBanner);     
+
+	TRpmbDeviceParms parms;
+	
+	parms.iCardNumber = 0;
+	parms.iSocketPtr = NULL;
+	
+	DMMCStack* stack = NULL;
+	TUint cardNumber = 0;
+	MRpmbInfo* rpmbInterface = NULL;
+
+    TInt r = MMCGetExtInterface(KInterfaceRpmb, (MMCMExtInterface*&) rpmbInterface, this); //this pointer not used in the case of Rpmb
+    if (r!=KErrNone)
+        {
+        Kern::Printf("%S setup for stack tests, MMCGetInterface returned error = %d",
+             &KDRpmbTestBanner, r);
+        return KErrGeneral;
+        }
+	if (rpmbInterface == NULL)
+		{
+		// unexpected error since MMCGetExtInterface didn't return an error
+		return KErrGeneral;
+		}
+
+    else
+        {
+		r = rpmbInterface->RpmbInfo(0, parms);
+		if (r != KErrNone)
+			{
+			// requested index non zero or bseport not configured with RPMB capable MMC device
+			return r;
+			}
+        
+        cardNumber = parms.iCardNumber;        
+        iSocket = parms.iSocketPtr;
+        if(iSocket == NULL)
+            {
+            Kern::Printf("%S setup for stack tests, socket pointer is NULL",
+                 &KDRpmbTestBanner);
+              return KErrNoMemory;
+            }
+        
+		// set up to be informed of changes on bus
+		iBusCallBack.iFunction = BusCallBack;
+		iBusCallBack.iPtr=this;
+		iBusCallBack.SetSocket(iSocket->iSocketNumber);
+		iBusCallBack.Add();
+
+        // power up the stack
+        // media drivers don't have to do this at this stage because already done
+ 		NKern::ThreadEnterCS();	
+
+		r = Kern::SemaphoreCreate(iPowerSemPtr,_L("DpmbPowerSem"), 0);
+
+		if (r!=KErrNone)
+			{		
+			NKern::ThreadLeaveCS();
+            Kern::Printf("%S sese you below thentup for stack tests, SemaphoreCreate returned %d",
+                    &KDRpmbTestBanner, r);
+            return KErrGeneral;
+			}
+		
+		r = iSocket->PowerUp();
+				
+        if (r!=KErrNone && r!= KErrCompletion)
+            {
+			NKern::ThreadLeaveCS();
+            Kern::Printf("%S setup for stack tests, PowerUp returned %d",
+                    &KDRpmbTestBanner, r);
+            return KErrGeneral;
+            }
+		
+        if (r == KErrNone)
+			{
+            // wait for socket to power up
+			Kern::SemaphoreWait(*iPowerSemPtr);
+			}
+
+		NKern::ThreadLeaveCS();
+  
+        stack = iSocket->Stack(0);
+        if (stack == NULL)
+            {
+            // baseport poorly configured
+            Kern::Printf("%S setup for stack tests, stack pointer is NULL",
+                &KDRpmbTestBanner);
+            return KErrGeneral;
+            }
+        }
+
+    TMMCard* card = stack->CardP(cardNumber);
+
+	if (card == NULL)
+		{
+		// baseport poorly configured
+        Kern::Printf("%S setup for stack tests, card pointer is NULL",
+            &KDRpmbTestBanner);
+		return KErrGeneral;
+		}
+
+	NKern::ThreadEnterCS();	
+
+ 	iSession = stack->AllocSession(iSessionEndCallBack);
+	
+	NKern::ThreadLeaveCS();
+	
+	if (iSession == NULL)
+		{
+		Kern::Printf("%S setup for stack tests, session pointer is NULL",
+		        &KDRpmbTestBanner);
+		return(KErrNoMemory);
+		}
+ 
+	iSession->SetStack(stack);
+
+	iSession->SetCard(card);
+		
+	TUint32 revision = 0;
+
+	// loop until extended csd becomes available in case earlier pause wasn't long enough
+	// this shouldn't need to be done
+	// a reliable method not depending on delays and or polling is required
+	do {
+		stack = iSocket->Stack(0);
+		if (stack)
+		{
+			card = stack->CardP(cardNumber);	
+			if (card)
+			{
+				revision = card->ExtendedCSD().ExtendedCSDRev();
+			}
+		}
+	} while (revision==0);
+		
+	TUint size = card->ExtendedCSD().RpmbSize();
+		
+	if(revision < 5 || size == 0)
+		{
+		Kern::Printf("%S setup for stack test, rpmb partition NOT detected", &KDRpmbTestBanner); 
+		return KErrNotSupported;
+		}
+	
+	// use memory from stack
+    TInt bufLen, minorBufLen;
+    stack->BufferInfo(iBufPtr, bufLen, minorBufLen);
+	// mmc media driver reserved the first KRpmbOneFramePacketLength bytes of the 
+	// PSL buffer to be used for RPMB requests / responses
+	iBufPtr += minorBufLen;
+
+	return KErrNone;
+	}
+
+
+TInt DRpmbTest::StackIsKeyProgrammed()
+// Write Data to block 0 without MACing 
+//   - expect not MACed error if key set 
+//   - expect key not prgrammed error if key not programmed
+    {    
+
+	Kern::Printf("%S write data stack test", &KDRpmbTestBanner);     
+        
+    // set up write request packet in stack memory
+    memset(iBufPtr,0,KRpmbOneFramePacketLength);
+    * (iBufPtr + KRpmbRequestLsbOffset) = KRpmbRequestWriteData;
+        
+    TInt r = SendToStackAndWait();
+	if (r != KErrNone)
+		{
+		return r;
+		}
+
+	TUint response = DecodeResponse(iBufPtr); 
+	TUint result = DecodeResult(iBufPtr);
+
+	if (response == KRpmbResponseWriteData)
+		{
+		if (result == KRpmbResultAuthenticationFailure)
+			{
+            Kern::Printf("%S write data stack test, key IS written", 
+                    &KDRpmbTestBanner);     
+            Kern::Printf("%S write data stack test PASS", &KDRpmbTestBanner);     
+			iKeySet = ETrue;
+			return KErrNone;
+			}
+		else if (result == KRpmbResultKeyNotProgrammed)
+			{
+            Kern::Printf("%S write data stack test, key NOT written", 
+                    &KDRpmbTestBanner);     
+            Kern::Printf("%S write data stack test PASS",&KDRpmbTestBanner);
+            iKeySet = EFalse;
+            return KErrNone;
+			}
+		}
+    Kern::Printf("%S write data stack test FAILED, response = %d, result = %d", 
+            &KDRpmbTestBanner, response, result);     
+    return KErrGeneral;
+	}
+
+TInt DRpmbTest::StackWriteKey()
+// Write key
+//   - expect no error if key not programmed
+//   - expect general error if key already programmed
+    {    
+    Kern::Printf("%S write key stack test", &KDRpmbTestBanner);     
+
+    // set up write key request packet in stack memory
+    memset(iBufPtr,0,KRpmbOneFramePacketLength);
+    * (iBufPtr + KRpmbRequestLsbOffset) = KRpmbRequestWriteKey;
+        
+    TInt r = SendToStackAndWait();
+	if (r != KErrNone)
+		{
+		return r;
+		}
+
+	TUint response = DecodeResponse(iBufPtr); 
+	TUint result = DecodeResult(iBufPtr);
+
+	if (response == KRpmbResponseWriteKey)
+		{
+		if (iKeySet && result == KRpmbResultGeneralFailure)
+			{
+            Kern::Printf("%S write key stack test, key ALREADY written", 
+                    &KDRpmbTestBanner);     
+            Kern::Printf("%S write key stack test PASS", &KDRpmbTestBanner);     
+			return KErrNone;
+			}
+		else if (!iKeySet && result == KRpmbResultOk)
+			{
+            Kern::Printf("%S write key stack test, key JUST written", 
+                    &KDRpmbTestBanner);     
+            Kern::Printf("%S write key stack test PASS", &KDRpmbTestBanner);     
+			return KErrNone;
+			}
+		}
+    Kern::Printf("%S write key stack test FAILED, response = %d, result = %d", 
+            &KDRpmbTestBanner, response, result);     
+    return KErrGeneral;	
+	}
+
+TInt DRpmbTest::StackReadWriteCounter()
+// Read Data Counter
+// - expect no error
+    {    
+    Kern::Printf("%S read write counter stack test", &KDRpmbTestBanner);     
+
+    // set up write key request packet in stack memory
+    memset(iBufPtr,0,KRpmbOneFramePacketLength);
+    * (iBufPtr + KRpmbRequestLsbOffset) = KRpmbRequestReadWriteCounter;
+        
+    TInt r = SendToStackAndWait();
+	if (r != KErrNone)
+		{
+		return r;
+		}
+	
+	TUint response = DecodeResponse(iBufPtr); 
+	TUint result = DecodeResult(iBufPtr);
+	TUint32 counter = DecodeCounter(iBufPtr);
+
+#ifdef  RPMBTESTS_TRY_TO_WRITE_KEY
+	if ((response == KRpmbResponseReadWriteCounter) && (result == KRpmbResultOk))
+#else
+	if ((response == KRpmbResponseReadWriteCounter) 
+		&& (result == KRpmbResultOk || result == KRpmbResultKeyNotProgrammed))
+#endif
+		{
+        Kern::Printf("%S read write counter stack test, counter = %d", 
+			&KDRpmbTestBanner, counter);     
+        Kern::Printf("%S read write counter stack test PASS", 
+                &KDRpmbTestBanner);     
+		return KErrNone;
+		}
+    Kern::Printf("%S read write counrter stack test FAILED, response = %d, result = %d", 
+            &KDRpmbTestBanner, response, result);     
+    return KErrGeneral;	
+	}
+
+
+TInt DRpmbTest::StackReadData()
+// Read Data from block 0
+// - expect no error
+    {    
+    Kern::Printf("%S read data stack test", &KDRpmbTestBanner);     
+
+    // set up write key request packet in stack memory
+    memset(iBufPtr,0,KRpmbOneFramePacketLength);
+    * (iBufPtr + KRpmbRequestLsbOffset) = KRpmbRequestReadData;
+        
+    TInt r = SendToStackAndWait();
+	if (r != KErrNone)
+		{
+		return r;
+		}
+
+	TUint response = DecodeResponse(iBufPtr); 
+	TUint result = DecodeResult(iBufPtr);
+
+#ifdef  RPMBTESTS_TRY_TO_WRITE_KEY
+	if ((response == KRpmbResponseReadData) && (result == KRpmbResultOk))
+#else
+	if ((response == KRpmbResponseReadData) 
+		&& (result == KRpmbResultOk || result == KRpmbResultKeyNotProgrammed))
+#endif
+		{
+		DisplayReadData(iBufPtr);
+        Kern::Printf("%S read data stack test PASS", &KDRpmbTestBanner);     
+		return KErrNone;
+		}
+	Kern::Printf("%S read data stack test FAILED, response = %d, result = %d", 
+            &KDRpmbTestBanner, response, result);     
+    return KErrGeneral;
+	}
+
+TInt DRpmbTest::SendToStackAndWait()
+	{
+// comment out to get timings with RPMB -> RPMB switches in place of User 
+// Area -> RPMB switces
+#define RPMBSTACKTEST_FIRST_SWITCH_TO_USER_AREA
+#ifdef RPMBSTACKTEST_FIRST_SWITCH_TO_USER_AREA	
+	// in normal operation it may be necessary to switch to RPMB partition
+	// prior to access
+	// so force the switch to occur by pre switching to the user area
+    iSession->SetPartition(TExtendedCSD::ESelectUserArea);
+#endif
+
+	TInt start, postswitch, end;
+
+	start = NKern::TickCount();
+
+	// lock stack
+	TInt r = iSocket->InCritical();
+	if (r != KErrNone)
+		{
+		Kern::Printf("%S DRpmbTest::SendToStackAndWait, error=%d",
+		        &KDRpmbTestBanner, r);
+		iSocket->EndInCritical();
+		return KErrGeneral;
+		}
+
+	 // switch to RPMB partition
+    iSession->SetPartition(TExtendedCSD::ESelectRPMB);
+
+	postswitch = NKern::TickCount();
+	
+    // set up for write exchange 
+    iSession->ResetCommandStack();
+    iSession->FillCommandArgs(0, KRpmbOneFramePacketLength, iBufPtr, KRpmbOneFramePacketLength);
+    iSession->iSessionID = ECIMRpmbAccess;
+    iSession->Engage();
+    
+    // wait for stack call to complete
+	r = Kern::SemaphoreWait(*iStackSemPtr);
+
+	end = NKern::TickCount();
+
+	Kern::Printf("%S switch to RPMB took %d %d uS timer ticks",
+		&KDRpmbTestBanner, start - postswitch, NKern::TickPeriod());
+	Kern::Printf("%S RPMB ECIMRpmbAccess took %d %d uS timer ticks",
+		&KDRpmbTestBanner, end - postswitch, NKern::TickPeriod());
+
+	if (r != KErrNone)
+		{
+		Kern::Printf("%S DRpmbTest::SendToStackAndWait, SemaphoreWait return code = %d",
+		        &KDRpmbTestBanner, r);
+		iSocket->EndInCritical();
+		return KErrGeneral;
+		}
+
+	// check stack epoc return code
+	r = iSession->EpocErrorCode();
+	if (r != KErrNone)
+		{		
+		Kern::Printf("%S DRpmbTest::stack epoc return code = %d",
+		        &KDRpmbTestBanner, r);
+		iSocket->EndInCritical();
+		return KErrGeneral;
+		}
+		
+	// unlock stack
+	iSocket->EndInCritical();
+
+	return KErrNone;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/driver/d_rpmb.h	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,89 @@
+// Copyright (c) 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:
+// e32test/rpmb/rpmb.h
+// 
+//
+
+/**
+ @file
+ @internalComponent
+ @prototype
+*/
+
+#include <kernel/kern_priv.h>
+#include <drivers/rpmbdevice.h>
+#include <drivers/mmc.h>
+
+// banner for reporting progress of these tests 
+_LIT(KDRpmbTestBanner,"RPMB TEST DRIVER: ");
+
+// RPMB test driver factory class
+class DRpmbTestFactory : public DLogicalDevice
+	{
+public:
+	DRpmbTestFactory();
+	~DRpmbTestFactory();
+	virtual TInt Install();
+	virtual void GetCaps(TDes8& aDes) const;
+	virtual TInt Create(DLogicalChannelBase*& aChannel);
+	};
+
+// RPMB test driver request handling class
+class DRpmbTest : public DLogicalChannelBase
+	{
+public:
+	DRpmbTest();
+	virtual ~DRpmbTest();
+	TInt DRpmbDeviceTests();
+	TInt RpmbStackTests();
+protected:
+	TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
+	TInt Request(TInt aFunction, TAny* a1, TAny* a2);
+private:
+	TInt SendAccessRequestNotOpen();
+	TInt OpenWithBadIndex();
+	TInt MultipleOpen();
+	TInt SendAccessRequestBadParms();
+	TInt InvalidRequestId();
+	TInt IsKeyProgrammed();
+	TInt WriteKey();
+	TInt ReadWriteCounter();
+	TInt ReadData();
+	TUint DecodeResponse(TUint8 * aResp);
+	TUint DecodeResult(TUint8 * aResp);
+	TUint32 DecodeCounter(TUint8 * aResp);
+	void DisplayReadData(TUint8 * aResp);
+	static void BusCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2);
+	static void StackCallBack(TAny * aSelf);
+	TInt StackBadIndex();
+	TInt SetupForStackTests();
+	TInt StackIsKeyProgrammed();
+	TInt StackWriteKey();
+	TInt StackReadWriteCounter();
+	TInt StackReadData();
+	TInt SendToStackAndWait();	
+private:
+	DRpmbDevice iRpmb;
+	DRpmbDevice iRpmbSecondInstance;
+	TUint8 * iRequest;
+	TUint8 * iResponse;
+	TBool iKeySet;
+	TUint8* iBufPtr;
+	DSemaphore * iStackSemPtr;
+	DSemaphore * iPowerSemPtr;
+	TPBusCallBack iBusCallBack;
+	TMMCCallBack iSessionEndCallBack;
+	DMMCSocket* iSocket;
+	DMMCSession* iSession;
+	};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/driver/d_rpmb.mmp	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,43 @@
+/// Copyright (c) 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:
+// e32test/group/d_rpmb.mmp
+// 
+//
+
+/**
+ @file
+*/
+
+#include "kernel/kern_ext.mmh"
+
+target 		d_rpmb.ldd
+targettype	ldd
+sourcepath	./
+source		d_rpmb.cpp
+
+library		rpmbext.lib
+
+library 	epbusmmc.lib
+
+epocallowdlldata
+
+vendorid	0x70000001
+
+start wins
+win32_headers
+end
+
+capability	all
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/rpmbtestautoexec.bat	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,17 @@
+rem
+rem Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+rem All rights reserved.
+rem This component and the accompanying materials are made available
+rem under the terms of the License "Eclipse Public License v1.0"
+rem which accompanies this distribution, and is available
+rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+rem
+rem Initial Contributors:
+rem Nokia Corporation - initial contribution.
+rem
+rem Contributors:
+rem
+rem Description:
+rem
+
+t_rpmb
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/t_rpmb.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,58 @@
+
+// Copyright (c) 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:
+// e32test/rpmb/t_rpmb.cpp
+// LDD for testing RPMB kernel extension
+// 
+//
+
+/**
+ @file
+ @internalComponent
+ @prototype
+*/
+
+#define	__E32TEST_EXTENSION__
+#include <e32test.h>
+#include "t_rpmb.h"
+
+RTest test(_L("t_rpmb"));
+RTestRpmb	RpmbTestDeviceDriver;
+
+/******************************************************************************
+ * Main
+ ******************************************************************************/
+TInt E32Main()
+	{
+#if !defined(__WINS__)
+	test.Title();
+	test.Start(_L("Opening device driver"));
+	TInt r;
+	r = User::LoadLogicalDevice(KRpmbTestLddName);
+	test_Value(r,r==KErrNone||r==KErrAlreadyExists);
+	r = RpmbTestDeviceDriver.Open();
+	test_KErrNone(r);
+	test.Next(_L("Execute RPMB tests"));	
+	r = RpmbTestDeviceDriver.RunTests();
+	test_KErrNone(r);
+	RpmbTestDeviceDriver.Close();
+	r = User::FreeLogicalDevice(KRpmbTestLddName);
+	test_KErrNone(r);
+	test.End();
+#else
+test.Printf(_L("This test does not run on emulator. \n"));
+#endif
+	return 0;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/t_rpmb.h	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,43 @@
+// Copyright (c) 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:
+// e32test/rpmb/t_rpmb.h
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @prototype
+*/
+
+// name of kernel side RPMB test driver
+_LIT(KRpmbTestLddName,"d_rpmb");
+
+// user side client object for accessing kernel side RPMB test driver
+class RTestRpmb : public RBusLogicalChannel
+	{
+public:
+	enum TControl
+		{
+		ERunTests=0,
+		};
+#ifndef __KERNEL_MODE__
+// these public methods are only accessed from the user side	
+public:
+	inline TInt Open()
+		{ return DoCreate(KRpmbTestLddName,TVersion(),KNullUnit,NULL,NULL); }
+	inline TInt RunTests()
+		{ return DoControl(ERunTests); }
+#endif // __KERNEL_MODE__
+	};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/t_rpmb.mmp	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,35 @@
+/// Copyright (c) 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:
+// e32test/group/t_rpmb.mmp
+// 
+//
+
+/**
+ @file
+*/
+
+target			t_rpmb.exe
+targettype		exe
+sourcepath		../rpmb
+source			t_rpmb.cpp
+
+library			euser.lib
+userinclude		../rpmb
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+vendorid	0x70000001
+
+capability		none
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/bench/t_trimbm.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,875 @@
+// Copyright (c) 1996-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:
+// f32test/bench/t_fsysbm.cpp
+//
+//
+
+#define __E32TEST_EXTENSION__
+
+#include <f32file.h>
+#include <e32test.h>
+#include <e32hal.h>
+#include <hal.h>
+#include <e32math.h>
+#include <e32ldr.h>
+#include <e32ldr_private.h>
+#include "t_server.h"
+#include "../../e32test/mmu/d_sharedchunk.h"
+#include "../../e32utils/pccd/d_mmcif.h"
+
+#define SYMBIAN_TEST_EXTENDED_BUFFER_SIZES	// test using a greater number of buffer sizes
+
+RTest test(_L("eMMC 4.4 TRIM Benchmark"));
+
+static const TUint K1K = 1024;								// 1K
+static const TUint K1M = K1K * K1K  ;						// 1M
+static const TUint K2M = 2 * K1M;						    // 2M
+
+
+#if defined(__WINS__)
+static TInt KMaxFileSize = 256 * K1K;					// 256K
+#else
+static TInt KMaxFileSize = K2M;							// 2M
+#endif
+
+const TTimeIntervalMicroSeconds32 KFloatingPointTestTime = 10000000;	// 10 seconds
+
+static TPtr8 DataBuf(NULL, KMaxFileSize,KMaxFileSize);
+
+static RSharedChunkLdd Ldd;
+static RChunk TheChunk;
+
+GLDEF_D	RFs TheFs;
+GLDEF_D TFileName gSessionPath;
+GLDEF_D TChar gDriveToTest;
+
+static RMmcCntrlIf iDriver;
+static TInt iStack = 0;
+static TInt iCard = 0;
+static TBool iDriverOpen = EFalse;
+
+enum TPanic {ECreatingConsole,ELoaderCheck,ELoadingMmcDriver,EStartingMmcDriver};
+
+LOCAL_C void Panic(TPanic aPanic)
+//
+// Panic
+//
+	{
+	User::Panic(_L("MMCTEST"),aPanic);
+	}
+	
+
+static RFile File;
+
+static TInt gFastCounterFreq;
+
+const TUint KMMCExtendedCSDLength=512;
+class TExtendedCSD
+	{
+public:
+	enum TExtCSDAccessBits {ECmdSet, ESetBits, EClearBits, EWriteByte};
+	enum TExtCSDModesFieldIndex 
+		{
+		ECmdSetIndex = 191, 
+		ECmdSetRevIndex = 189, 
+		EPowerClassIndex = 187,
+		EHighSpeedInterfaceTimingIndex = 185,
+		EBusWidthModeIndex = 183
+		};
+	enum TExtCSDBusWidths
+		{
+		EExtCsdBusWidth1 = 0x00,
+		EExtCsdBusWidth4 = 0x01,
+		EExtCsdBusWidth8 = 0x02
+		};
+	enum TCardTypes
+		{
+		EHighSpeedCard26Mhz = 0x01,
+		EHighSpeedCard52Mhz = 0x02
+		};
+public:
+	inline TExtendedCSD();				// Default constructor
+	inline TExtendedCSD(const TUint8*);
+	inline TExtendedCSD& operator=(const TExtendedCSD&);
+	inline TExtendedCSD& operator=(const TUint8*);
+	inline TUint8 At(TUint anIndex) const;	// Byte from CSD at anIndex
+public:
+	inline TUint SupportedCmdSet() const;
+	inline TUint MinPerfWrite8Bit52Mhz() const;
+	inline TUint MinPerfRead8Bit52Mhz() const;
+	inline TUint MinPerfWrite8Bit26Mhz_4Bit52Mhz() const;
+	inline TUint MinPerfRead8Bit26Mhz_4Bit52Mhz() const;
+	inline TUint MinPerfWrite4Bit26Mhz() const;
+	inline TUint MinPerfRead4Bit26Mhz() const;
+	inline TUint PowerClass26Mhz360V() const;
+	inline TUint PowerClass52Mhz360V() const;
+	inline TUint PowerClass26Mhz195V() const;
+	inline TUint PowerClass52Mhz195V() const;
+	inline TUint CardType() const;
+	inline TUint CSDStructureVer() const;
+	inline TUint ExtendedCSDRev() const;
+	inline TUint CmdSet() const;
+	inline TUint CmdSetRev() const;
+	inline TUint PowerClass() const;
+	inline TUint HighSpeedTiming() const;
+	inline TUint BusWidth() const;
+	
+	inline TUint TrimMultiplier() const;
+	inline TUint SecureFeatureSupport() const;
+	inline TUint SecureEraseMultiplier() const;
+	inline TUint SecureTrimMultiplier() const;
+
+private:
+	/**< @internalComponent little endian 512 byte field representing extended CSD	*/
+	TUint8 iData[KMMCExtendedCSDLength];
+	};
+
+inline TExtendedCSD::TExtendedCSD()	// Default constructor
+	{}				
+inline TExtendedCSD::TExtendedCSD(const TUint8* aPtr)
+	{memcpy(&iData[0], aPtr, KMMCExtendedCSDLength);}
+inline TExtendedCSD& TExtendedCSD::operator=(const TExtendedCSD& aCSD)
+	{memcpy(&iData[0], &aCSD.iData[0], KMMCExtendedCSDLength); return(*this);}
+inline TExtendedCSD& TExtendedCSD::operator=(const TUint8* aPtr)
+	{memcpy(&iData[0], aPtr, KMMCExtendedCSDLength); return(*this);}
+// field accessors.  
+// "Properties Segment" of Extended CSD - i.e. read-only fields
+inline TUint TExtendedCSD::SupportedCmdSet() const {return iData[504];}
+inline TUint TExtendedCSD::MinPerfWrite8Bit52Mhz() const {return iData[210];}
+inline TUint TExtendedCSD::MinPerfRead8Bit52Mhz() const {return iData[209];}
+inline TUint TExtendedCSD::MinPerfWrite8Bit26Mhz_4Bit52Mhz() const {return iData[208];}
+inline TUint TExtendedCSD::MinPerfRead8Bit26Mhz_4Bit52Mhz() const {return iData[207];}
+inline TUint TExtendedCSD::MinPerfWrite4Bit26Mhz() const {return iData[206];}
+inline TUint TExtendedCSD::MinPerfRead4Bit26Mhz() const {return iData[205];}
+inline TUint TExtendedCSD::PowerClass26Mhz360V() const {return iData[203];}
+inline TUint TExtendedCSD::PowerClass52Mhz360V() const {return iData[202];}
+inline TUint TExtendedCSD::PowerClass26Mhz195V() const {return iData[201];}
+inline TUint TExtendedCSD::PowerClass52Mhz195V() const {return iData[200];}
+inline TUint TExtendedCSD::CardType() const {return iData[196];}
+inline TUint TExtendedCSD::CSDStructureVer() const {return iData[194];}
+inline TUint TExtendedCSD::ExtendedCSDRev() const {return iData[192];}
+
+inline TUint TExtendedCSD::TrimMultiplier() const {return iData[232]; }
+inline TUint TExtendedCSD::SecureFeatureSupport() const {return iData[231]; }
+inline TUint TExtendedCSD::SecureEraseMultiplier() const {return iData[230]; }
+inline TUint TExtendedCSD::SecureTrimMultiplier() const {return iData[229]; }
+    
+    
+// "Modes Segment" of Extended CSD - i.e. modifiable fields
+inline TUint TExtendedCSD::CmdSet() const {return iData[191];}
+inline TUint TExtendedCSD::CmdSetRev() const {return iData[189];}
+inline TUint TExtendedCSD::PowerClass() const {return iData[187];}
+inline TUint TExtendedCSD::HighSpeedTiming() const {return iData[185];}
+typedef TPckg<TExtendedCSD> TExtendedCSDPckg;
+
+static TExtendedCSD extCSD;
+
+GLDEF_C TInt CurrentDrive()
+//
+// Return the current drive number
+//
+	{
+
+	TInt driveNum;
+	TInt r=TheFs.CharToDrive(gSessionPath[0],driveNum);
+	test_KErrNone(r);
+	return(driveNum);
+	}
+
+GLDEF_C void Format(TInt aDrive)
+//
+// Format current drive
+//
+	{
+
+	TUint initTicks = User::FastCounter();
+    TUint finalTicks = 0;
+    
+	TBuf<4> driveBuf=_L("?:\\");
+	driveBuf[0]=(TText)(aDrive+'A');
+	RFormat format;
+	TInt count;
+	    
+	TInt r=format.Open(TheFs,driveBuf, EFullFormat,count);  // EQuickFormat
+	test_KErrNone(r);
+	while(count)
+		{
+		TInt r=format.Next(count);
+		test_KErrNone(r);
+		}
+	format.Close();
+	
+	finalTicks = User::FastCounter();
+	TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;   
+	
+	TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+	test.Printf(_L("Time taken to format %d ms)\n"), timeTakenInMs); 
+	}
+
+
+
+static TInt getExtendedCSD()
+	{
+
+	if (!iDriverOpen)
+		return(KErrNotSupported);
+
+
+	// Power the stack down & up to make sure the CardInfo is up to date
+	iDriver.Reset();
+	User::After(1000); 
+	iDriver.PwrDownStack();
+	User::After(1000); 
+	TRequestStatus status;
+	iDriver.PwrUpAndInitStack(status);
+	User::WaitForRequest(status);
+    TInt err;
+	if ((err=status.Int())!=KErrNone)
+		{
+		test.Printf(_L("Error Powering Stack"),err);
+		return(err);
+		}
+	iDriver.SelectCard(iCard);
+
+	// Get the CSD first to check whether the ExtCSD is supported
+	TMmcCardInfo ci;
+	if ((err = iDriver.CardInfo(ci))!=KErrNone)
+        {
+		test.Printf(_L("Error getting card info"),err);
+        return(err);
+        }
+	//test.Printf(_L("CSD Spec version: %u\n"), ci.iSpecVers);
+
+	if (ci.iSpecVers < 4) 
+		{
+		test.Printf(_L("Error: Extended CSD not supported\n"));
+		return KErrNotSupported;
+		}
+
+	TExtendedCSDPckg extCSDPckg(extCSD);
+
+	iDriver.ReadExtCSD(status, extCSDPckg);
+
+	User::WaitForRequest(status);
+
+	if (status.Int() != KErrNone)
+        {
+		test.Printf(_L("Error getting Extended CSD\n"));
+        return(KErrGeneral);
+        }
+    return err;
+    }
+
+
+static TUint GetSecEraseMultValue(void)
+    {
+        TUint retVal = 0;
+        
+        getExtendedCSD();
+        retVal = extCSD.SecureEraseMultiplier();
+        
+        return retVal;
+    }
+
+static TUint GetSecTrimMultValue(void)
+    {
+        TUint retVal = 0;
+        
+        getExtendedCSD();
+        retVal = extCSD.SecureTrimMultiplier();
+        
+        return retVal;
+    }
+
+static TUint GetTrimMultValue(void)
+    {
+        TUint retVal = 0;
+        
+        getExtendedCSD();
+        retVal = extCSD.TrimMultiplier();
+        
+        return retVal;
+    }
+
+static TInt64 DiskSize(TInt aDrive)
+//
+//
+//
+	{
+	TVolumeInfo v;
+	TInt r=TheFs.Volume(v,aDrive);
+	test_KErrNone(r);
+	return(v.iSize);
+	}
+
+static TInt CalcEntries(TInt64 aDiskSize, TUint& aEntrySize)
+    {
+
+    aEntrySize = KMaxFileSize;    
+    TInt numFiles = (TInt)(aDiskSize / aEntrySize);
+    
+    while ( numFiles > 1000 )
+        {
+          aEntrySize = aEntrySize << 2 ;
+          numFiles = (TUint)(aDiskSize / aEntrySize);
+        }    
+    return numFiles;
+        
+    }
+
+static void WriteFull(TInt aDrive)
+    {
+    TInt64 diskSize = DiskSize(aDrive);
+    
+	RFile f;
+    TUint initTicks = 0;
+    TUint finalTicks = 0;
+
+	TFileName sessionPath;
+	TInt r=TheFs.SessionPath(sessionPath);
+	test_KErrNone(r);
+	TBuf8<8> WriteData =_L8("Wibbleuy");
+	
+	r=TheFs.MkDirAll(gSessionPath);
+	
+	
+    TUint entrySize = KMaxFileSize;
+    TInt numFiles = CalcEntries(diskSize, entrySize);
+    test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ; 
+    test.Printf(_L("Create %d entries\n"),numFiles);
+    
+    test.Printf(_L("TRIM_MULT     :%d\n"), GetTrimMultValue());
+    test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+    test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+    initTicks = User::FastCounter();
+    
+    for( TInt i = 0; i < numFiles; ++i)
+        {
+
+		test.Printf(_L("Create FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+		TFileName baseName= gSessionPath;
+		baseName.Append(_L("FILE"));
+		baseName.AppendNum(i);
+		r=f.Replace(TheFs,baseName,EFileWrite);
+		test_KErrNone(r);
+		r = f.SetSize(entrySize);
+		if( r == KErrDiskFull)
+		    {
+		        numFiles = i;
+		        break;
+		    }
+		test_Value(r, r == KErrNone || r==KErrDiskFull);
+		r=f.Write((entrySize-30),WriteData);
+		test_KErrNone(r);
+		f.Flush();
+		f.Close();
+		}
+
+    test.Printf(_L("\nTRIM_MULT     :%d\n"), GetTrimMultValue());
+    test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+    test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+    
+	test.Printf(_L("Test all entries have been created successfully\n"));
+	TBuf8<8> ReadData;
+	TInt Size=0;
+	for (TInt j=0; j < numFiles; j++)
+		{
+		
+        test.Printf(_L("Check FILE%d\t(%3d%%)\r"), j, (100*j/numFiles) );
+		TFileName baseName = gSessionPath;
+		baseName.Append(_L("FILE"));
+		baseName.AppendNum(j);
+
+		TInt r=f.Open(TheFs,baseName,EFileRead);
+		if (r!=KErrNone)
+			{
+			test_Value(r, r == KErrNotFound && j==numFiles);
+			return;
+			}
+		ReadData.FillZ();
+		r=f.Read((entrySize-30),ReadData);
+		test_KErrNone(r);
+		test(f.Size(Size)==KErrNone);
+		test(entrySize == (TUint)Size);
+		test(ReadData==WriteData);
+		f.Close();
+		}
+		
+	finalTicks = User::FastCounter();
+	TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;    
+   
+    TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+	test.Printf(_L("Time taken to create %d entries = %d ms (%d ms/entry)\n"), numFiles, timeTakenInMs, timeTakenInMs/numFiles );     
+	test.Printf(_L("TRIM_MULT     :%d\n"), GetTrimMultValue());
+    test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+    test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+    }
+
+static void ReWriteHalf(TInt aDrive)
+    {
+    TInt64 diskSize = DiskSize(aDrive);
+    
+    RFile f;
+    TUint initTicks = 0;
+    TUint finalTicks = 0;
+
+	TFileName sessionPath;
+	TInt r=TheFs.SessionPath(sessionPath);
+	test_KErrNone(r);
+	TBuf8<8> WriteData =_L8("Wibbleuy");
+	
+	r=TheFs.MkDirAll(gSessionPath);
+	
+	
+    TUint entrySize = KMaxFileSize;
+    TInt numFiles = CalcEntries(diskSize, entrySize);
+    test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ; 
+    test.Printf(_L("Create %d entries\n"),numFiles/2);
+    
+    test.Printf(_L("TRIM_MULT     :%d\n"), GetTrimMultValue());
+    test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+    test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+    initTicks = User::FastCounter();
+    
+    for( TInt i = 0; i < numFiles; i += 2)
+        {
+
+        test.Printf(_L("Create FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+		TFileName baseName= gSessionPath;
+		baseName.Append(_L("FILE"));
+		baseName.AppendNum(i);
+		r=f.Replace(TheFs,baseName,EFileWrite);
+		test_KErrNone(r);
+		r = f.SetSize(entrySize);
+		if( r == KErrDiskFull)
+		    {
+		        numFiles = i;
+		        break;
+		    }
+		test_Value(r, r == KErrNone || r==KErrDiskFull);
+		r=f.Write((entrySize-30),WriteData);
+		test_KErrNone(r);
+		f.Flush();
+		f.Close();
+		}
+
+    test.Printf(_L("\nTRIM_MULT     :%d\n"), GetTrimMultValue());
+    test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+    test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+    
+	test.Printf(_L("Test all entries have been created successfully\n"));
+	TBuf8<8> ReadData;
+	TInt Size=0;
+	for (TInt j=0; j < numFiles; j += 2)
+		{
+		
+        test.Printf(_L("Check FILE%d\t(%3d%%)\r"), j, (100*j/numFiles) );
+		TFileName baseName = gSessionPath;
+		baseName.Append(_L("FILE"));
+		baseName.AppendNum(j);
+
+		TInt r=f.Open(TheFs,baseName,EFileRead);
+		if (r!=KErrNone)
+			{
+			test_Value(r, r == KErrNotFound && j==numFiles);
+			return;
+			}
+		ReadData.FillZ();
+		r=f.Read((entrySize-30),ReadData);
+		test_KErrNone(r);
+		test(f.Size(Size)==KErrNone);
+		test(entrySize == (TUint)Size);
+		test(ReadData==WriteData);
+		f.Close();
+		}
+		
+	finalTicks = User::FastCounter();
+	TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;    
+   
+    TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+	test.Printf(_L("Time taken to create %d entries = %d ms (%d ms/entry)\n"), numFiles/2, timeTakenInMs, timeTakenInMs/numFiles/2 );     
+	test.Printf(_L("TRIM_MULT     :%d\n"), GetTrimMultValue());
+    test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+    test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+    }
+
+
+
+static void DeleteAll(TInt aDrive)
+    {
+    TInt64 diskSize = DiskSize(aDrive);
+    
+    TUint initTicks = 0;
+    TUint finalTicks = 0;
+
+	TFileName sessionPath;
+	TInt r=TheFs.SessionPath(sessionPath);
+	test_KErrNone(r);
+
+    TUint entrySize = KMaxFileSize;
+    TInt numFiles = CalcEntries(diskSize, entrySize);
+    test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ; 
+    test.Printf(_L("Delete %d entries\n"),numFiles);
+    
+    test.Printf(_L("TRIM_MULT     :%d\n"), GetTrimMultValue());
+    test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+    test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+    
+    initTicks = User::FastCounter();
+    
+    for( TInt i = 2; i < numFiles; ++i)
+        {
+        test.Printf(_L("Delete FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+		TFileName baseName = gSessionPath;
+		baseName.Append(_L("FILE"));
+		baseName.AppendNum(i);
+		TInt r=TheFs.Delete(baseName);
+		test_Value(r, r == KErrNotFound || r == KErrNone);
+		}
+		
+	finalTicks = User::FastCounter();
+	TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;   
+	
+	TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+	test.Printf(_L("Time taken to delete %d entries = %d ms (%d ms/entry)\n"), numFiles, timeTakenInMs, timeTakenInMs/numFiles); 
+	test.Printf(_L("TRIM_MULT     :%d\n"), GetTrimMultValue());
+    test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+    test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+    }
+
+static void DeleteHalf(TInt aDrive)
+    {
+    TInt64 diskSize = DiskSize(aDrive);
+    
+    TUint initTicks = 0;
+    TUint finalTicks = 0;
+
+	TFileName sessionPath;
+	TInt r=TheFs.SessionPath(sessionPath);
+	test_KErrNone(r);
+
+    TUint entrySize = KMaxFileSize;
+    TInt numFiles = CalcEntries(diskSize, entrySize);
+    test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ; 
+    test.Printf(_L("Delete %d entries\n"),numFiles/2);
+    
+    test.Printf(_L("TRIM_MULT     :%d\n"), GetTrimMultValue());
+    test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+    test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+    
+    initTicks = User::FastCounter();
+    
+    for( TInt i = 0; i < numFiles; i +=2)
+        {
+        test.Printf(_L("Delete FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+		TFileName baseName = gSessionPath;
+		baseName.Append(_L("FILE"));
+		baseName.AppendNum(i);
+		TInt r=TheFs.Delete(baseName);
+		test_Value(r, r == KErrNotFound || r == KErrNone);
+		}
+		
+	finalTicks = User::FastCounter();
+	TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;   
+	
+	TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+	test.Printf(_L("Time taken to delete %d entries = %d ms (%d ms/entry)\n"), numFiles/2, timeTakenInMs, timeTakenInMs/numFiles/2); 
+	test.Printf(_L("TRIM_MULT     :%d\n"), GetTrimMultValue());
+    test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+    test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+    }
+
+
+static void WaitUntilTrimDone()
+    {
+     
+    TUint initTicks = User::FastCounter();
+    TUint finalTicks = 0;
+
+#define READ_TO_KEEP_CARD_ON
+#ifdef READ_TO_KEEP_CARD_ON
+
+    const TInt readSize = 4096;
+    const TInt timeToRead = 30;
+
+	test.Printf(_L("Read a file for %d sec to keep card power on\n"), timeToRead );
+	TBuf8<4096> ReadData;
+		
+	RTimer timer;
+	timer.CreateLocal();
+	TRequestStatus reqStat;
+
+    //test.Printf(_L("Timer started.\n"));
+
+	TFileName baseName = gSessionPath;
+	baseName.Append(_L("FILE1"));
+
+    RFile f;
+	TInt r=f.Open(TheFs,baseName,EFileRead);
+	if (r!=KErrNone)
+		{
+		return;
+		}
+	TInt alreadyRead = 0;
+	TInt fileSize;
+	test(f.Size(fileSize)==KErrNone);
+	
+	//test.Printf(_L("File size:%d.\n"), fileSize);
+	
+	timer.After(reqStat, timeToRead*1000000); // After 30 secs
+	
+	while( reqStat==KRequestPending )
+	    {   
+    
+	    test.Printf(_L("Read pos:%d\r"), alreadyRead );
+	    ReadData.FillZ();
+	    r=f.Read(readSize,ReadData);
+	    
+	    test_KErrNone(r);
+        alreadyRead += readSize;
+        if( alreadyRead == fileSize)
+            {
+             alreadyRead = 0;
+		     f.Seek(ESeekStart, alreadyRead);
+            }
+        User::After(1000);        // 1 ms
+	    }
+    
+    timer.Close();
+    
+	f.Close();
+	
+    test.Printf(_L("\n"));
+
+#else
+
+    TInt trimMult = GetTrimMultValue(); // Get TRIM_MULT value from eMMC Extended CSD
+    test.Printf(_L("TRIM_MULT:%d\r"), trimMult);
+    while( trimMult-- > 0  )
+        {
+        // Wait for a while
+        User::After(300000);        // TRIM Timeout = 300ms x TRIM_MULT
+        test.Printf(_L("TRIM_MULT:%d\r"), trimMult);
+        TInt trim = GetTrimMultValue();
+        }
+
+#endif
+        
+    finalTicks = User::FastCounter(); 
+	TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;   
+	
+	TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+	test.Printf(_L("Time taken to TRIM done = %d ms\n"), timeTakenInMs); 
+    }
+
+
+
+void doExit()
+    {
+    iDriver.Close();
+
+    User::FreeLogicalDevice(_L("MmcIf"));
+        
+	test.End();
+	test.Close();
+        
+    }
+
+GLDEF_C void CallTestsL(void)
+//
+// Call all tests
+//
+	{
+
+	test.Next(gSessionPath);
+
+    TInt err;
+	err=User::LoadLogicalDevice(_L("D_MMCIF"));
+	__ASSERT_ALWAYS((err==KErrNone||err==KErrAlreadyExists),Panic(ELoadingMmcDriver));
+    test.Printf(_L("MMCIF driver loaded\n"));
+
+
+    iDriver.Close();
+	TInt r=iDriver.Open(iStack,iDriver.VersionRequired());
+	iDriverOpen=(r==KErrNone)?(TBool)ETrue:(TBool)EFalse;
+	test.Printf(_L("iDriverOpen %d\n"), iDriverOpen);    
+	if( !iDriverOpen )
+	    {
+	    doExit();   
+	    return;
+	    }
+
+    test.Next(_L("Get extended CSD"));
+    r = getExtendedCSD();
+
+    if( r != KErrNone )
+        {
+        test.Next(_L("Extended CSD doesn't exists. Exit."));    
+        doExit();
+        return;    
+        }    
+
+    if( extCSD.ExtendedCSDRev() < 5 )
+        {
+        test.Next(_L("TRIM feature doesn't exists. Exit!"));
+        }
+
+
+	r = HAL::Get(HAL::EFastCounterFrequency, gFastCounterFreq);
+	test_KErrNone(r);
+	test.Printf(_L("HAL::EFastCounterFrequency %d\n"), gFastCounterFreq);
+
+
+    TInt currentDrive = CurrentDrive();
+  	
+  	//  1. Format drive
+    test.Next(_L("Format drive"));
+    Format(currentDrive);
+        
+    //  2. Set TRIM off
+    //test.Next(_L("Set TRIM off"));
+    
+    
+    //  3. Write full with files and measure elapsed time
+    test.Next(_L("Write full"));
+    WriteFull(currentDrive);    
+    
+    //  4. Delete all files and measure elapsed time
+    test.Next(_L("Delete all files"));
+    DeleteAll(currentDrive);
+    
+    //  5. Rewrite all (or a set of) files and measure elapsed time
+    test.Next(_L("Write full"));
+    WriteFull(currentDrive);    
+    
+    //  6. Format drive
+    test.Next(_L("Format drive"));
+    Format(currentDrive);
+    
+    //  7. Set TRIM on
+    //test.Next(_L("Set TRIM on"));
+    
+    //  8. Write full with files and measure elapsed time
+    test.Next(_L("Write full"));
+    WriteFull(currentDrive);    
+    
+    //  9. Delete all files and measure elapsed time
+    test.Next(_L("Delete all files"));
+    DeleteAll(currentDrive);
+    
+    // 10. Wait for a while (give time to eMMC to do its TRIM job)
+    test.Next(_L("Wait for TRIM done"));
+    WaitUntilTrimDone();
+    
+    // 11. Rewrite all (or same set of) files and measure elapsed time
+    test.Next(_L("Write full"));
+    WriteFull(currentDrive);    
+    
+    // 12. Format drive
+    test.Next(_L("Format drive"));
+    Format(currentDrive);
+
+    // 13. Write full with files and measure elapsed time
+    test.Next(_L("Write full"));
+    WriteFull(currentDrive);    
+    
+    // 14. Delete half of files and measure elapsed time
+    test.Next(_L("Delete half of files"));
+    DeleteHalf(currentDrive);
+    
+    // 15. Re-write half of files and measure elapsed time
+    test.Next(_L("Re-write half"));
+    ReWriteHalf(currentDrive);    
+
+
+    // 16. Format drive
+    test.Next(_L("Format drive"));
+    Format(currentDrive);
+
+    // 17. Write full with files and measure elapsed time
+    test.Next(_L("Write full"));
+    WriteFull(currentDrive);    
+    
+    // 18. Delete half of files and measure elapsed time
+    test.Next(_L("Delete half of files"));
+    DeleteHalf(currentDrive);
+    
+    // 19. Wait for a while (give time to eMMC to do its TRIM job)
+    test.Next(_L("Wait for TRIM done"));
+    WaitUntilTrimDone();
+    
+    // 20. Re-write half of files and measure elapsed time
+    test.Next(_L("Re-write half"));
+    ReWriteHalf(currentDrive);    
+    
+    // 21. Format drive
+    test.Next(_L("Format drive"));
+    Format(currentDrive);
+
+    doExit();
+
+    return;
+	}
+
+GLDEF_C TInt E32Main()
+    {
+    TInt r=TheFs.Connect();
+	test_KErrNone(r);
+
+    test.Title();
+	test.Start(_L("Start Benchmarking ..."));
+	
+    TInt theDrive;
+    gDriveToTest='E';		
+	r=TheFs.CharToDrive(gDriveToTest,theDrive);
+	test_KErrNone(r);
+    
+    gSessionPath=_L("?:\\TRIMTEST\\");
+	TChar driveLetter;
+	r=TheFs.DriveToChar(theDrive,driveLetter);
+	test_KErrNone(r);
+	gSessionPath[0]=(TText)driveLetter;
+	r=TheFs.SetSessionPath(gSessionPath);
+	test_KErrNone(r);
+
+    r=TheFs.MkDirAll(gSessionPath);
+	if(r == KErrCorrupt)
+		{
+		test.Printf(_L("Attempting to create directory \'%S\' failed, KErrCorrupt\n"), &gSessionPath);
+		test.Printf(_L("This could be caused by a previous failing test, or a test media defect\n"));
+		test.Printf(_L("Formatting drive, retrying MkDirall\nShould subsequent tests fail with KErrCorrupt (%d) as well, replace test medium !\n"),
+			r);
+		Format(theDrive);
+		r=TheFs.MkDirAll(gSessionPath);
+		test_KErrNone(r);
+		}
+	else if (r == KErrNotReady)
+		{
+		TDriveInfo d;
+		r=TheFs.Drive(d, theDrive);
+		test_KErrNone(r);
+		if (d.iType == EMediaNotPresent)
+			test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)driveLetter);
+		else
+			test.Printf(_L("medium found (type %d) but drive %c: not ready\nPrevious test may have hung; else, check hardware.\n"), (TInt)d.iType, (TUint)driveLetter);
+		}
+	test_Value(r, r == KErrNone || r == KErrAlreadyExists);
+
+
+    CallTestsL();
+
+	TheFs.Close();
+
+    return(KErrNone);
+    }
--- a/kerneltest/f32test/group/bld.inf	Mon Oct 11 17:54:41 2010 +0100
+++ b/kerneltest/f32test/group/bld.inf	Mon Oct 11 19:11:06 2010 +0100
@@ -55,6 +55,9 @@
 
 t_fsrvbm    support
 t_fsysbm    support
+
+t_trimbm    manual
+
 t_whet      support
 #ifdef ARMCC
 t_whetvfp   support
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/group/t_trimbm.mmp	Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,35 @@
+// Copyright (c) 1997-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:
+// f32test/group/t_trimbm.mmp
+//
+//
+
+TARGET         t_trimbm.exe
+TARGETTYPE     EXE
+SOURCEPATH     ../bench
+SOURCE         t_trimbm.cpp
+SOURCEPATH     ../server
+SOURCEPATH     ../fileutils/src
+SOURCE         t_chlffs.cpp
+
+LIBRARY        euser.lib efsrv.lib hal.lib
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+USERINCLUDE    ../server
+USERINCLUDE    ../fileutils/inc
+
+EPOCHEAPSIZE	0x1000 0x02000000
+CAPABILITY		TCB DISKADMIN ALLFILES
+VENDORID 0x70000001
+
+SMPSAFE