1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/locmedia/locmedia.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,5753 @@
1.4 +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\drivers\locmedia\locmedia.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "locmedia.h"
1.22 +#include <d32locd.h>
1.23 +#include "dmasupport.h"
1.24 +#include <kernel/cache.h>
1.25 +
1.26 +#include "OstTraceDefinitions.h"
1.27 +#ifdef OST_TRACE_COMPILER_IN_USE
1.28 +#include "locmedia_ost.h"
1.29 +#ifdef __VC32__
1.30 +#pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
1.31 +#endif
1.32 +#include "locmediaTraces.h"
1.33 +#endif
1.34 +
1.35 +
1.36 +#if defined(_DEBUG) && defined(__DEMAND_PAGING__)
1.37 +//#define __DEBUG_DEMAND_PAGING__
1.38 +#endif
1.39 +
1.40 +
1.41 +#if 0
1.42 +#define CHECK_RET(r) if ((r)==KErrNotSupported && (KDebugNum(KSCRATCH))) {NKern::Lock(); *(TInt*)0xfaece5=0;}
1.43 +//#define CHECK_RET(r)
1.44 +#else
1.45 +#define CHECK_RET(r)
1.46 +#endif
1.47 +
1.48 +_LIT(KLddName,"LocDrv");
1.49 +_LIT(KLitMediaDriverName, "Media.*");
1.50 +_LIT(KLitLocMedia,"LocMedia");
1.51 +
1.52 +#define LOCM_FAULT() Kern::Fault("LOCMEDIA",__LINE__)
1.53 +
1.54 +const TInt KMaxLocalDriveCapsLength=256;
1.55 +const TInt KMaxQueryDeviceLength=256;
1.56 +
1.57 +// The maximum amount of user-data which will be pinned. If a request is longer
1.58 +// than this value it will be split up into a number of requests
1.59 +// This value is a bit arbitrary - it needs to be sufficiently large so that transfer
1.60 +// rates don't suffer too much - but it can't be too big or we'd be "stealing" too much
1.61 +// memory from the demand paging pool and starving other processes
1.62 +const TInt KMaxPinData = 256*1024;
1.63 +
1.64 +// The number of locks available for pinning shared by all the drive threads in the system.
1.65 +// If all locks are in use then a single pre-allocated lock is used.
1.66 +const TInt KDynamicPagingLockCount = 8;
1.67 +
1.68 +TLocDrv* TheDrives[KMaxLocalDrives];
1.69 +DMedia* TheMedia[KMaxLocalDrives];
1.70 +HBuf* DriveNames[KMaxLocalDrives];
1.71 +TInt UsedMedia=0;
1.72 +TPasswordStore* ThePasswordStore=NULL;
1.73 +
1.74 +class DPrimaryMediaBase::DBody : public DBase
1.75 + {
1.76 +public:
1.77 + TInt iPhysDevIndex;
1.78 + TInt iRequestCount;
1.79 +#ifdef __DEMAND_PAGING__
1.80 + DMediaPagingDevice* iPagingDevice;
1.81 + TInt iPageSizeMsk; // Mask of page size (e.g. 4096-1 -> 4095)
1.82 + TInt iMediaChanges;
1.83 +#endif
1.84 + };
1.85 +
1.86 +#ifdef __DEMAND_PAGING__
1.87 +DMediaPagingDevice* ThePagingDevices[KMaxLocalDrives];
1.88 +DPrimaryMediaBase* TheRomPagingMedia = NULL;
1.89 +DPrimaryMediaBase* TheDataPagingMedia = NULL;
1.90 +TBool DataPagingDeviceRegistered = EFalse;
1.91 +class DPinObjectAllocator;
1.92 +DPinObjectAllocator* ThePinObjectAllocator = NULL;
1.93 +
1.94 +// The paging media might share a DfcQ with other non-paging media (e.g. 2 MMC/SD cards sharing the same stack)
1.95 +// In this case, we need to avoid taking page faults on the non-paging media too, hence the need for these checks:
1.96 +inline TBool DataPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia)
1.97 + {return TheDataPagingMedia && TheDataPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;}
1.98 +inline TBool RomPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia)
1.99 + {return TheRomPagingMedia && TheRomPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;}
1.100 +
1.101 +
1.102 +
1.103 +/*
1.104 +DPinObjectAllocator
1.105 +
1.106 +Internal class which contains :
1.107 + (1) a queue of pre-allocated TVirtualPinObject's;
1.108 + (2) a single pre-allocated DFragmentationPagingLock object:
1.109 + this may be used if there are no TVirtualPinObject's available or if Kern::PinVirtualMemory() fails
1.110 +*/
1.111 +NONSHARABLE_CLASS(DPinObjectAllocator) : public DBase
1.112 + {
1.113 +public:
1.114 + /*
1.115 + SVirtualPinContainer
1.116 + Internal class encapsulating a TVirtualPinObject.
1.117 + Contains a SDblQueLink so that it may form part of a SDblQue
1.118 + */
1.119 + typedef struct
1.120 + {
1.121 + TVirtualPinObject* iObject;
1.122 + SDblQueLink iLink;
1.123 + } SVirtualPinContainer;
1.124 +
1.125 +public:
1.126 + inline DPinObjectAllocator() {};
1.127 + ~DPinObjectAllocator();
1.128 + TInt Construct(TInt aObjectCount, TUint aNumPages);
1.129 +
1.130 + SVirtualPinContainer* AcquirePinObject();
1.131 + void ReleasePinObject(SVirtualPinContainer* aVirtualPinObject);
1.132 +
1.133 + inline DFragmentationPagingLock& PreAllocatedDataLock() {return *iPreAllocatedDataLock;}
1.134 +
1.135 +private:
1.136 + // array of SVirtualPinContainer's
1.137 + SVirtualPinContainer* iVirtualPinContainers;
1.138 + TInt iObjectCount;
1.139 +
1.140 + // queues containing SVirtualPinContainer's
1.141 + SDblQue iFreeQ;
1.142 +
1.143 + // pre-allocated (small) buffers for locking client data should Kern::PinVirtualMemory() fail
1.144 + DFragmentationPagingLock* iPreAllocatedDataLock;
1.145 +
1.146 + // A mutex to protect access to the pinning objects.
1.147 + NFastMutex iLock;
1.148 +
1.149 +public:
1.150 + TUint iFragmentGranularity;
1.151 + };
1.152 +
1.153 +
1.154 +DPinObjectAllocator::~DPinObjectAllocator()
1.155 + {
1.156 + OstTraceFunctionEntry1( DPINOBJECTALLOCATOR_DPINOBJECTALLOCATOR_ENTRY, this );
1.157 + if (iPreAllocatedDataLock)
1.158 + {
1.159 + iPreAllocatedDataLock->Cleanup();
1.160 + delete iPreAllocatedDataLock;
1.161 + }
1.162 +
1.163 + for (TInt n=0; n<iObjectCount; n++)
1.164 + {
1.165 + SVirtualPinContainer& virtualPinContainer = iVirtualPinContainers[n];
1.166 + if (virtualPinContainer.iObject)
1.167 + Kern::DestroyVirtualPinObject(virtualPinContainer.iObject);
1.168 + }
1.169 +
1.170 + delete [] iVirtualPinContainers;
1.171 + OstTraceFunctionExit1( DPINOBJECTALLOCATOR_DPINOBJECTALLOCATOR_EXIT, this );
1.172 + }
1.173 +
1.174 +TInt DPinObjectAllocator::Construct(TInt aObjectCount, TUint aNumPages)
1.175 + {
1.176 + OstTraceFunctionEntryExt( DPINOBJECTALLOCATOR_CONSTRUCT_ENTRY, this );
1.177 + TInt pageSize = Kern::RoundToPageSize(1);
1.178 + iFragmentGranularity = pageSize * aNumPages;
1.179 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation granularity set to 0x%x", iFragmentGranularity));
1.180 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPINOBJECTALLOCATOR_CONSTRUCT, "Fragmentation granularity=0x%x", iFragmentGranularity);
1.181 +
1.182 + // construct the paging lock containing pre-allocated buffers
1.183 +
1.184 + iPreAllocatedDataLock = new DFragmentationPagingLock();
1.185 + if(!iPreAllocatedDataLock)
1.186 + {
1.187 + OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT1, this, KErrNoMemory );
1.188 + return KErrNoMemory;
1.189 + }
1.190 + TInt r = iPreAllocatedDataLock->Construct(aNumPages);
1.191 + if (r != KErrNone)
1.192 + {
1.193 + OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT2, this, r );
1.194 + return r;
1.195 + }
1.196 +
1.197 +
1.198 + SVirtualPinContainer* iVirtualPinContainers = new SVirtualPinContainer[aObjectCount];
1.199 + if (iVirtualPinContainers == NULL)
1.200 + {
1.201 + OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT3, this, KErrNoMemory );
1.202 + return KErrNoMemory;
1.203 + }
1.204 + memclr(iVirtualPinContainers, sizeof(SVirtualPinContainer) * aObjectCount);
1.205 + iObjectCount = aObjectCount;
1.206 +
1.207 + // construct the queue of dynamic paging locks
1.208 + for (TInt n=0; n<aObjectCount; n++)
1.209 + {
1.210 + SVirtualPinContainer& pinContainer = iVirtualPinContainers[n];
1.211 +
1.212 + TInt r = Kern::CreateVirtualPinObject(pinContainer.iObject);
1.213 + if (r != KErrNone)
1.214 + {
1.215 + OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT4, this, KErrNoMemory );
1.216 + return KErrNoMemory;
1.217 + }
1.218 +
1.219 + iFreeQ.Add(&pinContainer.iLink);
1.220 + }
1.221 +
1.222 + OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT5, this, KErrNone );
1.223 + return KErrNone;
1.224 + }
1.225 +
1.226 +/**
1.227 +returns a SVirtualPinContainer object or NULL if NULL available
1.228 +*/
1.229 +DPinObjectAllocator::SVirtualPinContainer* DPinObjectAllocator::AcquirePinObject()
1.230 + {
1.231 + OstTraceFunctionEntry1( DPINOBJECTALLOCATOR_ACQUIREPINOBJECT_ENTRY, this );
1.232 + SVirtualPinContainer* pinContainer = NULL;
1.233 +
1.234 + NKern::FMWait(&iLock);
1.235 +
1.236 + if (!iFreeQ.IsEmpty())
1.237 + {
1.238 + SDblQueLink* link = iFreeQ.First();
1.239 + pinContainer = _LOFF(link, SVirtualPinContainer, iLink);
1.240 + link->Deque();
1.241 + }
1.242 +
1.243 +
1.244 + NKern::FMSignal(&iLock);
1.245 + OstTraceFunctionExit1( DPINOBJECTALLOCATOR_ACQUIREPINOBJECT_EXIT, this );
1.246 + return pinContainer;
1.247 + }
1.248 +
1.249 +/**
1.250 +returns a SVirtualPinContainer object to the pool
1.251 +*/
1.252 +void DPinObjectAllocator::ReleasePinObject(SVirtualPinContainer* aPinContainer)
1.253 + {
1.254 + OstTraceFunctionEntry1( DPINOBJECTALLOCATOR_RELEASEPINOBJECT_ENTRY, this );
1.255 + NKern::FMWait(&iLock);
1.256 +
1.257 + iFreeQ.Add(&aPinContainer->iLink);
1.258 +
1.259 + NKern::FMSignal(&iLock);
1.260 + OstTraceFunctionExit1( DPINOBJECTALLOCATOR_RELEASEPINOBJECT_EXIT, this );
1.261 + }
1.262 +
1.263 +#endif // __DEMAND_PAGING__
1.264 +
1.265 +
1.266 +/********************************************
1.267 + * Local drive device base class
1.268 + ********************************************/
1.269 +DECLARE_EXTENSION_LDD()
1.270 + {
1.271 + return new DLocalDriveFactory;
1.272 + }
1.273 +
1.274 +DLocalDriveFactory::DLocalDriveFactory()
1.275 +//
1.276 +// Constructor
1.277 +//
1.278 + {
1.279 + OstTraceFunctionEntry1( DLOCALDRIVEFACTORY_DLOCALDRIVEFACTORY_ENTRY, this );
1.280 + iParseMask=KDeviceAllowUnit|KDeviceAllowInfo;
1.281 + iUnitsMask=~(0xffffffff<<KMaxLocalDrives);
1.282 + iVersion=TVersion(KLocalDriveMajorVersion,KLocalDriveMinorVersion,KLocalDriveBuildVersion);
1.283 + OstTraceFunctionExit1( DLOCALDRIVEFACTORY_DLOCALDRIVEFACTORY_EXIT, this );
1.284 + }
1.285 +
1.286 +TInt DLocalDriveFactory::Install()
1.287 +//
1.288 +// Install the device driver.
1.289 +//
1.290 + {
1.291 + return SetName(&KLddName);
1.292 + }
1.293 +
1.294 +void DLocalDriveFactory::GetCaps(TDes8& /*aDes*/) const
1.295 +//
1.296 +// Return the Comm capabilities.
1.297 +//
1.298 + {
1.299 +// TCapsLocalDriveV01 b;
1.300 +// b.version=iVersion;
1.301 +// aDes.FillZ(aDes.MaxLength());
1.302 +// aDes.Copy((TUint8 *)&b,Min(aDes.MaxLength(),sizeof(b)));
1.303 + }
1.304 +
1.305 +TInt DLocalDriveFactory::Create(DLogicalChannelBase*& aChannel)
1.306 +//
1.307 +// Create a channel on the device.
1.308 +//
1.309 + {
1.310 + OstTraceFunctionEntry1( DLOCALDRIVEFACTORY_CREATE_ENTRY, this );
1.311 + aChannel=new DLocalDrive;
1.312 + return aChannel?KErrNone:KErrNoMemory;
1.313 + }
1.314 +
1.315 +/********************************************
1.316 + * Local drive interface class
1.317 + ********************************************/
1.318 +DLocalDrive::DLocalDrive()
1.319 + {
1.320 +// iLink.iNext=NULL;
1.321 + }
1.322 +
1.323 +DLocalDrive::~DLocalDrive()
1.324 + {
1.325 + OstTraceFunctionEntry1( DLOCALDRIVE_DLOCALDRIVE_ENTRY, this );
1.326 + if (iDrive)
1.327 + {
1.328 + __KTRACE_OPT(KLOCDRV,Kern::Printf(">DLocalDrive::DoClose D:%d, M:%08x",iDrive->iDriveNumber,iDrive->iMedia));
1.329 + iDrive->Disconnect(this);
1.330 + __KTRACE_OPT(KLOCDRV,Kern::Printf("<DLocalDrive::DoClose D:%d, M:%08x",iDrive->iDriveNumber,iDrive->iMedia));
1.331 + }
1.332 + DThread* pC=NULL;
1.333 + NKern::LockSystem();
1.334 + if (iCleanup.iThread)
1.335 + {
1.336 + pC=iCleanup.iThread;
1.337 + iCleanup.Remove();
1.338 + iCleanup.iThread=NULL;
1.339 + }
1.340 + NKern::UnlockSystem();
1.341 + if (pC) // original client may already have terminated
1.342 + {
1.343 + if (iNotifyChangeRequest)
1.344 + Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrCancel);
1.345 + pC->Close(NULL); // balances Open() in DoCreate
1.346 + }
1.347 + if (iNotifyChangeRequest)
1.348 + Kern::DestroyClientRequest(iNotifyChangeRequest);
1.349 + OstTraceFunctionExit1( DLOCALDRIVE_DLOCALDRIVE_EXIT, this );
1.350 + }
1.351 +
1.352 +TInt DLocalDrive::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer)
1.353 + {
1.354 + OstTraceFunctionEntry1( DLOCALDRIVE_DOCREATE_ENTRY, this );
1.355 +
1.356 + if(!Kern::CurrentThreadHasCapability(ECapabilityTCB,__PLATSEC_DIAGNOSTIC_STRING("Checked by ELOCD.LDD (Local Media Driver)")))
1.357 + {
1.358 + OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT1, this, KErrPermissionDenied );
1.359 + return KErrPermissionDenied;
1.360 + }
1.361 + if (!Kern::QueryVersionSupported(TVersion(KLocalDriveMajorVersion,KLocalDriveMinorVersion,KLocalDriveBuildVersion),aVer))
1.362 + {
1.363 + OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT2, this, KErrNotSupported );
1.364 + return KErrNotSupported;
1.365 + }
1.366 +
1.367 + NKern::ThreadEnterCS();
1.368 + TInt r = Kern::CreateClientDataRequest(iNotifyChangeRequest);
1.369 + NKern::ThreadLeaveCS();
1.370 + if (r != KErrNone)
1.371 + {
1.372 + OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT3, this, r );
1.373 + return r;
1.374 + }
1.375 +
1.376 + DThread& t=Kern::CurrentThread();
1.377 + NKern::LockSystem();
1.378 + t.AddCleanup(&iCleanup);
1.379 + NKern::UnlockSystem();
1.380 + t.Open();
1.381 + iNotifyChangeRequest->SetDestPtr((TBool*) anInfo);
1.382 +
1.383 + iDrive=TheDrives[aUnit];
1.384 + if (!iDrive)
1.385 + {
1.386 + OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT4, this, KErrNotSupported );
1.387 + return KErrNotSupported;
1.388 + }
1.389 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DLocalDrive Create - connect to drive %d, M:%08x",iDrive->iDriveNumber,iDrive->iMedia));
1.390 + r=iDrive->Connect(this);
1.391 + __KTRACE_OPT(KLOCDRV,Kern::Printf("<DLocalDrive Create D:%d, M:%08x r:%d",iDrive->iDriveNumber,iDrive->iMedia,r));
1.392 +
1.393 + if (r!=KErrNone)
1.394 + iDrive=NULL; // didn't connect so don't disconnect
1.395 +
1.396 + OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT5, this, r );
1.397 + return r;
1.398 + }
1.399 +
1.400 +#if defined(_DEBUG)
1.401 +void DebugDumpDriveCaps(const TLocDrv* aDrive, const TAny* aCaps)
1.402 + {
1.403 + const TLocalDriveCapsV5& c=*(const TLocalDriveCapsV5*)aCaps;
1.404 + Kern::Printf("Drive %d Caps:", aDrive->iDriveNumber);
1.405 + Kern::Printf("Size: %lx", c.iSize);
1.406 + Kern::Printf("Type: %08x", c.iType);
1.407 + Kern::Printf("Bus : %08x", c.iConnectionBusType);
1.408 + Kern::Printf("DAtt: %08x", c.iDriveAtt);
1.409 + Kern::Printf("MAtt: %08x", c.iMediaAtt);
1.410 + Kern::Printf("Base: %08x", c.iBaseAddress);
1.411 + Kern::Printf("FSID: %04x", c.iFileSystemId);
1.412 + Kern::Printf("PTYP: %04x", c.iPartitionType);
1.413 + Kern::Printf("HIDN: %08x", c.iHiddenSectors);
1.414 + Kern::Printf("EBSZ: %08x", c.iEraseBlockSize);
1.415 + //---------------- V5 ------------------//
1.416 + if (c.iSerialNumLength != 0)
1.417 + {
1.418 + Kern::Printf("SN: length is %d", c.iSerialNumLength);
1.419 + TBuf8<2*KMaxSerialNumLength+20> snBuf;
1.420 + snBuf.Append(_L8("SN: content is "));
1.421 + for (TUint i=0; i<c.iSerialNumLength; i++)
1.422 + snBuf.AppendNumFixedWidth(c.iSerialNum[i], EHex, 2);
1.423 + Kern::Printf((const char*)snBuf.Ptr());
1.424 + }
1.425 + else
1.426 + Kern::Printf("SN: not supported");
1.427 + }
1.428 +#endif
1.429 +
1.430 +/*
1.431 + * Requests are passed in message as follows:
1.432 + * iValue = request ID
1.433 + * iArg[0,1]= Position
1.434 + * iArg[2,3]= Length
1.435 + * iArg[4] = Pointer to remote thread (NULL if client)
1.436 + * iArg[5] = Pointer to remote descriptor
1.437 + * iArg[6] = Offset into remote descriptor
1.438 + * iArg[7] = Flags (whole media)
1.439 + * iArg[8] = Pointer to TLocDrv
1.440 + */
1.441 +
1.442 +TInt DLocalDrive::Request(TInt aFunction, TAny* a1, TAny* a2)
1.443 + {
1.444 + OstTraceFunctionEntry1( DLOCALDRIVE_REQUEST_ENTRY, this );
1.445 + __TRACE_TIMING(0);
1.446 + __KTRACE_OPT(KLOCDRV,Kern::Printf(">DLocalDrive::DoControl D:%d M:%08x F:%d A1:%08x A2:%08x",
1.447 + iDrive->iDriveNumber, iDrive->iMedia, aFunction, a1, a2));
1.448 + 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 );
1.449 +
1.450 + TInt r=KErrNotSupported;
1.451 + TLocDrvRequest& m=TLocDrvRequest::Get();
1.452 + m.Flags()=0;
1.453 + m.Drive()=iDrive;
1.454 + switch (aFunction)
1.455 + {
1.456 + case RLocalDrive::EControlRead:
1.457 + {
1.458 + m.Id()=ERead;
1.459 + r=m.ProcessMessageData(a1);
1.460 + __TRACE_TIMING(1);
1.461 + if (r==KErrNone)
1.462 + {
1.463 + __TRACE_TIMING(2);
1.464 + 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);
1.465 + r=iDrive->Request(m);
1.466 + __TRACE_TIMING(3);
1.467 + 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 );
1.468 + }
1.469 + m.CloseRemoteThread();
1.470 + break;
1.471 + }
1.472 + case RLocalDrive::EControlWrite:
1.473 + {
1.474 + m.Id()=EWrite;
1.475 + r=m.ProcessMessageData(a1);
1.476 + if (r==KErrNone)
1.477 + {
1.478 + 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 );
1.479 + r=iDrive->Request(m);
1.480 + 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 );
1.481 + }
1.482 + m.CloseRemoteThread();
1.483 + break;
1.484 + }
1.485 + case RLocalDrive::EControlCaps:
1.486 + {
1.487 + TBuf8<KMaxLocalDriveCapsLength> capsBuf;
1.488 + capsBuf.SetMax();
1.489 + capsBuf.FillZ();
1.490 + m.Id()=ECaps;
1.491 + m.RemoteDes()=(TAny*)capsBuf.Ptr(); // overload this
1.492 + m.Length()=KMaxLocalDriveCapsLength; // for pinning
1.493 + r=iDrive->Request(m);
1.494 +
1.495 + if(r == KErrNone && iDrive->iMedia != NULL && iDrive->iMedia->iDriver != NULL)
1.496 + {
1.497 + // Fill in default media size if not specified by the driver
1.498 + //
1.499 + // - This uses the members of TLocalDriveCapsV4 which was primarily used
1.500 + // to report NAND flash characteristics, but are general enough to be
1.501 + // used to report the size of any type of media without adding yet
1.502 + // another extension to TLocalDriveCapsVx.
1.503 + //
1.504 +
1.505 + TLocalDriveCapsV4& caps = *(TLocalDriveCapsV4*)capsBuf.Ptr();
1.506 +
1.507 + if(caps.iSectorSizeInBytes == 0)
1.508 + {
1.509 + // Fill in a default value for the disk sector size
1.510 + caps.iSectorSizeInBytes = 512;
1.511 +
1.512 + // Zero the number of sectors, as a sector count makes no sense without a sector size
1.513 + // - Fault in debug mode if a sector count is provided to ensure that media driver creators
1.514 + // set this value,but in release mode continue gracefully be recalculating the sector count.
1.515 + __ASSERT_DEBUG(caps.iNumberOfSectors == 0, LOCM_FAULT());
1.516 + caps.iNumberOfSectors = 0;
1.517 + caps.iNumPagesPerBlock = 1; // ...to ensure compatiility with NAND semantics
1.518 + }
1.519 +
1.520 + if(caps.iNumberOfSectors == 0)
1.521 + {
1.522 + const Int64 totalSizeInSectors = iDrive->iMedia->iDriver->TotalSizeInBytes() / caps.iSectorSizeInBytes;
1.523 + __ASSERT_DEBUG(I64HIGH(totalSizeInSectors) == 0, LOCM_FAULT());
1.524 +
1.525 + if(I64HIGH(totalSizeInSectors) == 0)
1.526 + {
1.527 + caps.iNumberOfSectors = I64LOW(totalSizeInSectors);
1.528 + }
1.529 + }
1.530 + }
1.531 +
1.532 +#if defined(OST_TRACE_COMPILER_IN_USE) && defined(_DEBUG)
1.533 + const TLocalDriveCapsV5& caps=*(const TLocalDriveCapsV5*)capsBuf.Ptr();
1.534 +#endif
1.535 +
1.536 + 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);
1.537 + 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);
1.538 +
1.539 +#if defined(_DEBUG)
1.540 + __KTRACE_OPT(KLOCDRV,DebugDumpDriveCaps(iDrive,capsBuf.Ptr()));
1.541 +#endif
1.542 + Kern::InfoCopy(*(TDes8*)a1, capsBuf);
1.543 + break;
1.544 + }
1.545 + case RLocalDrive::EControlFormat:
1.546 + {
1.547 + m.Id()=EFormat;
1.548 + r=m.ProcessMessageData(a1);
1.549 + if (r==KErrNone)
1.550 + {
1.551 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORMAT, "EFormat; TLocDrvRequest Object=0x%x", (TUint) &m);
1.552 + r=iDrive->Request(m);
1.553 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORMAT_RETURN, "EFormat Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.554 + }
1.555 + break;
1.556 + }
1.557 + case RLocalDrive::EControlEnlarge:
1.558 + if ((TInt)a1<0)
1.559 + {
1.560 + r=KErrArgument;
1.561 + break;
1.562 + }
1.563 + m.Length()=(TInt)a1;
1.564 + m.Id()=EEnlarge;
1.565 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_ENLARGE, "EEnlarge; TLocDrvRequest Object=0x%x", (TUint) &m);
1.566 + r=iDrive->Request(m);
1.567 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_ENLARGE_RETURN, "EEnlarge Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.568 + break;
1.569 + case RLocalDrive::EControlReduce:
1.570 + {
1.571 + if ((TInt)a1<0 || (TInt)a2<0)
1.572 + {
1.573 + r=KErrArgument;
1.574 + break;
1.575 + }
1.576 + m.Pos()=(TInt)a1;
1.577 + m.Length()=(TInt)a2;
1.578 + m.Id()=EReduce;
1.579 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_REDUCE, "EReduce; TLocDrvRequest Object=0x%x", (TUint) &m);
1.580 + r=iDrive->Request(m);
1.581 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_REDUCE_RETURN, "EReduce Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.582 + break;
1.583 + }
1.584 + case RLocalDrive::EControlForceMediaChange:
1.585 + m.Pos()=(TInt)a1;
1.586 + m.Id()=EForceMediaChange;
1.587 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORCEMEDIACHANGE, "EForceMediaChange; TLocDrvRequest Object=0x%x", (TUint) &m);
1.588 + r = iDrive->Request(m);
1.589 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORCEMEDIACHANGE_RETURN, "EForceMediaChange Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.590 + break;
1.591 + case RLocalDrive::EControlMediaDevice:
1.592 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLMEDIADEVICE, "EControlMediaDevice; TLocDrvRequest Object=0x%x", (TUint) &m);
1.593 + r=iDrive->iPrimaryMedia->iDevice;
1.594 + break;
1.595 + case RLocalDrive::EControlIsRemovable:
1.596 + {
1.597 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLISREMOVABLE, "EControlIsRemovable; TLocDrvRequest Object=0x%x", (TUint) &m);
1.598 + TInt sockNum;
1.599 + r=iDrive->iPrimaryMedia->IsRemovableDevice(sockNum);
1.600 + if (r)
1.601 + kumemput32(a1,&sockNum,sizeof(TInt));
1.602 + break;
1.603 + }
1.604 + case RLocalDrive::EControlControlIO:
1.605 + {
1.606 + TLocalDriveControlIOData d;
1.607 + kumemget32(&d,a1,sizeof(d));
1.608 +
1.609 + m.Id() = EControlIO;
1.610 + m.iArg[0] = (TAny*) d.iCommand;
1.611 + m.iArg[1] = d.iParam1;
1.612 + m.iArg[2] = d.iParam2;
1.613 +
1.614 + // if d.iHandle is == KLocalMessageHandle (-1),
1.615 + // d.aParam1 and d.aParam2 are TAny* pointers
1.616 + //
1.617 + // if d.iHandle is == 0,
1.618 + // d.aParam1 and d.aParam2 are TInts
1.619 + //
1.620 + // if d.iHandle is > 0,
1.621 + // d.aParam1 is a data pointer (TUint8*)
1.622 + // d.aParam2 is an optional extra paramater (TInt)
1.623 + // d.iHandle is a data length (TInt)
1.624 + m.iArg[3] = (TAny*) d.iHandle;
1.625 +
1.626 + //We're highjacking fields representing
1.627 + //length and position in a normal message, so
1.628 + //let's not have the dispatcher function attempt
1.629 + //to adjust for partition size.
1.630 + m.Flags() |= TLocDrvRequest::EAdjusted;
1.631 +
1.632 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLCONTROLIO, "EControlControlIO; TLocDrvRequest Object=0x%x", (TUint) &m);
1.633 + r=iDrive->Request(m);
1.634 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLCONTROLIO_RETURN, "EControlControlIO Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.635 + break;
1.636 + }
1.637 + case RLocalDrive::EControlSetMountInfo:
1.638 + {
1.639 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLSETMOUNTINFO, "EControlSetMountInfo; TLocDrvRequest Object=0x%x", (TUint) &m);
1.640 + m.Id()=ERead;
1.641 + r=m.ProcessMessageData(a1);
1.642 + DPrimaryMediaBase* pM=iDrive->iPrimaryMedia;
1.643 + if(!pM || r!=KErrNone)
1.644 + break;
1.645 +
1.646 + if (pM->iMountInfo.iThread)
1.647 + {
1.648 + NKern::ThreadEnterCS();
1.649 + //Close original thread
1.650 + Kern::SafeClose((DObject*&) pM->iMountInfo.iThread,NULL);
1.651 + if (m.RemoteDes()!=NULL)
1.652 + {
1.653 + //Set new mount info and leave setting thread open
1.654 +#ifdef __DEMAND_PAGING__
1.655 + // lock the mount info if this is a data paging media - and keep it locked
1.656 + if ((DataPagingDfcQ(pM)) && ((r = LockMountInfo(*pM, m)) != KErrNone))
1.657 + break;
1.658 +#endif
1.659 + pM->iMountInfo.iInfo=(TDesC8*)m.RemoteDes();
1.660 + pM->iMountInfo.iThread=m.RemoteThread();
1.661 + }
1.662 + else
1.663 + {
1.664 + //Clear existing mount info and close setting thread
1.665 +
1.666 +#ifdef __DEMAND_PAGING__
1.667 + // unlock the mount info if this is a data paging media
1.668 + UnlockMountInfo(*pM);
1.669 +#endif
1.670 +
1.671 + pM->iMountInfo.iInfo=NULL;
1.672 + pM->iMountInfo.iThread=NULL;
1.673 + m.CloseRemoteThread();
1.674 + }
1.675 + NKern::ThreadLeaveCS();
1.676 + r=KErrNone;
1.677 + }
1.678 + else
1.679 + {
1.680 + //Setting mount info for the first time
1.681 + if (m.RemoteDes()==NULL)
1.682 + {
1.683 + // if no mount info, close setting thread opened in ProcessMessageData()
1.684 + m.CloseRemoteThread();
1.685 + break;
1.686 + }
1.687 +
1.688 + NKern::ThreadEnterCS();
1.689 +#ifdef __DEMAND_PAGING__
1.690 + // lock the mount info if this is a data paging media - and keep it locked
1.691 + if ((DataPagingDfcQ(pM)) && ((r = LockMountInfo(*pM, m)) != KErrNone))
1.692 + break;
1.693 +#endif
1.694 +
1.695 + pM->iMountInfo.iInfo=(TDesC8*)m.RemoteDes();
1.696 + pM->iMountInfo.iThread=m.RemoteThread();
1.697 + NKern::ThreadLeaveCS();
1.698 + r=KErrNone;
1.699 + }
1.700 + break;
1.701 + }
1.702 + case RLocalDrive::EControlPasswordLock:
1.703 + {
1.704 + m.Id()=EPasswordLock;
1.705 + m.RemoteDes() = a1;
1.706 +
1.707 + TMediaPassword oldPasswd;
1.708 + TMediaPassword newPasswd;
1.709 + TLocalDrivePasswordData pswData;
1.710 + r = ReadPasswordData(m, pswData, oldPasswd, newPasswd);
1.711 +
1.712 + if (r == KErrNone)
1.713 + {
1.714 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDLOCK, "EPasswordLock; TLocDrvRequest Object=0x%x", (TUint) &m);
1.715 + r = iDrive->Request(m);
1.716 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDLOCK_RETURN, "EPasswordLock Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.717 + }
1.718 + break;
1.719 + }
1.720 + case RLocalDrive::EControlPasswordUnlock:
1.721 + {
1.722 + m.Id()=EPasswordUnlock;
1.723 + m.RemoteDes() = a1;
1.724 +
1.725 + TMediaPassword oldPasswd;
1.726 + TMediaPassword newPasswd;
1.727 + TLocalDrivePasswordData pswData;
1.728 + r = ReadPasswordData(m, pswData, oldPasswd, newPasswd);
1.729 +
1.730 + if(r == KErrNone)
1.731 + {
1.732 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDUNLOCK, "EPasswordUnLock; TLocDrvRequest Object=0x%x", (TUint) &m);
1.733 + r=iDrive->Request(m);
1.734 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDUNLOCK_RETURN, "EPasswordUnLock Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.735 + }
1.736 + if (r == KErrNone)
1.737 + iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0;
1.738 + break;
1.739 + }
1.740 + case RLocalDrive::EControlPasswordClear:
1.741 + {
1.742 + m.Id()=EPasswordClear;
1.743 + m.RemoteDes() = a1;
1.744 +
1.745 + TMediaPassword oldPasswd;
1.746 + TMediaPassword newPasswd;
1.747 + TLocalDrivePasswordData pswData;
1.748 + r = ReadPasswordData(m, pswData, oldPasswd, newPasswd);
1.749 +
1.750 + if (r == KErrNone)
1.751 + {
1.752 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDCLEAR, "EPasswordClear; TLocDrvRequest Object=0x%x", (TUint) &m);
1.753 + r = iDrive->Request(m);
1.754 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDCLEAR_RETURN, "EPasswordClear Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.755 + }
1.756 + break;
1.757 + }
1.758 + case RLocalDrive::EControlPasswordErase:
1.759 + {
1.760 + m.Id()=EPasswordErase;
1.761 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDERASE, "EPasswordErase; TLocDrvRequest Object=0x%x", (TUint) &m);
1.762 + r=iDrive->Request(m);
1.763 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDERASE_RETURN, "EPasswordErase Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.764 + if(r == KErrNone)
1.765 + iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0;
1.766 + break;
1.767 + }
1.768 + case RLocalDrive::EControlNotifyChange:
1.769 + if (iCleanup.iThread != &Kern::CurrentThread())
1.770 + Kern::PanicCurrentThread(KLitLocMedia,KErrAccessDenied);
1.771 + r=KErrNone;
1.772 + if (!iNotifyChangeRequest->StatusPtr())
1.773 + r = iNotifyChangeRequest->SetStatus((TRequestStatus*) a1);
1.774 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLNOTIFYCHANGE, "EControlNotifyChange; TLocDrvRequest Object=0x%x", (TUint) &m);
1.775 + break;
1.776 + case RLocalDrive::EControlNotifyChangeCancel:
1.777 + if (iCleanup.iThread != &Kern::CurrentThread())
1.778 + Kern::PanicCurrentThread(KLitLocMedia,KErrAccessDenied);
1.779 + Kern::QueueRequestComplete(iCleanup.iThread,iNotifyChangeRequest,KErrCancel);
1.780 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLNOTIFYCHANGECANCEL, "EControlNotifyChangeCancel; TLocDrvRequest Object=0x%x", (TUint) &m);
1.781 + break;
1.782 + case RLocalDrive::EControlReadPasswordStore:
1.783 + {
1.784 + TUint8 passData[TPasswordStore::EMaxPasswordLength];
1.785 + m.RemoteDes() = (TAny*) passData;
1.786 + m.Length() = sizeof(passData);
1.787 + m.Id()=EReadPasswordStore;
1.788 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READPASSWORDSTORE, "EReadPasswordStore; TLocDrvRequest Object=0x%x", (TUint) &m);
1.789 + r=iDrive->Request(m);
1.790 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READPASSWORDSTORE_RETURN, "EReadPasswordStore Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.791 + if (r==KErrNone)
1.792 + {
1.793 + TPtr8 pData(passData, (TInt) m.Length(), TPasswordStore::EMaxPasswordLength);
1.794 + m.RemoteDes()=(TDes8*)a1;
1.795 + r = m.WriteRemote(&pData,0);
1.796 + }
1.797 + break;
1.798 + }
1.799 + case RLocalDrive::EControlWritePasswordStore:
1.800 + {
1.801 + TUint8 passData[TPasswordStore::EMaxPasswordLength];
1.802 + TPtr8 pData(passData, TPasswordStore::EMaxPasswordLength);
1.803 +
1.804 + DThread* pT=m.RemoteThread();
1.805 + if (!pT)
1.806 + pT=m.Client();
1.807 +
1.808 + m.RemoteDes() = (TDes8*)a1;
1.809 + r = Kern::ThreadGetDesLength(pT, m.RemoteDes());
1.810 + if ( r > pData.MaxLength() )
1.811 + r = KErrOverflow;
1.812 + if ( r < KErrNone)
1.813 + break;
1.814 +
1.815 + r = m.ReadRemote(&pData,0);
1.816 + if (r != KErrNone)
1.817 + break;
1.818 +
1.819 +
1.820 + m.RemoteDes() = (TAny*) pData.Ptr();
1.821 + m.Length() = pData.Length();
1.822 + m.Id()=EWritePasswordStore;
1.823 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITEPASSWORDSTORE, "EWritePasswordStore; TLocDrvRequest Object=0x%x", (TUint) &m);
1.824 + r=iDrive->Request(m);
1.825 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITEPASSWORDSTORE_RETURN, "EReadPasswordStore Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.826 + if(r == KErrNone)
1.827 + iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0;
1.828 + break;
1.829 + }
1.830 + case RLocalDrive::EControlPasswordStoreLengthInBytes:
1.831 + {
1.832 + m.Id()=EPasswordStoreLengthInBytes;
1.833 + TInt length;
1.834 + m.RemoteDes() = (TAny*) &length;
1.835 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDSTORELENGTH, "EPasswordStoreLengthInBytes; TLocDrvRequest Object=0x%x", (TUint) &m);
1.836 + r=iDrive->Request(m);
1.837 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDSTORELENGTH_RETURN, "EPasswordStoreLengthInBytes Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.838 +
1.839 + if (r == KErrNone)
1.840 + {
1.841 + m.RemoteDes()=a1;
1.842 + r = m.WriteRemoteRaw(&length,sizeof(TInt));
1.843 + }
1.844 +
1.845 + break;
1.846 + }
1.847 + case RLocalDrive::EControlGetLastErrorInfo:
1.848 + {
1.849 + m.Id()=EGetLastErrorInfo;
1.850 + m.iArg[0]=this;
1.851 + TErrorInfoBuf errorInfoBuf;
1.852 + errorInfoBuf.SetMax();
1.853 + errorInfoBuf.FillZ();
1.854 + m.RemoteDes()=(TAny*) errorInfoBuf.Ptr(); // overload this
1.855 + m.Length() = errorInfoBuf.MaxLength();
1.856 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_GETLASTERRORINFO, "EGetLastErrorInfo; TLocDrvRequest Object=0x%x", (TUint) &m);
1.857 + r=iDrive->Request(m);
1.858 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLGETLASTERRORINFO_RETURN, "EControlGetLastErrorInfo Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.859 + Kern::InfoCopy(*(TDes8*)a1, errorInfoBuf);
1.860 + break;
1.861 + }
1.862 + case RLocalDrive::EControlDeleteNotify:
1.863 + {
1.864 + m.Id()=EDeleteNotify;
1.865 + r=m.ProcessMessageData(a1);
1.866 + if (r==KErrNone)
1.867 + {
1.868 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_DELETENOTIFY, "EDeleteNotify; TLocDrvRequest Object=0x%x", (TUint) &m);
1.869 + r=iDrive->Request(m);
1.870 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_DELETENOTIFY_RETURN, "EDeleteNotify Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.871 + }
1.872 + break;
1.873 + }
1.874 +
1.875 + case RLocalDrive::EControlQueryDevice:
1.876 + {
1.877 + TBuf8<KMaxQueryDeviceLength> queryBuf;
1.878 + queryBuf.SetMax();
1.879 + queryBuf.FillZ();
1.880 +
1.881 + m.Id() = EQueryDevice;
1.882 + m.iArg[0] = a1; // RLocalDrive::TQueryDevice
1.883 + m.RemoteDes() = (TAny*)queryBuf.Ptr(); // overload this
1.884 + m.Length() = KMaxLocalDriveCapsLength; // for pinning
1.885 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE, "EQueryDevice; TLocDrvRequest Object=0x%x", (TUint) &m);
1.886 + r=iDrive->Request(m);
1.887 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE_RETURN, "EQueryDevice Return; TLocDrvRequest Object=0x%x", (TUint) &m);
1.888 + Kern::InfoCopy(*(TDes8*)a2, queryBuf);
1.889 + break;
1.890 + }
1.891 +
1.892 + }
1.893 + __KTRACE_OPT(KLOCDRV,Kern::Printf("<DLocalDrive::DoControl D:%d M:%08x ret %d",iDrive->iDriveNumber, iDrive->iMedia, r));
1.894 + __TRACE_TIMING(4);
1.895 + OstTraceFunctionExitExt( DLOCALDRIVE_REQUEST_EXIT, this, r );
1.896 + return r;
1.897 + }
1.898 +
1.899 +TInt DLocalDrive::ReadPasswordData(TLocDrvRequest& aReq, TLocalDrivePasswordData& aPswData, TMediaPassword& aOldPasswd, TMediaPassword& aNewPasswd)
1.900 + {
1.901 + TLocalDrivePasswordData clientData;
1.902 + TInt r = aReq.ReadRemoteRaw(&clientData, sizeof(TLocalDrivePasswordData));
1.903 +
1.904 + DThread* pT = aReq.RemoteThread();
1.905 + if (!pT)
1.906 + pT = aReq.Client();
1.907 +
1.908 + if (r == KErrNone)
1.909 + r = Kern::ThreadDesRead(pT, clientData.iOldPasswd, aOldPasswd, 0 ,KChunkShiftBy0);
1.910 + if (r == KErrNone)
1.911 + r = Kern::ThreadDesRead(pT, clientData.iNewPasswd, aNewPasswd, 0 ,KChunkShiftBy0);
1.912 +
1.913 + aPswData.iStorePasswd = clientData.iStorePasswd;
1.914 + aPswData.iOldPasswd = &aOldPasswd;
1.915 + aPswData.iNewPasswd = &aNewPasswd;
1.916 +
1.917 +
1.918 + aReq.RemoteDes() = (TAny*) &aPswData;
1.919 + aReq.Flags()|= TLocDrvRequest::EKernelBuffer;
1.920 +
1.921 + return r;
1.922 + }
1.923 +
1.924 +
1.925 +#ifdef __DEMAND_PAGING__
1.926 +TInt DLocalDrive::LockMountInfo(DPrimaryMediaBase& aPrimaryMedia, TLocDrvRequest& aReq)
1.927 + {
1.928 + OstTraceExt2(TRACE_FLOW, DLOCALDRIVE_LOCKMOUNTINFO_ENTRY, "> aPrimaryMedia=%x;aReq=%x", (TUint) &aPrimaryMedia, (TUint) &aReq );
1.929 + DMediaPagingDevice* pagingDevice = aPrimaryMedia.iBody->iPagingDevice;
1.930 + if (pagingDevice == NULL)
1.931 + {
1.932 + OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT1, this, KErrNone );
1.933 + return KErrNone;
1.934 + }
1.935 +
1.936 + __ASSERT_DEBUG(pagingDevice->iMountInfoDataLock == NULL, LOCM_FAULT());
1.937 + __ASSERT_DEBUG(pagingDevice->iMountInfoDescHdrLock == NULL, LOCM_FAULT());
1.938 + __ASSERT_DEBUG(pagingDevice->iMountInfoDescLenLock == NULL, LOCM_FAULT());
1.939 +
1.940 + DThread* pT = aReq.RemoteThread();
1.941 + if (!pT)
1.942 + pT = &Kern::CurrentThread(); // e.g. when using TBusLocalDrive directly
1.943 +
1.944 + TInt length = 0;
1.945 + TInt maxLength = 0;
1.946 + TUint8* desAddress = NULL;
1.947 + TInt r = Kern::ThreadGetDesInfo(pT,aReq.RemoteDes(),length,maxLength,desAddress,EFalse); // get descriptor length, maxlength and desAddress
1.948 + if (r != KErrNone)
1.949 + {
1.950 + OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT2, this, r );
1.951 + return r;
1.952 + }
1.953 + if (length == 0)
1.954 + {
1.955 + OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT3, this, KErrNone );
1.956 + return KErrNone;
1.957 + }
1.958 +
1.959 +
1.960 + static const TUint8 LengthLookup[16]={4,8,12,8,12,0,0,0,0,0,0,0,0,0,0,0};
1.961 + TUint32 desHdr;
1.962 + r = Kern::ThreadRawRead(pT, aReq.RemoteDes(), &desHdr, sizeof(desHdr));
1.963 + if(r!=KErrNone)
1.964 + {
1.965 + OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT4, this, r );
1.966 + return r;
1.967 + }
1.968 + TInt desType = desHdr >>KShiftDesType8;
1.969 + TInt desHdrLen = LengthLookup[desType];
1.970 + if(!desHdrLen)
1.971 + {
1.972 + OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT5, this, KErrBadDescriptor );
1.973 + return KErrBadDescriptor;
1.974 + }
1.975 +
1.976 +
1.977 + pagingDevice->iMountInfoDataLock = ThePinObjectAllocator->AcquirePinObject();
1.978 + pagingDevice->iMountInfoDescHdrLock = ThePinObjectAllocator->AcquirePinObject();
1.979 + pagingDevice->iMountInfoDescLenLock = ThePinObjectAllocator->AcquirePinObject();
1.980 +
1.981 + if (pagingDevice->iMountInfoDataLock == NULL ||
1.982 + pagingDevice->iMountInfoDescHdrLock == NULL ||
1.983 + pagingDevice->iMountInfoDescLenLock == NULL)
1.984 + {
1.985 + UnlockMountInfo(aPrimaryMedia); // tidy up
1.986 + OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT6, this, KErrNoMemory );
1.987 + return KErrNoMemory;
1.988 + }
1.989 +
1.990 +
1.991 + // First pin the descriptor header
1.992 + DPinObjectAllocator::SVirtualPinContainer* lock;
1.993 + lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock;
1.994 + r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) (TUint8*) aReq.RemoteDes(), desHdrLen, pT);
1.995 + if (r != KErrNone)
1.996 + {
1.997 + UnlockMountInfo(aPrimaryMedia); // tidy up
1.998 + OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT7, this, KErrNoMemory );
1.999 + return KErrNoMemory;
1.1000 + }
1.1001 +
1.1002 +
1.1003 +
1.1004 + // For EBufCPtr-type descriptors, need to pin the extra length before the buffer (!)
1.1005 + lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock;
1.1006 + if (desType == EBufCPtr)
1.1007 + {
1.1008 + TLinAddr extraLenAddr = TLinAddr(desAddress) - aReq.RemoteDesOffset() - sizeof(TUint32);
1.1009 + r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) (TUint8*) extraLenAddr, sizeof(TUint32), pT);
1.1010 + if (r != KErrNone)
1.1011 + {
1.1012 + UnlockMountInfo(aPrimaryMedia); // tidy up
1.1013 + OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT8, this, KErrNoMemory );
1.1014 + return KErrNoMemory;
1.1015 + }
1.1016 + }
1.1017 +
1.1018 +
1.1019 + // Now pin the descriptor contents
1.1020 + lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock;
1.1021 + r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) desAddress, length, pT);
1.1022 + if (r != KErrNone)
1.1023 + {
1.1024 + UnlockMountInfo(aPrimaryMedia); // tidy up
1.1025 + OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT9, this, KErrNoMemory );
1.1026 + return KErrNoMemory;
1.1027 + }
1.1028 +
1.1029 + OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT10, this, KErrNone );
1.1030 + return KErrNone;
1.1031 + }
1.1032 +
1.1033 +
1.1034 +void DLocalDrive::UnlockMountInfo(DPrimaryMediaBase& aPrimaryMedia)
1.1035 + {
1.1036 + OstTrace1(TRACE_FLOW, DLOCALDRIVE_UNLOCKMOUNTINFO_ENTRY, "> DLocalDrive::UnlockMountInfo;aPrimaryMedia=%x", (TUint) &aPrimaryMedia);
1.1037 +
1.1038 + DMediaPagingDevice* pagingDevice = aPrimaryMedia.iBody->iPagingDevice;
1.1039 + if (pagingDevice == NULL || pagingDevice->iMountInfoDataLock == NULL)
1.1040 + {
1.1041 + OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT1, this );
1.1042 + return;
1.1043 + }
1.1044 +
1.1045 +
1.1046 + if (pagingDevice->iMountInfoDataLock)
1.1047 + {
1.1048 + Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock)->iObject);
1.1049 + ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock);
1.1050 + pagingDevice->iMountInfoDataLock = NULL;
1.1051 + }
1.1052 +
1.1053 + if (pagingDevice->iMountInfoDescHdrLock)
1.1054 + {
1.1055 + Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock)->iObject);
1.1056 + ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock);
1.1057 + pagingDevice->iMountInfoDescHdrLock = NULL;
1.1058 + }
1.1059 +
1.1060 + if (pagingDevice->iMountInfoDescLenLock)
1.1061 + {
1.1062 + Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock)->iObject);
1.1063 + ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock);
1.1064 + pagingDevice->iMountInfoDescLenLock = NULL;
1.1065 + }
1.1066 +
1.1067 + OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT2, this );
1.1068 + }
1.1069 +#endif // __DEMAND_PAGING__
1.1070 +
1.1071 +void DLocalDrive::NotifyChange(DPrimaryMediaBase& aPrimaryMedia, TBool aMediaChange)
1.1072 + {
1.1073 + OstTraceExt2( TRACE_FLOW, DLOCALDRIVE_NOTIFYCHANGE_ENTRY, "> DLocalDrive::NotifyChange;aPrimaryMedia=%x;aMediaChange=%d", (TUint) &aPrimaryMedia, aMediaChange );
1.1074 +#ifndef __DEMAND_PAGING__
1.1075 + aPrimaryMedia;
1.1076 +#endif
1.1077 +
1.1078 + // Complete any notification request on media change or power down
1.1079 + if (aMediaChange)
1.1080 + {
1.1081 + DThread* pC=NULL;
1.1082 + NKern::LockSystem();
1.1083 + if (iCleanup.iThread)
1.1084 + {
1.1085 + pC=iCleanup.iThread;
1.1086 + pC->Open();
1.1087 + }
1.1088 + NKern::UnlockSystem();
1.1089 + if (pC)
1.1090 + {
1.1091 + TBool b = ETrue;
1.1092 + // if change not yet queued, queue it now
1.1093 + if (iNotifyChangeRequest->IsReady())
1.1094 + {
1.1095 + *((TBool*) iNotifyChangeRequest->Buffer()) = b;
1.1096 + Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrNone);
1.1097 + }
1.1098 + // If change has not even been requested by the client, maintain the pre-wdp behaviour
1.1099 + // and write data immediately back to client (possibly taking a page fault)
1.1100 + // N.B. Must NOT do this on data paging media
1.1101 +#ifdef __DEMAND_PAGING__
1.1102 + else if (!DataPagingDfcQ(&aPrimaryMedia))
1.1103 +#else
1.1104 + else
1.1105 +#endif
1.1106 + {
1.1107 + Kern::ThreadRawWrite(pC, iNotifyChangeRequest->DestPtr(), &b, sizeof(b), NULL);
1.1108 + }
1.1109 + pC->AsyncClose();
1.1110 + }
1.1111 + }
1.1112 + OstTraceFunctionExit1( DLOCALDRIVE_NOTIFYCHANGE_EXIT, this );
1.1113 + }
1.1114 +
1.1115 +TLocalDriveCleanup::TLocalDriveCleanup()
1.1116 + {
1.1117 + }
1.1118 +
1.1119 +// This will be called when the original client thread exits
1.1120 +// It is called in the context of the exiting thread with the system locked.
1.1121 +void TLocalDriveCleanup::Cleanup()
1.1122 + {
1.1123 + DLocalDrive& d=LocalDrive();
1.1124 + d.iNotifyChangeRequest=NULL;
1.1125 + DThread* pC=iThread;
1.1126 + Remove();
1.1127 + iThread=NULL;
1.1128 + NKern::UnlockSystem();
1.1129 + pC->Close(NULL); // balances Open() in DoCreate
1.1130 + NKern::LockSystem();
1.1131 + }
1.1132 +
1.1133 +/********************************************
1.1134 + * Local drive request class
1.1135 + ********************************************/
1.1136 +
1.1137 +/**
1.1138 +Reads data from the descriptor specified in the request, from the requesting
1.1139 +thread's process.
1.1140 +
1.1141 +This is used by the media driver to read data from a descriptor in the
1.1142 +requesting thread. The remote data is copied into the specified descriptor,
1.1143 +starting at the specified offset within that descriptor's data area.
1.1144 +
1.1145 +@param aDes The target descriptor into which data from the remote thread
1.1146 + is to be put.
1.1147 +@param anOffset The offset within the target descriptor data area, where data
1.1148 + from the remote thread is to be put. Note that this parameter
1.1149 + may be useful when write operations to the media must be broken
1.1150 + up into smaller chunks than the length requested.
1.1151 +
1.1152 +@return KErrNone,if successful, otherwise one of the other
1.1153 + system-wide error codes.
1.1154 +
1.1155 +@see Kern::ThreadDesRead()
1.1156 +*/
1.1157 +EXPORT_C TInt TLocDrvRequest::ReadRemote(TDes8* aDes, TInt anOffset)
1.1158 + {
1.1159 + OstTraceFunctionEntry1( TLOCDRVREQUEST_READREMOTE_ENTRY, this );
1.1160 + TInt r;
1.1161 + DThread* pT=RemoteThread();
1.1162 + if (!pT)
1.1163 + pT=Client();
1.1164 +
1.1165 +#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
1.1166 + if (Flags() & ETClientBuffer)
1.1167 + {
1.1168 + r = Kern::ThreadBufRead(pT, (TClientBuffer*) RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0);
1.1169 + OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTE_EXIT1, this, r );
1.1170 + return r;
1.1171 + }
1.1172 +
1.1173 + __ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT());
1.1174 +#endif
1.1175 + r = Kern::ThreadDesRead(pT,RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0);
1.1176 + OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTE_EXIT2, this, r );
1.1177 + return r;
1.1178 + }
1.1179 +
1.1180 +
1.1181 +
1.1182 +
1.1183 +/**
1.1184 +Reads data from an arbitrary descriptor in the requesting thread's process.
1.1185 +
1.1186 +This is used by the media driver to read data from a descriptor in the
1.1187 +requesting thread.
1.1188 +
1.1189 +NB This is NOT supported on datapaging media as there is no guarantee
1.1190 +that the remote descriptor won't be paged out. If this function is called and
1.1191 +data-paging is enabled the kernel will fault in debug mode and return
1.1192 +KErrNotSupported in release mode.
1.1193 +
1.1194 +@param aSrc A pointer to the source descriptor in the requesting thread's
1.1195 + address space.
1.1196 +@param aDes The target descriptor into which data from the remote thread
1.1197 + is to be put.
1.1198 +
1.1199 +@return KErrNone,if successful,
1.1200 + KErrNotSupported if data-paging is enabled
1.1201 + otherwise one of the other system-wide error codes.
1.1202 +
1.1203 +@see Kern::ThreadDesRead()
1.1204 +*/
1.1205 +EXPORT_C TInt TLocDrvRequest::ReadRemote(const TAny* aSrc, TDes8* aDes)
1.1206 + {
1.1207 + OstTraceFunctionEntry1( TLOCDRVREQUEST_READ_REMOTE_ENTRY, this );
1.1208 + if (Flags() & TLocDrvRequest::EKernelBuffer)
1.1209 + {
1.1210 + aDes->Copy(* (TDesC8*) aSrc);
1.1211 + return KErrNone;
1.1212 + }
1.1213 +
1.1214 + TInt r;
1.1215 + DThread* pT=RemoteThread();
1.1216 + if (!pT)
1.1217 + pT=Client();
1.1218 +
1.1219 +#ifdef __DEMAND_PAGING__
1.1220 + __ASSERT_DEBUG(!DataPagingDfcQ(Drive()->iPrimaryMedia), LOCM_FAULT());
1.1221 +
1.1222 + if (DataPagingDfcQ(Drive()->iPrimaryMedia))
1.1223 + {
1.1224 + OstTraceFunctionExitExt( TLOCDRVREQUEST_READ_REMOTE_EXIT1, this, KErrNotSupported );
1.1225 + return KErrNotSupported;
1.1226 + }
1.1227 +#endif
1.1228 +
1.1229 + r = Kern::ThreadDesRead(pT,aSrc,*aDes,0,KChunkShiftBy0);
1.1230 + OstTraceFunctionExitExt( TLOCDRVREQUEST_READ_REMOTE_EXIT2, this, r );
1.1231 + return r;
1.1232 + }
1.1233 +
1.1234 +
1.1235 +
1.1236 +
1.1237 +/**
1.1238 +Reads raw data from the requesting thread's process.
1.1239 +
1.1240 +This is used by the media driver to read raw data from a location in requesting
1.1241 +thread's address space. The remote data is copied into the specified
1.1242 +buffer.
1.1243 +
1.1244 +@param aDest A pointer to the buffer where the data is to be written.
1.1245 +@param aSize The number of bytes to read.
1.1246 +
1.1247 +@return KErrNone,if successful, otherwise one of the other
1.1248 + system-wide error codes.
1.1249 +
1.1250 +@see Kern::ThreadRawRead()
1.1251 +*/
1.1252 +EXPORT_C TInt TLocDrvRequest::ReadRemoteRaw(TAny* aDest, TInt aSize)
1.1253 + {
1.1254 + OstTraceFunctionEntry1( TLOCDRVREQUEST_READREMOTERAW_ENTRY, this );
1.1255 + if (Flags() & TLocDrvRequest::EKernelBuffer)
1.1256 + {
1.1257 + (void)memcpy(aDest, (TAny*) RemoteDes(), aSize);
1.1258 + return KErrNone;
1.1259 + }
1.1260 +
1.1261 + TInt r;
1.1262 + DThread* pT=RemoteThread();
1.1263 + if (!pT)
1.1264 + pT=Client();
1.1265 +
1.1266 +#ifdef __DEMAND_PAGING__
1.1267 + __ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT());
1.1268 +#endif
1.1269 +
1.1270 + r = Kern::ThreadRawRead(pT,RemoteDes(),aDest,aSize);
1.1271 + OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTERAW_EXIT, this, r );
1.1272 + return r;
1.1273 + }
1.1274 +
1.1275 +
1.1276 +/**
1.1277 +Writes data to a descriptor in the requesting thread's process.
1.1278 +
1.1279 +This is used by the media driver to write data to a descriptor in the requesting
1.1280 +thread. Data is copied from the specified descriptor, starting at the specified
1.1281 +offset within that descriptor's data area.
1.1282 +
1.1283 +@param aDes The source descriptor from which data is to be written to
1.1284 + the remote thread.
1.1285 +
1.1286 +@param anOffset The offset within the source descriptor data area, from where data
1.1287 + is to be written to the remote thread. Note that this parameter
1.1288 + may be useful when read operations from the media must be broken
1.1289 + up into smaller chunks than the length requested.
1.1290 +
1.1291 +@return KErrNone,if successful, otherwise one of the other
1.1292 + system-wide error codes.
1.1293 +
1.1294 +@see Kern::ThreadDesWrite()
1.1295 +*/
1.1296 +EXPORT_C TInt TLocDrvRequest::WriteRemote(const TDesC8* aDes, TInt anOffset)
1.1297 + {
1.1298 + OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITEREMOTE_ENTRY, this );
1.1299 + TInt r;
1.1300 + DThread* pC=Client();
1.1301 + DThread* pT=RemoteThread();
1.1302 + if (!pT)
1.1303 + pT=pC;
1.1304 +
1.1305 +#ifdef __DEMAND_PAGING__
1.1306 + if (Flags() & ETClientBuffer)
1.1307 + {
1.1308 + r = Kern::ThreadBufWrite(pT, (TClientBuffer*) RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC);
1.1309 + OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT1, this, r );
1.1310 + return r;
1.1311 + }
1.1312 +#endif
1.1313 + r = Kern::ThreadDesWrite(pT,RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC);
1.1314 + OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT2, this, r );
1.1315 + return r;
1.1316 + }
1.1317 +
1.1318 +
1.1319 +/**
1.1320 +Writes raw data to the requesting thread's process.
1.1321 +
1.1322 +This is used by the media driver to write raw data to a location in the
1.1323 +requesting thread's address space.
1.1324 +
1.1325 +@param aSrc The source addres from which data is to be written to
1.1326 + the remote thread.
1.1327 +
1.1328 +@param aSize The number of bytes to write.
1.1329 +
1.1330 +@return KErrNone,if successful, otherwise one of the other
1.1331 + system-wide error codes.
1.1332 +
1.1333 +@see Kern::ThreadRawWrite()
1.1334 +*/
1.1335 +EXPORT_C TInt TLocDrvRequest::WriteRemoteRaw(const TAny* aSrc, TInt aSize)
1.1336 + {
1.1337 + OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITEREMOTERAW_ENTRY, this );
1.1338 + TInt r;
1.1339 + DThread* pC=Client();
1.1340 + DThread* pT=RemoteThread();
1.1341 + if (!pT)
1.1342 + pT=pC;
1.1343 +
1.1344 +#ifdef __DEMAND_PAGING__
1.1345 + __ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT());
1.1346 +#endif
1.1347 + r = Kern::ThreadRawWrite(pT,RemoteDes(),aSrc,aSize,pC);
1.1348 + OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTERAW_EXIT, this, r );
1.1349 + return r;
1.1350 + }
1.1351 +
1.1352 +
1.1353 +TInt TLocDrvRequest::ProcessMessageData(TAny* aPtr)
1.1354 +//
1.1355 +// Get read/write parameters from client and open remote thread
1.1356 +//
1.1357 + {
1.1358 + OstTraceFunctionEntry1( TLOCDRVREQUEST_PROCESSMESSAGEDATA_ENTRY, this );
1.1359 + RemoteThread()=NULL;
1.1360 + DThread& t=Kern::CurrentThread();
1.1361 + TLocalDriveMessageData d;
1.1362 + kumemget32(&d,aPtr,sizeof(d));
1.1363 + OstTrace1( TRACE_INTERNALS, TLOCDRVREQUEST_PROCESSMESSAGEDATA, "Message handle=%d", d.iHandle );
1.1364 + if (d.iHandle!=KLocalMessageHandle && Id()!=DLocalDrive::EFormat)
1.1365 + {
1.1366 + NKern::LockSystem();
1.1367 + DThread* pT = RMessageK::MessageK(d.iHandle)->iClient;
1.1368 + if (!pT || pT->Open()!=KErrNone)
1.1369 + {
1.1370 + NKern::UnlockSystem();
1.1371 + OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT1, this, KErrBadHandle );
1.1372 + return KErrBadHandle;
1.1373 + }
1.1374 + t.iExtTempObj=pT;
1.1375 + RemoteThread()=pT;
1.1376 + NKern::UnlockSystem();
1.1377 + }
1.1378 + Pos()=d.iPos;
1.1379 + Length()=d.iLength;
1.1380 + RemoteDes()=(TAny*)d.iPtr;
1.1381 + RemoteDesOffset()=d.iOffset;
1.1382 + DriverFlags()=d.iFlags;
1.1383 + if (Pos()<0 || Length()<0)
1.1384 + {
1.1385 + OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT2, this, KErrArgument );
1.1386 + return KErrArgument;
1.1387 + }
1.1388 + OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT3, this, KErrNone );
1.1389 + return KErrNone;
1.1390 + }
1.1391 +
1.1392 +void TLocDrvRequest::CloseRemoteThread()
1.1393 + {
1.1394 + OstTraceFunctionEntry1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_ENTRY, this );
1.1395 +
1.1396 + if (!RemoteThread())
1.1397 + {
1.1398 + OstTraceFunctionExit1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_EXIT1, this );
1.1399 + return;
1.1400 + }
1.1401 + NKern::ThreadEnterCS();
1.1402 + DThread& t=Kern::CurrentThread();
1.1403 + RemoteThread()=NULL;
1.1404 + Kern::SafeClose((DObject*&)t.iExtTempObj,NULL);
1.1405 + NKern::ThreadLeaveCS();
1.1406 + OstTraceFunctionExit1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_EXIT2, this );
1.1407 + }
1.1408 +
1.1409 +EXPORT_C TInt TLocDrvRequest::CheckAndAdjustForPartition()
1.1410 + {
1.1411 + OstTraceFunctionEntry1( TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION_ENTRY, this );
1.1412 + TLocDrv& d=*Drive();
1.1413 + __KTRACE_OPT(KLOCDRV,Kern::Printf("CheckAndAdjustForPartition drive %d partition len %lx",d.iDriveNumber,d.iPartitionLen));
1.1414 + OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION1, "iDriveNumber=%d; partition length=0x%lx", d.iDriveNumber, (TInt) d.iPartitionLen );
1.1415 + Flags() |= EAdjusted;
1.1416 + TInt r;
1.1417 + switch (Id())
1.1418 + {
1.1419 + case DLocalDrive::ECaps:
1.1420 + case DLocalDrive::EForceMediaChange:
1.1421 + case DLocalDrive::EPasswordLock:
1.1422 + case DLocalDrive::EPasswordUnlock:
1.1423 + case DLocalDrive::EPasswordClear:
1.1424 + case DLocalDrive::EPasswordErase:
1.1425 + case DLocalDrive::EReadPasswordStore:
1.1426 + case DLocalDrive::EWritePasswordStore:
1.1427 + case DLocalDrive::EPasswordStoreLengthInBytes:
1.1428 + case DLocalDrive::EQueryDevice:
1.1429 + {
1.1430 + r = KErrNone;
1.1431 + break;
1.1432 + }
1.1433 + case DLocalDrive::EEnlarge:
1.1434 + __KTRACE_OPT(KLOCDRV,Kern::Printf("Enlarge request %lx",Length()));
1.1435 + OstTrace1( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION2, "Enlarge request=0x%lx", Length() );
1.1436 + if (Length()>KMaxTInt)
1.1437 + r = KErrArgument;
1.1438 + else
1.1439 + r = KErrNone;
1.1440 + break;
1.1441 + case DLocalDrive::EReduce:
1.1442 + __KTRACE_OPT(KLOCDRV,Kern::Printf("Reduce request %lx@%lx",Length(),Pos()));
1.1443 + OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION3, "Reduce request length=0x%lx; position=0x%lx", (TUint) Length(), (TUint) Pos() );
1.1444 + if (Pos()+Length()>d.iPartitionLen)
1.1445 + r = KErrArgument;
1.1446 + else
1.1447 + r = KErrNone;
1.1448 + break;
1.1449 + case DLocalDrive::EFormat:
1.1450 + __KTRACE_OPT(KLOCDRV,Kern::Printf("Format request %lx@%lx",Length(),Pos()));
1.1451 + OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION4, "Format request length=0x%lx; position=0x%lx", (TUint) Length(), (TUint) Pos() );
1.1452 + if (!(DriverFlags() & RLocalDrive::ELocDrvWholeMedia))
1.1453 + {
1.1454 + if (Pos()>d.iPartitionLen)
1.1455 + {
1.1456 + Length()=0;
1.1457 + r = KErrEof;
1.1458 + break;
1.1459 + }
1.1460 + Int64 left=d.iPartitionLen-Pos();
1.1461 + if (left<Length())
1.1462 + Length()=left;
1.1463 + Pos()+=d.iPartitionBaseAddr;
1.1464 + if (Length()==0)
1.1465 + {
1.1466 + r = KErrEof;
1.1467 + break;
1.1468 + }
1.1469 + }
1.1470 + r = KErrNone;
1.1471 + break;
1.1472 +
1.1473 +#ifdef __DEMAND_PAGING__
1.1474 + case DMediaPagingDevice::ERomPageInRequest:
1.1475 +// if the ROM was reported to LOCM then it will also need to be adjusted....
1.1476 +// Otherwise the media driver adjust it internally
1.1477 + case DMediaPagingDevice::ECodePageInRequest:
1.1478 + __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Adjusted Paging read request %lx@%lx",Length(),Pos()));
1.1479 + OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, TLOCDRVREQUESTCHECKANDADJUSTFORPARTITION5, "Adjusted Paging read request length=0x%lx; position=0x%lx", (TUint) Length(), (TUint) Pos());
1.1480 + if (Pos()+Length()>d.iPartitionLen)
1.1481 + {
1.1482 + r = KErrArgument;
1.1483 + break;
1.1484 + }
1.1485 + Pos()+=d.iPartitionBaseAddr;
1.1486 + r = KErrNone;
1.1487 + break;
1.1488 +#endif
1.1489 +
1.1490 + default: // read or write or fragment
1.1491 + __KTRACE_OPT(KLOCDRV,Kern::Printf("R/W request %lx@%lx",Length(),Pos()));
1.1492 + OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION6, "Read/Write request length=0x%x; position=0x%x", (TUint) Length(), (TUint) Pos() );
1.1493 + if (DriverFlags() & RLocalDrive::ELocDrvWholeMedia)
1.1494 + {
1.1495 + if (d.iMedia && d.iMedia->iDriver && Pos()+Length() > d.iMedia->iDriver->iTotalSizeInBytes)
1.1496 + {
1.1497 + r = KErrArgument;
1.1498 + break;
1.1499 + }
1.1500 + }
1.1501 + else
1.1502 + {
1.1503 + if (Pos()+Length() > d.iPartitionLen)
1.1504 + {
1.1505 + r = KErrArgument;
1.1506 + break;
1.1507 + }
1.1508 + Pos()+=d.iPartitionBaseAddr;
1.1509 + }
1.1510 + r = KErrNone;
1.1511 + }
1.1512 + OstTraceFunctionExitExt( TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION_EXIT, this, r );
1.1513 + return r;
1.1514 + }
1.1515 +
1.1516 +/********************************************
1.1517 + * Local drive class
1.1518 + ********************************************/
1.1519 +TLocDrv::TLocDrv(TInt aDriveNumber)
1.1520 + {
1.1521 + OstTraceFunctionEntryExt( TLOCDRV_TLOCDRV_ENTRY, this );
1.1522 + memclr(this, sizeof(TLocDrv));
1.1523 + iDriveNumber=aDriveNumber;
1.1524 + iPartitionNumber=-1;
1.1525 + OstTraceFunctionExit1( TLOCDRV_TLOCDRV_EXIT, this );
1.1526 + }
1.1527 +
1.1528 +/**
1.1529 +Initialises the DMedia entity with the media device number and ID.
1.1530 +
1.1531 +@param aDevice The unique ID for this device. This can take one of the
1.1532 + enumerated values defined in TMediaDevice enum.
1.1533 +
1.1534 +@param aMediaId The unique ID to associate with this media entity.
1.1535 +
1.1536 +@return KErrNone,if successful, otherwise one of the other
1.1537 + system-wide error codes.
1.1538 +
1.1539 +@see TMediaDevice
1.1540 +*/
1.1541 +EXPORT_C TInt DMedia::Create(TMediaDevice aDevice, TInt aMediaId, TInt)
1.1542 + {
1.1543 + OstTraceFunctionEntry1( DMEDIA_CREATE_ENTRY, this );
1.1544 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DMedia::Create media %d device %d",aMediaId,aDevice));
1.1545 + OstTraceExt2(TRACE_INTERNALS, DMEDIA_CREATE, "media=%d; device=%d", aMediaId, (TUint) aDevice);
1.1546 + iMediaId=aMediaId;
1.1547 + iDevice=aDevice;
1.1548 + OstTraceFunctionExitExt( DMEDIA_CREATE_EXIT, this, KErrNone );
1.1549 + return KErrNone;
1.1550 + }
1.1551 +
1.1552 +/********************************************
1.1553 + * Primary Media Class
1.1554 + ********************************************/
1.1555 +void asyncDfc(TAny* aPtr)
1.1556 + {
1.1557 + OstTraceFunctionEntry0( _ASYNCDFC_ENTRY );
1.1558 + DPrimaryMediaBase* pM=(DPrimaryMediaBase*)aPtr;
1.1559 + if (pM->iState==DMedia::EOpening)
1.1560 + pM->DoOpenMediaDriverComplete(pM->iAsyncErrorCode);
1.1561 + else if (pM->iState==DMedia::EReadPartitionInfo)
1.1562 + pM->DoPartitionInfoComplete(pM->iAsyncErrorCode);
1.1563 + OstTraceFunctionExit0( _ASYNCDFC_EXIT );
1.1564 + }
1.1565 +
1.1566 +void handleMsg(TAny* aPtr)
1.1567 + {
1.1568 + OstTraceFunctionEntry0( _HANDLEMSG_ENTRY );
1.1569 + DPrimaryMediaBase* primaryMedia=(DPrimaryMediaBase*)aPtr;
1.1570 +
1.1571 + for(TLocDrvRequest* m = (TLocDrvRequest*) primaryMedia->iMsgQ.iMessage;
1.1572 + m != NULL;
1.1573 + m = (TLocDrvRequest*) primaryMedia->iMsgQ.Poll())
1.1574 + {
1.1575 +#if defined(_DEBUG)
1.1576 + if (!primaryMedia->iMsgQ.iQ.IsEmpty())
1.1577 + __KTRACE_OPT(KLOCDRV, Kern::Printf("TRACE: handleMsg, queue not empty %08X", m));
1.1578 +#endif
1.1579 + primaryMedia->HandleMsg(*m);
1.1580 +
1.1581 +#ifdef __DEMAND_PAGING__
1.1582 + // don't empty the queue if this media is paging as there
1.1583 + // may be a (higher-priority) paging DFC waiting to run...
1.1584 + if (primaryMedia->iPagingMedia)
1.1585 + break;
1.1586 +#endif
1.1587 + }
1.1588 +
1.1589 +
1.1590 + primaryMedia->iMsgQ.Receive(); // allow reception of more messages
1.1591 + OstTraceFunctionExit0( _HANDLEMSG_EXIT );
1.1592 + }
1.1593 +
1.1594 +EXPORT_C DPrimaryMediaBase::DPrimaryMediaBase()
1.1595 + : iMsgQ(handleMsg, this, NULL, 1),
1.1596 + iDeferred(NULL, NULL, NULL, 0), // callback never used
1.1597 + iWaitMedChg(NULL, NULL, NULL, 0), // callback never used
1.1598 + iAsyncDfc(asyncDfc, this, 1)
1.1599 +/**
1.1600 +Constructor of DPrimaryMediaBase class.
1.1601 +Initialises the media state as closed.
1.1602 +*/
1.1603 + {
1.1604 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DPRIMARYMEDIABASE_ENTRY, this );
1.1605 + iState = EClosed;
1.1606 + }
1.1607 +
1.1608 +
1.1609 +
1.1610 +EXPORT_C TInt DPrimaryMediaBase::Create(TMediaDevice aDevice, TInt aMediaId, TInt aLastMediaId)
1.1611 +/**
1.1612 +Called from LocDrv::RegisterMediaDevice() function.
1.1613 +Calls DMedia::Create()
1.1614 +
1.1615 +@param aDevice Local media ID
1.1616 +@param aMediaId Media Id (unique for a media subsystem)
1.1617 +@param aLastMediaId This indicates number of used media ids+ number of DMedia objects to be associated with the media driver.
1.1618 +
1.1619 +@return KErrNone
1.1620 +@see TMediaDevice
1.1621 +
1.1622 +*/
1.1623 + {
1.1624 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_CREATE_ENTRY, this );
1.1625 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase::Create media %d-%d device %d",aMediaId,aLastMediaId,aDevice));
1.1626 + OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_CREATE, "aMediaId=%d; aLastMediaId=%d; aDevice=%d ", aMediaId, aLastMediaId, (TUint) aDevice );
1.1627 + TInt r=DMedia::Create(aDevice,aMediaId,0);
1.1628 +
1.1629 + if (r != KErrNone)
1.1630 + {
1.1631 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT1, this, r );
1.1632 + return r;
1.1633 + }
1.1634 + iBody = new DBody;
1.1635 + if (iBody == NULL)
1.1636 + {
1.1637 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT2, this, KErrNoMemory );
1.1638 + return KErrNoMemory;
1.1639 + }
1.1640 +
1.1641 +
1.1642 +
1.1643 +#ifdef __DEMAND_PAGING__
1.1644 + TInt pageSize = Kern::RoundToPageSize(1);
1.1645 + iBody->iPageSizeMsk = pageSize-1;
1.1646 +#endif
1.1647 +
1.1648 + iLastMediaId=aLastMediaId;
1.1649 + if (r==KErrNone && iDfcQ)
1.1650 + {
1.1651 + iMsgQ.SetDfcQ(iDfcQ);
1.1652 + iDeferred.SetDfcQ(iDfcQ);
1.1653 + iWaitMedChg.SetDfcQ(iDfcQ);
1.1654 + iAsyncDfc.SetDfcQ(iDfcQ);
1.1655 + }
1.1656 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT3, this, KErrNone );
1.1657 + return KErrNone;
1.1658 + }
1.1659 +
1.1660 +
1.1661 +EXPORT_C TInt DPrimaryMediaBase::Connect(DLocalDrive* aLocalDrive)
1.1662 +/**
1.1663 +Connects to a local drive
1.1664 +
1.1665 +@param aLocalDrive Local drive logical channel abstraction
1.1666 +
1.1667 +@pre Kernel must be unlocked
1.1668 +@pre Current thread in critical section
1.1669 +
1.1670 +@post Kernel must be unlocked
1.1671 +
1.1672 +@return KErrNone, if successful
1.1673 + KErrNotFound, If no PDD matches criteria while getting driver list
1.1674 + KErrNoMemory, If the array could not be expanded at some point while getting driver list or ran out of memory while opening media driver
1.1675 + KErrNotReady, If not ready when trying to open media driver
1.1676 + otherwise, one of the other system wide error codes.
1.1677 +
1.1678 +@see DLocalDrive
1.1679 +*/
1.1680 + {
1.1681 + OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_CONNECT_ENTRY, this );
1.1682 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Connect %O",iMediaId,aLocalDrive));
1.1683 + OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CONNECT, "iMediaId=%d; iDriveNumber=%d", iMediaId, aLocalDrive->iDrive->iDriveNumber );
1.1684 +
1.1685 + TInt r=KErrNone;
1.1686 +
1.1687 + if (iDfcQ)
1.1688 + {
1.1689 + TThreadMessage& m=Kern::Message();
1.1690 + m.iValue=EConnect;
1.1691 + m.iArg[0]=aLocalDrive;
1.1692 + r=m.SendReceive(&iMsgQ);
1.1693 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CONNECT_EXIT1, this, r );
1.1694 + return r;
1.1695 + }
1.1696 +
1.1697 + // If no DFC queue, must be a fixed media device
1.1698 + // If this is the first connection, open media driver now
1.1699 + // Assume no non-primary media exist on this device
1.1700 +
1.1701 + NKern::LockSystem();
1.1702 + TBool first=iConnectionQ.IsEmpty();
1.1703 + iConnectionQ.Add(&aLocalDrive->iLink);
1.1704 + NKern::UnlockSystem();
1.1705 + if (first)
1.1706 + {
1.1707 + r=OpenMediaDriver();
1.1708 + if (r!=KErrNone)
1.1709 + {
1.1710 + NKern::LockSystem();
1.1711 + aLocalDrive->Deque();
1.1712 + NKern::UnlockSystem();
1.1713 + }
1.1714 + }
1.1715 +
1.1716 + if (r==KErrNone)
1.1717 + aLocalDrive->iDrive->iMedia=this;
1.1718 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CONNECT_EXIT2, this, r );
1.1719 + return r;
1.1720 + }
1.1721 +
1.1722 +
1.1723 +
1.1724 +
1.1725 +EXPORT_C void DPrimaryMediaBase::Disconnect(DLocalDrive* aLocalDrive)
1.1726 +/**
1.1727 +Disconnects from a local drive
1.1728 +
1.1729 +@param aLocalDrive Local drive logical channel abstraction
1.1730 +
1.1731 +@pre Kernel must be unlocked
1.1732 +@pre Current thread in critical section
1.1733 +
1.1734 +@post Kernel must be unlocked
1.1735 +@see DLocalDrive
1.1736 +*/
1.1737 +
1.1738 + {
1.1739 + OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_DISCONNECT_ENTRY, this );
1.1740 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Disconnect %O",iMediaId,aLocalDrive));
1.1741 + OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_DISCONNECT, "iMediaId=%d; iDriveNumber=%d", iMediaId, aLocalDrive->iDrive->iDriveNumber );
1.1742 +
1.1743 + if (iDfcQ)
1.1744 + {
1.1745 + TThreadMessage& m=Kern::Message();
1.1746 + m.iValue=EDisconnect;
1.1747 + m.iArg[0]=aLocalDrive;
1.1748 + m.SendReceive(&iMsgQ);
1.1749 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_DISCONNECT_EXIT1, this );
1.1750 + return;
1.1751 + }
1.1752 +
1.1753 + // If no DFC queue, must be a fixed media device
1.1754 + // If this is the last connection, close media driver now
1.1755 + // Assume no non-primary media exist on this device
1.1756 + DMediaDriver* pD=NULL;
1.1757 + NKern::LockSystem();
1.1758 + aLocalDrive->iDrive->iMedia=NULL;
1.1759 + aLocalDrive->Deque();
1.1760 + if (iConnectionQ.IsEmpty())
1.1761 + {
1.1762 + pD=iDriver;
1.1763 + iDriver=NULL;
1.1764 + }
1.1765 + NKern::UnlockSystem();
1.1766 + if (pD)
1.1767 + pD->Close();
1.1768 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_DISCONNECT_EXIT2, this );
1.1769 + }
1.1770 +
1.1771 +EXPORT_C TInt DPrimaryMediaBase::Request(TLocDrvRequest& aReq)
1.1772 +/**
1.1773 +Issues a local drive request. It is called from TLocDrv::Request() function .
1.1774 +Each local drive request is encapsulated as a TLocDrvRequest- a class derived from TThreadMessage, the kernel message class.
1.1775 +TLocDrvRequest contains information pertaining to the request, including the ID and any associated parameters such as drive position, length and source/destination location.
1.1776 +Passes the request through to the media driver.
1.1777 +
1.1778 +@param m Encapsulates the request information received from the client
1.1779 +
1.1780 +@pre Enter with kernel unlocked
1.1781 +
1.1782 +@post Leave with Kernel unlocked
1.1783 +
1.1784 +@return KErrNone,if successful
1.1785 + KErrBadDescriptor, if request encapsulates a bad descriptor
1.1786 + Otherwise, one of the other system wide error codes.
1.1787 +
1.1788 +@see TLocDrvRequest
1.1789 +*/
1.1790 + {
1.1791 +OstTraceFunctionEntry1( DPRIMARYMEDIABASE_REQUEST_ENTRY, this );
1.1792 +
1.1793 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Request(%08x)",iMediaId,&aReq));
1.1794 + __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()));
1.1795 +
1.1796 + 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());
1.1797 +
1.1798 + TInt reqId = aReq.Id();
1.1799 +
1.1800 + if (reqId == DLocalDrive::ECaps)
1.1801 + DefaultDriveCaps(*(TLocalDriveCapsV2*)aReq.RemoteDes()); // fill in stuff we know even if no media present
1.1802 +
1.1803 + TInt r = QuickCheckStatus();
1.1804 + if (r != KErrNone && aReq.Id()!=DLocalDrive::EForceMediaChange && // EForceMediaChange, and
1.1805 + aReq.Id()!=DLocalDrive::EReadPasswordStore && // Password store operations
1.1806 + aReq.Id()!=DLocalDrive::EWritePasswordStore && // do not require the media
1.1807 + aReq.Id()!=DLocalDrive::EPasswordStoreLengthInBytes) // to be ready.)
1.1808 + {
1.1809 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT, this, r );
1.1810 + return r;
1.1811 + }
1.1812 +
1.1813 +
1.1814 + // for ERead & EWrite requests, get the linear address for pinning & DMA
1.1815 + TUint8* linAddress = NULL;
1.1816 + TClientBuffer clientBuffer;
1.1817 + DThread* pT = NULL;
1.1818 +
1.1819 + if (reqId == DLocalDrive::ERead || reqId == DLocalDrive::EWrite)
1.1820 + {
1.1821 + pT = aReq.RemoteThread();
1.1822 + if (!pT)
1.1823 + pT = &Kern::CurrentThread(); // e.g. when using TBusLocalDrive directly
1.1824 +
1.1825 + // for silly zero-length requests, return immediately, setting the client
1.1826 + // descriptor length to zero if it's a read request
1.1827 + if (aReq.Length() == 0)
1.1828 + {
1.1829 + DThread* pC = &Kern::CurrentThread();
1.1830 + r = KErrNone;
1.1831 + if (reqId == DLocalDrive::ERead)
1.1832 + {
1.1833 + TPtrC8 ptr(NULL, 0);
1.1834 + r = Kern::ThreadDesWrite(pT, aReq.RemoteDes(), ptr, aReq.RemoteDesOffset(), KChunkShiftBy0,pC);
1.1835 + }
1.1836 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT2, this, r );
1.1837 + return r;
1.1838 + }
1.1839 +
1.1840 + clientBuffer.SetFromDescriptor(aReq.RemoteDes(), pT);
1.1841 +
1.1842 + TInt length = 0;
1.1843 + TInt maxLength = 0;
1.1844 + TInt r = Kern::ThreadGetDesInfo(pT,aReq.RemoteDes(),length,maxLength,linAddress,EFalse); // get descriptor length, maxlength and linAddress
1.1845 + if (r != KErrNone)
1.1846 + {
1.1847 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT3, this, r );
1.1848 + return r;
1.1849 + }
1.1850 + linAddress+= aReq.RemoteDesOffset();
1.1851 +
1.1852 +#ifdef __DEMAND_PAGING__
1.1853 + // NB change in behavior IF DATA PAGING IS ENABLED: TLocDrvRequest::RemoteDes() points
1.1854 + // to a TClientBuffer rather than the client's remote descriptor
1.1855 + if (DataPagingDeviceRegistered)
1.1856 + {
1.1857 + aReq.RemoteDes() = &clientBuffer;
1.1858 + aReq.Flags() |= TLocDrvRequest::ETClientBuffer;
1.1859 + }
1.1860 +#endif
1.1861 + }
1.1862 +
1.1863 + if (iDfcQ)
1.1864 + {
1.1865 + __TRACE_TIMING(0x10);
1.1866 +
1.1867 +
1.1868 +#ifdef __DEMAND_PAGING__
1.1869 + // If this is a ROM/Code paging media, pin writes
1.1870 + // If there is a Data paging media registered, pin all requests with descriptors
1.1871 + if ( (DataPagingDeviceRegistered) || (reqId == DLocalDrive::EWrite && RomPagingDfcQ(this)) )
1.1872 + {
1.1873 + r = PinSendReceive(aReq, (TLinAddr) linAddress);
1.1874 + }
1.1875 + else
1.1876 +#endif // __DEMAND_PAGING__
1.1877 + r = SendReceive(aReq, (TLinAddr) linAddress);
1.1878 + }
1.1879 + else
1.1880 + {
1.1881 + // If no DFC queue, must be a fixed media device
1.1882 + // Media driver must already have been opened
1.1883 + // Assume no non-primary media exist on this device
1.1884 + // Just pass request straight through to media driver
1.1885 + r = aReq.CheckAndAdjustForPartition();
1.1886 + if (r == KErrNone)
1.1887 + r = iDriver->Request(aReq);
1.1888 + }
1.1889 +
1.1890 +#ifdef __DEMAND_PAGING__
1.1891 + // NB change in behavior IF DATA PAGING IS ENABLED: TLocDrvRequest::RemoteDes() points
1.1892 + // to a TClientBuffer rather than the client's remote descriptor
1.1893 + if (reqId == DLocalDrive::ERead && DataPagingDeviceRegistered && r == KErrNone)
1.1894 + {
1.1895 + r = clientBuffer.UpdateDescriptorLength(pT);
1.1896 + }
1.1897 +#endif
1.1898 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT4, this, r );
1.1899 + return r;
1.1900 + }
1.1901 +
1.1902 +
1.1903 +#ifdef __DEMAND_PAGING__
1.1904 +TInt DPrimaryMediaBase::PinSendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress)
1.1905 + {
1.1906 + OstTraceExt2(TRACE_FLOW, DPRIMARYMEDIABASE_PINSENDRECEIVE_ENTRY, "> DPrimaryMediaBase::PinSendReceive;aReq=%x;aLinAddress=%x;", (TUint) &aReq, (TUint) &aLinAddress );
1.1907 +
1.1908 + __ASSERT_DEBUG(ThePinObjectAllocator, LOCM_FAULT());
1.1909 +
1.1910 +
1.1911 + TInt msgId = aReq.Id();
1.1912 + TInt r;
1.1913 +
1.1914 + switch(msgId)
1.1915 + {
1.1916 + case DLocalDrive::EControlIO:
1.1917 + {
1.1918 + TInt controlIoType = aReq.Int3();
1.1919 + switch(controlIoType)
1.1920 + {
1.1921 + case KLocalMessageHandle:
1.1922 + // ControlIo is not supported if either of the two bare (TAny*) pointers are non-NULL
1.1923 + // as it's not possible to determine what the pointers are pointing at...
1.1924 + if (aReq.Int1() || aReq.Int2())
1.1925 + {
1.1926 + __KTRACE_OPT(KDATAPAGEWARN, Kern::Printf("Data paging: Naked EControlIO not supported on paging device: fn=%x", aReq.Int0()));
1.1927 + r = KErrNotSupported;
1.1928 + break;
1.1929 + }
1.1930 + // fall into...
1.1931 + case 0:
1.1932 + r = SendReceive(aReq);
1.1933 + break;
1.1934 +
1.1935 + default:
1.1936 + // if Int3() is > 0, Int1() is a data pointer, and Int3() is a length
1.1937 + if (controlIoType > (TInt) ThePinObjectAllocator->iFragmentGranularity)
1.1938 + {
1.1939 + r = KErrTooBig;
1.1940 + break;
1.1941 + }
1.1942 + if (controlIoType < 0)
1.1943 + {
1.1944 + r = KErrArgument;
1.1945 + break;
1.1946 + }
1.1947 + r = PinFragmentSendReceive(aReq, (TLinAddr) aReq.Ptr1(), controlIoType);
1.1948 + break;
1.1949 + }
1.1950 + break;
1.1951 + }
1.1952 +
1.1953 + case DLocalDrive::ERead:
1.1954 + case DLocalDrive::EWrite:
1.1955 + {
1.1956 + r = PinFragmentSendReceive(aReq, aLinAddress, aReq.Length());
1.1957 + break;
1.1958 + }
1.1959 +
1.1960 + // For all these requests, aReq.RemoteDes() points to a buffer on the stack in DLocalDrive::Request()
1.1961 + // This is a kernel stack & so should be unpaged & not require pinning...
1.1962 + case DLocalDrive::ECaps:
1.1963 + case DLocalDrive::EGetLastErrorInfo:
1.1964 + case DLocalDrive::EQueryDevice:
1.1965 + case DLocalDrive::EPasswordLock:
1.1966 + case DLocalDrive::EPasswordUnlock:
1.1967 + case DLocalDrive::EPasswordClear:
1.1968 + case DLocalDrive::EReadPasswordStore:
1.1969 + case DLocalDrive::EWritePasswordStore:
1.1970 + case DLocalDrive::EPasswordStoreLengthInBytes:
1.1971 + case DLocalDrive::EPasswordErase:
1.1972 +
1.1973 + default:
1.1974 + r = SendReceive(aReq);
1.1975 + }
1.1976 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_PINSENDRECEIVE_EXIT, this, r );
1.1977 + return r;
1.1978 + }
1.1979 +
1.1980 +TInt DPrimaryMediaBase::PinFragmentSendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress, TInt aLength)
1.1981 + {
1.1982 + OstTraceExt3(TRACE_FLOW, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE_ENTRY, "> DPrimaryMediaBase::PinFragmentSendReceive;aReq=%x;aLinAddress=%x;aLength=%d;", (TUint) &aReq, (TUint) &aLinAddress, aLength );
1.1983 +
1.1984 + 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)
1.1985 + TInt r = KErrNone;
1.1986 +
1.1987 +// Kern::Printf(">PFSR %02X aReq %08X aLinAddress %08X aLen %08X offset %08X", aReq.Id(), &aReq, aLinAddress, aLength, aReq.RemoteDesOffset());
1.1988 +
1.1989 + DThread* pT = aReq.RemoteThread();
1.1990 + if (!pT)
1.1991 + pT=&Kern::CurrentThread(); // e.g. when using TBusLocalDrive directly
1.1992 +
1.1993 + __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));
1.1994 + __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));
1.1995 + 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 );
1.1996 + 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 );
1.1997 +
1.1998 + // don't want this thread to be terminated until last fragment is sent to MD and mem can be free'd up
1.1999 + NKern::ThreadEnterCS();
1.2000 +
1.2001 + __ASSERT_DEBUG(ThePinObjectAllocator, LOCM_FAULT());
1.2002 +
1.2003 + TUint fragmentGranularity = ThePinObjectAllocator->iFragmentGranularity;
1.2004 + TInt dataLockResult = 0;
1.2005 + // fragmentation only allowed for read/write requests
1.2006 + __ASSERT_DEBUG(aLength <= (TInt) fragmentGranularity || (aReq.Id() == DLocalDrive::EWrite || aReq.Id() == DLocalDrive::ERead), LOCM_FAULT());
1.2007 +
1.2008 + // Pin the client buffer
1.2009 + TInt pinnedLen;
1.2010 + for (TInt pos = 0; pos < aLength; pos+= pinnedLen, aLinAddress+= pinnedLen)
1.2011 + {
1.2012 + pinnedLen = 0;
1.2013 +
1.2014 + // pin memory
1.2015 + TInt remainingLen = aLength - pos; // remaining length
1.2016 +
1.2017 + // first attempt to pin memory with no pre-allocated buffers (which may fail)
1.2018 + DPinObjectAllocator::SVirtualPinContainer* pinDataObject = ThePinObjectAllocator->AcquirePinObject();
1.2019 +
1.2020 + if (pinDataObject)
1.2021 + {
1.2022 + TInt lenToPin = Min(KMaxPinData, remainingLen);
1.2023 +
1.2024 + TInt r = Kern::PinVirtualMemory(pinDataObject->iObject, aLinAddress, lenToPin, pT);
1.2025 + if (r == KErrNone)
1.2026 + {
1.2027 + pinnedLen = lenToPin;
1.2028 + }
1.2029 + else
1.2030 + {
1.2031 +#ifdef __DEBUG_DEMAND_PAGING__
1.2032 + Kern::Printf("Kern::PinVirtualMemory() error %d", r);
1.2033 +#endif
1.2034 + // pin failed, so use preallocated buffer instead
1.2035 + ThePinObjectAllocator->ReleasePinObject(pinDataObject);
1.2036 + pinDataObject = NULL;
1.2037 + }
1.2038 + }
1.2039 +
1.2040 + if (!pinDataObject)
1.2041 + {
1.2042 + ThePinObjectAllocator->PreAllocatedDataLock().LockFragmentation();
1.2043 +
1.2044 + TLinAddr start = aLinAddress;
1.2045 + do
1.2046 + {
1.2047 + TInt lenToPin = Min((TInt) fragmentGranularity, remainingLen - pinnedLen);
1.2048 +
1.2049 +#ifdef __DEBUG_DEMAND_PAGING__
1.2050 + Kern::Printf(">SR PinS Id %d aLinAddress %08X lenToPin %08X offset %08X", aReq.Id(), aLinAddress, lenToPin);
1.2051 +#endif
1.2052 +
1.2053 + dataLockResult = ThePinObjectAllocator->PreAllocatedDataLock().Lock(pT, start, lenToPin);
1.2054 +
1.2055 +#ifdef __DEBUG_DEMAND_PAGING__
1.2056 + Kern::Printf("<SR PinS Id %d aLinAddress %08X lenToPin %08X offset %08X r %d", aReq.Id(), aLinAddress, lenToPin, r);
1.2057 +#endif
1.2058 +
1.2059 + start+= lenToPin;
1.2060 + pinnedLen+= lenToPin;
1.2061 + }
1.2062 + while (dataLockResult == 0 && pinnedLen < remainingLen);
1.2063 +
1.2064 + // if nothing pinned (dataLockResult == 0) or error (dataLockResult <0), release the mutex,
1.2065 + // otherwise (dataLockResult > 0) release it after calling SendReceive()
1.2066 + if (dataLockResult <= 0)
1.2067 + ThePinObjectAllocator->PreAllocatedDataLock().UnlockFragmentation();
1.2068 +
1.2069 +#ifdef __DEBUG_DEMAND_PAGING__
1.2070 + if (dataLockResult < 0)
1.2071 + Kern::Printf("DFragmentationPagingLock::Lock() %d", dataLockResult);
1.2072 +#endif
1.2073 +
1.2074 + if (dataLockResult < 0) // if lock returned an error then give up
1.2075 + {
1.2076 + r = dataLockResult;
1.2077 + break;
1.2078 + }
1.2079 + }
1.2080 +
1.2081 + // fragment request Id defaults to same as original request
1.2082 + fragment.Id() = aReq.Id();
1.2083 + fragment.Length() = Int64(pinnedLen);
1.2084 + fragment.RemoteDesOffset() = aReq.RemoteDesOffset() + pos;
1.2085 + fragment.Pos() = aReq.Pos() + pos;
1.2086 + fragment.Flags() = aReq.Flags();
1.2087 +
1.2088 + __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()));
1.2089 + 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());
1.2090 +
1.2091 +#ifdef BTRACE_PAGING_MEDIA
1.2092 + TInt buf[4];
1.2093 + buf[0] = pinnedLen; // fragment length
1.2094 + buf[1] = pos; // offset within original request
1.2095 + buf[2] = fragment.Pos(); // offset in media
1.2096 + buf[3] = (TInt)&pT->iNThread; // thread that issued the original write req
1.2097 + BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedFragmentBegin,&fragment,fragment.Id(),buf,sizeof(buf));
1.2098 +#endif
1.2099 + r = SendReceive(fragment, aLinAddress); // only come back here when message (fragment) has been completed
1.2100 +
1.2101 + // unpin memory
1.2102 + if (pinDataObject)
1.2103 + {
1.2104 + Kern::UnpinVirtualMemory(pinDataObject->iObject);
1.2105 + ThePinObjectAllocator->ReleasePinObject(pinDataObject);
1.2106 + }
1.2107 + else if (dataLockResult > 0) // pinDataObject = NULL
1.2108 + {
1.2109 + __ASSERT_DEBUG(dataLockResult == 1, LOCM_FAULT());
1.2110 + ThePinObjectAllocator->PreAllocatedDataLock().Unlock();
1.2111 + ThePinObjectAllocator->PreAllocatedDataLock().UnlockFragmentation();
1.2112 + }
1.2113 +
1.2114 +#ifdef BTRACE_PAGING_MEDIA
1.2115 + BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedFragmentEnd,&fragment,r);
1.2116 +#endif
1.2117 +
1.2118 + if (r != KErrNone)
1.2119 + break;
1.2120 + }
1.2121 +
1.2122 + NKern::ThreadLeaveCS();
1.2123 +
1.2124 +// Kern::Printf("<PFSR %02X aReq %08X aLinAddress %08X aLen %08X offset %08X", aReq.Id(), &aReq, aLinAddress, aLength, aReq.RemoteDesOffset());
1.2125 +
1.2126 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE_EXIT, this, r );
1.2127 + return r;
1.2128 + }
1.2129 +
1.2130 +#endif // __DEMAND_PAGING__
1.2131 +
1.2132 +
1.2133 +TInt DPrimaryMediaBase::SendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress)
1.2134 +/**
1.2135 + * If a Physical memory helper object is present for given drive,
1.2136 + * then message is routed via helper;
1.2137 + *
1.2138 + * @return KErrNone, if successful;
1.2139 + * otherwise, one of the other system wide error codes.
1.2140 + *
1.2141 + * @see TLocDrvRequest::SendReceive()
1.2142 + * @see DDmaHelper::SendReceive()
1.2143 + */
1.2144 + {
1.2145 + OstTraceExt2( TRACE_FLOW, DPRIMARYMEDIABASE_SENDRECEIVE_ENTRY, "> DPrimaryMediaBase::SendReceive;aReq=%x;aLinAddress=%x", (TUint) &aReq, (TUint) &aLinAddress );
1.2146 +
1.2147 + DDmaHelper* dmaHelper = aReq.Drive()->iDmaHelper;
1.2148 +
1.2149 +#ifdef __DEMAND_PAGING__
1.2150 + RequestCountInc();
1.2151 +#endif
1.2152 +
1.2153 + TInt r;
1.2154 +
1.2155 + if (dmaHelper)
1.2156 + r = dmaHelper->SendReceive(aReq, aLinAddress);
1.2157 + else
1.2158 + {
1.2159 + r = aReq.SendReceive(&iMsgQ);
1.2160 + }
1.2161 +#ifdef __DEMAND_PAGING__
1.2162 + RequestCountDec();
1.2163 +#endif
1.2164 +
1.2165 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_SENDRECEIVE_EXIT, this, r );
1.2166 + return r;
1.2167 + }
1.2168 +
1.2169 +
1.2170 +
1.2171 +EXPORT_C TInt DPrimaryMediaBase::ForceMediaChange(TInt)
1.2172 +/**
1.2173 +Forces a media change.The method can be overridden in the derived classes.
1.2174 +@param mode Media change mode
1.2175 +
1.2176 +@return KErrNotSupported, in the default implementation
1.2177 + KErrNone, if successful
1.2178 + Otherwise, one of the other system wide error codes.
1.2179 +
1.2180 +*/
1.2181 + {
1.2182 + // default implementation
1.2183 + return KErrNotSupported;
1.2184 + }
1.2185 +
1.2186 +EXPORT_C TInt DPrimaryMediaBase::InitiatePowerUp()
1.2187 +/**
1.2188 +Initiates Power up sequence
1.2189 +@return KErrCompletion, operation is complete successfully or otherwise
1.2190 + KErrNone, if successful
1.2191 + Otherwise, one of the other system wide error codes.
1.2192 +
1.2193 +*/
1.2194 + {
1.2195 + // default implementation, this is the default implementation.
1.2196 + return KErrCompletion;
1.2197 + }
1.2198 +
1.2199 +EXPORT_C TInt DPrimaryMediaBase::QuickCheckStatus()
1.2200 +/**
1.2201 +Checks the status of the media device, whether the device is present,absent,not ready,etc.
1.2202 +The function can be overridden in the derived classes
1.2203 +
1.2204 +@return KErrNone, if successful
1.2205 + Otherwise, one of the other system wide error codes.
1.2206 +
1.2207 +*/
1.2208 + {
1.2209 + // default implementation
1.2210 + return KErrNone;
1.2211 + }
1.2212 +
1.2213 +EXPORT_C void DPrimaryMediaBase::DefaultDriveCaps(TLocalDriveCapsV2& aCaps)
1.2214 +/**
1.2215 +Fills in the default drive capabilities in TLocalDriveCapsV2 .
1.2216 +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.
1.2217 +
1.2218 +@param aCaps Media drive capability fields. Extension to Capabilities fields(i.e) in addition to TLocalDriveCaps mainly to support Nor flash
1.2219 +@see TLocalDriveCapsV2
1.2220 +*/
1.2221 +
1.2222 + {
1.2223 + // default implementation
1.2224 + // aCaps is zeroed beforehand
1.2225 + aCaps.iType = EMediaUnknown;
1.2226 + }
1.2227 +
1.2228 +EXPORT_C TBool DPrimaryMediaBase::IsRemovableDevice(TInt& /*aSocketNum*/)
1.2229 +/**
1.2230 +Checks whether it is a removable device or not
1.2231 +@param aSocketNum Socket number
1.2232 +@return ETrue=Removable Device
1.2233 + EFalse=Non-Removable device, default implementation
1.2234 +
1.2235 +*/
1.2236 + {
1.2237 + // default implementation
1.2238 + return(EFalse);
1.2239 + }
1.2240 +
1.2241 +EXPORT_C void DPrimaryMediaBase::HandleMsg(TLocDrvRequest& m)
1.2242 +/**
1.2243 +It handles the drive request encapsulated in TLocDrvRequest depending on the message id.
1.2244 +
1.2245 +@param aRequest Encapsulates the request information received from the client
1.2246 +@see TLocDrvRequest
1.2247 +*/
1.2248 + {
1.2249 + OstTrace1( TRACE_FLOW, DPRIMARYMEDIABASE_HANDLEMSG_ENTRY, "> DPrimaryMediaBase::HandleMsg;m=%x;", (TUint) &m);
1.2250 +
1.2251 + switch (m.iValue)
1.2252 + {
1.2253 + case EConnect:
1.2254 + {
1.2255 + DLocalDrive* pD=(DLocalDrive*)m.Ptr0();
1.2256 + iConnectionQ.Add(&pD->iLink);
1.2257 + m.Complete(KErrNone, EFalse);
1.2258 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT1, this );
1.2259 + return;
1.2260 + }
1.2261 + case EDisconnect:
1.2262 + {
1.2263 + DLocalDrive* pD=(DLocalDrive*)m.Ptr0();
1.2264 + TLocDrv* pL=pD->iDrive;
1.2265 + DMedia* media=pL->iMedia;
1.2266 + if (iState==EReady && media && media->iDriver)
1.2267 + media->iDriver->Disconnect(pD,&m);
1.2268 + else
1.2269 + {
1.2270 + pD->Deque();
1.2271 + m.Complete(KErrNone, EFalse);
1.2272 + }
1.2273 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT2, this );
1.2274 + return;
1.2275 + }
1.2276 + case DLocalDrive::EForceMediaChange:
1.2277 + {
1.2278 + TUint flags = (TUint) m.Pos();
1.2279 +
1.2280 + // if KForceMediaChangeReOpenDriver specified wait for power up,
1.2281 + // and then re-open this drive's media driver
1.2282 + __KTRACE_OPT(KLOCDRV, Kern::Printf("EForceMediaChange, flags %08X\n", flags));
1.2283 + if (flags == (TUint) KForceMediaChangeReOpenMediaDriver)
1.2284 + {
1.2285 + TInt sock;
1.2286 + if (!IsRemovableDevice(sock))
1.2287 + {
1.2288 + CompleteRequest(m, KErrNotSupported);
1.2289 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT3, this );
1.2290 + return;
1.2291 + }
1.2292 + // wait for power up and then call DPrimaryMediaBase::DoRequest()
1.2293 + break;
1.2294 + }
1.2295 +
1.2296 + TInt r=ForceMediaChange(flags);
1.2297 + if (r==KErrNone)
1.2298 + {
1.2299 + // wait for media change notification to complete message
1.2300 + m.Forward(&iWaitMedChg,EFalse);
1.2301 + }
1.2302 + else
1.2303 + {
1.2304 + if (r==KErrNotSupported || r==KErrCompletion)
1.2305 + r=KErrNone;
1.2306 + CompleteRequest(m, r);
1.2307 + }
1.2308 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT4, this );
1.2309 + return;
1.2310 + }
1.2311 + case DLocalDrive::ECaps:
1.2312 + if (iState==EPoweredDown)
1.2313 + {
1.2314 + // The media is powered down, but the media driver still exists.
1.2315 + // - Issue the ECaps request without powering the media back up.
1.2316 + DoRequest(m);
1.2317 + __TRACE_TIMING(0x101);
1.2318 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT5, this );
1.2319 + return;
1.2320 + }
1.2321 + break;
1.2322 +
1.2323 + case DLocalDrive::ERead:
1.2324 + case DLocalDrive::EWrite:
1.2325 + case DLocalDrive::EFormat:
1.2326 + case DLocalDrive::EEnlarge:
1.2327 + case DLocalDrive::EReduce:
1.2328 + case DLocalDrive::EPasswordLock:
1.2329 + case DLocalDrive::EPasswordUnlock:
1.2330 + case DLocalDrive::EPasswordClear:
1.2331 + case DLocalDrive::EPasswordErase:
1.2332 + case DLocalDrive::EControlIO:
1.2333 + case DLocalDrive::EDeleteNotify:
1.2334 + case DLocalDrive::EQueryDevice:
1.2335 +
1.2336 +#ifdef __DEMAND_PAGING__
1.2337 + case DMediaPagingDevice::ERomPageInRequest:
1.2338 + case DMediaPagingDevice::ECodePageInRequest:
1.2339 +#endif
1.2340 + break;
1.2341 + case DLocalDrive::EGetLastErrorInfo:
1.2342 + {
1.2343 + DLocalDrive* pD=(DLocalDrive*)m.Ptr0();
1.2344 + TLocDrv* pL=pD->iDrive;
1.2345 + *((TErrorInfo*) m.RemoteDes()) = pL->iLastErrorInfo;
1.2346 + CompleteRequest(m, KErrNone);
1.2347 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT6, this );
1.2348 + return;
1.2349 + }
1.2350 + case DLocalDrive::EReadPasswordStore:
1.2351 + {
1.2352 + TPtr8 pswData ((TUint8*) m.RemoteDes(), (TInt) m.Length());
1.2353 + TInt r = ThePasswordStore->ReadPasswordData(pswData);
1.2354 + m.Length() = pswData.Length();
1.2355 + CompleteRequest(m, r);
1.2356 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT7, this );
1.2357 + return;
1.2358 + }
1.2359 + case DLocalDrive::EWritePasswordStore:
1.2360 + {
1.2361 + TPtrC8 pData((TUint8*) m.RemoteDes(), (TInt) m.Length());
1.2362 + TInt r = ThePasswordStore->WritePasswordData(pData);
1.2363 +
1.2364 + if(r != KErrNone)
1.2365 + {
1.2366 + CompleteRequest(m, r);
1.2367 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT8, this );
1.2368 + return;
1.2369 + }
1.2370 +
1.2371 + r = QuickCheckStatus();
1.2372 + if(r != KErrNone)
1.2373 + {
1.2374 + // Don't try to power up the device if it's not ready.
1.2375 + // - Note that this isn't an error that needs to be returned to the client.
1.2376 + CompleteRequest(m, KErrNone);
1.2377 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT9, this );
1.2378 + return;
1.2379 + }
1.2380 +
1.2381 + break;
1.2382 + }
1.2383 + case DLocalDrive::EPasswordStoreLengthInBytes:
1.2384 + {
1.2385 + TInt length = ThePasswordStore->PasswordStoreLengthInBytes();
1.2386 + *(TInt*) m.RemoteDes() = length;
1.2387 + CompleteRequest(m, KErrNone);
1.2388 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT10, this );
1.2389 + return;
1.2390 + }
1.2391 + default:
1.2392 + CHECK_RET(KErrNotSupported);
1.2393 + CompleteRequest(m, KErrNotSupported);
1.2394 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT11, this );
1.2395 + return;
1.2396 + }
1.2397 +
1.2398 + __KTRACE_OPT(KFAIL,Kern::Printf("mdrq %d",m.Id()));
1.2399 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::HandleMsg state %d req %d",iMediaId,iState,m.Id()));
1.2400 +
1.2401 + OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_HANDLEMSG2, "iMediaId=%d; iState=%d; req Id=%d", iMediaId, iState, m.Id());
1.2402 +
1.2403 + // if media driver already open, pass request through
1.2404 + if (iState==EReady)
1.2405 + {
1.2406 + DoRequest(m);
1.2407 + __TRACE_TIMING(0x101);
1.2408 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT12, this );
1.2409 + return;
1.2410 + }
1.2411 +
1.2412 + // if open or close in progress, defer this message
1.2413 + if (iState!=EClosed && iState!=EPoweredDown)
1.2414 + {
1.2415 +#ifdef __DEMAND_PAGING__
1.2416 + if (DMediaPagingDevice::PagingRequest(m))
1.2417 + {
1.2418 + __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
1.2419 + __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
1.2420 + __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
1.2421 +
1.2422 + __KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Deferring PageIn request 0x%08x because opening or closing",&m));
1.2423 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_HANDLEMSG3, "Deferring PageIn request 0x%08x because opening or closing", &m);
1.2424 + iBody->iPagingDevice->SendToDeferredQ(&m);
1.2425 + }
1.2426 + else
1.2427 +#endif
1.2428 + m.Forward(&iDeferred,EFalse);
1.2429 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT13, this );
1.2430 + return;
1.2431 + }
1.2432 +
1.2433 + // nothing is open, so try to open something
1.2434 + __ASSERT_ALWAYS(!iCurrentReq,LOCM_FAULT());
1.2435 +
1.2436 +#ifdef __DEMAND_PAGING__
1.2437 +
1.2438 +#ifdef BTRACE_PAGING_MEDIA
1.2439 + if (DMediaPagingDevice::PagingRequest(m))
1.2440 + BTraceContext12(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInQuietlyDeferred,&m,iState,m.iValue);
1.2441 +#endif // BTRACE_PAGING_MEDIA
1.2442 +
1.2443 +#ifdef _DEBUG
1.2444 + __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
1.2445 +
1.2446 + if (DMediaPagingDevice::PagingRequest(m))
1.2447 + {
1.2448 + __ASSERT_DEBUG(iPagingMedia,LOCM_FAULT());
1.2449 + __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
1.2450 + __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Page request 0x%08x received -> opening MD",&m));
1.2451 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_HANDLEMSG4, "Page request 0x%08x received; opening MD", &m);
1.2452 + }
1.2453 +#endif // _DEBUG
1.2454 +
1.2455 +#endif // __DEMAND_PAGING__
1.2456 +
1.2457 + iCurrentReq=&m;
1.2458 + if(iState == EClosed)
1.2459 + {
1.2460 + iState=EPoweringUp1;
1.2461 + }
1.2462 + else if (iState == EPoweredDown)
1.2463 + {
1.2464 + iState=EPoweringUp2;
1.2465 + }
1.2466 +
1.2467 + TInt r=InitiatePowerUp();
1.2468 + if (r==KErrNone || r==KErrServerBusy)
1.2469 + {
1.2470 + // wait for completion of power up request
1.2471 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT14, this );
1.2472 + return;
1.2473 + }
1.2474 + if (r==KErrCompletion)
1.2475 + r=KErrNone; // device already powered up
1.2476 + PowerUpComplete(r);
1.2477 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT15, this );
1.2478 + }
1.2479 +
1.2480 +EXPORT_C TInt DPrimaryMediaBase::DoRequest(TLocDrvRequest& m)
1.2481 +/**
1.2482 +If the media exists, it tries to get the partition information if not there.
1.2483 +It then passes on the request to the media driver by calling its Request( ) function.
1.2484 +Then it completes the kernel thread message and the reference count of the thread is closed asynchronously.
1.2485 +
1.2486 +@param aRequest Encapsulates the request information received from the client
1.2487 +
1.2488 +@return KErrNone, if successful
1.2489 + KErrNotReady, if missing partitions on removable media
1.2490 + KErrNotSupported, if missing partitions on fixed media
1.2491 + KErrArgument Out of range argument ,encapsulated in Local drive request , passed while checking and adjusting for partition
1.2492 + KErrEOF, Reached the end of file
1.2493 + KErrBadDescriptor, if request encapsulates a bad descriptor
1.2494 + Otherwise, one of the other system wide error codes.
1.2495 +
1.2496 +*/
1.2497 + {
1.2498 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOREQUEST_ENTRY, this );
1.2499 + __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DPrimaryMediaBase::DoRequest %d",m.Id()));
1.2500 + TLocDrv* pL=m.Drive();
1.2501 + DMedia* media=pL->iMedia;
1.2502 + TInt r=KErrNone;
1.2503 +
1.2504 + 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());
1.2505 +
1.2506 + // re-open this drive's media driver ?
1.2507 + if (m.iValue == DLocalDrive::EForceMediaChange)
1.2508 + {
1.2509 + __ASSERT_DEBUG(((TUint) m.Pos()) == (TUint) KForceMediaChangeReOpenMediaDriver, LOCM_FAULT());
1.2510 +
1.2511 + iCurrentReq=NULL;
1.2512 +
1.2513 + TLocDrv* pL = m.Drive();
1.2514 + DMedia* media = pL->iMedia;
1.2515 + if (media && media->iDriver)
1.2516 + CloseMediaDrivers(media);
1.2517 +
1.2518 + iState=EOpening;
1.2519 + StartOpenMediaDrivers();
1.2520 +
1.2521 + NotifyClients(ETrue,pL);
1.2522 + CompleteRequest(m, r);
1.2523 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT, this, r );
1.2524 + return r;
1.2525 + }
1.2526 +
1.2527 + if (!media || !media->iDriver || iState == EClosed)
1.2528 + {
1.2529 + // Return KErrNotReady for missing partitions on removable media
1.2530 + // as opposed to KErrNotSupported for missing partitions on fixed media
1.2531 + // since the latter don't exist whereas the former might exist at some time.
1.2532 + TInt sock;
1.2533 + r=IsRemovableDevice(sock) ? KErrNotReady : KErrNotSupported;
1.2534 + }
1.2535 +
1.2536 + iCurrentReq=&m;
1.2537 + if (r==KErrNone)
1.2538 + {
1.2539 + if(iTotalPartitionsOpened == 0)
1.2540 + {
1.2541 + UpdatePartitionInfo();
1.2542 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT2, this, KErrNone );
1.2543 + return KErrNone;
1.2544 + }
1.2545 + if (!(m.Flags() & TLocDrvRequest::EAdjusted))
1.2546 + {
1.2547 + // If this isn't the only partition, don't allow access to the whole media
1.2548 + if (iTotalPartitionsOpened > 1)
1.2549 + m.DriverFlags() &= ~RLocalDrive::ELocDrvWholeMedia;
1.2550 + r=m.CheckAndAdjustForPartition();
1.2551 + }
1.2552 + if (r==KErrNone)
1.2553 + {
1.2554 + OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_INTERNALS, DPRIMARYMEDIABASE_DOREQUEST_START, "req Id=%d; Remote Thread=0x%x", (TInt) m.Id(), (TUint) m.RemoteThread());
1.2555 + r=media->iDriver->Request(m);
1.2556 + if (r>0)
1.2557 + {
1.2558 + // defer request
1.2559 +#ifdef __DEMAND_PAGING__
1.2560 + if (DMediaPagingDevice::PagingRequest(m))
1.2561 + {
1.2562 + __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
1.2563 + __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
1.2564 + __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
1.2565 + __KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Defer PageIn request 0x%08x",&m));
1.2566 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOREQUEST2, "Defer PageIn request 0x%08x", &m);
1.2567 + DMediaPagingDevice* pagingdevice=iBody->iPagingDevice;
1.2568 +
1.2569 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.2570 + TInt id=m.iValue;
1.2571 + if (id==DMediaPagingDevice::ERomPageInRequest)
1.2572 + {
1.2573 + NKern::FMWait(&pagingdevice->iInstrumentationLock);
1.2574 + if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ)
1.2575 + pagingdevice->iROMStats.iTotalReDeferrals++;
1.2576 + else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ)
1.2577 + pagingdevice->iROMStats.iTotalSynchDeferredFromMainQ++;
1.2578 + NKern::FMSignal(&pagingdevice->iInstrumentationLock);
1.2579 + }
1.2580 + else if (m.Flags() & TLocDrvRequest::ECodePaging)
1.2581 + {
1.2582 + NKern::FMWait(&pagingdevice->iInstrumentationLock);
1.2583 + if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ)
1.2584 + pagingdevice->iCodeStats.iTotalReDeferrals++;
1.2585 + else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ)
1.2586 + pagingdevice->iCodeStats.iTotalSynchDeferredFromMainQ++;
1.2587 + NKern::FMSignal(&pagingdevice->iInstrumentationLock);
1.2588 + }
1.2589 + else if (m.Flags() & TLocDrvRequest::EDataPaging)
1.2590 + {
1.2591 + NKern::FMWait(&pagingdevice->iInstrumentationLock);
1.2592 + if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ)
1.2593 + pagingdevice->iDataStats.iTotalReDeferrals++;
1.2594 + else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ)
1.2595 + pagingdevice->iDataStats.iTotalSynchDeferredFromMainQ++;
1.2596 + NKern::FMSignal(&pagingdevice->iInstrumentationLock);
1.2597 + }
1.2598 +#endif
1.2599 + pagingdevice->SendToDeferredQ(&m);
1.2600 + }
1.2601 + else
1.2602 +#endif
1.2603 + m.Forward(&iDeferred,EFalse);
1.2604 + r=KErrNone;
1.2605 + }
1.2606 +#if defined(__DEMAND_PAGING__) && defined(_DEBUG)
1.2607 + else if (r == KErrNone && DMediaPagingDevice::PagingRequest(m))
1.2608 + {
1.2609 + __KTRACE_OPT(KLOCDPAGING,Kern::Printf("PageIn req 0x%08x completing asynchronously",&m));
1.2610 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOREQUEST3, "PageIn req 0x%08x completing asynchronously", &m);
1.2611 + }
1.2612 +#endif
1.2613 + }
1.2614 + }
1.2615 +
1.2616 + if (r!=KErrNone && iCurrentReq)
1.2617 + {
1.2618 + TInt s=(r==KErrCompletion)?KErrNone:r;
1.2619 + CHECK_RET(s);
1.2620 +
1.2621 +#ifdef __DEMAND_PAGING__
1.2622 + // got here because media driver cannot service or defer this request or did service it synchronously
1.2623 + if (DMediaPagingDevice::PagingRequest(m))
1.2624 + {
1.2625 + __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
1.2626 + __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
1.2627 + __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
1.2628 + __KTRACE_OPT(KLOCDPAGING,Kern::Printf("media driver cannot service or defer PageIn request 0x%08x or serviced it synchronously (%d)",&m, s));
1.2629 + 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);
1.2630 + iBody->iPagingDevice->CompleteRequest(&m, s);
1.2631 + }
1.2632 + else
1.2633 +#endif
1.2634 +
1.2635 + CompleteRequest(m, s);
1.2636 + 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);
1.2637 + }
1.2638 +
1.2639 + iCurrentReq=NULL;
1.2640 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT3, this, r );
1.2641 + return r;
1.2642 + }
1.2643 +
1.2644 +EXPORT_C void DPrimaryMediaBase::PowerUpComplete(TInt anError)
1.2645 +/**
1.2646 +Called after the device is powered up or there is some error while powering up the device.
1.2647 +If there is an error powering up the devices then it just completes the current running requests with an error
1.2648 +and also completes the outstanding requests on the iDeferred message queue by calling SetClosed( ).
1.2649 +If the device is powered up OK then it either opens the media drivers
1.2650 +and if they are already open then it handles the current/pending requests.
1.2651 +
1.2652 +@param anError Error code to be passed on while completing outstanding requests.
1.2653 +*/
1.2654 + {
1.2655 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_ENTRY, this );
1.2656 + __KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase(%d)::PowerUpComplete err %d iState %d",iMediaId,anError,iState));
1.2657 +
1.2658 + OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_POWERUPCOMPLETE, "iMediaId=%d; anError=%d; iState=%d", iMediaId, anError, iState );
1.2659 +
1.2660 + if (anError!=KErrNone)
1.2661 + {
1.2662 + // error powering up device
1.2663 + if (iState==EPoweringUp1 || iState==EPoweringUp2)
1.2664 + SetClosed(anError);
1.2665 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_EXIT, this );
1.2666 + return;
1.2667 + }
1.2668 +
1.2669 + // Powered up OK - now open media drivers
1.2670 + if (iState==EPoweringUp1)
1.2671 + {
1.2672 + iState=EOpening;
1.2673 + StartOpenMediaDrivers();
1.2674 + }
1.2675 + else if (iState==EPoweringUp2)
1.2676 + {
1.2677 + // media is powered up and ready, so handle the current/pending requests
1.2678 + MediaReadyHandleRequest();
1.2679 + }
1.2680 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_EXIT2, this );
1.2681 + }
1.2682 +
1.2683 +void DPrimaryMediaBase::CloseMediaDrivers(DMedia* aMedia)
1.2684 + {
1.2685 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_ENTRY, this );
1.2686 + __KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase(%d)::CloseMediaDrivers",iMediaId));
1.2687 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS1, "DPrimaryMediaBase iMediaId=%d", iMediaId );
1.2688 +
1.2689 + // we mustn't ever close the media driver if it's responsible for data paging as re-opening the drive
1.2690 + // would involve memory allocation which might cause deadlock if the kernel heap were to grow
1.2691 +#ifdef __DEMAND_PAGING__
1.2692 + if (DataPagingDfcQ(this))
1.2693 + {
1.2694 + __KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for data paging media %08X", this));
1.2695 + OstTrace1(TRACE_FLOW, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT1, "CloseMediaDrivers aborting for data paging media 0x%08x", this);
1.2696 + return;
1.2697 + }
1.2698 +#endif
1.2699 +
1.2700 + TInt i;
1.2701 + for (i=0; i<KMaxLocalDrives; i++)
1.2702 + {
1.2703 + TLocDrv* pL=TheDrives[i];
1.2704 + if (pL && pL->iPrimaryMedia==this)
1.2705 + {
1.2706 + __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",i));
1.2707 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", i );
1.2708 + if (aMedia == NULL || pL->iMedia == aMedia)
1.2709 + {
1.2710 + pL->iMedia=NULL;
1.2711 + }
1.2712 + }
1.2713 + }
1.2714 + for (i=iLastMediaId; i>=iMediaId; i--)
1.2715 + {
1.2716 + DMedia* pM=TheMedia[i];
1.2717 + if (aMedia == NULL || pM == aMedia)
1.2718 + {
1.2719 + DMediaDriver* pD=pM->iDriver;
1.2720 + pM->iDriver=NULL;
1.2721 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DMedia[%d] @ %08x Driver @ %08x",i,pM,pD));
1.2722 + OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS3, "MediaId=%d; DMedia=0x%08x; MediaDriver=0x%08x", (TInt) i, (TUint) pM, (TUint) pD );
1.2723 + if (pD)
1.2724 + pD->Close();
1.2725 + }
1.2726 + }
1.2727 + __KTRACE_OPT(KLOCDRV,Kern::Printf("<DPrimaryMediaBase(%d)::CloseMediaDrivers",iMediaId));
1.2728 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT2, this );
1.2729 + }
1.2730 +
1.2731 +void DPrimaryMediaBase::StartOpenMediaDrivers()
1.2732 + {
1.2733 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS_ENTRY, this );
1.2734 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::StartOpenMediaDrivers",iMediaId));
1.2735 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS, "DPrimaryMediaBase iMediaId=%d ",iMediaId);
1.2736 + TVersion ver(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
1.2737 +
1.2738 + // Get a list of all currently loaded media drivers
1.2739 + // Most media drivers do not make use of the pointer iMountInfo.iInfo when
1.2740 + // their Validate() procedures are called from RPhysicalDeviceArray::GetDriverList().
1.2741 + // However, a group of media drivers sharing the same id (passed in iDevice) may use
1.2742 + // the additional information pointed to by iMountInfo.iInfo to distinguish
1.2743 + // group members. This information is passed when the media driver is registered
1.2744 + // using LocDrv::RegisterMediaDevice().
1.2745 + TInt r=iPhysDevArray.GetDriverList(KLitMediaDriverName,iDevice,iMountInfo.iInfo,ver);
1.2746 + if (r!=KErrNone)
1.2747 + {
1.2748 + // out of memory or no driver exists
1.2749 + SetClosed(r);
1.2750 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS_EXIT1, this );
1.2751 + return;
1.2752 + }
1.2753 +
1.2754 + // Go through them starting with highest priority
1.2755 + iNextMediaId=iMediaId;
1.2756 + iBody->iPhysDevIndex=iPhysDevArray.Count()-1;
1.2757 + iTotalPartitionsOpened=0;
1.2758 + iMediaDriversOpened=0;
1.2759 + iNextMediaDriver=NULL;
1.2760 + OpenNextMediaDriver();
1.2761 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS_EXIT2, this );
1.2762 + }
1.2763 +
1.2764 +void DPrimaryMediaBase::OpenNextMediaDriver()
1.2765 + {
1.2766 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_ENTRY, this );
1.2767 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::OpenNextMediaDriver, this %x mediaId %d iBody->iPhysDevIndex %d",iNextMediaId, this, iMediaId, iBody->iPhysDevIndex));
1.2768 + 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);
1.2769 +
1.2770 + TVersion ver(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
1.2771 + SPhysicalDeviceEntry& e=iPhysDevArray[iBody->iPhysDevIndex];
1.2772 + DPhysicalDevice* pD=e.iPhysicalDevice;
1.2773 +
1.2774 + iState = EOpening;
1.2775 +
1.2776 + DMedia* pM=TheMedia[iNextMediaId];
1.2777 + if (pM && pM->iDriver != NULL)
1.2778 + {
1.2779 + iNextMediaDriver = pM->iDriver;
1.2780 + DoOpenMediaDriverComplete(KErrNone);
1.2781 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_EXIT1, this );
1.2782 + return;
1.2783 + }
1.2784 +
1.2785 + // this may be asynchronous
1.2786 + TInt s=pD->Create( (DBase*&)iNextMediaDriver, iMediaId, (TDesC8*) &iMountInfo, ver);
1.2787 +
1.2788 + __KTRACE_OPT(KLOCDRV,Kern::Printf("Media:Open-Opening %o(PRI:%d)-%d",pD,e.iPriority,s));
1.2789 + if (s!=KErrNone)
1.2790 + {
1.2791 + iAsyncErrorCode=s;
1.2792 + iAsyncDfc.Enque();
1.2793 + }
1.2794 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_EXIT2, this );
1.2795 + }
1.2796 +
1.2797 +// Called when a media driver has responded to the Open request
1.2798 +void DPrimaryMediaBase::DoOpenMediaDriverComplete(TInt anError)
1.2799 + {
1.2800 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_ENTRY, this );
1.2801 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::DoOpenMediaDriverComplete error %d iNextMediaDriver %x",iNextMediaId,anError,iNextMediaDriver));
1.2802 + OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE, "iMediaId=%d; anError=%d; iNextMediaDriver=0x%x", (TInt) iNextMediaId, (TInt) anError, (TUint) iNextMediaDriver);
1.2803 +
1.2804 +
1.2805 + if (anError!=KErrNone)
1.2806 + {
1.2807 + DMediaDriver* md = iNextMediaDriver;
1.2808 + iNextMediaDriver = NULL;
1.2809 + if (md)
1.2810 + md->Close();
1.2811 + }
1.2812 + if (anError==KErrNotReady || anError==KErrNoMemory)
1.2813 + {
1.2814 + // if it's not ready or we're out of memory, abort
1.2815 + CloseMediaDrivers();
1.2816 + SetClosed(anError);
1.2817 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_EXIT1, this );
1.2818 + return;
1.2819 + }
1.2820 + if (anError==KErrNone)
1.2821 + {
1.2822 + DMedia* pM=TheMedia[iNextMediaId];
1.2823 + pM->iDriver=iNextMediaDriver;
1.2824 + DPhysicalDevice*& pD=iPhysDevArray[iBody->iPhysDevIndex].iPhysicalDevice;
1.2825 + iNextMediaDriver->iPhysicalDevice=pD;
1.2826 + pD=NULL; // so it won't be closed when we tidy up
1.2827 + ++iMediaDriversOpened;
1.2828 + }
1.2829 +
1.2830 +
1.2831 + // if no error, read partition info on media
1.2832 + iState = EReadPartitionInfo;
1.2833 +
1.2834 + if (anError == KErrNone)
1.2835 + {
1.2836 + DMedia* pM=TheMedia[iNextMediaId];
1.2837 + TInt r = pM->iDriver->PartitionInfo(pM->iPartitionInfo);
1.2838 + if (r!=KErrNone)
1.2839 + {
1.2840 + if (r==KErrCompletion)
1.2841 + r=KErrNone;
1.2842 + DoPartitionInfoComplete(r);
1.2843 + }
1.2844 + }
1.2845 + else
1.2846 + {
1.2847 + DoPartitionInfoComplete(anError);
1.2848 + }
1.2849 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_EXIT2, this );
1.2850 + }
1.2851 +
1.2852 +void DPrimaryMediaBase::DoPartitionInfoComplete(TInt anError)
1.2853 + {
1.2854 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_ENTRY, this );
1.2855 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::DoPartitionInfoComplete error %d",iNextMediaId,anError));
1.2856 +
1.2857 + OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE1, "iNextMediaId=%d; anError=%d", iNextMediaId, anError );
1.2858 +
1.2859 + DMedia* pM=TheMedia[iNextMediaId];
1.2860 + if (anError==KErrNone || anError == KErrLocked)
1.2861 + {
1.2862 + // successfully read partition info
1.2863 + iTotalPartitionsOpened+=pM->PartitionCount();
1.2864 + }
1.2865 + else
1.2866 + {
1.2867 + // couldn't read partition info or driver failed to open
1.2868 + if (pM->iDriver)
1.2869 + {
1.2870 +#ifdef __DEMAND_PAGING__
1.2871 + if (DataPagingDfcQ(this))
1.2872 + {
1.2873 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DoPartitionInfoComplete(%d) Close Media Driver aborted for data paging media %08X", this));
1.2874 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE2, "Close Media Driver for data paging media 0x%08x", this);
1.2875 + }
1.2876 + else
1.2877 +#endif
1.2878 + {
1.2879 + pM->iDriver->Close();
1.2880 + pM->iDriver=NULL;
1.2881 + }
1.2882 + }
1.2883 + if (anError==KErrNotReady || anError==KErrNoMemory)
1.2884 + {
1.2885 + // if it's not ready or we're out of memory, or the drive is locked, abort
1.2886 + CloseMediaDrivers();
1.2887 + SetClosed(anError);
1.2888 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT, this );
1.2889 + return;
1.2890 + }
1.2891 + }
1.2892 +
1.2893 + // Open next media driver, if there is one
1.2894 + TBool complete = EFalse;
1.2895 + if (++iNextMediaId>iLastMediaId)
1.2896 + complete=ETrue;
1.2897 + if (iBody->iPhysDevIndex==0)
1.2898 + complete=ETrue;
1.2899 + else
1.2900 + iBody->iPhysDevIndex--;
1.2901 + if (!complete)
1.2902 + {
1.2903 + OpenNextMediaDriver();
1.2904 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT2, this );
1.2905 + return;
1.2906 + }
1.2907 +
1.2908 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase %d All media drivers open & partitions read",iMediaId));
1.2909 + __KTRACE_OPT(KLOCDRV,Kern::Printf("%d media drivers opened",iMediaDriversOpened));
1.2910 + OstTrace1( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE3, "iMediaDriversOpened=%d", iMediaDriversOpened );
1.2911 + if (iMediaDriversOpened==0)
1.2912 + {
1.2913 + SetClosed(KErrNotSupported);
1.2914 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT3, this );
1.2915 + return;
1.2916 + }
1.2917 +
1.2918 + // we are now finished with media driver list
1.2919 + iPhysDevArray.Close();
1.2920 +
1.2921 + // Finished reading partition info
1.2922 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase %d Read partition info complete",iMediaId));
1.2923 + __KTRACE_OPT(KLOCDRV,Kern::Printf("%d total partitions",iTotalPartitionsOpened));
1.2924 + OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE4, "Read partition info complete iMediaId=%d; iPartitionsOpened=%d", iMediaId, iTotalPartitionsOpened );
1.2925 + if (iTotalPartitionsOpened==0)
1.2926 + {
1.2927 + SetClosed(KErrNotSupported);
1.2928 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT4, this );
1.2929 + return;
1.2930 + }
1.2931 +
1.2932 + // work out mapping of drives to partitions/media
1.2933 + TInt totalPartitions=iTotalPartitionsOpened;
1.2934 + TInt id=iMediaId; // start with primary media
1.2935 + TInt partitionsOnThisMedia=PartitionCount();
1.2936 + TInt partition=0;
1.2937 + TInt j;
1.2938 + for (j=0; j<KMaxLocalDrives; j++)
1.2939 + {
1.2940 + TLocDrv* pD=TheDrives[j];
1.2941 + if (pD && pD->iPrimaryMedia==this)
1.2942 + {
1.2943 + if (totalPartitions==0)
1.2944 + {
1.2945 + pD->iMedia=NULL;
1.2946 + continue;
1.2947 + }
1.2948 + if (partition==partitionsOnThisMedia)
1.2949 + {
1.2950 + id++;
1.2951 + partition=0;
1.2952 + partitionsOnThisMedia=TheMedia[id]->PartitionCount();
1.2953 + }
1.2954 + __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d = Media %d Partition %d",j,id,partition));
1.2955 + OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE5, "Local Drive=%d; iMediaId=%d; partition=%d", j, id, partition );
1.2956 +
1.2957 + pD->iMedia=TheMedia[id];
1.2958 + pD->iPartitionNumber=partition;
1.2959 + memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry));
1.2960 + partition++;
1.2961 + totalPartitions--;
1.2962 + }
1.2963 + }
1.2964 +
1.2965 + // media is now ready - handle current or deferred requests
1.2966 + MediaReadyHandleRequest();
1.2967 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT5, this );
1.2968 + }
1.2969 +
1.2970 +void DPrimaryMediaBase::MediaReadyHandleRequest()
1.2971 + {
1.2972 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_MEDIAREADYHANDLEREQUEST_ENTRY, this );
1.2973 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase::MediaReadyHandleRequest() this %x", this));
1.2974 + iState = EReady;
1.2975 +
1.2976 + // now we can process the current request
1.2977 + // careful - thread may have exited while we were powering up
1.2978 + if (iCurrentReq)
1.2979 + {
1.2980 + DoRequest(*iCurrentReq); // this sets iCurrentReq=NULL
1.2981 + }
1.2982 +
1.2983 + // see if we can process any other requests concurrently
1.2984 + RunDeferred();
1.2985 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_MEDIAREADYHANDLEREQUEST_EXIT, this );
1.2986 + }
1.2987 +
1.2988 +void DPrimaryMediaBase::UpdatePartitionInfo()
1.2989 + {
1.2990 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_UPDATEPARTITIONINFO_ENTRY, this );
1.2991 + iState=EReadPartitionInfo;
1.2992 + iNextMediaId=iMediaId;
1.2993 + DMedia* pM=TheMedia[iNextMediaId];
1.2994 + TInt r=pM->iDriver->PartitionInfo(pM->iPartitionInfo);
1.2995 + if (r!=KErrNone)
1.2996 + {
1.2997 + if (r==KErrCompletion)
1.2998 + r=KErrNone;
1.2999 + DoPartitionInfoComplete(r);
1.3000 + }
1.3001 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_UPDATEPARTITIONINFO_EXIT, this );
1.3002 + }
1.3003 +
1.3004 +void DPrimaryMediaBase::CompleteCurrent(TInt anError)
1.3005 + {
1.3006 + OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_COMPLETECURRENT_ENTRY, this );
1.3007 + if (iCurrentReq)
1.3008 + {
1.3009 + CHECK_RET(anError);
1.3010 +#ifdef __DEMAND_PAGING__
1.3011 + // got here because it was powered down when powering up, or failed powering up or failed opening MD or got media change
1.3012 + if (DMediaPagingDevice::PagingRequest(*iCurrentReq))
1.3013 + {
1.3014 + __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
1.3015 + __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
1.3016 + __ASSERT_ALWAYS( ((iCurrentReq->Flags() & TLocDrvRequest::ECodePaging) == 0) || (iCurrentReq->Drive()->iPagingDrv), LOCM_FAULT());
1.3017 +
1.3018 + __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"));
1.3019 + 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");
1.3020 + iBody->iPagingDevice->CompleteRequest(iCurrentReq, anError);
1.3021 + }
1.3022 + else
1.3023 +#endif
1.3024 + CompleteRequest(*iCurrentReq, anError);
1.3025 + iCurrentReq=NULL;
1.3026 + }
1.3027 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_COMPLETECURRENT_EXIT, this );
1.3028 + }
1.3029 +
1.3030 +
1.3031 +void DPrimaryMediaBase::CompleteRequest(TLocDrvRequest& aMsg, TInt aResult)
1.3032 + {
1.3033 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_COMPLETEREQUEST_ENTRY, this );
1.3034 + OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_COMPLETEREQUEST1, "TLocDrvRequest Object=0x%x; aResult=%d", (TUint) &aMsg, aResult);
1.3035 + aMsg.Complete(aResult,EFalse);
1.3036 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_COMPLETEREQUEST_EXIT, this );
1.3037 + }
1.3038 +
1.3039 +EXPORT_C void DPrimaryMediaBase::RunDeferred()
1.3040 +/**
1.3041 +Runs deferred Requests. Initiated from DPrimaryMediaBase::PowerUpComplete() function
1.3042 +to see if any other requests can be processed concurrently.
1.3043 +Can also be called from DPrimaryMediaBase::NotifyPowerDown
1.3044 +or DPrimaryMediaBase::NotifyEmergencyPowerDown() function or DMediaDriver::Complete()
1.3045 +*/
1.3046 + {
1.3047 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_RUNDEFERRED_ENTRY, this );
1.3048 + // Do nothing if an open or close is in progress - this might be the case, for example,
1.3049 + // if a EForceMediaChange request (with the KForceMediaChangeReOpenMediaDriver flag)
1.3050 + // has recently been processed
1.3051 + if (iState!=EReady && iState!=EClosed && iState!=EPoweredDown)
1.3052 + {
1.3053 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT1, this );
1.3054 + return;
1.3055 + }
1.3056 +
1.3057 + // rerun deferred requests;
1.3058 +#ifdef __DEMAND_PAGING__
1.3059 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3060 + TInt countROM=0;
1.3061 + TInt countCode=0;
1.3062 +#endif
1.3063 +
1.3064 + if(iPagingMedia)
1.3065 + {
1.3066 + __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
1.3067 + if(iBody->iPagingDevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ) // if already emptying deferred page in queue, don't reenter
1.3068 + {
1.3069 + __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Already emptying deferred queue"));
1.3070 + OstTrace0(TRACE_FLOW, DPRIMARYMEDIABASE_RUNDEFERRED_EXIT2, "< Already emptying deferred queue");
1.3071 + return;
1.3072 + }
1.3073 +
1.3074 + DMediaPagingDevice* pagingdevice=iBody->iPagingDevice;
1.3075 + TLocDrvRequest* pL = (TLocDrvRequest*) pagingdevice->iDeferredQ.Last();
1.3076 + if(pL)
1.3077 + {
1.3078 + pagingdevice->iEmptyingQ|= DMediaPagingDevice::EDeferredQ; // prevent reentering when already emptying this queue
1.3079 + TLocDrvRequest* pM=NULL;
1.3080 + while (pM != pL && (pM = (TLocDrvRequest*) pagingdevice->iDeferredQ.Poll()) != NULL) // synchronously empty deferred queue but ignore re-deferrals
1.3081 + {
1.3082 + __ASSERT_ALWAYS( DMediaPagingDevice::PagingRequest(*pL), LOCM_FAULT() );
1.3083 +
1.3084 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3085 + (pM->iValue==DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++);
1.3086 + if(pM==pL)
1.3087 + {
1.3088 + NKern::FMWait(&pagingdevice->iInstrumentationLock);
1.3089 + if(pM->iValue==DMediaPagingDevice::ERomPageInRequest && pagingdevice->iROMStats.iMaxReqsInDeferred<countROM)
1.3090 + pagingdevice->iROMStats.iMaxReqsInDeferred=countROM;
1.3091 + else if ((pM->Flags() & TLocDrvRequest::ECodePaging) && pagingdevice->iCodeStats.iMaxReqsInDeferred<countCode)
1.3092 + pagingdevice->iCodeStats.iMaxReqsInDeferred=countCode;
1.3093 + else if ((pM->Flags() & TLocDrvRequest::EDataPaging) && pagingdevice->iDataStats.iMaxReqsInDeferred<countCode)
1.3094 + pagingdevice->iDataStats.iMaxReqsInDeferred=countCode;
1.3095 + NKern::FMSignal(&pagingdevice->iInstrumentationLock);
1.3096 + }
1.3097 +#endif
1.3098 + __KTRACE_OPT(KLOCDPAGING,Kern::Printf("RunDeferred: process req 0x%08x, last in deferred queue 0x%08x",pM,pL));
1.3099 + OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_RUNDEFERRED2, "process req=0x%08x; last in deferred queue=0x%08x",(TUint) pM, (TUint) pL);
1.3100 +#ifdef BTRACE_PAGING_MEDIA
1.3101 + BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInDeferredReposted,pM,pM->iValue);
1.3102 +#endif
1.3103 + // if Page In requests are synchronous this services them all in sequence,
1.3104 + // if they're asynch it re-defers them
1.3105 + DoRequest(*(TLocDrvRequest*)pM);
1.3106 + }
1.3107 + pagingdevice->iEmptyingQ&= ~DMediaPagingDevice::EDeferredQ;
1.3108 + }
1.3109 +
1.3110 + // the reason we now try an empty the main Page In queue is there is at least one type of Page In request
1.3111 + // serviced synchronously in which case when we empty the deferred Page In queue as above, received Page In
1.3112 + // requests are left in the main queue (not deferred) and we don't want to start processing deferred normal
1.3113 + // requests before these Page In requests. If all deferred normal requests are synchronous, the received Page
1.3114 + // In requests will have to wait until all are serviced. NB: requests may be deferred even if the MD services
1.3115 + // all requests synchronously, but runs background tasks that cannot be interrupted. In this last case the
1.3116 + // normal deferred queue may have some very long latency requests.
1.3117 + if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ) // already emptying main Page In queue, skip (any Page In requests will be deferred)
1.3118 + {
1.3119 + __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Already emptying main queue"));
1.3120 + OstTrace0(TRACE_FLOW, DPRIMARYMEDIABASE_RUNDEFERRED_EXIT3, "< Already emptying main queue");
1.3121 + return;
1.3122 + }
1.3123 +
1.3124 + TLocDrvRequest* pM=NULL;
1.3125 + if (!pagingdevice->iMainQ.iReady) // if it's ready, then queue is empty
1.3126 + {
1.3127 + pM = (TLocDrvRequest*) pagingdevice->iMainQ.iMessage;
1.3128 + pagingdevice->iMainQ.iMessage = NULL;
1.3129 + if (pM == NULL)
1.3130 + pM = (TLocDrvRequest*) pagingdevice->iMainQ.Poll();
1.3131 + }
1.3132 +
1.3133 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3134 + countROM = countCode=0;
1.3135 +#endif
1.3136 + if(pM)
1.3137 + {
1.3138 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3139 + __e32_atomic_add_ord32(&pagingdevice->iROMStats.iTotalSynchEmptiedMainQ, 1);
1.3140 +#endif
1.3141 + pagingdevice->iEmptyingQ|=DMediaPagingDevice::EMainQ;
1.3142 + for ( ; pM != NULL; pM = (TLocDrvRequest*) pagingdevice->iMainQ.Poll())
1.3143 + {
1.3144 + __ASSERT_ALWAYS(DMediaPagingDevice::PagingRequest(*pM), LOCM_FAULT());
1.3145 +
1.3146 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3147 + (pM->iValue==DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++);
1.3148 +#endif
1.3149 +
1.3150 + __KTRACE_OPT(KLOCDPAGING,Kern::Printf("RunDeferred: process req 0x%08x",pM));
1.3151 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_RUNDEFERRED4, "process req=0x%08x", pM);
1.3152 + DoRequest(*(TLocDrvRequest*)pM); // if Page In requests are synchronous this services them all in sequence, if they're asynch it defers them
1.3153 + }
1.3154 +
1.3155 + pagingdevice->iEmptyingQ&= ~DMediaPagingDevice::EMainQ;
1.3156 +
1.3157 +
1.3158 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3159 + NKern::FMWait(&pagingdevice->iInstrumentationLock);
1.3160 + pagingdevice->iROMStats.iTotalSynchServicedFromMainQ+=countROM;
1.3161 + if(pagingdevice->iROMStats.iMaxReqsInPending<countROM)
1.3162 + pagingdevice->iROMStats.iMaxReqsInPending=countROM;
1.3163 + pagingdevice->iCodeStats.iTotalSynchServicedFromMainQ+=countCode;
1.3164 + if(pagingdevice->iCodeStats.iMaxReqsInPending<countCode)
1.3165 + pagingdevice->iCodeStats.iMaxReqsInPending=countCode;
1.3166 + NKern::FMSignal(&pagingdevice->iInstrumentationLock);
1.3167 +#endif
1.3168 + } // if (pM)
1.3169 + } // if(iPagingMedia)
1.3170 +#endif
1.3171 + if (iRunningDeferred)
1.3172 + {
1.3173 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT4, this );
1.3174 + return;
1.3175 + }
1.3176 + TMessageBase* pL = iDeferred.Last();
1.3177 + if (!pL)
1.3178 + {
1.3179 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT5, this );
1.3180 + return; // no deferred requests
1.3181 + }
1.3182 + iRunningDeferred=1;
1.3183 + TMessageBase* pM=NULL;
1.3184 +
1.3185 + while( pM != pL && (pM=iDeferred.Poll()) != NULL) // stop after processing last one (requests may be re-deferred)
1.3186 + DoRequest(*(TLocDrvRequest*)pM);
1.3187 + iRunningDeferred=0;
1.3188 +
1.3189 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT6, this );
1.3190 + }
1.3191 +
1.3192 +void DPrimaryMediaBase::SetClosed(TInt anError)
1.3193 + {
1.3194 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_SETCLOSED_ENTRY, this );
1.3195 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::SetClosed error %d",iMediaId,anError));
1.3196 + OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_SETCLOSED, "iMediaId=%d; anError=%d", iMediaId, anError );
1.3197 + CHECK_RET(anError);
1.3198 +
1.3199 + // cancel DMediaDriver::OpenMediaDriverComplete() / DMediaDriver::PartitionInfoComplete() DFC
1.3200 + iAsyncDfc.Cancel();
1.3201 +
1.3202 + iDeferred.CompleteAll(anError);
1.3203 +
1.3204 +#ifdef __DEMAND_PAGING__
1.3205 + if(iPagingMedia)
1.3206 + iBody->iPagingDevice->iDeferredQ.CompleteAll(anError);
1.3207 +#endif
1.3208 +
1.3209 + CompleteCurrent(anError);
1.3210 +
1.3211 +
1.3212 +
1.3213 + if (iState==EOpening)
1.3214 + iPhysDevArray.Close();
1.3215 +
1.3216 + iState = EClosed;
1.3217 +
1.3218 + iWaitMedChg.CompleteAll(KErrNone);
1.3219 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_SETCLOSED_EXIT, this );
1.3220 + }
1.3221 +
1.3222 +void DPrimaryMediaBase::NotifyClients(TBool aMediaChange,TLocDrv* aLocDrv)
1.3223 +
1.3224 +//
1.3225 +// Notify all clients of a media change or power-down event
1.3226 +//
1.3227 + {
1.3228 + OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_NOTIFYCLIENTS_ENTRY, this );
1.3229 +
1.3230 + SDblQueLink* pL=iConnectionQ.iA.iNext;
1.3231 + while (pL!=&iConnectionQ.iA)
1.3232 + {
1.3233 + DLocalDrive* pD=_LOFF(pL,DLocalDrive,iLink);
1.3234 + // Issue the notification if the caller wants to notify all drives (aLocDrv == NULL) or
1.3235 + // the specified drive matches this one
1.3236 + if (aLocDrv == NULL || aLocDrv == pD->iDrive)
1.3237 + pD->NotifyChange(*this, aMediaChange);
1.3238 + pL=pL->iNext;
1.3239 + }
1.3240 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYCLIENTS_EXIT, this );
1.3241 + }
1.3242 +
1.3243 +EXPORT_C void DPrimaryMediaBase::NotifyMediaChange()
1.3244 +/**
1.3245 +Closes all media drivers on this device and notifies all connections that media change has occurred
1.3246 +and completes any outstanding requests with KErrNotReady.
1.3247 +This also completes any force media change requests with KErrNone.
1.3248 +*/
1.3249 + {
1.3250 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_ENTRY, this );
1.3251 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaChange state %d",iMediaId,iState));
1.3252 +
1.3253 + OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE, "iMediaId=%d; iState=%d", iMediaId, iState );
1.3254 +
1.3255 + TInt state=iState;
1.3256 +
1.3257 + __ASSERT_DEBUG(iBody, LOCM_FAULT());
1.3258 +
1.3259 +#ifdef __DEMAND_PAGING__
1.3260 + iBody->iMediaChanges++;
1.3261 +
1.3262 + // As data paging media never close, need to ensure the media driver cancels
1.3263 + // any requests it owns as the stack may be powered down by DPBusPrimaryMedia::ForceMediaChange().
1.3264 + // DMediaDriver::NotifyPowerDown() should do this
1.3265 + if(DataPagingDfcQ(this))
1.3266 + NotifyPowerDown();
1.3267 +#endif
1.3268 +
1.3269 + // complete any outstanding requests with KErrNotReady
1.3270 + // and any force media change requests with KErrNone
1.3271 + SetClosed(KErrNotReady);
1.3272 +
1.3273 + // close all media drivers on this device
1.3274 + if (state>=EOpening)
1.3275 + {
1.3276 + CloseMediaDrivers();
1.3277 + }
1.3278 +
1.3279 + // notify all connections that media change has occurred
1.3280 + NotifyClients(ETrue);
1.3281 +
1.3282 + // complete any force media change requests
1.3283 + iWaitMedChg.CompleteAll(KErrNone);
1.3284 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_EXIT, this );
1.3285 + }
1.3286 +
1.3287 +
1.3288 +EXPORT_C void DPrimaryMediaBase::NotifyPowerDown()
1.3289 +/**
1.3290 +Called on machine power-down. Notifies all media drivers on this device.
1.3291 +If device is not ready then it completes current requests but leaves other outstanding requests
1.3292 +If ready, media driver should complete current request.
1.3293 +
1.3294 +*/
1.3295 + {
1.3296 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_ENTRY, this );
1.3297 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyPowerDown state %d",iMediaId,iState));
1.3298 +
1.3299 + OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPOWERDOWN, "iMediaId=%d; iState=%d", iMediaId, iState );
1.3300 +
1.3301 + TInt id;
1.3302 + TBool allPersistent = ETrue;
1.3303 + TBool allOpen = ETrue;
1.3304 +
1.3305 + // notify all media drivers on this device
1.3306 + for (id=iMediaId; id<=iLastMediaId; id++)
1.3307 + {
1.3308 + DMedia* pM = TheMedia[id];
1.3309 + DMediaDriver* pD = pM->iDriver;
1.3310 +
1.3311 + if ((pD) && (iState==EReady || iState==EReadPartitionInfo || iState==EOpening || iState==EPoweringUp2 || iState==ERecovering))
1.3312 + pD->NotifyPowerDown();
1.3313 +
1.3314 + if (pD == NULL || pD->iPhysicalDevice == NULL)
1.3315 + allOpen = EFalse;
1.3316 + else if (pD->iPhysicalDevice->Info(DPhysicalDevice::EMediaDriverPersistent, NULL) != KErrNone)
1.3317 + {
1.3318 + // We must NOT destroy the media driver if this media is responsible for data paging as
1.3319 + // re-opening the media driver would involve memory allocation which might cause a deadlock
1.3320 +#ifdef __DEMAND_PAGING__
1.3321 + __ASSERT_ALWAYS(!DataPagingDfcQ(this), LOCM_FAULT());
1.3322 +#endif
1.3323 + allPersistent = EFalse;
1.3324 + }
1.3325 + }
1.3326 +
1.3327 + __KTRACE_OPT(KLOCDRV,Kern::Printf("allPersistent(%d)::allOpen %d",allPersistent, allOpen));
1.3328 + OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPOWERDOWN2, "allPersistent=%d; allOpen=%d", allPersistent, allOpen );
1.3329 +
1.3330 + if (allPersistent && allOpen && iState == EReady)
1.3331 + {
1.3332 + //
1.3333 + // The EPoweredDown state indicates that the media is powered down, but the media driver still exists.
1.3334 + //
1.3335 + // - This allows the media driver to still be accessed (ie - to determine driver capabilities) without
1.3336 + // the need to power up the device, which can be a lengthy operation.
1.3337 + //
1.3338 + // - NOTE : This will need re-visiting if we ever re-enable standby mode on a platform that is not capable
1.3339 + // of detecting door interrupts while in standby. In such a scenario, problems could occur as
1.3340 + // the device capabilities may change without the local media subsystem recognising.
1.3341 + //
1.3342 + iState=EPoweredDown;
1.3343 + }
1.3344 + else
1.3345 + {
1.3346 + CloseMediaDrivers();
1.3347 + SetClosed(KErrNotReady);
1.3348 + }
1.3349 +
1.3350 + NotifyClients(EFalse);
1.3351 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_EXIT, this );
1.3352 + }
1.3353 +
1.3354 +
1.3355 +EXPORT_C void DPrimaryMediaBase::NotifyPsuFault(TInt anError)
1.3356 +/**
1.3357 +Closes all media drivers on this device and completes any outstanding requests with error code.
1.3358 +@param anError Error code to be passed on while closing media drivers and completing outstanding requests.
1.3359 +*/
1.3360 +
1.3361 + {
1.3362 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYPSUFAULT_ENTRY, this );
1.3363 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyPsuFault state %d, err %d",iMediaId,iState,anError));
1.3364 + OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPSUFAULT, "iMediaId=%d; iState=%d; anError=%d", iMediaId, iState, anError );
1.3365 +
1.3366 + if (iState>=EOpening)
1.3367 + {
1.3368 + CloseMediaDrivers();
1.3369 + }
1.3370 +
1.3371 + // complete any outstanding requests with error
1.3372 + SetClosed(anError);
1.3373 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPSUFAULT_EXIT, this );
1.3374 + }
1.3375 +
1.3376 +EXPORT_C void DPrimaryMediaBase::NotifyEmergencyPowerDown()
1.3377 +/**
1.3378 +Called on emergency power down. Notifies all media drivers on this device.
1.3379 +If it is not in a ready state then it completes the current request but leaves other outstanding requests.
1.3380 +If it is ready then the media driver should complete the current request.
1.3381 +It closes all media drivers and notifies all clients of a power down event.
1.3382 +*/
1.3383 + {
1.3384 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_ENTRY, this );
1.3385 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyEmergencyPowerDown state %d",iMediaId,iState));
1.3386 + OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN, "iMediaId=%d; iState=%d", iMediaId, iState );
1.3387 +
1.3388 + TBool recover=EFalse;
1.3389 + if (iState==EReady && iCritical!=0)
1.3390 + {
1.3391 + // check if emergency power recovery supported
1.3392 + ;
1.3393 + }
1.3394 + if (recover)
1.3395 + {
1.3396 + }
1.3397 +
1.3398 + // else just return KErrAbort
1.3399 + // notify all media drivers on this device
1.3400 + if (iState==EReady || iState==EOpening || iState==EPoweringUp2 || iState==ERecovering)
1.3401 + {
1.3402 + TInt id;
1.3403 + for (id=iMediaId; id<=iLastMediaId; id++)
1.3404 + {
1.3405 + DMedia* pM=TheMedia[id];
1.3406 + DMediaDriver* pD=pM->iDriver;
1.3407 + if (pD)
1.3408 + pD->NotifyEmergencyPowerDown();
1.3409 + }
1.3410 + }
1.3411 +
1.3412 + if (iState!=EReady)
1.3413 + {
1.3414 + // complete current request but leave other outstanding requests
1.3415 + // if ready, media driver should complete current request
1.3416 + CompleteCurrent(KErrNotReady);
1.3417 + }
1.3418 + CloseMediaDrivers();
1.3419 + SetClosed(KErrNotReady);
1.3420 + NotifyClients(EFalse);
1.3421 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_EXIT, this );
1.3422 + }
1.3423 +
1.3424 +EXPORT_C void DPrimaryMediaBase::NotifyMediaPresent()
1.3425 +/**
1.3426 +Notifies clients of a media change by calling NotifyClients ( ) function to indicate that media is present.
1.3427 +*/
1.3428 + {
1.3429 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_ENTRY, this );
1.3430 + NotifyClients(ETrue);
1.3431 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_EXIT, this );
1.3432 + }
1.3433 +
1.3434 +EXPORT_C TInt DPrimaryMediaBase::DoInCritical()
1.3435 +/**
1.3436 +Flags the media driver as entering a critical part of its processing.
1.3437 +
1.3438 +In this context, critical means that the driver must be allowed to complete
1.3439 +its current activity.
1.3440 +For example, a request to power down the device must be deferred until
1.3441 +the driver exits the critical part.
1.3442 +
1.3443 +@return KErrNone, if the driver has been successfully flagged as being in
1.3444 + a critical part; otherwise, one of the other system-wide error codes.
1.3445 + The default implementation just returns KErrNone and can be overridden in the derived class
1.3446 +@see DPrimaryMediaBase::DoEndInCritical()
1.3447 +*/
1.3448 +
1.3449 + {
1.3450 + return KErrNone;
1.3451 + }
1.3452 +
1.3453 +EXPORT_C void DPrimaryMediaBase::DoEndInCritical()
1.3454 +/**
1.3455 +Flags the media driver as leaving a critical part of its processing.
1.3456 +
1.3457 +Default implementation does nothing
1.3458 +@see DPrimaryMediaBase::DoEndInCritical()
1.3459 +*/
1.3460 + {
1.3461 + }
1.3462 +
1.3463 +TInt DPrimaryMediaBase::InCritical()
1.3464 + {
1.3465 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_INCRITICAL_ENTRY, this );
1.3466 + if (iCritical==0)
1.3467 + {
1.3468 + TInt r=DoInCritical();
1.3469 + if (r!=KErrNone)
1.3470 + {
1.3471 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_INCRITICAL_EXIT1, this, r );
1.3472 + return r;
1.3473 + }
1.3474 + }
1.3475 + ++iCritical;
1.3476 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_INCRITICAL_EXIT2, this, KErrNone );
1.3477 + return KErrNone;
1.3478 + }
1.3479 +
1.3480 +void DPrimaryMediaBase::EndInCritical()
1.3481 + {
1.3482 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_ENDINCRITICAL_ENTRY, this );
1.3483 + if (--iCritical==0)
1.3484 + DoEndInCritical();
1.3485 + OstTraceFunctionExit1( DPRIMARYMEDIABASE_ENDINCRITICAL_EXIT, this );
1.3486 + }
1.3487 +
1.3488 +EXPORT_C void DPrimaryMediaBase::DeltaCurrentConsumption(TInt /*aCurrent*/)
1.3489 +/**
1.3490 +Sets the incremental value of current consumption to aCurrent.
1.3491 +The default implementation does nothing .
1.3492 +
1.3493 +@param aCurrent Delta Current in Milliamps
1.3494 +*/
1.3495 + {
1.3496 + // default implementation
1.3497 + }
1.3498 +
1.3499 +TInt DPrimaryMediaBase::OpenMediaDriver()
1.3500 +//
1.3501 +// Synchronous open for devices with no DFC queue (e.g. IRAM)
1.3502 +//
1.3503 + {
1.3504 + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_OPENMEDIADRIVER_ENTRY, this );
1.3505 +
1.3506 + __KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase:OpenMediaDriver-%d",iMediaId));
1.3507 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_OPENMEDIADRIVER1, "iMediaId=%d", iMediaId);
1.3508 +
1.3509 + TVersion ver(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
1.3510 +
1.3511 + // Get a list of all currently loaded media drivers
1.3512 + // Most media drivers do not make use of the pointer iMountInfo.iInfo when
1.3513 + // their Validate() procedures are called from RPhysicalDeviceArray::GetDriverList().
1.3514 + // However, a group of media drivers sharing the same id (passed in iDevice) may use
1.3515 + // the additional information pointed to by iMountInfo.iInfo to distinguish
1.3516 + // group members. This information is passed when the media driver is registered
1.3517 + // using LocDrv::RegisterMediaDevice().
1.3518 + TInt r=iPhysDevArray.GetDriverList(KLitMediaDriverName,iDevice,iMountInfo.iInfo,ver);
1.3519 + if (r!=KErrNone)
1.3520 + {
1.3521 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_OPENMEDIADRIVER_EXIT1, this, r );
1.3522 + return r;
1.3523 + }
1.3524 + // Go through them starting with highest priority
1.3525 + TInt totalPartitions=0;
1.3526 + TInt c=iPhysDevArray.Count(); // can't be zero
1.3527 + TInt i=c-1;
1.3528 + r=KErrNotSupported;
1.3529 + for (iNextMediaId=iMediaId; i>=0 && iNextMediaId<=iLastMediaId && r!=KErrNotReady; i--)
1.3530 + {
1.3531 + DPhysicalDevice* pD=iPhysDevArray[i].iPhysicalDevice;
1.3532 + DMediaDriver *pM=NULL;
1.3533 +
1.3534 + // try to open media driver
1.3535 + TInt s=pD->Create( (DBase*&)pM, iMediaId, NULL, ver);
1.3536 +
1.3537 + __KTRACE_OPT(KLOCDRV,Kern::Printf("Media:Open-Opening %o(PRI:%d)-%d",pD,iPhysDevArray[i].iPriority,s));
1.3538 + 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);
1.3539 + if (s!=KErrNone && pM)
1.3540 + {
1.3541 + pM->Close();
1.3542 + pM=NULL;
1.3543 + }
1.3544 + if (s==KErrNotReady)
1.3545 + {
1.3546 + r=KErrNotReady; // If it isn't ready - nothing will open.
1.3547 + break;
1.3548 + }
1.3549 + if (s==KErrNoMemory)
1.3550 + {
1.3551 + r=KErrNoMemory; // If we are out of memory, give up now
1.3552 + break;
1.3553 + }
1.3554 + if (s==KErrNone)
1.3555 + {
1.3556 + // Found a media driver for this device - check for valid partitions.
1.3557 + DMedia* media=TheMedia[iNextMediaId];
1.3558 + s=pM->PartitionInfo(media->iPartitionInfo);
1.3559 + if (s==KErrNone)
1.3560 + {
1.3561 + r=KErrNone;
1.3562 + media->iDriver=pM;
1.3563 + pM->iPhysicalDevice=pD;
1.3564 + iPhysDevArray[i].iPhysicalDevice=NULL; // so it won't be closed when we tidy up
1.3565 + totalPartitions+=media->PartitionCount();
1.3566 + }
1.3567 + else
1.3568 + pM->Close();
1.3569 + }
1.3570 + }
1.3571 +
1.3572 + // we are now finished with media driver list
1.3573 + iPhysDevArray.Close();
1.3574 +
1.3575 + // if driver opened OK, work out mapping of drives to partitions/media
1.3576 + if (r==KErrNone)
1.3577 + {
1.3578 + TInt id=iMediaId; // start with primary media
1.3579 + TInt partitionsOnThisMedia=PartitionCount();
1.3580 + TInt partition=0;
1.3581 + TInt j;
1.3582 + for (j=0; j<KMaxLocalDrives; j++)
1.3583 + {
1.3584 + TLocDrv* pD=TheDrives[j];
1.3585 + if (pD && pD->iPrimaryMedia==this)
1.3586 + {
1.3587 + if (totalPartitions==0)
1.3588 + {
1.3589 + pD->iMedia=NULL;
1.3590 + continue;
1.3591 + }
1.3592 + if (partition==partitionsOnThisMedia)
1.3593 + {
1.3594 + id++;
1.3595 + partition=0;
1.3596 + partitionsOnThisMedia=TheMedia[id]->PartitionCount();
1.3597 + }
1.3598 + pD->iMedia=TheMedia[id];
1.3599 + pD->iPartitionNumber=partition;
1.3600 + memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry));
1.3601 + partition++;
1.3602 + totalPartitions--;
1.3603 + }
1.3604 + }
1.3605 + }
1.3606 +
1.3607 + __KTRACE_OPT(KLOCDRV,Kern::Printf("<DPrimaryMediaBase:OpenMediaDriver-%d",r));
1.3608 + OstTraceFunctionExitExt( DPRIMARYMEDIABASE_OPENMEDIADRIVER_EXIT2, this, r );
1.3609 + return r;
1.3610 + }
1.3611 +
1.3612 +#ifdef __DEMAND_PAGING__
1.3613 +// RequestCountInc()
1.3614 +//
1.3615 +// Counts the number of outstanding requests
1.3616 +// For data-paging media, calls DPagingDevice::NotifyBusy() when count goes positive
1.3617 +//
1.3618 +void DPrimaryMediaBase::RequestCountInc()
1.3619 + {
1.3620 + __ASSERT_DEBUG(iBody, LOCM_FAULT());
1.3621 + TInt oldVal = (TInt) __e32_atomic_add_ord32(&iBody->iRequestCount, (TUint) 1);
1.3622 +//Kern::Printf("RCINC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal);
1.3623 +
1.3624 + OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTINC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal );
1.3625 +
1.3626 + if (oldVal == 0 && iBody->iPagingDevice)
1.3627 + {
1.3628 +//Kern::Printf("RCINC: NotifyBusy()");
1.3629 + iBody->iPagingDevice->NotifyBusy();
1.3630 + }
1.3631 + }
1.3632 +
1.3633 +// RequestCountDec()
1.3634 +//
1.3635 +// Counts the number of outstanding requests
1.3636 +// For data-paging media, calls DPagingDevice::NotifyIdle() when count reaches zero
1.3637 +//
1.3638 +void DPrimaryMediaBase::RequestCountDec()
1.3639 + {
1.3640 + __ASSERT_DEBUG(iBody, LOCM_FAULT());
1.3641 + TInt oldVal = (TInt) __e32_atomic_add_ord32(&iBody->iRequestCount, (TUint) -1);
1.3642 +//Kern::Printf("RCDEC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal);
1.3643 +
1.3644 + OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTDEC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal );
1.3645 +
1.3646 + if (oldVal == 1 && iBody->iPagingDevice)
1.3647 + {
1.3648 +//Kern::Printf("RCDEC: NotifyIdle()");
1.3649 + iBody->iPagingDevice->NotifyIdle();
1.3650 + }
1.3651 + __ASSERT_DEBUG(iBody->iRequestCount >= 0, LOCM_FAULT());
1.3652 + }
1.3653 +#endif // __DEMAND_PAGING__
1.3654 +
1.3655 +TPartitionInfo::TPartitionInfo()
1.3656 +//
1.3657 +// Constructor
1.3658 +//
1.3659 + {
1.3660 + memclr(this, sizeof(TPartitionInfo));
1.3661 + }
1.3662 +
1.3663 +#ifdef __DEMAND_PAGING__
1.3664 +
1.3665 +void pageInDfc(TAny* aPtr)
1.3666 + {
1.3667 + OstTraceFunctionEntry0( _PAGEINDFC_ENTRY );
1.3668 + __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("pageInDfc"));
1.3669 + DPrimaryMediaBase* primaryMedia=(DPrimaryMediaBase*)aPtr;
1.3670 + __ASSERT_ALWAYS(primaryMedia && primaryMedia->iPagingMedia && primaryMedia->iBody->iPagingDevice,LOCM_FAULT());
1.3671 + DMediaPagingDevice* pagingdevice=primaryMedia->iBody->iPagingDevice;
1.3672 +
1.3673 + TLocDrvRequest* m = (TLocDrvRequest*) pagingdevice->iMainQ.iMessage;
1.3674 + pagingdevice->iMainQ.iMessage = NULL;
1.3675 +
1.3676 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3677 + if (!m)
1.3678 + __e32_atomic_add_ord8(&pagingdevice->iROMStats.iTotalRunDry, 1);
1.3679 +#endif
1.3680 +
1.3681 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3682 + TInt countROM=0;
1.3683 + TInt countCode=0;
1.3684 +#endif
1.3685 +
1.3686 + for ( ; m != NULL; m = (TLocDrvRequest*) pagingdevice->iMainQ.Poll())
1.3687 + {
1.3688 + __ASSERT_ALWAYS(DMediaPagingDevice::PagingRequest(*m), LOCM_FAULT());
1.3689 +
1.3690 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3691 + (m->iValue == DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++);
1.3692 +#endif
1.3693 + __KTRACE_OPT(KLOCDPAGING, Kern::Printf("pageInDfc: process request 0x%08x, last in queue 0x%08x",m, pagingdevice->iMainQ.Last()) );
1.3694 + OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, PAGEINDFC2, "process request=0x%08x; last in queue=0x%08x",(TUint) m, (TUint) pagingdevice->iMainQ.Last());
1.3695 +
1.3696 + primaryMedia->HandleMsg(*m);
1.3697 + }
1.3698 +
1.3699 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3700 + NKern::FMWait(&pagingdevice->iInstrumentationLock);
1.3701 + if (pagingdevice->iROMStats.iMaxReqsInPending<countROM)
1.3702 + pagingdevice->iROMStats.iMaxReqsInPending=countROM;
1.3703 + if (pagingdevice->iCodeStats.iMaxReqsInPending<countCode)
1.3704 + pagingdevice->iCodeStats.iMaxReqsInPending=countCode;
1.3705 + NKern::FMSignal(&pagingdevice->iInstrumentationLock);
1.3706 +#endif
1.3707 +
1.3708 + pagingdevice->iMainQ.Receive(); // allow reception of more messages
1.3709 + OstTraceFunctionExit0( _PAGEINDFC_EXIT );
1.3710 + }
1.3711 +
1.3712 +DMediaPagingDevice::DMediaPagingDevice(DPrimaryMediaBase* aPtr)
1.3713 + : iMainQ(pageInDfc, aPtr, NULL, KMaxDfcPriority),
1.3714 + iDeferredQ(NULL, NULL, NULL, 0), // callback never used
1.3715 + iEmptyingQ(NULL),
1.3716 + iInstrumentationLock()
1.3717 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3718 + ,iServicingROM(NULL), iServicingCode(NULL)
1.3719 +#endif
1.3720 + {
1.3721 + OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_CONSTRUCTOR_ENTRY, this );
1.3722 + iPrimaryMedia = aPtr;
1.3723 + if (iPrimaryMedia->iDfcQ) // media driver has its own thread
1.3724 + {
1.3725 + iMainQ.SetDfcQ(iPrimaryMedia->iDfcQ);
1.3726 + }
1.3727 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3728 + memclr((TAny*)&iROMStats,sizeof(SMediaROMPagingConcurrencyInfo)+sizeof(SMediaCodePagingConcurrencyInfo));
1.3729 +#endif
1.3730 +#ifdef __DEMAND_PAGING_BENCHMARKS__
1.3731 + iROMBenchmarkData.iCount=iROMBenchmarkData.iTotalTime=iROMBenchmarkData.iMaxTime=0;
1.3732 + iROMBenchmarkData.iMinTime = KMaxTInt;
1.3733 + iCodeBenchmarkData.iCount=iCodeBenchmarkData.iTotalTime=iCodeBenchmarkData.iMaxTime=0;
1.3734 + iCodeBenchmarkData.iMinTime = KMaxTInt;
1.3735 + iDataInBenchmarkData.iCount=iDataInBenchmarkData.iTotalTime=iDataInBenchmarkData.iMaxTime=0;
1.3736 + iDataInBenchmarkData.iMinTime = KMaxTInt;
1.3737 + iDataOutBenchmarkData.iCount=iDataOutBenchmarkData.iTotalTime=iDataOutBenchmarkData.iMaxTime=0;
1.3738 + iDataOutBenchmarkData.iMinTime = KMaxTInt;
1.3739 +#endif
1.3740 +
1.3741 + iMainQ.Receive();
1.3742 + OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_CONSTRUCTOR_EXIT, this );
1.3743 + }
1.3744 +
1.3745 +DMediaPagingDevice::~DMediaPagingDevice()
1.3746 + {
1.3747 +OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_DESTRUCTOR_ENTRY, this );
1.3748 +
1.3749 + if (iMountInfoDataLock)
1.3750 + ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDataLock);
1.3751 +
1.3752 + if (iMountInfoDescHdrLock)
1.3753 + ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDescHdrLock);
1.3754 +
1.3755 + if (iMountInfoDescLenLock)
1.3756 + ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDescLenLock);
1.3757 + OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_DESTRUCTOR_EXIT, this );
1.3758 + }
1.3759 +
1.3760 +
1.3761 +void DMediaPagingDevice::SendToMainQueueDfcAndBlock(TThreadMessage* aMsg)
1.3762 + {
1.3763 + OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_SENDTOMAINQUEUEDFCANDBLOCK_ENTRY, this );
1.3764 + __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("Send request 0x%08x to main queue",aMsg));
1.3765 + __ASSERT_ALWAYS(aMsg->iState==TMessageBase::EFree,LOCM_FAULT()); // check that message was previously completed or never queued
1.3766 +
1.3767 + // if drive supports DMA, turn on Physical memory flag & sync memory
1.3768 + TLocDrvRequest& m=*(TLocDrvRequest*)(aMsg);
1.3769 +
1.3770 + TLinAddr addr = (TLinAddr) m.RemoteDes();
1.3771 + TInt len = I64LOW(m.Length());
1.3772 +
1.3773 + TBool needSyncAfterRead = EFalse;
1.3774 + if (m.Drive()->iDmaHelper)
1.3775 + {
1.3776 + m.Flags() |= TLocDrvRequest::EPhysAddr;
1.3777 + if (m.Id() == DLocalDrive::EWrite)
1.3778 + {
1.3779 + Cache::SyncMemoryBeforeDmaWrite(addr, len);
1.3780 + }
1.3781 + else
1.3782 + {
1.3783 + Cache::SyncMemoryBeforeDmaRead(addr, len);
1.3784 + needSyncAfterRead = ETrue;
1.3785 + }
1.3786 + }
1.3787 +
1.3788 + // Count the number of outstanding requests if this is the data-paging media, so that
1.3789 + // we can call DPagingDevice::NotifyBusy() / DPagingDevice::NotifyIdle()
1.3790 + if ((m.Flags() & TLocDrvRequest::EBackgroundPaging) == 0)
1.3791 + iPrimaryMedia->RequestCountInc();
1.3792 +
1.3793 + aMsg->SendReceive(&iMainQ);
1.3794 +
1.3795 +#ifdef __DEMAND_PAGING__
1.3796 + if ((m.Flags() & TLocDrvRequest::EBackgroundPaging) == 0)
1.3797 + iPrimaryMedia->RequestCountDec();
1.3798 +#endif
1.3799 +
1.3800 + if (needSyncAfterRead)
1.3801 + {
1.3802 + Cache::SyncMemoryAfterDmaRead(addr, len);
1.3803 + }
1.3804 +
1.3805 +
1.3806 + // come back here when request is completed
1.3807 + __ASSERT_DEBUG(aMsg->iState==TMessageBase::EFree,LOCM_FAULT()); // check message has been completed
1.3808 + OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_SENDTOMAINQUEUEDFCANDBLOCK_EXIT, this );
1.3809 + }
1.3810 +
1.3811 +void DMediaPagingDevice::SendToDeferredQ(TThreadMessage* aMsg)
1.3812 + {
1.3813 + OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_SENDTODEFERREDQ_ENTRY, this );
1.3814 + // This queue is only accessed from MD thread
1.3815 + __ASSERT_ALWAYS(aMsg->iState==TMessageBase::EAccepted,LOCM_FAULT()); // check that message was previously dequeued
1.3816 +#ifdef BTRACE_PAGING_MEDIA
1.3817 + if(iEmptyingQ&DMediaPagingDevice::EDeferredQ) // already deferring
1.3818 + BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInReDeferred,aMsg,aMsg->iValue);
1.3819 + else
1.3820 + BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInDeferred,aMsg,aMsg->iValue);
1.3821 +#endif
1.3822 +
1.3823 + aMsg->Forward(&iDeferredQ, EFalse);
1.3824 + OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_SENDTODEFERREDQ_EXIT, this );
1.3825 + }
1.3826 +
1.3827 +
1.3828 +void DMediaPagingDevice::CompleteRequest(TThreadMessage* aMsg, TInt aResult)
1.3829 + {
1.3830 + OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_COMPLETEREQUEST_ENTRY, this );
1.3831 + __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::CompleteRequest, request 0x%08x result %d", aMsg, aResult));
1.3832 + __ASSERT_DEBUG(aMsg->iState==TMessageBase::EAccepted,LOCM_FAULT());
1.3833 +
1.3834 +#ifdef BTRACE_PAGING_MEDIA
1.3835 + BTraceContext12(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInPagedIn,aMsg,aResult,aMsg->iValue);
1.3836 +#endif
1.3837 +
1.3838 + iPrimaryMedia->CompleteRequest(*((TLocDrvRequest*) aMsg), aResult);
1.3839 + OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_COMPLETEREQUEST_EXIT, this );
1.3840 + }
1.3841 +
1.3842 +TInt DMediaPagingDevice::Read(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt aDrvNumber)
1.3843 + {
1.3844 + OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_READ_ENTRY, this );
1.3845 + __ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT()); // that would lock up the system, thus better die now
1.3846 + __ASSERT_ALWAYS(aReq,LOCM_FAULT());
1.3847 + __ASSERT_CRITICAL
1.3848 +
1.3849 +#ifdef __DEMAND_PAGING_BENCHMARKS__
1.3850 + TUint32 bmStart = NKern::FastCounter();
1.3851 +#endif
1.3852 +
1.3853 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.3854 + TUint8* servicingCount;
1.3855 + NKern::FMWait(&iInstrumentationLock);
1.3856 + if(aDrvNumber == EDriveRomPaging) // ROM paging
1.3857 + {
1.3858 + servicingCount = &iServicingROM;
1.3859 + if(iServicingROM)
1.3860 + iROMStats.iTotalConcurrentReqs++;
1.3861 + if(!(++iServicingROM))
1.3862 + {
1.3863 + iServicingROM=1; // overflow...
1.3864 + iROMStats.iTotalConcurrentReqs=0; // ...reset this
1.3865 + }
1.3866 + TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
1.3867 + if(!empty)
1.3868 + iROMStats.iTotalReqIssuedNonEmptyQ++;
1.3869 + }
1.3870 + else if (aDrvNumber == EDriveDataPaging) // Data paging
1.3871 + {
1.3872 + servicingCount = &iServicingDataIn;
1.3873 + if(iServicingDataIn)
1.3874 + iDataStats.iTotalConcurrentReqs++;
1.3875 + if(!(++iServicingDataIn))
1.3876 + {
1.3877 + iServicingDataIn=1; // overflow...
1.3878 + iDataStats.iTotalConcurrentReqs=0; // ...reset this
1.3879 + }
1.3880 + TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
1.3881 + if(!empty)
1.3882 + iDataStats.iTotalReqIssuedNonEmptyQ++;
1.3883 + }
1.3884 + else
1.3885 + {
1.3886 + servicingCount = &iServicingCode;
1.3887 + if(iServicingCode)
1.3888 + iCodeStats.iTotalConcurrentReqs++;
1.3889 + if(!(++iServicingCode))
1.3890 + {
1.3891 + iServicingCode=1; // overflow...
1.3892 + iCodeStats.iTotalConcurrentReqs=0; // ...reset this
1.3893 + }
1.3894 + TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
1.3895 + if(!empty)
1.3896 + iCodeStats.iTotalReqIssuedNonEmptyQ++;
1.3897 + }
1.3898 + NKern::FMSignal(&iInstrumentationLock);
1.3899 +#endif
1.3900 +
1.3901 + TUint offset=aOffset<<iReadUnitShift;
1.3902 + TUint size=aSize<<iReadUnitShift;
1.3903 +
1.3904 +#ifdef BTRACE_PAGING_MEDIA
1.3905 + TInt buf[3];
1.3906 + buf[0]=size; // page in request length
1.3907 + buf[1]=aDrvNumber; // local drive number (-1 if ROM)
1.3908 + buf[2]=(TInt)aReq; // address of request object
1.3909 + BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInBegin,aBuffer,offset,buf,sizeof(buf));
1.3910 +#endif
1.3911 +
1.3912 + __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));
1.3913 + 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);
1.3914 +
1.3915 + // no DFCQ, media driver executes in the context of calling thread
1.3916 + if (!iPrimaryMedia->iDfcQ)
1.3917 + {
1.3918 + LOCM_FAULT(); // don't allow paging
1.3919 + OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_READ_EXIT, this, KErrNone );
1.3920 + return KErrNone; // keep compiler happy
1.3921 + }
1.3922 +
1.3923 +
1.3924 + TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
1.3925 +
1.3926 +
1.3927 +#ifdef __DEMAND_PAGING_BENCHMARKS__
1.3928 + SPagingBenchmarkInfo* info = NULL;
1.3929 +#endif
1.3930 +
1.3931 +
1.3932 + // Read from the media and allow for retries in the unlikely event of an error.
1.3933 + const TInt KPageInRetries = 5;
1.3934 + TInt retVal = KErrGeneral;
1.3935 + for (TInt i=0; retVal != KErrNone && i < KPageInRetries; i++)
1.3936 + {
1.3937 + m.Flags() = TLocDrvRequest::EPaging;
1.3938 + TLocDrv* pL=NULL;
1.3939 + if(aDrvNumber == EDriveRomPaging) // ROM paging
1.3940 + {
1.3941 + m.Id() = DMediaPagingDevice::ERomPageInRequest;
1.3942 + if (iRomPagingDriveNumber == KErrNotFound)
1.3943 + {
1.3944 + // ROM partition has not been reported by the media driver
1.3945 + // it is assumed that the media driver will adjust the request accordingly
1.3946 + m.Flags() |= TLocDrvRequest::EAdjusted;
1.3947 + // Use a media drive number so the request reaches the correct media...
1.3948 + m.Drive() = TheDrives[iFirstLocalDriveNumber];
1.3949 + }
1.3950 + else
1.3951 + {
1.3952 + //ROM partition has been reported
1.3953 + //Set drive for use with CheckAndAdjustForPartition
1.3954 + m.Drive() = TheDrives[iRomPagingDriveNumber];
1.3955 + }
1.3956 +#ifdef __DEMAND_PAGING_BENCHMARKS__
1.3957 + __e32_atomic_add_ord32(&iMediaPagingInfo.iRomPageInCount, (TUint) 1);
1.3958 + info = &iROMBenchmarkData;
1.3959 +#endif
1.3960 + }
1.3961 + else if(aDrvNumber == EDriveDataPaging) // Data paging
1.3962 + {
1.3963 + m.Id() = DLocalDrive::ERead;
1.3964 + m.Flags() |= TLocDrvRequest::EDataPaging;
1.3965 + m.Drive() = TheDrives[iDataPagingDriveNumber];
1.3966 +#ifdef __DEMAND_PAGING_BENCHMARKS__
1.3967 + __e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageInCount, (TUint) 1);
1.3968 + info = &iDataInBenchmarkData;
1.3969 +#endif
1.3970 + }
1.3971 + else if ((aDrvNumber >=0) && (aDrvNumber<KMaxLocalDrives)) // Code paging
1.3972 + {
1.3973 + m.Id() = DMediaPagingDevice::ECodePageInRequest;
1.3974 + m.Flags() |= TLocDrvRequest::ECodePaging;
1.3975 + pL=TheDrives[aDrvNumber];
1.3976 + __ASSERT_DEBUG(pL&&(pL->iPrimaryMedia==iPrimaryMedia),LOCM_FAULT()); // valid drive number?
1.3977 + m.Drive()=pL;
1.3978 +#ifdef __DEMAND_PAGING_BENCHMARKS__
1.3979 + __e32_atomic_add_ord32(&iMediaPagingInfo.iCodePageInCount, (TUint) 1);
1.3980 + info = &iCodeBenchmarkData;
1.3981 +#endif
1.3982 + }
1.3983 + else
1.3984 + LOCM_FAULT(); // invalid drive number
1.3985 +
1.3986 + m.RemoteThread()=NULL;
1.3987 + m.Pos()=offset;
1.3988 + m.Length()=Int64(size);
1.3989 + m.RemoteDes()=(TAny*)aBuffer;
1.3990 + m.RemoteDesOffset()=0; // pre-aligned
1.3991 + m.DriverFlags()=0;
1.3992 + __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()));
1.3993 + 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());
1.3994 +
1.3995 + __ASSERT_DEBUG(iPrimaryMedia->iBody, LOCM_FAULT());
1.3996 + TInt mediaChanges = iPrimaryMedia->iBody->iMediaChanges;
1.3997 +
1.3998 + SendToMainQueueDfcAndBlock(&m); // queues request, sets and opens client thread, queues dfc and blocks thread until request is completed
1.3999 + retVal = m.iValue;
1.4000 +
1.4001 +#ifdef __DEBUG_DEMAND_PAGING__
1.4002 + if (retVal != KErrNone)
1.4003 + {
1.4004 + Kern::Printf("Pagin Failure %d, retry %d", retVal, i);
1.4005 + }
1.4006 +#endif
1.4007 +
1.4008 + // reset retry count if there's ben a media change
1.4009 + if (retVal != KErrNone && mediaChanges != iPrimaryMedia->iBody->iMediaChanges)
1.4010 + i = 0;
1.4011 + } // for ()
1.4012 +
1.4013 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.4014 + NKern::FMWait(&iInstrumentationLock);
1.4015 + if (*servicingCount)
1.4016 + (*servicingCount)--;
1.4017 + NKern::FMSignal(&iInstrumentationLock);
1.4018 +#endif
1.4019 +
1.4020 +#ifdef __DEMAND_PAGING_BENCHMARKS__
1.4021 + TUint32 bmEnd = NKern::FastCounter();
1.4022 + ++info->iCount;
1.4023 +#if !defined(HIGHIGH_RES_TIMER) || defined(HIGH_RES_TIMER_COUNTS_UP)
1.4024 + TInt64 elapsed=bmEnd-bmStart;
1.4025 +#else
1.4026 + TInt64 elapsed=bmStart-bmEnd;
1.4027 +#endif
1.4028 + info->iTotalTime += elapsed;
1.4029 + if (elapsed > info->iMaxTime)
1.4030 + info->iMaxTime = elapsed;
1.4031 + if (elapsed < info->iMinTime)
1.4032 + info->iMinTime = elapsed;
1.4033 +#endif // __DEMAND_PAGING_BENCHMARKS__
1.4034 + OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_READ_EXIT2, this, retVal );
1.4035 + return retVal;
1.4036 + }
1.4037 +
1.4038 +TInt DMediaPagingDevice::Write(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TBool aBackground)
1.4039 + {
1.4040 + OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_WRITE_ENTRY, this );
1.4041 + __ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT()); // that would lock up the system, thus better die now
1.4042 + __ASSERT_ALWAYS(aReq,LOCM_FAULT());
1.4043 + __ASSERT_CRITICAL
1.4044 +
1.4045 +#ifdef __DEMAND_PAGING_BENCHMARKS__
1.4046 + TUint32 bmStart = NKern::FastCounter();
1.4047 +#endif
1.4048 +
1.4049 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.4050 + NKern::FMWait(&iInstrumentationLock);
1.4051 + if(iServicingDataOut)
1.4052 + iDataStats.iTotalConcurrentReqs++;
1.4053 + if(!(++iServicingDataOut))
1.4054 + {
1.4055 + iServicingDataOut=1; // overflow...
1.4056 + iDataStats.iTotalConcurrentReqs=0; // ...reset this
1.4057 + }
1.4058 + TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
1.4059 + if(!empty)
1.4060 + iDataStats.iTotalReqIssuedNonEmptyQ++;
1.4061 + NKern::FMSignal(&iInstrumentationLock);
1.4062 +#endif
1.4063 +
1.4064 + TUint offset=aOffset<<iReadUnitShift;
1.4065 + TUint size=aSize<<iReadUnitShift;
1.4066 +
1.4067 +#ifdef BTRACE_PAGING_MEDIA
1.4068 + TInt buf[2];
1.4069 + buf[0] = size; // page out request length
1.4070 + buf[1] = (TInt)aReq; // address of request object
1.4071 + BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageOutBegin,aBuffer,offset,buf,sizeof(buf));
1.4072 +#endif
1.4073 +
1.4074 + __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::Write, Req(0x%08x), Buff(0x%x),Offset(%d),Size(%d)",aReq,aBuffer,offset,size));
1.4075 + 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);
1.4076 +
1.4077 + // no DFCQ, media driver executes in the context of calling thread
1.4078 + if (!iPrimaryMedia->iDfcQ)
1.4079 + {
1.4080 + LOCM_FAULT(); // don't allow paging
1.4081 + OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_WRITE_EXIT, this, KErrNone );
1.4082 + return KErrNone; // keep compiler happy
1.4083 + }
1.4084 +
1.4085 +
1.4086 + TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
1.4087 +
1.4088 +#ifdef __DEMAND_PAGING_BENCHMARKS__
1.4089 + __e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageOutCount, (TUint) 1);
1.4090 + if (aBackground)
1.4091 + __e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageOutBackgroundCount, (TUint) 1);
1.4092 +#endif
1.4093 +
1.4094 + // Write to the media and allow for retries in the unlikely event of an error.
1.4095 + const TInt KPageOutRetries = 5;
1.4096 + TInt retVal = KErrGeneral;
1.4097 + for (TInt i=0; retVal != KErrNone && i < KPageOutRetries; i++)
1.4098 + {
1.4099 + m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging | (aBackground ? TLocDrvRequest::EBackgroundPaging : 0);
1.4100 +
1.4101 + m.Id() = DLocalDrive::EWrite;
1.4102 + m.Drive() = TheDrives[iDataPagingDriveNumber];
1.4103 +
1.4104 + m.RemoteThread()=NULL;
1.4105 + m.Pos()=offset;
1.4106 + m.Length()=Int64(size);
1.4107 + m.RemoteDes()=(TAny*)aBuffer;
1.4108 + m.RemoteDesOffset()=0; // pre-aligned
1.4109 + m.DriverFlags()=0;
1.4110 + __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()));
1.4111 + 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());
1.4112 +
1.4113 + __ASSERT_DEBUG(iPrimaryMedia->iBody, LOCM_FAULT());
1.4114 + TInt mediaChanges = iPrimaryMedia->iBody->iMediaChanges;
1.4115 +
1.4116 + SendToMainQueueDfcAndBlock(&m); // queues request, sets and opens client thread, queues dfc and blocks thread until request is completed
1.4117 +
1.4118 + retVal = m.iValue;
1.4119 +
1.4120 +#ifdef __DEBUG_DEMAND_PAGING__
1.4121 + if (retVal != KErrNone)
1.4122 + Kern::Printf("Pagout Failure %d, retry %d", retVal, i);
1.4123 +#endif
1.4124 + // reset retry count if there's ben a media change
1.4125 + if (retVal != KErrNone && mediaChanges != iPrimaryMedia->iBody->iMediaChanges)
1.4126 + i = 0;
1.4127 + } // for ()
1.4128 +
1.4129 +#ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
1.4130 + NKern::FMWait(&iInstrumentationLock);
1.4131 + if (iServicingDataOut)
1.4132 + iServicingDataOut--;
1.4133 + NKern::FMSignal(&iInstrumentationLock);
1.4134 +#endif
1.4135 +
1.4136 +#ifdef __DEMAND_PAGING_BENCHMARKS__
1.4137 + SPagingBenchmarkInfo& info = iDataOutBenchmarkData;
1.4138 + TUint32 bmEnd = NKern::FastCounter();
1.4139 + ++info.iCount;
1.4140 +#if !defined(HIGHIGH_RES_TIMER) || defined(HIGH_RES_TIMER_COUNTS_UP)
1.4141 + TInt64 elapsed=bmEnd-bmStart;
1.4142 +#else
1.4143 + TInt64 elapsed=bmStart-bmEnd;
1.4144 +#endif
1.4145 + info.iTotalTime += elapsed;
1.4146 + if (elapsed > info.iMaxTime)
1.4147 + info.iMaxTime = elapsed;
1.4148 + if (elapsed < info.iMinTime)
1.4149 + info.iMinTime = elapsed;
1.4150 +#endif // __DEMAND_PAGING_BENCHMARKS__
1.4151 +
1.4152 + OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_WRITE_EXIT2, this, retVal );
1.4153 + return retVal;
1.4154 + }
1.4155 +
1.4156 +
1.4157 +TInt DMediaPagingDevice::DeleteNotify(TThreadMessage* aReq,TUint aOffset,TUint aSize)
1.4158 + {
1.4159 + OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DELETENOTIFY_ENTRY, this );
1.4160 + if (iDeleteNotifyNotSupported)
1.4161 + {
1.4162 + OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT1, this, KErrNotSupported );
1.4163 + return KErrNotSupported;
1.4164 + }
1.4165 +
1.4166 + __ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT()); // that would lock up the system, thus better die now
1.4167 + __ASSERT_ALWAYS(aReq,LOCM_FAULT());
1.4168 + __ASSERT_ALWAYS(DataPagingDfcQ(iPrimaryMedia),LOCM_FAULT());
1.4169 + __ASSERT_CRITICAL
1.4170 +
1.4171 + TUint offset = aOffset<<iReadUnitShift;
1.4172 + TUint size = aSize<<iReadUnitShift;
1.4173 +
1.4174 +#ifdef BTRACE_PAGING_MEDIA
1.4175 + TInt buf[2];
1.4176 + buf[0] = size; // delete notify length
1.4177 + buf[1] = (TInt)aReq; // address of request object
1.4178 + BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedDeleteNotifyBegin,NULL,offset,buf,sizeof(buf));
1.4179 +#endif
1.4180 +
1.4181 + __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::Write, Req(0x%08x), Offset(%d),Size(%d)",aReq,offset,size));
1.4182 + OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_DELETENOTIFY1 , "req=0x%08x; offset=%d; size=%d", (TUint) aReq, offset, size);
1.4183 +
1.4184 + // no DFCQ, media driver executes in the context of calling thread
1.4185 + if (!iPrimaryMedia->iDfcQ)
1.4186 + {
1.4187 + LOCM_FAULT(); // don't allow paging
1.4188 + OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT2, this, KErrNone );
1.4189 + return KErrNone; // keep compiler happy
1.4190 + }
1.4191 +
1.4192 + TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
1.4193 +
1.4194 +
1.4195 + m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging;
1.4196 + m.Id() = DLocalDrive::EDeleteNotify;
1.4197 + m.Drive() = TheDrives[iDataPagingDriveNumber];
1.4198 +
1.4199 + m.RemoteThread() = NULL;
1.4200 + m.Pos() = offset;
1.4201 + m.Length() = Int64(size);
1.4202 + m.RemoteDes() = NULL;
1.4203 + m.RemoteDesOffset() = 0; // pre-aligned
1.4204 + m.DriverFlags()=0;
1.4205 + __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()));
1.4206 + 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());
1.4207 +
1.4208 + // send request aynchronously as we don't particularly care about the result
1.4209 + // and waiting would slow down the thread taking the page fault
1.4210 + iPrimaryMedia->RequestCountInc();
1.4211 +
1.4212 + m.SendReceive(&iMainQ); // send request synchronously
1.4213 +
1.4214 +#ifdef __DEMAND_PAGING__
1.4215 + iPrimaryMedia->RequestCountDec();
1.4216 +#endif
1.4217 +
1.4218 + TInt retVal = m.iValue;
1.4219 +
1.4220 + if (retVal == KErrNotSupported)
1.4221 + iDeleteNotifyNotSupported = ETrue;
1.4222 +
1.4223 + OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT3, this, retVal );
1.4224 + return retVal;
1.4225 + }
1.4226 +
1.4227 +
1.4228 +
1.4229 +EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* aSrc, TInt aSize, TInt anOffset)
1.4230 + {
1.4231 + OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITETOPAGEHANDLER_ENTRY, this );
1.4232 +#ifdef BTRACE_PAGING_MEDIA
1.4233 + TMediaDevice medDev=Drive()->iMedia->iDevice;
1.4234 + TInt buf[3];
1.4235 + buf[0]=(TUint32)RemoteDes();
1.4236 + buf[1]=anOffset;
1.4237 + buf[2]=aSize;
1.4238 + BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaMedDrvWriteBack,medDev,this,buf,sizeof(buf));
1.4239 +#endif
1.4240 + __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("TLocDrvRequest::WriteToPageHandler, memcpy((aTrg)%08x, (aSrc)%08x, (aLength)%08x)",(TUint32)RemoteDes()+anOffset,aSrc,aSize));
1.4241 + (void)memcpy((TAny*)((TUint32)RemoteDes()+anOffset), aSrc, aSize); // maybe in later versions this could be something else
1.4242 + OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITETOPAGEHANDLER_EXIT, this, KErrNone );
1.4243 + return KErrNone;
1.4244 + }
1.4245 +
1.4246 +EXPORT_C TInt TLocDrvRequest::ReadFromPageHandler(TAny* aDst, TInt aSize, TInt anOffset)
1.4247 + {
1.4248 + OstTraceFunctionEntry1( TLOCDRVREQUEST_READFROMPAGEHANDLER_ENTRY, this );
1.4249 +#ifdef BTRACE_PAGING_MEDIA
1.4250 + TMediaDevice medDev=Drive()->iMedia->iDevice;
1.4251 + TInt buf[3];
1.4252 + buf[0]=(TUint32)RemoteDes();
1.4253 + buf[1]=anOffset;
1.4254 + buf[2]=aSize;
1.4255 + BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaMedDrvRead,medDev,this,buf,sizeof(buf));
1.4256 +#endif
1.4257 + __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("TLocDrvRequest::ReadFromPageHandler, memcpy((aDst)%08x, (aTrg)%08x, (aLength)%08x)",aDst,(TUint32)RemoteDes()+anOffset,aSize));
1.4258 + (void)memcpy(aDst, (TAny*)((TUint32)RemoteDes()+anOffset), aSize); // maybe in later versions this could be something else
1.4259 + OstTraceFunctionExitExt( TLOCDRVREQUEST_READFROMPAGEHANDLER_EXIT, this, KErrNone );
1.4260 + return KErrNone;
1.4261 + }
1.4262 +
1.4263 +_LIT(KLitFragmentationMutexName, "FRAGMENTATION_MUTEX");
1.4264 +
1.4265 +TInt DFragmentationPagingLock::Construct(TUint aNumPages)
1.4266 + {
1.4267 + OstTraceFunctionEntryExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_ENTRY, this );
1.4268 + TInt r=KErrNone;
1.4269 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation Lock: creating Mutex"));
1.4270 + r=Kern::MutexCreate(this->iFragmentationMutex, KLitFragmentationMutexName, KMutexOrdNone);
1.4271 + if (r!=KErrNone)
1.4272 + {
1.4273 + OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT1, this, r );
1.4274 + return r;
1.4275 + }
1.4276 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation Lock: Mutex created OK"));
1.4277 + OstTraceDef0(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DFRAGMENTATIONPAGINGLOCK_CONSTRUCT1 , "Fragmentation Lock: Mutex created OK");
1.4278 +
1.4279 + iFragmentGranularity = 0;
1.4280 + if (aNumPages == 0)
1.4281 + {
1.4282 + OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT2, this, KErrNone );
1.4283 + return KErrNone;
1.4284 + }
1.4285 +
1.4286 + // in CS
1.4287 + TInt pageSize=Kern::RoundToPageSize(1);
1.4288 + LockFragmentation();
1.4289 + r=Alloc(pageSize*aNumPages); // alloc pages
1.4290 + UnlockFragmentation();
1.4291 +
1.4292 + if(r==KErrNone)
1.4293 + {
1.4294 + iFragmentGranularity = pageSize * aNumPages;
1.4295 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation granularity set to 0x%x", iFragmentGranularity));
1.4296 + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DFRAGMENTATIONPAGINGLOCK_CONSTRUCT2, "Fragmentation granularity=0x%x", iFragmentGranularity);
1.4297 + }
1.4298 +
1.4299 + OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT3, this, r );
1.4300 + return r;
1.4301 + }
1.4302 +
1.4303 +void DFragmentationPagingLock::Cleanup()
1.4304 + {
1.4305 + OstTraceFunctionEntry1( DFRAGMENTATIONPAGINGLOCK_CLEANUP_ENTRY, this );
1.4306 + // in CS
1.4307 + if (iFragmentationMutex)
1.4308 + {
1.4309 + LockFragmentation();
1.4310 + Free(); // at last!
1.4311 + UnlockFragmentation();
1.4312 + Kern::SafeClose((DObject*&)iFragmentationMutex,NULL);
1.4313 + }
1.4314 + OstTraceFunctionExit1( DFRAGMENTATIONPAGINGLOCK_CLEANUP_EXIT, this );
1.4315 + }
1.4316 +
1.4317 +#else
1.4318 +#if !defined(__WINS__)
1.4319 +EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* , TInt , TInt)
1.4320 + {
1.4321 + return KErrNone; // stub for def file
1.4322 + }
1.4323 +#endif // __WINS__
1.4324 +#endif //__DEMAND_PAGING__
1.4325 +/********************************************
1.4326 + * Media driver base class
1.4327 + ********************************************/
1.4328 +
1.4329 +
1.4330 +
1.4331 +
1.4332 +/**
1.4333 +Constructor.
1.4334 +
1.4335 +This is called, typically, by a derived class constructor in its ctor list.
1.4336 +
1.4337 +@param aMediaId The value of the unique media ID assigned when the media
1.4338 + driver is registered.
1.4339 +
1.4340 +@see LocDrv::RegisterMediaDevice()
1.4341 +*/
1.4342 +EXPORT_C DMediaDriver::DMediaDriver(TInt aMediaId)
1.4343 + {
1.4344 + OstTraceFunctionEntryExt( DMEDIADRIVER_DMEDIADRIVER_ENTRY, this );
1.4345 +
1.4346 +// iPhysicalDevice=NULL;
1.4347 +// iTotalSizeInBytes=0;
1.4348 +// iCurrentConsumption=0;
1.4349 +// iPrimaryMedia=NULL;
1.4350 +// iCritical=EFalse;
1.4351 + iPrimaryMedia=(DPrimaryMediaBase*)TheMedia[aMediaId];
1.4352 + OstTraceFunctionExit1( DMEDIADRIVER_DMEDIADRIVER_EXIT, this );
1.4353 + }
1.4354 +
1.4355 +
1.4356 +
1.4357 +
1.4358 +/**
1.4359 +Destructor.
1.4360 +
1.4361 +Sets the device's current consumption to zero, and calls Close() on
1.4362 +the PDD factory object.
1.4363 +
1.4364 +@see DObject::Close()
1.4365 +*/
1.4366 +EXPORT_C DMediaDriver::~DMediaDriver()
1.4367 + {
1.4368 + OstTraceFunctionEntry1( DMEDIADRIVER_DMEDIADRIVER_DESTRUCTOR_ENTRY, this );
1.4369 + SetCurrentConsumption(0);
1.4370 + Kern::SafeClose((DObject*&)iPhysicalDevice,NULL);
1.4371 + OstTraceFunctionExit1( DMEDIADRIVER_DMEDIADRIVER_DESTRUCTOR_EXIT, this );
1.4372 + }
1.4373 +
1.4374 +
1.4375 +
1.4376 +
1.4377 +/**
1.4378 +Closes the media driver.
1.4379 +
1.4380 +This default implementation simply deletes this DMediaDriver object.
1.4381 +
1.4382 +Media drivers can provide their own implementation, which gives them
1.4383 +the opportunity to clean up resources before closure; for example,
1.4384 +cancelling a DFC.
1.4385 +Any replacement function must call this base class function as
1.4386 +the last instruction.
1.4387 +*/
1.4388 +EXPORT_C void DMediaDriver::Close()
1.4389 + {
1.4390 + delete this;
1.4391 + }
1.4392 +
1.4393 +
1.4394 +
1.4395 +
1.4396 +/**
1.4397 +Sets the total size of the media device.
1.4398 +
1.4399 +The function must be called by the media driver's implementation of PartitionInfo().
1.4400 +
1.4401 +@param aTotalSizeInBytes The total size of the media, in bytes.
1.4402 +@param aLocDrv This is not used by media drivers; the class
1.4403 + definition provides a default value.
1.4404 +
1.4405 +@see DMediaDriver::PartitionInfo()
1.4406 +*/
1.4407 +EXPORT_C void DMediaDriver::SetTotalSizeInBytes(Int64 aTotalSizeInBytes, TLocDrv* aLocDrv)
1.4408 + {
1.4409 + OstTraceFunctionEntry1( DMEDIADRIVER_SETTOTALSIZEINBYTES_ENTRY, this );
1.4410 + iTotalSizeInBytes=aTotalSizeInBytes;
1.4411 + if (aLocDrv)
1.4412 + aLocDrv->iPartitionLen=aTotalSizeInBytes;
1.4413 + OstTraceFunctionExit1( DMEDIADRIVER_SETTOTALSIZEINBYTES_EXIT, this );
1.4414 + }
1.4415 +
1.4416 +
1.4417 +
1.4418 +
1.4419 +/**
1.4420 +Gets the total size of the media.
1.4421 +
1.4422 +@return The total size of the media, in bytes.
1.4423 +
1.4424 +@see DMediaDriver::SetTotalSizeInBytes()
1.4425 +*/
1.4426 +EXPORT_C Int64 DMediaDriver::TotalSizeInBytes()
1.4427 + {
1.4428 + return iTotalSizeInBytes;
1.4429 + }
1.4430 +
1.4431 +
1.4432 +
1.4433 +
1.4434 +/**
1.4435 +Flags the media driver as entering a critical part of its processing.
1.4436 +
1.4437 +In this context, critical means that the driver must be allowed to complete
1.4438 +its current activity.
1.4439 +For example, a request to power down the device must be deferred until
1.4440 +the driver exits the critical part.
1.4441 +
1.4442 +@return KErrNone, if the driver has been successfully flagged as being in
1.4443 + a critical part; otherwise, one of the other system-wide error codes.
1.4444 +
1.4445 +@see DMediaDriver::EndInCritical()
1.4446 +*/
1.4447 +EXPORT_C TInt DMediaDriver::InCritical()
1.4448 + {
1.4449 + OstTraceFunctionEntry1( DMEDIADRIVER_INCRITICAL_ENTRY, this );
1.4450 + if (!iCritical)
1.4451 + {
1.4452 + TInt r=iPrimaryMedia->InCritical();
1.4453 + if (r!=KErrNone)
1.4454 + {
1.4455 + OstTraceFunctionExitExt( DMEDIADRIVER_INCRITICAL_EXIT, this, r );
1.4456 + return r;
1.4457 + }
1.4458 + iCritical=ETrue;
1.4459 + }
1.4460 + OstTraceFunctionExitExt( DMEDIADRIVER_INCRITICAL_EXIT2, this, KErrNone );
1.4461 + return KErrNone;
1.4462 + }
1.4463 +
1.4464 +
1.4465 +
1.4466 +
1.4467 +/**
1.4468 +Flags the media driver as leaving a critical part of its processing.
1.4469 +
1.4470 +@see DMediaDriver::InCritical()
1.4471 +*/
1.4472 +EXPORT_C void DMediaDriver::EndInCritical()
1.4473 + {
1.4474 + OstTraceFunctionEntry1( DMEDIADRIVER_ENDINCRITICAL_ENTRY, this );
1.4475 + if (iCritical)
1.4476 + {
1.4477 + iCritical=EFalse;
1.4478 + iPrimaryMedia->EndInCritical();
1.4479 + }
1.4480 + OstTraceFunctionExit1( DMEDIADRIVER_ENDINCRITICAL_EXIT, this );
1.4481 + }
1.4482 +
1.4483 +
1.4484 +
1.4485 +
1.4486 +/**
1.4487 +@internalComponent
1.4488 +*/
1.4489 +EXPORT_C void DMediaDriver::SetCurrentConsumption(TInt aValue)
1.4490 + {
1.4491 + OstTraceFunctionEntryExt( DMEDIADRIVER_SETCURRENTCONSUMPTION_ENTRY, this );
1.4492 + TInt old = (TInt)__e32_atomic_swp_ord32(&iCurrentConsumption, aValue);
1.4493 + TInt delta = aValue - old;
1.4494 + iPrimaryMedia->DeltaCurrentConsumption(delta);
1.4495 + OstTraceFunctionExit1( DMEDIADRIVER_SETCURRENTCONSUMPTION_EXIT, this );
1.4496 + }
1.4497 +
1.4498 +
1.4499 +
1.4500 +
1.4501 +/**
1.4502 +Informs the media driver subsystem that an asynchronous request is complete.
1.4503 +
1.4504 +@param m The request that this call is completing.
1.4505 +@param aResult The return code for the asynchronous request. Typically, this
1.4506 + is KErrNone to report success, or one of the other system-wide
1.4507 + error codes to report failure or other problems.
1.4508 +*/
1.4509 +EXPORT_C void DMediaDriver::Complete(TLocDrvRequest& m, TInt aResult)
1.4510 + {
1.4511 + OstTraceExt2( TRACE_FLOW, DMEDIADRIVER_COMPLETE_ENTRY, "m=%x;aResult=%d", (TUint) &m, aResult );
1.4512 + CHECK_RET(aResult);
1.4513 +#ifdef __DEMAND_PAGING__
1.4514 + if (DMediaPagingDevice::PagingRequest(m))
1.4515 + {
1.4516 + __ASSERT_ALWAYS(iPrimaryMedia && iPrimaryMedia->iPagingMedia && iPrimaryMedia->iBody->iPagingDevice,LOCM_FAULT());
1.4517 + __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
1.4518 + DMediaPagingDevice* pagingdevice = iPrimaryMedia->iBody->iPagingDevice;
1.4519 + pagingdevice->CompleteRequest(&m, aResult);
1.4520 + }
1.4521 + else
1.4522 +#endif
1.4523 + iPrimaryMedia->CompleteRequest(m, aResult);
1.4524 +
1.4525 + if (&m == iPrimaryMedia->iCurrentReq) // Complete() called on request serviced synchronously
1.4526 + iPrimaryMedia->iCurrentReq = NULL;
1.4527 +
1.4528 + iPrimaryMedia->RunDeferred();
1.4529 + OstTraceFunctionExit1( DMEDIADRIVER_COMPLETE_EXIT, this );
1.4530 + }
1.4531 +
1.4532 +
1.4533 +
1.4534 +
1.4535 +/**
1.4536 +Informs the media driver subsystem that the media driver is open
1.4537 +and has been initialised.
1.4538 +
1.4539 +This can be called from the PDD factory function Create(), if opening and
1.4540 +initialising the media driver is synchronous, otherwise it should be called by
1.4541 +the asynchronous media driver function that is responsible for opening and
1.4542 +initialising the driver.
1.4543 +
1.4544 +@param anError KErrNone if successful, otherwise one of the other system wide
1.4545 + error codes.
1.4546 +*/
1.4547 +EXPORT_C void DMediaDriver::OpenMediaDriverComplete(TInt anError)
1.4548 + {
1.4549 + OstTraceFunctionEntry1( DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE_ENTRY, this );
1.4550 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DMediaDriver::OpenMediaDriverComplete(%d) this %x iPrimaryMedia %x", anError, this, iPrimaryMedia));
1.4551 + OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE, "anError %d this 0x%x iPrimaryMedia 0x%x", anError, (TUint) this, (TUint) iPrimaryMedia);
1.4552 + DPrimaryMediaBase* pM=iPrimaryMedia;
1.4553 + pM->iAsyncErrorCode=anError;
1.4554 + pM->iAsyncDfc.Enque();
1.4555 + OstTraceFunctionExit1( DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE_EXIT, this );
1.4556 + }
1.4557 +
1.4558 +
1.4559 +
1.4560 +
1.4561 +/**
1.4562 +Informs the media driver subsystem that the media driver has completed
1.4563 +the provision of partition information.
1.4564 +
1.4565 +The media driver provides partition information in its implementation
1.4566 +of PartitionInfo().
1.4567 +
1.4568 +@param anError KErrNone if successful, otherwise one of the other system wide
1.4569 + error codes.
1.4570 +
1.4571 +@see DMediaDriver::PartitionInfo()
1.4572 +*/
1.4573 +EXPORT_C void DMediaDriver::PartitionInfoComplete(TInt anError)
1.4574 + {
1.4575 + OstTraceFunctionEntry1( DMEDIADRIVER_PARTITIONINFOCOMPLETE_ENTRY, this );
1.4576 + __KTRACE_OPT(KLOCDRV,Kern::Printf("DMediaDriver::PartitionInfoComplete(%d) anError %d this %x iPrimaryMedia %x", anError, this, iPrimaryMedia));
1.4577 + OstTraceExt3( TRACE_INTERNALS, DMDEDIADRIVER_PARTITIONINFOCOMPLETE, "anError=%d; this=%x; iPrimaryMedia=%x", anError, (TUint) this, (TUint) iPrimaryMedia );
1.4578 + DPrimaryMediaBase* pM=iPrimaryMedia;
1.4579 + pM->iAsyncErrorCode=anError;
1.4580 + pM->iAsyncDfc.Enque();
1.4581 + OstTraceFunctionExit1( DMEDIADRIVER_PARTITIONINFOCOMPLETE_EXIT, this );
1.4582 + }
1.4583 +
1.4584 +
1.4585 +
1.4586 +
1.4587 +/**
1.4588 +@internalComponent
1.4589 +*/
1.4590 +// Default implementation
1.4591 +EXPORT_C void DMediaDriver::Disconnect(DLocalDrive* aLocalDrive, TThreadMessage* aMsg)
1.4592 + {
1.4593 + OstTraceFunctionEntryExt( DMEDIADRIVER_DISCONNECT_ENTRY, this );
1.4594 + // don't need to worry about DLocalDrive going away
1.4595 + aLocalDrive->Deque();
1.4596 +
1.4597 + aMsg->Complete(KErrNone, EFalse);
1.4598 + OstTraceFunctionExit1( DMEDIADRIVER_DISCONNECT_EXIT, this );
1.4599 + }
1.4600 +
1.4601 +
1.4602 +
1.4603 +
1.4604 +/**
1.4605 +Registers a media driver with the Local Media Subsystem, and provides
1.4606 +information about the number of supported drives, partitions,
1.4607 +names and drive numbers.
1.4608 +
1.4609 +@param aDevice The unique Media ID for this device.
1.4610 + This can take one of the enumerated values defined
1.4611 + by the TMediaDevice enum.
1.4612 +@param aDriveCount Specifies the number of local drive objects to be assigned
1.4613 + to the media driver. Drives that support more than one
1.4614 + partition must specify a number greater than 1.
1.4615 +@param aDriveList A pointer to an array of TInt values, which define
1.4616 + the drive numbers that are to be allocated to each partition.
1.4617 + 0 signifies Drive C, 1 signifies drive D, etc. For example,
1.4618 + to allocate drive letters J and K, specify an array
1.4619 + containing the values [7,8].
1.4620 + Note that the size of this array must be the same as the value
1.4621 + specified by aDriveCount.
1.4622 +@param aPrimaryMedia A pointer to the primary DPrimaryMedia object to be
1.4623 + associated with the media. This object is responsible for
1.4624 + the overall state of the media, i.e. powering up, reading
1.4625 + partition information etc. It also has overall control over
1.4626 + all partitions as represented by the additional (aNumMedia-1)
1.4627 + DMedia objects.
1.4628 +@param aNumMedia Specifies the total number of DMedia objects to be
1.4629 + associated with the media driver. This number includes the
1.4630 + primary DPrimaryMedia object referred to by aPrimaryMedia,
1.4631 + plus all of the DMedia objects that are created for each
1.4632 + additional drive, and which hold basic information about
1.4633 + partitions.
1.4634 +@param aName The name of the media driver, for example: PCCard
1.4635 +
1.4636 +@return KErrNone, if successful;
1.4637 + KErrInUse, if a drive is already in use;
1.4638 + KErrNoMemory, if there is insufficient memory;
1.4639 + or one of the other system-wide error codes.
1.4640 +*/
1.4641 +EXPORT_C TInt LocDrv::RegisterMediaDevice(TMediaDevice aDevice, TInt aDriveCount, const TInt* aDriveList, DPrimaryMediaBase* aPrimaryMedia, TInt aNumMedia, const TDesC& aName)
1.4642 + {
1.4643 + OstTraceFunctionEntry0( LOCDRV_REGISTERMEDIADEVICE_ENTRY );
1.4644 + // Create TLocDrv / DMedia objects to handle a media device
1.4645 + __KTRACE_OPT(KBOOT,Kern::Printf("RegisterMediaDevice %lS dev=%1d #drives=%d 1st=%d PM=%08x #media=%d",&aName,aDevice,aDriveCount,*aDriveList,aPrimaryMedia,aNumMedia));
1.4646 + 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 );
1.4647 +
1.4648 + const TInt* p=aDriveList;
1.4649 + TInt i;
1.4650 + TInt r=0;
1.4651 + if (UsedMedia+aNumMedia>KMaxLocalDrives)
1.4652 + {
1.4653 + OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT1, "< KErrInUse");
1.4654 + return KErrInUse;
1.4655 + }
1.4656 + for (i=0; i<aDriveCount; ++i)
1.4657 + {
1.4658 + TInt drv = *p++;
1.4659 + // -1 means not used; this is to enable Dual-slot MMC support
1.4660 + if (drv == -1)
1.4661 + continue;
1.4662 + __KTRACE_OPT(KBOOT,Kern::Printf("Registering drive %d", drv));
1.4663 + OstTrace1( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE2, "Registering drive=%d", drv );
1.4664 + if (TheDrives[drv])
1.4665 + {
1.4666 + __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d already in use", drv));
1.4667 + OstTrace1( TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT2, "< Drive %d already in use; KErrInUse", drv);
1.4668 + return KErrInUse;
1.4669 + }
1.4670 + }
1.4671 + HBuf* pN=HBuf::New(aName);
1.4672 + if (!pN)
1.4673 + {
1.4674 + OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT3, "< KErrNoMemory");
1.4675 + return KErrNoMemory;
1.4676 + }
1.4677 + TInt lastMedia=UsedMedia+aNumMedia-1;
1.4678 + for (i=UsedMedia; i<=lastMedia; ++i)
1.4679 + {
1.4680 + if (i==UsedMedia)
1.4681 + TheMedia[i]=aPrimaryMedia;
1.4682 + else
1.4683 + TheMedia[i]=new DMedia;
1.4684 + if (!TheMedia[i])
1.4685 + {
1.4686 + OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT4, "< KErrNoMemory");
1.4687 + return KErrNoMemory;
1.4688 + }
1.4689 + r=TheMedia[i]->Create(aDevice,i,lastMedia);
1.4690 + __KTRACE_OPT(KBOOT,Kern::Printf("Media %d Create() returns %d",i,r));
1.4691 + OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE3, "Media=%d Create(); retval=%d", i, r );
1.4692 + if (r!=KErrNone)
1.4693 + {
1.4694 + OstTrace1(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT5, "< retval=%d", r);
1.4695 + return r;
1.4696 + }
1.4697 + }
1.4698 +
1.4699 + __KTRACE_OPT(KBOOT,Kern::Printf("FirstMedia %d LastMedia %d",UsedMedia,lastMedia));
1.4700 + OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE4, "FirstMedia=%d; LastMedia=%d", UsedMedia, lastMedia );
1.4701 + UsedMedia+=aNumMedia;
1.4702 + p=aDriveList;
1.4703 + for (i=0; i<aDriveCount; ++i)
1.4704 + {
1.4705 + TInt drv=*p++;
1.4706 + if (drv == -1)
1.4707 + continue;
1.4708 + TLocDrv* pL=new TLocDrv(drv);
1.4709 + if (!pL)
1.4710 + {
1.4711 + OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT6, "< KErrNoMemory");
1.4712 + return KErrNoMemory;
1.4713 + }
1.4714 + TheDrives[drv]=pL;
1.4715 + DriveNames[drv]=pN;
1.4716 + pL->iPrimaryMedia=aPrimaryMedia;
1.4717 + __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pL));
1.4718 + OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE5, "Drive=%d; TLocDrv 0x%08x;", (TInt) drv, (TUint) pL );
1.4719 + }
1.4720 +
1.4721 + OstTraceFunctionExit0( LOCDRV_REGISTERMEDIADEVICE_EXIT7 );
1.4722 + return KErrNone;
1.4723 + }
1.4724 +
1.4725 +
1.4726 +
1.4727 +
1.4728 +/**
1.4729 +A utility function that is used internally to register the specified
1.4730 +password store.
1.4731 +
1.4732 +The password store is used to save passwords for local media.
1.4733 +
1.4734 +@param aStore A pointer to the password store to be registered.
1.4735 +
1.4736 +@return KErrNone, if successful;
1.4737 + KErrAlreadyExists, if a password store has already been registered.
1.4738 +*/
1.4739 +EXPORT_C TInt LocDrv::RegisterPasswordStore(TPasswordStore* aStore)
1.4740 + {
1.4741 + OstTraceFunctionEntry0( LOCDRV_REGISTERPASSWORDSTORE_ENTRY );
1.4742 + // Create TLocDrv / DMedia objects to handle a media device
1.4743 + __KTRACE_OPT(KBOOT,Kern::Printf("RegisterPasswordStore"));
1.4744 +
1.4745 + TInt r = KErrNone;
1.4746 +
1.4747 + if(ThePasswordStore == NULL)
1.4748 + ThePasswordStore = aStore;
1.4749 + else
1.4750 + r = KErrAlreadyExists;
1.4751 + OstTrace1(TRACE_INTERNALS, LOCDRV_REGISTERPASSWORDSTORE, "retval=%d", r);
1.4752 + OstTraceFunctionExit0( LOCDRV_REGISTERPASSWORDSTORE_EXIT );
1.4753 + return r;
1.4754 + }
1.4755 +
1.4756 +/**
1.4757 +Returns a pointer to the registered password store.
1.4758 +
1.4759 +The password store is used to save passwords for local media.
1.4760 +
1.4761 +@return A pointer to the registered password store.
1.4762 +*/
1.4763 +EXPORT_C TPasswordStore* LocDrv::PasswordStore()
1.4764 + {
1.4765 + return ThePasswordStore;
1.4766 + }
1.4767 +
1.4768 +#ifdef __DEMAND_PAGING__
1.4769 +/**
1.4770 +Registers a paging device with the Local Media Subsystem, and provides
1.4771 +information about drive numbers used in Code Paging.
1.4772 +
1.4773 +@param aPrimaryMedia A pointer to the primary DPrimaryMedia object associated
1.4774 + with the media.
1.4775 +@param aPagingDriveList A pointer to an array of TInt values, which define
1.4776 + the drive numbers used as Code backup in Code Paging, which
1.4777 + are the target of Page In requests. For NAND these will
1.4778 + will be usually associated with ROFS and/or User Data drives.
1.4779 + In ROM pagigng systems no drive is specified, it is assumed
1.4780 + a fixed media for which no non-primary media exists, will be
1.4781 + used.
1.4782 +@param aDriveCount Specifies the number of local drives associated with this
1.4783 + media device which can be used for code paging.
1.4784 +@param aPagingType Identifies the type of Paging this media device is capable
1.4785 + of servicing.
1.4786 +@param aReadShift Log2 of the read unit size. A read unit is the number of bytes
1.4787 + which the device can optimally read from the underlying media.
1.4788 + E.g. for small block NAND, a read unit would be equal to the
1.4789 + page size, 512 bytes, therefore iReadShift would be set to 9.
1.4790 +@param aNumPages The number of pages to alloc for each drive associated with this
1.4791 + media driver. The pages are used in request fragmentation.
1.4792 +
1.4793 +@return KErrNone, if successful;
1.4794 + KErrNotFound, if at least one of the drive numbers
1.4795 + specified has not yet been mapped.
1.4796 + KErrArgument, if the passed in an invalid argument.
1.4797 + KErrNotSupported, if at least one of the drive numbers
1.4798 + specifed is not associated with this Primary Media.
1.4799 + KErrNoMemory, if there is insufficient memory;
1.4800 + or one of the other system-wide error codes.
1.4801 +*/
1.4802 +EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* aPrimaryMedia, const TInt* aPagingDriveList, TInt aDriveCount, TUint aPagingType, TInt aReadShift, TUint aNumPages)
1.4803 + {
1.4804 + OstTraceFunctionEntry0( LOCDRV_REGISTERPAGINGDEVICE_ENTRY );
1.4805 +
1.4806 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf(">RegisterPagingDevice: paging type=%d PM=0x%x read shift=%d",aPagingType,aPrimaryMedia,aReadShift));
1.4807 + OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE1, "aPagingType=%d; aPrimaryMedia=0x%x; aReadShift=%d", (TInt) aPagingType, (TUint) aPrimaryMedia, (TInt) aReadShift);
1.4808 +
1.4809 + TInt i;
1.4810 +
1.4811 + if(!aPagingType || (aPagingType&~(DPagingDevice::ERom | DPagingDevice::ECode | DPagingDevice::EData)))
1.4812 + {
1.4813 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Unsupported paging type, exiting"));
1.4814 + OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT1, "< Unsupported paging type; KErrArgument");
1.4815 + return KErrArgument;
1.4816 + }
1.4817 +
1.4818 +
1.4819 +
1.4820 + for(i=0; i<KMaxLocalDrives; i++)
1.4821 + {
1.4822 + if (ThePagingDevices[i] == NULL)
1.4823 + continue;
1.4824 + if ((ThePagingDevices[i]->iType&DPagingDevice::ERom) && (aPagingType & DPagingDevice::ERom))
1.4825 + {
1.4826 + aPagingType&=~DPagingDevice::ERom; // already have a ROM paging device
1.4827 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has ROM pager on locdrv no %d",i));
1.4828 + }
1.4829 + if ((ThePagingDevices[i]->iType&DPagingDevice::EData) && (aPagingType & DPagingDevice::EData))
1.4830 + {
1.4831 + aPagingType&=~DPagingDevice::EData; // already have a Data paging device
1.4832 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has Data pager on locdrv no %d",i));
1.4833 + }
1.4834 + }
1.4835 +
1.4836 +
1.4837 + if (aPagingType == 0)
1.4838 + {
1.4839 + // there's already a ROM or Data paging device & this doesn't support code paging so quietly exit without further addo
1.4840 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Nothing left to register on locdrv no %d, exiting",i));
1.4841 + OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT2, "< Nothing left to register on locdrv no %d; KErrNone",i);
1.4842 + return KErrNone;
1.4843 + }
1.4844 +
1.4845 + const TInt* p=aPagingDriveList;
1.4846 + if(aPagingType&DPagingDevice::ECode) // supports code paging, do argument check
1.4847 + {
1.4848 + if(!aDriveCount || (aDriveCount>=KMaxLocalDrives))
1.4849 + {
1.4850 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive count: %d", aDriveCount));
1.4851 + OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT3, "< Invalid code paging drive count=%d; KErrArgument", aDriveCount);
1.4852 + return KErrArgument;
1.4853 + }
1.4854 +
1.4855 + TInt drvCount=0;
1.4856 + for(i=0; i<KMaxLocalDrives; i++)
1.4857 + if(TheDrives[i] && TheDrives[i]->iPrimaryMedia==aPrimaryMedia)
1.4858 + drvCount++;
1.4859 + if(aDriveCount>drvCount) // can't exceed number of drives registered by this device
1.4860 + {
1.4861 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive count=%d; total=%d", aDriveCount, drvCount));
1.4862 + OstTraceExt2(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT4, "< Invalid code paging drive count=%d; total=%d; KErrArgument", aDriveCount, drvCount);
1.4863 + return KErrArgument;
1.4864 + }
1.4865 +
1.4866 + for (i=0; i<aDriveCount; ++i)
1.4867 + {
1.4868 + __KTRACE_OPT(KBOOT,Kern::Printf("RegisterPagingDevice: registering drive=%d ",*p));
1.4869 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE2, "Registering Drive=%d", *p );
1.4870 + TInt drv=*p++;
1.4871 + if(drv>=KMaxLocalDrives)
1.4872 + {
1.4873 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive number: %d", drv));
1.4874 + OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT5, "< Invalid code paging drive number=%d; KErrArgument", drv);
1.4875 + return KErrArgument;
1.4876 + }
1.4877 + TLocDrv* pD=TheDrives[drv];
1.4878 + if (!pD)
1.4879 + {
1.4880 + OstTrace0(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT6, "< KErrNotFound");
1.4881 + return KErrNotFound;
1.4882 + }
1.4883 + if (pD->iPrimaryMedia!=aPrimaryMedia)
1.4884 + {
1.4885 + OstTrace0(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT7, "< KErrNotSupported");
1.4886 + return KErrNotSupported;
1.4887 + }
1.4888 + }
1.4889 + }
1.4890 +
1.4891 +
1.4892 + TInt firstLocalDriveNumber = KErrNotFound;
1.4893 + TInt romPagingDriveNumber = KErrNotFound;
1.4894 +
1.4895 + TInt dataPagingDriveNumber = KErrNotFound;
1.4896 + TInt swapSize = 0;
1.4897 +
1.4898 + // find the local drive assocated with the primary media
1.4899 + for (i=0; i<KMaxLocalDrives; ++i)
1.4900 + {
1.4901 + if(TheDrives[i] && TheDrives[i]->iPrimaryMedia == aPrimaryMedia)
1.4902 + {
1.4903 + firstLocalDriveNumber = i;
1.4904 + break;
1.4905 + }
1.4906 + }
1.4907 + __ASSERT_ALWAYS(i < KMaxLocalDrives, LOCM_FAULT());
1.4908 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("DMediaPagingDevice(), firstLocalDriveNumber %d", firstLocalDriveNumber));
1.4909 + OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE3, "firstLocalDriveNumber=%d", firstLocalDriveNumber );
1.4910 +
1.4911 + // Send an ECaps message to wake up the media driver & ensure all partitions are
1.4912 + // reported, then search for paged-data or paged-ROM partitions
1.4913 + if ((aPagingType & DPagingDevice::EData) ||
1.4914 + (aPagingType & DPagingDevice::ERom && aPrimaryMedia->iDfcQ && aPrimaryMedia->iMsgQ.iReady))
1.4915 + {
1.4916 + // the message queue must have been started already (by the media driver calling iMsgQ.Receive())
1.4917 + // otherwise we can't send the DLocalDrive::EQueryDevice request
1.4918 + if (aPrimaryMedia->iDfcQ && !aPrimaryMedia->iMsgQ.iReady)
1.4919 + {
1.4920 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Message queue not started"));
1.4921 + OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT8, "< RegisterPagingDevice: Message queue not started; KErrNotReady");
1.4922 + return KErrNotReady;
1.4923 + }
1.4924 +
1.4925 +
1.4926 + TLocDrvRequest m;
1.4927 + memclr(&m, sizeof(m));
1.4928 +
1.4929 +
1.4930 + // Get the Caps from the device. NB for MMC/SD we may need to retry as some PSLs start up
1.4931 + // in "door open" or "media not present" state which can result in the cancellation of requests
1.4932 + TInt i;
1.4933 + const TInt KRetries = 5;
1.4934 + TInt r = KErrNotReady;
1.4935 + for (i=0; r == KErrNotReady && i < KRetries; i++)
1.4936 + {
1.4937 + TBuf8<KMaxLocalDriveCapsLength> capsBuf;
1.4938 + capsBuf.SetMax();
1.4939 + capsBuf.FillZ();
1.4940 + m.Drive() = TheDrives[firstLocalDriveNumber];
1.4941 + m.Id() = DLocalDrive::ECaps;
1.4942 + m.RemoteDes() = (TAny*)capsBuf.Ptr(); // overload this
1.4943 + m.Length() = KMaxLocalDriveCapsLength; // for pinning
1.4944 + r = aPrimaryMedia->Request(m);
1.4945 +
1.4946 +//Kern::Printf("EQueryPageDeviceInfo: i %d: r %d ", i, r);
1.4947 + __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Paging device ECaps: i %d: r %d ", i, r));
1.4948 + OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE4, "Paging device ECaps: i %d retval=%d", i, r);
1.4949 + }
1.4950 +
1.4951 + if (r != KErrNone)
1.4952 + {
1.4953 + OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< retval=%d",r);
1.4954 + return r;
1.4955 + }
1.4956 +
1.4957 + TLocDrv* drive;
1.4958 + for (i=0; i<KMaxLocalDrives; ++i)
1.4959 + {
1.4960 + drive = TheDrives[i];
1.4961 + if(drive && drive->iPrimaryMedia == aPrimaryMedia)
1.4962 + {
1.4963 + __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("RegisterPagingDevice: local drive %d, partition type %x size %x", i, drive->iPartitionType, I64LOW(drive->iPartitionLen)));
1.4964 + // ROM partition ?
1.4965 + if ((romPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypeROM))
1.4966 + {
1.4967 + __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found ROM partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
1.4968 + 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));
1.4969 + romPagingDriveNumber = i;
1.4970 + }
1.4971 + // swap partition ?
1.4972 + else if ((dataPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypePagedData))
1.4973 + {
1.4974 + __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found swap partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
1.4975 + 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) );
1.4976 + dataPagingDriveNumber = i;
1.4977 + swapSize = drive->iPartitionLen >> aReadShift;
1.4978 + }
1.4979 + }
1.4980 + }
1.4981 +
1.4982 + if (swapSize == 0)
1.4983 + {
1.4984 + __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Disabling data paging"));
1.4985 + OstTraceDef0(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE7, "Disabling data paging");
1.4986 + aPagingType &= ~DPagingDevice::EData;
1.4987 + }
1.4988 +
1.4989 + }
1.4990 +
1.4991 +
1.4992 + // create and set up a DPagingDevice to allow PageIn request servicing
1.4993 + DMediaPagingDevice* pagingDevice = new DMediaPagingDevice(aPrimaryMedia);
1.4994 + if(!pagingDevice)
1.4995 + {
1.4996 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create paging device"));
1.4997 + OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT_EXIT10, "< RegisterPagingDevice: could not create paging device; KErrNoMemory");
1.4998 + return KErrNoMemory;
1.4999 + }
1.5000 +
1.5001 + pagingDevice->iType = aPagingType;
1.5002 + pagingDevice->iReadUnitShift = aReadShift;
1.5003 +
1.5004 + pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber;
1.5005 + pagingDevice->iRomPagingDriveNumber = romPagingDriveNumber;
1.5006 +
1.5007 + pagingDevice->iDataPagingDriveNumber = dataPagingDriveNumber;
1.5008 + pagingDevice->iSwapSize = swapSize;
1.5009 +
1.5010 +#ifdef __DEBUG_DEMAND_PAGING__
1.5011 + Kern::Printf("PagingDevice :");
1.5012 + Kern::Printf("iType 0x%x\n", pagingDevice->iType);
1.5013 + Kern::Printf("iReadUnitShift 0x%x\n", pagingDevice->iReadUnitShift);
1.5014 + Kern::Printf("iFirstLocalDriveNumber 0x%x\n", pagingDevice->iFirstLocalDriveNumber);
1.5015 + Kern::Printf("iRomPagingDriveNumber 0x%x\n", pagingDevice->iRomPagingDriveNumber);
1.5016 + Kern::Printf("iDataPagingDriveNumber 0x%x\n", pagingDevice->iDataPagingDriveNumber);
1.5017 + Kern::Printf("iSwapSize 0x%x\n", pagingDevice->iSwapSize);
1.5018 + #endif
1.5019 +
1.5020 +
1.5021 + // This table is indexed by DPagingDevice::TType
1.5022 + const char* DeviceName[] =
1.5023 + {
1.5024 + "Error",
1.5025 + "RomPagingDevice",
1.5026 + "CodePagingDevice",
1.5027 + "RomAndCodePagingDevice",
1.5028 + "DataPagingDevice",
1.5029 + "RomAndDataPagingDevice",
1.5030 + "CodeAndDataPagingDevice",
1.5031 + "RomAndCodeAndDataPagingDevice"
1.5032 + };
1.5033 +
1.5034 +
1.5035 + if(aPagingType & DPagingDevice::ECode)
1.5036 + {
1.5037 + for (i=0; i<aDriveCount; ++i)
1.5038 + pagingDevice->iDrivesSupported|=(0x1<<aPagingDriveList[i]);
1.5039 + }
1.5040 + pagingDevice->iName = DeviceName[aPagingType];
1.5041 +
1.5042 + if (ThePinObjectAllocator == NULL)
1.5043 + ThePinObjectAllocator = new DPinObjectAllocator();
1.5044 + if(!ThePinObjectAllocator)
1.5045 + {
1.5046 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator"));
1.5047 + OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory");
1.5048 + return KErrNoMemory;
1.5049 + }
1.5050 + TInt r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages);
1.5051 + if (r != KErrNone)
1.5052 + {
1.5053 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not construct ThePinObjectAllocator"));
1.5054 + OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT12, "< RegisterPagingDevice: could not construct ThePinObjectAllocator; retval=%d",r);
1.5055 + return r;
1.5056 + }
1.5057 +
1.5058 +
1.5059 + // Register our DPagingDevice with the Kernel
1.5060 + r=Kern::InstallPagingDevice(pagingDevice);
1.5061 +
1.5062 +#ifdef __DEBUG_DEMAND_PAGING__
1.5063 + Kern::Printf("Kern::InstallPagingDevice() r %d", r);
1.5064 +#endif
1.5065 +
1.5066 + if (r!=KErrNone)
1.5067 + {
1.5068 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not install paging device"));
1.5069 + OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT13, "< RegisterPagingDevice: could not install paging device; retval=%d", r);
1.5070 + delete pagingDevice;
1.5071 + return r;
1.5072 + }
1.5073 +
1.5074 + // all hunky dory, save paging device and mark our media as pageable
1.5075 + ThePagingDevices[aPrimaryMedia->iMediaId] = pagingDevice; // association created between PrimaryMedia and PagingDevice via iMediaId
1.5076 + aPrimaryMedia->iPagingMedia = 1;
1.5077 +
1.5078 + // mark our drives as pageable
1.5079 + p=aPagingDriveList;
1.5080 + if (aPagingType&DPagingDevice::ECode)
1.5081 + {
1.5082 + for (i=0; i<aDriveCount; ++i)
1.5083 + {
1.5084 + TLocDrv* pD=TheDrives[*p++];
1.5085 + pD->iPagingDrv=1;
1.5086 + }
1.5087 + }
1.5088 +
1.5089 + // Flags to indicate that a paging device is registered and pinning of user requests may be required
1.5090 + aPrimaryMedia->iPagingMedia = 1;
1.5091 +
1.5092 + // point the primary media to the paging device
1.5093 + aPrimaryMedia->iBody->iPagingDevice = pagingDevice;
1.5094 +
1.5095 + if (aPagingType & DPagingDevice::ERom)
1.5096 + {
1.5097 + aPrimaryMedia->iRomPagingMedia = 1;
1.5098 + TheRomPagingMedia = aPrimaryMedia;
1.5099 + }
1.5100 +
1.5101 + // Is data paging enabled in this ROM ?
1.5102 + TInt memModelAttributes = Kern::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
1.5103 + TBool dataPagingSupported = memModelAttributes & EMemModelAttrDataPaging;
1.5104 +#ifdef __DEBUG_DEMAND_PAGING__
1.5105 + Kern::Printf("memModelAttributes %08X", memModelAttributes);
1.5106 + Kern::Printf("DataPagingSupported %d", dataPagingSupported);
1.5107 +#endif
1.5108 + if (!dataPagingSupported)
1.5109 + {
1.5110 +#ifdef __DEBUG_DEMAND_PAGING__
1.5111 + if (aPagingType & DPagingDevice::EData)
1.5112 + {
1.5113 + Kern::Printf("Disabling data paging, not supported in this ROM");
1.5114 + }
1.5115 +#endif
1.5116 + aPagingType&= ~DPagingDevice::EData;
1.5117 + }
1.5118 +
1.5119 +
1.5120 + if (aPagingType & DPagingDevice::EData)
1.5121 + {
1.5122 + DataPagingDeviceRegistered = ETrue;
1.5123 + aPrimaryMedia->iDataPagingMedia = 1;
1.5124 + TheDataPagingMedia = aPrimaryMedia;
1.5125 + }
1.5126 +
1.5127 + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("< RegisterPagingDevice"));
1.5128 + OstTraceFunctionExit0( LOCDRV_REGISTERPAGINGDEVICE_EXIT14 );
1.5129 + return KErrNone;
1.5130 + }
1.5131 +
1.5132 +#else //__DEMAND_PAGING__
1.5133 +
1.5134 +#if !defined(__WINS__)
1.5135 +EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* , const TInt* , TInt , TUint , TInt , TUint )
1.5136 + {
1.5137 + return KErrNotSupported;
1.5138 + } // stub for def file
1.5139 +#endif // __WINS__
1.5140 +
1.5141 +#endif //__DEMAND_PAGING__
1.5142 +
1.5143 +
1.5144 +/**
1.5145 +Registers a media device with physical memory addressing capabilities with the
1.5146 +Local Media Subsystem.
1.5147 +
1.5148 +@param aPrimaryMedia A pointer to the primary DPrimaryMedia object associated
1.5149 + with the media device.
1.5150 +@param aMediaBlockSize The Minimum transfer size (bytes) for the media device.
1.5151 +@param aDmaMaxAddressable The Maximum Addressing Range for the media device's DMA controller, 0 if None.
1.5152 +@param aDmaAlignment The required memory alignment for the media device's DMA controller.
1.5153 +
1.5154 +@return KErrNone, Always;
1.5155 +*/
1.5156 +EXPORT_C TInt LocDrv::RegisterDmaDevice(DPrimaryMediaBase* aPrimaryMedia,
1.5157 + TInt aMediaBlockSize, // Minimum transfer size (bytes) for the media
1.5158 + TInt aDmaMaxAddressable, // Max Addressing Range for DMA controller, 0 if None.
1.5159 + TInt aDmaAlignment) // DMA Alignment e.g. word alignment required = 2
1.5160 + {
1.5161 + OstTraceFunctionEntry0( LOCDRV_REGISTERDMADEVICE_ENTRY );
1.5162 +
1.5163 + __KTRACE_OPT(KBOOT ,Kern::Printf("RegisterPhysicalAddrDevice: PM=0x%x BS=%d MaxAddr=%d DMA=%d",
1.5164 + aPrimaryMedia, aMediaBlockSize, aDmaMaxAddressable, aDmaAlignment));
1.5165 + OstTraceExt4( TRACE_INTERNALS, LOCDRV_REGISTERDMADEVICE, "aPrimaryMedia=0x%x; aMediaBlockSize=%d; aDmaMaxAddressable=%d; aDmaAlignment=%d", (TUint) aPrimaryMedia, (TInt) aMediaBlockSize, (TInt) aDmaMaxAddressable, (TInt) aDmaAlignment );
1.5166 +
1.5167 + for (TInt i=0; i<KMaxLocalDrives; ++i)
1.5168 + {
1.5169 + TLocDrv* pL=TheDrives[i];
1.5170 + if (pL && pL->iPrimaryMedia == aPrimaryMedia && pL->iDmaHelper == NULL)
1.5171 + {
1.5172 + pL->iDmaHelper = new DDmaHelper;
1.5173 + __ASSERT_ALWAYS(pL != NULL, LOCM_FAULT());
1.5174 +
1.5175 + // if no limit stated on addressing range use 1MB
1.5176 + TInt MaxAddress = aDmaMaxAddressable ? (1024*1024) : aDmaMaxAddressable;
1.5177 +
1.5178 + TInt r = pL->iDmaHelper->Construct(MaxAddress, aMediaBlockSize, aDmaAlignment);
1.5179 + __ASSERT_ALWAYS(r == KErrNone, LOCM_FAULT());
1.5180 + }
1.5181 + }
1.5182 +
1.5183 + OstTraceFunctionExit0( LOCDRV_REGISTERDMADEVICE_EXIT );
1.5184 + return KErrNone;
1.5185 + }
1.5186 +
1.5187 +void GetDriveInfo(TDriveInfoV1& info)
1.5188 + {
1.5189 + OstTraceFunctionEntry1( GETDRIVEINFO_ENTRY, ( TUint )&( info ) );
1.5190 + TInt i;
1.5191 + TInt drives=0;
1.5192 + TUint32 sock_mask=0;
1.5193 + TInt sockets=0;
1.5194 +
1.5195 + info.iRegisteredDriveBitmask = 0;
1.5196 +
1.5197 + for (i=0; i<KMaxPBusSockets; ++i)
1.5198 + info.iSocketName[i].Zero();
1.5199 + for (i=0; i<KMaxLocalDrives; ++i)
1.5200 + {
1.5201 + TLocDrv* pL=TheDrives[i];
1.5202 + if (pL)
1.5203 + {
1.5204 + ++drives;
1.5205 + TInt sockNum;
1.5206 + DPrimaryMediaBase* pM=pL->iPrimaryMedia;
1.5207 + if (pM->IsRemovableDevice(sockNum))
1.5208 + {
1.5209 + if (!(sock_mask & (1<<sockNum)))
1.5210 + {
1.5211 + info.iSocketName[sockNum]=*DriveNames[i];
1.5212 + __KTRACE_OPT(KLOCDRV,Kern::Printf("Socket %d device %d name %lS", sockNum, pM->iDevice, DriveNames[i]));
1.5213 + OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO1, "Socket=%d; device=%d", sockNum, (TUint) pM->iDevice );
1.5214 + if ( (sockNum + 1) > sockets )
1.5215 + sockets = sockNum + 1;
1.5216 + }
1.5217 + sock_mask |= (1<<sockNum);
1.5218 + }
1.5219 + info.iDriveName[i]=*DriveNames[i];
1.5220 + __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d device %d name %lS",i,pM->iDevice,DriveNames[i]));
1.5221 + OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO2, "Drive=%d; device=%d", i, (TUint) pM->iDevice );
1.5222 +
1.5223 + info.iRegisteredDriveBitmask |= (0x01 << i);
1.5224 + }
1.5225 + }
1.5226 + info.iTotalSupportedDrives=drives;
1.5227 + info.iTotalSockets=sockets;
1.5228 + info.iRuggedFileSystem=ETrue;
1.5229 + __KTRACE_OPT(KLOCDRV,Kern::Printf("Total drives=%d, sockets=%d",drives,sockets));
1.5230 + OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO3, "Total drives=%d; sockets=%d", drives, sockets );
1.5231 + OstTraceFunctionExit0( GETDRIVEINFO_EXIT );
1.5232 + }
1.5233 +
1.5234 +#if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__)
1.5235 +void ResetConcurrencyStats(DMediaPagingDevice* aDevice, TMediaPagingStats aStats)
1.5236 + {
1.5237 + NKern::FMWait(&aDevice->iInstrumentationLock);
1.5238 + switch(aStats)
1.5239 + {
1.5240 + case EMediaPagingStatsRom:
1.5241 + aDevice->iServicingROM=0;
1.5242 + memclr(&aDevice->iROMStats,sizeof(SMediaROMPagingConcurrencyInfo));
1.5243 + break;
1.5244 + case EMediaPagingStatsCode:
1.5245 + aDevice->iServicingCode=0;
1.5246 + memclr(&aDevice->iCodeStats,sizeof(SMediaCodePagingConcurrencyInfo));
1.5247 + break;
1.5248 + case EMediaPagingStatsDataIn:
1.5249 + aDevice->iServicingDataIn=0;
1.5250 + memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo));
1.5251 + break;
1.5252 + case EMediaPagingStatsDataOut:
1.5253 + aDevice->iServicingDataOut=0;
1.5254 + memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo));
1.5255 + break;
1.5256 + case EMediaPagingStatsAll:
1.5257 + aDevice->iServicingROM=0;
1.5258 + aDevice->iServicingCode=0;
1.5259 + aDevice->iServicingDataIn=0;
1.5260 + aDevice->iServicingDataOut=0;
1.5261 + memclr(&aDevice->iROMStats,sizeof(SMediaROMPagingConcurrencyInfo));
1.5262 + memclr(&aDevice->iCodeStats,sizeof(SMediaCodePagingConcurrencyInfo));
1.5263 + memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo));
1.5264 + break;
1.5265 + }
1.5266 + NKern::FMSignal(&aDevice->iInstrumentationLock);
1.5267 + }
1.5268 +#endif
1.5269 +#if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
1.5270 +void ResetBenchmarkStats(DMediaPagingDevice* aDevice, TMediaPagingStats aStats)
1.5271 + {
1.5272 + NKern::FMWait(&aDevice->iInstrumentationLock);
1.5273 + switch(aStats)
1.5274 + {
1.5275 + case EMediaPagingStatsRom:
1.5276 + aDevice->iROMBenchmarkData.iCount = 0;
1.5277 + aDevice->iROMBenchmarkData.iTotalTime = 0;
1.5278 + aDevice->iROMBenchmarkData.iMaxTime = 0;
1.5279 + aDevice->iROMBenchmarkData.iMinTime = KMaxTInt;
1.5280 + break;
1.5281 + case EMediaPagingStatsCode:
1.5282 + aDevice->iCodeBenchmarkData.iCount = 0;
1.5283 + aDevice->iCodeBenchmarkData.iTotalTime = 0;
1.5284 + aDevice->iCodeBenchmarkData.iMaxTime = 0;
1.5285 + aDevice->iCodeBenchmarkData.iMinTime = KMaxTInt;
1.5286 + break;
1.5287 + case EMediaPagingStatsDataIn:
1.5288 + aDevice->iDataInBenchmarkData.iCount = 0;
1.5289 + aDevice->iDataInBenchmarkData.iTotalTime = 0;
1.5290 + aDevice->iDataInBenchmarkData.iMaxTime = 0;
1.5291 + aDevice->iDataInBenchmarkData.iMinTime = KMaxTInt;
1.5292 + break;
1.5293 + case EMediaPagingStatsDataOut:
1.5294 + aDevice->iDataOutBenchmarkData.iCount = 0;
1.5295 + aDevice->iDataOutBenchmarkData.iTotalTime = 0;
1.5296 + aDevice->iDataOutBenchmarkData.iMaxTime = 0;
1.5297 + aDevice->iDataOutBenchmarkData.iMinTime = KMaxTInt;
1.5298 + break;
1.5299 + case EMediaPagingStatsAll:
1.5300 + aDevice->iDataInBenchmarkData.iCount = 0;
1.5301 + aDevice->iDataInBenchmarkData.iTotalTime = 0;
1.5302 + aDevice->iDataInBenchmarkData.iMaxTime = 0;
1.5303 + aDevice->iDataInBenchmarkData.iMinTime = KMaxTInt;
1.5304 +
1.5305 + aDevice->iDataOutBenchmarkData.iCount = 0;
1.5306 + aDevice->iDataOutBenchmarkData.iTotalTime = 0;
1.5307 + aDevice->iDataOutBenchmarkData.iMaxTime = 0;
1.5308 + aDevice->iDataOutBenchmarkData.iMinTime = KMaxTInt;
1.5309 +
1.5310 + aDevice->iROMBenchmarkData.iCount = 0;
1.5311 + aDevice->iROMBenchmarkData.iTotalTime = 0;
1.5312 + aDevice->iROMBenchmarkData.iMaxTime = 0;
1.5313 + aDevice->iROMBenchmarkData.iMinTime = KMaxTInt;
1.5314 +
1.5315 + aDevice->iCodeBenchmarkData.iCount = 0;
1.5316 + aDevice->iCodeBenchmarkData.iTotalTime = 0;
1.5317 + aDevice->iCodeBenchmarkData.iMaxTime = 0;
1.5318 + aDevice->iCodeBenchmarkData.iMinTime = KMaxTInt;
1.5319 + break;
1.5320 + }
1.5321 + NKern::FMSignal(&aDevice->iInstrumentationLock);
1.5322 + }
1.5323 +#endif
1.5324 +
1.5325 +TInt MediaHalFunction(TAny*, TInt aFunction, TAny* a1, TAny* a2)
1.5326 + {
1.5327 + TInt r=KErrNotSupported;
1.5328 + switch (aFunction)
1.5329 + {
1.5330 + case EMediaHalDriveInfo:
1.5331 + {
1.5332 + (void) a2;
1.5333 + TDriveInfoV1Buf infoBuf;
1.5334 + TDriveInfoV1& info=infoBuf();
1.5335 + GetDriveInfo(info);
1.5336 + Kern::InfoCopy(*(TDes8*)a1,infoBuf);
1.5337 + r=KErrNone;
1.5338 + break;
1.5339 + }
1.5340 +#if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__)
1.5341 + case EMediaHalGetROMConcurrencyInfo:
1.5342 + {
1.5343 + TInt drvNo=(TInt)a1;
1.5344 + TLocDrv* drv=TheDrives[drvNo];
1.5345 + if(!drv)
1.5346 + break;
1.5347 + DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice;
1.5348 + if(!device)
1.5349 + break;
1.5350 + NKern::FMWait(&device->iInstrumentationLock);
1.5351 + SMediaROMPagingConcurrencyInfo info=device->iROMStats;
1.5352 + NKern::FMSignal(&device->iInstrumentationLock);
1.5353 + kumemput32(a2,&info,sizeof(info));
1.5354 + r=KErrNone;
1.5355 + break;
1.5356 + }
1.5357 + case EMediaHalGetCodeConcurrencyInfo:
1.5358 + {
1.5359 + TInt drvNo=(TInt)a1;
1.5360 + TLocDrv* drv=TheDrives[drvNo];
1.5361 + if(!drv)
1.5362 + break;
1.5363 + DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
1.5364 + if(!device)
1.5365 + break;
1.5366 + NKern::FMWait(&device->iInstrumentationLock);
1.5367 + SMediaCodePagingConcurrencyInfo info=device->iCodeStats;
1.5368 + NKern::FMSignal(&device->iInstrumentationLock);
1.5369 + kumemput32(a2,&info,sizeof(info));
1.5370 + r=KErrNone;
1.5371 + break;
1.5372 + }
1.5373 + case EMediaHalGetDataConcurrencyInfo:
1.5374 + {
1.5375 + TInt drvNo=(TInt)a1;
1.5376 + TLocDrv* drv=TheDrives[drvNo];
1.5377 + if(!drv)
1.5378 + break;
1.5379 + DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice;
1.5380 + if(!device)
1.5381 + break;
1.5382 + NKern::FMWait(&device->iInstrumentationLock);
1.5383 + SMediaDataPagingConcurrencyInfo info=device->iDataStats;
1.5384 + NKern::FMSignal(&device->iInstrumentationLock);
1.5385 + kumemput32(a2,&info,sizeof(info));
1.5386 + r=KErrNone;
1.5387 + break;
1.5388 + }
1.5389 + case EMediaHalResetConcurrencyInfo:
1.5390 + {
1.5391 + TInt drvNo=(TInt)a1;
1.5392 + TLocDrv* drv=TheDrives[drvNo];
1.5393 + if(!drv)
1.5394 + break;
1.5395 + DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
1.5396 + if(!device)
1.5397 + break;
1.5398 + TUint index=(TInt)a2;
1.5399 + if(index>EMediaPagingStatsCode)
1.5400 + break;
1.5401 + ResetConcurrencyStats(device, (TMediaPagingStats)index);
1.5402 + r=KErrNone;
1.5403 + break;
1.5404 + }
1.5405 +#endif
1.5406 +#if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
1.5407 + case EMediaHalGetROMPagingBenchmark:
1.5408 + {
1.5409 + TInt drvNo=(TInt)a1;
1.5410 + TLocDrv* drv=TheDrives[drvNo];
1.5411 + if(!drv)
1.5412 + break;
1.5413 + DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
1.5414 + if(!device)
1.5415 + break;
1.5416 + NKern::FMWait(&device->iInstrumentationLock);
1.5417 + SPagingBenchmarkInfo info = device->iROMBenchmarkData;
1.5418 + NKern::FMSignal(&device->iInstrumentationLock);
1.5419 + kumemput32(a2,&info,sizeof(info));
1.5420 + r=KErrNone;
1.5421 + break;
1.5422 + }
1.5423 + case EMediaHalGetCodePagingBenchmark:
1.5424 + {
1.5425 + TInt drvNo=(TInt)a1;
1.5426 + TLocDrv* drv=TheDrives[drvNo];
1.5427 + if(!drv)
1.5428 + break;
1.5429 + DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
1.5430 + if(!device)
1.5431 + break;
1.5432 + NKern::FMWait(&device->iInstrumentationLock);
1.5433 + SPagingBenchmarkInfo info = device->iCodeBenchmarkData;
1.5434 + NKern::FMSignal(&device->iInstrumentationLock);
1.5435 + kumemput32(a2,&info,sizeof(info));
1.5436 + r=KErrNone;
1.5437 + break;
1.5438 + }
1.5439 + case EMediaHalGetDataInPagingBenchmark:
1.5440 + {
1.5441 + TInt drvNo=(TInt)a1;
1.5442 + TLocDrv* drv=TheDrives[drvNo];
1.5443 + if(!drv)
1.5444 + break;
1.5445 + DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
1.5446 + if(!device)
1.5447 + break;
1.5448 + NKern::FMWait(&device->iInstrumentationLock);
1.5449 + SPagingBenchmarkInfo info = device->iDataInBenchmarkData;
1.5450 + NKern::FMSignal(&device->iInstrumentationLock);
1.5451 + kumemput32(a2,&info,sizeof(info));
1.5452 + r=KErrNone;
1.5453 + break;
1.5454 + }
1.5455 + case EMediaHalGetDataOutPagingBenchmark:
1.5456 + {
1.5457 + TInt drvNo=(TInt)a1;
1.5458 + TLocDrv* drv=TheDrives[drvNo];
1.5459 + if(!drv)
1.5460 + break;
1.5461 + DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
1.5462 + if(!device)
1.5463 + break;
1.5464 + NKern::FMWait(&device->iInstrumentationLock);
1.5465 + SPagingBenchmarkInfo info = device->iDataOutBenchmarkData;
1.5466 + NKern::FMSignal(&device->iInstrumentationLock);
1.5467 + kumemput32(a2,&info,sizeof(info));
1.5468 + r=KErrNone;
1.5469 + break;
1.5470 + }
1.5471 + case EMediaHalResetPagingBenchmark:
1.5472 + {
1.5473 + TInt drvNo=(TInt)a1;
1.5474 + TLocDrv* drv=TheDrives[drvNo];
1.5475 + if(!drv)
1.5476 + break;
1.5477 + DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
1.5478 + if(!device)
1.5479 + break;
1.5480 + TUint index=(TInt)a2;
1.5481 + if(index>EMediaPagingStatsCode)
1.5482 + break;
1.5483 + ResetBenchmarkStats(device, (TMediaPagingStats)index);
1.5484 + r=KErrNone;
1.5485 + break;
1.5486 + }
1.5487 + case EMediaHalGetPagingInfo:
1.5488 + {
1.5489 + TInt drvNo=(TInt)a1;
1.5490 + TLocDrv* drv=TheDrives[drvNo];
1.5491 + if(!drv)
1.5492 + break;
1.5493 + DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
1.5494 + if(!device)
1.5495 + break;
1.5496 + NKern::FMWait(&device->iInstrumentationLock);
1.5497 + SMediaPagingInfo info = device->iMediaPagingInfo;
1.5498 + NKern::FMSignal(&device->iInstrumentationLock);
1.5499 + kumemput32(a2,&info,sizeof(info));
1.5500 + r=KErrNone;
1.5501 + break;
1.5502 + }
1.5503 +#endif
1.5504 + default:
1.5505 + break;
1.5506 + }
1.5507 + return r;
1.5508 + }
1.5509 +
1.5510 +
1.5511 +/******************************************************************************
1.5512 + Partition table scanner
1.5513 + ******************************************************************************/
1.5514 +
1.5515 +#ifdef _DEBUG
1.5516 +#define DMEMDUMP(base,size) DbgMemDump((TLinAddr)base,size)
1.5517 +void DbgMemDump(TLinAddr aBase, TInt aSize)
1.5518 + {
1.5519 + TInt off;
1.5520 + const TUint8* p=(const TUint8*)aBase;
1.5521 + NKern::Lock();
1.5522 + for (off=0; off<aSize; off+=16, p+=16)
1.5523 + {
1.5524 + Kern::Printf("%04x: %02x %02x %02x %02x %02x %02x %02x %02x | %02x %02x %02x %02x %02x %02x %02x %02x",
1.5525 + off, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
1.5526 + p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
1.5527 + }
1.5528 + NKern::Unlock();
1.5529 + }
1.5530 +#else
1.5531 +#define DMEMDUMP(base,size)
1.5532 +#endif
1.5533 +
1.5534 +EXPORT_C void TPartitionTableScanner::Set(TUint8* aSectorBuffer, TPartitionEntry* aEntry, TInt aMaxPartitions, TInt64 aMediaSize)
1.5535 + {
1.5536 + __KTRACE_OPT(KLOCDRV, Kern::Printf("TPartitionTableScanner @ %08x : buf %08x entry %08x max %d sz %08x %08x",
1.5537 + this, aSectorBuffer, aEntry, aMaxPartitions, I64HIGH(aMediaSize), I64LOW(aMediaSize)));
1.5538 + OstTraceExt4( TRACE_INTERNALS, TPARTITIONTABLESCANNER_SET, "TPartitionTableScanner at 0x%08x; aSectorBuffer=0x%08x; aEntry=0x%08x; aMaxPartitions=%d", (TUint) this, (TUint) aSectorBuffer, (TUint) aEntry, aMaxPartitions );
1.5539 + __ASSERT_ALWAYS(aMaxPartitions>0, LOCM_FAULT());
1.5540 + memclr(this, sizeof(TPartitionTableScanner));
1.5541 + iLBA = -1;
1.5542 + iSectorBuffer = aSectorBuffer;
1.5543 + iFirstEntry = aEntry;
1.5544 + iNextEntry = aEntry;
1.5545 + iLimit = aEntry + aMaxPartitions;
1.5546 + iMediaSize = aMediaSize;
1.5547 + }
1.5548 +
1.5549 +EXPORT_C TInt TPartitionTableScanner::NumberOfPartitionsFound() const
1.5550 + {
1.5551 + TInt n = iNextEntry - iFirstEntry;
1.5552 + __KTRACE_OPT(KLOCDRV, Kern::Printf("TPartitionTableScanner N=%d", n));
1.5553 + OstTrace1( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NUMBERPARTITIONS, "Number of partitions=%d", n );
1.5554 + return n;
1.5555 + }
1.5556 +
1.5557 +TPartitionTableScanner::SPart::SPart(const TUint8* a)
1.5558 + {
1.5559 + iBootInd = a[0];
1.5560 + iType = a[4];
1.5561 + iRSS = a[8]|(a[9]<<8)|(a[10]<<16)|(a[11]<<24);
1.5562 + iSectors = a[12]|(a[13]<<8)|(a[14]<<16)|(a[15]<<24);
1.5563 + __KTRACE_OPT(KLOCDRV, Kern::Printf("SPart: BI=%02x TYPE=%02x RSS=%08x SIZE=%08x", iBootInd, iType, iRSS, iSectors));
1.5564 + OstTraceExt4(TRACE_INTERNALS, TPARTITIONTABLESCANNER_SPART_SPART, "SPart: iBootInd=%02x; iType=%02x; iRSS=%08x; iSectors=%08x", (TUint) iBootInd, (TUint) iType, (TUint) iRSS, (TUint) iSectors);
1.5565 + }
1.5566 +
1.5567 +TInt TPartitionTableScanner::MakeEntry(const SPart& a)
1.5568 + {
1.5569 + OstTraceFunctionEntry1( TPARTITIONTABLESCANNER_MAKEENTRY_ENTRY, this );
1.5570 + if (iNextEntry == iLimit)
1.5571 + {
1.5572 + OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT1, this, KErrOverflow );
1.5573 + return KErrOverflow;
1.5574 + }
1.5575 + if (a.iRSS<=0 || a.iSectors<=0 || a.iRSS>=iMediaSize)
1.5576 + {
1.5577 + OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT2, this, KErrCorrupt );
1.5578 + return KErrCorrupt;
1.5579 + }
1.5580 + if (TUint64(a.iRSS) + TUint64(a.iSectors) > TUint64(iMediaSize))
1.5581 + {
1.5582 + OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT3, this, KErrCorrupt );
1.5583 + return KErrCorrupt;
1.5584 + }
1.5585 + iNextEntry->iBootIndicator = a.iBootInd;
1.5586 + iNextEntry->iPartitionType = a.iType;
1.5587 + iNextEntry->iPartitionBaseAddr = TInt64(a.iRSS)<<ESectorShift;
1.5588 + iNextEntry->iPartitionLen = TInt64(a.iSectors)<<ESectorShift;
1.5589 + ++iNextEntry;
1.5590 + OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT4, this, KErrNone );
1.5591 + return KErrNone;
1.5592 + }
1.5593 +
1.5594 +EXPORT_C TInt64 TPartitionTableScanner::NextLBA()
1.5595 + {
1.5596 + OstTraceFunctionEntry0( TPARTITIONTABLESCANNER_NEXTLBA_ENTRY );
1.5597 + __KTRACE_OPT(KLOCDRV, Kern::Printf(">TPartitionTableScanner iLBA=%08x %08x", I64HIGH(iLBA), I64LOW(iLBA)));
1.5598 + OstTraceExt2( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NEXTLBA1, "TPartitionTableScanner iLBA=%08x %08x", I64HIGH(iLBA), I64LOW(iLBA) );
1.5599 + TInt r;
1.5600 + TUint8* b = iSectorBuffer;
1.5601 + TUint8* pS = b + 0x1be;
1.5602 + TUint8* pE = pS + 64;
1.5603 + TUint8* p = pS;
1.5604 + TInt orig_sp = iStackPointer;
1.5605 + TInt sp;
1.5606 + if (iLBA < 0)
1.5607 + {
1.5608 + iLBA = 0;
1.5609 + goto end;
1.5610 + }
1.5611 + __KTRACE_OPT(KLOCDRV,DMEMDUMP(b, ESectorSize));
1.5612 + if (b[ESectorSize-2]!=0x55 || b[ESectorSize-1]!=0xaa)
1.5613 + {
1.5614 + __KTRACE_OPT(KLOCDRV, Kern::Printf("Bad signature"));
1.5615 + OstTrace0( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NEXTLBA2, "Bad signature" );
1.5616 + iLBA = KErrCorrupt;
1.5617 + goto end;
1.5618 + }
1.5619 + if (iLBA==0 && iNextEntry==iFirstEntry)
1.5620 + {
1.5621 + // Look for bootable partition first
1.5622 + for (; p<pE; p+=16)
1.5623 + {
1.5624 + SPart pt(p);
1.5625 + if (pt.iBootInd==0x80 && pt.iType && pt.iSectors>0)
1.5626 + {
1.5627 + p[4] = 0;
1.5628 + r = MakeEntry(pt);
1.5629 + if (r!=KErrNone)
1.5630 + {
1.5631 + iLBA = r;
1.5632 + goto end;
1.5633 + }
1.5634 + }
1.5635 + }
1.5636 + }
1.5637 + // Look for extended partitions
1.5638 + for (p=pE-16; p>=pS; p-=16)
1.5639 + {
1.5640 + SPart pt(p);
1.5641 + if ((pt.iType==0x05 || pt.iType==0x0f) && pt.iSectors>0)
1.5642 + {
1.5643 + // This one is an EBR
1.5644 + p[4] = 0;
1.5645 + if (iStackPointer == EMaxNest)
1.5646 + {
1.5647 + if (iStackPointer == orig_sp)
1.5648 + continue;
1.5649 + --iStackPointer;
1.5650 + for(sp = orig_sp; sp<iStackPointer; ++sp)
1.5651 + iStack[sp] = iStack[sp+1];
1.5652 + }
1.5653 + iStack[iStackPointer].iRSS = pt.iRSS;
1.5654 + iStack[iStackPointer].iSectors = pt.iSectors;
1.5655 + ++iStackPointer;
1.5656 +#ifdef _DEBUG
1.5657 + for (sp=0; sp<iStackPointer; ++sp)
1.5658 + {
1.5659 + const TInt64& rss = iStack[sp].iRSS;
1.5660 + const TInt64& size = iStack[sp].iSectors;
1.5661 + __KTRACE_OPT(KLOCDRV, Kern::Printf("Stack[%d] RSS %08x %08x SIZE %08x %08x", sp,
1.5662 + I64HIGH(rss), I64LOW(rss), I64HIGH(size), I64LOW(size) ));
1.5663 + 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));
1.5664 + }
1.5665 +#endif
1.5666 + }
1.5667 + }
1.5668 + // Look for other data partitions
1.5669 + for (p=pS; p<pE; p+=16)
1.5670 + {
1.5671 + SPart pt(p);
1.5672 + if (pt.iType && pt.iSectors>0)
1.5673 + {
1.5674 + pt.iRSS += TUint32(iLBA); // data partitions are specified relative to the EBR they appear in
1.5675 + r = MakeEntry(pt);
1.5676 + if (r!=KErrNone)
1.5677 + {
1.5678 + iLBA = r;
1.5679 + goto end;
1.5680 + }
1.5681 + }
1.5682 + }
1.5683 + // If any EBRs on stack, pop off the first and process it
1.5684 + if (iStackPointer)
1.5685 + {
1.5686 + --iStackPointer;
1.5687 + iLBA = iFirstEBR + iStack[iStackPointer].iRSS; // LBA of second and subsequent EBR is specified relative to first EBR
1.5688 + if (!iFirstEBR)
1.5689 + iFirstEBR = iLBA;
1.5690 + }
1.5691 + else
1.5692 + iLBA = KErrEof; // finished
1.5693 +
1.5694 +end:
1.5695 + __KTRACE_OPT(KLOCDRV, Kern::Printf("<TPartitionTableScanner iLBA=%08x %08x", I64HIGH(iLBA), I64LOW(iLBA)));
1.5696 + OstTraceExt2( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NEXTLBA3, "TPartitionTableScanner iLBA=0x%08x 0x%08x", I64HIGH(iLBA), I64LOW(iLBA) );
1.5697 + OstTraceFunctionExit0( TPARTITIONTABLESCANNER_NEXTLBA_EXIT );
1.5698 + return iLBA;
1.5699 + }
1.5700 +
1.5701 +/**
1.5702 + * Returns Address and Length of next contiguous Physical memory fragment
1.5703 + *
1.5704 + * @param aAddr On success, populated with the Physical Address of the next fragment.
1.5705 + * @param aLen On success, populated with the length in bytes of the next fragment.
1.5706 + *
1.5707 + * @return KErrNone, if successful;
1.5708 + * KErrNoMemory, if no more memory fragments left.
1.5709 + * KErrNotSupported, if Physical Memory addressing is not supported by this Media.
1.5710 + */
1.5711 +EXPORT_C TInt TLocDrvRequest::GetNextPhysicalAddress(TPhysAddr& aAddr, TInt& aLen)
1.5712 + {
1.5713 + OstTraceExt2(TRACE_FLOW, TLOCDRVREQUEST_GETNEXTPHYSICALADDRESS_ENTRY, "> TLocDrvRequest::GetNextPhysicalAddress;aAddr=%x;aLen=%d;", (TUint) &aAddr, aLen );
1.5714 + if (Flags() & EPhysAddr)
1.5715 + {
1.5716 +#ifdef __DEMAND_PAGING__
1.5717 + if (DMediaPagingDevice::PagingRequest(*this))
1.5718 + {
1.5719 + return DDmaHelper::GetPhysicalAddress(*this, aAddr, aLen);
1.5720 + }
1.5721 +#endif
1.5722 + return Drive()->iDmaHelper->GetPhysicalAddress(aAddr, aLen);
1.5723 + }
1.5724 + else
1.5725 + {
1.5726 + OstTraceFunctionExitExt( TLOCDRVREQUEST_GETNEXTPHYSICALADDRESS_EXIT, this, KErrNotSupported );
1.5727 + return KErrNotSupported;
1.5728 + }
1.5729 + }
1.5730 +
1.5731 +
1.5732 +/******************************************************************************
1.5733 + Entry point
1.5734 + ******************************************************************************/
1.5735 +DECLARE_STANDARD_EXTENSION()
1.5736 + {
1.5737 + __KTRACE_OPT(KBOOT,Kern::Printf("Starting LOCMEDIA extension"));
1.5738 +
1.5739 + // install the HAL function
1.5740 + TInt r=Kern::AddHalEntry(EHalGroupMedia,MediaHalFunction,NULL);
1.5741 +#ifdef __DEMAND_PAGING__
1.5742 + if (r==KErrNone)
1.5743 + {
1.5744 + __KTRACE_OPT(KBOOT,Kern::Printf("Creating LocDrv device"));
1.5745 + DLocalDriveFactory* device = new DLocalDriveFactory;
1.5746 + if (device==NULL)
1.5747 + r=KErrNoMemory;
1.5748 + else
1.5749 + r=Kern::InstallLogicalDevice(device);
1.5750 + __KTRACE_OPT(KBOOT,Kern::Printf("Installing LocDrv device in kernel returned %d",r));
1.5751 + }
1.5752 +#endif // __DEMAND_PAGING__
1.5753 + return r;
1.5754 + }
1.5755 +
1.5756 +