os/kernelhwsrv/kernel/eka/drivers/locmedia/locmedia.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\drivers\locmedia\locmedia.cpp
    15 // 
    16 //
    17 
    18 #include "locmedia.h"
    19 #include <d32locd.h>
    20 #include "dmasupport.h"
    21 #include <kernel/cache.h>
    22 
    23 #include "OstTraceDefinitions.h"
    24 #ifdef OST_TRACE_COMPILER_IN_USE
    25 #include "locmedia_ost.h"
    26 #ifdef __VC32__
    27 #pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
    28 #endif
    29 #include "locmediaTraces.h"
    30 #endif
    31 
    32 
    33 #if defined(_DEBUG) && defined(__DEMAND_PAGING__)
    34 //#define __DEBUG_DEMAND_PAGING__
    35 #endif
    36 
    37 
    38 #if 0
    39 #define CHECK_RET(r)	if ((r)==KErrNotSupported && (KDebugNum(KSCRATCH))) {NKern::Lock(); *(TInt*)0xfaece5=0;}
    40 //#define CHECK_RET(r)
    41 #else
    42 #define CHECK_RET(r)
    43 #endif
    44 
    45 _LIT(KLddName,"LocDrv");
    46 _LIT(KLitMediaDriverName, "Media.*");
    47 _LIT(KLitLocMedia,"LocMedia");
    48 
    49 #define LOCM_FAULT()	Kern::Fault("LOCMEDIA",__LINE__)
    50 
    51 const TInt KMaxLocalDriveCapsLength=256;
    52 const TInt KMaxQueryDeviceLength=256;
    53 
    54 // The maximum amount of user-data which will be pinned. If a request is longer 
    55 // than this value it will be split up into a number of requests
    56 // This value is a bit arbitrary - it needs to be sufficiently large so that transfer 
    57 // rates don't suffer too much - but it can't be too big or we'd be "stealing" too much 
    58 // memory from the demand paging pool and starving other processes
    59 const TInt KMaxPinData = 256*1024;
    60 
    61 // The number of locks available for pinning shared by all the drive threads in the system. 
    62 // If all locks are in use then a single pre-allocated lock is used.
    63 const TInt KDynamicPagingLockCount = 8;
    64 
    65 TLocDrv* TheDrives[KMaxLocalDrives];
    66 DMedia* TheMedia[KMaxLocalDrives];
    67 HBuf* DriveNames[KMaxLocalDrives];
    68 TInt UsedMedia=0;
    69 TPasswordStore* ThePasswordStore=NULL;
    70 
    71 class DPrimaryMediaBase::DBody : public DBase
    72 	{
    73 public:
    74 	TInt iPhysDevIndex;
    75 	TInt iRequestCount;
    76 #ifdef __DEMAND_PAGING__
    77 	DMediaPagingDevice* iPagingDevice;
    78 	TInt iPageSizeMsk;			// Mask of page size (e.g. 4096-1 -> 4095)
    79 	TInt iMediaChanges;
    80 #endif
    81 	};
    82 
    83 #ifdef __DEMAND_PAGING__
    84 DMediaPagingDevice* ThePagingDevices[KMaxLocalDrives];
    85 DPrimaryMediaBase* TheRomPagingMedia = NULL;
    86 DPrimaryMediaBase* TheDataPagingMedia = NULL;
    87 TBool DataPagingDeviceRegistered = EFalse;
    88 class DPinObjectAllocator;
    89 DPinObjectAllocator* ThePinObjectAllocator = NULL;
    90 
    91 // The paging media might share a DfcQ with other non-paging media (e.g. 2 MMC/SD cards sharing the same stack)
    92 // In this case, we need to avoid taking page faults on the non-paging media too, hence the need for these checks:
    93 inline TBool DataPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia)
    94 	{return TheDataPagingMedia && TheDataPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;}
    95 inline TBool RomPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia)
    96 	{return TheRomPagingMedia && TheRomPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;}
    97 
    98 
    99 
   100 /* 
   101 DPinObjectAllocator
   102 
   103 Internal class which contains :
   104 	(1) a queue of pre-allocated TVirtualPinObject's; 
   105 	(2) a single pre-allocated DFragmentationPagingLock object: 
   106 		this may be used if there are no TVirtualPinObject's available or if Kern::PinVirtualMemory() fails
   107 */
   108 NONSHARABLE_CLASS(DPinObjectAllocator) : public DBase
   109 	{
   110 public:
   111 	/*
   112 	SVirtualPinContainer
   113 	Internal class encapsulating a TVirtualPinObject.
   114 	Contains a SDblQueLink so that it may form part of a SDblQue
   115 	*/
   116 	typedef struct
   117 		{
   118 		TVirtualPinObject* iObject;
   119 		SDblQueLink iLink;
   120 		} SVirtualPinContainer;
   121 
   122 public:
   123 	inline DPinObjectAllocator() {};
   124 	~DPinObjectAllocator();
   125 	TInt Construct(TInt aObjectCount, TUint aNumPages);
   126 	
   127 	SVirtualPinContainer* AcquirePinObject();
   128 	void ReleasePinObject(SVirtualPinContainer* aVirtualPinObject);
   129 
   130 	inline DFragmentationPagingLock& PreAllocatedDataLock() {return *iPreAllocatedDataLock;}
   131 
   132 private:
   133 	// array of SVirtualPinContainer's
   134 	SVirtualPinContainer* iVirtualPinContainers;
   135 	TInt iObjectCount;
   136 
   137 	// queues containing SVirtualPinContainer's
   138 	SDblQue iFreeQ;
   139 	
   140 	// pre-allocated (small) buffers for locking client data should Kern::PinVirtualMemory() fail
   141 	DFragmentationPagingLock* iPreAllocatedDataLock;
   142 
   143 	// A mutex to protect access to the pinning objects.
   144 	NFastMutex iLock;
   145 
   146 public:
   147 	TUint iFragmentGranularity;
   148 	};
   149 
   150 
   151 DPinObjectAllocator::~DPinObjectAllocator()
   152 	{
   153 	OstTraceFunctionEntry1( DPINOBJECTALLOCATOR_DPINOBJECTALLOCATOR_ENTRY, this );
   154 	if (iPreAllocatedDataLock)
   155 		{
   156 		iPreAllocatedDataLock->Cleanup();
   157 		delete iPreAllocatedDataLock;
   158 		}
   159 
   160 	for (TInt n=0; n<iObjectCount; n++)
   161 		{
   162 		SVirtualPinContainer& virtualPinContainer = iVirtualPinContainers[n];
   163 		if (virtualPinContainer.iObject)
   164 			Kern::DestroyVirtualPinObject(virtualPinContainer.iObject);
   165 		}
   166 
   167 	delete [] iVirtualPinContainers;
   168 	OstTraceFunctionExit1( DPINOBJECTALLOCATOR_DPINOBJECTALLOCATOR_EXIT, this );
   169 	}
   170 
   171 TInt DPinObjectAllocator::Construct(TInt aObjectCount, TUint aNumPages)
   172 	{
   173 	OstTraceFunctionEntryExt( DPINOBJECTALLOCATOR_CONSTRUCT_ENTRY, this );
   174 	TInt pageSize = Kern::RoundToPageSize(1);
   175 	iFragmentGranularity = pageSize * aNumPages;
   176 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation granularity set to 0x%x", iFragmentGranularity));
   177 	OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPINOBJECTALLOCATOR_CONSTRUCT, "Fragmentation granularity=0x%x", iFragmentGranularity);
   178 	
   179 	// construct the paging lock containing pre-allocated buffers
   180 
   181 	iPreAllocatedDataLock = new DFragmentationPagingLock();
   182 	if(!iPreAllocatedDataLock)
   183 	    {
   184 		OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT1, this, KErrNoMemory );
   185 		return KErrNoMemory;
   186 	    }
   187 	TInt r = iPreAllocatedDataLock->Construct(aNumPages);
   188 	if (r != KErrNone)
   189 	    {
   190 		OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT2, this, r );
   191 		return r;
   192 	    }
   193 
   194 
   195 	SVirtualPinContainer* iVirtualPinContainers = new SVirtualPinContainer[aObjectCount];
   196 	if (iVirtualPinContainers == NULL)
   197 	    {
   198 		OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT3, this, KErrNoMemory );
   199 		return KErrNoMemory;
   200 	    }
   201 	memclr(iVirtualPinContainers, sizeof(SVirtualPinContainer) * aObjectCount);
   202 	iObjectCount = aObjectCount;
   203 
   204 	// construct the queue of dynamic paging locks
   205 	for (TInt n=0; n<aObjectCount; n++)
   206 		{
   207 		SVirtualPinContainer& pinContainer = iVirtualPinContainers[n];
   208 
   209 		TInt r = Kern::CreateVirtualPinObject(pinContainer.iObject);
   210 		if (r != KErrNone)
   211 		    {
   212 			OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT4, this, KErrNoMemory );
   213 			return KErrNoMemory;
   214 		    }
   215 
   216 		iFreeQ.Add(&pinContainer.iLink);
   217 		}
   218 	
   219 	OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT5, this, KErrNone );
   220 	return KErrNone;
   221 	}
   222 
   223 /** 
   224 returns a SVirtualPinContainer object or NULL if NULL available
   225 */
   226 DPinObjectAllocator::SVirtualPinContainer* DPinObjectAllocator::AcquirePinObject()
   227 	{
   228 	OstTraceFunctionEntry1( DPINOBJECTALLOCATOR_ACQUIREPINOBJECT_ENTRY, this );
   229 	SVirtualPinContainer* pinContainer = NULL;
   230 	
   231 	NKern::FMWait(&iLock);
   232 
   233 	if (!iFreeQ.IsEmpty())
   234 		{
   235 		SDblQueLink* link = iFreeQ.First();
   236 		pinContainer = _LOFF(link, SVirtualPinContainer, iLink);
   237 		link->Deque();
   238 		}
   239 
   240 
   241 	NKern::FMSignal(&iLock);
   242 	OstTraceFunctionExit1( DPINOBJECTALLOCATOR_ACQUIREPINOBJECT_EXIT, this );
   243 	return pinContainer;
   244 	}
   245 
   246 /** 
   247 returns a SVirtualPinContainer object to the pool
   248 */
   249 void DPinObjectAllocator::ReleasePinObject(SVirtualPinContainer* aPinContainer)
   250 	{
   251 	OstTraceFunctionEntry1( DPINOBJECTALLOCATOR_RELEASEPINOBJECT_ENTRY, this );
   252 	NKern::FMWait(&iLock);
   253 
   254 	iFreeQ.Add(&aPinContainer->iLink);
   255 
   256 	NKern::FMSignal(&iLock);
   257 	OstTraceFunctionExit1( DPINOBJECTALLOCATOR_RELEASEPINOBJECT_EXIT, this );
   258 	}
   259 
   260 #endif	// __DEMAND_PAGING__
   261 
   262 
   263 /********************************************
   264  * Local drive device base class
   265  ********************************************/
   266 DECLARE_EXTENSION_LDD()
   267 	{
   268 	return new DLocalDriveFactory;
   269 	}
   270 
   271 DLocalDriveFactory::DLocalDriveFactory()
   272 //
   273 // Constructor
   274 //
   275 	{
   276 	OstTraceFunctionEntry1( DLOCALDRIVEFACTORY_DLOCALDRIVEFACTORY_ENTRY, this );
   277 	iParseMask=KDeviceAllowUnit|KDeviceAllowInfo;
   278 	iUnitsMask=~(0xffffffff<<KMaxLocalDrives);
   279 	iVersion=TVersion(KLocalDriveMajorVersion,KLocalDriveMinorVersion,KLocalDriveBuildVersion);
   280 	OstTraceFunctionExit1( DLOCALDRIVEFACTORY_DLOCALDRIVEFACTORY_EXIT, this );
   281 	}
   282 
   283 TInt DLocalDriveFactory::Install()
   284 //
   285 // Install the device driver.
   286 //
   287 	{
   288 	return SetName(&KLddName);
   289 	}
   290 
   291 void DLocalDriveFactory::GetCaps(TDes8& /*aDes*/) const
   292 //
   293 // Return the Comm capabilities.
   294 //
   295 	{
   296 //	TCapsLocalDriveV01 b;
   297 //	b.version=iVersion;
   298 //	aDes.FillZ(aDes.MaxLength());
   299 //	aDes.Copy((TUint8 *)&b,Min(aDes.MaxLength(),sizeof(b)));
   300 	}
   301 
   302 TInt DLocalDriveFactory::Create(DLogicalChannelBase*& aChannel)
   303 //
   304 // Create a channel on the device.
   305 //
   306 	{
   307 	OstTraceFunctionEntry1( DLOCALDRIVEFACTORY_CREATE_ENTRY, this );
   308 	aChannel=new DLocalDrive;
   309 	return aChannel?KErrNone:KErrNoMemory;
   310 	}
   311 
   312 /********************************************
   313  * Local drive interface class
   314  ********************************************/
   315 DLocalDrive::DLocalDrive()
   316 	{
   317 //	iLink.iNext=NULL;
   318 	}
   319 
   320 DLocalDrive::~DLocalDrive()
   321 	{
   322 	OstTraceFunctionEntry1( DLOCALDRIVE_DLOCALDRIVE_ENTRY, this );
   323 	if (iDrive)
   324 		{
   325 		__KTRACE_OPT(KLOCDRV,Kern::Printf(">DLocalDrive::DoClose D:%d, M:%08x",iDrive->iDriveNumber,iDrive->iMedia));
   326 		iDrive->Disconnect(this);
   327 		__KTRACE_OPT(KLOCDRV,Kern::Printf("<DLocalDrive::DoClose D:%d, M:%08x",iDrive->iDriveNumber,iDrive->iMedia));
   328 		}
   329 	DThread* pC=NULL;
   330 	NKern::LockSystem();
   331 	if (iCleanup.iThread)
   332 		{
   333 		pC=iCleanup.iThread;
   334 		iCleanup.Remove();
   335 		iCleanup.iThread=NULL;
   336 		}
   337 	NKern::UnlockSystem();
   338 	if (pC)	// original client may already have terminated
   339 		{
   340 		if (iNotifyChangeRequest)
   341 			Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrCancel);
   342 		pC->Close(NULL);	// balances Open() in DoCreate
   343 		}
   344 	if (iNotifyChangeRequest)
   345 		Kern::DestroyClientRequest(iNotifyChangeRequest);
   346 	OstTraceFunctionExit1( DLOCALDRIVE_DLOCALDRIVE_EXIT, this );
   347 	}
   348 
   349 TInt DLocalDrive::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer)
   350 	{
   351     OstTraceFunctionEntry1( DLOCALDRIVE_DOCREATE_ENTRY, this );
   352     
   353 	if(!Kern::CurrentThreadHasCapability(ECapabilityTCB,__PLATSEC_DIAGNOSTIC_STRING("Checked by ELOCD.LDD (Local Media Driver)")))
   354 	    {
   355 		OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT1, this, KErrPermissionDenied );
   356 		return KErrPermissionDenied;
   357 	    }
   358 	if (!Kern::QueryVersionSupported(TVersion(KLocalDriveMajorVersion,KLocalDriveMinorVersion,KLocalDriveBuildVersion),aVer))
   359 	    {
   360 		OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT2, this, KErrNotSupported );
   361 		return KErrNotSupported;
   362 	    }
   363 
   364 	NKern::ThreadEnterCS();
   365 	TInt r = Kern::CreateClientDataRequest(iNotifyChangeRequest);
   366 	NKern::ThreadLeaveCS();
   367 	if (r != KErrNone)
   368 	    {
   369 		OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT3, this, r );
   370 		return r;
   371 	    }
   372 	
   373 	DThread& t=Kern::CurrentThread();
   374 	NKern::LockSystem();
   375 	t.AddCleanup(&iCleanup);
   376 	NKern::UnlockSystem();
   377 	t.Open();
   378 	iNotifyChangeRequest->SetDestPtr((TBool*) anInfo);
   379 
   380 	iDrive=TheDrives[aUnit];
   381 	if (!iDrive)
   382 	    {
   383 		OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT4, this, KErrNotSupported );
   384 		return KErrNotSupported;
   385 	    }
   386 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DLocalDrive Create - connect to drive %d, M:%08x",iDrive->iDriveNumber,iDrive->iMedia));
   387 	r=iDrive->Connect(this);
   388 	__KTRACE_OPT(KLOCDRV,Kern::Printf("<DLocalDrive Create D:%d, M:%08x r:%d",iDrive->iDriveNumber,iDrive->iMedia,r));
   389 
   390 	if (r!=KErrNone)
   391 		iDrive=NULL;	// didn't connect so don't disconnect
   392 	
   393 	OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT5, this, r );
   394 	return r;
   395 	}
   396 
   397 #if defined(_DEBUG)
   398 void DebugDumpDriveCaps(const TLocDrv* aDrive, const TAny* aCaps)
   399 	{
   400 	const TLocalDriveCapsV5& c=*(const TLocalDriveCapsV5*)aCaps;
   401 	Kern::Printf("Drive %d Caps:", aDrive->iDriveNumber);
   402 	Kern::Printf("Size: %lx", c.iSize);
   403 	Kern::Printf("Type: %08x", c.iType);
   404 	Kern::Printf("Bus : %08x", c.iConnectionBusType);
   405 	Kern::Printf("DAtt: %08x", c.iDriveAtt);
   406 	Kern::Printf("MAtt: %08x", c.iMediaAtt);
   407 	Kern::Printf("Base: %08x", c.iBaseAddress);
   408 	Kern::Printf("FSID: %04x", c.iFileSystemId);
   409 	Kern::Printf("PTYP: %04x", c.iPartitionType);
   410 	Kern::Printf("HIDN: %08x", c.iHiddenSectors);
   411 	Kern::Printf("EBSZ: %08x", c.iEraseBlockSize);
   412     //---------------- V5 ------------------//
   413     if (c.iSerialNumLength != 0)
   414         {
   415         Kern::Printf("SN: length is %d", c.iSerialNumLength);
   416         TBuf8<2*KMaxSerialNumLength+20> snBuf;
   417         snBuf.Append(_L8("SN: content is "));
   418         for (TUint i=0; i<c.iSerialNumLength; i++)
   419             snBuf.AppendNumFixedWidth(c.iSerialNum[i], EHex, 2);
   420         Kern::Printf((const char*)snBuf.Ptr());
   421         }
   422     else
   423         Kern::Printf("SN: not supported");
   424 	}
   425 #endif
   426 
   427 /*
   428  * Requests are passed in message as follows:
   429  * iValue	= request ID
   430  * iArg[0,1]= Position
   431  * iArg[2,3]= Length
   432  * iArg[4]	= Pointer to remote thread (NULL if client)
   433  * iArg[5]	= Pointer to remote descriptor
   434  * iArg[6]	= Offset into remote descriptor
   435  * iArg[7]	= Flags (whole media)
   436  * iArg[8]	= Pointer to TLocDrv
   437  */
   438 
   439 TInt DLocalDrive::Request(TInt aFunction, TAny* a1, TAny* a2)
   440 	{
   441 	OstTraceFunctionEntry1( DLOCALDRIVE_REQUEST_ENTRY, this );
   442 	__TRACE_TIMING(0);
   443 	__KTRACE_OPT(KLOCDRV,Kern::Printf(">DLocalDrive::DoControl D:%d M:%08x F:%d A1:%08x A2:%08x",
   444 														iDrive->iDriveNumber, iDrive->iMedia, aFunction, a1, a2));
   445 	OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST, "iMedia=0x%08x; iDriveNumber=%d; Request Id=%d", (TUint) iDrive->iMedia, (TInt) iDrive->iDriveNumber, (TInt) aFunction );
   446 	
   447 	TInt r=KErrNotSupported;
   448 	TLocDrvRequest& m=TLocDrvRequest::Get();
   449 	m.Flags()=0;
   450 	m.Drive()=iDrive;
   451 	switch (aFunction)
   452 		{
   453 		case RLocalDrive::EControlRead:
   454 			{
   455 			m.Id()=ERead;
   456 			r=m.ProcessMessageData(a1);
   457 			__TRACE_TIMING(1);
   458 			if (r==KErrNone)
   459 				{
   460 				__TRACE_TIMING(2);
   461 				OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READ, "ERead iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m);
   462 				r=iDrive->Request(m);
   463 				__TRACE_TIMING(3);
   464 				OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READ_RETURN, "ERead Return iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m );
   465 				}
   466 			m.CloseRemoteThread();
   467 			break;
   468 			}
   469 		case RLocalDrive::EControlWrite:
   470 			{
   471 			m.Id()=EWrite;
   472 			r=m.ProcessMessageData(a1);
   473 			if (r==KErrNone)
   474 				{
   475 				OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITE, "EWrite iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m );
   476 				r=iDrive->Request(m);
   477 				OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITE_RETURN, "EWrite Return iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m );
   478 				}
   479 			m.CloseRemoteThread();
   480 			break;
   481 			}
   482 		case RLocalDrive::EControlCaps:
   483 			{
   484 			TBuf8<KMaxLocalDriveCapsLength> capsBuf;
   485 			capsBuf.SetMax();
   486 			capsBuf.FillZ();
   487 			m.Id()=ECaps;
   488 			m.RemoteDes()=(TAny*)capsBuf.Ptr();	// overload this
   489 			m.Length()=KMaxLocalDriveCapsLength;	// for pinning
   490 			r=iDrive->Request(m);
   491 
   492 			if(r == KErrNone && iDrive->iMedia != NULL && iDrive->iMedia->iDriver != NULL)
   493 				{
   494 				// Fill in default media size if not specified by the driver
   495 				//
   496 				// - This uses the members of TLocalDriveCapsV4 which was primarily used
   497 				//   to report NAND flash characteristics, but are general enough to be
   498 				//	 used to report the size of any type of media without adding yet
   499 				//	 another extension to TLocalDriveCapsVx.
   500 				//
   501 				
   502 				TLocalDriveCapsV4& caps = *(TLocalDriveCapsV4*)capsBuf.Ptr();
   503 				
   504 				if(caps.iSectorSizeInBytes == 0)
   505 					{
   506 					// Fill in a default value for the disk sector size
   507 					caps.iSectorSizeInBytes = 512;
   508 
   509 					// Zero the number of sectors, as a sector count makes no sense without a sector size
   510 					//  - Fault in debug mode if a sector count is provided to ensure that media driver creators
   511 					//	  set this value,but in release mode continue gracefully be recalculating the sector count.
   512 					__ASSERT_DEBUG(caps.iNumberOfSectors == 0, LOCM_FAULT());
   513 					caps.iNumberOfSectors  = 0;
   514 					caps.iNumPagesPerBlock = 1;	// ...to ensure compatiility with NAND semantics
   515 					}
   516 
   517 				if(caps.iNumberOfSectors == 0)
   518 					{
   519 					const Int64 totalSizeInSectors = iDrive->iMedia->iDriver->TotalSizeInBytes() / caps.iSectorSizeInBytes;
   520 					__ASSERT_DEBUG(I64HIGH(totalSizeInSectors) == 0, LOCM_FAULT());
   521 
   522 					if(I64HIGH(totalSizeInSectors) == 0)
   523 						{
   524 						caps.iNumberOfSectors = I64LOW(totalSizeInSectors);
   525 						}
   526 					}
   527 				}
   528 
   529 #if defined(OST_TRACE_COMPILER_IN_USE) && defined(_DEBUG)
   530 			const TLocalDriveCapsV5& caps=*(const TLocalDriveCapsV5*)capsBuf.Ptr();
   531 #endif
   532 			
   533 			OstTraceExt5( TRACE_INTERNALS, DLOCALDRIVE_REQUEST_CAPS1, "Device caps: iDriveNumber=%d; iSize=0x%x; iType=%d; iDriveAtt=%d; TLocDrvRequest Object=0x%x", (TInt)iDrive->iDriveNumber, (TUint) caps.iSize, (TInt) caps.iType, (TInt) caps.iDriveAtt, (TUint) &m);
   534 			OstTraceExt5( TRACE_INTERNALS, DLOCALDRIVE_REQUEST_CAPS2, "Device caps: iBaseAddress=0x%x; iFileSystemId=%d; iPartitionType=%d; iHiddenSectors=0x%x; iEraseBlockSize=0x%x", (TUint) caps.iBaseAddress, (TInt) caps.iFileSystemId, (TUint) caps.iPartitionType, (TUint) caps.iHiddenSectors, (TUint) caps.iEraseBlockSize);
   535 			
   536 #if defined(_DEBUG)
   537 			__KTRACE_OPT(KLOCDRV,DebugDumpDriveCaps(iDrive,capsBuf.Ptr()));
   538 #endif
   539 			Kern::InfoCopy(*(TDes8*)a1, capsBuf);
   540 			break;
   541 			}
   542 		case RLocalDrive::EControlFormat:
   543 			{
   544 			m.Id()=EFormat;
   545 			r=m.ProcessMessageData(a1);
   546 			if (r==KErrNone)
   547 			    {
   548 			    OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORMAT, "EFormat; TLocDrvRequest Object=0x%x", (TUint) &m);
   549 				r=iDrive->Request(m);
   550 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORMAT_RETURN, "EFormat Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   551 			    }
   552 			break;
   553 			}
   554 		case RLocalDrive::EControlEnlarge:
   555 			if ((TInt)a1<0)
   556 				{
   557 				r=KErrArgument;
   558 				break;
   559 				}
   560 			m.Length()=(TInt)a1;
   561 			m.Id()=EEnlarge;
   562 			OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_ENLARGE, "EEnlarge; TLocDrvRequest Object=0x%x", (TUint) &m);
   563 			r=iDrive->Request(m);
   564 			OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_ENLARGE_RETURN, "EEnlarge Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   565 			break;
   566 		case RLocalDrive::EControlReduce:
   567 			{
   568 			if ((TInt)a1<0 || (TInt)a2<0)
   569 				{
   570 				r=KErrArgument;
   571 				break;
   572 				}
   573 			m.Pos()=(TInt)a1;
   574 			m.Length()=(TInt)a2;
   575 			m.Id()=EReduce;
   576 	        OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_REDUCE, "EReduce; TLocDrvRequest Object=0x%x", (TUint) &m);
   577 			r=iDrive->Request(m);
   578 	        OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_REDUCE_RETURN, "EReduce Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   579 			break;
   580 			}
   581 		case RLocalDrive::EControlForceMediaChange:
   582 			m.Pos()=(TInt)a1;
   583 			m.Id()=EForceMediaChange;
   584 	        OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORCEMEDIACHANGE, "EForceMediaChange; TLocDrvRequest Object=0x%x", (TUint) &m);
   585 			r = iDrive->Request(m);
   586 	        OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORCEMEDIACHANGE_RETURN, "EForceMediaChange Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   587 			break;
   588 		case RLocalDrive::EControlMediaDevice:
   589 	        OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLMEDIADEVICE, "EControlMediaDevice; TLocDrvRequest Object=0x%x", (TUint) &m);
   590 			r=iDrive->iPrimaryMedia->iDevice;
   591 			break;
   592 		case RLocalDrive::EControlIsRemovable:
   593 			{
   594 	        OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLISREMOVABLE, "EControlIsRemovable; TLocDrvRequest Object=0x%x", (TUint) &m);
   595 			TInt sockNum;
   596 			r=iDrive->iPrimaryMedia->IsRemovableDevice(sockNum);
   597 			if (r)
   598 				kumemput32(a1,&sockNum,sizeof(TInt));
   599 			break;	
   600 			}
   601 		case RLocalDrive::EControlControlIO:
   602 			{
   603 			TLocalDriveControlIOData d;
   604 			kumemget32(&d,a1,sizeof(d));
   605 
   606 			m.Id() = EControlIO;
   607 			m.iArg[0] = (TAny*) d.iCommand;
   608 			m.iArg[1] = d.iParam1;
   609 			m.iArg[2] = d.iParam2;
   610 
   611 			// if d.iHandle is == KLocalMessageHandle (-1),
   612 			//	d.aParam1 and d.aParam2 are TAny* pointers
   613 			//
   614 			// if d.iHandle is == 0, 
   615 			//	d.aParam1 and d.aParam2 are TInts
   616 			//
   617 			// if d.iHandle is > 0, 
   618 			//	d.aParam1 is a data pointer (TUint8*) 
   619 			//	d.aParam2 is an optional extra paramater (TInt)
   620 			//	d.iHandle is a data length (TInt)
   621 			m.iArg[3] = (TAny*) d.iHandle;
   622 
   623 			//We're highjacking fields representing
   624 			//length and position in a normal message, so
   625 			//let's not have the dispatcher function attempt
   626 			//to adjust for partition size.
   627 			m.Flags() |= TLocDrvRequest::EAdjusted;
   628 			
   629 	        OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLCONTROLIO, "EControlControlIO; TLocDrvRequest Object=0x%x", (TUint) &m);
   630 			r=iDrive->Request(m);
   631 			OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLCONTROLIO_RETURN, "EControlControlIO Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   632 			break;
   633 			}
   634 		case RLocalDrive::EControlSetMountInfo:
   635 			{
   636 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLSETMOUNTINFO, "EControlSetMountInfo; TLocDrvRequest Object=0x%x", (TUint) &m);
   637 			m.Id()=ERead;
   638 			r=m.ProcessMessageData(a1);
   639 			DPrimaryMediaBase* pM=iDrive->iPrimaryMedia;
   640 			if(!pM || r!=KErrNone)
   641 				break;
   642 
   643 			if (pM->iMountInfo.iThread)
   644 				{
   645 				NKern::ThreadEnterCS();
   646 				//Close original thread
   647 				Kern::SafeClose((DObject*&) pM->iMountInfo.iThread,NULL);
   648 				if (m.RemoteDes()!=NULL)
   649 					{
   650 					//Set new mount info and leave setting thread open
   651 #ifdef __DEMAND_PAGING__
   652 					// lock the mount info if this is a data paging media - and keep it locked
   653 					if ((DataPagingDfcQ(pM)) && ((r = LockMountInfo(*pM, m)) != KErrNone))
   654 						break;
   655 #endif
   656 					pM->iMountInfo.iInfo=(TDesC8*)m.RemoteDes();
   657 					pM->iMountInfo.iThread=m.RemoteThread();
   658 					}
   659 				else
   660 					{
   661 					//Clear existing mount info and close setting thread
   662 
   663 #ifdef __DEMAND_PAGING__
   664 					// unlock the mount info if this is a data paging media
   665 					UnlockMountInfo(*pM);
   666 #endif
   667 
   668 					pM->iMountInfo.iInfo=NULL;
   669 					pM->iMountInfo.iThread=NULL;
   670 					m.CloseRemoteThread();
   671 					}
   672 				NKern::ThreadLeaveCS();
   673 				r=KErrNone;
   674 				}
   675 			else
   676 				{
   677 				//Setting mount info for the first time
   678 				if (m.RemoteDes()==NULL)
   679 					{
   680 					// if no mount info, close setting thread opened in ProcessMessageData()
   681 					m.CloseRemoteThread();
   682 					break;
   683 					}
   684 
   685 				NKern::ThreadEnterCS();
   686 #ifdef __DEMAND_PAGING__
   687 				// lock the mount info if this is a data paging media - and keep it locked
   688 				if ((DataPagingDfcQ(pM)) && ((r = LockMountInfo(*pM, m)) != KErrNone))
   689 					break;
   690 #endif
   691 
   692 				pM->iMountInfo.iInfo=(TDesC8*)m.RemoteDes();
   693 				pM->iMountInfo.iThread=m.RemoteThread();
   694 				NKern::ThreadLeaveCS();
   695 				r=KErrNone;
   696 				}
   697 			break;
   698 			}
   699 		case RLocalDrive::EControlPasswordLock:
   700 			{
   701 			m.Id()=EPasswordLock;
   702 			m.RemoteDes() = a1;
   703 
   704 			TMediaPassword oldPasswd;
   705 			TMediaPassword newPasswd;
   706 			TLocalDrivePasswordData pswData;
   707 			r = ReadPasswordData(m, pswData, oldPasswd, newPasswd);
   708 
   709 			if (r == KErrNone)
   710 				{
   711 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDLOCK, "EPasswordLock; TLocDrvRequest Object=0x%x", (TUint) &m);
   712 				r = iDrive->Request(m);
   713 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDLOCK_RETURN, "EPasswordLock Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   714 				}
   715 			break;
   716 			}
   717 		case RLocalDrive::EControlPasswordUnlock:
   718 			{
   719 			m.Id()=EPasswordUnlock;
   720 			m.RemoteDes() = a1;
   721 
   722 			TMediaPassword oldPasswd;
   723 			TMediaPassword newPasswd;
   724 			TLocalDrivePasswordData pswData;
   725 			r = ReadPasswordData(m, pswData, oldPasswd, newPasswd);
   726 
   727 			if(r == KErrNone)
   728 				{
   729 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDUNLOCK, "EPasswordUnLock; TLocDrvRequest Object=0x%x", (TUint) &m);
   730 				r=iDrive->Request(m);
   731 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDUNLOCK_RETURN, "EPasswordUnLock Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   732 				}
   733 			if (r == KErrNone)
   734 				iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0;
   735 			break;
   736 			}
   737 		case RLocalDrive::EControlPasswordClear:
   738 			{
   739 			m.Id()=EPasswordClear;
   740 			m.RemoteDes() = a1;
   741 
   742 			TMediaPassword oldPasswd;
   743 			TMediaPassword newPasswd;
   744 			TLocalDrivePasswordData pswData;
   745 			r = ReadPasswordData(m, pswData, oldPasswd, newPasswd);
   746 
   747 			if (r == KErrNone)
   748 				{
   749 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDCLEAR, "EPasswordClear; TLocDrvRequest Object=0x%x", (TUint) &m);
   750 				r = iDrive->Request(m);
   751 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDCLEAR_RETURN, "EPasswordClear Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   752 				}
   753 			break;
   754 			}
   755 		case RLocalDrive::EControlPasswordErase:
   756 			{
   757 			m.Id()=EPasswordErase;
   758 			OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDERASE, "EPasswordErase; TLocDrvRequest Object=0x%x", (TUint) &m);
   759 			r=iDrive->Request(m);
   760 			OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDERASE_RETURN, "EPasswordErase Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   761 			if(r == KErrNone)
   762 				iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0;
   763 			break;
   764 			}
   765 		case RLocalDrive::EControlNotifyChange:
   766 			if (iCleanup.iThread != &Kern::CurrentThread())
   767 				Kern::PanicCurrentThread(KLitLocMedia,KErrAccessDenied);
   768 			r=KErrNone;
   769 			if (!iNotifyChangeRequest->StatusPtr())
   770 				r = iNotifyChangeRequest->SetStatus((TRequestStatus*) a1);
   771 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLNOTIFYCHANGE, "EControlNotifyChange; TLocDrvRequest Object=0x%x", (TUint) &m);
   772 			break;
   773 		case RLocalDrive::EControlNotifyChangeCancel:
   774 			if (iCleanup.iThread != &Kern::CurrentThread())
   775 				Kern::PanicCurrentThread(KLitLocMedia,KErrAccessDenied);
   776 			Kern::QueueRequestComplete(iCleanup.iThread,iNotifyChangeRequest,KErrCancel);
   777 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLNOTIFYCHANGECANCEL, "EControlNotifyChangeCancel; TLocDrvRequest Object=0x%x", (TUint) &m);
   778 			break;
   779 		case RLocalDrive::EControlReadPasswordStore:
   780 			{
   781 			TUint8  passData[TPasswordStore::EMaxPasswordLength];
   782 			m.RemoteDes() = (TAny*) passData;
   783 			m.Length() = sizeof(passData);
   784 			m.Id()=EReadPasswordStore;
   785 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READPASSWORDSTORE, "EReadPasswordStore; TLocDrvRequest Object=0x%x", (TUint) &m);
   786 			r=iDrive->Request(m);
   787 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READPASSWORDSTORE_RETURN, "EReadPasswordStore Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   788 			if (r==KErrNone)
   789 				{
   790 				TPtr8 pData(passData, (TInt) m.Length(), TPasswordStore::EMaxPasswordLength);
   791 				m.RemoteDes()=(TDes8*)a1;
   792 				r = m.WriteRemote(&pData,0);
   793 				}
   794 			break;
   795 			}
   796 		case RLocalDrive::EControlWritePasswordStore:
   797 			{
   798 			TUint8  passData[TPasswordStore::EMaxPasswordLength];
   799 			TPtr8 pData(passData, TPasswordStore::EMaxPasswordLength);
   800 
   801 			DThread* pT=m.RemoteThread();
   802 			if (!pT)
   803 				pT=m.Client();
   804 
   805 			m.RemoteDes() = (TDes8*)a1;
   806 			r = Kern::ThreadGetDesLength(pT, m.RemoteDes());
   807 			if ( r > pData.MaxLength() )
   808 				r = KErrOverflow;
   809 			if ( r < KErrNone)
   810 				break;
   811 
   812 			r = m.ReadRemote(&pData,0);
   813 			if (r != KErrNone)
   814 				break;
   815 
   816 
   817 			m.RemoteDes() = (TAny*) pData.Ptr();
   818 			m.Length() = pData.Length();
   819 			m.Id()=EWritePasswordStore;
   820 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITEPASSWORDSTORE, "EWritePasswordStore; TLocDrvRequest Object=0x%x", (TUint) &m);
   821 			r=iDrive->Request(m);
   822 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITEPASSWORDSTORE_RETURN, "EReadPasswordStore Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   823 			if(r == KErrNone)
   824 				iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0;
   825 			break;
   826 			}
   827 		case RLocalDrive::EControlPasswordStoreLengthInBytes:
   828 			{
   829 			m.Id()=EPasswordStoreLengthInBytes;
   830 			TInt length;
   831 			m.RemoteDes() = (TAny*) &length;
   832 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDSTORELENGTH, "EPasswordStoreLengthInBytes; TLocDrvRequest Object=0x%x", (TUint) &m);
   833 			r=iDrive->Request(m);
   834 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDSTORELENGTH_RETURN, "EPasswordStoreLengthInBytes Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   835 
   836 			if (r == KErrNone)
   837 				{
   838 				m.RemoteDes()=a1;
   839 				r = m.WriteRemoteRaw(&length,sizeof(TInt));
   840 				}
   841 			
   842 			break;
   843 			}
   844 		case RLocalDrive::EControlGetLastErrorInfo:
   845 			{
   846 			m.Id()=EGetLastErrorInfo;
   847 			m.iArg[0]=this;
   848 			TErrorInfoBuf errorInfoBuf;
   849 			errorInfoBuf.SetMax();
   850 			errorInfoBuf.FillZ();
   851 			m.RemoteDes()=(TAny*) errorInfoBuf.Ptr();	// overload this
   852 			m.Length() = errorInfoBuf.MaxLength();
   853 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_GETLASTERRORINFO, "EGetLastErrorInfo; TLocDrvRequest Object=0x%x", (TUint) &m);
   854 			r=iDrive->Request(m);
   855 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLGETLASTERRORINFO_RETURN, "EControlGetLastErrorInfo Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   856 			Kern::InfoCopy(*(TDes8*)a1, errorInfoBuf);
   857 			break;
   858 			}
   859 		case RLocalDrive::EControlDeleteNotify:
   860 			{
   861 			m.Id()=EDeleteNotify;
   862 			r=m.ProcessMessageData(a1);
   863 			if (r==KErrNone)
   864 			    {
   865 			    OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_DELETENOTIFY, "EDeleteNotify; TLocDrvRequest Object=0x%x", (TUint) &m);
   866 				r=iDrive->Request(m);
   867 				OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_DELETENOTIFY_RETURN, "EDeleteNotify Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   868 			    }
   869 			break;
   870 			}
   871 
   872 		case RLocalDrive::EControlQueryDevice:
   873 			{
   874 			TBuf8<KMaxQueryDeviceLength> queryBuf;
   875 			queryBuf.SetMax();
   876 			queryBuf.FillZ();
   877 			
   878 			m.Id() = EQueryDevice;
   879 			m.iArg[0] = a1;		// RLocalDrive::TQueryDevice
   880 			m.RemoteDes() = (TAny*)queryBuf.Ptr();	// overload this
   881 			m.Length() = KMaxLocalDriveCapsLength;	// for pinning
   882 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE, "EQueryDevice; TLocDrvRequest Object=0x%x", (TUint) &m);
   883 			r=iDrive->Request(m);
   884 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE_RETURN, "EQueryDevice Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   885 			Kern::InfoCopy(*(TDes8*)a2, queryBuf);
   886 			break;
   887 			}
   888 
   889 		}
   890 	__KTRACE_OPT(KLOCDRV,Kern::Printf("<DLocalDrive::DoControl D:%d M:%08x ret %d",iDrive->iDriveNumber, iDrive->iMedia, r));
   891 	__TRACE_TIMING(4);
   892 	OstTraceFunctionExitExt( DLOCALDRIVE_REQUEST_EXIT, this, r );
   893 	return r;
   894 	}
   895 
   896 TInt DLocalDrive::ReadPasswordData(TLocDrvRequest& aReq, TLocalDrivePasswordData& aPswData, TMediaPassword& aOldPasswd, TMediaPassword& aNewPasswd)
   897 	{
   898 	TLocalDrivePasswordData clientData;
   899 	TInt r = aReq.ReadRemoteRaw(&clientData, sizeof(TLocalDrivePasswordData));
   900 
   901 	DThread* pT = aReq.RemoteThread();
   902 	if (!pT)
   903 		pT = aReq.Client();
   904 
   905 	if (r == KErrNone)
   906 		r = Kern::ThreadDesRead(pT, clientData.iOldPasswd, aOldPasswd, 0 ,KChunkShiftBy0);
   907 	if (r == KErrNone)
   908 		r = Kern::ThreadDesRead(pT, clientData.iNewPasswd, aNewPasswd, 0 ,KChunkShiftBy0);
   909 	
   910 	aPswData.iStorePasswd = clientData.iStorePasswd;
   911 	aPswData.iOldPasswd = &aOldPasswd;
   912 	aPswData.iNewPasswd = &aNewPasswd;
   913 
   914 
   915 	aReq.RemoteDes() = (TAny*) &aPswData;
   916 	aReq.Flags()|= TLocDrvRequest::EKernelBuffer;
   917 
   918 	return r;
   919 	}
   920 
   921 
   922 #ifdef __DEMAND_PAGING__
   923 TInt DLocalDrive::LockMountInfo(DPrimaryMediaBase& aPrimaryMedia, TLocDrvRequest& aReq)
   924 	{
   925 	OstTraceExt2(TRACE_FLOW, DLOCALDRIVE_LOCKMOUNTINFO_ENTRY, "> aPrimaryMedia=%x;aReq=%x", (TUint) &aPrimaryMedia, (TUint) &aReq );
   926 	DMediaPagingDevice* pagingDevice = aPrimaryMedia.iBody->iPagingDevice;
   927 	if (pagingDevice == NULL)
   928 	    {
   929 		OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT1, this, KErrNone );
   930 		return KErrNone;
   931 	    }
   932 
   933 	__ASSERT_DEBUG(pagingDevice->iMountInfoDataLock == NULL, LOCM_FAULT());
   934 	__ASSERT_DEBUG(pagingDevice->iMountInfoDescHdrLock == NULL, LOCM_FAULT());
   935 	__ASSERT_DEBUG(pagingDevice->iMountInfoDescLenLock == NULL, LOCM_FAULT());
   936 
   937 	DThread* pT = aReq.RemoteThread();
   938 	if (!pT)
   939 		pT = &Kern::CurrentThread();	// e.g. when using TBusLocalDrive directly
   940 
   941 	TInt length = 0;
   942 	TInt maxLength = 0;
   943 	TUint8* desAddress = NULL;
   944 	TInt r = Kern::ThreadGetDesInfo(pT,aReq.RemoteDes(),length,maxLength,desAddress,EFalse);	// get descriptor length, maxlength and desAddress
   945 	if (r != KErrNone)
   946 	    {
   947 		OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT2, this, r );
   948 		return r;
   949 	    }
   950 	if (length == 0)
   951 	    {
   952 		OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT3, this, KErrNone );
   953 		return KErrNone;
   954 	    }
   955 
   956 
   957 	static const TUint8 LengthLookup[16]={4,8,12,8,12,0,0,0,0,0,0,0,0,0,0,0};
   958 	TUint32 desHdr;
   959 	r = Kern::ThreadRawRead(pT, aReq.RemoteDes(), &desHdr, sizeof(desHdr));
   960 	if(r!=KErrNone)
   961 	    {
   962 		OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT4, this, r );
   963 		return r;
   964 	    }
   965 	TInt desType = desHdr >>KShiftDesType8;
   966 	TInt desHdrLen = LengthLookup[desType];
   967 	if(!desHdrLen)
   968 	    {
   969 		OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT5, this, KErrBadDescriptor );
   970 		return KErrBadDescriptor;
   971 	    }
   972 
   973 
   974 	pagingDevice->iMountInfoDataLock = ThePinObjectAllocator->AcquirePinObject();
   975 	pagingDevice->iMountInfoDescHdrLock = ThePinObjectAllocator->AcquirePinObject();
   976 	pagingDevice->iMountInfoDescLenLock = ThePinObjectAllocator->AcquirePinObject();
   977 
   978 	if (pagingDevice->iMountInfoDataLock == NULL || 
   979 		pagingDevice->iMountInfoDescHdrLock == NULL || 
   980 		pagingDevice->iMountInfoDescLenLock == NULL)
   981 		{
   982 		UnlockMountInfo(aPrimaryMedia);	// tidy up
   983 		OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT6, this, KErrNoMemory );
   984 		return KErrNoMemory;
   985 		}
   986 
   987 
   988 	// First pin the descriptor header 
   989 	DPinObjectAllocator::SVirtualPinContainer* lock;
   990 	lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock;
   991 	r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) (TUint8*) aReq.RemoteDes(), desHdrLen, pT);
   992 	if (r != KErrNone)
   993 		{
   994 		UnlockMountInfo(aPrimaryMedia);	// tidy up
   995 		OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT7, this, KErrNoMemory );
   996 		return KErrNoMemory;
   997 		}
   998 
   999 	
  1000 	
  1001 	// For EBufCPtr-type descriptors, need to pin the extra length before the buffer (!)
  1002 	lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock;
  1003 	if (desType == EBufCPtr)
  1004 		{
  1005 		TLinAddr extraLenAddr = TLinAddr(desAddress) - aReq.RemoteDesOffset() - sizeof(TUint32);
  1006 		r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) (TUint8*) extraLenAddr, sizeof(TUint32), pT);
  1007 		if (r != KErrNone)
  1008 			{
  1009 			UnlockMountInfo(aPrimaryMedia);	// tidy up
  1010 			OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT8, this, KErrNoMemory );
  1011 			return KErrNoMemory;
  1012 			}
  1013 		}
  1014 
  1015 
  1016 	// Now pin the descriptor contents
  1017 	lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock;
  1018 	r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) desAddress, length, pT);
  1019 	if (r != KErrNone)
  1020 		{
  1021 		UnlockMountInfo(aPrimaryMedia);	// tidy up
  1022 		OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT9, this, KErrNoMemory );
  1023 		return KErrNoMemory;
  1024 		}
  1025 
  1026 	OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT10, this, KErrNone );
  1027 	return KErrNone;
  1028 	}
  1029 
  1030 
  1031 void DLocalDrive::UnlockMountInfo(DPrimaryMediaBase& aPrimaryMedia)
  1032 	{
  1033 	OstTrace1(TRACE_FLOW, DLOCALDRIVE_UNLOCKMOUNTINFO_ENTRY, "> DLocalDrive::UnlockMountInfo;aPrimaryMedia=%x", (TUint) &aPrimaryMedia);
  1034 	
  1035 	DMediaPagingDevice* pagingDevice = aPrimaryMedia.iBody->iPagingDevice; 
  1036 	if (pagingDevice == NULL || pagingDevice->iMountInfoDataLock == NULL)
  1037 	    {
  1038 		OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT1, this );
  1039 		return;
  1040 	    }
  1041 
  1042 
  1043 	if (pagingDevice->iMountInfoDataLock)
  1044 		{
  1045 		Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock)->iObject);
  1046 		ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock);
  1047 		pagingDevice->iMountInfoDataLock = NULL;
  1048 		}
  1049 	
  1050 	if (pagingDevice->iMountInfoDescHdrLock)
  1051 		{
  1052 		Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock)->iObject);
  1053 		ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock);
  1054 		pagingDevice->iMountInfoDescHdrLock = NULL;
  1055 		}
  1056 	
  1057 	if (pagingDevice->iMountInfoDescLenLock)
  1058 		{
  1059 		Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock)->iObject);
  1060 		ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock);
  1061 		pagingDevice->iMountInfoDescLenLock = NULL;
  1062 		}
  1063 	
  1064 	OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT2, this );
  1065 	}
  1066 #endif	// __DEMAND_PAGING__
  1067 
  1068 void DLocalDrive::NotifyChange(DPrimaryMediaBase& aPrimaryMedia, TBool aMediaChange)
  1069 	{
  1070     OstTraceExt2( TRACE_FLOW, DLOCALDRIVE_NOTIFYCHANGE_ENTRY, "> DLocalDrive::NotifyChange;aPrimaryMedia=%x;aMediaChange=%d", (TUint) &aPrimaryMedia, aMediaChange );
  1071 #ifndef __DEMAND_PAGING__
  1072 	aPrimaryMedia;
  1073 #endif
  1074 
  1075 	// Complete any notification request on media change or power down
  1076 	if (aMediaChange)
  1077 		{
  1078 		DThread* pC=NULL;
  1079 		NKern::LockSystem();
  1080 		if (iCleanup.iThread)
  1081 			{
  1082 			pC=iCleanup.iThread;
  1083 			pC->Open();
  1084 			}
  1085 		NKern::UnlockSystem();
  1086 		if (pC)
  1087 			{
  1088 			TBool b = ETrue;
  1089 			// if change not yet queued, queue it now
  1090 			if (iNotifyChangeRequest->IsReady())
  1091 				{
  1092 				*((TBool*) iNotifyChangeRequest->Buffer()) = b;
  1093 				Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrNone);
  1094 				}
  1095 			// If change has not even been requested by the client, maintain the pre-wdp behaviour 
  1096 			// and write data immediately back to client (possibly taking a page fault)
  1097 			// N.B. Must NOT do this on data paging media
  1098 #ifdef __DEMAND_PAGING__
  1099 			else if (!DataPagingDfcQ(&aPrimaryMedia))
  1100 #else
  1101 			else
  1102 #endif
  1103 				{
  1104 				Kern::ThreadRawWrite(pC, iNotifyChangeRequest->DestPtr(), &b, sizeof(b), NULL);
  1105 				}
  1106 			pC->AsyncClose();
  1107 			}
  1108 		}
  1109 	OstTraceFunctionExit1( DLOCALDRIVE_NOTIFYCHANGE_EXIT, this );
  1110 	}
  1111 
  1112 TLocalDriveCleanup::TLocalDriveCleanup()
  1113 	{
  1114 	}
  1115 
  1116 // This will be called when the original client thread exits
  1117 // It is called in the context of the exiting thread with the system locked.
  1118 void TLocalDriveCleanup::Cleanup()
  1119 	{
  1120 	DLocalDrive& d=LocalDrive();
  1121 	d.iNotifyChangeRequest=NULL;
  1122 	DThread* pC=iThread;
  1123 	Remove();
  1124 	iThread=NULL;
  1125 	NKern::UnlockSystem();
  1126 	pC->Close(NULL);	// balances Open() in DoCreate
  1127 	NKern::LockSystem();
  1128 	}
  1129 
  1130 /********************************************
  1131  * Local drive request class
  1132  ********************************************/
  1133  
  1134 /**
  1135 Reads data from the descriptor specified in the request, from the requesting
  1136 thread's process.
  1137 
  1138 This is used by the media driver to read data from a descriptor in the
  1139 requesting thread.  The remote data is copied into the specified descriptor,
  1140 starting at the specified offset within that descriptor's data area.
  1141 
  1142 @param aDes     The target descriptor into which data from the remote thread
  1143                 is to be put.
  1144 @param anOffset The offset within the target descriptor data area, where data
  1145                 from the remote thread is to be put. Note that this parameter
  1146                 may be useful when write operations to the media must be broken
  1147                 up into smaller chunks than the length requested.
  1148 
  1149 @return KErrNone,if successful, otherwise one of the other
  1150         system-wide error codes.
  1151 
  1152 @see Kern::ThreadDesRead()
  1153 */
  1154 EXPORT_C TInt TLocDrvRequest::ReadRemote(TDes8* aDes, TInt anOffset)
  1155 	{
  1156 	OstTraceFunctionEntry1( TLOCDRVREQUEST_READREMOTE_ENTRY, this );
  1157 	TInt r;
  1158 	DThread* pT=RemoteThread();
  1159 	if (!pT)
  1160 		pT=Client();
  1161 
  1162 #ifdef __DEMAND_PAGING__	// only if driver has its own thread, we don't support paging in MD which run in the context of their clients
  1163 	if (Flags() & ETClientBuffer)
  1164 	    {
  1165         r = Kern::ThreadBufRead(pT, (TClientBuffer*) RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0);
  1166 		OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTE_EXIT1, this, r );
  1167 		return r; 
  1168 	    }
  1169 	
  1170 	__ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT());
  1171 #endif
  1172 	r = Kern::ThreadDesRead(pT,RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0);
  1173 	OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTE_EXIT2, this, r );
  1174 	return r;
  1175 	}
  1176 
  1177 
  1178 
  1179 
  1180 /**
  1181 Reads data from an arbitrary descriptor in the requesting thread's process.
  1182 
  1183 This is used by the media driver to read data from a descriptor in the
  1184 requesting thread.  
  1185 
  1186 NB This is NOT supported on datapaging media as there is no guarantee 
  1187 that the remote descriptor won't be paged out. If this function is called and
  1188 data-paging is enabled the kernel will fault in debug mode and return 
  1189 KErrNotSupported in release mode.
  1190 
  1191 @param aSrc     A pointer to the source descriptor in the requesting thread's
  1192                 address space.
  1193 @param aDes     The target descriptor into which data from the remote thread
  1194                 is to be put.
  1195 
  1196 @return KErrNone,if successful, 
  1197 		KErrNotSupported if data-paging is enabled
  1198 		otherwise one of the other  system-wide error codes.
  1199 
  1200 @see Kern::ThreadDesRead()
  1201 */
  1202 EXPORT_C TInt TLocDrvRequest::ReadRemote(const TAny* aSrc, TDes8* aDes)
  1203 	{
  1204 	OstTraceFunctionEntry1( TLOCDRVREQUEST_READ_REMOTE_ENTRY, this );
  1205 	if (Flags() & TLocDrvRequest::EKernelBuffer)
  1206 		{
  1207 		aDes->Copy(* (TDesC8*) aSrc);
  1208 		return KErrNone;
  1209 		}
  1210 
  1211 	TInt r;
  1212 	DThread* pT=RemoteThread();
  1213 	if (!pT)
  1214 		pT=Client();
  1215 
  1216 #ifdef __DEMAND_PAGING__
  1217 	__ASSERT_DEBUG(!DataPagingDfcQ(Drive()->iPrimaryMedia), LOCM_FAULT());
  1218 
  1219 	if (DataPagingDfcQ(Drive()->iPrimaryMedia))
  1220 		{
  1221 		OstTraceFunctionExitExt( TLOCDRVREQUEST_READ_REMOTE_EXIT1, this, KErrNotSupported );
  1222 		return KErrNotSupported;
  1223 	    }
  1224 #endif
  1225 	
  1226 	r = Kern::ThreadDesRead(pT,aSrc,*aDes,0,KChunkShiftBy0);
  1227 	OstTraceFunctionExitExt( TLOCDRVREQUEST_READ_REMOTE_EXIT2, this, r );
  1228 	return r;
  1229 	}
  1230 
  1231 
  1232 
  1233 
  1234 /**
  1235 Reads raw data from the requesting thread's process.
  1236 
  1237 This is used by the media driver to read raw data from a location in requesting
  1238 thread's address space.  The remote data is copied into the specified
  1239 buffer.
  1240 
  1241 @param aDest    A pointer to the buffer where the data is to be written.
  1242 @param aSize    The number of bytes to read.
  1243 
  1244 @return KErrNone,if successful, otherwise one of the other
  1245         system-wide error codes.
  1246 
  1247 @see Kern::ThreadRawRead()
  1248 */
  1249 EXPORT_C TInt TLocDrvRequest::ReadRemoteRaw(TAny* aDest, TInt aSize)
  1250 	{
  1251 	OstTraceFunctionEntry1( TLOCDRVREQUEST_READREMOTERAW_ENTRY, this );
  1252 	if (Flags() & TLocDrvRequest::EKernelBuffer)
  1253 		{
  1254 		(void)memcpy(aDest, (TAny*) RemoteDes(), aSize);
  1255 		return KErrNone;
  1256 		}
  1257 
  1258 	TInt r;
  1259 	DThread* pT=RemoteThread();
  1260 	if (!pT)
  1261 		pT=Client();
  1262 
  1263 #ifdef __DEMAND_PAGING__
  1264 	__ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT());
  1265 #endif
  1266 	
  1267 	r = Kern::ThreadRawRead(pT,RemoteDes(),aDest,aSize);
  1268 	OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTERAW_EXIT, this, r );
  1269 	return r;
  1270 	}
  1271 
  1272 
  1273 /**
  1274 Writes data to a descriptor in the requesting thread's process.
  1275 
  1276 This is used by the media driver to write data to a descriptor in the requesting
  1277 thread.  Data is copied from the specified descriptor, starting at the specified
  1278 offset within that descriptor's data area.
  1279 
  1280 @param aDes     The source descriptor from which data is to be written to
  1281                 the remote thread.
  1282                 
  1283 @param anOffset The offset within the source descriptor data area, from where data
  1284                 is to be written to the remote thread. Note that this parameter
  1285                 may be useful when read operations from the media must be broken
  1286                 up into smaller chunks than the length requested.
  1287 
  1288 @return KErrNone,if successful, otherwise one of the other
  1289         system-wide error codes.
  1290 
  1291 @see Kern::ThreadDesWrite()
  1292 */
  1293 EXPORT_C TInt TLocDrvRequest::WriteRemote(const TDesC8* aDes, TInt anOffset)
  1294 	{
  1295     OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITEREMOTE_ENTRY, this );
  1296     TInt r;
  1297 	DThread* pC=Client();
  1298 	DThread* pT=RemoteThread();
  1299 	if (!pT)
  1300 		pT=pC;
  1301 
  1302 #ifdef __DEMAND_PAGING__
  1303 	if (Flags() & ETClientBuffer)
  1304 	    {
  1305         r = Kern::ThreadBufWrite(pT, (TClientBuffer*) RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC);
  1306 		OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT1, this, r );
  1307 		return r;
  1308 	    }
  1309 #endif
  1310 	r = Kern::ThreadDesWrite(pT,RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC);
  1311 	OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT2, this, r );
  1312 	return r;
  1313 	}
  1314 
  1315 
  1316 /**
  1317 Writes raw data to the requesting thread's process.
  1318 
  1319 This is used by the media driver to write raw data to a location in the
  1320 requesting thread's address space.
  1321 
  1322 @param aSrc     The source addres from which data is to be written to
  1323                 the remote thread.
  1324                 
  1325 @param aSize    The number of bytes to write.
  1326 
  1327 @return KErrNone,if successful, otherwise one of the other
  1328         system-wide error codes.
  1329 
  1330 @see Kern::ThreadRawWrite()
  1331 */
  1332 EXPORT_C TInt TLocDrvRequest::WriteRemoteRaw(const TAny* aSrc, TInt aSize)
  1333 	{
  1334     OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITEREMOTERAW_ENTRY, this );
  1335     TInt r;
  1336 	DThread* pC=Client();
  1337 	DThread* pT=RemoteThread();
  1338 	if (!pT)
  1339 		pT=pC;
  1340 
  1341 #ifdef __DEMAND_PAGING__
  1342 	__ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT());
  1343 #endif
  1344 	r = Kern::ThreadRawWrite(pT,RemoteDes(),aSrc,aSize,pC);
  1345 	OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTERAW_EXIT, this, r );
  1346 	return r;
  1347 	}
  1348 
  1349 
  1350 TInt TLocDrvRequest::ProcessMessageData(TAny* aPtr)
  1351 //
  1352 // Get read/write parameters from client and open remote thread
  1353 //
  1354 	{
  1355 	OstTraceFunctionEntry1( TLOCDRVREQUEST_PROCESSMESSAGEDATA_ENTRY, this );
  1356 	RemoteThread()=NULL;
  1357 	DThread& t=Kern::CurrentThread();
  1358 	TLocalDriveMessageData d;
  1359 	kumemget32(&d,aPtr,sizeof(d));
  1360 	OstTrace1( TRACE_INTERNALS, TLOCDRVREQUEST_PROCESSMESSAGEDATA, "Message handle=%d", d.iHandle );
  1361 	if (d.iHandle!=KLocalMessageHandle && Id()!=DLocalDrive::EFormat)
  1362 		{
  1363 		NKern::LockSystem();
  1364 		DThread* pT = RMessageK::MessageK(d.iHandle)->iClient;
  1365 		if (!pT || pT->Open()!=KErrNone)
  1366 			{
  1367 			NKern::UnlockSystem();
  1368 			OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT1, this, KErrBadHandle );
  1369 			return KErrBadHandle;
  1370 			}
  1371 		t.iExtTempObj=pT;
  1372 		RemoteThread()=pT;
  1373 		NKern::UnlockSystem();
  1374 		}
  1375 	Pos()=d.iPos;
  1376 	Length()=d.iLength;
  1377 	RemoteDes()=(TAny*)d.iPtr;
  1378 	RemoteDesOffset()=d.iOffset;
  1379 	DriverFlags()=d.iFlags;
  1380 	if (Pos()<0 || Length()<0)
  1381 	    {
  1382 		OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT2, this, KErrArgument );
  1383 		return KErrArgument;
  1384 	    }
  1385 	OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT3, this, KErrNone );
  1386 	return KErrNone;
  1387 	}
  1388 
  1389 void TLocDrvRequest::CloseRemoteThread()
  1390 	{
  1391     OstTraceFunctionEntry1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_ENTRY, this );
  1392     
  1393 	if (!RemoteThread())
  1394 	    {
  1395 		OstTraceFunctionExit1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_EXIT1, this );
  1396 		return;
  1397 	    }
  1398 	NKern::ThreadEnterCS();
  1399 	DThread& t=Kern::CurrentThread();
  1400 	RemoteThread()=NULL;
  1401 	Kern::SafeClose((DObject*&)t.iExtTempObj,NULL);
  1402 	NKern::ThreadLeaveCS();
  1403 	OstTraceFunctionExit1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_EXIT2, this );
  1404 	}
  1405 
  1406 EXPORT_C TInt TLocDrvRequest::CheckAndAdjustForPartition()
  1407 	{
  1408 	OstTraceFunctionEntry1( TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION_ENTRY, this );
  1409 	TLocDrv& d=*Drive();
  1410 	__KTRACE_OPT(KLOCDRV,Kern::Printf("CheckAndAdjustForPartition drive %d partition len %lx",d.iDriveNumber,d.iPartitionLen));
  1411 	OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION1, "iDriveNumber=%d; partition length=0x%lx", d.iDriveNumber, (TInt) d.iPartitionLen );
  1412 	Flags() |= EAdjusted;
  1413 	TInt r;
  1414 	switch (Id())
  1415 		{
  1416 		case DLocalDrive::ECaps:
  1417 		case DLocalDrive::EForceMediaChange:
  1418 		case DLocalDrive::EPasswordLock:
  1419 		case DLocalDrive::EPasswordUnlock:
  1420 		case DLocalDrive::EPasswordClear:
  1421 		case DLocalDrive::EPasswordErase:
  1422 		case DLocalDrive::EReadPasswordStore:
  1423  		case DLocalDrive::EWritePasswordStore:
  1424  		case DLocalDrive::EPasswordStoreLengthInBytes:
  1425 		case DLocalDrive::EQueryDevice:
  1426 		    {
  1427 			r = KErrNone;
  1428 			break;
  1429 		    }
  1430 		case DLocalDrive::EEnlarge:
  1431 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Enlarge request %lx",Length()));
  1432 			OstTrace1( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION2, "Enlarge request=0x%lx", Length() );
  1433 			if (Length()>KMaxTInt)
  1434 				r = KErrArgument;
  1435 			else
  1436 			    r = KErrNone;
  1437 			break;
  1438 		case DLocalDrive::EReduce:
  1439 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Reduce request %lx@%lx",Length(),Pos()));
  1440 			OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION3, "Reduce request length=0x%lx; position=0x%lx", (TUint) Length(), (TUint) Pos() );
  1441 			if (Pos()+Length()>d.iPartitionLen)
  1442 				r = KErrArgument;
  1443 			else
  1444                 r = KErrNone;
  1445 			break;
  1446 		case DLocalDrive::EFormat:
  1447 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Format request %lx@%lx",Length(),Pos()));
  1448 			OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION4, "Format request length=0x%lx; position=0x%lx", (TUint) Length(), (TUint) Pos() );
  1449 			if (!(DriverFlags() & RLocalDrive::ELocDrvWholeMedia))
  1450 				{
  1451 				if (Pos()>d.iPartitionLen)
  1452 					{
  1453 					Length()=0;
  1454 					r = KErrEof;
  1455 					break;
  1456 					}
  1457 				Int64 left=d.iPartitionLen-Pos();
  1458 				if (left<Length())
  1459 					Length()=left;
  1460 				Pos()+=d.iPartitionBaseAddr;
  1461 				if (Length()==0)
  1462 				    {
  1463 					r = KErrEof;
  1464 					break;
  1465 				    }
  1466 				}
  1467 			r = KErrNone;
  1468 			break;
  1469 
  1470 #ifdef __DEMAND_PAGING__
  1471 		case DMediaPagingDevice::ERomPageInRequest:
  1472 //          if the ROM was reported to LOCM then it will also need to be adjusted.... 
  1473 //		    Otherwise the media driver adjust it internally
  1474 		case DMediaPagingDevice::ECodePageInRequest:
  1475 			__KTRACE_OPT(KLOCDPAGING,Kern::Printf("Adjusted Paging read request %lx@%lx",Length(),Pos()));
  1476 			OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, TLOCDRVREQUESTCHECKANDADJUSTFORPARTITION5, "Adjusted Paging read request length=0x%lx; position=0x%lx", (TUint) Length(),  (TUint) Pos());
  1477 			if (Pos()+Length()>d.iPartitionLen)
  1478 			    {
  1479 				r = KErrArgument;
  1480 				break;
  1481 			    }
  1482 			Pos()+=d.iPartitionBaseAddr;
  1483 			r = KErrNone;
  1484 			break;
  1485 #endif
  1486 		
  1487 		default:	// read or write or fragment
  1488 			__KTRACE_OPT(KLOCDRV,Kern::Printf("R/W request %lx@%lx",Length(),Pos()));
  1489 			OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION6, "Read/Write request length=0x%x; position=0x%x", (TUint) Length(), (TUint) Pos() );
  1490 			if (DriverFlags() & RLocalDrive::ELocDrvWholeMedia)
  1491 				{
  1492 				if (d.iMedia && d.iMedia->iDriver && Pos()+Length() > d.iMedia->iDriver->iTotalSizeInBytes)
  1493 				    {
  1494 					r = KErrArgument;
  1495 					break;
  1496 				    }
  1497 				}
  1498 			else
  1499 				{
  1500 				if (Pos()+Length() > d.iPartitionLen)
  1501 				    {
  1502 					r = KErrArgument;
  1503 					break;
  1504 				    }
  1505 				Pos()+=d.iPartitionBaseAddr;
  1506 				}
  1507 		r = KErrNone;
  1508 		}
  1509 	OstTraceFunctionExitExt( TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION_EXIT, this, r );
  1510 	return r;
  1511 	}
  1512 
  1513 /********************************************
  1514  * Local drive class
  1515  ********************************************/
  1516 TLocDrv::TLocDrv(TInt aDriveNumber)
  1517 	{
  1518 	OstTraceFunctionEntryExt( TLOCDRV_TLOCDRV_ENTRY, this );
  1519 	memclr(this, sizeof(TLocDrv));
  1520 	iDriveNumber=aDriveNumber;
  1521 	iPartitionNumber=-1;
  1522 	OstTraceFunctionExit1( TLOCDRV_TLOCDRV_EXIT, this );
  1523 	}
  1524 
  1525 /**
  1526 Initialises the DMedia entity with the media device number and ID.
  1527  
  1528 @param	aDevice		The unique ID for this device. This can take one of the
  1529 					enumerated values defined in TMediaDevice enum.
  1530 
  1531 @param	aMediaId	The unique ID to associate with this media entity.
  1532 
  1533 @return KErrNone,if successful, otherwise one of the other
  1534         system-wide error codes.
  1535 
  1536 @see	TMediaDevice
  1537 */
  1538 EXPORT_C TInt DMedia::Create(TMediaDevice aDevice, TInt aMediaId, TInt)
  1539 	{
  1540 	OstTraceFunctionEntry1( DMEDIA_CREATE_ENTRY, this );
  1541 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DMedia::Create media %d device %d",aMediaId,aDevice));
  1542 	OstTraceExt2(TRACE_INTERNALS, DMEDIA_CREATE, "media=%d; device=%d", aMediaId, (TUint) aDevice);
  1543 	iMediaId=aMediaId;
  1544 	iDevice=aDevice;
  1545 	OstTraceFunctionExitExt( DMEDIA_CREATE_EXIT, this, KErrNone );
  1546 	return KErrNone;
  1547 	}
  1548 
  1549 /********************************************
  1550  * Primary Media Class
  1551  ********************************************/
  1552 void asyncDfc(TAny* aPtr)
  1553 	{
  1554 	OstTraceFunctionEntry0( _ASYNCDFC_ENTRY );
  1555 	DPrimaryMediaBase* pM=(DPrimaryMediaBase*)aPtr;
  1556 	if (pM->iState==DMedia::EOpening)
  1557 		pM->DoOpenMediaDriverComplete(pM->iAsyncErrorCode);
  1558 	else if (pM->iState==DMedia::EReadPartitionInfo)
  1559 		pM->DoPartitionInfoComplete(pM->iAsyncErrorCode);
  1560 	OstTraceFunctionExit0( _ASYNCDFC_EXIT );
  1561 	}
  1562 
  1563 void handleMsg(TAny* aPtr)
  1564 	{
  1565 	OstTraceFunctionEntry0( _HANDLEMSG_ENTRY );
  1566 	DPrimaryMediaBase* primaryMedia=(DPrimaryMediaBase*)aPtr;
  1567 
  1568 	for(TLocDrvRequest* m = (TLocDrvRequest*) primaryMedia->iMsgQ.iMessage; 
  1569 		m != NULL; 
  1570 		m = (TLocDrvRequest*) primaryMedia->iMsgQ.Poll())
  1571 		{
  1572 #if defined(_DEBUG)	
  1573 		if (!primaryMedia->iMsgQ.iQ.IsEmpty())	
  1574 			__KTRACE_OPT(KLOCDRV, Kern::Printf("TRACE: handleMsg, queue not empty %08X", m));	
  1575 #endif
  1576 		primaryMedia->HandleMsg(*m);
  1577 		
  1578 #ifdef __DEMAND_PAGING__
  1579 		// don't empty the queue if this media is paging as there 
  1580 		// may be a (higher-priority) paging DFC waiting to run...
  1581 		if (primaryMedia->iPagingMedia)
  1582 			break;
  1583 #endif
  1584 		}
  1585 
  1586 
  1587 	primaryMedia->iMsgQ.Receive();	// allow reception of more messages
  1588 	OstTraceFunctionExit0( _HANDLEMSG_EXIT );
  1589 	}
  1590 
  1591 EXPORT_C DPrimaryMediaBase::DPrimaryMediaBase()
  1592 	:	iMsgQ(handleMsg, this, NULL, 1),
  1593 		iDeferred(NULL, NULL, NULL, 0),			// callback never used
  1594 		iWaitMedChg(NULL, NULL, NULL, 0),		// callback never used
  1595 		iAsyncDfc(asyncDfc, this, 1)
  1596 /**
  1597 Constructor of DPrimaryMediaBase class.
  1598 Initialises the media state as closed.
  1599 */
  1600 	{
  1601 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DPRIMARYMEDIABASE_ENTRY, this );
  1602 	iState = EClosed;
  1603 	}
  1604 
  1605 
  1606 
  1607 EXPORT_C TInt DPrimaryMediaBase::Create(TMediaDevice aDevice, TInt aMediaId, TInt aLastMediaId)
  1608 /**
  1609 Called from LocDrv::RegisterMediaDevice() function.
  1610 Calls DMedia::Create()
  1611 
  1612 @param aDevice Local media ID 
  1613 @param aMediaId Media Id (unique for a media subsystem)
  1614 @param aLastMediaId This indicates number of used media ids+ number of DMedia objects to be associated with the media driver.
  1615 
  1616 @return KErrNone
  1617 @see TMediaDevice 
  1618 
  1619 */
  1620 	{
  1621 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_CREATE_ENTRY, this );
  1622 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase::Create media %d-%d device %d",aMediaId,aLastMediaId,aDevice));
  1623 	OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_CREATE, "aMediaId=%d; aLastMediaId=%d; aDevice=%d ", aMediaId, aLastMediaId, (TUint) aDevice );
  1624 	TInt r=DMedia::Create(aDevice,aMediaId,0);
  1625 	
  1626 	if (r != KErrNone)
  1627 	    {
  1628 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT1, this, r );
  1629 		return r;
  1630 	    }
  1631 	iBody = new DBody;
  1632 	if (iBody == NULL)
  1633 	    {
  1634 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT2, this, KErrNoMemory );
  1635 		return KErrNoMemory;
  1636 	    }
  1637 	
  1638 	
  1639 
  1640 #ifdef __DEMAND_PAGING__
  1641 	TInt pageSize = Kern::RoundToPageSize(1);
  1642 	iBody->iPageSizeMsk = pageSize-1;
  1643 #endif
  1644 
  1645 	iLastMediaId=aLastMediaId;
  1646 	if (r==KErrNone && iDfcQ)
  1647 		{
  1648 		iMsgQ.SetDfcQ(iDfcQ);
  1649 		iDeferred.SetDfcQ(iDfcQ);
  1650 		iWaitMedChg.SetDfcQ(iDfcQ);
  1651 		iAsyncDfc.SetDfcQ(iDfcQ);
  1652 		}
  1653 	OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT3, this, KErrNone );
  1654 	return KErrNone;
  1655 	}
  1656 
  1657 
  1658 EXPORT_C TInt DPrimaryMediaBase::Connect(DLocalDrive* aLocalDrive)
  1659 /**
  1660 Connects to a local drive
  1661 
  1662 @param aLocalDrive Local drive logical channel abstraction
  1663 
  1664 @pre Kernel must be unlocked
  1665 @pre Current thread in critical section
  1666 
  1667 @post Kernel must be unlocked
  1668 
  1669 @return KErrNone, if successful
  1670 		KErrNotFound, If no PDD matches criteria while getting driver list
  1671 		KErrNoMemory, If the array could not be expanded at some point while getting driver list or ran out of memory while opening media driver
  1672 		KErrNotReady, If not ready when trying to open media driver
  1673 		otherwise, one of the other system wide error codes.
  1674 
  1675 @see DLocalDrive
  1676 */
  1677 	{
  1678 	OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_CONNECT_ENTRY, this );
  1679 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Connect %O",iMediaId,aLocalDrive));
  1680 	OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CONNECT, "iMediaId=%d; iDriveNumber=%d", iMediaId, aLocalDrive->iDrive->iDriveNumber );
  1681 	
  1682 	TInt r=KErrNone;
  1683 	
  1684 	if (iDfcQ)
  1685 		{
  1686 		TThreadMessage& m=Kern::Message();
  1687 		m.iValue=EConnect;
  1688 		m.iArg[0]=aLocalDrive;
  1689 		r=m.SendReceive(&iMsgQ);
  1690 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CONNECT_EXIT1, this, r );
  1691 		return r;
  1692 		}
  1693 
  1694 	// If no DFC queue, must be a fixed media device
  1695 	// If this is the first connection, open media driver now
  1696 	// Assume no non-primary media exist on this device
  1697 	
  1698 	NKern::LockSystem();
  1699 	TBool first=iConnectionQ.IsEmpty();
  1700 	iConnectionQ.Add(&aLocalDrive->iLink);
  1701 	NKern::UnlockSystem();
  1702 	if (first)
  1703 		{
  1704 		r=OpenMediaDriver();
  1705 		if (r!=KErrNone)
  1706 			{
  1707 			NKern::LockSystem();
  1708 			aLocalDrive->Deque();
  1709 			NKern::UnlockSystem();
  1710 			}
  1711 		}
  1712 	
  1713 	if (r==KErrNone)
  1714 		aLocalDrive->iDrive->iMedia=this;
  1715 	OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CONNECT_EXIT2, this, r );
  1716 	return r;
  1717 	}
  1718 
  1719 
  1720 
  1721 
  1722 EXPORT_C void DPrimaryMediaBase::Disconnect(DLocalDrive* aLocalDrive)
  1723 /**
  1724 Disconnects from a local drive
  1725 
  1726 @param aLocalDrive Local drive logical channel abstraction
  1727 
  1728 @pre Kernel must be unlocked
  1729 @pre Current thread in critical section
  1730 
  1731 @post Kernel must be unlocked
  1732 @see DLocalDrive
  1733 */
  1734 
  1735 	{
  1736 	OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_DISCONNECT_ENTRY, this );
  1737 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Disconnect %O",iMediaId,aLocalDrive));
  1738 	OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_DISCONNECT, "iMediaId=%d; iDriveNumber=%d", iMediaId, aLocalDrive->iDrive->iDriveNumber );
  1739 	
  1740 	if (iDfcQ)
  1741 		{
  1742 		TThreadMessage& m=Kern::Message();
  1743 		m.iValue=EDisconnect;
  1744 		m.iArg[0]=aLocalDrive;
  1745 		m.SendReceive(&iMsgQ);
  1746 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_DISCONNECT_EXIT1, this );
  1747 		return;
  1748 		}
  1749 
  1750 	// If no DFC queue, must be a fixed media device
  1751 	// If this is the last connection, close media driver now
  1752 	// Assume no non-primary media exist on this device
  1753 	DMediaDriver* pD=NULL;
  1754 	NKern::LockSystem();
  1755 	aLocalDrive->iDrive->iMedia=NULL;
  1756 	aLocalDrive->Deque();
  1757 	if (iConnectionQ.IsEmpty())
  1758 		{
  1759 		pD=iDriver;
  1760 		iDriver=NULL;
  1761 		}
  1762 	NKern::UnlockSystem();
  1763 	if (pD)
  1764 		pD->Close();
  1765 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_DISCONNECT_EXIT2, this );
  1766 	}
  1767 
  1768 EXPORT_C TInt DPrimaryMediaBase::Request(TLocDrvRequest& aReq)
  1769 /**
  1770 Issues a local drive request. It is called from TLocDrv::Request() function .
  1771 Each local drive request is encapsulated as a TLocDrvRequest- a class derived from TThreadMessage, the kernel message class. 
  1772 TLocDrvRequest contains information pertaining to the request, including the ID and any associated parameters such as drive position, length and source/destination location.
  1773 Passes the request through to the media driver.
  1774 
  1775 @param m Encapsulates the request information received from the client
  1776 
  1777 @pre Enter with kernel unlocked
  1778 
  1779 @post Leave with Kernel unlocked
  1780 
  1781 @return KErrNone,if successful
  1782 	KErrBadDescriptor, if request encapsulates a bad descriptor
  1783 	Otherwise, one of the other system wide error codes.
  1784 
  1785 @see TLocDrvRequest
  1786 */
  1787 	{
  1788 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_REQUEST_ENTRY, this );
  1789 
  1790 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Request(%08x)",iMediaId,&aReq));
  1791 	__KTRACE_OPT(KLOCDRV,Kern::Printf("this=%x, ReqId=%d, Pos=%lx, Len=%lx, remote thread %O",this,aReq.Id(),aReq.Pos(),aReq.Length(),aReq.RemoteThread()));
  1792 
  1793 	OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_REQUEST, "reqId=%d; length=0x%lx; position=0x%lx; remote thread=0x%x", (TInt) aReq.Id(), (TUint) aReq.Length(),  (TUint) aReq.Pos(), (TUint) aReq.RemoteThread());
  1794 	
  1795 	TInt reqId = aReq.Id();
  1796 
  1797 	if (reqId == DLocalDrive::ECaps)
  1798 		DefaultDriveCaps(*(TLocalDriveCapsV2*)aReq.RemoteDes());	// fill in stuff we know even if no media present
  1799 
  1800 	TInt r = QuickCheckStatus();
  1801 	if (r != KErrNone && aReq.Id()!=DLocalDrive::EForceMediaChange &&			// EForceMediaChange, and 
  1802  			 			 aReq.Id()!=DLocalDrive::EReadPasswordStore &&			// Password store operations 
  1803  						 aReq.Id()!=DLocalDrive::EWritePasswordStore &&			// do not require the media 
  1804  						 aReq.Id()!=DLocalDrive::EPasswordStoreLengthInBytes)	// to be ready.)
  1805  	 	{
  1806 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT, this, r );
  1807 		return r;
  1808  	  	}
  1809  	  	
  1810 
  1811 	// for ERead & EWrite requests, get the linear address for pinning & DMA
  1812 	TUint8* linAddress = NULL;
  1813 	TClientBuffer clientBuffer;
  1814 	DThread* pT = NULL;
  1815 
  1816 	if (reqId == DLocalDrive::ERead || reqId == DLocalDrive::EWrite)
  1817 		{
  1818 		pT = aReq.RemoteThread();
  1819 		if (!pT)
  1820 			pT = &Kern::CurrentThread();	// e.g. when using TBusLocalDrive directly
  1821 
  1822 		// for silly zero-length requests, return immediately, setting the client 
  1823 		// descriptor length to zero if it's a read request
  1824 		if (aReq.Length() == 0)
  1825 			{
  1826 			DThread* pC = &Kern::CurrentThread();
  1827 			r = KErrNone;
  1828 			if (reqId == DLocalDrive::ERead)
  1829 				{
  1830 				TPtrC8 ptr(NULL, 0);
  1831 				r = Kern::ThreadDesWrite(pT, aReq.RemoteDes(), ptr, aReq.RemoteDesOffset(), KChunkShiftBy0,pC);
  1832 				}
  1833 			OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT2, this, r );
  1834 			return r;
  1835 			}
  1836 
  1837 		clientBuffer.SetFromDescriptor(aReq.RemoteDes(), pT);
  1838 
  1839 		TInt length = 0;
  1840 		TInt maxLength = 0;
  1841 		TInt r = Kern::ThreadGetDesInfo(pT,aReq.RemoteDes(),length,maxLength,linAddress,EFalse);	// get descriptor length, maxlength and linAddress
  1842 		if (r != KErrNone)
  1843 		    {
  1844 			OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT3, this, r );
  1845 			return r;
  1846 		    }
  1847 		linAddress+= aReq.RemoteDesOffset();
  1848 
  1849 #ifdef __DEMAND_PAGING__
  1850 		// NB change in behavior IF DATA PAGING IS ENABLED: TLocDrvRequest::RemoteDes() points 
  1851 		// to a TClientBuffer rather than the client's remote descriptor
  1852 		if (DataPagingDeviceRegistered)
  1853 			{
  1854 			aReq.RemoteDes() = &clientBuffer;
  1855 			aReq.Flags() |= TLocDrvRequest::ETClientBuffer;
  1856 			}
  1857 #endif
  1858 		}
  1859 
  1860 	if (iDfcQ)
  1861 		{
  1862 		__TRACE_TIMING(0x10);
  1863 
  1864 
  1865 #ifdef __DEMAND_PAGING__
  1866 		// If this is a ROM/Code paging media, pin writes 
  1867 		// If there is a Data paging media registered, pin all requests with descriptors 
  1868 		if ( (DataPagingDeviceRegistered) || (reqId == DLocalDrive::EWrite && RomPagingDfcQ(this)) )
  1869 		    {	    
  1870 			r = PinSendReceive(aReq, (TLinAddr) linAddress);
  1871 		    }
  1872 		else
  1873 #endif	// __DEMAND_PAGING__
  1874 			r = SendReceive(aReq, (TLinAddr) linAddress);
  1875 		}
  1876 	else
  1877 		{
  1878 		// If no DFC queue, must be a fixed media device
  1879 		// Media driver must already have been opened
  1880 		// Assume no non-primary media exist on this device
  1881 		// Just pass request straight through to media driver
  1882 		r = aReq.CheckAndAdjustForPartition();
  1883 		if (r == KErrNone)
  1884 			r = iDriver->Request(aReq);		
  1885 		}
  1886 
  1887 #ifdef __DEMAND_PAGING__
  1888 		// NB change in behavior IF DATA PAGING IS ENABLED: TLocDrvRequest::RemoteDes() points 
  1889 		// to a TClientBuffer rather than the client's remote descriptor
  1890 	if (reqId == DLocalDrive::ERead && DataPagingDeviceRegistered && r == KErrNone)
  1891 		{
  1892 		r = clientBuffer.UpdateDescriptorLength(pT);
  1893 		}
  1894 #endif
  1895 	OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT4, this, r );
  1896 	return r;
  1897 	}
  1898 
  1899 
  1900 #ifdef __DEMAND_PAGING__
  1901 TInt DPrimaryMediaBase::PinSendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress)
  1902 	{
  1903     OstTraceExt2(TRACE_FLOW, DPRIMARYMEDIABASE_PINSENDRECEIVE_ENTRY, "> DPrimaryMediaBase::PinSendReceive;aReq=%x;aLinAddress=%x;", (TUint) &aReq, (TUint) &aLinAddress );
  1904 
  1905 	__ASSERT_DEBUG(ThePinObjectAllocator, LOCM_FAULT());
  1906 
  1907 
  1908 	TInt msgId = aReq.Id();
  1909 	TInt r;
  1910 
  1911 	switch(msgId)
  1912 		{
  1913 		case DLocalDrive::EControlIO:
  1914 			{
  1915 			TInt controlIoType = aReq.Int3(); 
  1916 			switch(controlIoType)
  1917 				{
  1918 				case KLocalMessageHandle:
  1919 					// ControlIo is not supported if either of the two bare (TAny*) pointers are non-NULL 
  1920 					// as it's not possible to determine what the pointers are pointing at...
  1921 					if (aReq.Int1() || aReq.Int2())
  1922 						{
  1923 						__KTRACE_OPT(KDATAPAGEWARN, Kern::Printf("Data paging: Naked EControlIO not supported on paging device: fn=%x", aReq.Int0()));
  1924 						r = KErrNotSupported;
  1925 						break;
  1926 						}
  1927 					// fall into...
  1928 				case 0:
  1929 					r = SendReceive(aReq);
  1930 					break;
  1931 
  1932 				default:
  1933 					// if Int3() is > 0, Int1() is a data pointer, and Int3() is a length
  1934 					if (controlIoType > (TInt) ThePinObjectAllocator->iFragmentGranularity)
  1935 					    {
  1936 						r = KErrTooBig;
  1937 						break;
  1938 					    }
  1939 					if (controlIoType < 0)
  1940 					    {
  1941 						r = KErrArgument;
  1942 						break;
  1943 					    }
  1944 					r = PinFragmentSendReceive(aReq, (TLinAddr) aReq.Ptr1(), controlIoType);
  1945 					break;
  1946 				}
  1947 			break;
  1948 			}
  1949 
  1950 		case DLocalDrive::ERead:
  1951 		case DLocalDrive::EWrite:
  1952 			{
  1953 			r = PinFragmentSendReceive(aReq, aLinAddress, aReq.Length());
  1954 			break;
  1955 			}
  1956 		
  1957 		// For all these requests, aReq.RemoteDes() points to a buffer on the stack in DLocalDrive::Request()
  1958 		// This is a kernel stack & so should be unpaged & not require pinning...
  1959 		case DLocalDrive::ECaps:
  1960 		case DLocalDrive::EGetLastErrorInfo:
  1961 		case DLocalDrive::EQueryDevice:
  1962 		case DLocalDrive::EPasswordLock:
  1963 		case DLocalDrive::EPasswordUnlock:
  1964 		case DLocalDrive::EPasswordClear:
  1965 		case DLocalDrive::EReadPasswordStore:
  1966 		case DLocalDrive::EWritePasswordStore:
  1967 		case DLocalDrive::EPasswordStoreLengthInBytes:
  1968 		case DLocalDrive::EPasswordErase:
  1969 
  1970 		default:		
  1971 			r = SendReceive(aReq);
  1972 		}
  1973 	OstTraceFunctionExitExt( DPRIMARYMEDIABASE_PINSENDRECEIVE_EXIT, this, r );
  1974 	return r;
  1975 	}
  1976 
  1977 TInt DPrimaryMediaBase::PinFragmentSendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress, TInt aLength)
  1978 	{
  1979 	OstTraceExt3(TRACE_FLOW, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE_ENTRY, "> DPrimaryMediaBase::PinFragmentSendReceive;aReq=%x;aLinAddress=%x;aLength=%d;", (TUint) &aReq, (TUint) &aLinAddress, aLength );
  1980 	
  1981 	TLocDrvRequest fragment = aReq;		// create a request on the stack for use during fragmentation, pre-fill with the original req args, leave original Kernel message as repository (thread will block, message contents won't change)
  1982 	TInt r = KErrNone;
  1983 
  1984 //	Kern::Printf(">PFSR %02X aReq %08X aLinAddress %08X aLen %08X offset %08X", aReq.Id(), &aReq, aLinAddress, aLength, aReq.RemoteDesOffset());
  1985 
  1986 	DThread* pT = aReq.RemoteThread();
  1987 	if (!pT)
  1988 		pT=&Kern::CurrentThread();	// e.g. when using TBusLocalDrive directly
  1989 
  1990 	__KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Fragmenting Read/Write Request(0x%08x) on drive(%d), remote des(0x%x), offset into des(0x%x), original req Length(0x%x)",&aReq,aReq.Drive()->iDriveNumber,(TInt)(aReq.RemoteDes()),aReq.RemoteDesOffset(),aLength));
  1991 	__KTRACE_OPT(KLOCDPAGING,Kern::Printf("Remote thread(0x%08x), current thread(0x%08x), start of data to write(0x%08x)",aReq.RemoteThread(),&Kern::CurrentThread(),(TInt)aLinAddress));
  1992 	OstTraceDefExt5(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE1, "Fragmenting Read/Write Request=0x%08x; drive=%d; remote des=0x%x; offset into des=0x%x; original length=0x%x", (TUint) &aReq, (TUint) aReq.Drive()->iDriveNumber, (TInt) (aReq.RemoteDes()), (TInt) aReq.RemoteDesOffset(), (TInt) aLength );
  1993 	OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE2, "Remote Thread=0x%08x; current Thread=0x%x; start of data to write=0x%08x", (TUint) aReq.RemoteThread(), (TUint) &Kern::CurrentThread(),(TUint)aLinAddress );
  1994 	
  1995 	// don't want this thread to be terminated until last fragment is sent to MD and mem can be free'd up
  1996 	NKern::ThreadEnterCS();			
  1997 
  1998 	__ASSERT_DEBUG(ThePinObjectAllocator, LOCM_FAULT());
  1999 
  2000 	TUint fragmentGranularity = ThePinObjectAllocator->iFragmentGranularity;
  2001 	TInt dataLockResult = 0;
  2002 	// fragmentation only allowed for read/write requests
  2003 	__ASSERT_DEBUG(aLength <= (TInt) fragmentGranularity || (aReq.Id() == DLocalDrive::EWrite || aReq.Id() == DLocalDrive::ERead), LOCM_FAULT());
  2004 
  2005 	// Pin the client buffer
  2006 	TInt pinnedLen;
  2007 	for (TInt pos = 0; pos < aLength; pos+= pinnedLen, aLinAddress+= pinnedLen)
  2008 		{
  2009 		pinnedLen = 0;
  2010 
  2011 		// pin memory
  2012 		TInt remainingLen = aLength - pos; // remaining length
  2013 
  2014 		// first attempt to pin memory with no pre-allocated buffers (which may fail)
  2015 		DPinObjectAllocator::SVirtualPinContainer* pinDataObject = ThePinObjectAllocator->AcquirePinObject();
  2016 
  2017 		if (pinDataObject)
  2018 			{
  2019 			TInt lenToPin = Min(KMaxPinData, remainingLen);
  2020 
  2021 			TInt r = Kern::PinVirtualMemory(pinDataObject->iObject, aLinAddress, lenToPin, pT);
  2022 			if (r == KErrNone)
  2023 				{
  2024 				pinnedLen = lenToPin;
  2025 				}
  2026 			else
  2027 				{
  2028 #ifdef __DEBUG_DEMAND_PAGING__
  2029 				Kern::Printf("Kern::PinVirtualMemory() error %d", r);
  2030 #endif
  2031 				// pin failed, so use preallocated buffer instead
  2032 				ThePinObjectAllocator->ReleasePinObject(pinDataObject);
  2033 				pinDataObject = NULL;
  2034 				}
  2035 			}
  2036 
  2037 		if (!pinDataObject)
  2038 			{
  2039 			ThePinObjectAllocator->PreAllocatedDataLock().LockFragmentation();
  2040 
  2041 			TLinAddr start = aLinAddress;
  2042 			do
  2043 				{
  2044 				TInt lenToPin = Min((TInt) fragmentGranularity, remainingLen - pinnedLen);
  2045 
  2046 #ifdef __DEBUG_DEMAND_PAGING__
  2047 				Kern::Printf(">SR PinS Id %d aLinAddress %08X lenToPin %08X offset %08X", aReq.Id(), aLinAddress, lenToPin);
  2048 #endif
  2049 
  2050 				dataLockResult = ThePinObjectAllocator->PreAllocatedDataLock().Lock(pT, start, lenToPin);
  2051 
  2052 #ifdef __DEBUG_DEMAND_PAGING__
  2053 				Kern::Printf("<SR PinS Id %d aLinAddress %08X lenToPin %08X offset %08X r %d", aReq.Id(), aLinAddress, lenToPin, r);
  2054 #endif
  2055 
  2056 				start+= lenToPin;
  2057 				pinnedLen+= lenToPin;
  2058 				}
  2059 			while (dataLockResult == 0 && pinnedLen < remainingLen);
  2060 			
  2061 			// if nothing pinned (dataLockResult == 0) or error (dataLockResult <0), release the mutex,
  2062 			// otherwise (dataLockResult > 0) release it after calling SendReceive()
  2063 			if (dataLockResult <= 0)
  2064 				ThePinObjectAllocator->PreAllocatedDataLock().UnlockFragmentation();
  2065 
  2066 #ifdef __DEBUG_DEMAND_PAGING__
  2067 				if (dataLockResult < 0)
  2068 					Kern::Printf("DFragmentationPagingLock::Lock() %d", dataLockResult);			
  2069 #endif
  2070 
  2071 			if (dataLockResult < 0)	// if lock returned an error then give up
  2072 				{
  2073 				r = dataLockResult;
  2074 				break;
  2075 				}
  2076 			}
  2077 
  2078 		// fragment request Id defaults to same as original request
  2079 		fragment.Id() = aReq.Id();
  2080 		fragment.Length() = Int64(pinnedLen);
  2081 		fragment.RemoteDesOffset() = aReq.RemoteDesOffset() + pos;
  2082 		fragment.Pos() = aReq.Pos() + pos;
  2083 		fragment.Flags() = aReq.Flags();
  2084 
  2085 		__KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Send fragment (0x%08x) type(%d), length(0x%x), offset within original req(0x%x), pos in media(0x%lx)",&fragment,fragment.Id(), pinnedLen, pos, fragment.Pos()));
  2086 		OstTraceDefExt5(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE3, "Send fragment 0x%08x; type=%d; length=0x%x; offset within original req=0x%x; position in media=0x%lx", (TUint) &fragment, (TInt) fragment.Id(), (TUint) pinnedLen, (TUint) pos, (TUint) fragment.Pos());
  2087 		
  2088 #ifdef BTRACE_PAGING_MEDIA
  2089 		TInt buf[4];
  2090 		buf[0] = pinnedLen;	// fragment length
  2091 		buf[1] = pos;		// offset within original request
  2092 		buf[2] = fragment.Pos(); // offset in media
  2093 		buf[3] = (TInt)&pT->iNThread;	// thread that issued the original write req
  2094 		BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedFragmentBegin,&fragment,fragment.Id(),buf,sizeof(buf));
  2095 #endif
  2096 		r = SendReceive(fragment, aLinAddress);	// only come back here when message (fragment) has been completed
  2097 		
  2098 		// unpin memory
  2099 		if (pinDataObject)
  2100 			{
  2101 			Kern::UnpinVirtualMemory(pinDataObject->iObject);
  2102 			ThePinObjectAllocator->ReleasePinObject(pinDataObject);
  2103 			}
  2104 		else if (dataLockResult > 0)	// pinDataObject = NULL
  2105 			{
  2106 			__ASSERT_DEBUG(dataLockResult == 1, LOCM_FAULT());
  2107 			ThePinObjectAllocator->PreAllocatedDataLock().Unlock();
  2108 			ThePinObjectAllocator->PreAllocatedDataLock().UnlockFragmentation();
  2109 			}
  2110 
  2111 #ifdef BTRACE_PAGING_MEDIA
  2112 		BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedFragmentEnd,&fragment,r);
  2113 #endif
  2114 
  2115 		if (r != KErrNone)
  2116 			break;
  2117 		}
  2118 
  2119 	NKern::ThreadLeaveCS();
  2120 
  2121 //	Kern::Printf("<PFSR %02X aReq %08X aLinAddress %08X aLen %08X offset %08X", aReq.Id(), &aReq, aLinAddress, aLength, aReq.RemoteDesOffset());
  2122 
  2123 	OstTraceFunctionExitExt( DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE_EXIT, this, r );
  2124 	return r;
  2125 	}
  2126 
  2127 #endif	// __DEMAND_PAGING__
  2128 
  2129 
  2130 TInt DPrimaryMediaBase::SendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress)
  2131 /**
  2132  * If a Physical memory helper object is present for given drive,
  2133  * then message is routed via helper;
  2134  * 
  2135  * @return KErrNone, if successful;
  2136  * 		   otherwise, one of the other system wide error codes.
  2137  * 
  2138  * @see TLocDrvRequest::SendReceive()
  2139  * @see DDmaHelper::SendReceive()
  2140  */
  2141 	{
  2142 	OstTraceExt2( TRACE_FLOW, DPRIMARYMEDIABASE_SENDRECEIVE_ENTRY, "> DPrimaryMediaBase::SendReceive;aReq=%x;aLinAddress=%x", (TUint) &aReq, (TUint) &aLinAddress );
  2143 	
  2144 	DDmaHelper* dmaHelper = aReq.Drive()->iDmaHelper;
  2145 
  2146 #ifdef __DEMAND_PAGING__
  2147 	RequestCountInc();
  2148 #endif
  2149 
  2150 	TInt r;
  2151 
  2152 	if (dmaHelper)
  2153 		r = dmaHelper->SendReceive(aReq, aLinAddress);
  2154 	else
  2155 	    { 
  2156 		r = aReq.SendReceive(&iMsgQ);
  2157 	    }
  2158 #ifdef __DEMAND_PAGING__
  2159 	RequestCountDec();
  2160 #endif
  2161 
  2162 	OstTraceFunctionExitExt( DPRIMARYMEDIABASE_SENDRECEIVE_EXIT, this, r );
  2163 	return r;
  2164 	}
  2165 
  2166 
  2167 
  2168 EXPORT_C TInt DPrimaryMediaBase::ForceMediaChange(TInt)
  2169 /**
  2170 Forces a media change.The method can be overridden in the derived classes.
  2171 @param mode Media change mode
  2172 
  2173 @return KErrNotSupported, in the default implementation
  2174 		KErrNone, if successful
  2175 		Otherwise, one of the other system wide error codes.
  2176 
  2177 */
  2178 	{
  2179 	// default implementation
  2180 	return KErrNotSupported;
  2181 	}
  2182 
  2183 EXPORT_C TInt DPrimaryMediaBase::InitiatePowerUp()
  2184 /**
  2185 Initiates Power up sequence
  2186 @return KErrCompletion, operation is complete successfully or otherwise
  2187 		KErrNone, if successful
  2188 		Otherwise, one of the other system wide error codes.
  2189 
  2190 */
  2191 	{
  2192 	// default implementation, this is the default implementation.
  2193 	return KErrCompletion;
  2194 	}
  2195 
  2196 EXPORT_C TInt DPrimaryMediaBase::QuickCheckStatus()
  2197 /**
  2198 Checks the status of the media device, whether the device is present,absent,not ready,etc.
  2199 The function can be overridden in the derived classes
  2200 
  2201 @return KErrNone, if successful
  2202 		Otherwise, one of the other system wide error codes.
  2203 
  2204 */
  2205 	{
  2206 	// default implementation
  2207 	return KErrNone;
  2208 	}
  2209 
  2210 EXPORT_C void DPrimaryMediaBase::DefaultDriveCaps(TLocalDriveCapsV2& aCaps)
  2211 /**
  2212 Fills in the default drive capabilities in TLocalDriveCapsV2 .
  2213 It initializes media type of drive as unknown and has to be overridden in the derived class. Called from the Request ( ) function of the same class.
  2214 
  2215 @param aCaps Media drive capability fields. Extension to Capabilities fields(i.e) in addition to TLocalDriveCaps mainly to support Nor flash
  2216 @see TLocalDriveCapsV2
  2217 */
  2218 
  2219 	{
  2220 	// default implementation
  2221 	// aCaps is zeroed beforehand
  2222 	aCaps.iType = EMediaUnknown;
  2223 	}
  2224 	
  2225 EXPORT_C TBool DPrimaryMediaBase::IsRemovableDevice(TInt& /*aSocketNum*/)
  2226 /**
  2227 Checks whether it is a removable device or not
  2228 @param aSocketNum Socket number
  2229 @return ETrue=Removable Device
  2230 		EFalse=Non-Removable device, default implementation
  2231 
  2232 */
  2233 	{
  2234 	// default implementation
  2235 	return(EFalse);
  2236 	}
  2237 
  2238 EXPORT_C void DPrimaryMediaBase::HandleMsg(TLocDrvRequest& m)
  2239 /**
  2240 It handles the drive request encapsulated in TLocDrvRequest depending on the message id.
  2241 
  2242 @param aRequest Encapsulates the request information received from the client
  2243 @see TLocDrvRequest
  2244 */
  2245 	{
  2246 	OstTrace1( TRACE_FLOW, DPRIMARYMEDIABASE_HANDLEMSG_ENTRY, "> DPrimaryMediaBase::HandleMsg;m=%x;", (TUint) &m);
  2247 	
  2248 	switch (m.iValue)
  2249 		{
  2250 		case EConnect:
  2251 			{
  2252 			DLocalDrive* pD=(DLocalDrive*)m.Ptr0();
  2253 			iConnectionQ.Add(&pD->iLink);
  2254 			m.Complete(KErrNone, EFalse);
  2255 			OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT1, this );
  2256 			return;
  2257 			}
  2258 		case EDisconnect:
  2259 			{
  2260 			DLocalDrive* pD=(DLocalDrive*)m.Ptr0();
  2261 			TLocDrv* pL=pD->iDrive;
  2262 			DMedia* media=pL->iMedia;
  2263 			if (iState==EReady && media && media->iDriver)
  2264 				media->iDriver->Disconnect(pD,&m);
  2265 			else
  2266 				{
  2267 				pD->Deque();
  2268 				m.Complete(KErrNone, EFalse);
  2269 				}
  2270 			OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT2, this );
  2271 			return;
  2272 			}
  2273 		case DLocalDrive::EForceMediaChange:
  2274 			{
  2275 			TUint flags = (TUint) m.Pos();
  2276 
  2277 			// if KForceMediaChangeReOpenDriver specified wait for power up, 
  2278 			// and then re-open this drive's media driver
  2279 			__KTRACE_OPT(KLOCDRV, Kern::Printf("EForceMediaChange, flags %08X\n", flags));
  2280 			if (flags == (TUint) KForceMediaChangeReOpenMediaDriver)
  2281 				{
  2282 				TInt sock;
  2283 				if (!IsRemovableDevice(sock))
  2284 					{
  2285 					CompleteRequest(m, KErrNotSupported);
  2286 					OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT3, this );
  2287 					return;
  2288 					}
  2289 				// wait for power up and then call DPrimaryMediaBase::DoRequest()
  2290 				break;
  2291 				}
  2292 
  2293 			TInt r=ForceMediaChange(flags);
  2294 			if (r==KErrNone)
  2295 				{
  2296 				// wait for media change notification to complete message
  2297 				m.Forward(&iWaitMedChg,EFalse);
  2298 				}
  2299 			else
  2300 				{
  2301 				if (r==KErrNotSupported || r==KErrCompletion)
  2302 					r=KErrNone;
  2303 				CompleteRequest(m, r);
  2304 				}
  2305 			OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT4, this );
  2306 			return;
  2307 			}
  2308 		case DLocalDrive::ECaps:
  2309 			if (iState==EPoweredDown)
  2310 				{
  2311 				// The media is powered down, but the media driver still exists.
  2312 				//  - Issue the ECaps request without powering the media back up.
  2313 				DoRequest(m);
  2314 				__TRACE_TIMING(0x101);
  2315 				OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT5, this );
  2316 				return;
  2317 				}
  2318 			break;
  2319 
  2320 		case DLocalDrive::ERead:
  2321 		case DLocalDrive::EWrite:
  2322 		case DLocalDrive::EFormat:
  2323 		case DLocalDrive::EEnlarge:
  2324 		case DLocalDrive::EReduce:
  2325 		case DLocalDrive::EPasswordLock:
  2326 		case DLocalDrive::EPasswordUnlock:
  2327 		case DLocalDrive::EPasswordClear:
  2328 		case DLocalDrive::EPasswordErase:
  2329 		case DLocalDrive::EControlIO:
  2330 		case DLocalDrive::EDeleteNotify:
  2331 		case DLocalDrive::EQueryDevice:
  2332 
  2333 #ifdef __DEMAND_PAGING__
  2334 		case DMediaPagingDevice::ERomPageInRequest:
  2335 		case DMediaPagingDevice::ECodePageInRequest:
  2336 #endif
  2337 			break;
  2338 		case DLocalDrive::EGetLastErrorInfo:
  2339 			{
  2340 			DLocalDrive* pD=(DLocalDrive*)m.Ptr0();
  2341 			TLocDrv* pL=pD->iDrive;
  2342 			*((TErrorInfo*) m.RemoteDes()) = pL->iLastErrorInfo;
  2343 			CompleteRequest(m, KErrNone);
  2344 			OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT6, this );
  2345 			return;
  2346 			}
  2347 		case DLocalDrive::EReadPasswordStore:
  2348 			{
  2349 			TPtr8 pswData ((TUint8*) m.RemoteDes(), (TInt) m.Length());
  2350 			TInt r = ThePasswordStore->ReadPasswordData(pswData);
  2351 			m.Length() = pswData.Length();
  2352 			CompleteRequest(m, r);
  2353 			OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT7, this );
  2354 			return;
  2355 			}
  2356 		case DLocalDrive::EWritePasswordStore:
  2357 			{
  2358 			TPtrC8 pData((TUint8*) m.RemoteDes(), (TInt) m.Length());
  2359 			TInt r = ThePasswordStore->WritePasswordData(pData);
  2360 
  2361 			if(r != KErrNone)
  2362 				{
  2363 				CompleteRequest(m, r);
  2364 				OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT8, this );
  2365 				return;
  2366 				}
  2367 
  2368 			r = QuickCheckStatus();
  2369 			if(r != KErrNone)
  2370 				{
  2371 				// Don't try to power up the device if it's not ready.
  2372 				// - Note that this isn't an error that needs to be returned to the client.
  2373 				CompleteRequest(m, KErrNone);
  2374 				OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT9, this );
  2375 				return;
  2376 				}
  2377 
  2378 			break;
  2379 			}
  2380 		case DLocalDrive::EPasswordStoreLengthInBytes:
  2381 			{
  2382 			TInt length = ThePasswordStore->PasswordStoreLengthInBytes();
  2383 			*(TInt*) m.RemoteDes() = length;
  2384 			CompleteRequest(m, KErrNone);
  2385 			OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT10, this );
  2386 			return;
  2387 			}
  2388 		default:
  2389 			CHECK_RET(KErrNotSupported);
  2390 			CompleteRequest(m, KErrNotSupported);
  2391 			OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT11, this );
  2392 			return;
  2393 		}
  2394 
  2395 	__KTRACE_OPT(KFAIL,Kern::Printf("mdrq %d",m.Id()));
  2396 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::HandleMsg state %d req %d",iMediaId,iState,m.Id()));
  2397 
  2398 	OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_HANDLEMSG2, "iMediaId=%d; iState=%d; req Id=%d", iMediaId, iState, m.Id());
  2399 	
  2400 	// if media driver already open, pass request through
  2401 	if (iState==EReady)
  2402 		{
  2403 		DoRequest(m);
  2404 		__TRACE_TIMING(0x101);
  2405 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT12, this );
  2406 		return;
  2407 		}
  2408 
  2409 	// if open or close in progress, defer this message
  2410 	if (iState!=EClosed && iState!=EPoweredDown)
  2411 		{
  2412 #ifdef __DEMAND_PAGING__
  2413 		if (DMediaPagingDevice::PagingRequest(m))
  2414 			{
  2415 			__ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
  2416 			__ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
  2417 			__ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
  2418 
  2419 			__KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Deferring PageIn request 0x%08x because opening or closing",&m));
  2420 			OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_HANDLEMSG3, "Deferring PageIn request 0x%08x because opening or closing", &m);
  2421 			iBody->iPagingDevice->SendToDeferredQ(&m);
  2422 			}
  2423 		else
  2424 #endif
  2425 		m.Forward(&iDeferred,EFalse);
  2426 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT13, this );
  2427 		return;
  2428 		}
  2429 
  2430 	// nothing is open, so try to open something
  2431 	__ASSERT_ALWAYS(!iCurrentReq,LOCM_FAULT());
  2432 
  2433 #ifdef __DEMAND_PAGING__
  2434 
  2435 #ifdef BTRACE_PAGING_MEDIA
  2436 	if (DMediaPagingDevice::PagingRequest(m))
  2437 		BTraceContext12(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInQuietlyDeferred,&m,iState,m.iValue);
  2438 #endif	// BTRACE_PAGING_MEDIA
  2439 
  2440 #ifdef _DEBUG
  2441 	__ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
  2442 
  2443 	if (DMediaPagingDevice::PagingRequest(m))
  2444 		{
  2445 		__ASSERT_DEBUG(iPagingMedia,LOCM_FAULT());
  2446 		__ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
  2447 		__KTRACE_OPT(KLOCDPAGING,Kern::Printf("Page request 0x%08x received -> opening MD",&m));
  2448 		OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_HANDLEMSG4, "Page request 0x%08x received; opening MD", &m);
  2449 		}
  2450 #endif	// _DEBUG
  2451 
  2452 #endif	// __DEMAND_PAGING__
  2453 
  2454 	iCurrentReq=&m;
  2455 	if(iState == EClosed)
  2456 		{
  2457 		iState=EPoweringUp1;
  2458 		}
  2459 	else if (iState == EPoweredDown)
  2460 		{
  2461 		iState=EPoweringUp2;
  2462 		}
  2463 
  2464 	TInt r=InitiatePowerUp();
  2465 	if (r==KErrNone || r==KErrServerBusy)
  2466 		{
  2467 		// wait for completion of power up request
  2468 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT14, this );
  2469 		return;
  2470 		}
  2471 	if (r==KErrCompletion)
  2472 		r=KErrNone;		// device already powered up
  2473 	PowerUpComplete(r);
  2474 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT15, this );
  2475 	}
  2476 
  2477 EXPORT_C TInt DPrimaryMediaBase::DoRequest(TLocDrvRequest& m)
  2478 /**
  2479 If the media exists, it tries to get the partition information if not there. 
  2480 It then passes on the request to the media driver by calling its Request( ) function. 
  2481 Then it completes the kernel thread message and the reference count of the thread is closed asynchronously.
  2482 
  2483 @param aRequest Encapsulates the request information received from the client
  2484 
  2485 @return KErrNone, if successful
  2486 	KErrNotReady, if missing partitions on removable media
  2487 	KErrNotSupported, if missing partitions on fixed media
  2488 	KErrArgument Out of range argument ,encapsulated in Local drive request , passed while checking and adjusting for partition
  2489 	KErrEOF, Reached the end of file
  2490 	KErrBadDescriptor, if request encapsulates a bad descriptor
  2491 	Otherwise, one of the other system wide error codes.
  2492 
  2493 */
  2494 	{
  2495 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOREQUEST_ENTRY, this );
  2496 	__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DPrimaryMediaBase::DoRequest %d",m.Id()));
  2497 	TLocDrv* pL=m.Drive();
  2498 	DMedia* media=pL->iMedia;
  2499 	TInt r=KErrNone;
  2500 	
  2501 	OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_DOREQUEST, "req Id=%d; length=0x%x; position=0x%x", (TInt) m.Id(), (TInt) m.Length(), (TInt) m.Pos());
  2502 	
  2503 	// re-open this drive's media driver ?
  2504 	if (m.iValue == DLocalDrive::EForceMediaChange)
  2505 		{
  2506 		__ASSERT_DEBUG(((TUint) m.Pos()) == (TUint) KForceMediaChangeReOpenMediaDriver, LOCM_FAULT());
  2507 
  2508 		iCurrentReq=NULL;
  2509 
  2510 		TLocDrv* pL = m.Drive();
  2511 		DMedia* media = pL->iMedia;
  2512 		if (media && media->iDriver)
  2513 			CloseMediaDrivers(media);
  2514 
  2515 		iState=EOpening;
  2516 		StartOpenMediaDrivers();
  2517 
  2518 		NotifyClients(ETrue,pL);
  2519 		CompleteRequest(m, r);
  2520 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT, this, r );
  2521 		return r;
  2522 		}
  2523 
  2524 	if (!media || !media->iDriver || iState == EClosed)
  2525 		{
  2526 		// Return KErrNotReady for missing partitions on removable media
  2527 		// as opposed to KErrNotSupported for missing partitions on fixed media
  2528 		// since the latter don't exist whereas the former might exist at some time.
  2529 		TInt sock;
  2530 		r=IsRemovableDevice(sock) ? KErrNotReady : KErrNotSupported;
  2531 		}
  2532 
  2533 	iCurrentReq=&m;
  2534 	if (r==KErrNone)
  2535 		{
  2536 		if(iTotalPartitionsOpened == 0)
  2537 			{
  2538 			UpdatePartitionInfo();
  2539 			OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT2, this, KErrNone );
  2540 			return KErrNone;
  2541 			}
  2542 		if (!(m.Flags() & TLocDrvRequest::EAdjusted))
  2543 			{
  2544 			// If this isn't the only partition, don't allow access to the whole media 
  2545 			if (iTotalPartitionsOpened > 1)
  2546 				m.DriverFlags() &= ~RLocalDrive::ELocDrvWholeMedia;
  2547 			r=m.CheckAndAdjustForPartition();
  2548 			}
  2549 		if (r==KErrNone)
  2550 			{
  2551 			OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_INTERNALS, DPRIMARYMEDIABASE_DOREQUEST_START, "req Id=%d; Remote Thread=0x%x", (TInt) m.Id(), (TUint) m.RemoteThread());
  2552 			r=media->iDriver->Request(m);
  2553 			if (r>0)
  2554 				{
  2555 				// defer request
  2556 #ifdef __DEMAND_PAGING__
  2557 				if (DMediaPagingDevice::PagingRequest(m))
  2558 					{
  2559 					__ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
  2560 					__ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
  2561 					__ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
  2562 					__KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Defer PageIn request 0x%08x",&m));
  2563 					OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOREQUEST2, "Defer PageIn request 0x%08x", &m);
  2564 					DMediaPagingDevice* pagingdevice=iBody->iPagingDevice; 
  2565 
  2566 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  2567 					TInt id=m.iValue;
  2568 					if (id==DMediaPagingDevice::ERomPageInRequest)
  2569 						{
  2570 						NKern::FMWait(&pagingdevice->iInstrumentationLock);
  2571 						if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ)
  2572 							pagingdevice->iROMStats.iTotalReDeferrals++;
  2573 						else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ)
  2574 							pagingdevice->iROMStats.iTotalSynchDeferredFromMainQ++;
  2575 						NKern::FMSignal(&pagingdevice->iInstrumentationLock);
  2576 						}
  2577 					else if (m.Flags() & TLocDrvRequest::ECodePaging)
  2578 						{
  2579 						NKern::FMWait(&pagingdevice->iInstrumentationLock);
  2580 						if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ)
  2581 							pagingdevice->iCodeStats.iTotalReDeferrals++;
  2582 						else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ)
  2583 							pagingdevice->iCodeStats.iTotalSynchDeferredFromMainQ++;
  2584 						NKern::FMSignal(&pagingdevice->iInstrumentationLock);
  2585 						}
  2586 					else if (m.Flags() & TLocDrvRequest::EDataPaging)
  2587 						{
  2588 						NKern::FMWait(&pagingdevice->iInstrumentationLock);
  2589 						if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ)
  2590 							pagingdevice->iDataStats.iTotalReDeferrals++;
  2591 						else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ)
  2592 							pagingdevice->iDataStats.iTotalSynchDeferredFromMainQ++;
  2593 						NKern::FMSignal(&pagingdevice->iInstrumentationLock);
  2594 						}
  2595 #endif
  2596 					pagingdevice->SendToDeferredQ(&m);
  2597 					}
  2598 				else
  2599 #endif
  2600 					m.Forward(&iDeferred,EFalse);
  2601 				r=KErrNone;
  2602 				}
  2603 #if defined(__DEMAND_PAGING__) && defined(_DEBUG)
  2604 			else if (r == KErrNone && DMediaPagingDevice::PagingRequest(m))
  2605 			    {
  2606 				__KTRACE_OPT(KLOCDPAGING,Kern::Printf("PageIn req 0x%08x completing asynchronously",&m));
  2607                 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOREQUEST3, "PageIn req 0x%08x completing asynchronously", &m);
  2608 			    }
  2609 #endif
  2610 			}
  2611 		}
  2612 
  2613 	if (r!=KErrNone && iCurrentReq)
  2614 		{
  2615 		TInt s=(r==KErrCompletion)?KErrNone:r;
  2616 		CHECK_RET(s);
  2617 
  2618 #ifdef __DEMAND_PAGING__
  2619 		// got here because media driver cannot service or defer this request or did service it synchronously
  2620 		if (DMediaPagingDevice::PagingRequest(m))
  2621 			{
  2622 			__ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
  2623 			__ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
  2624 			__ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
  2625 			__KTRACE_OPT(KLOCDPAGING,Kern::Printf("media driver cannot service or defer PageIn request 0x%08x or serviced it synchronously (%d)",&m, s));
  2626 			OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOREQUEST4, "Media driver cannot service or defer PageIn request 0x%08x or serviced it synchronously; retval=%d",(TUint) &m, s);
  2627 			iBody->iPagingDevice->CompleteRequest(&m, s);
  2628 			}
  2629 		else
  2630 #endif
  2631 
  2632 		CompleteRequest(m, s);
  2633 		OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_INTERNALS, DPRIMARYMEDIABASE_DOREQUEST_RETURN, "Return req Id=%d; Remote Thread=0x%x; retval=%d", (TInt) m.Id(), (TUint) m.RemoteThread(), (TInt) s);
  2634 		}
  2635 
  2636 	iCurrentReq=NULL;
  2637 	OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT3, this, r );
  2638 	return r;
  2639 	}
  2640 
  2641 EXPORT_C void DPrimaryMediaBase::PowerUpComplete(TInt anError)
  2642 /**
  2643 Called after the device is powered up or there is some error while powering up the device. 
  2644 If there is an error powering up the devices then it just completes the current running requests with an error 
  2645 and also completes the outstanding requests on the iDeferred message queue by calling SetClosed( ).
  2646 If the device is powered up OK then it either opens the media drivers 
  2647 and if they are already open then it handles the current/pending requests.
  2648 
  2649 @param anError Error code to be passed on while completing outstanding requests.
  2650 */
  2651 	{
  2652 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_ENTRY, this );
  2653 	__KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase(%d)::PowerUpComplete err %d iState %d",iMediaId,anError,iState));
  2654 	
  2655 	OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_POWERUPCOMPLETE, "iMediaId=%d; anError=%d; iState=%d", iMediaId, anError, iState );
  2656 	
  2657 	if (anError!=KErrNone)
  2658 		{
  2659 		// error powering up device
  2660 		if (iState==EPoweringUp1 || iState==EPoweringUp2)
  2661 			SetClosed(anError);
  2662 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_EXIT, this );
  2663 		return;
  2664 		}
  2665 
  2666 	// Powered up OK - now open media drivers
  2667 	if (iState==EPoweringUp1)
  2668 		{
  2669 		iState=EOpening;
  2670 		StartOpenMediaDrivers();
  2671 		}
  2672 	else if (iState==EPoweringUp2)
  2673 		{
  2674 		// media is powered up and ready, so handle the current/pending requests
  2675 		MediaReadyHandleRequest();
  2676 		}
  2677 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_EXIT2, this );
  2678 	}
  2679 
  2680 void DPrimaryMediaBase::CloseMediaDrivers(DMedia* aMedia)
  2681 	{
  2682 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_ENTRY, this );
  2683 	__KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase(%d)::CloseMediaDrivers",iMediaId));
  2684 	OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS1, "DPrimaryMediaBase iMediaId=%d", iMediaId );
  2685 	
  2686 	// we mustn't ever close the media driver if it's responsible for data paging as re-opening the drive
  2687 	// would involve memory allocation which might cause deadlock if the kernel heap were to grow
  2688 #ifdef __DEMAND_PAGING__
  2689 	if (DataPagingDfcQ(this))
  2690 		{
  2691 		__KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for data paging media %08X", this));
  2692 		OstTrace1(TRACE_FLOW, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT1, "CloseMediaDrivers aborting for data paging media 0x%08x", this);
  2693 		return;
  2694 		}
  2695 #endif
  2696 
  2697 	TInt i;
  2698 	for (i=0; i<KMaxLocalDrives; i++)
  2699 		{
  2700 		TLocDrv* pL=TheDrives[i];
  2701 		if (pL && pL->iPrimaryMedia==this)
  2702 			{
  2703 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",i));
  2704 			OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", i );
  2705 			if (aMedia == NULL || pL->iMedia == aMedia)
  2706 				{
  2707 				pL->iMedia=NULL;
  2708 				}
  2709 			}
  2710 		}
  2711 	for (i=iLastMediaId; i>=iMediaId; i--)
  2712 		{
  2713 		DMedia* pM=TheMedia[i];
  2714 		if (aMedia == NULL || pM == aMedia)
  2715 			{
  2716 			DMediaDriver* pD=pM->iDriver;
  2717 			pM->iDriver=NULL;
  2718 			__KTRACE_OPT(KLOCDRV,Kern::Printf("DMedia[%d] @ %08x Driver @ %08x",i,pM,pD));
  2719 			OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS3, "MediaId=%d; DMedia=0x%08x; MediaDriver=0x%08x", (TInt) i, (TUint) pM, (TUint) pD );
  2720 			if (pD)
  2721 				pD->Close();
  2722 			}
  2723 		}
  2724 	__KTRACE_OPT(KLOCDRV,Kern::Printf("<DPrimaryMediaBase(%d)::CloseMediaDrivers",iMediaId));
  2725 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT2, this );
  2726 	}
  2727 
  2728 void DPrimaryMediaBase::StartOpenMediaDrivers()
  2729 	{
  2730 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS_ENTRY, this );
  2731 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::StartOpenMediaDrivers",iMediaId));
  2732 	OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS, "DPrimaryMediaBase iMediaId=%d ",iMediaId);
  2733 	TVersion ver(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
  2734 
  2735 	// Get a list of all currently loaded media drivers
  2736 	// Most media drivers do not make use of the pointer iMountInfo.iInfo when 
  2737 	// their Validate() procedures are called from RPhysicalDeviceArray::GetDriverList(). 
  2738 	// However, a group of media drivers sharing the same id (passed in iDevice) may use 
  2739 	// the additional information pointed to by iMountInfo.iInfo to distinguish 
  2740 	// group members. This information is passed when the media driver is registered 
  2741 	// using LocDrv::RegisterMediaDevice().
  2742 	TInt r=iPhysDevArray.GetDriverList(KLitMediaDriverName,iDevice,iMountInfo.iInfo,ver);
  2743 	if (r!=KErrNone)
  2744 		{
  2745 		// out of memory or no driver exists
  2746 		SetClosed(r);
  2747 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS_EXIT1, this );
  2748 		return;
  2749 		}
  2750 
  2751 	// Go through them starting with highest priority
  2752 	iNextMediaId=iMediaId;
  2753 	iBody->iPhysDevIndex=iPhysDevArray.Count()-1;
  2754 	iTotalPartitionsOpened=0;
  2755 	iMediaDriversOpened=0;
  2756 	iNextMediaDriver=NULL;
  2757 	OpenNextMediaDriver();
  2758 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS_EXIT2, this );
  2759 	}
  2760 
  2761 void DPrimaryMediaBase::OpenNextMediaDriver()
  2762 	{
  2763 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_ENTRY, this );
  2764 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::OpenNextMediaDriver, this %x mediaId %d iBody->iPhysDevIndex %d",iNextMediaId, this, iMediaId, iBody->iPhysDevIndex));
  2765 	OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER, "DPrimaryMediaBase iNextMediaId=%d; this=%x; imediaId=%d; iBody->iPhysDevIndex=%d",iNextMediaId, (TUint) this, iMediaId, iBody->iPhysDevIndex);
  2766 	
  2767 	TVersion ver(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
  2768 	SPhysicalDeviceEntry& e=iPhysDevArray[iBody->iPhysDevIndex];
  2769 	DPhysicalDevice* pD=e.iPhysicalDevice;
  2770 
  2771 	iState = EOpening;
  2772 
  2773 	DMedia* pM=TheMedia[iNextMediaId];
  2774 	if (pM && pM->iDriver != NULL)
  2775 		{
  2776 		iNextMediaDriver = pM->iDriver;
  2777 		DoOpenMediaDriverComplete(KErrNone);
  2778 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_EXIT1, this );
  2779 		return;
  2780 		}
  2781 
  2782 	// this may be asynchronous
  2783 	TInt s=pD->Create( (DBase*&)iNextMediaDriver, iMediaId,  (TDesC8*) &iMountInfo, ver);
  2784 	
  2785 	__KTRACE_OPT(KLOCDRV,Kern::Printf("Media:Open-Opening %o(PRI:%d)-%d",pD,e.iPriority,s));
  2786 	if (s!=KErrNone)
  2787 		{
  2788 		iAsyncErrorCode=s;
  2789 		iAsyncDfc.Enque();
  2790 		}
  2791 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_EXIT2, this );
  2792 	}
  2793 
  2794 // Called when a media driver has responded to the Open request
  2795 void DPrimaryMediaBase::DoOpenMediaDriverComplete(TInt anError)
  2796 	{
  2797 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_ENTRY, this );
  2798 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::DoOpenMediaDriverComplete error %d iNextMediaDriver %x",iNextMediaId,anError,iNextMediaDriver));
  2799     OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE, "iMediaId=%d; anError=%d; iNextMediaDriver=0x%x", (TInt) iNextMediaId, (TInt) anError, (TUint) iNextMediaDriver);
  2800 
  2801 	
  2802 	if (anError!=KErrNone)
  2803 		{
  2804 		DMediaDriver* md = iNextMediaDriver;
  2805 		iNextMediaDriver = NULL;
  2806 		if (md)
  2807 			md->Close();
  2808 		}
  2809 	if (anError==KErrNotReady || anError==KErrNoMemory)
  2810 		{
  2811 		// if it's not ready or we're out of memory, abort
  2812 		CloseMediaDrivers();
  2813 		SetClosed(anError);
  2814 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_EXIT1, this );
  2815 		return;
  2816 		}
  2817 	if (anError==KErrNone)
  2818 		{
  2819 		DMedia* pM=TheMedia[iNextMediaId];
  2820 		pM->iDriver=iNextMediaDriver;
  2821 		DPhysicalDevice*& pD=iPhysDevArray[iBody->iPhysDevIndex].iPhysicalDevice;
  2822 		iNextMediaDriver->iPhysicalDevice=pD;
  2823 		pD=NULL;	// so it won't be closed when we tidy up
  2824 		++iMediaDriversOpened;
  2825 		}
  2826 
  2827 	
  2828 	// if no error, read partition info on media
  2829 	iState = EReadPartitionInfo;
  2830 
  2831 	if (anError == KErrNone)
  2832 		{
  2833 		DMedia* pM=TheMedia[iNextMediaId];
  2834 		TInt r = pM->iDriver->PartitionInfo(pM->iPartitionInfo);
  2835 		if (r!=KErrNone)
  2836 			{
  2837 			if (r==KErrCompletion)
  2838 				r=KErrNone;
  2839 			DoPartitionInfoComplete(r);
  2840 			}
  2841 		}
  2842 	else
  2843 		{
  2844 		DoPartitionInfoComplete(anError);
  2845 		}
  2846 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_EXIT2, this );
  2847 	}
  2848 
  2849 void DPrimaryMediaBase::DoPartitionInfoComplete(TInt anError)
  2850 	{
  2851 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_ENTRY, this );
  2852 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::DoPartitionInfoComplete error %d",iNextMediaId,anError));
  2853 
  2854 	OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE1, "iNextMediaId=%d; anError=%d", iNextMediaId, anError );
  2855 	
  2856 	DMedia* pM=TheMedia[iNextMediaId];
  2857 	if (anError==KErrNone || anError == KErrLocked)
  2858 		{
  2859 		// successfully read partition info
  2860 		iTotalPartitionsOpened+=pM->PartitionCount();
  2861 		}
  2862 	else
  2863 		{
  2864 		// couldn't read partition info or driver failed to open
  2865 		if (pM->iDriver)
  2866 			{
  2867 #ifdef __DEMAND_PAGING__
  2868 			if (DataPagingDfcQ(this))
  2869 				{
  2870 				__KTRACE_OPT(KLOCDRV,Kern::Printf("DoPartitionInfoComplete(%d) Close Media Driver aborted for data paging media %08X", this));
  2871 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE2, "Close Media Driver for data paging media 0x%08x", this);
  2872 				}
  2873 			else
  2874 #endif
  2875 				{
  2876 				pM->iDriver->Close();
  2877 				pM->iDriver=NULL;
  2878 				}
  2879 			}
  2880 		if (anError==KErrNotReady || anError==KErrNoMemory)
  2881 			{
  2882 			// if it's not ready or we're out of memory, or the drive is locked, abort
  2883 			CloseMediaDrivers();
  2884 			SetClosed(anError);
  2885 			OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT, this );
  2886 			return;
  2887 			}
  2888 		}
  2889 
  2890 	// Open next media driver, if there is one
  2891 	TBool complete = EFalse;
  2892 	if (++iNextMediaId>iLastMediaId)
  2893 		complete=ETrue;
  2894 	if (iBody->iPhysDevIndex==0)
  2895 		complete=ETrue;
  2896 	else
  2897 		iBody->iPhysDevIndex--;
  2898 	if (!complete)
  2899 		{
  2900 		OpenNextMediaDriver();
  2901 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT2, this );
  2902 		return;
  2903 		}
  2904 
  2905 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase %d All media drivers open & partitions read",iMediaId));
  2906 	__KTRACE_OPT(KLOCDRV,Kern::Printf("%d media drivers opened",iMediaDriversOpened));
  2907 	OstTrace1( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE3, "iMediaDriversOpened=%d", iMediaDriversOpened );
  2908 	if (iMediaDriversOpened==0)
  2909 		{
  2910 		SetClosed(KErrNotSupported);
  2911 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT3, this );
  2912 		return;
  2913 		}
  2914 
  2915 	// we are now finished with media driver list
  2916 	iPhysDevArray.Close();
  2917 
  2918 	// Finished reading partition info
  2919 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase %d Read partition info complete",iMediaId));
  2920 	__KTRACE_OPT(KLOCDRV,Kern::Printf("%d total partitions",iTotalPartitionsOpened));
  2921 	OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE4, "Read partition info complete iMediaId=%d; iPartitionsOpened=%d", iMediaId, iTotalPartitionsOpened );
  2922 	if (iTotalPartitionsOpened==0)
  2923 		{
  2924 		SetClosed(KErrNotSupported);
  2925 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT4, this );
  2926 		return;
  2927 		}
  2928 	
  2929 	// work out mapping of drives to partitions/media
  2930 	TInt totalPartitions=iTotalPartitionsOpened;
  2931 	TInt id=iMediaId;	// start with primary media
  2932 	TInt partitionsOnThisMedia=PartitionCount();
  2933 	TInt partition=0;
  2934 	TInt j;
  2935 	for (j=0; j<KMaxLocalDrives; j++)
  2936 		{
  2937 		TLocDrv* pD=TheDrives[j];
  2938 		if (pD && pD->iPrimaryMedia==this)
  2939 			{
  2940 			if (totalPartitions==0)
  2941 				{
  2942 				pD->iMedia=NULL;
  2943 				continue;
  2944 				}
  2945 			if (partition==partitionsOnThisMedia)
  2946 				{
  2947 				id++;
  2948 				partition=0;
  2949 				partitionsOnThisMedia=TheMedia[id]->PartitionCount();
  2950 				}
  2951 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d = Media %d Partition %d",j,id,partition));
  2952 			OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE5, "Local Drive=%d; iMediaId=%d; partition=%d", j, id, partition );
  2953 			
  2954 			pD->iMedia=TheMedia[id];
  2955 			pD->iPartitionNumber=partition;
  2956 			memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry));
  2957 			partition++;
  2958 			totalPartitions--;
  2959 			}
  2960 		}
  2961 
  2962 	// media is now ready - handle current or deferred requests
  2963 	MediaReadyHandleRequest();
  2964 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT5, this );
  2965 	}
  2966 
  2967 void DPrimaryMediaBase::MediaReadyHandleRequest()
  2968 	{
  2969 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_MEDIAREADYHANDLEREQUEST_ENTRY, this );
  2970 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase::MediaReadyHandleRequest() this %x", this));
  2971 	iState = EReady;
  2972 
  2973 	// now we can process the current request
  2974 	// careful - thread may have exited while we were powering up
  2975 	if (iCurrentReq)
  2976 		{
  2977 		DoRequest(*iCurrentReq);	// this sets iCurrentReq=NULL
  2978 		}
  2979 
  2980 	// see if we can process any other requests concurrently
  2981 	RunDeferred();
  2982 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_MEDIAREADYHANDLEREQUEST_EXIT, this );
  2983 	}
  2984 
  2985 void DPrimaryMediaBase::UpdatePartitionInfo()
  2986 	{
  2987 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_UPDATEPARTITIONINFO_ENTRY, this );
  2988 	iState=EReadPartitionInfo;
  2989 	iNextMediaId=iMediaId;
  2990 	DMedia* pM=TheMedia[iNextMediaId];
  2991 	TInt r=pM->iDriver->PartitionInfo(pM->iPartitionInfo);
  2992 	if (r!=KErrNone)
  2993 		{
  2994 		if (r==KErrCompletion)
  2995 			r=KErrNone;
  2996 		DoPartitionInfoComplete(r);
  2997 		}
  2998 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_UPDATEPARTITIONINFO_EXIT, this );
  2999 	}
  3000 
  3001 void DPrimaryMediaBase::CompleteCurrent(TInt anError)
  3002 	{
  3003 	OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_COMPLETECURRENT_ENTRY, this );
  3004 	if (iCurrentReq)
  3005 		{
  3006 		CHECK_RET(anError);
  3007 #ifdef __DEMAND_PAGING__
  3008 		// got here because it was powered down when powering up, or failed powering up or failed opening MD or got media change
  3009 		if (DMediaPagingDevice::PagingRequest(*iCurrentReq))
  3010 			{
  3011 			__ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
  3012 			__ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
  3013 			__ASSERT_ALWAYS( ((iCurrentReq->Flags() & TLocDrvRequest::ECodePaging) == 0) || (iCurrentReq->Drive()->iPagingDrv), LOCM_FAULT());
  3014 
  3015 			__KTRACE_OPT2(KLOCDPAGING,KFAIL,Kern::Printf("Got here because it was powered down when powering up, or failed powering up or failed opening MD or got media change"));
  3016 			OstTraceDef0(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_COMPLETECURRENT, "Completed request due to powered down when powering up, or failed powering up or failed opening MD or got media change");
  3017 			iBody->iPagingDevice->CompleteRequest(iCurrentReq, anError);
  3018 			}
  3019 		else
  3020 #endif
  3021 		CompleteRequest(*iCurrentReq, anError);
  3022 		iCurrentReq=NULL;
  3023 		}
  3024 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_COMPLETECURRENT_EXIT, this );
  3025 	}
  3026 
  3027 
  3028 void DPrimaryMediaBase::CompleteRequest(TLocDrvRequest& aMsg, TInt aResult)
  3029 	{
  3030 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_COMPLETEREQUEST_ENTRY, this );
  3031 	OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_COMPLETEREQUEST1, "TLocDrvRequest Object=0x%x; aResult=%d", (TUint) &aMsg, aResult);
  3032 	aMsg.Complete(aResult,EFalse);
  3033 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_COMPLETEREQUEST_EXIT, this );
  3034 	}
  3035 
  3036 EXPORT_C void DPrimaryMediaBase::RunDeferred()
  3037 /**
  3038 Runs deferred Requests. Initiated from DPrimaryMediaBase::PowerUpComplete() function 
  3039 to see if any other requests can be processed concurrently. 
  3040 Can also be called from DPrimaryMediaBase::NotifyPowerDown 
  3041 or DPrimaryMediaBase::NotifyEmergencyPowerDown() function or DMediaDriver::Complete()
  3042 */
  3043 	{
  3044 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_RUNDEFERRED_ENTRY, this );
  3045 	// Do nothing if an open or close is in progress - this might be the case, for example, 
  3046 	// if a EForceMediaChange request (with the  KForceMediaChangeReOpenMediaDriver flag) 
  3047 	// has recently been processed
  3048 	if (iState!=EReady && iState!=EClosed && iState!=EPoweredDown)
  3049 	    {
  3050 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT1, this );
  3051 		return;
  3052 	    }
  3053 	
  3054 	// rerun deferred requests;
  3055 #ifdef __DEMAND_PAGING__
  3056 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3057 	TInt countROM=0;
  3058 	TInt countCode=0;
  3059 #endif
  3060 
  3061 	if(iPagingMedia)
  3062 		{
  3063 		__ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
  3064 		if(iBody->iPagingDevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ)		// if already emptying deferred page in queue, don't reenter
  3065 			{
  3066 			__KTRACE_OPT(KLOCDPAGING,Kern::Printf("Already emptying deferred queue"));
  3067 			OstTrace0(TRACE_FLOW, DPRIMARYMEDIABASE_RUNDEFERRED_EXIT2, "< Already emptying deferred queue");
  3068 			return;
  3069 			}
  3070 
  3071 		DMediaPagingDevice* pagingdevice=iBody->iPagingDevice;
  3072 		TLocDrvRequest* pL = (TLocDrvRequest*) pagingdevice->iDeferredQ.Last();
  3073 		if(pL)
  3074 			{
  3075 			pagingdevice->iEmptyingQ|= DMediaPagingDevice::EDeferredQ;			// prevent reentering when already emptying this queue
  3076 			TLocDrvRequest* pM=NULL;
  3077 			while (pM != pL && (pM = (TLocDrvRequest*) pagingdevice->iDeferredQ.Poll()) != NULL)	// synchronously empty deferred queue but ignore re-deferrals
  3078 				{
  3079 				__ASSERT_ALWAYS( DMediaPagingDevice::PagingRequest(*pL), LOCM_FAULT() );
  3080 
  3081 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3082 				(pM->iValue==DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++);
  3083 				if(pM==pL)
  3084 					{
  3085 					NKern::FMWait(&pagingdevice->iInstrumentationLock);
  3086 					if(pM->iValue==DMediaPagingDevice::ERomPageInRequest && pagingdevice->iROMStats.iMaxReqsInDeferred<countROM)
  3087 						pagingdevice->iROMStats.iMaxReqsInDeferred=countROM;
  3088 					else if ((pM->Flags() & TLocDrvRequest::ECodePaging) && pagingdevice->iCodeStats.iMaxReqsInDeferred<countCode)
  3089 							pagingdevice->iCodeStats.iMaxReqsInDeferred=countCode;
  3090 					else if ((pM->Flags() & TLocDrvRequest::EDataPaging) && pagingdevice->iDataStats.iMaxReqsInDeferred<countCode)
  3091 							pagingdevice->iDataStats.iMaxReqsInDeferred=countCode;
  3092 					NKern::FMSignal(&pagingdevice->iInstrumentationLock);
  3093 					}
  3094 #endif
  3095 				__KTRACE_OPT(KLOCDPAGING,Kern::Printf("RunDeferred: process req 0x%08x, last in deferred queue 0x%08x",pM,pL));
  3096 				OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_RUNDEFERRED2, "process req=0x%08x; last in deferred queue=0x%08x",(TUint) pM, (TUint) pL);
  3097 #ifdef BTRACE_PAGING_MEDIA
  3098 				BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInDeferredReposted,pM,pM->iValue);
  3099 #endif
  3100 				// if Page In requests are synchronous this services them all in sequence, 
  3101 				// if they're asynch it re-defers them
  3102 				DoRequest(*(TLocDrvRequest*)pM);	
  3103 				}
  3104 			pagingdevice->iEmptyingQ&= ~DMediaPagingDevice::EDeferredQ;
  3105 			}
  3106 
  3107 		// the reason we now try an empty the main Page In queue is there is at least one type of Page In request 
  3108 		// serviced synchronously in which case when we empty the deferred Page In queue as above, received Page In 
  3109 		// requests are left in the main queue (not deferred) and we don't want to start processing deferred normal 
  3110 		// requests before these Page In requests. If all deferred normal requests are synchronous, the received Page 
  3111 		// In requests will have to wait until all are serviced. NB: requests may be deferred even if the MD services 
  3112 		// all requests synchronously, but runs background tasks that cannot be interrupted. In this last case the 
  3113 		// normal deferred queue may have some very long latency requests.
  3114 		if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ)	// already emptying main Page In queue, skip (any Page In requests will be deferred)
  3115 			{
  3116 			__KTRACE_OPT(KLOCDPAGING,Kern::Printf("Already emptying main queue"));
  3117 			OstTrace0(TRACE_FLOW, DPRIMARYMEDIABASE_RUNDEFERRED_EXIT3, "< Already emptying main queue");
  3118 			return;
  3119 			}
  3120 	
  3121 		TLocDrvRequest* pM=NULL;
  3122 		if (!pagingdevice->iMainQ.iReady)	// if it's ready, then queue is empty
  3123 			{
  3124 			pM = (TLocDrvRequest*) pagingdevice->iMainQ.iMessage;
  3125 			pagingdevice->iMainQ.iMessage = NULL;
  3126 			if (pM == NULL)
  3127 				pM = (TLocDrvRequest*) pagingdevice->iMainQ.Poll();
  3128 			}
  3129 
  3130 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3131 		countROM = countCode=0;
  3132 #endif
  3133 		if(pM)
  3134 			{
  3135 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3136 			__e32_atomic_add_ord32(&pagingdevice->iROMStats.iTotalSynchEmptiedMainQ, 1);
  3137 #endif
  3138 			pagingdevice->iEmptyingQ|=DMediaPagingDevice::EMainQ;
  3139 			for ( ; pM != NULL; pM = (TLocDrvRequest*) pagingdevice->iMainQ.Poll())
  3140 				{
  3141 				__ASSERT_ALWAYS(DMediaPagingDevice::PagingRequest(*pM), LOCM_FAULT());
  3142 
  3143 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3144 				(pM->iValue==DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++);
  3145 #endif
  3146 
  3147 				__KTRACE_OPT(KLOCDPAGING,Kern::Printf("RunDeferred: process req 0x%08x",pM));
  3148 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_RUNDEFERRED4, "process req=0x%08x", pM);
  3149 				DoRequest(*(TLocDrvRequest*)pM);	// if Page In requests are synchronous this services them all in sequence, if they're asynch it defers them
  3150 				}
  3151 
  3152 			pagingdevice->iEmptyingQ&= ~DMediaPagingDevice::EMainQ;
  3153 
  3154 
  3155 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3156 			NKern::FMWait(&pagingdevice->iInstrumentationLock);
  3157 			pagingdevice->iROMStats.iTotalSynchServicedFromMainQ+=countROM;
  3158 			if(pagingdevice->iROMStats.iMaxReqsInPending<countROM)
  3159 				pagingdevice->iROMStats.iMaxReqsInPending=countROM;
  3160 			pagingdevice->iCodeStats.iTotalSynchServicedFromMainQ+=countCode;
  3161 			if(pagingdevice->iCodeStats.iMaxReqsInPending<countCode)
  3162 				pagingdevice->iCodeStats.iMaxReqsInPending=countCode;
  3163 			NKern::FMSignal(&pagingdevice->iInstrumentationLock);
  3164 #endif
  3165 			}	// if (pM)
  3166 		}	// 	if(iPagingMedia)
  3167 #endif
  3168 	if (iRunningDeferred)
  3169 	    {
  3170 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT4, this );
  3171 		return;
  3172 	    }
  3173 	TMessageBase* pL = iDeferred.Last();
  3174 	if (!pL)
  3175 	    {
  3176 		OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT5, this );
  3177 		return;	// no deferred requests
  3178 	    }
  3179 	iRunningDeferred=1;
  3180 	TMessageBase* pM=NULL;
  3181 
  3182 	while( pM != pL && (pM=iDeferred.Poll()) != NULL)	// stop after processing last one (requests may be re-deferred)
  3183 		DoRequest(*(TLocDrvRequest*)pM);
  3184 	iRunningDeferred=0;
  3185 	
  3186 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT6, this );
  3187 	}
  3188 
  3189 void DPrimaryMediaBase::SetClosed(TInt anError)
  3190 	{
  3191 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_SETCLOSED_ENTRY, this );
  3192 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::SetClosed error %d",iMediaId,anError));
  3193 	OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_SETCLOSED, "iMediaId=%d; anError=%d", iMediaId, anError );
  3194 	CHECK_RET(anError);
  3195 
  3196 	// cancel DMediaDriver::OpenMediaDriverComplete() / DMediaDriver::PartitionInfoComplete() DFC
  3197 	iAsyncDfc.Cancel();
  3198 
  3199 	iDeferred.CompleteAll(anError);
  3200 
  3201 #ifdef __DEMAND_PAGING__
  3202 	if(iPagingMedia)
  3203 		iBody->iPagingDevice->iDeferredQ.CompleteAll(anError);
  3204 #endif
  3205 
  3206 	CompleteCurrent(anError);
  3207 
  3208 	
  3209 
  3210 	if (iState==EOpening)
  3211 		iPhysDevArray.Close();
  3212 
  3213 	iState = EClosed;
  3214 
  3215 	iWaitMedChg.CompleteAll(KErrNone);
  3216 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_SETCLOSED_EXIT, this );
  3217 	}
  3218 
  3219 void DPrimaryMediaBase::NotifyClients(TBool aMediaChange,TLocDrv* aLocDrv)
  3220 
  3221 //
  3222 // Notify all clients of a media change or power-down event
  3223 //
  3224 	{
  3225 	OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_NOTIFYCLIENTS_ENTRY, this );
  3226 	
  3227 	SDblQueLink* pL=iConnectionQ.iA.iNext;
  3228 	while (pL!=&iConnectionQ.iA)
  3229 		{
  3230 		DLocalDrive* pD=_LOFF(pL,DLocalDrive,iLink);
  3231 		// Issue the notification if the caller wants to notify all drives (aLocDrv == NULL) or 
  3232 		// the specified drive matches this one
  3233 		if (aLocDrv == NULL || aLocDrv == pD->iDrive)
  3234 			pD->NotifyChange(*this, aMediaChange);
  3235 		pL=pL->iNext;
  3236 		}
  3237 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYCLIENTS_EXIT, this );
  3238 	}
  3239 
  3240 EXPORT_C void DPrimaryMediaBase::NotifyMediaChange()
  3241 /**
  3242 Closes all media drivers on this device and notifies all connections that media change has occurred 
  3243 and completes any outstanding requests with KErrNotReady. 
  3244 This also completes any force media change requests with KErrNone.
  3245 */
  3246 	{
  3247 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_ENTRY, this );
  3248 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaChange state %d",iMediaId,iState));
  3249 
  3250 	OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE, "iMediaId=%d; iState=%d", iMediaId, iState );
  3251 	
  3252 	TInt state=iState;
  3253 
  3254 	__ASSERT_DEBUG(iBody, LOCM_FAULT());
  3255 
  3256 #ifdef __DEMAND_PAGING__
  3257 	iBody->iMediaChanges++;
  3258 
  3259 	// As data paging media never close, need to ensure the media driver cancels
  3260 	// any requests it owns as the stack may be powered down by DPBusPrimaryMedia::ForceMediaChange().
  3261 	// DMediaDriver::NotifyPowerDown() should do this
  3262 	if(DataPagingDfcQ(this))
  3263 		NotifyPowerDown();
  3264 #endif
  3265 
  3266 	// complete any outstanding requests with KErrNotReady
  3267 	// and any force media change requests with KErrNone
  3268 	SetClosed(KErrNotReady);
  3269 
  3270 	// close all media drivers on this device
  3271 	if (state>=EOpening)
  3272 		{
  3273 		CloseMediaDrivers();
  3274 		}
  3275 
  3276 	// notify all connections that media change has occurred
  3277 	NotifyClients(ETrue);
  3278 
  3279 	// complete any force media change requests
  3280 	iWaitMedChg.CompleteAll(KErrNone);
  3281 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_EXIT, this );
  3282 	}
  3283 
  3284 
  3285 EXPORT_C void DPrimaryMediaBase::NotifyPowerDown()
  3286 /**
  3287 Called on machine power-down. Notifies all media drivers on this device. 
  3288 If device is not ready then it completes current requests but leaves other outstanding requests
  3289 If ready, media driver should complete current request.
  3290 
  3291 */
  3292 	{
  3293 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_ENTRY, this );
  3294 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyPowerDown state %d",iMediaId,iState));
  3295 	
  3296 	OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPOWERDOWN, "iMediaId=%d; iState=%d", iMediaId, iState );
  3297 	
  3298 	TInt id;
  3299 	TBool allPersistent = ETrue;
  3300 	TBool allOpen = ETrue;
  3301 
  3302 	 // notify all media drivers on this device
  3303 	for (id=iMediaId; id<=iLastMediaId; id++)
  3304 		{
  3305 		DMedia* pM = TheMedia[id];
  3306 		DMediaDriver* pD = pM->iDriver; 
  3307 		
  3308 		if ((pD) && (iState==EReady || iState==EReadPartitionInfo || iState==EOpening || iState==EPoweringUp2 || iState==ERecovering))
  3309 			pD->NotifyPowerDown();
  3310 
  3311 		if (pD == NULL || pD->iPhysicalDevice == NULL)
  3312 			allOpen = EFalse;
  3313 		else if (pD->iPhysicalDevice->Info(DPhysicalDevice::EMediaDriverPersistent, NULL) != KErrNone)
  3314 			{
  3315 			// We must NOT destroy the media driver if this media is responsible for data paging as 
  3316 			// re-opening the media driver would involve memory allocation which might cause a deadlock
  3317 #ifdef __DEMAND_PAGING__
  3318 			__ASSERT_ALWAYS(!DataPagingDfcQ(this), LOCM_FAULT());
  3319 #endif
  3320 			allPersistent = EFalse;
  3321 			}
  3322 		}
  3323 
  3324 	__KTRACE_OPT(KLOCDRV,Kern::Printf("allPersistent(%d)::allOpen %d",allPersistent, allOpen));
  3325 	OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPOWERDOWN2, "allPersistent=%d; allOpen=%d", allPersistent, allOpen );
  3326 
  3327 	if (allPersistent && allOpen && iState == EReady)
  3328 		{
  3329 		//
  3330 		// The EPoweredDown state indicates that the media is powered down, but the media driver still exists.
  3331 		//
  3332 		//  - This allows the media driver to still be accessed (ie - to determine driver capabilities) without
  3333 		//    the need to power up the device, which can be a lengthy operation.
  3334 		//
  3335 		//  - NOTE : This will need re-visiting if we ever re-enable standby mode on a platform that is not capable
  3336 		//           of detecting door interrupts while in standby.  In such a scenario, problems could occur as 
  3337 		//			the device capabilities may change without the local media subsystem recognising.
  3338 		//
  3339 		iState=EPoweredDown;
  3340 		}
  3341 	else
  3342 		{
  3343 		CloseMediaDrivers();
  3344 		SetClosed(KErrNotReady);
  3345 		}
  3346 
  3347 	NotifyClients(EFalse);
  3348 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_EXIT, this );
  3349 	}
  3350 
  3351 
  3352 EXPORT_C void DPrimaryMediaBase::NotifyPsuFault(TInt anError)
  3353 /**
  3354 Closes all media drivers on this device and completes any outstanding requests with error code.
  3355 @param anError Error code to be passed on while closing media drivers and completing outstanding requests.
  3356 */
  3357 
  3358 	{
  3359 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYPSUFAULT_ENTRY, this );
  3360 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyPsuFault state %d, err %d",iMediaId,iState,anError));
  3361 	OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPSUFAULT, "iMediaId=%d; iState=%d; anError=%d", iMediaId, iState, anError );
  3362 	
  3363 	if (iState>=EOpening)
  3364 		{
  3365 		CloseMediaDrivers();
  3366 		}
  3367 
  3368 	// complete any outstanding requests with error
  3369 	SetClosed(anError);
  3370 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPSUFAULT_EXIT, this );
  3371 	}
  3372 
  3373 EXPORT_C void DPrimaryMediaBase::NotifyEmergencyPowerDown()
  3374 /**
  3375 Called on emergency power down. Notifies all media drivers on this device. 
  3376 If it is not in a ready state then it completes the current request but leaves other outstanding requests.
  3377 If it is ready then the media driver should complete the current request. 
  3378 It closes all media drivers and notifies all clients of a power down event.
  3379 */
  3380 	{
  3381 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_ENTRY, this );
  3382 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyEmergencyPowerDown state %d",iMediaId,iState));
  3383 	OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN, "iMediaId=%d; iState=%d", iMediaId, iState );
  3384 	
  3385 	TBool recover=EFalse;
  3386 	if (iState==EReady && iCritical!=0)
  3387 		{
  3388 		// check if emergency power recovery supported
  3389 		;
  3390 		}
  3391 	if (recover)
  3392 		{
  3393 		}
  3394 
  3395 	// else just return KErrAbort
  3396 	// notify all media drivers on this device
  3397 	if (iState==EReady || iState==EOpening || iState==EPoweringUp2 || iState==ERecovering)
  3398 		{
  3399 		TInt id;
  3400 		for (id=iMediaId; id<=iLastMediaId; id++)
  3401 			{
  3402 			DMedia* pM=TheMedia[id];
  3403 			DMediaDriver* pD=pM->iDriver;
  3404 			if (pD)
  3405 				pD->NotifyEmergencyPowerDown();
  3406 			}
  3407 		}
  3408 
  3409 	if (iState!=EReady)
  3410 		{
  3411 		// complete current request but leave other outstanding requests
  3412 		// if ready, media driver should complete current request
  3413 		CompleteCurrent(KErrNotReady);
  3414 		}
  3415 	CloseMediaDrivers();
  3416 	SetClosed(KErrNotReady);
  3417 	NotifyClients(EFalse);
  3418 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_EXIT, this );
  3419 	}
  3420 
  3421 EXPORT_C void DPrimaryMediaBase::NotifyMediaPresent()
  3422 /**
  3423 Notifies clients of a media change by calling NotifyClients ( ) function to indicate that media is present.
  3424 */
  3425 	{
  3426 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_ENTRY, this );
  3427 	NotifyClients(ETrue);
  3428 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_EXIT, this );
  3429 	}
  3430 
  3431 EXPORT_C TInt DPrimaryMediaBase::DoInCritical()
  3432 /**
  3433 Flags the media driver as entering a critical part of its processing.
  3434 
  3435 In this context, critical means that the driver must be allowed to complete
  3436 its current activity.
  3437 For example, a request to power down the device must be deferred until
  3438 the driver exits the critical part.
  3439 
  3440 @return KErrNone, if the driver has been successfully flagged as being in
  3441         a critical part; otherwise, one of the other system-wide error codes.
  3442         The default implementation just returns KErrNone and can be overridden in the derived class
  3443 @see DPrimaryMediaBase::DoEndInCritical()
  3444 */
  3445 
  3446 	{
  3447 	return KErrNone;
  3448 	}
  3449 
  3450 EXPORT_C void DPrimaryMediaBase::DoEndInCritical()
  3451 /**
  3452 Flags the media driver as leaving a critical part of its processing.
  3453 
  3454 Default implementation does nothing
  3455 @see DPrimaryMediaBase::DoEndInCritical()
  3456 */
  3457 	{
  3458 	}
  3459 
  3460 TInt DPrimaryMediaBase::InCritical()
  3461 	{
  3462 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_INCRITICAL_ENTRY, this );
  3463 	if (iCritical==0)
  3464 		{
  3465 		TInt r=DoInCritical();
  3466 		if (r!=KErrNone)
  3467 		    {
  3468 			OstTraceFunctionExitExt( DPRIMARYMEDIABASE_INCRITICAL_EXIT1, this, r );
  3469 			return r;
  3470 		    }
  3471 		}
  3472 	++iCritical;
  3473 	OstTraceFunctionExitExt( DPRIMARYMEDIABASE_INCRITICAL_EXIT2, this, KErrNone );
  3474 	return KErrNone;
  3475 	}
  3476 
  3477 void DPrimaryMediaBase::EndInCritical()
  3478 	{
  3479 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_ENDINCRITICAL_ENTRY, this );
  3480 	if (--iCritical==0)
  3481 		DoEndInCritical();
  3482 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_ENDINCRITICAL_EXIT, this );
  3483 	}
  3484 
  3485 EXPORT_C void DPrimaryMediaBase::DeltaCurrentConsumption(TInt /*aCurrent*/)
  3486 /**
  3487 Sets the incremental value of current consumption to aCurrent.
  3488 The default implementation does nothing .
  3489 
  3490 @param aCurrent Delta Current in Milliamps
  3491 */
  3492 	{
  3493 	// default implementation
  3494 	}
  3495 
  3496 TInt DPrimaryMediaBase::OpenMediaDriver()
  3497 //
  3498 // Synchronous open for devices with no DFC queue (e.g. IRAM)
  3499 //
  3500 	{
  3501     OstTraceFunctionEntry1( DPRIMARYMEDIABASE_OPENMEDIADRIVER_ENTRY, this );
  3502     
  3503 	__KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase:OpenMediaDriver-%d",iMediaId));
  3504 	OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_OPENMEDIADRIVER1, "iMediaId=%d", iMediaId);
  3505 	
  3506 	TVersion ver(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
  3507 
  3508 	// Get a list of all currently loaded media drivers
  3509 	// Most media drivers do not make use of the pointer iMountInfo.iInfo when 
  3510 	// their Validate() procedures are called from RPhysicalDeviceArray::GetDriverList(). 
  3511 	// However, a group of media drivers sharing the same id (passed in iDevice) may use 
  3512 	// the additional information pointed to by iMountInfo.iInfo to distinguish 
  3513 	// group members. This information is passed when the media driver is registered 
  3514 	// using LocDrv::RegisterMediaDevice().
  3515 	TInt r=iPhysDevArray.GetDriverList(KLitMediaDriverName,iDevice,iMountInfo.iInfo,ver);
  3516 	if (r!=KErrNone)
  3517 	    {
  3518 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_OPENMEDIADRIVER_EXIT1, this, r );
  3519 		return r;
  3520 	    }
  3521 	// Go through them starting with highest priority
  3522 	TInt totalPartitions=0;
  3523 	TInt c=iPhysDevArray.Count();	// can't be zero
  3524 	TInt i=c-1;
  3525 	r=KErrNotSupported;
  3526 	for (iNextMediaId=iMediaId; i>=0 && iNextMediaId<=iLastMediaId && r!=KErrNotReady; i--)
  3527 		{
  3528 		DPhysicalDevice* pD=iPhysDevArray[i].iPhysicalDevice;
  3529 		DMediaDriver *pM=NULL;
  3530 
  3531 		// try to open media driver
  3532 		TInt s=pD->Create( (DBase*&)pM, iMediaId, NULL, ver); 
  3533 
  3534 		__KTRACE_OPT(KLOCDRV,Kern::Printf("Media:Open-Opening %o(PRI:%d)-%d",pD,iPhysDevArray[i].iPriority,s));
  3535 		OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_OPENMEDIADRIVER2, "Media:Open-Opening 0x%x iPriority=%d; retval=%d", (TUint) pD, (TUint) iPhysDevArray[i].iPriority, (TUint) s);
  3536 		if (s!=KErrNone && pM)
  3537 			{
  3538 			pM->Close();
  3539 			pM=NULL;
  3540 			}
  3541 		if (s==KErrNotReady)
  3542 			{
  3543 			r=KErrNotReady; // If it isn't ready - nothing will open.
  3544 			break;
  3545 			}
  3546 		if (s==KErrNoMemory)
  3547 			{
  3548 			r=KErrNoMemory; // If we are out of memory, give up now
  3549 			break;
  3550 			}
  3551 		if (s==KErrNone)
  3552 			{
  3553 			// Found a media driver for this device - check for valid partitions.
  3554 			DMedia* media=TheMedia[iNextMediaId];
  3555 			s=pM->PartitionInfo(media->iPartitionInfo);
  3556 			if (s==KErrNone)
  3557 				{
  3558 				r=KErrNone;
  3559 				media->iDriver=pM;
  3560 				pM->iPhysicalDevice=pD;
  3561 				iPhysDevArray[i].iPhysicalDevice=NULL;	// so it won't be closed when we tidy up
  3562 				totalPartitions+=media->PartitionCount();
  3563 				}
  3564 			else
  3565 				pM->Close();
  3566 			}
  3567 		}
  3568 
  3569 	// we are now finished with media driver list
  3570 	iPhysDevArray.Close();
  3571 
  3572 	// if driver opened OK, work out mapping of drives to partitions/media
  3573 	if (r==KErrNone)
  3574 		{
  3575 		TInt id=iMediaId;	// start with primary media
  3576 		TInt partitionsOnThisMedia=PartitionCount();
  3577 		TInt partition=0;
  3578 		TInt j;
  3579 		for (j=0; j<KMaxLocalDrives; j++)
  3580 			{
  3581 			TLocDrv* pD=TheDrives[j];
  3582 			if (pD && pD->iPrimaryMedia==this)
  3583 				{
  3584 				if (totalPartitions==0)
  3585 					{
  3586 					pD->iMedia=NULL;
  3587 					continue;
  3588 					}
  3589 				if (partition==partitionsOnThisMedia)
  3590 					{
  3591 					id++;
  3592 					partition=0;
  3593 					partitionsOnThisMedia=TheMedia[id]->PartitionCount();
  3594 					}
  3595 				pD->iMedia=TheMedia[id];
  3596 				pD->iPartitionNumber=partition;
  3597 				memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry));
  3598 				partition++;
  3599 				totalPartitions--;
  3600 				}
  3601 			}
  3602 		}
  3603 
  3604 	__KTRACE_OPT(KLOCDRV,Kern::Printf("<DPrimaryMediaBase:OpenMediaDriver-%d",r));
  3605 	OstTraceFunctionExitExt( DPRIMARYMEDIABASE_OPENMEDIADRIVER_EXIT2, this, r );
  3606 	return r;
  3607 	}
  3608 
  3609 #ifdef __DEMAND_PAGING__
  3610 // RequestCountInc()
  3611 // 
  3612 // Counts the number of outstanding requests
  3613 // For data-paging media, calls DPagingDevice::NotifyBusy() when count goes positive
  3614 //
  3615 void DPrimaryMediaBase::RequestCountInc()
  3616 	{
  3617 	__ASSERT_DEBUG(iBody, LOCM_FAULT());
  3618 	TInt oldVal = (TInt) __e32_atomic_add_ord32(&iBody->iRequestCount, (TUint) 1);
  3619 //Kern::Printf("RCINC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal);
  3620 	
  3621 	OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTINC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal );
  3622 	
  3623 	if (oldVal == 0 && iBody->iPagingDevice)
  3624 		{
  3625 //Kern::Printf("RCINC: NotifyBusy()");
  3626 		iBody->iPagingDevice->NotifyBusy();
  3627 		}
  3628 	}
  3629 
  3630 // RequestCountDec()
  3631 // 
  3632 // Counts the number of outstanding requests
  3633 // For data-paging media, calls DPagingDevice::NotifyIdle() when count reaches zero
  3634 //
  3635 void DPrimaryMediaBase::RequestCountDec()
  3636 	{
  3637 	__ASSERT_DEBUG(iBody, LOCM_FAULT());
  3638 	TInt oldVal = (TInt) __e32_atomic_add_ord32(&iBody->iRequestCount, (TUint) -1);
  3639 //Kern::Printf("RCDEC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal);
  3640 	
  3641 	OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTDEC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal );
  3642 	
  3643 	if (oldVal == 1 && iBody->iPagingDevice)
  3644 		{
  3645 //Kern::Printf("RCDEC: NotifyIdle()");
  3646 		iBody->iPagingDevice->NotifyIdle();
  3647 		}
  3648 	__ASSERT_DEBUG(iBody->iRequestCount >= 0, LOCM_FAULT());
  3649 	}
  3650 #endif	// __DEMAND_PAGING__
  3651 
  3652 TPartitionInfo::TPartitionInfo()
  3653 //
  3654 // Constructor
  3655 //
  3656 	{
  3657 	memclr(this, sizeof(TPartitionInfo));
  3658 	}
  3659 
  3660 #ifdef __DEMAND_PAGING__
  3661 
  3662 void pageInDfc(TAny* aPtr)
  3663 	{
  3664 	OstTraceFunctionEntry0( _PAGEINDFC_ENTRY );
  3665 	__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("pageInDfc"));
  3666 	DPrimaryMediaBase* primaryMedia=(DPrimaryMediaBase*)aPtr;
  3667 	__ASSERT_ALWAYS(primaryMedia && primaryMedia->iPagingMedia && primaryMedia->iBody->iPagingDevice,LOCM_FAULT());
  3668 	DMediaPagingDevice* pagingdevice=primaryMedia->iBody->iPagingDevice;
  3669 
  3670 	TLocDrvRequest* m = (TLocDrvRequest*) pagingdevice->iMainQ.iMessage;
  3671 	pagingdevice->iMainQ.iMessage = NULL;
  3672 
  3673 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3674 	if (!m)
  3675 		__e32_atomic_add_ord8(&pagingdevice->iROMStats.iTotalRunDry, 1);
  3676 #endif
  3677 
  3678 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3679 	TInt countROM=0;
  3680 	TInt countCode=0;
  3681 #endif
  3682 
  3683 	for ( ; m != NULL; m = (TLocDrvRequest*) pagingdevice->iMainQ.Poll())
  3684 		{
  3685 		__ASSERT_ALWAYS(DMediaPagingDevice::PagingRequest(*m), LOCM_FAULT());
  3686 
  3687 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3688 		(m->iValue == DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++);
  3689 #endif
  3690 		__KTRACE_OPT(KLOCDPAGING, Kern::Printf("pageInDfc: process request 0x%08x, last in queue 0x%08x",m, pagingdevice->iMainQ.Last()) );
  3691 		OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, PAGEINDFC2, "process request=0x%08x; last in queue=0x%08x",(TUint) m, (TUint) pagingdevice->iMainQ.Last());
  3692 
  3693 		primaryMedia->HandleMsg(*m);
  3694 		}
  3695 
  3696 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3697 	NKern::FMWait(&pagingdevice->iInstrumentationLock);
  3698 	if (pagingdevice->iROMStats.iMaxReqsInPending<countROM)
  3699 		pagingdevice->iROMStats.iMaxReqsInPending=countROM;
  3700 	if (pagingdevice->iCodeStats.iMaxReqsInPending<countCode)
  3701 		pagingdevice->iCodeStats.iMaxReqsInPending=countCode;
  3702 	NKern::FMSignal(&pagingdevice->iInstrumentationLock);
  3703 #endif
  3704 
  3705 	pagingdevice->iMainQ.Receive();	// allow reception of more messages
  3706 	OstTraceFunctionExit0( _PAGEINDFC_EXIT );
  3707 	}
  3708 
  3709 DMediaPagingDevice::DMediaPagingDevice(DPrimaryMediaBase* aPtr)
  3710 	:	iMainQ(pageInDfc, aPtr, NULL, KMaxDfcPriority),
  3711 		iDeferredQ(NULL, NULL, NULL, 0),			// callback never used
  3712 		iEmptyingQ(NULL),
  3713 		iInstrumentationLock()
  3714 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3715 		,iServicingROM(NULL), iServicingCode(NULL)
  3716 #endif
  3717 	{
  3718 	OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_CONSTRUCTOR_ENTRY, this );
  3719 	iPrimaryMedia = aPtr;
  3720 	if (iPrimaryMedia->iDfcQ)	// media driver has its own thread
  3721 		{
  3722 		iMainQ.SetDfcQ(iPrimaryMedia->iDfcQ);
  3723 		}
  3724 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3725 	memclr((TAny*)&iROMStats,sizeof(SMediaROMPagingConcurrencyInfo)+sizeof(SMediaCodePagingConcurrencyInfo));
  3726 #endif
  3727 #ifdef __DEMAND_PAGING_BENCHMARKS__
  3728 	iROMBenchmarkData.iCount=iROMBenchmarkData.iTotalTime=iROMBenchmarkData.iMaxTime=0;
  3729 	iROMBenchmarkData.iMinTime = KMaxTInt;
  3730 	iCodeBenchmarkData.iCount=iCodeBenchmarkData.iTotalTime=iCodeBenchmarkData.iMaxTime=0;
  3731 	iCodeBenchmarkData.iMinTime = KMaxTInt;
  3732 	iDataInBenchmarkData.iCount=iDataInBenchmarkData.iTotalTime=iDataInBenchmarkData.iMaxTime=0;
  3733 	iDataInBenchmarkData.iMinTime = KMaxTInt;
  3734 	iDataOutBenchmarkData.iCount=iDataOutBenchmarkData.iTotalTime=iDataOutBenchmarkData.iMaxTime=0;
  3735 	iDataOutBenchmarkData.iMinTime = KMaxTInt;
  3736 #endif
  3737 
  3738 	iMainQ.Receive();
  3739 	OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_CONSTRUCTOR_EXIT, this );
  3740 	}
  3741 
  3742 DMediaPagingDevice::~DMediaPagingDevice()
  3743 	{
  3744 OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_DESTRUCTOR_ENTRY, this );
  3745 
  3746 	if (iMountInfoDataLock)
  3747 		ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDataLock);
  3748 	
  3749 	if (iMountInfoDescHdrLock)
  3750 		ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDescHdrLock);
  3751 	
  3752 	if (iMountInfoDescLenLock)
  3753 		ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDescLenLock);
  3754 	OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_DESTRUCTOR_EXIT, this );
  3755 	}
  3756 
  3757 
  3758 void DMediaPagingDevice::SendToMainQueueDfcAndBlock(TThreadMessage* aMsg)
  3759 	{
  3760 	OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_SENDTOMAINQUEUEDFCANDBLOCK_ENTRY, this );
  3761 	__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("Send request 0x%08x to main queue",aMsg));
  3762 	__ASSERT_ALWAYS(aMsg->iState==TMessageBase::EFree,LOCM_FAULT());	// check that message was previously completed or never queued
  3763 
  3764 	// if drive supports DMA, turn on Physical memory flag & sync memory
  3765 	TLocDrvRequest& m=*(TLocDrvRequest*)(aMsg);
  3766 	
  3767 	TLinAddr addr = (TLinAddr) m.RemoteDes();
  3768 	TInt len = I64LOW(m.Length());
  3769 
  3770 	TBool needSyncAfterRead = EFalse;
  3771 	if (m.Drive()->iDmaHelper)
  3772 		{
  3773 		m.Flags() |= TLocDrvRequest::EPhysAddr;
  3774 		if (m.Id() == DLocalDrive::EWrite)
  3775 			{
  3776 			Cache::SyncMemoryBeforeDmaWrite(addr, len);
  3777 			}
  3778 		else
  3779 			{
  3780 			Cache::SyncMemoryBeforeDmaRead(addr, len);
  3781 			needSyncAfterRead = ETrue;
  3782 			}
  3783 		}
  3784 
  3785 	// Count the number of outstanding requests if this is the data-paging media, so that
  3786 	// we can call DPagingDevice::NotifyBusy() / DPagingDevice::NotifyIdle()
  3787 	if ((m.Flags() & TLocDrvRequest::EBackgroundPaging) == 0)
  3788 		iPrimaryMedia->RequestCountInc();
  3789 	
  3790 	aMsg->SendReceive(&iMainQ);
  3791 
  3792 #ifdef __DEMAND_PAGING__
  3793 	if ((m.Flags() & TLocDrvRequest::EBackgroundPaging) == 0)
  3794 		iPrimaryMedia->RequestCountDec();
  3795 #endif
  3796 
  3797 	if (needSyncAfterRead)
  3798 		{
  3799 		Cache::SyncMemoryAfterDmaRead(addr, len);
  3800 		}
  3801 
  3802 	
  3803 	// come back here when request is completed
  3804 	__ASSERT_DEBUG(aMsg->iState==TMessageBase::EFree,LOCM_FAULT());		// check message has been completed
  3805 	OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_SENDTOMAINQUEUEDFCANDBLOCK_EXIT, this );
  3806 	}
  3807 
  3808 void DMediaPagingDevice::SendToDeferredQ(TThreadMessage* aMsg)
  3809 	{
  3810 	OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_SENDTODEFERREDQ_ENTRY, this );
  3811 	// This queue is only accessed from MD thread
  3812 	__ASSERT_ALWAYS(aMsg->iState==TMessageBase::EAccepted,LOCM_FAULT());	// check that message was previously dequeued
  3813 #ifdef BTRACE_PAGING_MEDIA
  3814 	if(iEmptyingQ&DMediaPagingDevice::EDeferredQ)		// already deferring
  3815 		BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInReDeferred,aMsg,aMsg->iValue);
  3816 	else
  3817 		BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInDeferred,aMsg,aMsg->iValue);
  3818 #endif
  3819 
  3820 	aMsg->Forward(&iDeferredQ, EFalse);
  3821 	OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_SENDTODEFERREDQ_EXIT, this );
  3822 	}
  3823 
  3824 
  3825 void DMediaPagingDevice::CompleteRequest(TThreadMessage* aMsg, TInt aResult)
  3826 	{
  3827 	OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_COMPLETEREQUEST_ENTRY, this );
  3828 	__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::CompleteRequest, request 0x%08x result %d", aMsg, aResult));
  3829 	__ASSERT_DEBUG(aMsg->iState==TMessageBase::EAccepted,LOCM_FAULT());
  3830 
  3831 #ifdef BTRACE_PAGING_MEDIA
  3832 	BTraceContext12(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInPagedIn,aMsg,aResult,aMsg->iValue);
  3833 #endif
  3834 
  3835 	iPrimaryMedia->CompleteRequest(*((TLocDrvRequest*) aMsg), aResult);
  3836 	OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_COMPLETEREQUEST_EXIT, this );
  3837 	}
  3838 
  3839 TInt DMediaPagingDevice::Read(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt aDrvNumber)
  3840 	{
  3841 	OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_READ_ENTRY, this );
  3842 	__ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT());	// that would lock up the system, thus better die now
  3843 	__ASSERT_ALWAYS(aReq,LOCM_FAULT());
  3844 	__ASSERT_CRITICAL
  3845 
  3846 #ifdef __DEMAND_PAGING_BENCHMARKS__
  3847 	TUint32 bmStart = NKern::FastCounter();
  3848 #endif
  3849 
  3850 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  3851 	TUint8* servicingCount;
  3852 	NKern::FMWait(&iInstrumentationLock);
  3853 	if(aDrvNumber == EDriveRomPaging)	// ROM paging
  3854 		{
  3855 		servicingCount = &iServicingROM;
  3856 		if(iServicingROM)
  3857 			iROMStats.iTotalConcurrentReqs++;
  3858 		if(!(++iServicingROM))
  3859 			{
  3860 			iServicingROM=1;					// overflow...
  3861 			iROMStats.iTotalConcurrentReqs=0;	// ...reset this
  3862 			}
  3863 		TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
  3864 		if(!empty)
  3865 			iROMStats.iTotalReqIssuedNonEmptyQ++;
  3866 		}
  3867 	else if (aDrvNumber == EDriveDataPaging)	// Data paging
  3868 		{
  3869 		servicingCount = &iServicingDataIn;
  3870 		if(iServicingDataIn)
  3871 			iDataStats.iTotalConcurrentReqs++;
  3872 		if(!(++iServicingDataIn))
  3873 			{
  3874 			iServicingDataIn=1;					// overflow...
  3875 			iDataStats.iTotalConcurrentReqs=0;	// ...reset this
  3876 			}
  3877 		TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
  3878 		if(!empty)
  3879 			iDataStats.iTotalReqIssuedNonEmptyQ++;
  3880 		}
  3881 	else
  3882 		{
  3883 		servicingCount = &iServicingCode;
  3884 		if(iServicingCode)
  3885 			iCodeStats.iTotalConcurrentReqs++;
  3886 		if(!(++iServicingCode))
  3887 			{
  3888 			iServicingCode=1;					// overflow...
  3889 			iCodeStats.iTotalConcurrentReqs=0;	// ...reset this
  3890 			}
  3891 		TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
  3892 		if(!empty)
  3893 			iCodeStats.iTotalReqIssuedNonEmptyQ++;
  3894 		}
  3895 	NKern::FMSignal(&iInstrumentationLock);
  3896 #endif
  3897 
  3898 	TUint offset=aOffset<<iReadUnitShift;
  3899 	TUint size=aSize<<iReadUnitShift;
  3900 
  3901 #ifdef BTRACE_PAGING_MEDIA
  3902 	TInt buf[3];
  3903 	buf[0]=size;		// page in request length
  3904 	buf[1]=aDrvNumber;	// local drive number (-1 if ROM)
  3905 	buf[2]=(TInt)aReq;	// address of request object
  3906 	BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInBegin,aBuffer,offset,buf,sizeof(buf));
  3907 #endif
  3908 
  3909 	__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::Read, Req(0x%08x), Buff(0x%x),Offset(%d),Size(%d),DrvNo(%d)",aReq,aBuffer,offset,size,aDrvNumber));
  3910 	OstTraceDefExt5(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_READ1, "req=0x%08x; aBuffer=0x%x; offset=%d; size=%d; aDrvNumber=%d", (TUint) aReq, (TInt) aBuffer, (TInt) offset, (TUint) size, (TUint) aDrvNumber);
  3911 	
  3912 	// no DFCQ, media driver executes in the context of calling thread
  3913 	if (!iPrimaryMedia->iDfcQ)
  3914 		{
  3915 		LOCM_FAULT();		// don't allow paging
  3916 		OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_READ_EXIT, this, KErrNone );
  3917 		return KErrNone;	// keep compiler happy
  3918 		}
  3919 
  3920 
  3921 	TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
  3922 	
  3923 
  3924 #ifdef __DEMAND_PAGING_BENCHMARKS__
  3925 	SPagingBenchmarkInfo* info = NULL;
  3926 #endif
  3927 
  3928 
  3929 	// Read from the media and allow for retries in the unlikely event of an error.
  3930 	const TInt KPageInRetries = 5;
  3931 	TInt retVal = KErrGeneral;
  3932 	for (TInt i=0; retVal != KErrNone && i < KPageInRetries; i++)
  3933 		{
  3934 		m.Flags() = TLocDrvRequest::EPaging;
  3935 		TLocDrv* pL=NULL;
  3936 		if(aDrvNumber == EDriveRomPaging)					// ROM paging
  3937 			{
  3938 			m.Id() = DMediaPagingDevice::ERomPageInRequest;
  3939 			if (iRomPagingDriveNumber == KErrNotFound)
  3940 			    {
  3941 			    // ROM partition has not been reported by the media driver
  3942 			    // it is assumed that the media driver will adjust the request accordingly
  3943 			    m.Flags() |= TLocDrvRequest::EAdjusted;
  3944 				// Use a media drive number so the request reaches the correct media...
  3945 				m.Drive() = TheDrives[iFirstLocalDriveNumber];
  3946 			    }
  3947 			else
  3948 			    {
  3949 			    //ROM partition has been reported
  3950 			    //Set drive for use with CheckAndAdjustForPartition
  3951                 m.Drive() = TheDrives[iRomPagingDriveNumber];
  3952 			    }
  3953 #ifdef __DEMAND_PAGING_BENCHMARKS__
  3954 			__e32_atomic_add_ord32(&iMediaPagingInfo.iRomPageInCount, (TUint) 1);
  3955 			info = &iROMBenchmarkData;
  3956 #endif
  3957 			}
  3958 		else if(aDrvNumber == EDriveDataPaging)				// Data paging
  3959 			{
  3960 			m.Id() = DLocalDrive::ERead;
  3961 			m.Flags() |= TLocDrvRequest::EDataPaging;
  3962 			m.Drive() = TheDrives[iDataPagingDriveNumber];
  3963 #ifdef __DEMAND_PAGING_BENCHMARKS__
  3964 			__e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageInCount, (TUint) 1);
  3965 			info = &iDataInBenchmarkData;
  3966 #endif
  3967 			}
  3968 		else if ((aDrvNumber >=0) && (aDrvNumber<KMaxLocalDrives))	// Code paging
  3969 			{
  3970 			m.Id() = DMediaPagingDevice::ECodePageInRequest;
  3971 			m.Flags() |= TLocDrvRequest::ECodePaging;
  3972 			pL=TheDrives[aDrvNumber];
  3973 			__ASSERT_DEBUG(pL&&(pL->iPrimaryMedia==iPrimaryMedia),LOCM_FAULT());	// valid drive number?
  3974 			m.Drive()=pL;
  3975 #ifdef __DEMAND_PAGING_BENCHMARKS__
  3976 			__e32_atomic_add_ord32(&iMediaPagingInfo.iCodePageInCount, (TUint) 1);
  3977 			info = &iCodeBenchmarkData;
  3978 #endif
  3979 			}
  3980 		else
  3981 			LOCM_FAULT(); // invalid drive number
  3982 
  3983 		m.RemoteThread()=NULL;
  3984 		m.Pos()=offset;
  3985 		m.Length()=Int64(size);
  3986 		m.RemoteDes()=(TAny*)aBuffer;
  3987 		m.RemoteDesOffset()=0;		// pre-aligned
  3988 		m.DriverFlags()=0;
  3989 		__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("ReqId=%d, Pos=0x%lx, Len=0x%lx, remote Des 0x%x",m.Id(),m.Pos(),m.Length(),m.RemoteDes()));
  3990 		OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_READ2, "reqId=%d; position=0x%lx; length=0x%x; remote Des=0x%x", (TInt) m.Id(), (TUint) m.Pos(), (TUint) m.Length(), (TUint) m.RemoteDes());
  3991 		
  3992 		__ASSERT_DEBUG(iPrimaryMedia->iBody, LOCM_FAULT());
  3993 		TInt mediaChanges = iPrimaryMedia->iBody->iMediaChanges;
  3994 
  3995 		SendToMainQueueDfcAndBlock(&m);		// queues request, sets and opens client thread, queues dfc and blocks thread until request is completed
  3996 		retVal = m.iValue;
  3997 
  3998 #ifdef __DEBUG_DEMAND_PAGING__
  3999 		if (retVal != KErrNone)
  4000 		    {
  4001 			Kern::Printf("Pagin Failure %d, retry %d", retVal, i);
  4002 		    }
  4003 #endif
  4004 
  4005 		// reset retry count if there's ben a media change
  4006 		if (retVal != KErrNone && mediaChanges != iPrimaryMedia->iBody->iMediaChanges)
  4007 			i = 0;
  4008 		}	// for ()
  4009 
  4010 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  4011 	NKern::FMWait(&iInstrumentationLock);
  4012 	if (*servicingCount)
  4013 		(*servicingCount)--;
  4014 	NKern::FMSignal(&iInstrumentationLock);
  4015 #endif
  4016 
  4017 #ifdef __DEMAND_PAGING_BENCHMARKS__
  4018 	TUint32 bmEnd = NKern::FastCounter();
  4019 	++info->iCount;
  4020 #if !defined(HIGHIGH_RES_TIMER) || defined(HIGH_RES_TIMER_COUNTS_UP)
  4021 	TInt64 elapsed=bmEnd-bmStart;
  4022 #else
  4023 	TInt64 elapsed=bmStart-bmEnd;
  4024 #endif
  4025 	info->iTotalTime += elapsed;
  4026 	if (elapsed > info->iMaxTime)
  4027 		info->iMaxTime = elapsed;
  4028 	if (elapsed < info->iMinTime)
  4029 		info->iMinTime = elapsed;
  4030 #endif // __DEMAND_PAGING_BENCHMARKS__
  4031 	OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_READ_EXIT2, this, retVal );
  4032 	return retVal;
  4033 	}
  4034 
  4035 TInt DMediaPagingDevice::Write(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TBool aBackground)
  4036 	{
  4037 	OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_WRITE_ENTRY, this );
  4038 	__ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT());	// that would lock up the system, thus better die now
  4039 	__ASSERT_ALWAYS(aReq,LOCM_FAULT());
  4040 	__ASSERT_CRITICAL
  4041 
  4042 #ifdef __DEMAND_PAGING_BENCHMARKS__
  4043 	TUint32 bmStart = NKern::FastCounter();
  4044 #endif
  4045 
  4046 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  4047 	NKern::FMWait(&iInstrumentationLock);
  4048 	if(iServicingDataOut)
  4049 		iDataStats.iTotalConcurrentReqs++;
  4050 	if(!(++iServicingDataOut))
  4051 		{
  4052 		iServicingDataOut=1;				// overflow...
  4053 		iDataStats.iTotalConcurrentReqs=0;	// ...reset this
  4054 		}
  4055 	TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
  4056 	if(!empty)
  4057 		iDataStats.iTotalReqIssuedNonEmptyQ++;
  4058 	NKern::FMSignal(&iInstrumentationLock);
  4059 #endif
  4060 
  4061 	TUint offset=aOffset<<iReadUnitShift;
  4062 	TUint size=aSize<<iReadUnitShift;
  4063 
  4064 #ifdef BTRACE_PAGING_MEDIA
  4065 	TInt buf[2];
  4066 	buf[0] = size;				// page out request length
  4067 	buf[1] = (TInt)aReq;		// address of request object
  4068 	BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageOutBegin,aBuffer,offset,buf,sizeof(buf));
  4069 #endif
  4070 
  4071 	__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::Write, Req(0x%08x), Buff(0x%x),Offset(%d),Size(%d)",aReq,aBuffer,offset,size));
  4072 	OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_WRITE1, "req=0x%08x; aBuffer=0x%x; offset=%d; size=%d", (TUint) aReq, (TUint) aBuffer, offset, size);
  4073 	
  4074 	// no DFCQ, media driver executes in the context of calling thread
  4075 	if (!iPrimaryMedia->iDfcQ)
  4076 		{
  4077 		LOCM_FAULT();		// don't allow paging
  4078 		OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_WRITE_EXIT, this, KErrNone );
  4079 		return KErrNone;	// keep compiler happy
  4080 		}
  4081 
  4082 
  4083 	TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
  4084 	
  4085 #ifdef __DEMAND_PAGING_BENCHMARKS__
  4086 	__e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageOutCount, (TUint) 1);
  4087 	if (aBackground)
  4088 		__e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageOutBackgroundCount, (TUint) 1);
  4089 #endif
  4090 
  4091 	// Write to the media and allow for retries in the unlikely event of an error.
  4092 	const TInt KPageOutRetries = 5;
  4093 	TInt retVal = KErrGeneral;
  4094 	for (TInt i=0; retVal != KErrNone && i < KPageOutRetries; i++)
  4095 		{
  4096 		m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging | (aBackground ? TLocDrvRequest::EBackgroundPaging : 0);
  4097 
  4098 		m.Id() = DLocalDrive::EWrite;
  4099 		m.Drive() = TheDrives[iDataPagingDriveNumber];
  4100 
  4101 		m.RemoteThread()=NULL;
  4102 		m.Pos()=offset;
  4103 		m.Length()=Int64(size);
  4104 		m.RemoteDes()=(TAny*)aBuffer;
  4105 		m.RemoteDesOffset()=0;		// pre-aligned
  4106 		m.DriverFlags()=0;
  4107 		__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("ReqId=%d, Pos=0x%lx, Len=0x%lx, remote Des 0x%x",m.Id(),m.Pos(),m.Length(),m.RemoteDes()));
  4108 		OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_WRITE2, "reqId=%d; position=0x%lx; length=0x%lx; remote Des=0x%x", (TInt) m.Id(), (TUint) m.Pos(), (TUint) m.Length(), (TUint) m.RemoteDes());
  4109 		
  4110 		__ASSERT_DEBUG(iPrimaryMedia->iBody, LOCM_FAULT());
  4111 		TInt mediaChanges = iPrimaryMedia->iBody->iMediaChanges;
  4112 
  4113 		SendToMainQueueDfcAndBlock(&m);		// queues request, sets and opens client thread, queues dfc and blocks thread until request is completed
  4114 		
  4115 		retVal = m.iValue;
  4116 
  4117 #ifdef __DEBUG_DEMAND_PAGING__
  4118 		if (retVal != KErrNone)
  4119 			Kern::Printf("Pagout Failure %d, retry %d", retVal, i);
  4120 #endif
  4121 		// reset retry count if there's ben a media change
  4122 		if (retVal != KErrNone && mediaChanges != iPrimaryMedia->iBody->iMediaChanges)
  4123 			i = 0;
  4124 		}	// for ()
  4125 
  4126 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
  4127 	NKern::FMWait(&iInstrumentationLock);
  4128 	if (iServicingDataOut)
  4129 		iServicingDataOut--;
  4130 	NKern::FMSignal(&iInstrumentationLock);
  4131 #endif
  4132 
  4133 #ifdef __DEMAND_PAGING_BENCHMARKS__
  4134 	SPagingBenchmarkInfo& info = iDataOutBenchmarkData;
  4135 	TUint32 bmEnd = NKern::FastCounter();
  4136 	++info.iCount;
  4137 #if !defined(HIGHIGH_RES_TIMER) || defined(HIGH_RES_TIMER_COUNTS_UP)
  4138 	TInt64 elapsed=bmEnd-bmStart;
  4139 #else
  4140 	TInt64 elapsed=bmStart-bmEnd;
  4141 #endif
  4142 	info.iTotalTime += elapsed;
  4143 	if (elapsed > info.iMaxTime)
  4144 		info.iMaxTime = elapsed;
  4145 	if (elapsed < info.iMinTime)
  4146 		info.iMinTime = elapsed;
  4147 #endif // __DEMAND_PAGING_BENCHMARKS__
  4148 	
  4149 	OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_WRITE_EXIT2, this, retVal );
  4150 	return retVal;
  4151 	}
  4152 
  4153 
  4154 TInt DMediaPagingDevice::DeleteNotify(TThreadMessage* aReq,TUint aOffset,TUint aSize)
  4155 	{
  4156 	OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DELETENOTIFY_ENTRY, this );
  4157 	if (iDeleteNotifyNotSupported)
  4158 	    {
  4159 		OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT1, this, KErrNotSupported );
  4160 		return KErrNotSupported;
  4161 	    }
  4162 
  4163 	__ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT());	// that would lock up the system, thus better die now
  4164 	__ASSERT_ALWAYS(aReq,LOCM_FAULT());
  4165 	__ASSERT_ALWAYS(DataPagingDfcQ(iPrimaryMedia),LOCM_FAULT());
  4166 	__ASSERT_CRITICAL
  4167 
  4168 	TUint offset = aOffset<<iReadUnitShift;
  4169 	TUint size = aSize<<iReadUnitShift;
  4170 
  4171 #ifdef BTRACE_PAGING_MEDIA
  4172 	TInt buf[2];
  4173 	buf[0] = size;		// delete notify length
  4174 	buf[1] = (TInt)aReq;	// address of request object
  4175 	BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedDeleteNotifyBegin,NULL,offset,buf,sizeof(buf));
  4176 #endif
  4177 
  4178 	__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::Write, Req(0x%08x), Offset(%d),Size(%d)",aReq,offset,size));
  4179 	OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_DELETENOTIFY1 , "req=0x%08x; offset=%d; size=%d", (TUint) aReq, offset, size);
  4180 	
  4181 	// no DFCQ, media driver executes in the context of calling thread
  4182 	if (!iPrimaryMedia->iDfcQ)
  4183 		{
  4184 		LOCM_FAULT();		// don't allow paging
  4185 		OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT2, this, KErrNone );
  4186 		return KErrNone;	// keep compiler happy
  4187 		}
  4188 
  4189 	TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
  4190 
  4191 
  4192 	m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging;
  4193 	m.Id() = DLocalDrive::EDeleteNotify;
  4194 	m.Drive() = TheDrives[iDataPagingDriveNumber];
  4195 
  4196 	m.RemoteThread() = NULL;
  4197 	m.Pos() = offset;
  4198 	m.Length() = Int64(size);
  4199 	m.RemoteDes() = NULL;
  4200 	m.RemoteDesOffset() = 0;		// pre-aligned
  4201 	m.DriverFlags()=0;
  4202 	__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("ReqId=%d, Pos=0x%lx, Len=0x%lx, remote Des 0x%x",m.Id(),m.Pos(),m.Length(),m.RemoteDes()));
  4203 	OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_DELETENOTIFY2 , "reqId=%d; position=0x%lx; length=0x%lx; remote Des=0x%x", m.Id(), m.Pos(), m.Length(), (TUint) m.RemoteDes());
  4204 
  4205 	// send request aynchronously as we don't particularly care about the result 
  4206 	// and waiting would slow down the thread taking the page fault
  4207 	iPrimaryMedia->RequestCountInc();
  4208 
  4209 	m.SendReceive(&iMainQ);	// send  request synchronously
  4210 
  4211 #ifdef __DEMAND_PAGING__
  4212 	iPrimaryMedia->RequestCountDec();
  4213 #endif
  4214 
  4215 	TInt retVal = m.iValue;
  4216 
  4217 	if (retVal == KErrNotSupported)
  4218 		iDeleteNotifyNotSupported = ETrue;
  4219 
  4220 	OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT3, this, retVal );
  4221 	return retVal;
  4222 	}
  4223 
  4224 
  4225 
  4226 EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* aSrc, TInt aSize, TInt anOffset)
  4227 	{
  4228 	OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITETOPAGEHANDLER_ENTRY, this );
  4229 #ifdef BTRACE_PAGING_MEDIA
  4230 	TMediaDevice medDev=Drive()->iMedia->iDevice;
  4231 	TInt buf[3];
  4232 	buf[0]=(TUint32)RemoteDes();
  4233 	buf[1]=anOffset;
  4234 	buf[2]=aSize;
  4235 	BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaMedDrvWriteBack,medDev,this,buf,sizeof(buf));
  4236 #endif
  4237 	__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("TLocDrvRequest::WriteToPageHandler, memcpy((aTrg)%08x, (aSrc)%08x, (aLength)%08x)",(TUint32)RemoteDes()+anOffset,aSrc,aSize));
  4238 	(void)memcpy((TAny*)((TUint32)RemoteDes()+anOffset), aSrc, aSize);	// maybe in later versions this could be something else
  4239 	OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITETOPAGEHANDLER_EXIT, this, KErrNone );
  4240 	return KErrNone;
  4241 	}
  4242 
  4243 EXPORT_C TInt TLocDrvRequest::ReadFromPageHandler(TAny* aDst, TInt aSize, TInt anOffset)
  4244 	{
  4245 	OstTraceFunctionEntry1( TLOCDRVREQUEST_READFROMPAGEHANDLER_ENTRY, this );
  4246 #ifdef BTRACE_PAGING_MEDIA
  4247 	TMediaDevice medDev=Drive()->iMedia->iDevice;
  4248 	TInt buf[3];
  4249 	buf[0]=(TUint32)RemoteDes();
  4250 	buf[1]=anOffset;
  4251 	buf[2]=aSize;
  4252 	BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaMedDrvRead,medDev,this,buf,sizeof(buf));
  4253 #endif
  4254 	__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("TLocDrvRequest::ReadFromPageHandler, memcpy((aDst)%08x, (aTrg)%08x, (aLength)%08x)",aDst,(TUint32)RemoteDes()+anOffset,aSize));
  4255 	(void)memcpy(aDst, (TAny*)((TUint32)RemoteDes()+anOffset), aSize);	// maybe in later versions this could be something else
  4256 	OstTraceFunctionExitExt( TLOCDRVREQUEST_READFROMPAGEHANDLER_EXIT, this, KErrNone );
  4257 	return KErrNone;
  4258 	}
  4259 
  4260 _LIT(KLitFragmentationMutexName, "FRAGMENTATION_MUTEX");
  4261 
  4262 TInt DFragmentationPagingLock::Construct(TUint aNumPages)
  4263 	{
  4264 	OstTraceFunctionEntryExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_ENTRY, this );
  4265 	TInt r=KErrNone;
  4266 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation Lock: creating Mutex"));
  4267 	r=Kern::MutexCreate(this->iFragmentationMutex, KLitFragmentationMutexName, KMutexOrdNone);
  4268 	if (r!=KErrNone)
  4269 	    {
  4270 		OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT1, this, r );
  4271 		return r;
  4272 	    }
  4273 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation Lock: Mutex created OK"));
  4274 	OstTraceDef0(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DFRAGMENTATIONPAGINGLOCK_CONSTRUCT1 , "Fragmentation Lock: Mutex created OK");
  4275 
  4276 	iFragmentGranularity = 0;
  4277 	if (aNumPages == 0)
  4278 	    {
  4279 		OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT2, this, KErrNone );
  4280 		return KErrNone;
  4281 	    }
  4282 	
  4283 	// in CS
  4284 	TInt pageSize=Kern::RoundToPageSize(1);
  4285 	LockFragmentation();
  4286 	r=Alloc(pageSize*aNumPages);	// alloc pages
  4287 	UnlockFragmentation();
  4288 
  4289 	if(r==KErrNone)
  4290 		{
  4291 		iFragmentGranularity = pageSize * aNumPages;
  4292 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation granularity set to 0x%x", iFragmentGranularity));
  4293 		OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DFRAGMENTATIONPAGINGLOCK_CONSTRUCT2, "Fragmentation granularity=0x%x", iFragmentGranularity);
  4294 		}
  4295 
  4296 	OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT3, this, r );
  4297 	return r;
  4298 	}
  4299 
  4300 void DFragmentationPagingLock::Cleanup()
  4301 	{
  4302 	OstTraceFunctionEntry1( DFRAGMENTATIONPAGINGLOCK_CLEANUP_ENTRY, this );
  4303 	// in CS
  4304 	if (iFragmentationMutex)
  4305 		{
  4306 		LockFragmentation();
  4307 		Free();					// at last!
  4308 		UnlockFragmentation();
  4309 		Kern::SafeClose((DObject*&)iFragmentationMutex,NULL);
  4310 		}
  4311 	OstTraceFunctionExit1( DFRAGMENTATIONPAGINGLOCK_CLEANUP_EXIT, this );
  4312 	}
  4313 
  4314 #else
  4315 #if !defined(__WINS__)
  4316 EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* , TInt , TInt)
  4317 	{
  4318 	return KErrNone;		// stub for def file
  4319 	}
  4320 #endif // __WINS__
  4321 #endif //__DEMAND_PAGING__
  4322 /********************************************
  4323  * Media driver base class
  4324  ********************************************/
  4325  
  4326  
  4327  
  4328  
  4329 /**
  4330 Constructor.
  4331 
  4332 This is called, typically, by a derived class constructor in its ctor list.
  4333 
  4334 @param aMediaId The value of the unique media ID assigned when the media
  4335                 driver is registered.
  4336                 
  4337 @see LocDrv::RegisterMediaDevice()                
  4338 */
  4339 EXPORT_C DMediaDriver::DMediaDriver(TInt aMediaId)
  4340 	{
  4341 	OstTraceFunctionEntryExt( DMEDIADRIVER_DMEDIADRIVER_ENTRY, this );
  4342 	
  4343 //	iPhysicalDevice=NULL;
  4344 //	iTotalSizeInBytes=0;
  4345 //	iCurrentConsumption=0;
  4346 //	iPrimaryMedia=NULL;
  4347 //	iCritical=EFalse;
  4348 	iPrimaryMedia=(DPrimaryMediaBase*)TheMedia[aMediaId];
  4349 	OstTraceFunctionExit1( DMEDIADRIVER_DMEDIADRIVER_EXIT, this );
  4350 	}
  4351 
  4352 
  4353 
  4354 
  4355 /**
  4356 Destructor.
  4357 
  4358 Sets the device's current consumption to zero, and calls Close() on
  4359 the PDD factory object.
  4360 
  4361 @see DObject::Close()
  4362 */
  4363 EXPORT_C DMediaDriver::~DMediaDriver()
  4364 	{
  4365 	OstTraceFunctionEntry1( DMEDIADRIVER_DMEDIADRIVER_DESTRUCTOR_ENTRY, this );
  4366 	SetCurrentConsumption(0);
  4367 	Kern::SafeClose((DObject*&)iPhysicalDevice,NULL);
  4368 	OstTraceFunctionExit1( DMEDIADRIVER_DMEDIADRIVER_DESTRUCTOR_EXIT, this );
  4369 	}
  4370 
  4371 
  4372 
  4373 
  4374 /**
  4375 Closes the media driver.
  4376 
  4377 This default implementation simply deletes this DMediaDriver object.
  4378 
  4379 Media drivers can provide their own implementation, which gives them
  4380 the opportunity to clean up resources before closure; for example,
  4381 cancelling a DFC.
  4382 Any replacement function must call this base class function as
  4383 the last instruction. 
  4384 */
  4385 EXPORT_C void DMediaDriver::Close()
  4386 	{
  4387 	delete this;
  4388 	}
  4389 
  4390 
  4391 
  4392 
  4393 /**
  4394 Sets the total size of the media device.
  4395 
  4396 The function must be called by the media driver's implementation of PartitionInfo().
  4397 
  4398 @param aTotalSizeInBytes The total size of the media, in bytes.
  4399 @param aLocDrv           This is not used by media drivers; the class
  4400                          definition provides a default value.
  4401 
  4402 @see DMediaDriver::PartitionInfo()
  4403 */
  4404 EXPORT_C void DMediaDriver::SetTotalSizeInBytes(Int64 aTotalSizeInBytes, TLocDrv* aLocDrv)
  4405 	{
  4406 	OstTraceFunctionEntry1( DMEDIADRIVER_SETTOTALSIZEINBYTES_ENTRY, this );
  4407 	iTotalSizeInBytes=aTotalSizeInBytes;
  4408 	if (aLocDrv)
  4409 		aLocDrv->iPartitionLen=aTotalSizeInBytes;
  4410 	OstTraceFunctionExit1( DMEDIADRIVER_SETTOTALSIZEINBYTES_EXIT, this );
  4411 	}
  4412 
  4413 
  4414 
  4415 
  4416 /**
  4417 Gets the total size of the media.
  4418 
  4419 @return The total size of the media, in bytes.
  4420 
  4421 @see DMediaDriver::SetTotalSizeInBytes()
  4422 */
  4423 EXPORT_C Int64 DMediaDriver::TotalSizeInBytes()
  4424 	{
  4425 	return iTotalSizeInBytes;
  4426 	}
  4427 
  4428 
  4429 
  4430 
  4431 /**
  4432 Flags the media driver as entering a critical part of its processing.
  4433 
  4434 In this context, critical means that the driver must be allowed to complete
  4435 its current activity.
  4436 For example, a request to power down the device must be deferred until
  4437 the driver exits the critical part.
  4438 
  4439 @return KErrNone, if the driver has been successfully flagged as being in
  4440         a critical part; otherwise, one of the other system-wide error codes.
  4441         
  4442 @see DMediaDriver::EndInCritical()
  4443 */
  4444 EXPORT_C TInt DMediaDriver::InCritical()
  4445 	{
  4446 	OstTraceFunctionEntry1( DMEDIADRIVER_INCRITICAL_ENTRY, this );
  4447 	if (!iCritical)
  4448 		{
  4449 		TInt r=iPrimaryMedia->InCritical();
  4450 		if (r!=KErrNone)
  4451 		    {
  4452 			OstTraceFunctionExitExt( DMEDIADRIVER_INCRITICAL_EXIT, this, r );
  4453 			return r;
  4454 		    }
  4455 		iCritical=ETrue;
  4456 		}
  4457 	OstTraceFunctionExitExt( DMEDIADRIVER_INCRITICAL_EXIT2, this, KErrNone );
  4458 	return KErrNone;
  4459 	}
  4460 
  4461 
  4462 
  4463 
  4464 /**
  4465 Flags the media driver as leaving a critical part of its processing.
  4466 
  4467 @see DMediaDriver::InCritical()
  4468 */
  4469 EXPORT_C void DMediaDriver::EndInCritical()
  4470 	{
  4471 	OstTraceFunctionEntry1( DMEDIADRIVER_ENDINCRITICAL_ENTRY, this );
  4472 	if (iCritical)
  4473 		{
  4474 		iCritical=EFalse;
  4475 		iPrimaryMedia->EndInCritical();
  4476 		}
  4477 	OstTraceFunctionExit1( DMEDIADRIVER_ENDINCRITICAL_EXIT, this );
  4478 	}
  4479 
  4480 
  4481 
  4482 
  4483 /**
  4484 @internalComponent
  4485 */
  4486 EXPORT_C void DMediaDriver::SetCurrentConsumption(TInt aValue)
  4487 	{
  4488 	OstTraceFunctionEntryExt( DMEDIADRIVER_SETCURRENTCONSUMPTION_ENTRY, this );
  4489 	TInt old = (TInt)__e32_atomic_swp_ord32(&iCurrentConsumption, aValue);
  4490 	TInt delta = aValue - old;
  4491 	iPrimaryMedia->DeltaCurrentConsumption(delta);
  4492 	OstTraceFunctionExit1( DMEDIADRIVER_SETCURRENTCONSUMPTION_EXIT, this );
  4493 	}
  4494 
  4495 
  4496 
  4497 
  4498 /**
  4499 Informs the media driver subsystem that an asynchronous request is complete.
  4500 
  4501 @param m       The request that this call is completing.
  4502 @param aResult The return code for the asynchronous request. Typically, this
  4503                is KErrNone to report success, or one of the other system-wide
  4504                error codes to report failure or other problems.
  4505 */
  4506 EXPORT_C void DMediaDriver::Complete(TLocDrvRequest& m, TInt aResult)
  4507 	{
  4508 	OstTraceExt2( TRACE_FLOW, DMEDIADRIVER_COMPLETE_ENTRY, "m=%x;aResult=%d", (TUint) &m, aResult );
  4509 	CHECK_RET(aResult);
  4510 #ifdef __DEMAND_PAGING__
  4511 	if (DMediaPagingDevice::PagingRequest(m))
  4512 		{
  4513 		__ASSERT_ALWAYS(iPrimaryMedia && iPrimaryMedia->iPagingMedia && iPrimaryMedia->iBody->iPagingDevice,LOCM_FAULT());
  4514 		__ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
  4515 		DMediaPagingDevice* pagingdevice = iPrimaryMedia->iBody->iPagingDevice;
  4516 		pagingdevice->CompleteRequest(&m, aResult);
  4517 		}
  4518 	else
  4519 #endif
  4520 	iPrimaryMedia->CompleteRequest(m, aResult);
  4521 	
  4522 	if (&m == iPrimaryMedia->iCurrentReq)	// Complete() called on request serviced synchronously
  4523 		iPrimaryMedia->iCurrentReq = NULL;
  4524 
  4525 	iPrimaryMedia->RunDeferred();
  4526 	OstTraceFunctionExit1( DMEDIADRIVER_COMPLETE_EXIT, this );
  4527 	}
  4528 
  4529 
  4530 
  4531  
  4532 /**
  4533 Informs the media driver subsystem that the media driver is open
  4534 and has been initialised.
  4535 
  4536 This can be called from the PDD factory function Create(), if opening and
  4537 initialising the media driver is synchronous, otherwise it should be called by
  4538 the asynchronous media driver function that is responsible for opening and
  4539 initialising the driver.
  4540 
  4541 @param anError KErrNone if successful, otherwise one of the other system wide
  4542        error codes.
  4543 */
  4544 EXPORT_C void DMediaDriver::OpenMediaDriverComplete(TInt anError)
  4545 	{
  4546 	OstTraceFunctionEntry1( DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE_ENTRY, this );
  4547 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DMediaDriver::OpenMediaDriverComplete(%d) this %x iPrimaryMedia %x", anError, this, iPrimaryMedia));
  4548 	OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE, "anError %d this 0x%x iPrimaryMedia 0x%x", anError, (TUint) this, (TUint) iPrimaryMedia);
  4549 	DPrimaryMediaBase* pM=iPrimaryMedia;
  4550 	pM->iAsyncErrorCode=anError;
  4551 	pM->iAsyncDfc.Enque();
  4552 	OstTraceFunctionExit1( DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE_EXIT, this );
  4553 	}
  4554 
  4555 
  4556 
  4557 
  4558 /**
  4559 Informs the media driver subsystem that the media driver has completed
  4560 the provision of partition information.
  4561 
  4562 The media driver provides partition information in its implementation
  4563 of PartitionInfo().
  4564 
  4565 @param anError KErrNone if successful, otherwise one of the other system wide
  4566        error codes.
  4567 
  4568 @see DMediaDriver::PartitionInfo()
  4569 */
  4570 EXPORT_C void DMediaDriver::PartitionInfoComplete(TInt anError)
  4571 	{
  4572 	OstTraceFunctionEntry1( DMEDIADRIVER_PARTITIONINFOCOMPLETE_ENTRY, this );
  4573 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DMediaDriver::PartitionInfoComplete(%d) anError %d this %x iPrimaryMedia %x", anError, this, iPrimaryMedia));
  4574 	OstTraceExt3( TRACE_INTERNALS, DMDEDIADRIVER_PARTITIONINFOCOMPLETE, "anError=%d; this=%x; iPrimaryMedia=%x", anError, (TUint) this, (TUint) iPrimaryMedia );
  4575 	DPrimaryMediaBase* pM=iPrimaryMedia;
  4576 	pM->iAsyncErrorCode=anError;
  4577 	pM->iAsyncDfc.Enque();
  4578 	OstTraceFunctionExit1( DMEDIADRIVER_PARTITIONINFOCOMPLETE_EXIT, this );
  4579 	}
  4580 
  4581 
  4582 
  4583 
  4584 /**
  4585 @internalComponent
  4586 */
  4587 // Default implementation
  4588 EXPORT_C void DMediaDriver::Disconnect(DLocalDrive* aLocalDrive, TThreadMessage* aMsg)
  4589 	{
  4590 	OstTraceFunctionEntryExt( DMEDIADRIVER_DISCONNECT_ENTRY, this );
  4591 	// don't need to worry about DLocalDrive going away
  4592 	aLocalDrive->Deque();
  4593 
  4594 	aMsg->Complete(KErrNone, EFalse);
  4595 	OstTraceFunctionExit1( DMEDIADRIVER_DISCONNECT_EXIT, this );
  4596 	}
  4597 
  4598 
  4599 
  4600 
  4601 /**
  4602 Registers a media driver with the Local Media Subsystem, and provides
  4603 information about the number of supported drives, partitions,
  4604 names and drive numbers.
  4605 
  4606 @param aDevice       The unique Media ID for this device.
  4607                      This can take one of the enumerated values defined
  4608                      by the TMediaDevice enum.
  4609 @param aDriveCount   Specifies the number of local drive objects to be assigned
  4610                      to the media driver. Drives that support more than one
  4611                      partition must specify a number greater than 1.
  4612 @param aDriveList    A pointer to an array of TInt values, which define
  4613                      the drive numbers that are to be allocated to each partition.
  4614                      0 signifies Drive C, 1 signifies drive D, etc. For example,
  4615                      to allocate drive letters J and K, specify an array
  4616                      containing the values [7,8].
  4617                      Note that the size of this array must be the same as the value 
  4618                      specified by aDriveCount.
  4619 @param aPrimaryMedia A pointer to the primary DPrimaryMedia object to be
  4620                      associated with the media. This object is responsible for
  4621                      the overall state of the media, i.e. powering up, reading
  4622                      partition information etc. It also has overall control over
  4623                      all partitions as represented by the additional (aNumMedia-1)
  4624                      DMedia objects. 
  4625 @param aNumMedia     Specifies the total number of DMedia objects to be
  4626                      associated with the media driver. This number includes the
  4627                      primary DPrimaryMedia object referred to by aPrimaryMedia,
  4628                      plus all of the DMedia objects that are created for each
  4629                      additional drive, and which hold basic information about
  4630                      partitions.
  4631 @param aName         The name of the media driver, for example: PCCard
  4632        
  4633 @return              KErrNone, if successful;
  4634                      KErrInUse, if a drive is already in use;
  4635                      KErrNoMemory, if there is insufficient memory;
  4636                      or one of the other system-wide error codes.  
  4637 */
  4638 EXPORT_C TInt LocDrv::RegisterMediaDevice(TMediaDevice aDevice, TInt aDriveCount, const TInt* aDriveList, DPrimaryMediaBase* aPrimaryMedia, TInt aNumMedia, const TDesC& aName)
  4639 	{
  4640 	OstTraceFunctionEntry0( LOCDRV_REGISTERMEDIADEVICE_ENTRY );
  4641 	// Create TLocDrv / DMedia objects to handle a media device
  4642 	__KTRACE_OPT(KBOOT,Kern::Printf("RegisterMediaDevice %lS dev=%1d #drives=%d 1st=%d PM=%08x #media=%d",&aName,aDevice,aDriveCount,*aDriveList,aPrimaryMedia,aNumMedia));
  4643 	OstTraceExt5( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE1, "aDevice=%d; aDriveCount=%d; aDriveList=%d; aPrimaryMedia=0x%08x; aNumMedia=%d", (TInt) aDevice, (TInt) aDriveCount, (TInt) *aDriveList, (TUint) aPrimaryMedia, (TInt) aNumMedia );
  4644 	
  4645 	const TInt* p=aDriveList;
  4646 	TInt i;
  4647 	TInt r=0;
  4648 	if (UsedMedia+aNumMedia>KMaxLocalDrives)
  4649 	    {
  4650 		OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT1, "< KErrInUse");
  4651 		return KErrInUse;
  4652 	    }
  4653 	for (i=0; i<aDriveCount; ++i)
  4654 		{
  4655 		TInt drv = *p++;
  4656 		// -1 means not used; this is to enable Dual-slot MMC support 
  4657 		if (drv == -1)
  4658 			continue;
  4659 		__KTRACE_OPT(KBOOT,Kern::Printf("Registering drive %d", drv));
  4660 		OstTrace1( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE2, "Registering drive=%d", drv );
  4661 		if (TheDrives[drv])
  4662 			{
  4663 			__KTRACE_OPT(KBOOT,Kern::Printf("Drive %d already in use", drv));
  4664 			OstTrace1( TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT2, "< Drive %d already in use; KErrInUse", drv);
  4665 			return KErrInUse;
  4666 			}
  4667 		}
  4668 	HBuf* pN=HBuf::New(aName);
  4669 	if (!pN)
  4670 	    {
  4671         OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT3, "< KErrNoMemory");
  4672 		return KErrNoMemory;
  4673 	    }
  4674 	TInt lastMedia=UsedMedia+aNumMedia-1;
  4675 	for (i=UsedMedia; i<=lastMedia; ++i)
  4676 		{
  4677 		if (i==UsedMedia)
  4678 			TheMedia[i]=aPrimaryMedia;
  4679 		else
  4680 			TheMedia[i]=new DMedia;
  4681 		if (!TheMedia[i])
  4682 		    {
  4683              OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT4, "< KErrNoMemory");
  4684 			return KErrNoMemory;
  4685 		    }
  4686 		r=TheMedia[i]->Create(aDevice,i,lastMedia);
  4687 		__KTRACE_OPT(KBOOT,Kern::Printf("Media %d Create() returns %d",i,r));
  4688 		OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE3, "Media=%d Create(); retval=%d", i, r );
  4689 		if (r!=KErrNone)
  4690 		    {
  4691             OstTrace1(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT5, "< retval=%d", r);
  4692 			return r;
  4693 		    }
  4694 		}
  4695 
  4696 	__KTRACE_OPT(KBOOT,Kern::Printf("FirstMedia %d LastMedia %d",UsedMedia,lastMedia));
  4697 	OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE4, "FirstMedia=%d; LastMedia=%d", UsedMedia, lastMedia );
  4698 	UsedMedia+=aNumMedia;
  4699 	p=aDriveList;
  4700 	for (i=0; i<aDriveCount; ++i)
  4701 		{
  4702 		TInt drv=*p++;
  4703 		if (drv == -1)
  4704 			continue;
  4705 		TLocDrv* pL=new TLocDrv(drv);
  4706 		if (!pL)
  4707 		    {
  4708             OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT6, "< KErrNoMemory");
  4709 			return KErrNoMemory;
  4710 		    }
  4711 		TheDrives[drv]=pL;
  4712 		DriveNames[drv]=pN;
  4713 		pL->iPrimaryMedia=aPrimaryMedia;
  4714 		__KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pL));
  4715 		OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE5, "Drive=%d; TLocDrv 0x%08x;", (TInt) drv, (TUint) pL );
  4716 		}
  4717 
  4718 	OstTraceFunctionExit0( LOCDRV_REGISTERMEDIADEVICE_EXIT7 );
  4719 	return KErrNone;
  4720 	}
  4721 
  4722 
  4723 
  4724 
  4725 /**
  4726 A utility function that is used internally to register the specified
  4727 password store.
  4728 
  4729 The password store is used to save passwords for local media.
  4730 
  4731 @param aStore A pointer to the password store to be registered.
  4732 
  4733 @return KErrNone, if successful;
  4734         KErrAlreadyExists, if a password store has already been registered.
  4735 */ 
  4736 EXPORT_C TInt LocDrv::RegisterPasswordStore(TPasswordStore* aStore)
  4737 	{
  4738 	OstTraceFunctionEntry0( LOCDRV_REGISTERPASSWORDSTORE_ENTRY );
  4739 	// Create TLocDrv / DMedia objects to handle a media device
  4740 	__KTRACE_OPT(KBOOT,Kern::Printf("RegisterPasswordStore"));
  4741 	
  4742 	TInt r = KErrNone;
  4743 
  4744 	if(ThePasswordStore == NULL)
  4745 		ThePasswordStore = aStore;
  4746 	else
  4747 		r = KErrAlreadyExists;
  4748 	OstTrace1(TRACE_INTERNALS, LOCDRV_REGISTERPASSWORDSTORE, "retval=%d", r);
  4749 	OstTraceFunctionExit0( LOCDRV_REGISTERPASSWORDSTORE_EXIT );
  4750 	return r;
  4751 	}
  4752 
  4753 /**
  4754 Returns a pointer to the registered password store.
  4755 
  4756 The password store is used to save passwords for local media.
  4757 
  4758 @return A pointer to the registered password store.
  4759 */ 
  4760 EXPORT_C TPasswordStore* LocDrv::PasswordStore()
  4761 	{
  4762 	return ThePasswordStore;
  4763 	}
  4764 
  4765 #ifdef __DEMAND_PAGING__
  4766 /**
  4767 Registers a paging device with the Local Media Subsystem, and provides
  4768 information about drive numbers used in Code Paging.
  4769 
  4770 @param aPrimaryMedia A pointer to the primary DPrimaryMedia object associated 
  4771 					 with the media.
  4772 @param aPagingDriveList    A pointer to an array of TInt values, which define
  4773                      the drive numbers used as Code backup in Code Paging, which
  4774 					 are the target of Page In requests. For NAND these will
  4775 					 will be usually associated with ROFS and/or User Data drives.
  4776 					 In ROM pagigng systems no drive is specified, it is assumed
  4777 					 a fixed media for which no non-primary media exists, will be 
  4778 					 used.
  4779 @param aDriveCount   Specifies the number of local drives associated with this
  4780 					 media device which can be used for code paging. 
  4781 @param aPagingType	 Identifies the type of Paging this media device is capable
  4782 					 of servicing.
  4783 @param aReadShift	 Log2 of the read unit size. A read unit is the number of bytes
  4784 					 which the device can optimally read from the underlying media.
  4785 					 E.g. for small block NAND, a read unit would be equal to the 
  4786 					 page size,	512 bytes, therefore iReadShift would be set to 9.
  4787 @param aNumPages     The number of pages to alloc for each drive associated with this
  4788 					 media driver. The pages are used in request fragmentation.
  4789 
  4790 @return              KErrNone, if successful;
  4791 					 KErrNotFound, if at least one of the drive numbers
  4792 					 specified has not yet been mapped.
  4793 					 KErrArgument, if the passed in an invalid argument.
  4794 					 KErrNotSupported, if at least one of the drive numbers 
  4795 					 specifed is not associated with this Primary Media.
  4796                      KErrNoMemory, if there is insufficient memory;
  4797                      or one of the other system-wide error codes.  
  4798 */
  4799 EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* aPrimaryMedia, const TInt* aPagingDriveList, TInt aDriveCount, TUint aPagingType, TInt aReadShift, TUint aNumPages)
  4800 	{
  4801 	OstTraceFunctionEntry0( LOCDRV_REGISTERPAGINGDEVICE_ENTRY );
  4802 	
  4803 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf(">RegisterPagingDevice: paging type=%d PM=0x%x read shift=%d",aPagingType,aPrimaryMedia,aReadShift));
  4804 	OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE1, "aPagingType=%d; aPrimaryMedia=0x%x; aReadShift=%d", (TInt) aPagingType, (TUint) aPrimaryMedia, (TInt) aReadShift);
  4805 	
  4806 	TInt i;
  4807 
  4808 	if(!aPagingType || (aPagingType&~(DPagingDevice::ERom | DPagingDevice::ECode | DPagingDevice::EData)))
  4809 		{
  4810 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Unsupported paging type, exiting"));
  4811 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT1, "< Unsupported paging type; KErrArgument");
  4812 		return KErrArgument;
  4813 		}
  4814 
  4815 
  4816 
  4817 	for(i=0; i<KMaxLocalDrives; i++)
  4818 		{
  4819 		if (ThePagingDevices[i] == NULL)
  4820 			continue;
  4821 		if ((ThePagingDevices[i]->iType&DPagingDevice::ERom) &&	(aPagingType & DPagingDevice::ERom))
  4822 			{
  4823 			aPagingType&=~DPagingDevice::ERom;		// already have a ROM paging device
  4824 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has ROM pager on locdrv no %d",i));
  4825 			}
  4826 		if ((ThePagingDevices[i]->iType&DPagingDevice::EData) && (aPagingType & DPagingDevice::EData))
  4827 			{
  4828 			aPagingType&=~DPagingDevice::EData;		// already have a Data paging device
  4829 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has Data pager on locdrv no %d",i));
  4830 			}
  4831 		}
  4832 
  4833 
  4834 	if (aPagingType == 0)
  4835 		{
  4836 		// there's already a ROM or Data paging device & this doesn't support code paging so quietly exit without further addo
  4837 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Nothing left to register on locdrv no %d, exiting",i));
  4838 		OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT2, "< Nothing left to register on locdrv no %d; KErrNone",i);
  4839 		return KErrNone;
  4840 		}
  4841 
  4842 	const TInt* p=aPagingDriveList;
  4843 	if(aPagingType&DPagingDevice::ECode)	// supports code paging, do argument check
  4844 		{
  4845 		if(!aDriveCount || (aDriveCount>=KMaxLocalDrives))
  4846 			{
  4847 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive count: %d", aDriveCount));
  4848 			OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT3, "< Invalid code paging drive count=%d; KErrArgument", aDriveCount);
  4849 			return KErrArgument;
  4850 			}
  4851 
  4852 		TInt drvCount=0;
  4853 		for(i=0; i<KMaxLocalDrives; i++)
  4854 			if(TheDrives[i] && TheDrives[i]->iPrimaryMedia==aPrimaryMedia)
  4855 				drvCount++;
  4856 		if(aDriveCount>drvCount)	// can't exceed number of drives registered by this device
  4857 			{
  4858 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive count=%d; total=%d", aDriveCount, drvCount));
  4859 			OstTraceExt2(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT4, "< Invalid code paging drive count=%d; total=%d; KErrArgument", aDriveCount, drvCount);
  4860 			return KErrArgument;
  4861 			}
  4862 
  4863 		for (i=0; i<aDriveCount; ++i)
  4864 			{
  4865 			__KTRACE_OPT(KBOOT,Kern::Printf("RegisterPagingDevice: registering drive=%d ",*p));
  4866 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE2, "Registering Drive=%d", *p );
  4867 			TInt drv=*p++;
  4868 			if(drv>=KMaxLocalDrives)
  4869 				{
  4870 				__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive number: %d", drv));
  4871 				OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT5, "< Invalid code paging drive number=%d; KErrArgument", drv);
  4872 				return KErrArgument;
  4873 				}
  4874 			TLocDrv* pD=TheDrives[drv];
  4875 			if (!pD)
  4876 			    {
  4877                 OstTrace0(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT6, "< KErrNotFound");
  4878 				return KErrNotFound;
  4879 			    }
  4880 			if (pD->iPrimaryMedia!=aPrimaryMedia)
  4881 			    {
  4882                 OstTrace0(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT7, "< KErrNotSupported");
  4883 				return KErrNotSupported;
  4884 			    }
  4885 			}
  4886 		}
  4887 
  4888 
  4889 	TInt firstLocalDriveNumber = KErrNotFound; 
  4890 	TInt romPagingDriveNumber = KErrNotFound;
  4891 
  4892 	TInt dataPagingDriveNumber = KErrNotFound;
  4893 	TInt swapSize = 0;
  4894 
  4895 	// find the local drive assocated with the primary media
  4896 	for (i=0; i<KMaxLocalDrives; ++i)
  4897 		{
  4898 		if(TheDrives[i] && TheDrives[i]->iPrimaryMedia == aPrimaryMedia)
  4899 			{
  4900 			firstLocalDriveNumber = i;
  4901 			break;
  4902 			}
  4903 		}
  4904 	__ASSERT_ALWAYS(i < KMaxLocalDrives, LOCM_FAULT());
  4905 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("DMediaPagingDevice(), firstLocalDriveNumber %d", firstLocalDriveNumber));
  4906 	OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE3, "firstLocalDriveNumber=%d", firstLocalDriveNumber );
  4907 	
  4908 	// Send an ECaps message to wake up the media driver & ensure all partitions are 
  4909 	// reported, then search for paged-data or paged-ROM partitions
  4910 	if ((aPagingType & DPagingDevice::EData) ||
  4911 		(aPagingType & DPagingDevice::ERom && aPrimaryMedia->iDfcQ && aPrimaryMedia->iMsgQ.iReady))
  4912 		{
  4913 		// the message queue must have been started already (by the media driver calling iMsgQ.Receive())
  4914 		// otherwise we can't send the DLocalDrive::EQueryDevice request
  4915 		if (aPrimaryMedia->iDfcQ && !aPrimaryMedia->iMsgQ.iReady)
  4916 			{
  4917 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Message queue not started"));
  4918 			OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT8, "< RegisterPagingDevice: Message queue not started; KErrNotReady");
  4919 			return KErrNotReady;
  4920 			}
  4921 
  4922 
  4923 		TLocDrvRequest m;
  4924 		memclr(&m, sizeof(m));
  4925 		
  4926 
  4927 		// Get the Caps from the device. NB for MMC/SD we may need to retry as some PSLs start up
  4928 		// in "door open" or "media not present" state which can result in the cancellation of requests
  4929 		TInt i;
  4930 		const TInt KRetries = 5;
  4931 		TInt r = KErrNotReady;
  4932 		for (i=0; r == KErrNotReady && i < KRetries; i++)
  4933 			{
  4934 			TBuf8<KMaxLocalDriveCapsLength> capsBuf;
  4935 			capsBuf.SetMax();
  4936 			capsBuf.FillZ();
  4937 			m.Drive() = TheDrives[firstLocalDriveNumber];
  4938 			m.Id() = DLocalDrive::ECaps;
  4939 			m.RemoteDes() = (TAny*)capsBuf.Ptr();	// overload this
  4940 			m.Length() = KMaxLocalDriveCapsLength;	// for pinning
  4941 			r = aPrimaryMedia->Request(m);
  4942 
  4943 //Kern::Printf("EQueryPageDeviceInfo: i %d: r %d ", i, r);
  4944 			__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Paging device ECaps: i %d: r %d ", i, r));
  4945 			OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE4, "Paging device ECaps: i %d retval=%d", i, r);
  4946 			}
  4947 
  4948 		if (r != KErrNone)
  4949 		    {
  4950             OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< retval=%d",r);
  4951 			return r;
  4952 		    }
  4953 
  4954 		TLocDrv* drive;
  4955 		for (i=0; i<KMaxLocalDrives; ++i)
  4956 			{
  4957 			drive = TheDrives[i];
  4958 			if(drive && drive->iPrimaryMedia == aPrimaryMedia)
  4959 				{
  4960 				__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("RegisterPagingDevice: local drive %d, partition type %x size %x", i, drive->iPartitionType, I64LOW(drive->iPartitionLen)));
  4961 				// ROM partition ?
  4962 				if ((romPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypeROM))
  4963 					{
  4964 					__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found ROM partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
  4965 					OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE5, "Found ROM partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen));
  4966 					romPagingDriveNumber = i;
  4967 					}
  4968 			    // swap partition ?
  4969 				else if ((dataPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypePagedData))
  4970 					{
  4971 					__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found swap partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
  4972 					OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE6, "Found SWAP partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen) );			
  4973 					dataPagingDriveNumber = i;
  4974 					swapSize = drive->iPartitionLen >> aReadShift;
  4975 					}
  4976 				}
  4977 			}
  4978 
  4979 		if (swapSize == 0)
  4980 			{
  4981 			__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Disabling data paging"));
  4982 			OstTraceDef0(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE7, "Disabling data paging");
  4983 			aPagingType &= ~DPagingDevice::EData;
  4984 			}
  4985 
  4986 		}
  4987 
  4988 
  4989 	// create and set up a DPagingDevice to allow PageIn request servicing
  4990 	DMediaPagingDevice* pagingDevice = new DMediaPagingDevice(aPrimaryMedia);
  4991 	if(!pagingDevice)
  4992 		{
  4993 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create paging device"));
  4994 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT_EXIT10, "< RegisterPagingDevice: could not create paging device; KErrNoMemory");
  4995 		return KErrNoMemory;
  4996 		}
  4997 
  4998 	pagingDevice->iType = aPagingType;
  4999 	pagingDevice->iReadUnitShift = aReadShift;
  5000 
  5001 	pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber;
  5002 	pagingDevice->iRomPagingDriveNumber = romPagingDriveNumber;
  5003 
  5004 	pagingDevice->iDataPagingDriveNumber = dataPagingDriveNumber;
  5005 	pagingDevice->iSwapSize = swapSize;
  5006 
  5007 #ifdef __DEBUG_DEMAND_PAGING__
  5008 	Kern::Printf("PagingDevice :");
  5009 	Kern::Printf("iType 0x%x\n", pagingDevice->iType);
  5010 	Kern::Printf("iReadUnitShift 0x%x\n", pagingDevice->iReadUnitShift);
  5011 	Kern::Printf("iFirstLocalDriveNumber 0x%x\n", pagingDevice->iFirstLocalDriveNumber);
  5012 	Kern::Printf("iRomPagingDriveNumber 0x%x\n", pagingDevice->iRomPagingDriveNumber);
  5013 	Kern::Printf("iDataPagingDriveNumber 0x%x\n", pagingDevice->iDataPagingDriveNumber);
  5014 	Kern::Printf("iSwapSize 0x%x\n", pagingDevice->iSwapSize);
  5015 	#endif
  5016 
  5017 
  5018 	// This table is indexed by DPagingDevice::TType
  5019 	const char* DeviceName[] = 
  5020 		{
  5021 		"Error",
  5022 		"RomPagingDevice",
  5023 		"CodePagingDevice",
  5024 		"RomAndCodePagingDevice",
  5025 		"DataPagingDevice",
  5026 		"RomAndDataPagingDevice",
  5027 		"CodeAndDataPagingDevice",
  5028 		"RomAndCodeAndDataPagingDevice"
  5029 		};
  5030 
  5031 
  5032 	if(aPagingType & DPagingDevice::ECode)
  5033 		{
  5034 		for (i=0; i<aDriveCount; ++i)
  5035 			pagingDevice->iDrivesSupported|=(0x1<<aPagingDriveList[i]);
  5036 		}
  5037 	pagingDevice->iName = DeviceName[aPagingType];
  5038 
  5039 	if (ThePinObjectAllocator == NULL)
  5040 		ThePinObjectAllocator = new DPinObjectAllocator();
  5041 	if(!ThePinObjectAllocator)
  5042 		{
  5043 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator"));
  5044 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory");
  5045 		return KErrNoMemory;
  5046 		}
  5047 	TInt r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages);
  5048 	if (r != KErrNone)
  5049 		{
  5050 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not construct ThePinObjectAllocator"));
  5051 		OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT12, "< RegisterPagingDevice: could not construct ThePinObjectAllocator; retval=%d",r);
  5052 		return r;
  5053 		}
  5054 
  5055 
  5056 	// Register our DPagingDevice with the Kernel
  5057 	r=Kern::InstallPagingDevice(pagingDevice);
  5058 
  5059 #ifdef __DEBUG_DEMAND_PAGING__
  5060 	Kern::Printf("Kern::InstallPagingDevice() r %d", r);
  5061 #endif
  5062 
  5063 	if (r!=KErrNone)
  5064 		{
  5065 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not install paging device"));
  5066 		OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT13, "< RegisterPagingDevice: could not install paging device; retval=%d", r);
  5067 		delete pagingDevice;
  5068 		return r;
  5069 		}
  5070 
  5071 	// all hunky dory, save paging device and mark our media as pageable
  5072 	ThePagingDevices[aPrimaryMedia->iMediaId] = pagingDevice;	// association created between PrimaryMedia and PagingDevice via iMediaId
  5073 	aPrimaryMedia->iPagingMedia = 1;
  5074 
  5075 	// mark our drives as pageable
  5076 	p=aPagingDriveList;
  5077 	if (aPagingType&DPagingDevice::ECode)
  5078 		{
  5079 		for (i=0; i<aDriveCount; ++i)
  5080 			{
  5081 			TLocDrv* pD=TheDrives[*p++];
  5082 			pD->iPagingDrv=1;
  5083 			}
  5084 		}
  5085 
  5086 	// Flags to indicate that a paging device is registered and pinning of user requests may be required
  5087 	aPrimaryMedia->iPagingMedia = 1;
  5088 
  5089 	// point the primary media to the paging device
  5090 	aPrimaryMedia->iBody->iPagingDevice = pagingDevice;
  5091 
  5092 	if (aPagingType & DPagingDevice::ERom)
  5093 		{
  5094 		aPrimaryMedia->iRomPagingMedia = 1;
  5095 		TheRomPagingMedia = aPrimaryMedia;
  5096 		}
  5097 	
  5098 	// Is data paging enabled in this ROM ?
  5099 	TInt memModelAttributes = Kern::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
  5100 	TBool dataPagingSupported = memModelAttributes & EMemModelAttrDataPaging;
  5101 #ifdef __DEBUG_DEMAND_PAGING__
  5102 	Kern::Printf("memModelAttributes %08X", memModelAttributes);
  5103 	Kern::Printf("DataPagingSupported %d", dataPagingSupported);
  5104 #endif
  5105 	if (!dataPagingSupported)
  5106 		{
  5107 #ifdef __DEBUG_DEMAND_PAGING__
  5108 		if (aPagingType & DPagingDevice::EData)
  5109 		    {
  5110 			Kern::Printf("Disabling data paging, not supported in this ROM");
  5111 		    }
  5112 #endif
  5113 		aPagingType&= ~DPagingDevice::EData;
  5114 		}
  5115 
  5116 
  5117 	if (aPagingType & DPagingDevice::EData)
  5118 		{
  5119 		DataPagingDeviceRegistered = ETrue;
  5120 		aPrimaryMedia->iDataPagingMedia = 1;
  5121 		TheDataPagingMedia = aPrimaryMedia;
  5122 		}
  5123 
  5124 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("< RegisterPagingDevice"));
  5125 	OstTraceFunctionExit0( LOCDRV_REGISTERPAGINGDEVICE_EXIT14 );
  5126 	return KErrNone;
  5127 	}
  5128 
  5129 #else //__DEMAND_PAGING__
  5130 
  5131 #if !defined(__WINS__)
  5132 EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* , const TInt* , TInt , TUint , TInt , TUint )
  5133 	{
  5134 	return KErrNotSupported;
  5135 	}		// stub for def file
  5136 #endif // __WINS__
  5137 
  5138 #endif //__DEMAND_PAGING__
  5139 
  5140 
  5141 /**
  5142 Registers a media device with physical memory addressing capabilities with the
  5143 Local Media Subsystem.
  5144 
  5145 @param aPrimaryMedia A pointer to the primary DPrimaryMedia object associated 
  5146 					 with the media device.
  5147 @param aMediaBlockSize The Minimum transfer size (bytes) for the media device.
  5148 @param aDmaMaxAddressable The Maximum Addressing Range for the media device's DMA controller, 0 if None.				 
  5149 @param aDmaAlignment The required memory alignment for the media device's DMA controller.
  5150 
  5151 @return KErrNone, Always;
  5152 */
  5153 EXPORT_C TInt LocDrv::RegisterDmaDevice(DPrimaryMediaBase* aPrimaryMedia, 
  5154 										TInt aMediaBlockSize,				// Minimum transfer size (bytes) for the media
  5155 										TInt aDmaMaxAddressable,			// Max Addressing Range for DMA controller, 0 if None.
  5156 										TInt aDmaAlignment)					// DMA Alignment e.g. word alignment required = 2
  5157 	{
  5158 	OstTraceFunctionEntry0( LOCDRV_REGISTERDMADEVICE_ENTRY );
  5159 	
  5160 	__KTRACE_OPT(KBOOT ,Kern::Printf("RegisterPhysicalAddrDevice: PM=0x%x BS=%d MaxAddr=%d DMA=%d", 
  5161 									aPrimaryMedia, aMediaBlockSize, aDmaMaxAddressable, aDmaAlignment));
  5162 	OstTraceExt4( TRACE_INTERNALS, LOCDRV_REGISTERDMADEVICE, "aPrimaryMedia=0x%x; aMediaBlockSize=%d; aDmaMaxAddressable=%d; aDmaAlignment=%d", (TUint) aPrimaryMedia, (TInt) aMediaBlockSize, (TInt) aDmaMaxAddressable, (TInt) aDmaAlignment );
  5163 	
  5164 	for (TInt i=0; i<KMaxLocalDrives; ++i)
  5165 		{
  5166 		TLocDrv* pL=TheDrives[i];
  5167 		if (pL && pL->iPrimaryMedia == aPrimaryMedia && pL->iDmaHelper == NULL)
  5168 			{
  5169 			pL->iDmaHelper = new DDmaHelper;
  5170 			__ASSERT_ALWAYS(pL != NULL, LOCM_FAULT());
  5171 			
  5172 			// if no limit stated on addressing range use 1MB
  5173 			TInt MaxAddress = aDmaMaxAddressable ? (1024*1024) : aDmaMaxAddressable;
  5174 			
  5175 			TInt r = pL->iDmaHelper->Construct(MaxAddress, aMediaBlockSize, aDmaAlignment);
  5176 			__ASSERT_ALWAYS(r == KErrNone, LOCM_FAULT());
  5177 			}
  5178 		}
  5179 
  5180 	OstTraceFunctionExit0( LOCDRV_REGISTERDMADEVICE_EXIT );
  5181 	return KErrNone;
  5182 	}
  5183 
  5184 void GetDriveInfo(TDriveInfoV1& info)
  5185 	{
  5186 	OstTraceFunctionEntry1( GETDRIVEINFO_ENTRY, ( TUint )&( info ) );
  5187 	TInt i;
  5188 	TInt drives=0;
  5189 	TUint32 sock_mask=0;
  5190 	TInt sockets=0;
  5191 
  5192 	info.iRegisteredDriveBitmask = 0;
  5193 
  5194 	for (i=0; i<KMaxPBusSockets; ++i)
  5195 		info.iSocketName[i].Zero();
  5196 	for (i=0; i<KMaxLocalDrives; ++i)
  5197 		{
  5198 		TLocDrv* pL=TheDrives[i];
  5199 		if (pL)
  5200 			{
  5201 			++drives;
  5202 			TInt sockNum;
  5203 			DPrimaryMediaBase* pM=pL->iPrimaryMedia;
  5204 			if (pM->IsRemovableDevice(sockNum))
  5205 				{
  5206 				if (!(sock_mask & (1<<sockNum)))
  5207 					{
  5208 					info.iSocketName[sockNum]=*DriveNames[i];
  5209 					__KTRACE_OPT(KLOCDRV,Kern::Printf("Socket %d device %d name %lS", sockNum, pM->iDevice, DriveNames[i]));
  5210 					OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO1, "Socket=%d; device=%d", sockNum, (TUint) pM->iDevice );
  5211 					if ( (sockNum + 1) > sockets )
  5212 						sockets = sockNum + 1;
  5213 					}
  5214 				sock_mask |= (1<<sockNum);
  5215 				}
  5216 			info.iDriveName[i]=*DriveNames[i];
  5217 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d device %d name %lS",i,pM->iDevice,DriveNames[i]));
  5218 			OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO2, "Drive=%d; device=%d", i, (TUint) pM->iDevice );
  5219 			
  5220 			info.iRegisteredDriveBitmask |= (0x01 << i);
  5221 			}
  5222 		}
  5223 	info.iTotalSupportedDrives=drives;
  5224 	info.iTotalSockets=sockets;
  5225 	info.iRuggedFileSystem=ETrue;
  5226 	__KTRACE_OPT(KLOCDRV,Kern::Printf("Total drives=%d, sockets=%d",drives,sockets));
  5227 	OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO3, "Total drives=%d; sockets=%d", drives, sockets );
  5228 	OstTraceFunctionExit0( GETDRIVEINFO_EXIT );
  5229 	}
  5230 
  5231 #if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__)
  5232 void ResetConcurrencyStats(DMediaPagingDevice* aDevice, TMediaPagingStats aStats)
  5233 	{
  5234 	NKern::FMWait(&aDevice->iInstrumentationLock);
  5235 	switch(aStats)
  5236 		{
  5237 		case EMediaPagingStatsRom:
  5238 			aDevice->iServicingROM=0;
  5239 			memclr(&aDevice->iROMStats,sizeof(SMediaROMPagingConcurrencyInfo));
  5240 			break;
  5241 		case EMediaPagingStatsCode:
  5242 			aDevice->iServicingCode=0;
  5243 			memclr(&aDevice->iCodeStats,sizeof(SMediaCodePagingConcurrencyInfo));
  5244 			break;
  5245 		case EMediaPagingStatsDataIn:
  5246 			aDevice->iServicingDataIn=0;
  5247 			memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo));
  5248 			break;
  5249 		case EMediaPagingStatsDataOut:
  5250 			aDevice->iServicingDataOut=0;
  5251 			memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo));
  5252 			break;
  5253 		case EMediaPagingStatsAll:
  5254 			aDevice->iServicingROM=0;
  5255 			aDevice->iServicingCode=0;
  5256 			aDevice->iServicingDataIn=0;
  5257 			aDevice->iServicingDataOut=0;
  5258 			memclr(&aDevice->iROMStats,sizeof(SMediaROMPagingConcurrencyInfo));
  5259 			memclr(&aDevice->iCodeStats,sizeof(SMediaCodePagingConcurrencyInfo));
  5260 			memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo));
  5261 			break;
  5262 		}
  5263 	NKern::FMSignal(&aDevice->iInstrumentationLock);
  5264 	}
  5265 #endif
  5266 #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
  5267 void ResetBenchmarkStats(DMediaPagingDevice* aDevice, TMediaPagingStats aStats)
  5268 	{
  5269 	NKern::FMWait(&aDevice->iInstrumentationLock);
  5270 	switch(aStats)
  5271 		{
  5272 		case EMediaPagingStatsRom:
  5273 			aDevice->iROMBenchmarkData.iCount = 0;
  5274 			aDevice->iROMBenchmarkData.iTotalTime = 0;
  5275 			aDevice->iROMBenchmarkData.iMaxTime = 0;
  5276 			aDevice->iROMBenchmarkData.iMinTime = KMaxTInt;
  5277 			break;
  5278 		case EMediaPagingStatsCode:
  5279 			aDevice->iCodeBenchmarkData.iCount = 0;
  5280 			aDevice->iCodeBenchmarkData.iTotalTime = 0;
  5281 			aDevice->iCodeBenchmarkData.iMaxTime = 0;
  5282 			aDevice->iCodeBenchmarkData.iMinTime = KMaxTInt;
  5283 			break;
  5284 		case EMediaPagingStatsDataIn:
  5285 			aDevice->iDataInBenchmarkData.iCount = 0;
  5286 			aDevice->iDataInBenchmarkData.iTotalTime = 0;
  5287 			aDevice->iDataInBenchmarkData.iMaxTime = 0;
  5288 			aDevice->iDataInBenchmarkData.iMinTime = KMaxTInt;
  5289 			break;
  5290 		case EMediaPagingStatsDataOut:
  5291 			aDevice->iDataOutBenchmarkData.iCount = 0;
  5292 			aDevice->iDataOutBenchmarkData.iTotalTime = 0;
  5293 			aDevice->iDataOutBenchmarkData.iMaxTime = 0;
  5294 			aDevice->iDataOutBenchmarkData.iMinTime = KMaxTInt;
  5295 			break;
  5296 		case EMediaPagingStatsAll:
  5297 			aDevice->iDataInBenchmarkData.iCount = 0;
  5298 			aDevice->iDataInBenchmarkData.iTotalTime = 0;
  5299 			aDevice->iDataInBenchmarkData.iMaxTime = 0;
  5300 			aDevice->iDataInBenchmarkData.iMinTime = KMaxTInt;
  5301 
  5302 			aDevice->iDataOutBenchmarkData.iCount = 0;
  5303 			aDevice->iDataOutBenchmarkData.iTotalTime = 0;
  5304 			aDevice->iDataOutBenchmarkData.iMaxTime = 0;
  5305 			aDevice->iDataOutBenchmarkData.iMinTime = KMaxTInt;
  5306 
  5307 			aDevice->iROMBenchmarkData.iCount = 0;
  5308 			aDevice->iROMBenchmarkData.iTotalTime = 0;
  5309 			aDevice->iROMBenchmarkData.iMaxTime = 0;
  5310 			aDevice->iROMBenchmarkData.iMinTime = KMaxTInt;
  5311 
  5312 			aDevice->iCodeBenchmarkData.iCount = 0;
  5313 			aDevice->iCodeBenchmarkData.iTotalTime = 0;
  5314 			aDevice->iCodeBenchmarkData.iMaxTime = 0;
  5315 			aDevice->iCodeBenchmarkData.iMinTime = KMaxTInt;
  5316 			break;
  5317 		}
  5318 	NKern::FMSignal(&aDevice->iInstrumentationLock);
  5319 	}
  5320 #endif
  5321 
  5322 TInt MediaHalFunction(TAny*, TInt aFunction, TAny* a1, TAny* a2)
  5323 	{
  5324 	TInt r=KErrNotSupported;
  5325 	switch (aFunction)
  5326 		{
  5327 		case EMediaHalDriveInfo:
  5328 			{
  5329 			(void) a2;
  5330 			TDriveInfoV1Buf infoBuf;
  5331 			TDriveInfoV1& info=infoBuf();
  5332 			GetDriveInfo(info);
  5333 			Kern::InfoCopy(*(TDes8*)a1,infoBuf);
  5334 			r=KErrNone;
  5335 			break;
  5336 			}
  5337 #if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__)
  5338 		case EMediaHalGetROMConcurrencyInfo:
  5339 			{
  5340 			TInt drvNo=(TInt)a1;
  5341 			TLocDrv* drv=TheDrives[drvNo];
  5342 			if(!drv)
  5343 				break;
  5344 			DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice;
  5345 			if(!device)
  5346 				break;
  5347 			NKern::FMWait(&device->iInstrumentationLock);
  5348 			SMediaROMPagingConcurrencyInfo info=device->iROMStats;
  5349 			NKern::FMSignal(&device->iInstrumentationLock);
  5350 			kumemput32(a2,&info,sizeof(info));
  5351 			r=KErrNone;
  5352 			break;
  5353 			}
  5354 		case EMediaHalGetCodeConcurrencyInfo:
  5355 			{
  5356 			TInt drvNo=(TInt)a1;
  5357 			TLocDrv* drv=TheDrives[drvNo];
  5358 			if(!drv)
  5359 				break;
  5360 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
  5361 			if(!device)
  5362 				break;
  5363 			NKern::FMWait(&device->iInstrumentationLock);
  5364 			SMediaCodePagingConcurrencyInfo info=device->iCodeStats;
  5365 			NKern::FMSignal(&device->iInstrumentationLock);
  5366 			kumemput32(a2,&info,sizeof(info));
  5367 			r=KErrNone;
  5368 			break;
  5369 			}
  5370 		case EMediaHalGetDataConcurrencyInfo:
  5371 			{
  5372 			TInt drvNo=(TInt)a1;
  5373 			TLocDrv* drv=TheDrives[drvNo];
  5374 			if(!drv)
  5375 				break;
  5376 			DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice;
  5377 			if(!device)
  5378 				break;
  5379 			NKern::FMWait(&device->iInstrumentationLock);
  5380 			SMediaDataPagingConcurrencyInfo info=device->iDataStats;
  5381 			NKern::FMSignal(&device->iInstrumentationLock);
  5382 			kumemput32(a2,&info,sizeof(info));
  5383 			r=KErrNone;
  5384 			break;
  5385 			}
  5386 		case EMediaHalResetConcurrencyInfo:
  5387 			{
  5388 			TInt drvNo=(TInt)a1;
  5389 			TLocDrv* drv=TheDrives[drvNo];
  5390 			if(!drv)
  5391 				break;
  5392 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
  5393 			if(!device)
  5394 				break;
  5395 			TUint index=(TInt)a2;
  5396 			if(index>EMediaPagingStatsCode)
  5397 				break;
  5398 			ResetConcurrencyStats(device, (TMediaPagingStats)index);
  5399 			r=KErrNone;
  5400 			break;
  5401 			}
  5402 #endif
  5403 #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
  5404 		case EMediaHalGetROMPagingBenchmark:
  5405 			{
  5406 			TInt drvNo=(TInt)a1;
  5407 			TLocDrv* drv=TheDrives[drvNo];
  5408 			if(!drv)
  5409 				break;
  5410 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
  5411 			if(!device)
  5412 				break;
  5413 			NKern::FMWait(&device->iInstrumentationLock);
  5414 			SPagingBenchmarkInfo info = device->iROMBenchmarkData;
  5415 			NKern::FMSignal(&device->iInstrumentationLock);
  5416 			kumemput32(a2,&info,sizeof(info));
  5417 			r=KErrNone;
  5418 			break;
  5419 			}		
  5420 		case EMediaHalGetCodePagingBenchmark:
  5421 			{
  5422 			TInt drvNo=(TInt)a1;
  5423 			TLocDrv* drv=TheDrives[drvNo];
  5424 			if(!drv)
  5425 				break;
  5426 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
  5427 			if(!device)
  5428 				break;
  5429 			NKern::FMWait(&device->iInstrumentationLock);
  5430 			SPagingBenchmarkInfo info = device->iCodeBenchmarkData;
  5431 			NKern::FMSignal(&device->iInstrumentationLock);
  5432 			kumemput32(a2,&info,sizeof(info));
  5433 			r=KErrNone;
  5434 			break;
  5435 			}	
  5436 		case EMediaHalGetDataInPagingBenchmark:
  5437 			{
  5438 			TInt drvNo=(TInt)a1;
  5439 			TLocDrv* drv=TheDrives[drvNo];
  5440 			if(!drv)
  5441 				break;
  5442 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
  5443 			if(!device)
  5444 				break;
  5445 			NKern::FMWait(&device->iInstrumentationLock);
  5446 			SPagingBenchmarkInfo info = device->iDataInBenchmarkData;
  5447 			NKern::FMSignal(&device->iInstrumentationLock);
  5448 			kumemput32(a2,&info,sizeof(info));
  5449 			r=KErrNone;
  5450 			break;
  5451 			}		
  5452 		case EMediaHalGetDataOutPagingBenchmark:
  5453 			{
  5454 			TInt drvNo=(TInt)a1;
  5455 			TLocDrv* drv=TheDrives[drvNo];
  5456 			if(!drv)
  5457 				break;
  5458 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
  5459 			if(!device)
  5460 				break;
  5461 			NKern::FMWait(&device->iInstrumentationLock);
  5462 			SPagingBenchmarkInfo info = device->iDataOutBenchmarkData;
  5463 			NKern::FMSignal(&device->iInstrumentationLock);
  5464 			kumemput32(a2,&info,sizeof(info));
  5465 			r=KErrNone;
  5466 			break;
  5467 			}		
  5468 		case EMediaHalResetPagingBenchmark:
  5469 			{
  5470 			TInt drvNo=(TInt)a1;
  5471 			TLocDrv* drv=TheDrives[drvNo];
  5472 			if(!drv)
  5473 				break;
  5474 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
  5475 			if(!device)
  5476 				break;
  5477 			TUint index=(TInt)a2;
  5478 			if(index>EMediaPagingStatsCode)
  5479 				break;
  5480 			ResetBenchmarkStats(device, (TMediaPagingStats)index);
  5481 			r=KErrNone;
  5482 			break;
  5483 			}
  5484 		case EMediaHalGetPagingInfo:
  5485 			{
  5486 			TInt drvNo=(TInt)a1;
  5487 			TLocDrv* drv=TheDrives[drvNo];
  5488 			if(!drv)
  5489 				break;
  5490 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
  5491 			if(!device)
  5492 				break;
  5493 			NKern::FMWait(&device->iInstrumentationLock);
  5494 			SMediaPagingInfo info = device->iMediaPagingInfo;
  5495 			NKern::FMSignal(&device->iInstrumentationLock);
  5496 			kumemput32(a2,&info,sizeof(info));
  5497 			r=KErrNone;
  5498 			break;
  5499 			}		
  5500 #endif
  5501 		default:
  5502 			break;
  5503 		}
  5504 	return r;
  5505 	}
  5506 
  5507 
  5508 /******************************************************************************
  5509  Partition table scanner
  5510  ******************************************************************************/
  5511 
  5512 #ifdef _DEBUG
  5513 #define DMEMDUMP(base,size)	DbgMemDump((TLinAddr)base,size)
  5514 void DbgMemDump(TLinAddr aBase, TInt aSize)
  5515 	{
  5516 	TInt off;
  5517 	const TUint8* p=(const TUint8*)aBase;
  5518 	NKern::Lock();
  5519 	for (off=0; off<aSize; off+=16, p+=16)
  5520 		{
  5521 		Kern::Printf("%04x: %02x %02x %02x %02x  %02x %02x %02x %02x | %02x %02x %02x %02x  %02x %02x %02x %02x",
  5522 			off,	p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
  5523 					p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
  5524 		}
  5525 	NKern::Unlock();
  5526 	}
  5527 #else
  5528 #define DMEMDUMP(base,size)
  5529 #endif
  5530 
  5531 EXPORT_C void TPartitionTableScanner::Set(TUint8* aSectorBuffer, TPartitionEntry* aEntry, TInt aMaxPartitions, TInt64 aMediaSize)
  5532 	{
  5533 	__KTRACE_OPT(KLOCDRV, Kern::Printf("TPartitionTableScanner @ %08x : buf %08x entry %08x max %d sz %08x %08x",
  5534 								this, aSectorBuffer, aEntry, aMaxPartitions, I64HIGH(aMediaSize), I64LOW(aMediaSize)));
  5535 	OstTraceExt4( TRACE_INTERNALS, TPARTITIONTABLESCANNER_SET, "TPartitionTableScanner at 0x%08x; aSectorBuffer=0x%08x; aEntry=0x%08x; aMaxPartitions=%d", (TUint) this, (TUint) aSectorBuffer, (TUint) aEntry, aMaxPartitions );
  5536 	__ASSERT_ALWAYS(aMaxPartitions>0, LOCM_FAULT());
  5537 	memclr(this, sizeof(TPartitionTableScanner));
  5538 	iLBA = -1;
  5539 	iSectorBuffer = aSectorBuffer;
  5540 	iFirstEntry = aEntry;
  5541 	iNextEntry = aEntry;
  5542 	iLimit = aEntry + aMaxPartitions;
  5543 	iMediaSize = aMediaSize;
  5544 	}
  5545 
  5546 EXPORT_C TInt TPartitionTableScanner::NumberOfPartitionsFound() const
  5547 	{
  5548 	TInt n = iNextEntry - iFirstEntry;
  5549 	__KTRACE_OPT(KLOCDRV, Kern::Printf("TPartitionTableScanner N=%d", n));
  5550 	OstTrace1( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NUMBERPARTITIONS, "Number of partitions=%d", n );
  5551 	return n;
  5552 	}
  5553 
  5554 TPartitionTableScanner::SPart::SPart(const TUint8* a)
  5555 	{
  5556 	iBootInd = a[0];
  5557 	iType = a[4];
  5558 	iRSS = a[8]|(a[9]<<8)|(a[10]<<16)|(a[11]<<24);
  5559 	iSectors = a[12]|(a[13]<<8)|(a[14]<<16)|(a[15]<<24);
  5560 	__KTRACE_OPT(KLOCDRV, Kern::Printf("SPart: BI=%02x TYPE=%02x RSS=%08x SIZE=%08x", iBootInd, iType, iRSS, iSectors));
  5561 	OstTraceExt4(TRACE_INTERNALS, TPARTITIONTABLESCANNER_SPART_SPART, "SPart: iBootInd=%02x; iType=%02x; iRSS=%08x; iSectors=%08x", (TUint) iBootInd, (TUint) iType, (TUint) iRSS, (TUint) iSectors);
  5562 	}
  5563 
  5564 TInt TPartitionTableScanner::MakeEntry(const SPart& a)
  5565 	{
  5566 	OstTraceFunctionEntry1( TPARTITIONTABLESCANNER_MAKEENTRY_ENTRY, this );
  5567 	if (iNextEntry == iLimit)
  5568 	    {
  5569 		OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT1, this, KErrOverflow );
  5570 		return KErrOverflow;
  5571 	    }
  5572 	if (a.iRSS<=0 || a.iSectors<=0 || a.iRSS>=iMediaSize)
  5573 	    {
  5574 		OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT2, this, KErrCorrupt );
  5575 		return KErrCorrupt;
  5576 	    }
  5577 	if (TUint64(a.iRSS) + TUint64(a.iSectors) > TUint64(iMediaSize))
  5578 	    {
  5579 		OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT3, this, KErrCorrupt );
  5580 		return KErrCorrupt;
  5581 	    }
  5582 	iNextEntry->iBootIndicator = a.iBootInd;
  5583 	iNextEntry->iPartitionType = a.iType;
  5584 	iNextEntry->iPartitionBaseAddr = TInt64(a.iRSS)<<ESectorShift;
  5585 	iNextEntry->iPartitionLen = TInt64(a.iSectors)<<ESectorShift;
  5586 	++iNextEntry;
  5587 	OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT4, this, KErrNone );
  5588 	return KErrNone;
  5589 	}
  5590 
  5591 EXPORT_C TInt64 TPartitionTableScanner::NextLBA()
  5592 	{
  5593 	OstTraceFunctionEntry0( TPARTITIONTABLESCANNER_NEXTLBA_ENTRY );
  5594 	__KTRACE_OPT(KLOCDRV, Kern::Printf(">TPartitionTableScanner iLBA=%08x %08x", I64HIGH(iLBA), I64LOW(iLBA)));
  5595 	OstTraceExt2( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NEXTLBA1, "TPartitionTableScanner iLBA=%08x %08x", I64HIGH(iLBA), I64LOW(iLBA) );
  5596 	TInt r;
  5597 	TUint8* b = iSectorBuffer;
  5598 	TUint8* pS = b + 0x1be;
  5599 	TUint8* pE = pS + 64;
  5600 	TUint8* p = pS;
  5601 	TInt orig_sp = iStackPointer;
  5602 	TInt sp;
  5603 	if (iLBA < 0)
  5604 		{
  5605 		iLBA = 0;
  5606 		goto end;
  5607 		}
  5608 	__KTRACE_OPT(KLOCDRV,DMEMDUMP(b, ESectorSize));
  5609 	if (b[ESectorSize-2]!=0x55 || b[ESectorSize-1]!=0xaa)
  5610 		{
  5611 		__KTRACE_OPT(KLOCDRV, Kern::Printf("Bad signature"));
  5612 		OstTrace0( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NEXTLBA2, "Bad signature" );
  5613 		iLBA = KErrCorrupt;
  5614 		goto end;
  5615 		}
  5616 	if (iLBA==0 && iNextEntry==iFirstEntry)
  5617 		{
  5618 		// Look for bootable partition first
  5619 		for (; p<pE; p+=16)
  5620 			{
  5621 			SPart pt(p);
  5622 			if (pt.iBootInd==0x80 && pt.iType && pt.iSectors>0)
  5623 				{
  5624 				p[4] = 0;
  5625 				r = MakeEntry(pt);
  5626 				if (r!=KErrNone)
  5627 					{
  5628 					iLBA = r;
  5629 					goto end;
  5630 					}
  5631 				}
  5632 			}
  5633 		}
  5634 	// Look for extended partitions
  5635 	for (p=pE-16; p>=pS; p-=16)
  5636 		{
  5637 		SPart pt(p);
  5638 		if ((pt.iType==0x05 || pt.iType==0x0f) && pt.iSectors>0)
  5639 			{
  5640 			// This one is an EBR
  5641 			p[4] = 0;
  5642 			if (iStackPointer == EMaxNest)
  5643 				{
  5644 				if (iStackPointer == orig_sp)
  5645 					continue;
  5646 				--iStackPointer;
  5647 				for(sp = orig_sp; sp<iStackPointer; ++sp)
  5648 					iStack[sp] = iStack[sp+1];
  5649 				}
  5650 			iStack[iStackPointer].iRSS = pt.iRSS;
  5651 			iStack[iStackPointer].iSectors = pt.iSectors;
  5652 			++iStackPointer;
  5653 #ifdef _DEBUG
  5654 			for (sp=0; sp<iStackPointer; ++sp)
  5655 				{
  5656 				const TInt64& rss = iStack[sp].iRSS;
  5657 				const TInt64& size = iStack[sp].iSectors;
  5658 				__KTRACE_OPT(KLOCDRV, Kern::Printf("Stack[%d] RSS %08x %08x SIZE %08x %08x", sp,
  5659 					I64HIGH(rss), I64LOW(rss), I64HIGH(size), I64LOW(size) ));
  5660 				OstTraceExt5(TRACE_INTERNALS, PARTITIONTABLESCANNER_NEXTLBA3, "Stack[%d] RSS 0x%x 0x%x SIZE 0x%08x 0x%08x", (TInt) sp, (TUint) I64HIGH(rss), (TUint) I64LOW(rss), (TUint) I64HIGH(size), (TUint) I64LOW(size));
  5661 				}
  5662 #endif
  5663 			}
  5664 		}
  5665 	// Look for other data partitions
  5666 	for (p=pS; p<pE; p+=16)
  5667 		{
  5668 		SPart pt(p);
  5669 		if (pt.iType && pt.iSectors>0)
  5670 			{
  5671 			pt.iRSS += TUint32(iLBA);	// data partitions are specified relative to the EBR they appear in
  5672 			r = MakeEntry(pt);
  5673 			if (r!=KErrNone)
  5674 				{
  5675 				iLBA = r;
  5676 				goto end;
  5677 				}
  5678 			}
  5679 		}
  5680 	// If any EBRs on stack, pop off the first and process it
  5681 	if (iStackPointer)
  5682 		{
  5683 		--iStackPointer;
  5684 		iLBA = iFirstEBR + iStack[iStackPointer].iRSS;	// LBA of second and subsequent EBR is specified relative to first EBR
  5685 		if (!iFirstEBR)
  5686 			iFirstEBR = iLBA;
  5687 		}
  5688 	else
  5689 		iLBA = KErrEof;	// finished
  5690 
  5691 end:
  5692 	__KTRACE_OPT(KLOCDRV, Kern::Printf("<TPartitionTableScanner iLBA=%08x %08x", I64HIGH(iLBA), I64LOW(iLBA)));
  5693 	OstTraceExt2( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NEXTLBA3, "TPartitionTableScanner iLBA=0x%08x 0x%08x", I64HIGH(iLBA), I64LOW(iLBA) );
  5694 	OstTraceFunctionExit0( TPARTITIONTABLESCANNER_NEXTLBA_EXIT );
  5695 	return iLBA;
  5696 	}
  5697 
  5698 /**
  5699  * Returns Address and Length of next contiguous Physical memory fragment
  5700  * 
  5701  * @param aAddr On success, populated with the Physical Address of the next fragment.
  5702  * @param aLen  On success, populated with the length in bytes of the next fragment.
  5703  * 
  5704  * @return KErrNone, if successful;
  5705  * 		   KErrNoMemory, if no more memory fragments left.
  5706  * 		   KErrNotSupported, if Physical Memory addressing is not supported by this Media.
  5707  */
  5708 EXPORT_C TInt TLocDrvRequest::GetNextPhysicalAddress(TPhysAddr& aAddr, TInt& aLen)
  5709 	{
  5710 	OstTraceExt2(TRACE_FLOW, TLOCDRVREQUEST_GETNEXTPHYSICALADDRESS_ENTRY, "> TLocDrvRequest::GetNextPhysicalAddress;aAddr=%x;aLen=%d;", (TUint) &aAddr, aLen );
  5711 	if (Flags() & EPhysAddr) 
  5712 		{
  5713 #ifdef __DEMAND_PAGING__
  5714 		if (DMediaPagingDevice::PagingRequest(*this))
  5715 			{
  5716 			return DDmaHelper::GetPhysicalAddress(*this, aAddr, aLen);
  5717 			}
  5718 #endif
  5719 		return Drive()->iDmaHelper->GetPhysicalAddress(aAddr, aLen);
  5720 		}
  5721 	else
  5722 		{
  5723 		OstTraceFunctionExitExt( TLOCDRVREQUEST_GETNEXTPHYSICALADDRESS_EXIT, this, KErrNotSupported );
  5724 		return KErrNotSupported;
  5725 		}
  5726 	}
  5727 
  5728 
  5729 /******************************************************************************
  5730  Entry point
  5731  ******************************************************************************/
  5732 DECLARE_STANDARD_EXTENSION()
  5733 	{
  5734 	__KTRACE_OPT(KBOOT,Kern::Printf("Starting LOCMEDIA extension"));
  5735 
  5736 	// install the HAL function
  5737 	TInt r=Kern::AddHalEntry(EHalGroupMedia,MediaHalFunction,NULL);
  5738 #ifdef __DEMAND_PAGING__
  5739 	if (r==KErrNone)
  5740 		{
  5741 		__KTRACE_OPT(KBOOT,Kern::Printf("Creating LocDrv device"));
  5742 		DLocalDriveFactory* device = new DLocalDriveFactory;
  5743 		if (device==NULL)
  5744 			r=KErrNoMemory;
  5745 		else
  5746 			r=Kern::InstallLogicalDevice(device);
  5747 		__KTRACE_OPT(KBOOT,Kern::Printf("Installing LocDrv device in kernel returned %d",r));
  5748 		}
  5749 #endif // __DEMAND_PAGING__
  5750 	return r;
  5751 	}
  5752 
  5753