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