First public contribution.
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\drivers\locmedia\locmedia.cpp
20 #include "dmasupport.h"
21 #include <kernel/cache.h>
23 #include "OstTraceDefinitions.h"
24 #ifdef OST_TRACE_COMPILER_IN_USE
25 #include "locmedia_ost.h"
27 #pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
29 #include "locmediaTraces.h"
33 #if defined(_DEBUG) && defined(__DEMAND_PAGING__)
34 //#define __DEBUG_DEMAND_PAGING__
39 #define CHECK_RET(r) if ((r)==KErrNotSupported && (KDebugNum(KSCRATCH))) {NKern::Lock(); *(TInt*)0xfaece5=0;}
40 //#define CHECK_RET(r)
45 _LIT(KLddName,"LocDrv");
46 _LIT(KLitMediaDriverName, "Media.*");
47 _LIT(KLitLocMedia,"LocMedia");
49 #define LOCM_FAULT() Kern::Fault("LOCMEDIA",__LINE__)
51 const TInt KMaxLocalDriveCapsLength=256;
52 const TInt KMaxQueryDeviceLength=256;
54 // The maximum amount of user-data which will be pinned. If a request is longer
55 // than this value it will be split up into a number of requests
56 // This value is a bit arbitrary - it needs to be sufficiently large so that transfer
57 // rates don't suffer too much - but it can't be too big or we'd be "stealing" too much
58 // memory from the demand paging pool and starving other processes
59 const TInt KMaxPinData = 256*1024;
61 // The number of locks available for pinning shared by all the drive threads in the system.
62 // If all locks are in use then a single pre-allocated lock is used.
63 const TInt KDynamicPagingLockCount = 8;
65 TLocDrv* TheDrives[KMaxLocalDrives];
66 DMedia* TheMedia[KMaxLocalDrives];
67 HBuf* DriveNames[KMaxLocalDrives];
69 TPasswordStore* ThePasswordStore=NULL;
71 class DPrimaryMediaBase::DBody : public DBase
76 #ifdef __DEMAND_PAGING__
77 DMediaPagingDevice* iPagingDevice;
78 TInt iPageSizeMsk; // Mask of page size (e.g. 4096-1 -> 4095)
83 #ifdef __DEMAND_PAGING__
84 DMediaPagingDevice* ThePagingDevices[KMaxLocalDrives];
85 DPrimaryMediaBase* TheRomPagingMedia = NULL;
86 DPrimaryMediaBase* TheDataPagingMedia = NULL;
87 TBool DataPagingDeviceRegistered = EFalse;
88 class DPinObjectAllocator;
89 DPinObjectAllocator* ThePinObjectAllocator = NULL;
91 // The paging media might share a DfcQ with other non-paging media (e.g. 2 MMC/SD cards sharing the same stack)
92 // In this case, we need to avoid taking page faults on the non-paging media too, hence the need for these checks:
93 inline TBool DataPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia)
94 {return TheDataPagingMedia && TheDataPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;}
95 inline TBool RomPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia)
96 {return TheRomPagingMedia && TheRomPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;}
103 Internal class which contains :
104 (1) a queue of pre-allocated TVirtualPinObject's;
105 (2) a single pre-allocated DFragmentationPagingLock object:
106 this may be used if there are no TVirtualPinObject's available or if Kern::PinVirtualMemory() fails
108 NONSHARABLE_CLASS(DPinObjectAllocator) : public DBase
113 Internal class encapsulating a TVirtualPinObject.
114 Contains a SDblQueLink so that it may form part of a SDblQue
118 TVirtualPinObject* iObject;
120 } SVirtualPinContainer;
123 inline DPinObjectAllocator() {};
124 ~DPinObjectAllocator();
125 TInt Construct(TInt aObjectCount, TUint aNumPages);
127 SVirtualPinContainer* AcquirePinObject();
128 void ReleasePinObject(SVirtualPinContainer* aVirtualPinObject);
130 inline DFragmentationPagingLock& PreAllocatedDataLock() {return *iPreAllocatedDataLock;}
133 // array of SVirtualPinContainer's
134 SVirtualPinContainer* iVirtualPinContainers;
137 // queues containing SVirtualPinContainer's
140 // pre-allocated (small) buffers for locking client data should Kern::PinVirtualMemory() fail
141 DFragmentationPagingLock* iPreAllocatedDataLock;
143 // A mutex to protect access to the pinning objects.
147 TUint iFragmentGranularity;
151 DPinObjectAllocator::~DPinObjectAllocator()
153 OstTraceFunctionEntry1( DPINOBJECTALLOCATOR_DPINOBJECTALLOCATOR_ENTRY, this );
154 if (iPreAllocatedDataLock)
156 iPreAllocatedDataLock->Cleanup();
157 delete iPreAllocatedDataLock;
160 for (TInt n=0; n<iObjectCount; n++)
162 SVirtualPinContainer& virtualPinContainer = iVirtualPinContainers[n];
163 if (virtualPinContainer.iObject)
164 Kern::DestroyVirtualPinObject(virtualPinContainer.iObject);
167 delete [] iVirtualPinContainers;
168 OstTraceFunctionExit1( DPINOBJECTALLOCATOR_DPINOBJECTALLOCATOR_EXIT, this );
171 TInt DPinObjectAllocator::Construct(TInt aObjectCount, TUint aNumPages)
173 OstTraceFunctionEntryExt( DPINOBJECTALLOCATOR_CONSTRUCT_ENTRY, this );
174 TInt pageSize = Kern::RoundToPageSize(1);
175 iFragmentGranularity = pageSize * aNumPages;
176 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation granularity set to 0x%x", iFragmentGranularity));
177 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPINOBJECTALLOCATOR_CONSTRUCT, "Fragmentation granularity=0x%x", iFragmentGranularity);
179 // construct the paging lock containing pre-allocated buffers
181 iPreAllocatedDataLock = new DFragmentationPagingLock();
182 if(!iPreAllocatedDataLock)
184 OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT1, this, KErrNoMemory );
187 TInt r = iPreAllocatedDataLock->Construct(aNumPages);
190 OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT2, this, r );
195 SVirtualPinContainer* iVirtualPinContainers = new SVirtualPinContainer[aObjectCount];
196 if (iVirtualPinContainers == NULL)
198 OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT3, this, KErrNoMemory );
201 memclr(iVirtualPinContainers, sizeof(SVirtualPinContainer) * aObjectCount);
202 iObjectCount = aObjectCount;
204 // construct the queue of dynamic paging locks
205 for (TInt n=0; n<aObjectCount; n++)
207 SVirtualPinContainer& pinContainer = iVirtualPinContainers[n];
209 TInt r = Kern::CreateVirtualPinObject(pinContainer.iObject);
212 OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT4, this, KErrNoMemory );
216 iFreeQ.Add(&pinContainer.iLink);
219 OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT5, this, KErrNone );
224 returns a SVirtualPinContainer object or NULL if NULL available
226 DPinObjectAllocator::SVirtualPinContainer* DPinObjectAllocator::AcquirePinObject()
228 OstTraceFunctionEntry1( DPINOBJECTALLOCATOR_ACQUIREPINOBJECT_ENTRY, this );
229 SVirtualPinContainer* pinContainer = NULL;
231 NKern::FMWait(&iLock);
233 if (!iFreeQ.IsEmpty())
235 SDblQueLink* link = iFreeQ.First();
236 pinContainer = _LOFF(link, SVirtualPinContainer, iLink);
241 NKern::FMSignal(&iLock);
242 OstTraceFunctionExit1( DPINOBJECTALLOCATOR_ACQUIREPINOBJECT_EXIT, this );
247 returns a SVirtualPinContainer object to the pool
249 void DPinObjectAllocator::ReleasePinObject(SVirtualPinContainer* aPinContainer)
251 OstTraceFunctionEntry1( DPINOBJECTALLOCATOR_RELEASEPINOBJECT_ENTRY, this );
252 NKern::FMWait(&iLock);
254 iFreeQ.Add(&aPinContainer->iLink);
256 NKern::FMSignal(&iLock);
257 OstTraceFunctionExit1( DPINOBJECTALLOCATOR_RELEASEPINOBJECT_EXIT, this );
260 #endif // __DEMAND_PAGING__
263 /********************************************
264 * Local drive device base class
265 ********************************************/
266 DECLARE_EXTENSION_LDD()
268 return new DLocalDriveFactory;
271 DLocalDriveFactory::DLocalDriveFactory()
276 OstTraceFunctionEntry1( DLOCALDRIVEFACTORY_DLOCALDRIVEFACTORY_ENTRY, this );
277 iParseMask=KDeviceAllowUnit|KDeviceAllowInfo;
278 iUnitsMask=~(0xffffffff<<KMaxLocalDrives);
279 iVersion=TVersion(KLocalDriveMajorVersion,KLocalDriveMinorVersion,KLocalDriveBuildVersion);
280 OstTraceFunctionExit1( DLOCALDRIVEFACTORY_DLOCALDRIVEFACTORY_EXIT, this );
283 TInt DLocalDriveFactory::Install()
285 // Install the device driver.
288 return SetName(&KLddName);
291 void DLocalDriveFactory::GetCaps(TDes8& /*aDes*/) const
293 // Return the Comm capabilities.
296 // TCapsLocalDriveV01 b;
297 // b.version=iVersion;
298 // aDes.FillZ(aDes.MaxLength());
299 // aDes.Copy((TUint8 *)&b,Min(aDes.MaxLength(),sizeof(b)));
302 TInt DLocalDriveFactory::Create(DLogicalChannelBase*& aChannel)
304 // Create a channel on the device.
307 OstTraceFunctionEntry1( DLOCALDRIVEFACTORY_CREATE_ENTRY, this );
308 aChannel=new DLocalDrive;
309 return aChannel?KErrNone:KErrNoMemory;
312 /********************************************
313 * Local drive interface class
314 ********************************************/
315 DLocalDrive::DLocalDrive()
320 DLocalDrive::~DLocalDrive()
322 OstTraceFunctionEntry1( DLOCALDRIVE_DLOCALDRIVE_ENTRY, this );
325 __KTRACE_OPT(KLOCDRV,Kern::Printf(">DLocalDrive::DoClose D:%d, M:%08x",iDrive->iDriveNumber,iDrive->iMedia));
326 iDrive->Disconnect(this);
327 __KTRACE_OPT(KLOCDRV,Kern::Printf("<DLocalDrive::DoClose D:%d, M:%08x",iDrive->iDriveNumber,iDrive->iMedia));
331 if (iCleanup.iThread)
335 iCleanup.iThread=NULL;
337 NKern::UnlockSystem();
338 if (pC) // original client may already have terminated
340 if (iNotifyChangeRequest)
341 Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrCancel);
342 pC->Close(NULL); // balances Open() in DoCreate
344 if (iNotifyChangeRequest)
345 Kern::DestroyClientRequest(iNotifyChangeRequest);
346 OstTraceFunctionExit1( DLOCALDRIVE_DLOCALDRIVE_EXIT, this );
349 TInt DLocalDrive::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer)
351 OstTraceFunctionEntry1( DLOCALDRIVE_DOCREATE_ENTRY, this );
353 if(!Kern::CurrentThreadHasCapability(ECapabilityTCB,__PLATSEC_DIAGNOSTIC_STRING("Checked by ELOCD.LDD (Local Media Driver)")))
355 OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT1, this, KErrPermissionDenied );
356 return KErrPermissionDenied;
358 if (!Kern::QueryVersionSupported(TVersion(KLocalDriveMajorVersion,KLocalDriveMinorVersion,KLocalDriveBuildVersion),aVer))
360 OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT2, this, KErrNotSupported );
361 return KErrNotSupported;
364 NKern::ThreadEnterCS();
365 TInt r = Kern::CreateClientDataRequest(iNotifyChangeRequest);
366 NKern::ThreadLeaveCS();
369 OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT3, this, r );
373 DThread& t=Kern::CurrentThread();
375 t.AddCleanup(&iCleanup);
376 NKern::UnlockSystem();
378 iNotifyChangeRequest->SetDestPtr((TBool*) anInfo);
380 iDrive=TheDrives[aUnit];
383 OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT4, this, KErrNotSupported );
384 return KErrNotSupported;
386 __KTRACE_OPT(KLOCDRV,Kern::Printf("DLocalDrive Create - connect to drive %d, M:%08x",iDrive->iDriveNumber,iDrive->iMedia));
387 r=iDrive->Connect(this);
388 __KTRACE_OPT(KLOCDRV,Kern::Printf("<DLocalDrive Create D:%d, M:%08x r:%d",iDrive->iDriveNumber,iDrive->iMedia,r));
391 iDrive=NULL; // didn't connect so don't disconnect
393 OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT5, this, r );
398 void DebugDumpDriveCaps(const TLocDrv* aDrive, const TAny* aCaps)
400 const TLocalDriveCapsV5& c=*(const TLocalDriveCapsV5*)aCaps;
401 Kern::Printf("Drive %d Caps:", aDrive->iDriveNumber);
402 Kern::Printf("Size: %lx", c.iSize);
403 Kern::Printf("Type: %08x", c.iType);
404 Kern::Printf("Bus : %08x", c.iConnectionBusType);
405 Kern::Printf("DAtt: %08x", c.iDriveAtt);
406 Kern::Printf("MAtt: %08x", c.iMediaAtt);
407 Kern::Printf("Base: %08x", c.iBaseAddress);
408 Kern::Printf("FSID: %04x", c.iFileSystemId);
409 Kern::Printf("PTYP: %04x", c.iPartitionType);
410 Kern::Printf("HIDN: %08x", c.iHiddenSectors);
411 Kern::Printf("EBSZ: %08x", c.iEraseBlockSize);
412 //---------------- V5 ------------------//
413 if (c.iSerialNumLength != 0)
415 Kern::Printf("SN: length is %d", c.iSerialNumLength);
416 TBuf8<2*KMaxSerialNumLength+20> snBuf;
417 snBuf.Append(_L8("SN: content is "));
418 for (TUint i=0; i<c.iSerialNumLength; i++)
419 snBuf.AppendNumFixedWidth(c.iSerialNum[i], EHex, 2);
420 Kern::Printf((const char*)snBuf.Ptr());
423 Kern::Printf("SN: not supported");
428 * Requests are passed in message as follows:
429 * iValue = request ID
430 * iArg[0,1]= Position
432 * iArg[4] = Pointer to remote thread (NULL if client)
433 * iArg[5] = Pointer to remote descriptor
434 * iArg[6] = Offset into remote descriptor
435 * iArg[7] = Flags (whole media)
436 * iArg[8] = Pointer to TLocDrv
439 TInt DLocalDrive::Request(TInt aFunction, TAny* a1, TAny* a2)
441 OstTraceFunctionEntry1( DLOCALDRIVE_REQUEST_ENTRY, this );
443 __KTRACE_OPT(KLOCDRV,Kern::Printf(">DLocalDrive::DoControl D:%d M:%08x F:%d A1:%08x A2:%08x",
444 iDrive->iDriveNumber, iDrive->iMedia, aFunction, a1, a2));
445 OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST, "iMedia=0x%08x; iDriveNumber=%d; Request Id=%d", (TUint) iDrive->iMedia, (TInt) iDrive->iDriveNumber, (TInt) aFunction );
447 TInt r=KErrNotSupported;
448 TLocDrvRequest& m=TLocDrvRequest::Get();
453 case RLocalDrive::EControlRead:
456 r=m.ProcessMessageData(a1);
461 OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READ, "ERead iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m);
462 r=iDrive->Request(m);
464 OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READ_RETURN, "ERead Return iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m );
466 m.CloseRemoteThread();
469 case RLocalDrive::EControlWrite:
472 r=m.ProcessMessageData(a1);
475 OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITE, "EWrite iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m );
476 r=iDrive->Request(m);
477 OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITE_RETURN, "EWrite Return iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m );
479 m.CloseRemoteThread();
482 case RLocalDrive::EControlCaps:
484 TBuf8<KMaxLocalDriveCapsLength> capsBuf;
488 m.RemoteDes()=(TAny*)capsBuf.Ptr(); // overload this
489 m.Length()=KMaxLocalDriveCapsLength; // for pinning
490 r=iDrive->Request(m);
492 if(r == KErrNone && iDrive->iMedia != NULL && iDrive->iMedia->iDriver != NULL)
494 // Fill in default media size if not specified by the driver
496 // - This uses the members of TLocalDriveCapsV4 which was primarily used
497 // to report NAND flash characteristics, but are general enough to be
498 // used to report the size of any type of media without adding yet
499 // another extension to TLocalDriveCapsVx.
502 TLocalDriveCapsV4& caps = *(TLocalDriveCapsV4*)capsBuf.Ptr();
504 if(caps.iSectorSizeInBytes == 0)
506 // Fill in a default value for the disk sector size
507 caps.iSectorSizeInBytes = 512;
509 // Zero the number of sectors, as a sector count makes no sense without a sector size
510 // - Fault in debug mode if a sector count is provided to ensure that media driver creators
511 // set this value,but in release mode continue gracefully be recalculating the sector count.
512 __ASSERT_DEBUG(caps.iNumberOfSectors == 0, LOCM_FAULT());
513 caps.iNumberOfSectors = 0;
514 caps.iNumPagesPerBlock = 1; // ...to ensure compatiility with NAND semantics
517 if(caps.iNumberOfSectors == 0)
519 const Int64 totalSizeInSectors = iDrive->iMedia->iDriver->TotalSizeInBytes() / caps.iSectorSizeInBytes;
520 __ASSERT_DEBUG(I64HIGH(totalSizeInSectors) == 0, LOCM_FAULT());
522 if(I64HIGH(totalSizeInSectors) == 0)
524 caps.iNumberOfSectors = I64LOW(totalSizeInSectors);
529 #if defined(OST_TRACE_COMPILER_IN_USE) && defined(_DEBUG)
530 const TLocalDriveCapsV5& caps=*(const TLocalDriveCapsV5*)capsBuf.Ptr();
533 OstTraceExt5( TRACE_INTERNALS, DLOCALDRIVE_REQUEST_CAPS1, "Device caps: iDriveNumber=%d; iSize=0x%x; iType=%d; iDriveAtt=%d; TLocDrvRequest Object=0x%x", (TInt)iDrive->iDriveNumber, (TUint) caps.iSize, (TInt) caps.iType, (TInt) caps.iDriveAtt, (TUint) &m);
534 OstTraceExt5( TRACE_INTERNALS, DLOCALDRIVE_REQUEST_CAPS2, "Device caps: iBaseAddress=0x%x; iFileSystemId=%d; iPartitionType=%d; iHiddenSectors=0x%x; iEraseBlockSize=0x%x", (TUint) caps.iBaseAddress, (TInt) caps.iFileSystemId, (TUint) caps.iPartitionType, (TUint) caps.iHiddenSectors, (TUint) caps.iEraseBlockSize);
537 __KTRACE_OPT(KLOCDRV,DebugDumpDriveCaps(iDrive,capsBuf.Ptr()));
539 Kern::InfoCopy(*(TDes8*)a1, capsBuf);
542 case RLocalDrive::EControlFormat:
545 r=m.ProcessMessageData(a1);
548 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORMAT, "EFormat; TLocDrvRequest Object=0x%x", (TUint) &m);
549 r=iDrive->Request(m);
550 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORMAT_RETURN, "EFormat Return; TLocDrvRequest Object=0x%x", (TUint) &m);
554 case RLocalDrive::EControlEnlarge:
562 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_ENLARGE, "EEnlarge; TLocDrvRequest Object=0x%x", (TUint) &m);
563 r=iDrive->Request(m);
564 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_ENLARGE_RETURN, "EEnlarge Return; TLocDrvRequest Object=0x%x", (TUint) &m);
566 case RLocalDrive::EControlReduce:
568 if ((TInt)a1<0 || (TInt)a2<0)
576 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_REDUCE, "EReduce; TLocDrvRequest Object=0x%x", (TUint) &m);
577 r=iDrive->Request(m);
578 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_REDUCE_RETURN, "EReduce Return; TLocDrvRequest Object=0x%x", (TUint) &m);
581 case RLocalDrive::EControlForceMediaChange:
583 m.Id()=EForceMediaChange;
584 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORCEMEDIACHANGE, "EForceMediaChange; TLocDrvRequest Object=0x%x", (TUint) &m);
585 r = iDrive->Request(m);
586 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORCEMEDIACHANGE_RETURN, "EForceMediaChange Return; TLocDrvRequest Object=0x%x", (TUint) &m);
588 case RLocalDrive::EControlMediaDevice:
589 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLMEDIADEVICE, "EControlMediaDevice; TLocDrvRequest Object=0x%x", (TUint) &m);
590 r=iDrive->iPrimaryMedia->iDevice;
592 case RLocalDrive::EControlIsRemovable:
594 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLISREMOVABLE, "EControlIsRemovable; TLocDrvRequest Object=0x%x", (TUint) &m);
596 r=iDrive->iPrimaryMedia->IsRemovableDevice(sockNum);
598 kumemput32(a1,&sockNum,sizeof(TInt));
601 case RLocalDrive::EControlControlIO:
603 TLocalDriveControlIOData d;
604 kumemget32(&d,a1,sizeof(d));
607 m.iArg[0] = (TAny*) d.iCommand;
608 m.iArg[1] = d.iParam1;
609 m.iArg[2] = d.iParam2;
611 // if d.iHandle is == KLocalMessageHandle (-1),
612 // d.aParam1 and d.aParam2 are TAny* pointers
614 // if d.iHandle is == 0,
615 // d.aParam1 and d.aParam2 are TInts
617 // if d.iHandle is > 0,
618 // d.aParam1 is a data pointer (TUint8*)
619 // d.aParam2 is an optional extra paramater (TInt)
620 // d.iHandle is a data length (TInt)
621 m.iArg[3] = (TAny*) d.iHandle;
623 //We're highjacking fields representing
624 //length and position in a normal message, so
625 //let's not have the dispatcher function attempt
626 //to adjust for partition size.
627 m.Flags() |= TLocDrvRequest::EAdjusted;
629 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLCONTROLIO, "EControlControlIO; TLocDrvRequest Object=0x%x", (TUint) &m);
630 r=iDrive->Request(m);
631 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLCONTROLIO_RETURN, "EControlControlIO Return; TLocDrvRequest Object=0x%x", (TUint) &m);
634 case RLocalDrive::EControlSetMountInfo:
636 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLSETMOUNTINFO, "EControlSetMountInfo; TLocDrvRequest Object=0x%x", (TUint) &m);
638 r=m.ProcessMessageData(a1);
639 DPrimaryMediaBase* pM=iDrive->iPrimaryMedia;
640 if(!pM || r!=KErrNone)
643 if (pM->iMountInfo.iThread)
645 NKern::ThreadEnterCS();
646 //Close original thread
647 Kern::SafeClose((DObject*&) pM->iMountInfo.iThread,NULL);
648 if (m.RemoteDes()!=NULL)
650 //Set new mount info and leave setting thread open
651 #ifdef __DEMAND_PAGING__
652 // lock the mount info if this is a data paging media - and keep it locked
653 if ((DataPagingDfcQ(pM)) && ((r = LockMountInfo(*pM, m)) != KErrNone))
656 pM->iMountInfo.iInfo=(TDesC8*)m.RemoteDes();
657 pM->iMountInfo.iThread=m.RemoteThread();
661 //Clear existing mount info and close setting thread
663 #ifdef __DEMAND_PAGING__
664 // unlock the mount info if this is a data paging media
665 UnlockMountInfo(*pM);
668 pM->iMountInfo.iInfo=NULL;
669 pM->iMountInfo.iThread=NULL;
670 m.CloseRemoteThread();
672 NKern::ThreadLeaveCS();
677 //Setting mount info for the first time
678 if (m.RemoteDes()==NULL)
680 // if no mount info, close setting thread opened in ProcessMessageData()
681 m.CloseRemoteThread();
685 NKern::ThreadEnterCS();
686 #ifdef __DEMAND_PAGING__
687 // lock the mount info if this is a data paging media - and keep it locked
688 if ((DataPagingDfcQ(pM)) && ((r = LockMountInfo(*pM, m)) != KErrNone))
692 pM->iMountInfo.iInfo=(TDesC8*)m.RemoteDes();
693 pM->iMountInfo.iThread=m.RemoteThread();
694 NKern::ThreadLeaveCS();
699 case RLocalDrive::EControlPasswordLock:
701 m.Id()=EPasswordLock;
704 TMediaPassword oldPasswd;
705 TMediaPassword newPasswd;
706 TLocalDrivePasswordData pswData;
707 r = ReadPasswordData(m, pswData, oldPasswd, newPasswd);
711 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDLOCK, "EPasswordLock; TLocDrvRequest Object=0x%x", (TUint) &m);
712 r = iDrive->Request(m);
713 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDLOCK_RETURN, "EPasswordLock Return; TLocDrvRequest Object=0x%x", (TUint) &m);
717 case RLocalDrive::EControlPasswordUnlock:
719 m.Id()=EPasswordUnlock;
722 TMediaPassword oldPasswd;
723 TMediaPassword newPasswd;
724 TLocalDrivePasswordData pswData;
725 r = ReadPasswordData(m, pswData, oldPasswd, newPasswd);
729 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDUNLOCK, "EPasswordUnLock; TLocDrvRequest Object=0x%x", (TUint) &m);
730 r=iDrive->Request(m);
731 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDUNLOCK_RETURN, "EPasswordUnLock Return; TLocDrvRequest Object=0x%x", (TUint) &m);
734 iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0;
737 case RLocalDrive::EControlPasswordClear:
739 m.Id()=EPasswordClear;
742 TMediaPassword oldPasswd;
743 TMediaPassword newPasswd;
744 TLocalDrivePasswordData pswData;
745 r = ReadPasswordData(m, pswData, oldPasswd, newPasswd);
749 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDCLEAR, "EPasswordClear; TLocDrvRequest Object=0x%x", (TUint) &m);
750 r = iDrive->Request(m);
751 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDCLEAR_RETURN, "EPasswordClear Return; TLocDrvRequest Object=0x%x", (TUint) &m);
755 case RLocalDrive::EControlPasswordErase:
757 m.Id()=EPasswordErase;
758 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDERASE, "EPasswordErase; TLocDrvRequest Object=0x%x", (TUint) &m);
759 r=iDrive->Request(m);
760 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDERASE_RETURN, "EPasswordErase Return; TLocDrvRequest Object=0x%x", (TUint) &m);
762 iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0;
765 case RLocalDrive::EControlNotifyChange:
766 if (iCleanup.iThread != &Kern::CurrentThread())
767 Kern::PanicCurrentThread(KLitLocMedia,KErrAccessDenied);
769 if (!iNotifyChangeRequest->StatusPtr())
770 r = iNotifyChangeRequest->SetStatus((TRequestStatus*) a1);
771 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLNOTIFYCHANGE, "EControlNotifyChange; TLocDrvRequest Object=0x%x", (TUint) &m);
773 case RLocalDrive::EControlNotifyChangeCancel:
774 if (iCleanup.iThread != &Kern::CurrentThread())
775 Kern::PanicCurrentThread(KLitLocMedia,KErrAccessDenied);
776 Kern::QueueRequestComplete(iCleanup.iThread,iNotifyChangeRequest,KErrCancel);
777 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLNOTIFYCHANGECANCEL, "EControlNotifyChangeCancel; TLocDrvRequest Object=0x%x", (TUint) &m);
779 case RLocalDrive::EControlReadPasswordStore:
781 TUint8 passData[TPasswordStore::EMaxPasswordLength];
782 m.RemoteDes() = (TAny*) passData;
783 m.Length() = sizeof(passData);
784 m.Id()=EReadPasswordStore;
785 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READPASSWORDSTORE, "EReadPasswordStore; TLocDrvRequest Object=0x%x", (TUint) &m);
786 r=iDrive->Request(m);
787 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READPASSWORDSTORE_RETURN, "EReadPasswordStore Return; TLocDrvRequest Object=0x%x", (TUint) &m);
790 TPtr8 pData(passData, (TInt) m.Length(), TPasswordStore::EMaxPasswordLength);
791 m.RemoteDes()=(TDes8*)a1;
792 r = m.WriteRemote(&pData,0);
796 case RLocalDrive::EControlWritePasswordStore:
798 TUint8 passData[TPasswordStore::EMaxPasswordLength];
799 TPtr8 pData(passData, TPasswordStore::EMaxPasswordLength);
801 DThread* pT=m.RemoteThread();
805 m.RemoteDes() = (TDes8*)a1;
806 r = Kern::ThreadGetDesLength(pT, m.RemoteDes());
807 if ( r > pData.MaxLength() )
812 r = m.ReadRemote(&pData,0);
817 m.RemoteDes() = (TAny*) pData.Ptr();
818 m.Length() = pData.Length();
819 m.Id()=EWritePasswordStore;
820 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITEPASSWORDSTORE, "EWritePasswordStore; TLocDrvRequest Object=0x%x", (TUint) &m);
821 r=iDrive->Request(m);
822 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITEPASSWORDSTORE_RETURN, "EReadPasswordStore Return; TLocDrvRequest Object=0x%x", (TUint) &m);
824 iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0;
827 case RLocalDrive::EControlPasswordStoreLengthInBytes:
829 m.Id()=EPasswordStoreLengthInBytes;
831 m.RemoteDes() = (TAny*) &length;
832 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDSTORELENGTH, "EPasswordStoreLengthInBytes; TLocDrvRequest Object=0x%x", (TUint) &m);
833 r=iDrive->Request(m);
834 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDSTORELENGTH_RETURN, "EPasswordStoreLengthInBytes Return; TLocDrvRequest Object=0x%x", (TUint) &m);
839 r = m.WriteRemoteRaw(&length,sizeof(TInt));
844 case RLocalDrive::EControlGetLastErrorInfo:
846 m.Id()=EGetLastErrorInfo;
848 TErrorInfoBuf errorInfoBuf;
849 errorInfoBuf.SetMax();
850 errorInfoBuf.FillZ();
851 m.RemoteDes()=(TAny*) errorInfoBuf.Ptr(); // overload this
852 m.Length() = errorInfoBuf.MaxLength();
853 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_GETLASTERRORINFO, "EGetLastErrorInfo; TLocDrvRequest Object=0x%x", (TUint) &m);
854 r=iDrive->Request(m);
855 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLGETLASTERRORINFO_RETURN, "EControlGetLastErrorInfo Return; TLocDrvRequest Object=0x%x", (TUint) &m);
856 Kern::InfoCopy(*(TDes8*)a1, errorInfoBuf);
859 case RLocalDrive::EControlDeleteNotify:
861 m.Id()=EDeleteNotify;
862 r=m.ProcessMessageData(a1);
865 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_DELETENOTIFY, "EDeleteNotify; TLocDrvRequest Object=0x%x", (TUint) &m);
866 r=iDrive->Request(m);
867 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_DELETENOTIFY_RETURN, "EDeleteNotify Return; TLocDrvRequest Object=0x%x", (TUint) &m);
872 case RLocalDrive::EControlQueryDevice:
874 TBuf8<KMaxQueryDeviceLength> queryBuf;
878 m.Id() = EQueryDevice;
879 m.iArg[0] = a1; // RLocalDrive::TQueryDevice
880 m.RemoteDes() = (TAny*)queryBuf.Ptr(); // overload this
881 m.Length() = KMaxLocalDriveCapsLength; // for pinning
882 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE, "EQueryDevice; TLocDrvRequest Object=0x%x", (TUint) &m);
883 r=iDrive->Request(m);
884 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE_RETURN, "EQueryDevice Return; TLocDrvRequest Object=0x%x", (TUint) &m);
885 Kern::InfoCopy(*(TDes8*)a2, queryBuf);
890 __KTRACE_OPT(KLOCDRV,Kern::Printf("<DLocalDrive::DoControl D:%d M:%08x ret %d",iDrive->iDriveNumber, iDrive->iMedia, r));
892 OstTraceFunctionExitExt( DLOCALDRIVE_REQUEST_EXIT, this, r );
896 TInt DLocalDrive::ReadPasswordData(TLocDrvRequest& aReq, TLocalDrivePasswordData& aPswData, TMediaPassword& aOldPasswd, TMediaPassword& aNewPasswd)
898 TLocalDrivePasswordData clientData;
899 TInt r = aReq.ReadRemoteRaw(&clientData, sizeof(TLocalDrivePasswordData));
901 DThread* pT = aReq.RemoteThread();
906 r = Kern::ThreadDesRead(pT, clientData.iOldPasswd, aOldPasswd, 0 ,KChunkShiftBy0);
908 r = Kern::ThreadDesRead(pT, clientData.iNewPasswd, aNewPasswd, 0 ,KChunkShiftBy0);
910 aPswData.iStorePasswd = clientData.iStorePasswd;
911 aPswData.iOldPasswd = &aOldPasswd;
912 aPswData.iNewPasswd = &aNewPasswd;
915 aReq.RemoteDes() = (TAny*) &aPswData;
916 aReq.Flags()|= TLocDrvRequest::EKernelBuffer;
922 #ifdef __DEMAND_PAGING__
923 TInt DLocalDrive::LockMountInfo(DPrimaryMediaBase& aPrimaryMedia, TLocDrvRequest& aReq)
925 OstTraceExt2(TRACE_FLOW, DLOCALDRIVE_LOCKMOUNTINFO_ENTRY, "> aPrimaryMedia=%x;aReq=%x", (TUint) &aPrimaryMedia, (TUint) &aReq );
926 DMediaPagingDevice* pagingDevice = aPrimaryMedia.iBody->iPagingDevice;
927 if (pagingDevice == NULL)
929 OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT1, this, KErrNone );
933 __ASSERT_DEBUG(pagingDevice->iMountInfoDataLock == NULL, LOCM_FAULT());
934 __ASSERT_DEBUG(pagingDevice->iMountInfoDescHdrLock == NULL, LOCM_FAULT());
935 __ASSERT_DEBUG(pagingDevice->iMountInfoDescLenLock == NULL, LOCM_FAULT());
937 DThread* pT = aReq.RemoteThread();
939 pT = &Kern::CurrentThread(); // e.g. when using TBusLocalDrive directly
943 TUint8* desAddress = NULL;
944 TInt r = Kern::ThreadGetDesInfo(pT,aReq.RemoteDes(),length,maxLength,desAddress,EFalse); // get descriptor length, maxlength and desAddress
947 OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT2, this, r );
952 OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT3, this, KErrNone );
957 static const TUint8 LengthLookup[16]={4,8,12,8,12,0,0,0,0,0,0,0,0,0,0,0};
959 r = Kern::ThreadRawRead(pT, aReq.RemoteDes(), &desHdr, sizeof(desHdr));
962 OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT4, this, r );
965 TInt desType = desHdr >>KShiftDesType8;
966 TInt desHdrLen = LengthLookup[desType];
969 OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT5, this, KErrBadDescriptor );
970 return KErrBadDescriptor;
974 pagingDevice->iMountInfoDataLock = ThePinObjectAllocator->AcquirePinObject();
975 pagingDevice->iMountInfoDescHdrLock = ThePinObjectAllocator->AcquirePinObject();
976 pagingDevice->iMountInfoDescLenLock = ThePinObjectAllocator->AcquirePinObject();
978 if (pagingDevice->iMountInfoDataLock == NULL ||
979 pagingDevice->iMountInfoDescHdrLock == NULL ||
980 pagingDevice->iMountInfoDescLenLock == NULL)
982 UnlockMountInfo(aPrimaryMedia); // tidy up
983 OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT6, this, KErrNoMemory );
988 // First pin the descriptor header
989 DPinObjectAllocator::SVirtualPinContainer* lock;
990 lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock;
991 r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) (TUint8*) aReq.RemoteDes(), desHdrLen, pT);
994 UnlockMountInfo(aPrimaryMedia); // tidy up
995 OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT7, this, KErrNoMemory );
1001 // For EBufCPtr-type descriptors, need to pin the extra length before the buffer (!)
1002 lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock;
1003 if (desType == EBufCPtr)
1005 TLinAddr extraLenAddr = TLinAddr(desAddress) - aReq.RemoteDesOffset() - sizeof(TUint32);
1006 r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) (TUint8*) extraLenAddr, sizeof(TUint32), pT);
1009 UnlockMountInfo(aPrimaryMedia); // tidy up
1010 OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT8, this, KErrNoMemory );
1011 return KErrNoMemory;
1016 // Now pin the descriptor contents
1017 lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock;
1018 r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) desAddress, length, pT);
1021 UnlockMountInfo(aPrimaryMedia); // tidy up
1022 OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT9, this, KErrNoMemory );
1023 return KErrNoMemory;
1026 OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT10, this, KErrNone );
1031 void DLocalDrive::UnlockMountInfo(DPrimaryMediaBase& aPrimaryMedia)
1033 OstTrace1(TRACE_FLOW, DLOCALDRIVE_UNLOCKMOUNTINFO_ENTRY, "> DLocalDrive::UnlockMountInfo;aPrimaryMedia=%x", (TUint) &aPrimaryMedia);
1035 DMediaPagingDevice* pagingDevice = aPrimaryMedia.iBody->iPagingDevice;
1036 if (pagingDevice == NULL || pagingDevice->iMountInfoDataLock == NULL)
1038 OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT1, this );
1043 if (pagingDevice->iMountInfoDataLock)
1045 Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock)->iObject);
1046 ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock);
1047 pagingDevice->iMountInfoDataLock = NULL;
1050 if (pagingDevice->iMountInfoDescHdrLock)
1052 Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock)->iObject);
1053 ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock);
1054 pagingDevice->iMountInfoDescHdrLock = NULL;
1057 if (pagingDevice->iMountInfoDescLenLock)
1059 Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock)->iObject);
1060 ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock);
1061 pagingDevice->iMountInfoDescLenLock = NULL;
1064 OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT2, this );
1066 #endif // __DEMAND_PAGING__
1068 void DLocalDrive::NotifyChange(DPrimaryMediaBase& aPrimaryMedia, TBool aMediaChange)
1070 OstTraceExt2( TRACE_FLOW, DLOCALDRIVE_NOTIFYCHANGE_ENTRY, "> DLocalDrive::NotifyChange;aPrimaryMedia=%x;aMediaChange=%d", (TUint) &aPrimaryMedia, aMediaChange );
1071 #ifndef __DEMAND_PAGING__
1075 // Complete any notification request on media change or power down
1079 NKern::LockSystem();
1080 if (iCleanup.iThread)
1082 pC=iCleanup.iThread;
1085 NKern::UnlockSystem();
1089 // if change not yet queued, queue it now
1090 if (iNotifyChangeRequest->IsReady())
1092 *((TBool*) iNotifyChangeRequest->Buffer()) = b;
1093 Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrNone);
1095 // If change has not even been requested by the client, maintain the pre-wdp behaviour
1096 // and write data immediately back to client (possibly taking a page fault)
1097 // N.B. Must NOT do this on data paging media
1098 #ifdef __DEMAND_PAGING__
1099 else if (!DataPagingDfcQ(&aPrimaryMedia))
1104 Kern::ThreadRawWrite(pC, iNotifyChangeRequest->DestPtr(), &b, sizeof(b), NULL);
1109 OstTraceFunctionExit1( DLOCALDRIVE_NOTIFYCHANGE_EXIT, this );
1112 TLocalDriveCleanup::TLocalDriveCleanup()
1116 // This will be called when the original client thread exits
1117 // It is called in the context of the exiting thread with the system locked.
1118 void TLocalDriveCleanup::Cleanup()
1120 DLocalDrive& d=LocalDrive();
1121 d.iNotifyChangeRequest=NULL;
1122 DThread* pC=iThread;
1125 NKern::UnlockSystem();
1126 pC->Close(NULL); // balances Open() in DoCreate
1127 NKern::LockSystem();
1130 /********************************************
1131 * Local drive request class
1132 ********************************************/
1135 Reads data from the descriptor specified in the request, from the requesting
1138 This is used by the media driver to read data from a descriptor in the
1139 requesting thread. The remote data is copied into the specified descriptor,
1140 starting at the specified offset within that descriptor's data area.
1142 @param aDes The target descriptor into which data from the remote thread
1144 @param anOffset The offset within the target descriptor data area, where data
1145 from the remote thread is to be put. Note that this parameter
1146 may be useful when write operations to the media must be broken
1147 up into smaller chunks than the length requested.
1149 @return KErrNone,if successful, otherwise one of the other
1150 system-wide error codes.
1152 @see Kern::ThreadDesRead()
1154 EXPORT_C TInt TLocDrvRequest::ReadRemote(TDes8* aDes, TInt anOffset)
1156 OstTraceFunctionEntry1( TLOCDRVREQUEST_READREMOTE_ENTRY, this );
1158 DThread* pT=RemoteThread();
1162 #ifdef __DEMAND_PAGING__ // only if driver has its own thread, we don't support paging in MD which run in the context of their clients
1163 if (Flags() & ETClientBuffer)
1165 r = Kern::ThreadBufRead(pT, (TClientBuffer*) RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0);
1166 OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTE_EXIT1, this, r );
1170 __ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT());
1172 r = Kern::ThreadDesRead(pT,RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0);
1173 OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTE_EXIT2, this, r );
1181 Reads data from an arbitrary descriptor in the requesting thread's process.
1183 This is used by the media driver to read data from a descriptor in the
1186 NB This is NOT supported on datapaging media as there is no guarantee
1187 that the remote descriptor won't be paged out. If this function is called and
1188 data-paging is enabled the kernel will fault in debug mode and return
1189 KErrNotSupported in release mode.
1191 @param aSrc A pointer to the source descriptor in the requesting thread's
1193 @param aDes The target descriptor into which data from the remote thread
1196 @return KErrNone,if successful,
1197 KErrNotSupported if data-paging is enabled
1198 otherwise one of the other system-wide error codes.
1200 @see Kern::ThreadDesRead()
1202 EXPORT_C TInt TLocDrvRequest::ReadRemote(const TAny* aSrc, TDes8* aDes)
1204 OstTraceFunctionEntry1( TLOCDRVREQUEST_READ_REMOTE_ENTRY, this );
1205 if (Flags() & TLocDrvRequest::EKernelBuffer)
1207 aDes->Copy(* (TDesC8*) aSrc);
1212 DThread* pT=RemoteThread();
1216 #ifdef __DEMAND_PAGING__
1217 __ASSERT_DEBUG(!DataPagingDfcQ(Drive()->iPrimaryMedia), LOCM_FAULT());
1219 if (DataPagingDfcQ(Drive()->iPrimaryMedia))
1221 OstTraceFunctionExitExt( TLOCDRVREQUEST_READ_REMOTE_EXIT1, this, KErrNotSupported );
1222 return KErrNotSupported;
1226 r = Kern::ThreadDesRead(pT,aSrc,*aDes,0,KChunkShiftBy0);
1227 OstTraceFunctionExitExt( TLOCDRVREQUEST_READ_REMOTE_EXIT2, this, r );
1235 Reads raw data from the requesting thread's process.
1237 This is used by the media driver to read raw data from a location in requesting
1238 thread's address space. The remote data is copied into the specified
1241 @param aDest A pointer to the buffer where the data is to be written.
1242 @param aSize The number of bytes to read.
1244 @return KErrNone,if successful, otherwise one of the other
1245 system-wide error codes.
1247 @see Kern::ThreadRawRead()
1249 EXPORT_C TInt TLocDrvRequest::ReadRemoteRaw(TAny* aDest, TInt aSize)
1251 OstTraceFunctionEntry1( TLOCDRVREQUEST_READREMOTERAW_ENTRY, this );
1252 if (Flags() & TLocDrvRequest::EKernelBuffer)
1254 (void)memcpy(aDest, (TAny*) RemoteDes(), aSize);
1259 DThread* pT=RemoteThread();
1263 #ifdef __DEMAND_PAGING__
1264 __ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT());
1267 r = Kern::ThreadRawRead(pT,RemoteDes(),aDest,aSize);
1268 OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTERAW_EXIT, this, r );
1274 Writes data to a descriptor in the requesting thread's process.
1276 This is used by the media driver to write data to a descriptor in the requesting
1277 thread. Data is copied from the specified descriptor, starting at the specified
1278 offset within that descriptor's data area.
1280 @param aDes The source descriptor from which data is to be written to
1283 @param anOffset The offset within the source descriptor data area, from where data
1284 is to be written to the remote thread. Note that this parameter
1285 may be useful when read operations from the media must be broken
1286 up into smaller chunks than the length requested.
1288 @return KErrNone,if successful, otherwise one of the other
1289 system-wide error codes.
1291 @see Kern::ThreadDesWrite()
1293 EXPORT_C TInt TLocDrvRequest::WriteRemote(const TDesC8* aDes, TInt anOffset)
1295 OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITEREMOTE_ENTRY, this );
1297 DThread* pC=Client();
1298 DThread* pT=RemoteThread();
1302 #ifdef __DEMAND_PAGING__
1303 if (Flags() & ETClientBuffer)
1305 r = Kern::ThreadBufWrite(pT, (TClientBuffer*) RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC);
1306 OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT1, this, r );
1310 r = Kern::ThreadDesWrite(pT,RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC);
1311 OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT2, this, r );
1317 Writes raw data to the requesting thread's process.
1319 This is used by the media driver to write raw data to a location in the
1320 requesting thread's address space.
1322 @param aSrc The source addres from which data is to be written to
1325 @param aSize The number of bytes to write.
1327 @return KErrNone,if successful, otherwise one of the other
1328 system-wide error codes.
1330 @see Kern::ThreadRawWrite()
1332 EXPORT_C TInt TLocDrvRequest::WriteRemoteRaw(const TAny* aSrc, TInt aSize)
1334 OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITEREMOTERAW_ENTRY, this );
1336 DThread* pC=Client();
1337 DThread* pT=RemoteThread();
1341 #ifdef __DEMAND_PAGING__
1342 __ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT());
1344 r = Kern::ThreadRawWrite(pT,RemoteDes(),aSrc,aSize,pC);
1345 OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTERAW_EXIT, this, r );
1350 TInt TLocDrvRequest::ProcessMessageData(TAny* aPtr)
1352 // Get read/write parameters from client and open remote thread
1355 OstTraceFunctionEntry1( TLOCDRVREQUEST_PROCESSMESSAGEDATA_ENTRY, this );
1356 RemoteThread()=NULL;
1357 DThread& t=Kern::CurrentThread();
1358 TLocalDriveMessageData d;
1359 kumemget32(&d,aPtr,sizeof(d));
1360 OstTrace1( TRACE_INTERNALS, TLOCDRVREQUEST_PROCESSMESSAGEDATA, "Message handle=%d", d.iHandle );
1361 if (d.iHandle!=KLocalMessageHandle && Id()!=DLocalDrive::EFormat)
1363 NKern::LockSystem();
1364 DThread* pT = RMessageK::MessageK(d.iHandle)->iClient;
1365 if (!pT || pT->Open()!=KErrNone)
1367 NKern::UnlockSystem();
1368 OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT1, this, KErrBadHandle );
1369 return KErrBadHandle;
1373 NKern::UnlockSystem();
1377 RemoteDes()=(TAny*)d.iPtr;
1378 RemoteDesOffset()=d.iOffset;
1379 DriverFlags()=d.iFlags;
1380 if (Pos()<0 || Length()<0)
1382 OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT2, this, KErrArgument );
1383 return KErrArgument;
1385 OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT3, this, KErrNone );
1389 void TLocDrvRequest::CloseRemoteThread()
1391 OstTraceFunctionEntry1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_ENTRY, this );
1393 if (!RemoteThread())
1395 OstTraceFunctionExit1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_EXIT1, this );
1398 NKern::ThreadEnterCS();
1399 DThread& t=Kern::CurrentThread();
1400 RemoteThread()=NULL;
1401 Kern::SafeClose((DObject*&)t.iExtTempObj,NULL);
1402 NKern::ThreadLeaveCS();
1403 OstTraceFunctionExit1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_EXIT2, this );
1406 EXPORT_C TInt TLocDrvRequest::CheckAndAdjustForPartition()
1408 OstTraceFunctionEntry1( TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION_ENTRY, this );
1409 TLocDrv& d=*Drive();
1410 __KTRACE_OPT(KLOCDRV,Kern::Printf("CheckAndAdjustForPartition drive %d partition len %lx",d.iDriveNumber,d.iPartitionLen));
1411 OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION1, "iDriveNumber=%d; partition length=0x%lx", d.iDriveNumber, (TInt) d.iPartitionLen );
1412 Flags() |= EAdjusted;
1416 case DLocalDrive::ECaps:
1417 case DLocalDrive::EForceMediaChange:
1418 case DLocalDrive::EPasswordLock:
1419 case DLocalDrive::EPasswordUnlock:
1420 case DLocalDrive::EPasswordClear:
1421 case DLocalDrive::EPasswordErase:
1422 case DLocalDrive::EReadPasswordStore:
1423 case DLocalDrive::EWritePasswordStore:
1424 case DLocalDrive::EPasswordStoreLengthInBytes:
1425 case DLocalDrive::EQueryDevice:
1430 case DLocalDrive::EEnlarge:
1431 __KTRACE_OPT(KLOCDRV,Kern::Printf("Enlarge request %lx",Length()));
1432 OstTrace1( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION2, "Enlarge request=0x%lx", Length() );
1433 if (Length()>KMaxTInt)
1438 case DLocalDrive::EReduce:
1439 __KTRACE_OPT(KLOCDRV,Kern::Printf("Reduce request %lx@%lx",Length(),Pos()));
1440 OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION3, "Reduce request length=0x%lx; position=0x%lx", (TUint) Length(), (TUint) Pos() );
1441 if (Pos()+Length()>d.iPartitionLen)
1446 case DLocalDrive::EFormat:
1447 __KTRACE_OPT(KLOCDRV,Kern::Printf("Format request %lx@%lx",Length(),Pos()));
1448 OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION4, "Format request length=0x%lx; position=0x%lx", (TUint) Length(), (TUint) Pos() );
1449 if (!(DriverFlags() & RLocalDrive::ELocDrvWholeMedia))
1451 if (Pos()>d.iPartitionLen)
1457 Int64 left=d.iPartitionLen-Pos();
1460 Pos()+=d.iPartitionBaseAddr;
1470 #ifdef __DEMAND_PAGING__
1471 case DMediaPagingDevice::ERomPageInRequest:
1472 // if the ROM was reported to LOCM then it will also need to be adjusted....
1473 // Otherwise the media driver adjust it internally
1474 case DMediaPagingDevice::ECodePageInRequest:
1475 __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Adjusted Paging read request %lx@%lx",Length(),Pos()));
1476 OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, TLOCDRVREQUESTCHECKANDADJUSTFORPARTITION5, "Adjusted Paging read request length=0x%lx; position=0x%lx", (TUint) Length(), (TUint) Pos());
1477 if (Pos()+Length()>d.iPartitionLen)
1482 Pos()+=d.iPartitionBaseAddr;
1487 default: // read or write or fragment
1488 __KTRACE_OPT(KLOCDRV,Kern::Printf("R/W request %lx@%lx",Length(),Pos()));
1489 OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION6, "Read/Write request length=0x%x; position=0x%x", (TUint) Length(), (TUint) Pos() );
1490 if (DriverFlags() & RLocalDrive::ELocDrvWholeMedia)
1492 if (d.iMedia && d.iMedia->iDriver && Pos()+Length() > d.iMedia->iDriver->iTotalSizeInBytes)
1500 if (Pos()+Length() > d.iPartitionLen)
1505 Pos()+=d.iPartitionBaseAddr;
1509 OstTraceFunctionExitExt( TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION_EXIT, this, r );
1513 /********************************************
1515 ********************************************/
1516 TLocDrv::TLocDrv(TInt aDriveNumber)
1518 OstTraceFunctionEntryExt( TLOCDRV_TLOCDRV_ENTRY, this );
1519 memclr(this, sizeof(TLocDrv));
1520 iDriveNumber=aDriveNumber;
1521 iPartitionNumber=-1;
1522 OstTraceFunctionExit1( TLOCDRV_TLOCDRV_EXIT, this );
1526 Initialises the DMedia entity with the media device number and ID.
1528 @param aDevice The unique ID for this device. This can take one of the
1529 enumerated values defined in TMediaDevice enum.
1531 @param aMediaId The unique ID to associate with this media entity.
1533 @return KErrNone,if successful, otherwise one of the other
1534 system-wide error codes.
1538 EXPORT_C TInt DMedia::Create(TMediaDevice aDevice, TInt aMediaId, TInt)
1540 OstTraceFunctionEntry1( DMEDIA_CREATE_ENTRY, this );
1541 __KTRACE_OPT(KLOCDRV,Kern::Printf("DMedia::Create media %d device %d",aMediaId,aDevice));
1542 OstTraceExt2(TRACE_INTERNALS, DMEDIA_CREATE, "media=%d; device=%d", aMediaId, (TUint) aDevice);
1545 OstTraceFunctionExitExt( DMEDIA_CREATE_EXIT, this, KErrNone );
1549 /********************************************
1550 * Primary Media Class
1551 ********************************************/
1552 void asyncDfc(TAny* aPtr)
1554 OstTraceFunctionEntry0( _ASYNCDFC_ENTRY );
1555 DPrimaryMediaBase* pM=(DPrimaryMediaBase*)aPtr;
1556 if (pM->iState==DMedia::EOpening)
1557 pM->DoOpenMediaDriverComplete(pM->iAsyncErrorCode);
1558 else if (pM->iState==DMedia::EReadPartitionInfo)
1559 pM->DoPartitionInfoComplete(pM->iAsyncErrorCode);
1560 OstTraceFunctionExit0( _ASYNCDFC_EXIT );
1563 void handleMsg(TAny* aPtr)
1565 OstTraceFunctionEntry0( _HANDLEMSG_ENTRY );
1566 DPrimaryMediaBase* primaryMedia=(DPrimaryMediaBase*)aPtr;
1568 for(TLocDrvRequest* m = (TLocDrvRequest*) primaryMedia->iMsgQ.iMessage;
1570 m = (TLocDrvRequest*) primaryMedia->iMsgQ.Poll())
1573 if (!primaryMedia->iMsgQ.iQ.IsEmpty())
1574 __KTRACE_OPT(KLOCDRV, Kern::Printf("TRACE: handleMsg, queue not empty %08X", m));
1576 primaryMedia->HandleMsg(*m);
1578 #ifdef __DEMAND_PAGING__
1579 // don't empty the queue if this media is paging as there
1580 // may be a (higher-priority) paging DFC waiting to run...
1581 if (primaryMedia->iPagingMedia)
1587 primaryMedia->iMsgQ.Receive(); // allow reception of more messages
1588 OstTraceFunctionExit0( _HANDLEMSG_EXIT );
1591 EXPORT_C DPrimaryMediaBase::DPrimaryMediaBase()
1592 : iMsgQ(handleMsg, this, NULL, 1),
1593 iDeferred(NULL, NULL, NULL, 0), // callback never used
1594 iWaitMedChg(NULL, NULL, NULL, 0), // callback never used
1595 iAsyncDfc(asyncDfc, this, 1)
1597 Constructor of DPrimaryMediaBase class.
1598 Initialises the media state as closed.
1601 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DPRIMARYMEDIABASE_ENTRY, this );
1607 EXPORT_C TInt DPrimaryMediaBase::Create(TMediaDevice aDevice, TInt aMediaId, TInt aLastMediaId)
1609 Called from LocDrv::RegisterMediaDevice() function.
1610 Calls DMedia::Create()
1612 @param aDevice Local media ID
1613 @param aMediaId Media Id (unique for a media subsystem)
1614 @param aLastMediaId This indicates number of used media ids+ number of DMedia objects to be associated with the media driver.
1621 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_CREATE_ENTRY, this );
1622 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase::Create media %d-%d device %d",aMediaId,aLastMediaId,aDevice));
1623 OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_CREATE, "aMediaId=%d; aLastMediaId=%d; aDevice=%d ", aMediaId, aLastMediaId, (TUint) aDevice );
1624 TInt r=DMedia::Create(aDevice,aMediaId,0);
1628 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT1, this, r );
1634 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT2, this, KErrNoMemory );
1635 return KErrNoMemory;
1640 #ifdef __DEMAND_PAGING__
1641 TInt pageSize = Kern::RoundToPageSize(1);
1642 iBody->iPageSizeMsk = pageSize-1;
1645 iLastMediaId=aLastMediaId;
1646 if (r==KErrNone && iDfcQ)
1648 iMsgQ.SetDfcQ(iDfcQ);
1649 iDeferred.SetDfcQ(iDfcQ);
1650 iWaitMedChg.SetDfcQ(iDfcQ);
1651 iAsyncDfc.SetDfcQ(iDfcQ);
1653 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT3, this, KErrNone );
1658 EXPORT_C TInt DPrimaryMediaBase::Connect(DLocalDrive* aLocalDrive)
1660 Connects to a local drive
1662 @param aLocalDrive Local drive logical channel abstraction
1664 @pre Kernel must be unlocked
1665 @pre Current thread in critical section
1667 @post Kernel must be unlocked
1669 @return KErrNone, if successful
1670 KErrNotFound, If no PDD matches criteria while getting driver list
1671 KErrNoMemory, If the array could not be expanded at some point while getting driver list or ran out of memory while opening media driver
1672 KErrNotReady, If not ready when trying to open media driver
1673 otherwise, one of the other system wide error codes.
1678 OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_CONNECT_ENTRY, this );
1679 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Connect %O",iMediaId,aLocalDrive));
1680 OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CONNECT, "iMediaId=%d; iDriveNumber=%d", iMediaId, aLocalDrive->iDrive->iDriveNumber );
1686 TThreadMessage& m=Kern::Message();
1688 m.iArg[0]=aLocalDrive;
1689 r=m.SendReceive(&iMsgQ);
1690 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CONNECT_EXIT1, this, r );
1694 // If no DFC queue, must be a fixed media device
1695 // If this is the first connection, open media driver now
1696 // Assume no non-primary media exist on this device
1698 NKern::LockSystem();
1699 TBool first=iConnectionQ.IsEmpty();
1700 iConnectionQ.Add(&aLocalDrive->iLink);
1701 NKern::UnlockSystem();
1704 r=OpenMediaDriver();
1707 NKern::LockSystem();
1708 aLocalDrive->Deque();
1709 NKern::UnlockSystem();
1714 aLocalDrive->iDrive->iMedia=this;
1715 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CONNECT_EXIT2, this, r );
1722 EXPORT_C void DPrimaryMediaBase::Disconnect(DLocalDrive* aLocalDrive)
1724 Disconnects from a local drive
1726 @param aLocalDrive Local drive logical channel abstraction
1728 @pre Kernel must be unlocked
1729 @pre Current thread in critical section
1731 @post Kernel must be unlocked
1736 OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_DISCONNECT_ENTRY, this );
1737 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Disconnect %O",iMediaId,aLocalDrive));
1738 OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_DISCONNECT, "iMediaId=%d; iDriveNumber=%d", iMediaId, aLocalDrive->iDrive->iDriveNumber );
1742 TThreadMessage& m=Kern::Message();
1743 m.iValue=EDisconnect;
1744 m.iArg[0]=aLocalDrive;
1745 m.SendReceive(&iMsgQ);
1746 OstTraceFunctionExit1( DPRIMARYMEDIABASE_DISCONNECT_EXIT1, this );
1750 // If no DFC queue, must be a fixed media device
1751 // If this is the last connection, close media driver now
1752 // Assume no non-primary media exist on this device
1753 DMediaDriver* pD=NULL;
1754 NKern::LockSystem();
1755 aLocalDrive->iDrive->iMedia=NULL;
1756 aLocalDrive->Deque();
1757 if (iConnectionQ.IsEmpty())
1762 NKern::UnlockSystem();
1765 OstTraceFunctionExit1( DPRIMARYMEDIABASE_DISCONNECT_EXIT2, this );
1768 EXPORT_C TInt DPrimaryMediaBase::Request(TLocDrvRequest& aReq)
1770 Issues a local drive request. It is called from TLocDrv::Request() function .
1771 Each local drive request is encapsulated as a TLocDrvRequest- a class derived from TThreadMessage, the kernel message class.
1772 TLocDrvRequest contains information pertaining to the request, including the ID and any associated parameters such as drive position, length and source/destination location.
1773 Passes the request through to the media driver.
1775 @param m Encapsulates the request information received from the client
1777 @pre Enter with kernel unlocked
1779 @post Leave with Kernel unlocked
1781 @return KErrNone,if successful
1782 KErrBadDescriptor, if request encapsulates a bad descriptor
1783 Otherwise, one of the other system wide error codes.
1788 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_REQUEST_ENTRY, this );
1790 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Request(%08x)",iMediaId,&aReq));
1791 __KTRACE_OPT(KLOCDRV,Kern::Printf("this=%x, ReqId=%d, Pos=%lx, Len=%lx, remote thread %O",this,aReq.Id(),aReq.Pos(),aReq.Length(),aReq.RemoteThread()));
1793 OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_REQUEST, "reqId=%d; length=0x%lx; position=0x%lx; remote thread=0x%x", (TInt) aReq.Id(), (TUint) aReq.Length(), (TUint) aReq.Pos(), (TUint) aReq.RemoteThread());
1795 TInt reqId = aReq.Id();
1797 if (reqId == DLocalDrive::ECaps)
1798 DefaultDriveCaps(*(TLocalDriveCapsV2*)aReq.RemoteDes()); // fill in stuff we know even if no media present
1800 TInt r = QuickCheckStatus();
1801 if (r != KErrNone && aReq.Id()!=DLocalDrive::EForceMediaChange && // EForceMediaChange, and
1802 aReq.Id()!=DLocalDrive::EReadPasswordStore && // Password store operations
1803 aReq.Id()!=DLocalDrive::EWritePasswordStore && // do not require the media
1804 aReq.Id()!=DLocalDrive::EPasswordStoreLengthInBytes) // to be ready.)
1806 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT, this, r );
1811 // for ERead & EWrite requests, get the linear address for pinning & DMA
1812 TUint8* linAddress = NULL;
1813 TClientBuffer clientBuffer;
1816 if (reqId == DLocalDrive::ERead || reqId == DLocalDrive::EWrite)
1818 pT = aReq.RemoteThread();
1820 pT = &Kern::CurrentThread(); // e.g. when using TBusLocalDrive directly
1822 // for silly zero-length requests, return immediately, setting the client
1823 // descriptor length to zero if it's a read request
1824 if (aReq.Length() == 0)
1826 DThread* pC = &Kern::CurrentThread();
1828 if (reqId == DLocalDrive::ERead)
1830 TPtrC8 ptr(NULL, 0);
1831 r = Kern::ThreadDesWrite(pT, aReq.RemoteDes(), ptr, aReq.RemoteDesOffset(), KChunkShiftBy0,pC);
1833 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT2, this, r );
1837 clientBuffer.SetFromDescriptor(aReq.RemoteDes(), pT);
1841 TInt r = Kern::ThreadGetDesInfo(pT,aReq.RemoteDes(),length,maxLength,linAddress,EFalse); // get descriptor length, maxlength and linAddress
1844 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT3, this, r );
1847 linAddress+= aReq.RemoteDesOffset();
1849 #ifdef __DEMAND_PAGING__
1850 // NB change in behavior IF DATA PAGING IS ENABLED: TLocDrvRequest::RemoteDes() points
1851 // to a TClientBuffer rather than the client's remote descriptor
1852 if (DataPagingDeviceRegistered)
1854 aReq.RemoteDes() = &clientBuffer;
1855 aReq.Flags() |= TLocDrvRequest::ETClientBuffer;
1862 __TRACE_TIMING(0x10);
1865 #ifdef __DEMAND_PAGING__
1866 // If this is a ROM/Code paging media, pin writes
1867 // If there is a Data paging media registered, pin all requests with descriptors
1868 if ( (DataPagingDeviceRegistered) || (reqId == DLocalDrive::EWrite && RomPagingDfcQ(this)) )
1870 r = PinSendReceive(aReq, (TLinAddr) linAddress);
1873 #endif // __DEMAND_PAGING__
1874 r = SendReceive(aReq, (TLinAddr) linAddress);
1878 // If no DFC queue, must be a fixed media device
1879 // Media driver must already have been opened
1880 // Assume no non-primary media exist on this device
1881 // Just pass request straight through to media driver
1882 r = aReq.CheckAndAdjustForPartition();
1884 r = iDriver->Request(aReq);
1887 #ifdef __DEMAND_PAGING__
1888 // NB change in behavior IF DATA PAGING IS ENABLED: TLocDrvRequest::RemoteDes() points
1889 // to a TClientBuffer rather than the client's remote descriptor
1890 if (reqId == DLocalDrive::ERead && DataPagingDeviceRegistered && r == KErrNone)
1892 r = clientBuffer.UpdateDescriptorLength(pT);
1895 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT4, this, r );
1900 #ifdef __DEMAND_PAGING__
1901 TInt DPrimaryMediaBase::PinSendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress)
1903 OstTraceExt2(TRACE_FLOW, DPRIMARYMEDIABASE_PINSENDRECEIVE_ENTRY, "> DPrimaryMediaBase::PinSendReceive;aReq=%x;aLinAddress=%x;", (TUint) &aReq, (TUint) &aLinAddress );
1905 __ASSERT_DEBUG(ThePinObjectAllocator, LOCM_FAULT());
1908 TInt msgId = aReq.Id();
1913 case DLocalDrive::EControlIO:
1915 TInt controlIoType = aReq.Int3();
1916 switch(controlIoType)
1918 case KLocalMessageHandle:
1919 // ControlIo is not supported if either of the two bare (TAny*) pointers are non-NULL
1920 // as it's not possible to determine what the pointers are pointing at...
1921 if (aReq.Int1() || aReq.Int2())
1923 __KTRACE_OPT(KDATAPAGEWARN, Kern::Printf("Data paging: Naked EControlIO not supported on paging device: fn=%x", aReq.Int0()));
1924 r = KErrNotSupported;
1929 r = SendReceive(aReq);
1933 // if Int3() is > 0, Int1() is a data pointer, and Int3() is a length
1934 if (controlIoType > (TInt) ThePinObjectAllocator->iFragmentGranularity)
1939 if (controlIoType < 0)
1944 r = PinFragmentSendReceive(aReq, (TLinAddr) aReq.Ptr1(), controlIoType);
1950 case DLocalDrive::ERead:
1951 case DLocalDrive::EWrite:
1953 r = PinFragmentSendReceive(aReq, aLinAddress, aReq.Length());
1957 // For all these requests, aReq.RemoteDes() points to a buffer on the stack in DLocalDrive::Request()
1958 // This is a kernel stack & so should be unpaged & not require pinning...
1959 case DLocalDrive::ECaps:
1960 case DLocalDrive::EGetLastErrorInfo:
1961 case DLocalDrive::EQueryDevice:
1962 case DLocalDrive::EPasswordLock:
1963 case DLocalDrive::EPasswordUnlock:
1964 case DLocalDrive::EPasswordClear:
1965 case DLocalDrive::EReadPasswordStore:
1966 case DLocalDrive::EWritePasswordStore:
1967 case DLocalDrive::EPasswordStoreLengthInBytes:
1968 case DLocalDrive::EPasswordErase:
1971 r = SendReceive(aReq);
1973 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_PINSENDRECEIVE_EXIT, this, r );
1977 TInt DPrimaryMediaBase::PinFragmentSendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress, TInt aLength)
1979 OstTraceExt3(TRACE_FLOW, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE_ENTRY, "> DPrimaryMediaBase::PinFragmentSendReceive;aReq=%x;aLinAddress=%x;aLength=%d;", (TUint) &aReq, (TUint) &aLinAddress, aLength );
1981 TLocDrvRequest fragment = aReq; // create a request on the stack for use during fragmentation, pre-fill with the original req args, leave original Kernel message as repository (thread will block, message contents won't change)
1984 // Kern::Printf(">PFSR %02X aReq %08X aLinAddress %08X aLen %08X offset %08X", aReq.Id(), &aReq, aLinAddress, aLength, aReq.RemoteDesOffset());
1986 DThread* pT = aReq.RemoteThread();
1988 pT=&Kern::CurrentThread(); // e.g. when using TBusLocalDrive directly
1990 __KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Fragmenting Read/Write Request(0x%08x) on drive(%d), remote des(0x%x), offset into des(0x%x), original req Length(0x%x)",&aReq,aReq.Drive()->iDriveNumber,(TInt)(aReq.RemoteDes()),aReq.RemoteDesOffset(),aLength));
1991 __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Remote thread(0x%08x), current thread(0x%08x), start of data to write(0x%08x)",aReq.RemoteThread(),&Kern::CurrentThread(),(TInt)aLinAddress));
1992 OstTraceDefExt5(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE1, "Fragmenting Read/Write Request=0x%08x; drive=%d; remote des=0x%x; offset into des=0x%x; original length=0x%x", (TUint) &aReq, (TUint) aReq.Drive()->iDriveNumber, (TInt) (aReq.RemoteDes()), (TInt) aReq.RemoteDesOffset(), (TInt) aLength );
1993 OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE2, "Remote Thread=0x%08x; current Thread=0x%x; start of data to write=0x%08x", (TUint) aReq.RemoteThread(), (TUint) &Kern::CurrentThread(),(TUint)aLinAddress );
1995 // don't want this thread to be terminated until last fragment is sent to MD and mem can be free'd up
1996 NKern::ThreadEnterCS();
1998 __ASSERT_DEBUG(ThePinObjectAllocator, LOCM_FAULT());
2000 TUint fragmentGranularity = ThePinObjectAllocator->iFragmentGranularity;
2001 TInt dataLockResult = 0;
2002 // fragmentation only allowed for read/write requests
2003 __ASSERT_DEBUG(aLength <= (TInt) fragmentGranularity || (aReq.Id() == DLocalDrive::EWrite || aReq.Id() == DLocalDrive::ERead), LOCM_FAULT());
2005 // Pin the client buffer
2007 for (TInt pos = 0; pos < aLength; pos+= pinnedLen, aLinAddress+= pinnedLen)
2012 TInt remainingLen = aLength - pos; // remaining length
2014 // first attempt to pin memory with no pre-allocated buffers (which may fail)
2015 DPinObjectAllocator::SVirtualPinContainer* pinDataObject = ThePinObjectAllocator->AcquirePinObject();
2019 TInt lenToPin = Min(KMaxPinData, remainingLen);
2021 TInt r = Kern::PinVirtualMemory(pinDataObject->iObject, aLinAddress, lenToPin, pT);
2024 pinnedLen = lenToPin;
2028 #ifdef __DEBUG_DEMAND_PAGING__
2029 Kern::Printf("Kern::PinVirtualMemory() error %d", r);
2031 // pin failed, so use preallocated buffer instead
2032 ThePinObjectAllocator->ReleasePinObject(pinDataObject);
2033 pinDataObject = NULL;
2039 ThePinObjectAllocator->PreAllocatedDataLock().LockFragmentation();
2041 TLinAddr start = aLinAddress;
2044 TInt lenToPin = Min((TInt) fragmentGranularity, remainingLen - pinnedLen);
2046 #ifdef __DEBUG_DEMAND_PAGING__
2047 Kern::Printf(">SR PinS Id %d aLinAddress %08X lenToPin %08X offset %08X", aReq.Id(), aLinAddress, lenToPin);
2050 dataLockResult = ThePinObjectAllocator->PreAllocatedDataLock().Lock(pT, start, lenToPin);
2052 #ifdef __DEBUG_DEMAND_PAGING__
2053 Kern::Printf("<SR PinS Id %d aLinAddress %08X lenToPin %08X offset %08X r %d", aReq.Id(), aLinAddress, lenToPin, r);
2057 pinnedLen+= lenToPin;
2059 while (dataLockResult == 0 && pinnedLen < remainingLen);
2061 // if nothing pinned (dataLockResult == 0) or error (dataLockResult <0), release the mutex,
2062 // otherwise (dataLockResult > 0) release it after calling SendReceive()
2063 if (dataLockResult <= 0)
2064 ThePinObjectAllocator->PreAllocatedDataLock().UnlockFragmentation();
2066 #ifdef __DEBUG_DEMAND_PAGING__
2067 if (dataLockResult < 0)
2068 Kern::Printf("DFragmentationPagingLock::Lock() %d", dataLockResult);
2071 if (dataLockResult < 0) // if lock returned an error then give up
2078 // fragment request Id defaults to same as original request
2079 fragment.Id() = aReq.Id();
2080 fragment.Length() = Int64(pinnedLen);
2081 fragment.RemoteDesOffset() = aReq.RemoteDesOffset() + pos;
2082 fragment.Pos() = aReq.Pos() + pos;
2083 fragment.Flags() = aReq.Flags();
2085 __KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Send fragment (0x%08x) type(%d), length(0x%x), offset within original req(0x%x), pos in media(0x%lx)",&fragment,fragment.Id(), pinnedLen, pos, fragment.Pos()));
2086 OstTraceDefExt5(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE3, "Send fragment 0x%08x; type=%d; length=0x%x; offset within original req=0x%x; position in media=0x%lx", (TUint) &fragment, (TInt) fragment.Id(), (TUint) pinnedLen, (TUint) pos, (TUint) fragment.Pos());
2088 #ifdef BTRACE_PAGING_MEDIA
2090 buf[0] = pinnedLen; // fragment length
2091 buf[1] = pos; // offset within original request
2092 buf[2] = fragment.Pos(); // offset in media
2093 buf[3] = (TInt)&pT->iNThread; // thread that issued the original write req
2094 BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedFragmentBegin,&fragment,fragment.Id(),buf,sizeof(buf));
2096 r = SendReceive(fragment, aLinAddress); // only come back here when message (fragment) has been completed
2101 Kern::UnpinVirtualMemory(pinDataObject->iObject);
2102 ThePinObjectAllocator->ReleasePinObject(pinDataObject);
2104 else if (dataLockResult > 0) // pinDataObject = NULL
2106 __ASSERT_DEBUG(dataLockResult == 1, LOCM_FAULT());
2107 ThePinObjectAllocator->PreAllocatedDataLock().Unlock();
2108 ThePinObjectAllocator->PreAllocatedDataLock().UnlockFragmentation();
2111 #ifdef BTRACE_PAGING_MEDIA
2112 BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedFragmentEnd,&fragment,r);
2119 NKern::ThreadLeaveCS();
2121 // Kern::Printf("<PFSR %02X aReq %08X aLinAddress %08X aLen %08X offset %08X", aReq.Id(), &aReq, aLinAddress, aLength, aReq.RemoteDesOffset());
2123 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE_EXIT, this, r );
2127 #endif // __DEMAND_PAGING__
2130 TInt DPrimaryMediaBase::SendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress)
2132 * If a Physical memory helper object is present for given drive,
2133 * then message is routed via helper;
2135 * @return KErrNone, if successful;
2136 * otherwise, one of the other system wide error codes.
2138 * @see TLocDrvRequest::SendReceive()
2139 * @see DDmaHelper::SendReceive()
2142 OstTraceExt2( TRACE_FLOW, DPRIMARYMEDIABASE_SENDRECEIVE_ENTRY, "> DPrimaryMediaBase::SendReceive;aReq=%x;aLinAddress=%x", (TUint) &aReq, (TUint) &aLinAddress );
2144 DDmaHelper* dmaHelper = aReq.Drive()->iDmaHelper;
2146 #ifdef __DEMAND_PAGING__
2153 r = dmaHelper->SendReceive(aReq, aLinAddress);
2156 r = aReq.SendReceive(&iMsgQ);
2158 #ifdef __DEMAND_PAGING__
2162 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_SENDRECEIVE_EXIT, this, r );
2168 EXPORT_C TInt DPrimaryMediaBase::ForceMediaChange(TInt)
2170 Forces a media change.The method can be overridden in the derived classes.
2171 @param mode Media change mode
2173 @return KErrNotSupported, in the default implementation
2174 KErrNone, if successful
2175 Otherwise, one of the other system wide error codes.
2179 // default implementation
2180 return KErrNotSupported;
2183 EXPORT_C TInt DPrimaryMediaBase::InitiatePowerUp()
2185 Initiates Power up sequence
2186 @return KErrCompletion, operation is complete successfully or otherwise
2187 KErrNone, if successful
2188 Otherwise, one of the other system wide error codes.
2192 // default implementation, this is the default implementation.
2193 return KErrCompletion;
2196 EXPORT_C TInt DPrimaryMediaBase::QuickCheckStatus()
2198 Checks the status of the media device, whether the device is present,absent,not ready,etc.
2199 The function can be overridden in the derived classes
2201 @return KErrNone, if successful
2202 Otherwise, one of the other system wide error codes.
2206 // default implementation
2210 EXPORT_C void DPrimaryMediaBase::DefaultDriveCaps(TLocalDriveCapsV2& aCaps)
2212 Fills in the default drive capabilities in TLocalDriveCapsV2 .
2213 It initializes media type of drive as unknown and has to be overridden in the derived class. Called from the Request ( ) function of the same class.
2215 @param aCaps Media drive capability fields. Extension to Capabilities fields(i.e) in addition to TLocalDriveCaps mainly to support Nor flash
2216 @see TLocalDriveCapsV2
2220 // default implementation
2221 // aCaps is zeroed beforehand
2222 aCaps.iType = EMediaUnknown;
2225 EXPORT_C TBool DPrimaryMediaBase::IsRemovableDevice(TInt& /*aSocketNum*/)
2227 Checks whether it is a removable device or not
2228 @param aSocketNum Socket number
2229 @return ETrue=Removable Device
2230 EFalse=Non-Removable device, default implementation
2234 // default implementation
2238 EXPORT_C void DPrimaryMediaBase::HandleMsg(TLocDrvRequest& m)
2240 It handles the drive request encapsulated in TLocDrvRequest depending on the message id.
2242 @param aRequest Encapsulates the request information received from the client
2246 OstTrace1( TRACE_FLOW, DPRIMARYMEDIABASE_HANDLEMSG_ENTRY, "> DPrimaryMediaBase::HandleMsg;m=%x;", (TUint) &m);
2252 DLocalDrive* pD=(DLocalDrive*)m.Ptr0();
2253 iConnectionQ.Add(&pD->iLink);
2254 m.Complete(KErrNone, EFalse);
2255 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT1, this );
2260 DLocalDrive* pD=(DLocalDrive*)m.Ptr0();
2261 TLocDrv* pL=pD->iDrive;
2262 DMedia* media=pL->iMedia;
2263 if (iState==EReady && media && media->iDriver)
2264 media->iDriver->Disconnect(pD,&m);
2268 m.Complete(KErrNone, EFalse);
2270 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT2, this );
2273 case DLocalDrive::EForceMediaChange:
2275 TUint flags = (TUint) m.Pos();
2277 // if KForceMediaChangeReOpenDriver specified wait for power up,
2278 // and then re-open this drive's media driver
2279 __KTRACE_OPT(KLOCDRV, Kern::Printf("EForceMediaChange, flags %08X\n", flags));
2280 if (flags == (TUint) KForceMediaChangeReOpenMediaDriver)
2283 if (!IsRemovableDevice(sock))
2285 CompleteRequest(m, KErrNotSupported);
2286 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT3, this );
2289 // wait for power up and then call DPrimaryMediaBase::DoRequest()
2293 TInt r=ForceMediaChange(flags);
2296 // wait for media change notification to complete message
2297 m.Forward(&iWaitMedChg,EFalse);
2301 if (r==KErrNotSupported || r==KErrCompletion)
2303 CompleteRequest(m, r);
2305 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT4, this );
2308 case DLocalDrive::ECaps:
2309 if (iState==EPoweredDown)
2311 // The media is powered down, but the media driver still exists.
2312 // - Issue the ECaps request without powering the media back up.
2314 __TRACE_TIMING(0x101);
2315 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT5, this );
2320 case DLocalDrive::ERead:
2321 case DLocalDrive::EWrite:
2322 case DLocalDrive::EFormat:
2323 case DLocalDrive::EEnlarge:
2324 case DLocalDrive::EReduce:
2325 case DLocalDrive::EPasswordLock:
2326 case DLocalDrive::EPasswordUnlock:
2327 case DLocalDrive::EPasswordClear:
2328 case DLocalDrive::EPasswordErase:
2329 case DLocalDrive::EControlIO:
2330 case DLocalDrive::EDeleteNotify:
2331 case DLocalDrive::EQueryDevice:
2333 #ifdef __DEMAND_PAGING__
2334 case DMediaPagingDevice::ERomPageInRequest:
2335 case DMediaPagingDevice::ECodePageInRequest:
2338 case DLocalDrive::EGetLastErrorInfo:
2340 DLocalDrive* pD=(DLocalDrive*)m.Ptr0();
2341 TLocDrv* pL=pD->iDrive;
2342 *((TErrorInfo*) m.RemoteDes()) = pL->iLastErrorInfo;
2343 CompleteRequest(m, KErrNone);
2344 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT6, this );
2347 case DLocalDrive::EReadPasswordStore:
2349 TPtr8 pswData ((TUint8*) m.RemoteDes(), (TInt) m.Length());
2350 TInt r = ThePasswordStore->ReadPasswordData(pswData);
2351 m.Length() = pswData.Length();
2352 CompleteRequest(m, r);
2353 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT7, this );
2356 case DLocalDrive::EWritePasswordStore:
2358 TPtrC8 pData((TUint8*) m.RemoteDes(), (TInt) m.Length());
2359 TInt r = ThePasswordStore->WritePasswordData(pData);
2363 CompleteRequest(m, r);
2364 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT8, this );
2368 r = QuickCheckStatus();
2371 // Don't try to power up the device if it's not ready.
2372 // - Note that this isn't an error that needs to be returned to the client.
2373 CompleteRequest(m, KErrNone);
2374 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT9, this );
2380 case DLocalDrive::EPasswordStoreLengthInBytes:
2382 TInt length = ThePasswordStore->PasswordStoreLengthInBytes();
2383 *(TInt*) m.RemoteDes() = length;
2384 CompleteRequest(m, KErrNone);
2385 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT10, this );
2389 CHECK_RET(KErrNotSupported);
2390 CompleteRequest(m, KErrNotSupported);
2391 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT11, this );
2395 __KTRACE_OPT(KFAIL,Kern::Printf("mdrq %d",m.Id()));
2396 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::HandleMsg state %d req %d",iMediaId,iState,m.Id()));
2398 OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_HANDLEMSG2, "iMediaId=%d; iState=%d; req Id=%d", iMediaId, iState, m.Id());
2400 // if media driver already open, pass request through
2404 __TRACE_TIMING(0x101);
2405 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT12, this );
2409 // if open or close in progress, defer this message
2410 if (iState!=EClosed && iState!=EPoweredDown)
2412 #ifdef __DEMAND_PAGING__
2413 if (DMediaPagingDevice::PagingRequest(m))
2415 __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
2416 __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
2417 __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
2419 __KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Deferring PageIn request 0x%08x because opening or closing",&m));
2420 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_HANDLEMSG3, "Deferring PageIn request 0x%08x because opening or closing", &m);
2421 iBody->iPagingDevice->SendToDeferredQ(&m);
2425 m.Forward(&iDeferred,EFalse);
2426 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT13, this );
2430 // nothing is open, so try to open something
2431 __ASSERT_ALWAYS(!iCurrentReq,LOCM_FAULT());
2433 #ifdef __DEMAND_PAGING__
2435 #ifdef BTRACE_PAGING_MEDIA
2436 if (DMediaPagingDevice::PagingRequest(m))
2437 BTraceContext12(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInQuietlyDeferred,&m,iState,m.iValue);
2438 #endif // BTRACE_PAGING_MEDIA
2441 __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
2443 if (DMediaPagingDevice::PagingRequest(m))
2445 __ASSERT_DEBUG(iPagingMedia,LOCM_FAULT());
2446 __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
2447 __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Page request 0x%08x received -> opening MD",&m));
2448 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_HANDLEMSG4, "Page request 0x%08x received; opening MD", &m);
2452 #endif // __DEMAND_PAGING__
2455 if(iState == EClosed)
2457 iState=EPoweringUp1;
2459 else if (iState == EPoweredDown)
2461 iState=EPoweringUp2;
2464 TInt r=InitiatePowerUp();
2465 if (r==KErrNone || r==KErrServerBusy)
2467 // wait for completion of power up request
2468 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT14, this );
2471 if (r==KErrCompletion)
2472 r=KErrNone; // device already powered up
2474 OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT15, this );
2477 EXPORT_C TInt DPrimaryMediaBase::DoRequest(TLocDrvRequest& m)
2479 If the media exists, it tries to get the partition information if not there.
2480 It then passes on the request to the media driver by calling its Request( ) function.
2481 Then it completes the kernel thread message and the reference count of the thread is closed asynchronously.
2483 @param aRequest Encapsulates the request information received from the client
2485 @return KErrNone, if successful
2486 KErrNotReady, if missing partitions on removable media
2487 KErrNotSupported, if missing partitions on fixed media
2488 KErrArgument Out of range argument ,encapsulated in Local drive request , passed while checking and adjusting for partition
2489 KErrEOF, Reached the end of file
2490 KErrBadDescriptor, if request encapsulates a bad descriptor
2491 Otherwise, one of the other system wide error codes.
2495 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOREQUEST_ENTRY, this );
2496 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DPrimaryMediaBase::DoRequest %d",m.Id()));
2497 TLocDrv* pL=m.Drive();
2498 DMedia* media=pL->iMedia;
2501 OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_DOREQUEST, "req Id=%d; length=0x%x; position=0x%x", (TInt) m.Id(), (TInt) m.Length(), (TInt) m.Pos());
2503 // re-open this drive's media driver ?
2504 if (m.iValue == DLocalDrive::EForceMediaChange)
2506 __ASSERT_DEBUG(((TUint) m.Pos()) == (TUint) KForceMediaChangeReOpenMediaDriver, LOCM_FAULT());
2510 TLocDrv* pL = m.Drive();
2511 DMedia* media = pL->iMedia;
2512 if (media && media->iDriver)
2513 CloseMediaDrivers(media);
2516 StartOpenMediaDrivers();
2518 NotifyClients(ETrue,pL);
2519 CompleteRequest(m, r);
2520 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT, this, r );
2524 if (!media || !media->iDriver || iState == EClosed)
2526 // Return KErrNotReady for missing partitions on removable media
2527 // as opposed to KErrNotSupported for missing partitions on fixed media
2528 // since the latter don't exist whereas the former might exist at some time.
2530 r=IsRemovableDevice(sock) ? KErrNotReady : KErrNotSupported;
2536 if(iTotalPartitionsOpened == 0)
2538 UpdatePartitionInfo();
2539 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT2, this, KErrNone );
2542 if (!(m.Flags() & TLocDrvRequest::EAdjusted))
2544 // If this isn't the only partition, don't allow access to the whole media
2545 if (iTotalPartitionsOpened > 1)
2546 m.DriverFlags() &= ~RLocalDrive::ELocDrvWholeMedia;
2547 r=m.CheckAndAdjustForPartition();
2551 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_INTERNALS, DPRIMARYMEDIABASE_DOREQUEST_START, "req Id=%d; Remote Thread=0x%x", (TInt) m.Id(), (TUint) m.RemoteThread());
2552 r=media->iDriver->Request(m);
2556 #ifdef __DEMAND_PAGING__
2557 if (DMediaPagingDevice::PagingRequest(m))
2559 __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
2560 __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
2561 __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
2562 __KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Defer PageIn request 0x%08x",&m));
2563 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOREQUEST2, "Defer PageIn request 0x%08x", &m);
2564 DMediaPagingDevice* pagingdevice=iBody->iPagingDevice;
2566 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
2568 if (id==DMediaPagingDevice::ERomPageInRequest)
2570 NKern::FMWait(&pagingdevice->iInstrumentationLock);
2571 if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ)
2572 pagingdevice->iROMStats.iTotalReDeferrals++;
2573 else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ)
2574 pagingdevice->iROMStats.iTotalSynchDeferredFromMainQ++;
2575 NKern::FMSignal(&pagingdevice->iInstrumentationLock);
2577 else if (m.Flags() & TLocDrvRequest::ECodePaging)
2579 NKern::FMWait(&pagingdevice->iInstrumentationLock);
2580 if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ)
2581 pagingdevice->iCodeStats.iTotalReDeferrals++;
2582 else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ)
2583 pagingdevice->iCodeStats.iTotalSynchDeferredFromMainQ++;
2584 NKern::FMSignal(&pagingdevice->iInstrumentationLock);
2586 else if (m.Flags() & TLocDrvRequest::EDataPaging)
2588 NKern::FMWait(&pagingdevice->iInstrumentationLock);
2589 if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ)
2590 pagingdevice->iDataStats.iTotalReDeferrals++;
2591 else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ)
2592 pagingdevice->iDataStats.iTotalSynchDeferredFromMainQ++;
2593 NKern::FMSignal(&pagingdevice->iInstrumentationLock);
2596 pagingdevice->SendToDeferredQ(&m);
2600 m.Forward(&iDeferred,EFalse);
2603 #if defined(__DEMAND_PAGING__) && defined(_DEBUG)
2604 else if (r == KErrNone && DMediaPagingDevice::PagingRequest(m))
2606 __KTRACE_OPT(KLOCDPAGING,Kern::Printf("PageIn req 0x%08x completing asynchronously",&m));
2607 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOREQUEST3, "PageIn req 0x%08x completing asynchronously", &m);
2613 if (r!=KErrNone && iCurrentReq)
2615 TInt s=(r==KErrCompletion)?KErrNone:r;
2618 #ifdef __DEMAND_PAGING__
2619 // got here because media driver cannot service or defer this request or did service it synchronously
2620 if (DMediaPagingDevice::PagingRequest(m))
2622 __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
2623 __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
2624 __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
2625 __KTRACE_OPT(KLOCDPAGING,Kern::Printf("media driver cannot service or defer PageIn request 0x%08x or serviced it synchronously (%d)",&m, s));
2626 OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOREQUEST4, "Media driver cannot service or defer PageIn request 0x%08x or serviced it synchronously; retval=%d",(TUint) &m, s);
2627 iBody->iPagingDevice->CompleteRequest(&m, s);
2632 CompleteRequest(m, s);
2633 OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_INTERNALS, DPRIMARYMEDIABASE_DOREQUEST_RETURN, "Return req Id=%d; Remote Thread=0x%x; retval=%d", (TInt) m.Id(), (TUint) m.RemoteThread(), (TInt) s);
2637 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT3, this, r );
2641 EXPORT_C void DPrimaryMediaBase::PowerUpComplete(TInt anError)
2643 Called after the device is powered up or there is some error while powering up the device.
2644 If there is an error powering up the devices then it just completes the current running requests with an error
2645 and also completes the outstanding requests on the iDeferred message queue by calling SetClosed( ).
2646 If the device is powered up OK then it either opens the media drivers
2647 and if they are already open then it handles the current/pending requests.
2649 @param anError Error code to be passed on while completing outstanding requests.
2652 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_ENTRY, this );
2653 __KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase(%d)::PowerUpComplete err %d iState %d",iMediaId,anError,iState));
2655 OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_POWERUPCOMPLETE, "iMediaId=%d; anError=%d; iState=%d", iMediaId, anError, iState );
2657 if (anError!=KErrNone)
2659 // error powering up device
2660 if (iState==EPoweringUp1 || iState==EPoweringUp2)
2662 OstTraceFunctionExit1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_EXIT, this );
2666 // Powered up OK - now open media drivers
2667 if (iState==EPoweringUp1)
2670 StartOpenMediaDrivers();
2672 else if (iState==EPoweringUp2)
2674 // media is powered up and ready, so handle the current/pending requests
2675 MediaReadyHandleRequest();
2677 OstTraceFunctionExit1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_EXIT2, this );
2680 void DPrimaryMediaBase::CloseMediaDrivers(DMedia* aMedia)
2682 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_ENTRY, this );
2683 __KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase(%d)::CloseMediaDrivers",iMediaId));
2684 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS1, "DPrimaryMediaBase iMediaId=%d", iMediaId );
2686 // we mustn't ever close the media driver if it's responsible for data paging as re-opening the drive
2687 // would involve memory allocation which might cause deadlock if the kernel heap were to grow
2688 #ifdef __DEMAND_PAGING__
2689 if (DataPagingDfcQ(this))
2691 __KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for data paging media %08X", this));
2692 OstTrace1(TRACE_FLOW, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT1, "CloseMediaDrivers aborting for data paging media 0x%08x", this);
2698 for (i=0; i<KMaxLocalDrives; i++)
2700 TLocDrv* pL=TheDrives[i];
2701 if (pL && pL->iPrimaryMedia==this)
2703 __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",i));
2704 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", i );
2705 if (aMedia == NULL || pL->iMedia == aMedia)
2711 for (i=iLastMediaId; i>=iMediaId; i--)
2713 DMedia* pM=TheMedia[i];
2714 if (aMedia == NULL || pM == aMedia)
2716 DMediaDriver* pD=pM->iDriver;
2718 __KTRACE_OPT(KLOCDRV,Kern::Printf("DMedia[%d] @ %08x Driver @ %08x",i,pM,pD));
2719 OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS3, "MediaId=%d; DMedia=0x%08x; MediaDriver=0x%08x", (TInt) i, (TUint) pM, (TUint) pD );
2724 __KTRACE_OPT(KLOCDRV,Kern::Printf("<DPrimaryMediaBase(%d)::CloseMediaDrivers",iMediaId));
2725 OstTraceFunctionExit1( DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT2, this );
2728 void DPrimaryMediaBase::StartOpenMediaDrivers()
2730 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS_ENTRY, this );
2731 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::StartOpenMediaDrivers",iMediaId));
2732 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS, "DPrimaryMediaBase iMediaId=%d ",iMediaId);
2733 TVersion ver(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
2735 // Get a list of all currently loaded media drivers
2736 // Most media drivers do not make use of the pointer iMountInfo.iInfo when
2737 // their Validate() procedures are called from RPhysicalDeviceArray::GetDriverList().
2738 // However, a group of media drivers sharing the same id (passed in iDevice) may use
2739 // the additional information pointed to by iMountInfo.iInfo to distinguish
2740 // group members. This information is passed when the media driver is registered
2741 // using LocDrv::RegisterMediaDevice().
2742 TInt r=iPhysDevArray.GetDriverList(KLitMediaDriverName,iDevice,iMountInfo.iInfo,ver);
2745 // out of memory or no driver exists
2747 OstTraceFunctionExit1( DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS_EXIT1, this );
2751 // Go through them starting with highest priority
2752 iNextMediaId=iMediaId;
2753 iBody->iPhysDevIndex=iPhysDevArray.Count()-1;
2754 iTotalPartitionsOpened=0;
2755 iMediaDriversOpened=0;
2756 iNextMediaDriver=NULL;
2757 OpenNextMediaDriver();
2758 OstTraceFunctionExit1( DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS_EXIT2, this );
2761 void DPrimaryMediaBase::OpenNextMediaDriver()
2763 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_ENTRY, this );
2764 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::OpenNextMediaDriver, this %x mediaId %d iBody->iPhysDevIndex %d",iNextMediaId, this, iMediaId, iBody->iPhysDevIndex));
2765 OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER, "DPrimaryMediaBase iNextMediaId=%d; this=%x; imediaId=%d; iBody->iPhysDevIndex=%d",iNextMediaId, (TUint) this, iMediaId, iBody->iPhysDevIndex);
2767 TVersion ver(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
2768 SPhysicalDeviceEntry& e=iPhysDevArray[iBody->iPhysDevIndex];
2769 DPhysicalDevice* pD=e.iPhysicalDevice;
2773 DMedia* pM=TheMedia[iNextMediaId];
2774 if (pM && pM->iDriver != NULL)
2776 iNextMediaDriver = pM->iDriver;
2777 DoOpenMediaDriverComplete(KErrNone);
2778 OstTraceFunctionExit1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_EXIT1, this );
2782 // this may be asynchronous
2783 TInt s=pD->Create( (DBase*&)iNextMediaDriver, iMediaId, (TDesC8*) &iMountInfo, ver);
2785 __KTRACE_OPT(KLOCDRV,Kern::Printf("Media:Open-Opening %o(PRI:%d)-%d",pD,e.iPriority,s));
2791 OstTraceFunctionExit1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_EXIT2, this );
2794 // Called when a media driver has responded to the Open request
2795 void DPrimaryMediaBase::DoOpenMediaDriverComplete(TInt anError)
2797 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_ENTRY, this );
2798 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::DoOpenMediaDriverComplete error %d iNextMediaDriver %x",iNextMediaId,anError,iNextMediaDriver));
2799 OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE, "iMediaId=%d; anError=%d; iNextMediaDriver=0x%x", (TInt) iNextMediaId, (TInt) anError, (TUint) iNextMediaDriver);
2802 if (anError!=KErrNone)
2804 DMediaDriver* md = iNextMediaDriver;
2805 iNextMediaDriver = NULL;
2809 if (anError==KErrNotReady || anError==KErrNoMemory)
2811 // if it's not ready or we're out of memory, abort
2812 CloseMediaDrivers();
2814 OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_EXIT1, this );
2817 if (anError==KErrNone)
2819 DMedia* pM=TheMedia[iNextMediaId];
2820 pM->iDriver=iNextMediaDriver;
2821 DPhysicalDevice*& pD=iPhysDevArray[iBody->iPhysDevIndex].iPhysicalDevice;
2822 iNextMediaDriver->iPhysicalDevice=pD;
2823 pD=NULL; // so it won't be closed when we tidy up
2824 ++iMediaDriversOpened;
2828 // if no error, read partition info on media
2829 iState = EReadPartitionInfo;
2831 if (anError == KErrNone)
2833 DMedia* pM=TheMedia[iNextMediaId];
2834 TInt r = pM->iDriver->PartitionInfo(pM->iPartitionInfo);
2837 if (r==KErrCompletion)
2839 DoPartitionInfoComplete(r);
2844 DoPartitionInfoComplete(anError);
2846 OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_EXIT2, this );
2849 void DPrimaryMediaBase::DoPartitionInfoComplete(TInt anError)
2851 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_ENTRY, this );
2852 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::DoPartitionInfoComplete error %d",iNextMediaId,anError));
2854 OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE1, "iNextMediaId=%d; anError=%d", iNextMediaId, anError );
2856 DMedia* pM=TheMedia[iNextMediaId];
2857 if (anError==KErrNone || anError == KErrLocked)
2859 // successfully read partition info
2860 iTotalPartitionsOpened+=pM->PartitionCount();
2864 // couldn't read partition info or driver failed to open
2867 #ifdef __DEMAND_PAGING__
2868 if (DataPagingDfcQ(this))
2870 __KTRACE_OPT(KLOCDRV,Kern::Printf("DoPartitionInfoComplete(%d) Close Media Driver aborted for data paging media %08X", this));
2871 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE2, "Close Media Driver for data paging media 0x%08x", this);
2876 pM->iDriver->Close();
2880 if (anError==KErrNotReady || anError==KErrNoMemory)
2882 // if it's not ready or we're out of memory, or the drive is locked, abort
2883 CloseMediaDrivers();
2885 OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT, this );
2890 // Open next media driver, if there is one
2891 TBool complete = EFalse;
2892 if (++iNextMediaId>iLastMediaId)
2894 if (iBody->iPhysDevIndex==0)
2897 iBody->iPhysDevIndex--;
2900 OpenNextMediaDriver();
2901 OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT2, this );
2905 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase %d All media drivers open & partitions read",iMediaId));
2906 __KTRACE_OPT(KLOCDRV,Kern::Printf("%d media drivers opened",iMediaDriversOpened));
2907 OstTrace1( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE3, "iMediaDriversOpened=%d", iMediaDriversOpened );
2908 if (iMediaDriversOpened==0)
2910 SetClosed(KErrNotSupported);
2911 OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT3, this );
2915 // we are now finished with media driver list
2916 iPhysDevArray.Close();
2918 // Finished reading partition info
2919 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase %d Read partition info complete",iMediaId));
2920 __KTRACE_OPT(KLOCDRV,Kern::Printf("%d total partitions",iTotalPartitionsOpened));
2921 OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE4, "Read partition info complete iMediaId=%d; iPartitionsOpened=%d", iMediaId, iTotalPartitionsOpened );
2922 if (iTotalPartitionsOpened==0)
2924 SetClosed(KErrNotSupported);
2925 OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT4, this );
2929 // work out mapping of drives to partitions/media
2930 TInt totalPartitions=iTotalPartitionsOpened;
2931 TInt id=iMediaId; // start with primary media
2932 TInt partitionsOnThisMedia=PartitionCount();
2935 for (j=0; j<KMaxLocalDrives; j++)
2937 TLocDrv* pD=TheDrives[j];
2938 if (pD && pD->iPrimaryMedia==this)
2940 if (totalPartitions==0)
2945 if (partition==partitionsOnThisMedia)
2949 partitionsOnThisMedia=TheMedia[id]->PartitionCount();
2951 __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d = Media %d Partition %d",j,id,partition));
2952 OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE5, "Local Drive=%d; iMediaId=%d; partition=%d", j, id, partition );
2954 pD->iMedia=TheMedia[id];
2955 pD->iPartitionNumber=partition;
2956 memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry));
2962 // media is now ready - handle current or deferred requests
2963 MediaReadyHandleRequest();
2964 OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT5, this );
2967 void DPrimaryMediaBase::MediaReadyHandleRequest()
2969 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_MEDIAREADYHANDLEREQUEST_ENTRY, this );
2970 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase::MediaReadyHandleRequest() this %x", this));
2973 // now we can process the current request
2974 // careful - thread may have exited while we were powering up
2977 DoRequest(*iCurrentReq); // this sets iCurrentReq=NULL
2980 // see if we can process any other requests concurrently
2982 OstTraceFunctionExit1( DPRIMARYMEDIABASE_MEDIAREADYHANDLEREQUEST_EXIT, this );
2985 void DPrimaryMediaBase::UpdatePartitionInfo()
2987 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_UPDATEPARTITIONINFO_ENTRY, this );
2988 iState=EReadPartitionInfo;
2989 iNextMediaId=iMediaId;
2990 DMedia* pM=TheMedia[iNextMediaId];
2991 TInt r=pM->iDriver->PartitionInfo(pM->iPartitionInfo);
2994 if (r==KErrCompletion)
2996 DoPartitionInfoComplete(r);
2998 OstTraceFunctionExit1( DPRIMARYMEDIABASE_UPDATEPARTITIONINFO_EXIT, this );
3001 void DPrimaryMediaBase::CompleteCurrent(TInt anError)
3003 OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_COMPLETECURRENT_ENTRY, this );
3007 #ifdef __DEMAND_PAGING__
3008 // got here because it was powered down when powering up, or failed powering up or failed opening MD or got media change
3009 if (DMediaPagingDevice::PagingRequest(*iCurrentReq))
3011 __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT());
3012 __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
3013 __ASSERT_ALWAYS( ((iCurrentReq->Flags() & TLocDrvRequest::ECodePaging) == 0) || (iCurrentReq->Drive()->iPagingDrv), LOCM_FAULT());
3015 __KTRACE_OPT2(KLOCDPAGING,KFAIL,Kern::Printf("Got here because it was powered down when powering up, or failed powering up or failed opening MD or got media change"));
3016 OstTraceDef0(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_COMPLETECURRENT, "Completed request due to powered down when powering up, or failed powering up or failed opening MD or got media change");
3017 iBody->iPagingDevice->CompleteRequest(iCurrentReq, anError);
3021 CompleteRequest(*iCurrentReq, anError);
3024 OstTraceFunctionExit1( DPRIMARYMEDIABASE_COMPLETECURRENT_EXIT, this );
3028 void DPrimaryMediaBase::CompleteRequest(TLocDrvRequest& aMsg, TInt aResult)
3030 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_COMPLETEREQUEST_ENTRY, this );
3031 OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_COMPLETEREQUEST1, "TLocDrvRequest Object=0x%x; aResult=%d", (TUint) &aMsg, aResult);
3032 aMsg.Complete(aResult,EFalse);
3033 OstTraceFunctionExit1( DPRIMARYMEDIABASE_COMPLETEREQUEST_EXIT, this );
3036 EXPORT_C void DPrimaryMediaBase::RunDeferred()
3038 Runs deferred Requests. Initiated from DPrimaryMediaBase::PowerUpComplete() function
3039 to see if any other requests can be processed concurrently.
3040 Can also be called from DPrimaryMediaBase::NotifyPowerDown
3041 or DPrimaryMediaBase::NotifyEmergencyPowerDown() function or DMediaDriver::Complete()
3044 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_RUNDEFERRED_ENTRY, this );
3045 // Do nothing if an open or close is in progress - this might be the case, for example,
3046 // if a EForceMediaChange request (with the KForceMediaChangeReOpenMediaDriver flag)
3047 // has recently been processed
3048 if (iState!=EReady && iState!=EClosed && iState!=EPoweredDown)
3050 OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT1, this );
3054 // rerun deferred requests;
3055 #ifdef __DEMAND_PAGING__
3056 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3063 __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT());
3064 if(iBody->iPagingDevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ) // if already emptying deferred page in queue, don't reenter
3066 __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Already emptying deferred queue"));
3067 OstTrace0(TRACE_FLOW, DPRIMARYMEDIABASE_RUNDEFERRED_EXIT2, "< Already emptying deferred queue");
3071 DMediaPagingDevice* pagingdevice=iBody->iPagingDevice;
3072 TLocDrvRequest* pL = (TLocDrvRequest*) pagingdevice->iDeferredQ.Last();
3075 pagingdevice->iEmptyingQ|= DMediaPagingDevice::EDeferredQ; // prevent reentering when already emptying this queue
3076 TLocDrvRequest* pM=NULL;
3077 while (pM != pL && (pM = (TLocDrvRequest*) pagingdevice->iDeferredQ.Poll()) != NULL) // synchronously empty deferred queue but ignore re-deferrals
3079 __ASSERT_ALWAYS( DMediaPagingDevice::PagingRequest(*pL), LOCM_FAULT() );
3081 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3082 (pM->iValue==DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++);
3085 NKern::FMWait(&pagingdevice->iInstrumentationLock);
3086 if(pM->iValue==DMediaPagingDevice::ERomPageInRequest && pagingdevice->iROMStats.iMaxReqsInDeferred<countROM)
3087 pagingdevice->iROMStats.iMaxReqsInDeferred=countROM;
3088 else if ((pM->Flags() & TLocDrvRequest::ECodePaging) && pagingdevice->iCodeStats.iMaxReqsInDeferred<countCode)
3089 pagingdevice->iCodeStats.iMaxReqsInDeferred=countCode;
3090 else if ((pM->Flags() & TLocDrvRequest::EDataPaging) && pagingdevice->iDataStats.iMaxReqsInDeferred<countCode)
3091 pagingdevice->iDataStats.iMaxReqsInDeferred=countCode;
3092 NKern::FMSignal(&pagingdevice->iInstrumentationLock);
3095 __KTRACE_OPT(KLOCDPAGING,Kern::Printf("RunDeferred: process req 0x%08x, last in deferred queue 0x%08x",pM,pL));
3096 OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_RUNDEFERRED2, "process req=0x%08x; last in deferred queue=0x%08x",(TUint) pM, (TUint) pL);
3097 #ifdef BTRACE_PAGING_MEDIA
3098 BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInDeferredReposted,pM,pM->iValue);
3100 // if Page In requests are synchronous this services them all in sequence,
3101 // if they're asynch it re-defers them
3102 DoRequest(*(TLocDrvRequest*)pM);
3104 pagingdevice->iEmptyingQ&= ~DMediaPagingDevice::EDeferredQ;
3107 // the reason we now try an empty the main Page In queue is there is at least one type of Page In request
3108 // serviced synchronously in which case when we empty the deferred Page In queue as above, received Page In
3109 // requests are left in the main queue (not deferred) and we don't want to start processing deferred normal
3110 // requests before these Page In requests. If all deferred normal requests are synchronous, the received Page
3111 // In requests will have to wait until all are serviced. NB: requests may be deferred even if the MD services
3112 // all requests synchronously, but runs background tasks that cannot be interrupted. In this last case the
3113 // normal deferred queue may have some very long latency requests.
3114 if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ) // already emptying main Page In queue, skip (any Page In requests will be deferred)
3116 __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Already emptying main queue"));
3117 OstTrace0(TRACE_FLOW, DPRIMARYMEDIABASE_RUNDEFERRED_EXIT3, "< Already emptying main queue");
3121 TLocDrvRequest* pM=NULL;
3122 if (!pagingdevice->iMainQ.iReady) // if it's ready, then queue is empty
3124 pM = (TLocDrvRequest*) pagingdevice->iMainQ.iMessage;
3125 pagingdevice->iMainQ.iMessage = NULL;
3127 pM = (TLocDrvRequest*) pagingdevice->iMainQ.Poll();
3130 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3131 countROM = countCode=0;
3135 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3136 __e32_atomic_add_ord32(&pagingdevice->iROMStats.iTotalSynchEmptiedMainQ, 1);
3138 pagingdevice->iEmptyingQ|=DMediaPagingDevice::EMainQ;
3139 for ( ; pM != NULL; pM = (TLocDrvRequest*) pagingdevice->iMainQ.Poll())
3141 __ASSERT_ALWAYS(DMediaPagingDevice::PagingRequest(*pM), LOCM_FAULT());
3143 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3144 (pM->iValue==DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++);
3147 __KTRACE_OPT(KLOCDPAGING,Kern::Printf("RunDeferred: process req 0x%08x",pM));
3148 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_RUNDEFERRED4, "process req=0x%08x", pM);
3149 DoRequest(*(TLocDrvRequest*)pM); // if Page In requests are synchronous this services them all in sequence, if they're asynch it defers them
3152 pagingdevice->iEmptyingQ&= ~DMediaPagingDevice::EMainQ;
3155 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3156 NKern::FMWait(&pagingdevice->iInstrumentationLock);
3157 pagingdevice->iROMStats.iTotalSynchServicedFromMainQ+=countROM;
3158 if(pagingdevice->iROMStats.iMaxReqsInPending<countROM)
3159 pagingdevice->iROMStats.iMaxReqsInPending=countROM;
3160 pagingdevice->iCodeStats.iTotalSynchServicedFromMainQ+=countCode;
3161 if(pagingdevice->iCodeStats.iMaxReqsInPending<countCode)
3162 pagingdevice->iCodeStats.iMaxReqsInPending=countCode;
3163 NKern::FMSignal(&pagingdevice->iInstrumentationLock);
3166 } // if(iPagingMedia)
3168 if (iRunningDeferred)
3170 OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT4, this );
3173 TMessageBase* pL = iDeferred.Last();
3176 OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT5, this );
3177 return; // no deferred requests
3180 TMessageBase* pM=NULL;
3182 while( pM != pL && (pM=iDeferred.Poll()) != NULL) // stop after processing last one (requests may be re-deferred)
3183 DoRequest(*(TLocDrvRequest*)pM);
3186 OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT6, this );
3189 void DPrimaryMediaBase::SetClosed(TInt anError)
3191 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_SETCLOSED_ENTRY, this );
3192 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::SetClosed error %d",iMediaId,anError));
3193 OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_SETCLOSED, "iMediaId=%d; anError=%d", iMediaId, anError );
3196 // cancel DMediaDriver::OpenMediaDriverComplete() / DMediaDriver::PartitionInfoComplete() DFC
3199 iDeferred.CompleteAll(anError);
3201 #ifdef __DEMAND_PAGING__
3203 iBody->iPagingDevice->iDeferredQ.CompleteAll(anError);
3206 CompleteCurrent(anError);
3210 if (iState==EOpening)
3211 iPhysDevArray.Close();
3215 iWaitMedChg.CompleteAll(KErrNone);
3216 OstTraceFunctionExit1( DPRIMARYMEDIABASE_SETCLOSED_EXIT, this );
3219 void DPrimaryMediaBase::NotifyClients(TBool aMediaChange,TLocDrv* aLocDrv)
3222 // Notify all clients of a media change or power-down event
3225 OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_NOTIFYCLIENTS_ENTRY, this );
3227 SDblQueLink* pL=iConnectionQ.iA.iNext;
3228 while (pL!=&iConnectionQ.iA)
3230 DLocalDrive* pD=_LOFF(pL,DLocalDrive,iLink);
3231 // Issue the notification if the caller wants to notify all drives (aLocDrv == NULL) or
3232 // the specified drive matches this one
3233 if (aLocDrv == NULL || aLocDrv == pD->iDrive)
3234 pD->NotifyChange(*this, aMediaChange);
3237 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYCLIENTS_EXIT, this );
3240 EXPORT_C void DPrimaryMediaBase::NotifyMediaChange()
3242 Closes all media drivers on this device and notifies all connections that media change has occurred
3243 and completes any outstanding requests with KErrNotReady.
3244 This also completes any force media change requests with KErrNone.
3247 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_ENTRY, this );
3248 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaChange state %d",iMediaId,iState));
3250 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE, "iMediaId=%d; iState=%d", iMediaId, iState );
3254 __ASSERT_DEBUG(iBody, LOCM_FAULT());
3256 #ifdef __DEMAND_PAGING__
3257 iBody->iMediaChanges++;
3259 // As data paging media never close, need to ensure the media driver cancels
3260 // any requests it owns as the stack may be powered down by DPBusPrimaryMedia::ForceMediaChange().
3261 // DMediaDriver::NotifyPowerDown() should do this
3262 if(DataPagingDfcQ(this))
3266 // complete any outstanding requests with KErrNotReady
3267 // and any force media change requests with KErrNone
3268 SetClosed(KErrNotReady);
3270 // close all media drivers on this device
3271 if (state>=EOpening)
3273 CloseMediaDrivers();
3276 // notify all connections that media change has occurred
3277 NotifyClients(ETrue);
3279 // complete any force media change requests
3280 iWaitMedChg.CompleteAll(KErrNone);
3281 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_EXIT, this );
3285 EXPORT_C void DPrimaryMediaBase::NotifyPowerDown()
3287 Called on machine power-down. Notifies all media drivers on this device.
3288 If device is not ready then it completes current requests but leaves other outstanding requests
3289 If ready, media driver should complete current request.
3293 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_ENTRY, this );
3294 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyPowerDown state %d",iMediaId,iState));
3296 OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPOWERDOWN, "iMediaId=%d; iState=%d", iMediaId, iState );
3299 TBool allPersistent = ETrue;
3300 TBool allOpen = ETrue;
3302 // notify all media drivers on this device
3303 for (id=iMediaId; id<=iLastMediaId; id++)
3305 DMedia* pM = TheMedia[id];
3306 DMediaDriver* pD = pM->iDriver;
3308 if ((pD) && (iState==EReady || iState==EReadPartitionInfo || iState==EOpening || iState==EPoweringUp2 || iState==ERecovering))
3309 pD->NotifyPowerDown();
3311 if (pD == NULL || pD->iPhysicalDevice == NULL)
3313 else if (pD->iPhysicalDevice->Info(DPhysicalDevice::EMediaDriverPersistent, NULL) != KErrNone)
3315 // We must NOT destroy the media driver if this media is responsible for data paging as
3316 // re-opening the media driver would involve memory allocation which might cause a deadlock
3317 #ifdef __DEMAND_PAGING__
3318 __ASSERT_ALWAYS(!DataPagingDfcQ(this), LOCM_FAULT());
3320 allPersistent = EFalse;
3324 __KTRACE_OPT(KLOCDRV,Kern::Printf("allPersistent(%d)::allOpen %d",allPersistent, allOpen));
3325 OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPOWERDOWN2, "allPersistent=%d; allOpen=%d", allPersistent, allOpen );
3327 if (allPersistent && allOpen && iState == EReady)
3330 // The EPoweredDown state indicates that the media is powered down, but the media driver still exists.
3332 // - This allows the media driver to still be accessed (ie - to determine driver capabilities) without
3333 // the need to power up the device, which can be a lengthy operation.
3335 // - NOTE : This will need re-visiting if we ever re-enable standby mode on a platform that is not capable
3336 // of detecting door interrupts while in standby. In such a scenario, problems could occur as
3337 // the device capabilities may change without the local media subsystem recognising.
3339 iState=EPoweredDown;
3343 CloseMediaDrivers();
3344 SetClosed(KErrNotReady);
3347 NotifyClients(EFalse);
3348 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_EXIT, this );
3352 EXPORT_C void DPrimaryMediaBase::NotifyPsuFault(TInt anError)
3354 Closes all media drivers on this device and completes any outstanding requests with error code.
3355 @param anError Error code to be passed on while closing media drivers and completing outstanding requests.
3359 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYPSUFAULT_ENTRY, this );
3360 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyPsuFault state %d, err %d",iMediaId,iState,anError));
3361 OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPSUFAULT, "iMediaId=%d; iState=%d; anError=%d", iMediaId, iState, anError );
3363 if (iState>=EOpening)
3365 CloseMediaDrivers();
3368 // complete any outstanding requests with error
3370 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPSUFAULT_EXIT, this );
3373 EXPORT_C void DPrimaryMediaBase::NotifyEmergencyPowerDown()
3375 Called on emergency power down. Notifies all media drivers on this device.
3376 If it is not in a ready state then it completes the current request but leaves other outstanding requests.
3377 If it is ready then the media driver should complete the current request.
3378 It closes all media drivers and notifies all clients of a power down event.
3381 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_ENTRY, this );
3382 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyEmergencyPowerDown state %d",iMediaId,iState));
3383 OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN, "iMediaId=%d; iState=%d", iMediaId, iState );
3385 TBool recover=EFalse;
3386 if (iState==EReady && iCritical!=0)
3388 // check if emergency power recovery supported
3395 // else just return KErrAbort
3396 // notify all media drivers on this device
3397 if (iState==EReady || iState==EOpening || iState==EPoweringUp2 || iState==ERecovering)
3400 for (id=iMediaId; id<=iLastMediaId; id++)
3402 DMedia* pM=TheMedia[id];
3403 DMediaDriver* pD=pM->iDriver;
3405 pD->NotifyEmergencyPowerDown();
3411 // complete current request but leave other outstanding requests
3412 // if ready, media driver should complete current request
3413 CompleteCurrent(KErrNotReady);
3415 CloseMediaDrivers();
3416 SetClosed(KErrNotReady);
3417 NotifyClients(EFalse);
3418 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_EXIT, this );
3421 EXPORT_C void DPrimaryMediaBase::NotifyMediaPresent()
3423 Notifies clients of a media change by calling NotifyClients ( ) function to indicate that media is present.
3426 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_ENTRY, this );
3427 NotifyClients(ETrue);
3428 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_EXIT, this );
3431 EXPORT_C TInt DPrimaryMediaBase::DoInCritical()
3433 Flags the media driver as entering a critical part of its processing.
3435 In this context, critical means that the driver must be allowed to complete
3436 its current activity.
3437 For example, a request to power down the device must be deferred until
3438 the driver exits the critical part.
3440 @return KErrNone, if the driver has been successfully flagged as being in
3441 a critical part; otherwise, one of the other system-wide error codes.
3442 The default implementation just returns KErrNone and can be overridden in the derived class
3443 @see DPrimaryMediaBase::DoEndInCritical()
3450 EXPORT_C void DPrimaryMediaBase::DoEndInCritical()
3452 Flags the media driver as leaving a critical part of its processing.
3454 Default implementation does nothing
3455 @see DPrimaryMediaBase::DoEndInCritical()
3460 TInt DPrimaryMediaBase::InCritical()
3462 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_INCRITICAL_ENTRY, this );
3465 TInt r=DoInCritical();
3468 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_INCRITICAL_EXIT1, this, r );
3473 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_INCRITICAL_EXIT2, this, KErrNone );
3477 void DPrimaryMediaBase::EndInCritical()
3479 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_ENDINCRITICAL_ENTRY, this );
3482 OstTraceFunctionExit1( DPRIMARYMEDIABASE_ENDINCRITICAL_EXIT, this );
3485 EXPORT_C void DPrimaryMediaBase::DeltaCurrentConsumption(TInt /*aCurrent*/)
3487 Sets the incremental value of current consumption to aCurrent.
3488 The default implementation does nothing .
3490 @param aCurrent Delta Current in Milliamps
3493 // default implementation
3496 TInt DPrimaryMediaBase::OpenMediaDriver()
3498 // Synchronous open for devices with no DFC queue (e.g. IRAM)
3501 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_OPENMEDIADRIVER_ENTRY, this );
3503 __KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase:OpenMediaDriver-%d",iMediaId));
3504 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_OPENMEDIADRIVER1, "iMediaId=%d", iMediaId);
3506 TVersion ver(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
3508 // Get a list of all currently loaded media drivers
3509 // Most media drivers do not make use of the pointer iMountInfo.iInfo when
3510 // their Validate() procedures are called from RPhysicalDeviceArray::GetDriverList().
3511 // However, a group of media drivers sharing the same id (passed in iDevice) may use
3512 // the additional information pointed to by iMountInfo.iInfo to distinguish
3513 // group members. This information is passed when the media driver is registered
3514 // using LocDrv::RegisterMediaDevice().
3515 TInt r=iPhysDevArray.GetDriverList(KLitMediaDriverName,iDevice,iMountInfo.iInfo,ver);
3518 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_OPENMEDIADRIVER_EXIT1, this, r );
3521 // Go through them starting with highest priority
3522 TInt totalPartitions=0;
3523 TInt c=iPhysDevArray.Count(); // can't be zero
3526 for (iNextMediaId=iMediaId; i>=0 && iNextMediaId<=iLastMediaId && r!=KErrNotReady; i--)
3528 DPhysicalDevice* pD=iPhysDevArray[i].iPhysicalDevice;
3529 DMediaDriver *pM=NULL;
3531 // try to open media driver
3532 TInt s=pD->Create( (DBase*&)pM, iMediaId, NULL, ver);
3534 __KTRACE_OPT(KLOCDRV,Kern::Printf("Media:Open-Opening %o(PRI:%d)-%d",pD,iPhysDevArray[i].iPriority,s));
3535 OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_OPENMEDIADRIVER2, "Media:Open-Opening 0x%x iPriority=%d; retval=%d", (TUint) pD, (TUint) iPhysDevArray[i].iPriority, (TUint) s);
3536 if (s!=KErrNone && pM)
3541 if (s==KErrNotReady)
3543 r=KErrNotReady; // If it isn't ready - nothing will open.
3546 if (s==KErrNoMemory)
3548 r=KErrNoMemory; // If we are out of memory, give up now
3553 // Found a media driver for this device - check for valid partitions.
3554 DMedia* media=TheMedia[iNextMediaId];
3555 s=pM->PartitionInfo(media->iPartitionInfo);
3560 pM->iPhysicalDevice=pD;
3561 iPhysDevArray[i].iPhysicalDevice=NULL; // so it won't be closed when we tidy up
3562 totalPartitions+=media->PartitionCount();
3569 // we are now finished with media driver list
3570 iPhysDevArray.Close();
3572 // if driver opened OK, work out mapping of drives to partitions/media
3575 TInt id=iMediaId; // start with primary media
3576 TInt partitionsOnThisMedia=PartitionCount();
3579 for (j=0; j<KMaxLocalDrives; j++)
3581 TLocDrv* pD=TheDrives[j];
3582 if (pD && pD->iPrimaryMedia==this)
3584 if (totalPartitions==0)
3589 if (partition==partitionsOnThisMedia)
3593 partitionsOnThisMedia=TheMedia[id]->PartitionCount();
3595 pD->iMedia=TheMedia[id];
3596 pD->iPartitionNumber=partition;
3597 memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry));
3604 __KTRACE_OPT(KLOCDRV,Kern::Printf("<DPrimaryMediaBase:OpenMediaDriver-%d",r));
3605 OstTraceFunctionExitExt( DPRIMARYMEDIABASE_OPENMEDIADRIVER_EXIT2, this, r );
3609 #ifdef __DEMAND_PAGING__
3610 // RequestCountInc()
3612 // Counts the number of outstanding requests
3613 // For data-paging media, calls DPagingDevice::NotifyBusy() when count goes positive
3615 void DPrimaryMediaBase::RequestCountInc()
3617 __ASSERT_DEBUG(iBody, LOCM_FAULT());
3618 TInt oldVal = (TInt) __e32_atomic_add_ord32(&iBody->iRequestCount, (TUint) 1);
3619 //Kern::Printf("RCINC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal);
3621 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTINC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal );
3623 if (oldVal == 0 && iBody->iPagingDevice)
3625 //Kern::Printf("RCINC: NotifyBusy()");
3626 iBody->iPagingDevice->NotifyBusy();
3630 // RequestCountDec()
3632 // Counts the number of outstanding requests
3633 // For data-paging media, calls DPagingDevice::NotifyIdle() when count reaches zero
3635 void DPrimaryMediaBase::RequestCountDec()
3637 __ASSERT_DEBUG(iBody, LOCM_FAULT());
3638 TInt oldVal = (TInt) __e32_atomic_add_ord32(&iBody->iRequestCount, (TUint) -1);
3639 //Kern::Printf("RCDEC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal);
3641 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTDEC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal );
3643 if (oldVal == 1 && iBody->iPagingDevice)
3645 //Kern::Printf("RCDEC: NotifyIdle()");
3646 iBody->iPagingDevice->NotifyIdle();
3648 __ASSERT_DEBUG(iBody->iRequestCount >= 0, LOCM_FAULT());
3650 #endif // __DEMAND_PAGING__
3652 TPartitionInfo::TPartitionInfo()
3657 memclr(this, sizeof(TPartitionInfo));
3660 #ifdef __DEMAND_PAGING__
3662 void pageInDfc(TAny* aPtr)
3664 OstTraceFunctionEntry0( _PAGEINDFC_ENTRY );
3665 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("pageInDfc"));
3666 DPrimaryMediaBase* primaryMedia=(DPrimaryMediaBase*)aPtr;
3667 __ASSERT_ALWAYS(primaryMedia && primaryMedia->iPagingMedia && primaryMedia->iBody->iPagingDevice,LOCM_FAULT());
3668 DMediaPagingDevice* pagingdevice=primaryMedia->iBody->iPagingDevice;
3670 TLocDrvRequest* m = (TLocDrvRequest*) pagingdevice->iMainQ.iMessage;
3671 pagingdevice->iMainQ.iMessage = NULL;
3673 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3675 __e32_atomic_add_ord8(&pagingdevice->iROMStats.iTotalRunDry, 1);
3678 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3683 for ( ; m != NULL; m = (TLocDrvRequest*) pagingdevice->iMainQ.Poll())
3685 __ASSERT_ALWAYS(DMediaPagingDevice::PagingRequest(*m), LOCM_FAULT());
3687 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3688 (m->iValue == DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++);
3690 __KTRACE_OPT(KLOCDPAGING, Kern::Printf("pageInDfc: process request 0x%08x, last in queue 0x%08x",m, pagingdevice->iMainQ.Last()) );
3691 OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, PAGEINDFC2, "process request=0x%08x; last in queue=0x%08x",(TUint) m, (TUint) pagingdevice->iMainQ.Last());
3693 primaryMedia->HandleMsg(*m);
3696 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3697 NKern::FMWait(&pagingdevice->iInstrumentationLock);
3698 if (pagingdevice->iROMStats.iMaxReqsInPending<countROM)
3699 pagingdevice->iROMStats.iMaxReqsInPending=countROM;
3700 if (pagingdevice->iCodeStats.iMaxReqsInPending<countCode)
3701 pagingdevice->iCodeStats.iMaxReqsInPending=countCode;
3702 NKern::FMSignal(&pagingdevice->iInstrumentationLock);
3705 pagingdevice->iMainQ.Receive(); // allow reception of more messages
3706 OstTraceFunctionExit0( _PAGEINDFC_EXIT );
3709 DMediaPagingDevice::DMediaPagingDevice(DPrimaryMediaBase* aPtr)
3710 : iMainQ(pageInDfc, aPtr, NULL, KMaxDfcPriority),
3711 iDeferredQ(NULL, NULL, NULL, 0), // callback never used
3713 iInstrumentationLock()
3714 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3715 ,iServicingROM(NULL), iServicingCode(NULL)
3718 OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_CONSTRUCTOR_ENTRY, this );
3719 iPrimaryMedia = aPtr;
3720 if (iPrimaryMedia->iDfcQ) // media driver has its own thread
3722 iMainQ.SetDfcQ(iPrimaryMedia->iDfcQ);
3724 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3725 memclr((TAny*)&iROMStats,sizeof(SMediaROMPagingConcurrencyInfo)+sizeof(SMediaCodePagingConcurrencyInfo));
3727 #ifdef __DEMAND_PAGING_BENCHMARKS__
3728 iROMBenchmarkData.iCount=iROMBenchmarkData.iTotalTime=iROMBenchmarkData.iMaxTime=0;
3729 iROMBenchmarkData.iMinTime = KMaxTInt;
3730 iCodeBenchmarkData.iCount=iCodeBenchmarkData.iTotalTime=iCodeBenchmarkData.iMaxTime=0;
3731 iCodeBenchmarkData.iMinTime = KMaxTInt;
3732 iDataInBenchmarkData.iCount=iDataInBenchmarkData.iTotalTime=iDataInBenchmarkData.iMaxTime=0;
3733 iDataInBenchmarkData.iMinTime = KMaxTInt;
3734 iDataOutBenchmarkData.iCount=iDataOutBenchmarkData.iTotalTime=iDataOutBenchmarkData.iMaxTime=0;
3735 iDataOutBenchmarkData.iMinTime = KMaxTInt;
3739 OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_CONSTRUCTOR_EXIT, this );
3742 DMediaPagingDevice::~DMediaPagingDevice()
3744 OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_DESTRUCTOR_ENTRY, this );
3746 if (iMountInfoDataLock)
3747 ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDataLock);
3749 if (iMountInfoDescHdrLock)
3750 ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDescHdrLock);
3752 if (iMountInfoDescLenLock)
3753 ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDescLenLock);
3754 OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_DESTRUCTOR_EXIT, this );
3758 void DMediaPagingDevice::SendToMainQueueDfcAndBlock(TThreadMessage* aMsg)
3760 OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_SENDTOMAINQUEUEDFCANDBLOCK_ENTRY, this );
3761 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("Send request 0x%08x to main queue",aMsg));
3762 __ASSERT_ALWAYS(aMsg->iState==TMessageBase::EFree,LOCM_FAULT()); // check that message was previously completed or never queued
3764 // if drive supports DMA, turn on Physical memory flag & sync memory
3765 TLocDrvRequest& m=*(TLocDrvRequest*)(aMsg);
3767 TLinAddr addr = (TLinAddr) m.RemoteDes();
3768 TInt len = I64LOW(m.Length());
3770 TBool needSyncAfterRead = EFalse;
3771 if (m.Drive()->iDmaHelper)
3773 m.Flags() |= TLocDrvRequest::EPhysAddr;
3774 if (m.Id() == DLocalDrive::EWrite)
3776 Cache::SyncMemoryBeforeDmaWrite(addr, len);
3780 Cache::SyncMemoryBeforeDmaRead(addr, len);
3781 needSyncAfterRead = ETrue;
3785 // Count the number of outstanding requests if this is the data-paging media, so that
3786 // we can call DPagingDevice::NotifyBusy() / DPagingDevice::NotifyIdle()
3787 if ((m.Flags() & TLocDrvRequest::EBackgroundPaging) == 0)
3788 iPrimaryMedia->RequestCountInc();
3790 aMsg->SendReceive(&iMainQ);
3792 #ifdef __DEMAND_PAGING__
3793 if ((m.Flags() & TLocDrvRequest::EBackgroundPaging) == 0)
3794 iPrimaryMedia->RequestCountDec();
3797 if (needSyncAfterRead)
3799 Cache::SyncMemoryAfterDmaRead(addr, len);
3803 // come back here when request is completed
3804 __ASSERT_DEBUG(aMsg->iState==TMessageBase::EFree,LOCM_FAULT()); // check message has been completed
3805 OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_SENDTOMAINQUEUEDFCANDBLOCK_EXIT, this );
3808 void DMediaPagingDevice::SendToDeferredQ(TThreadMessage* aMsg)
3810 OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_SENDTODEFERREDQ_ENTRY, this );
3811 // This queue is only accessed from MD thread
3812 __ASSERT_ALWAYS(aMsg->iState==TMessageBase::EAccepted,LOCM_FAULT()); // check that message was previously dequeued
3813 #ifdef BTRACE_PAGING_MEDIA
3814 if(iEmptyingQ&DMediaPagingDevice::EDeferredQ) // already deferring
3815 BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInReDeferred,aMsg,aMsg->iValue);
3817 BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInDeferred,aMsg,aMsg->iValue);
3820 aMsg->Forward(&iDeferredQ, EFalse);
3821 OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_SENDTODEFERREDQ_EXIT, this );
3825 void DMediaPagingDevice::CompleteRequest(TThreadMessage* aMsg, TInt aResult)
3827 OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_COMPLETEREQUEST_ENTRY, this );
3828 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::CompleteRequest, request 0x%08x result %d", aMsg, aResult));
3829 __ASSERT_DEBUG(aMsg->iState==TMessageBase::EAccepted,LOCM_FAULT());
3831 #ifdef BTRACE_PAGING_MEDIA
3832 BTraceContext12(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInPagedIn,aMsg,aResult,aMsg->iValue);
3835 iPrimaryMedia->CompleteRequest(*((TLocDrvRequest*) aMsg), aResult);
3836 OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_COMPLETEREQUEST_EXIT, this );
3839 TInt DMediaPagingDevice::Read(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt aDrvNumber)
3841 OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_READ_ENTRY, this );
3842 __ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT()); // that would lock up the system, thus better die now
3843 __ASSERT_ALWAYS(aReq,LOCM_FAULT());
3846 #ifdef __DEMAND_PAGING_BENCHMARKS__
3847 TUint32 bmStart = NKern::FastCounter();
3850 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
3851 TUint8* servicingCount;
3852 NKern::FMWait(&iInstrumentationLock);
3853 if(aDrvNumber == EDriveRomPaging) // ROM paging
3855 servicingCount = &iServicingROM;
3857 iROMStats.iTotalConcurrentReqs++;
3858 if(!(++iServicingROM))
3860 iServicingROM=1; // overflow...
3861 iROMStats.iTotalConcurrentReqs=0; // ...reset this
3863 TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
3865 iROMStats.iTotalReqIssuedNonEmptyQ++;
3867 else if (aDrvNumber == EDriveDataPaging) // Data paging
3869 servicingCount = &iServicingDataIn;
3870 if(iServicingDataIn)
3871 iDataStats.iTotalConcurrentReqs++;
3872 if(!(++iServicingDataIn))
3874 iServicingDataIn=1; // overflow...
3875 iDataStats.iTotalConcurrentReqs=0; // ...reset this
3877 TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
3879 iDataStats.iTotalReqIssuedNonEmptyQ++;
3883 servicingCount = &iServicingCode;
3885 iCodeStats.iTotalConcurrentReqs++;
3886 if(!(++iServicingCode))
3888 iServicingCode=1; // overflow...
3889 iCodeStats.iTotalConcurrentReqs=0; // ...reset this
3891 TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
3893 iCodeStats.iTotalReqIssuedNonEmptyQ++;
3895 NKern::FMSignal(&iInstrumentationLock);
3898 TUint offset=aOffset<<iReadUnitShift;
3899 TUint size=aSize<<iReadUnitShift;
3901 #ifdef BTRACE_PAGING_MEDIA
3903 buf[0]=size; // page in request length
3904 buf[1]=aDrvNumber; // local drive number (-1 if ROM)
3905 buf[2]=(TInt)aReq; // address of request object
3906 BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInBegin,aBuffer,offset,buf,sizeof(buf));
3909 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::Read, Req(0x%08x), Buff(0x%x),Offset(%d),Size(%d),DrvNo(%d)",aReq,aBuffer,offset,size,aDrvNumber));
3910 OstTraceDefExt5(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_READ1, "req=0x%08x; aBuffer=0x%x; offset=%d; size=%d; aDrvNumber=%d", (TUint) aReq, (TInt) aBuffer, (TInt) offset, (TUint) size, (TUint) aDrvNumber);
3912 // no DFCQ, media driver executes in the context of calling thread
3913 if (!iPrimaryMedia->iDfcQ)
3915 LOCM_FAULT(); // don't allow paging
3916 OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_READ_EXIT, this, KErrNone );
3917 return KErrNone; // keep compiler happy
3921 TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
3924 #ifdef __DEMAND_PAGING_BENCHMARKS__
3925 SPagingBenchmarkInfo* info = NULL;
3929 // Read from the media and allow for retries in the unlikely event of an error.
3930 const TInt KPageInRetries = 5;
3931 TInt retVal = KErrGeneral;
3932 for (TInt i=0; retVal != KErrNone && i < KPageInRetries; i++)
3934 m.Flags() = TLocDrvRequest::EPaging;
3936 if(aDrvNumber == EDriveRomPaging) // ROM paging
3938 m.Id() = DMediaPagingDevice::ERomPageInRequest;
3939 if (iRomPagingDriveNumber == KErrNotFound)
3941 // ROM partition has not been reported by the media driver
3942 // it is assumed that the media driver will adjust the request accordingly
3943 m.Flags() |= TLocDrvRequest::EAdjusted;
3944 // Use a media drive number so the request reaches the correct media...
3945 m.Drive() = TheDrives[iFirstLocalDriveNumber];
3949 //ROM partition has been reported
3950 //Set drive for use with CheckAndAdjustForPartition
3951 m.Drive() = TheDrives[iRomPagingDriveNumber];
3953 #ifdef __DEMAND_PAGING_BENCHMARKS__
3954 __e32_atomic_add_ord32(&iMediaPagingInfo.iRomPageInCount, (TUint) 1);
3955 info = &iROMBenchmarkData;
3958 else if(aDrvNumber == EDriveDataPaging) // Data paging
3960 m.Id() = DLocalDrive::ERead;
3961 m.Flags() |= TLocDrvRequest::EDataPaging;
3962 m.Drive() = TheDrives[iDataPagingDriveNumber];
3963 #ifdef __DEMAND_PAGING_BENCHMARKS__
3964 __e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageInCount, (TUint) 1);
3965 info = &iDataInBenchmarkData;
3968 else if ((aDrvNumber >=0) && (aDrvNumber<KMaxLocalDrives)) // Code paging
3970 m.Id() = DMediaPagingDevice::ECodePageInRequest;
3971 m.Flags() |= TLocDrvRequest::ECodePaging;
3972 pL=TheDrives[aDrvNumber];
3973 __ASSERT_DEBUG(pL&&(pL->iPrimaryMedia==iPrimaryMedia),LOCM_FAULT()); // valid drive number?
3975 #ifdef __DEMAND_PAGING_BENCHMARKS__
3976 __e32_atomic_add_ord32(&iMediaPagingInfo.iCodePageInCount, (TUint) 1);
3977 info = &iCodeBenchmarkData;
3981 LOCM_FAULT(); // invalid drive number
3983 m.RemoteThread()=NULL;
3985 m.Length()=Int64(size);
3986 m.RemoteDes()=(TAny*)aBuffer;
3987 m.RemoteDesOffset()=0; // pre-aligned
3989 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("ReqId=%d, Pos=0x%lx, Len=0x%lx, remote Des 0x%x",m.Id(),m.Pos(),m.Length(),m.RemoteDes()));
3990 OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_READ2, "reqId=%d; position=0x%lx; length=0x%x; remote Des=0x%x", (TInt) m.Id(), (TUint) m.Pos(), (TUint) m.Length(), (TUint) m.RemoteDes());
3992 __ASSERT_DEBUG(iPrimaryMedia->iBody, LOCM_FAULT());
3993 TInt mediaChanges = iPrimaryMedia->iBody->iMediaChanges;
3995 SendToMainQueueDfcAndBlock(&m); // queues request, sets and opens client thread, queues dfc and blocks thread until request is completed
3998 #ifdef __DEBUG_DEMAND_PAGING__
3999 if (retVal != KErrNone)
4001 Kern::Printf("Pagin Failure %d, retry %d", retVal, i);
4005 // reset retry count if there's ben a media change
4006 if (retVal != KErrNone && mediaChanges != iPrimaryMedia->iBody->iMediaChanges)
4010 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
4011 NKern::FMWait(&iInstrumentationLock);
4012 if (*servicingCount)
4013 (*servicingCount)--;
4014 NKern::FMSignal(&iInstrumentationLock);
4017 #ifdef __DEMAND_PAGING_BENCHMARKS__
4018 TUint32 bmEnd = NKern::FastCounter();
4020 #if !defined(HIGHIGH_RES_TIMER) || defined(HIGH_RES_TIMER_COUNTS_UP)
4021 TInt64 elapsed=bmEnd-bmStart;
4023 TInt64 elapsed=bmStart-bmEnd;
4025 info->iTotalTime += elapsed;
4026 if (elapsed > info->iMaxTime)
4027 info->iMaxTime = elapsed;
4028 if (elapsed < info->iMinTime)
4029 info->iMinTime = elapsed;
4030 #endif // __DEMAND_PAGING_BENCHMARKS__
4031 OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_READ_EXIT2, this, retVal );
4035 TInt DMediaPagingDevice::Write(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TBool aBackground)
4037 OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_WRITE_ENTRY, this );
4038 __ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT()); // that would lock up the system, thus better die now
4039 __ASSERT_ALWAYS(aReq,LOCM_FAULT());
4042 #ifdef __DEMAND_PAGING_BENCHMARKS__
4043 TUint32 bmStart = NKern::FastCounter();
4046 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
4047 NKern::FMWait(&iInstrumentationLock);
4048 if(iServicingDataOut)
4049 iDataStats.iTotalConcurrentReqs++;
4050 if(!(++iServicingDataOut))
4052 iServicingDataOut=1; // overflow...
4053 iDataStats.iTotalConcurrentReqs=0; // ...reset this
4055 TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty();
4057 iDataStats.iTotalReqIssuedNonEmptyQ++;
4058 NKern::FMSignal(&iInstrumentationLock);
4061 TUint offset=aOffset<<iReadUnitShift;
4062 TUint size=aSize<<iReadUnitShift;
4064 #ifdef BTRACE_PAGING_MEDIA
4066 buf[0] = size; // page out request length
4067 buf[1] = (TInt)aReq; // address of request object
4068 BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageOutBegin,aBuffer,offset,buf,sizeof(buf));
4071 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::Write, Req(0x%08x), Buff(0x%x),Offset(%d),Size(%d)",aReq,aBuffer,offset,size));
4072 OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_WRITE1, "req=0x%08x; aBuffer=0x%x; offset=%d; size=%d", (TUint) aReq, (TUint) aBuffer, offset, size);
4074 // no DFCQ, media driver executes in the context of calling thread
4075 if (!iPrimaryMedia->iDfcQ)
4077 LOCM_FAULT(); // don't allow paging
4078 OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_WRITE_EXIT, this, KErrNone );
4079 return KErrNone; // keep compiler happy
4083 TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
4085 #ifdef __DEMAND_PAGING_BENCHMARKS__
4086 __e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageOutCount, (TUint) 1);
4088 __e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageOutBackgroundCount, (TUint) 1);
4091 // Write to the media and allow for retries in the unlikely event of an error.
4092 const TInt KPageOutRetries = 5;
4093 TInt retVal = KErrGeneral;
4094 for (TInt i=0; retVal != KErrNone && i < KPageOutRetries; i++)
4096 m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging | (aBackground ? TLocDrvRequest::EBackgroundPaging : 0);
4098 m.Id() = DLocalDrive::EWrite;
4099 m.Drive() = TheDrives[iDataPagingDriveNumber];
4101 m.RemoteThread()=NULL;
4103 m.Length()=Int64(size);
4104 m.RemoteDes()=(TAny*)aBuffer;
4105 m.RemoteDesOffset()=0; // pre-aligned
4107 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("ReqId=%d, Pos=0x%lx, Len=0x%lx, remote Des 0x%x",m.Id(),m.Pos(),m.Length(),m.RemoteDes()));
4108 OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_WRITE2, "reqId=%d; position=0x%lx; length=0x%lx; remote Des=0x%x", (TInt) m.Id(), (TUint) m.Pos(), (TUint) m.Length(), (TUint) m.RemoteDes());
4110 __ASSERT_DEBUG(iPrimaryMedia->iBody, LOCM_FAULT());
4111 TInt mediaChanges = iPrimaryMedia->iBody->iMediaChanges;
4113 SendToMainQueueDfcAndBlock(&m); // queues request, sets and opens client thread, queues dfc and blocks thread until request is completed
4117 #ifdef __DEBUG_DEMAND_PAGING__
4118 if (retVal != KErrNone)
4119 Kern::Printf("Pagout Failure %d, retry %d", retVal, i);
4121 // reset retry count if there's ben a media change
4122 if (retVal != KErrNone && mediaChanges != iPrimaryMedia->iBody->iMediaChanges)
4126 #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__
4127 NKern::FMWait(&iInstrumentationLock);
4128 if (iServicingDataOut)
4129 iServicingDataOut--;
4130 NKern::FMSignal(&iInstrumentationLock);
4133 #ifdef __DEMAND_PAGING_BENCHMARKS__
4134 SPagingBenchmarkInfo& info = iDataOutBenchmarkData;
4135 TUint32 bmEnd = NKern::FastCounter();
4137 #if !defined(HIGHIGH_RES_TIMER) || defined(HIGH_RES_TIMER_COUNTS_UP)
4138 TInt64 elapsed=bmEnd-bmStart;
4140 TInt64 elapsed=bmStart-bmEnd;
4142 info.iTotalTime += elapsed;
4143 if (elapsed > info.iMaxTime)
4144 info.iMaxTime = elapsed;
4145 if (elapsed < info.iMinTime)
4146 info.iMinTime = elapsed;
4147 #endif // __DEMAND_PAGING_BENCHMARKS__
4149 OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_WRITE_EXIT2, this, retVal );
4154 TInt DMediaPagingDevice::DeleteNotify(TThreadMessage* aReq,TUint aOffset,TUint aSize)
4156 OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DELETENOTIFY_ENTRY, this );
4157 if (iDeleteNotifyNotSupported)
4159 OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT1, this, KErrNotSupported );
4160 return KErrNotSupported;
4163 __ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT()); // that would lock up the system, thus better die now
4164 __ASSERT_ALWAYS(aReq,LOCM_FAULT());
4165 __ASSERT_ALWAYS(DataPagingDfcQ(iPrimaryMedia),LOCM_FAULT());
4168 TUint offset = aOffset<<iReadUnitShift;
4169 TUint size = aSize<<iReadUnitShift;
4171 #ifdef BTRACE_PAGING_MEDIA
4173 buf[0] = size; // delete notify length
4174 buf[1] = (TInt)aReq; // address of request object
4175 BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedDeleteNotifyBegin,NULL,offset,buf,sizeof(buf));
4178 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::Write, Req(0x%08x), Offset(%d),Size(%d)",aReq,offset,size));
4179 OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_DELETENOTIFY1 , "req=0x%08x; offset=%d; size=%d", (TUint) aReq, offset, size);
4181 // no DFCQ, media driver executes in the context of calling thread
4182 if (!iPrimaryMedia->iDfcQ)
4184 LOCM_FAULT(); // don't allow paging
4185 OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT2, this, KErrNone );
4186 return KErrNone; // keep compiler happy
4189 TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
4192 m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging;
4193 m.Id() = DLocalDrive::EDeleteNotify;
4194 m.Drive() = TheDrives[iDataPagingDriveNumber];
4196 m.RemoteThread() = NULL;
4198 m.Length() = Int64(size);
4199 m.RemoteDes() = NULL;
4200 m.RemoteDesOffset() = 0; // pre-aligned
4202 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("ReqId=%d, Pos=0x%lx, Len=0x%lx, remote Des 0x%x",m.Id(),m.Pos(),m.Length(),m.RemoteDes()));
4203 OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_DELETENOTIFY2 , "reqId=%d; position=0x%lx; length=0x%lx; remote Des=0x%x", m.Id(), m.Pos(), m.Length(), (TUint) m.RemoteDes());
4205 // send request aynchronously as we don't particularly care about the result
4206 // and waiting would slow down the thread taking the page fault
4207 iPrimaryMedia->RequestCountInc();
4209 m.SendReceive(&iMainQ); // send request synchronously
4211 #ifdef __DEMAND_PAGING__
4212 iPrimaryMedia->RequestCountDec();
4215 TInt retVal = m.iValue;
4217 if (retVal == KErrNotSupported)
4218 iDeleteNotifyNotSupported = ETrue;
4220 OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT3, this, retVal );
4226 EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* aSrc, TInt aSize, TInt anOffset)
4228 OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITETOPAGEHANDLER_ENTRY, this );
4229 #ifdef BTRACE_PAGING_MEDIA
4230 TMediaDevice medDev=Drive()->iMedia->iDevice;
4232 buf[0]=(TUint32)RemoteDes();
4235 BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaMedDrvWriteBack,medDev,this,buf,sizeof(buf));
4237 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("TLocDrvRequest::WriteToPageHandler, memcpy((aTrg)%08x, (aSrc)%08x, (aLength)%08x)",(TUint32)RemoteDes()+anOffset,aSrc,aSize));
4238 (void)memcpy((TAny*)((TUint32)RemoteDes()+anOffset), aSrc, aSize); // maybe in later versions this could be something else
4239 OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITETOPAGEHANDLER_EXIT, this, KErrNone );
4243 EXPORT_C TInt TLocDrvRequest::ReadFromPageHandler(TAny* aDst, TInt aSize, TInt anOffset)
4245 OstTraceFunctionEntry1( TLOCDRVREQUEST_READFROMPAGEHANDLER_ENTRY, this );
4246 #ifdef BTRACE_PAGING_MEDIA
4247 TMediaDevice medDev=Drive()->iMedia->iDevice;
4249 buf[0]=(TUint32)RemoteDes();
4252 BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaMedDrvRead,medDev,this,buf,sizeof(buf));
4254 __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("TLocDrvRequest::ReadFromPageHandler, memcpy((aDst)%08x, (aTrg)%08x, (aLength)%08x)",aDst,(TUint32)RemoteDes()+anOffset,aSize));
4255 (void)memcpy(aDst, (TAny*)((TUint32)RemoteDes()+anOffset), aSize); // maybe in later versions this could be something else
4256 OstTraceFunctionExitExt( TLOCDRVREQUEST_READFROMPAGEHANDLER_EXIT, this, KErrNone );
4260 _LIT(KLitFragmentationMutexName, "FRAGMENTATION_MUTEX");
4262 TInt DFragmentationPagingLock::Construct(TUint aNumPages)
4264 OstTraceFunctionEntryExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_ENTRY, this );
4266 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation Lock: creating Mutex"));
4267 r=Kern::MutexCreate(this->iFragmentationMutex, KLitFragmentationMutexName, KMutexOrdNone);
4270 OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT1, this, r );
4273 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation Lock: Mutex created OK"));
4274 OstTraceDef0(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DFRAGMENTATIONPAGINGLOCK_CONSTRUCT1 , "Fragmentation Lock: Mutex created OK");
4276 iFragmentGranularity = 0;
4279 OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT2, this, KErrNone );
4284 TInt pageSize=Kern::RoundToPageSize(1);
4285 LockFragmentation();
4286 r=Alloc(pageSize*aNumPages); // alloc pages
4287 UnlockFragmentation();
4291 iFragmentGranularity = pageSize * aNumPages;
4292 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation granularity set to 0x%x", iFragmentGranularity));
4293 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DFRAGMENTATIONPAGINGLOCK_CONSTRUCT2, "Fragmentation granularity=0x%x", iFragmentGranularity);
4296 OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT3, this, r );
4300 void DFragmentationPagingLock::Cleanup()
4302 OstTraceFunctionEntry1( DFRAGMENTATIONPAGINGLOCK_CLEANUP_ENTRY, this );
4304 if (iFragmentationMutex)
4306 LockFragmentation();
4308 UnlockFragmentation();
4309 Kern::SafeClose((DObject*&)iFragmentationMutex,NULL);
4311 OstTraceFunctionExit1( DFRAGMENTATIONPAGINGLOCK_CLEANUP_EXIT, this );
4315 #if !defined(__WINS__)
4316 EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* , TInt , TInt)
4318 return KErrNone; // stub for def file
4321 #endif //__DEMAND_PAGING__
4322 /********************************************
4323 * Media driver base class
4324 ********************************************/
4332 This is called, typically, by a derived class constructor in its ctor list.
4334 @param aMediaId The value of the unique media ID assigned when the media
4335 driver is registered.
4337 @see LocDrv::RegisterMediaDevice()
4339 EXPORT_C DMediaDriver::DMediaDriver(TInt aMediaId)
4341 OstTraceFunctionEntryExt( DMEDIADRIVER_DMEDIADRIVER_ENTRY, this );
4343 // iPhysicalDevice=NULL;
4344 // iTotalSizeInBytes=0;
4345 // iCurrentConsumption=0;
4346 // iPrimaryMedia=NULL;
4347 // iCritical=EFalse;
4348 iPrimaryMedia=(DPrimaryMediaBase*)TheMedia[aMediaId];
4349 OstTraceFunctionExit1( DMEDIADRIVER_DMEDIADRIVER_EXIT, this );
4358 Sets the device's current consumption to zero, and calls Close() on
4359 the PDD factory object.
4361 @see DObject::Close()
4363 EXPORT_C DMediaDriver::~DMediaDriver()
4365 OstTraceFunctionEntry1( DMEDIADRIVER_DMEDIADRIVER_DESTRUCTOR_ENTRY, this );
4366 SetCurrentConsumption(0);
4367 Kern::SafeClose((DObject*&)iPhysicalDevice,NULL);
4368 OstTraceFunctionExit1( DMEDIADRIVER_DMEDIADRIVER_DESTRUCTOR_EXIT, this );
4375 Closes the media driver.
4377 This default implementation simply deletes this DMediaDriver object.
4379 Media drivers can provide their own implementation, which gives them
4380 the opportunity to clean up resources before closure; for example,
4382 Any replacement function must call this base class function as
4383 the last instruction.
4385 EXPORT_C void DMediaDriver::Close()
4394 Sets the total size of the media device.
4396 The function must be called by the media driver's implementation of PartitionInfo().
4398 @param aTotalSizeInBytes The total size of the media, in bytes.
4399 @param aLocDrv This is not used by media drivers; the class
4400 definition provides a default value.
4402 @see DMediaDriver::PartitionInfo()
4404 EXPORT_C void DMediaDriver::SetTotalSizeInBytes(Int64 aTotalSizeInBytes, TLocDrv* aLocDrv)
4406 OstTraceFunctionEntry1( DMEDIADRIVER_SETTOTALSIZEINBYTES_ENTRY, this );
4407 iTotalSizeInBytes=aTotalSizeInBytes;
4409 aLocDrv->iPartitionLen=aTotalSizeInBytes;
4410 OstTraceFunctionExit1( DMEDIADRIVER_SETTOTALSIZEINBYTES_EXIT, this );
4417 Gets the total size of the media.
4419 @return The total size of the media, in bytes.
4421 @see DMediaDriver::SetTotalSizeInBytes()
4423 EXPORT_C Int64 DMediaDriver::TotalSizeInBytes()
4425 return iTotalSizeInBytes;
4432 Flags the media driver as entering a critical part of its processing.
4434 In this context, critical means that the driver must be allowed to complete
4435 its current activity.
4436 For example, a request to power down the device must be deferred until
4437 the driver exits the critical part.
4439 @return KErrNone, if the driver has been successfully flagged as being in
4440 a critical part; otherwise, one of the other system-wide error codes.
4442 @see DMediaDriver::EndInCritical()
4444 EXPORT_C TInt DMediaDriver::InCritical()
4446 OstTraceFunctionEntry1( DMEDIADRIVER_INCRITICAL_ENTRY, this );
4449 TInt r=iPrimaryMedia->InCritical();
4452 OstTraceFunctionExitExt( DMEDIADRIVER_INCRITICAL_EXIT, this, r );
4457 OstTraceFunctionExitExt( DMEDIADRIVER_INCRITICAL_EXIT2, this, KErrNone );
4465 Flags the media driver as leaving a critical part of its processing.
4467 @see DMediaDriver::InCritical()
4469 EXPORT_C void DMediaDriver::EndInCritical()
4471 OstTraceFunctionEntry1( DMEDIADRIVER_ENDINCRITICAL_ENTRY, this );
4475 iPrimaryMedia->EndInCritical();
4477 OstTraceFunctionExit1( DMEDIADRIVER_ENDINCRITICAL_EXIT, this );
4486 EXPORT_C void DMediaDriver::SetCurrentConsumption(TInt aValue)
4488 OstTraceFunctionEntryExt( DMEDIADRIVER_SETCURRENTCONSUMPTION_ENTRY, this );
4489 TInt old = (TInt)__e32_atomic_swp_ord32(&iCurrentConsumption, aValue);
4490 TInt delta = aValue - old;
4491 iPrimaryMedia->DeltaCurrentConsumption(delta);
4492 OstTraceFunctionExit1( DMEDIADRIVER_SETCURRENTCONSUMPTION_EXIT, this );
4499 Informs the media driver subsystem that an asynchronous request is complete.
4501 @param m The request that this call is completing.
4502 @param aResult The return code for the asynchronous request. Typically, this
4503 is KErrNone to report success, or one of the other system-wide
4504 error codes to report failure or other problems.
4506 EXPORT_C void DMediaDriver::Complete(TLocDrvRequest& m, TInt aResult)
4508 OstTraceExt2( TRACE_FLOW, DMEDIADRIVER_COMPLETE_ENTRY, "m=%x;aResult=%d", (TUint) &m, aResult );
4510 #ifdef __DEMAND_PAGING__
4511 if (DMediaPagingDevice::PagingRequest(m))
4513 __ASSERT_ALWAYS(iPrimaryMedia && iPrimaryMedia->iPagingMedia && iPrimaryMedia->iBody->iPagingDevice,LOCM_FAULT());
4514 __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT());
4515 DMediaPagingDevice* pagingdevice = iPrimaryMedia->iBody->iPagingDevice;
4516 pagingdevice->CompleteRequest(&m, aResult);
4520 iPrimaryMedia->CompleteRequest(m, aResult);
4522 if (&m == iPrimaryMedia->iCurrentReq) // Complete() called on request serviced synchronously
4523 iPrimaryMedia->iCurrentReq = NULL;
4525 iPrimaryMedia->RunDeferred();
4526 OstTraceFunctionExit1( DMEDIADRIVER_COMPLETE_EXIT, this );
4533 Informs the media driver subsystem that the media driver is open
4534 and has been initialised.
4536 This can be called from the PDD factory function Create(), if opening and
4537 initialising the media driver is synchronous, otherwise it should be called by
4538 the asynchronous media driver function that is responsible for opening and
4539 initialising the driver.
4541 @param anError KErrNone if successful, otherwise one of the other system wide
4544 EXPORT_C void DMediaDriver::OpenMediaDriverComplete(TInt anError)
4546 OstTraceFunctionEntry1( DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE_ENTRY, this );
4547 __KTRACE_OPT(KLOCDRV,Kern::Printf("DMediaDriver::OpenMediaDriverComplete(%d) this %x iPrimaryMedia %x", anError, this, iPrimaryMedia));
4548 OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE, "anError %d this 0x%x iPrimaryMedia 0x%x", anError, (TUint) this, (TUint) iPrimaryMedia);
4549 DPrimaryMediaBase* pM=iPrimaryMedia;
4550 pM->iAsyncErrorCode=anError;
4551 pM->iAsyncDfc.Enque();
4552 OstTraceFunctionExit1( DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE_EXIT, this );
4559 Informs the media driver subsystem that the media driver has completed
4560 the provision of partition information.
4562 The media driver provides partition information in its implementation
4565 @param anError KErrNone if successful, otherwise one of the other system wide
4568 @see DMediaDriver::PartitionInfo()
4570 EXPORT_C void DMediaDriver::PartitionInfoComplete(TInt anError)
4572 OstTraceFunctionEntry1( DMEDIADRIVER_PARTITIONINFOCOMPLETE_ENTRY, this );
4573 __KTRACE_OPT(KLOCDRV,Kern::Printf("DMediaDriver::PartitionInfoComplete(%d) anError %d this %x iPrimaryMedia %x", anError, this, iPrimaryMedia));
4574 OstTraceExt3( TRACE_INTERNALS, DMDEDIADRIVER_PARTITIONINFOCOMPLETE, "anError=%d; this=%x; iPrimaryMedia=%x", anError, (TUint) this, (TUint) iPrimaryMedia );
4575 DPrimaryMediaBase* pM=iPrimaryMedia;
4576 pM->iAsyncErrorCode=anError;
4577 pM->iAsyncDfc.Enque();
4578 OstTraceFunctionExit1( DMEDIADRIVER_PARTITIONINFOCOMPLETE_EXIT, this );
4587 // Default implementation
4588 EXPORT_C void DMediaDriver::Disconnect(DLocalDrive* aLocalDrive, TThreadMessage* aMsg)
4590 OstTraceFunctionEntryExt( DMEDIADRIVER_DISCONNECT_ENTRY, this );
4591 // don't need to worry about DLocalDrive going away
4592 aLocalDrive->Deque();
4594 aMsg->Complete(KErrNone, EFalse);
4595 OstTraceFunctionExit1( DMEDIADRIVER_DISCONNECT_EXIT, this );
4602 Registers a media driver with the Local Media Subsystem, and provides
4603 information about the number of supported drives, partitions,
4604 names and drive numbers.
4606 @param aDevice The unique Media ID for this device.
4607 This can take one of the enumerated values defined
4608 by the TMediaDevice enum.
4609 @param aDriveCount Specifies the number of local drive objects to be assigned
4610 to the media driver. Drives that support more than one
4611 partition must specify a number greater than 1.
4612 @param aDriveList A pointer to an array of TInt values, which define
4613 the drive numbers that are to be allocated to each partition.
4614 0 signifies Drive C, 1 signifies drive D, etc. For example,
4615 to allocate drive letters J and K, specify an array
4616 containing the values [7,8].
4617 Note that the size of this array must be the same as the value
4618 specified by aDriveCount.
4619 @param aPrimaryMedia A pointer to the primary DPrimaryMedia object to be
4620 associated with the media. This object is responsible for
4621 the overall state of the media, i.e. powering up, reading
4622 partition information etc. It also has overall control over
4623 all partitions as represented by the additional (aNumMedia-1)
4625 @param aNumMedia Specifies the total number of DMedia objects to be
4626 associated with the media driver. This number includes the
4627 primary DPrimaryMedia object referred to by aPrimaryMedia,
4628 plus all of the DMedia objects that are created for each
4629 additional drive, and which hold basic information about
4631 @param aName The name of the media driver, for example: PCCard
4633 @return KErrNone, if successful;
4634 KErrInUse, if a drive is already in use;
4635 KErrNoMemory, if there is insufficient memory;
4636 or one of the other system-wide error codes.
4638 EXPORT_C TInt LocDrv::RegisterMediaDevice(TMediaDevice aDevice, TInt aDriveCount, const TInt* aDriveList, DPrimaryMediaBase* aPrimaryMedia, TInt aNumMedia, const TDesC& aName)
4640 OstTraceFunctionEntry0( LOCDRV_REGISTERMEDIADEVICE_ENTRY );
4641 // Create TLocDrv / DMedia objects to handle a media device
4642 __KTRACE_OPT(KBOOT,Kern::Printf("RegisterMediaDevice %lS dev=%1d #drives=%d 1st=%d PM=%08x #media=%d",&aName,aDevice,aDriveCount,*aDriveList,aPrimaryMedia,aNumMedia));
4643 OstTraceExt5( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE1, "aDevice=%d; aDriveCount=%d; aDriveList=%d; aPrimaryMedia=0x%08x; aNumMedia=%d", (TInt) aDevice, (TInt) aDriveCount, (TInt) *aDriveList, (TUint) aPrimaryMedia, (TInt) aNumMedia );
4645 const TInt* p=aDriveList;
4648 if (UsedMedia+aNumMedia>KMaxLocalDrives)
4650 OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT1, "< KErrInUse");
4653 for (i=0; i<aDriveCount; ++i)
4656 // -1 means not used; this is to enable Dual-slot MMC support
4659 __KTRACE_OPT(KBOOT,Kern::Printf("Registering drive %d", drv));
4660 OstTrace1( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE2, "Registering drive=%d", drv );
4663 __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d already in use", drv));
4664 OstTrace1( TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT2, "< Drive %d already in use; KErrInUse", drv);
4668 HBuf* pN=HBuf::New(aName);
4671 OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT3, "< KErrNoMemory");
4672 return KErrNoMemory;
4674 TInt lastMedia=UsedMedia+aNumMedia-1;
4675 for (i=UsedMedia; i<=lastMedia; ++i)
4678 TheMedia[i]=aPrimaryMedia;
4680 TheMedia[i]=new DMedia;
4683 OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT4, "< KErrNoMemory");
4684 return KErrNoMemory;
4686 r=TheMedia[i]->Create(aDevice,i,lastMedia);
4687 __KTRACE_OPT(KBOOT,Kern::Printf("Media %d Create() returns %d",i,r));
4688 OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE3, "Media=%d Create(); retval=%d", i, r );
4691 OstTrace1(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT5, "< retval=%d", r);
4696 __KTRACE_OPT(KBOOT,Kern::Printf("FirstMedia %d LastMedia %d",UsedMedia,lastMedia));
4697 OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE4, "FirstMedia=%d; LastMedia=%d", UsedMedia, lastMedia );
4698 UsedMedia+=aNumMedia;
4700 for (i=0; i<aDriveCount; ++i)
4705 TLocDrv* pL=new TLocDrv(drv);
4708 OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT6, "< KErrNoMemory");
4709 return KErrNoMemory;
4713 pL->iPrimaryMedia=aPrimaryMedia;
4714 __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pL));
4715 OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE5, "Drive=%d; TLocDrv 0x%08x;", (TInt) drv, (TUint) pL );
4718 OstTraceFunctionExit0( LOCDRV_REGISTERMEDIADEVICE_EXIT7 );
4726 A utility function that is used internally to register the specified
4729 The password store is used to save passwords for local media.
4731 @param aStore A pointer to the password store to be registered.
4733 @return KErrNone, if successful;
4734 KErrAlreadyExists, if a password store has already been registered.
4736 EXPORT_C TInt LocDrv::RegisterPasswordStore(TPasswordStore* aStore)
4738 OstTraceFunctionEntry0( LOCDRV_REGISTERPASSWORDSTORE_ENTRY );
4739 // Create TLocDrv / DMedia objects to handle a media device
4740 __KTRACE_OPT(KBOOT,Kern::Printf("RegisterPasswordStore"));
4744 if(ThePasswordStore == NULL)
4745 ThePasswordStore = aStore;
4747 r = KErrAlreadyExists;
4748 OstTrace1(TRACE_INTERNALS, LOCDRV_REGISTERPASSWORDSTORE, "retval=%d", r);
4749 OstTraceFunctionExit0( LOCDRV_REGISTERPASSWORDSTORE_EXIT );
4754 Returns a pointer to the registered password store.
4756 The password store is used to save passwords for local media.
4758 @return A pointer to the registered password store.
4760 EXPORT_C TPasswordStore* LocDrv::PasswordStore()
4762 return ThePasswordStore;
4765 #ifdef __DEMAND_PAGING__
4767 Registers a paging device with the Local Media Subsystem, and provides
4768 information about drive numbers used in Code Paging.
4770 @param aPrimaryMedia A pointer to the primary DPrimaryMedia object associated
4772 @param aPagingDriveList A pointer to an array of TInt values, which define
4773 the drive numbers used as Code backup in Code Paging, which
4774 are the target of Page In requests. For NAND these will
4775 will be usually associated with ROFS and/or User Data drives.
4776 In ROM pagigng systems no drive is specified, it is assumed
4777 a fixed media for which no non-primary media exists, will be
4779 @param aDriveCount Specifies the number of local drives associated with this
4780 media device which can be used for code paging.
4781 @param aPagingType Identifies the type of Paging this media device is capable
4783 @param aReadShift Log2 of the read unit size. A read unit is the number of bytes
4784 which the device can optimally read from the underlying media.
4785 E.g. for small block NAND, a read unit would be equal to the
4786 page size, 512 bytes, therefore iReadShift would be set to 9.
4787 @param aNumPages The number of pages to alloc for each drive associated with this
4788 media driver. The pages are used in request fragmentation.
4790 @return KErrNone, if successful;
4791 KErrNotFound, if at least one of the drive numbers
4792 specified has not yet been mapped.
4793 KErrArgument, if the passed in an invalid argument.
4794 KErrNotSupported, if at least one of the drive numbers
4795 specifed is not associated with this Primary Media.
4796 KErrNoMemory, if there is insufficient memory;
4797 or one of the other system-wide error codes.
4799 EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* aPrimaryMedia, const TInt* aPagingDriveList, TInt aDriveCount, TUint aPagingType, TInt aReadShift, TUint aNumPages)
4801 OstTraceFunctionEntry0( LOCDRV_REGISTERPAGINGDEVICE_ENTRY );
4803 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf(">RegisterPagingDevice: paging type=%d PM=0x%x read shift=%d",aPagingType,aPrimaryMedia,aReadShift));
4804 OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE1, "aPagingType=%d; aPrimaryMedia=0x%x; aReadShift=%d", (TInt) aPagingType, (TUint) aPrimaryMedia, (TInt) aReadShift);
4808 if(!aPagingType || (aPagingType&~(DPagingDevice::ERom | DPagingDevice::ECode | DPagingDevice::EData)))
4810 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Unsupported paging type, exiting"));
4811 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT1, "< Unsupported paging type; KErrArgument");
4812 return KErrArgument;
4817 for(i=0; i<KMaxLocalDrives; i++)
4819 if (ThePagingDevices[i] == NULL)
4821 if ((ThePagingDevices[i]->iType&DPagingDevice::ERom) && (aPagingType & DPagingDevice::ERom))
4823 aPagingType&=~DPagingDevice::ERom; // already have a ROM paging device
4824 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has ROM pager on locdrv no %d",i));
4826 if ((ThePagingDevices[i]->iType&DPagingDevice::EData) && (aPagingType & DPagingDevice::EData))
4828 aPagingType&=~DPagingDevice::EData; // already have a Data paging device
4829 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has Data pager on locdrv no %d",i));
4834 if (aPagingType == 0)
4836 // there's already a ROM or Data paging device & this doesn't support code paging so quietly exit without further addo
4837 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Nothing left to register on locdrv no %d, exiting",i));
4838 OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT2, "< Nothing left to register on locdrv no %d; KErrNone",i);
4842 const TInt* p=aPagingDriveList;
4843 if(aPagingType&DPagingDevice::ECode) // supports code paging, do argument check
4845 if(!aDriveCount || (aDriveCount>=KMaxLocalDrives))
4847 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive count: %d", aDriveCount));
4848 OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT3, "< Invalid code paging drive count=%d; KErrArgument", aDriveCount);
4849 return KErrArgument;
4853 for(i=0; i<KMaxLocalDrives; i++)
4854 if(TheDrives[i] && TheDrives[i]->iPrimaryMedia==aPrimaryMedia)
4856 if(aDriveCount>drvCount) // can't exceed number of drives registered by this device
4858 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive count=%d; total=%d", aDriveCount, drvCount));
4859 OstTraceExt2(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT4, "< Invalid code paging drive count=%d; total=%d; KErrArgument", aDriveCount, drvCount);
4860 return KErrArgument;
4863 for (i=0; i<aDriveCount; ++i)
4865 __KTRACE_OPT(KBOOT,Kern::Printf("RegisterPagingDevice: registering drive=%d ",*p));
4866 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE2, "Registering Drive=%d", *p );
4868 if(drv>=KMaxLocalDrives)
4870 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive number: %d", drv));
4871 OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT5, "< Invalid code paging drive number=%d; KErrArgument", drv);
4872 return KErrArgument;
4874 TLocDrv* pD=TheDrives[drv];
4877 OstTrace0(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT6, "< KErrNotFound");
4878 return KErrNotFound;
4880 if (pD->iPrimaryMedia!=aPrimaryMedia)
4882 OstTrace0(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT7, "< KErrNotSupported");
4883 return KErrNotSupported;
4889 TInt firstLocalDriveNumber = KErrNotFound;
4890 TInt romPagingDriveNumber = KErrNotFound;
4892 TInt dataPagingDriveNumber = KErrNotFound;
4895 // find the local drive assocated with the primary media
4896 for (i=0; i<KMaxLocalDrives; ++i)
4898 if(TheDrives[i] && TheDrives[i]->iPrimaryMedia == aPrimaryMedia)
4900 firstLocalDriveNumber = i;
4904 __ASSERT_ALWAYS(i < KMaxLocalDrives, LOCM_FAULT());
4905 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("DMediaPagingDevice(), firstLocalDriveNumber %d", firstLocalDriveNumber));
4906 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE3, "firstLocalDriveNumber=%d", firstLocalDriveNumber );
4908 // Send an ECaps message to wake up the media driver & ensure all partitions are
4909 // reported, then search for paged-data or paged-ROM partitions
4910 if ((aPagingType & DPagingDevice::EData) ||
4911 (aPagingType & DPagingDevice::ERom && aPrimaryMedia->iDfcQ && aPrimaryMedia->iMsgQ.iReady))
4913 // the message queue must have been started already (by the media driver calling iMsgQ.Receive())
4914 // otherwise we can't send the DLocalDrive::EQueryDevice request
4915 if (aPrimaryMedia->iDfcQ && !aPrimaryMedia->iMsgQ.iReady)
4917 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Message queue not started"));
4918 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT8, "< RegisterPagingDevice: Message queue not started; KErrNotReady");
4919 return KErrNotReady;
4924 memclr(&m, sizeof(m));
4927 // Get the Caps from the device. NB for MMC/SD we may need to retry as some PSLs start up
4928 // in "door open" or "media not present" state which can result in the cancellation of requests
4930 const TInt KRetries = 5;
4931 TInt r = KErrNotReady;
4932 for (i=0; r == KErrNotReady && i < KRetries; i++)
4934 TBuf8<KMaxLocalDriveCapsLength> capsBuf;
4937 m.Drive() = TheDrives[firstLocalDriveNumber];
4938 m.Id() = DLocalDrive::ECaps;
4939 m.RemoteDes() = (TAny*)capsBuf.Ptr(); // overload this
4940 m.Length() = KMaxLocalDriveCapsLength; // for pinning
4941 r = aPrimaryMedia->Request(m);
4943 //Kern::Printf("EQueryPageDeviceInfo: i %d: r %d ", i, r);
4944 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Paging device ECaps: i %d: r %d ", i, r));
4945 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE4, "Paging device ECaps: i %d retval=%d", i, r);
4950 OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< retval=%d",r);
4955 for (i=0; i<KMaxLocalDrives; ++i)
4957 drive = TheDrives[i];
4958 if(drive && drive->iPrimaryMedia == aPrimaryMedia)
4960 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("RegisterPagingDevice: local drive %d, partition type %x size %x", i, drive->iPartitionType, I64LOW(drive->iPartitionLen)));
4962 if ((romPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypeROM))
4964 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found ROM partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
4965 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE5, "Found ROM partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen));
4966 romPagingDriveNumber = i;
4969 else if ((dataPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypePagedData))
4971 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found swap partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
4972 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE6, "Found SWAP partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen) );
4973 dataPagingDriveNumber = i;
4974 swapSize = drive->iPartitionLen >> aReadShift;
4981 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Disabling data paging"));
4982 OstTraceDef0(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE7, "Disabling data paging");
4983 aPagingType &= ~DPagingDevice::EData;
4989 // create and set up a DPagingDevice to allow PageIn request servicing
4990 DMediaPagingDevice* pagingDevice = new DMediaPagingDevice(aPrimaryMedia);
4993 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create paging device"));
4994 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT_EXIT10, "< RegisterPagingDevice: could not create paging device; KErrNoMemory");
4995 return KErrNoMemory;
4998 pagingDevice->iType = aPagingType;
4999 pagingDevice->iReadUnitShift = aReadShift;
5001 pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber;
5002 pagingDevice->iRomPagingDriveNumber = romPagingDriveNumber;
5004 pagingDevice->iDataPagingDriveNumber = dataPagingDriveNumber;
5005 pagingDevice->iSwapSize = swapSize;
5007 #ifdef __DEBUG_DEMAND_PAGING__
5008 Kern::Printf("PagingDevice :");
5009 Kern::Printf("iType 0x%x\n", pagingDevice->iType);
5010 Kern::Printf("iReadUnitShift 0x%x\n", pagingDevice->iReadUnitShift);
5011 Kern::Printf("iFirstLocalDriveNumber 0x%x\n", pagingDevice->iFirstLocalDriveNumber);
5012 Kern::Printf("iRomPagingDriveNumber 0x%x\n", pagingDevice->iRomPagingDriveNumber);
5013 Kern::Printf("iDataPagingDriveNumber 0x%x\n", pagingDevice->iDataPagingDriveNumber);
5014 Kern::Printf("iSwapSize 0x%x\n", pagingDevice->iSwapSize);
5018 // This table is indexed by DPagingDevice::TType
5019 const char* DeviceName[] =
5024 "RomAndCodePagingDevice",
5026 "RomAndDataPagingDevice",
5027 "CodeAndDataPagingDevice",
5028 "RomAndCodeAndDataPagingDevice"
5032 if(aPagingType & DPagingDevice::ECode)
5034 for (i=0; i<aDriveCount; ++i)
5035 pagingDevice->iDrivesSupported|=(0x1<<aPagingDriveList[i]);
5037 pagingDevice->iName = DeviceName[aPagingType];
5039 if (ThePinObjectAllocator == NULL)
5040 ThePinObjectAllocator = new DPinObjectAllocator();
5041 if(!ThePinObjectAllocator)
5043 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator"));
5044 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory");
5045 return KErrNoMemory;
5047 TInt r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages);
5050 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not construct ThePinObjectAllocator"));
5051 OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT12, "< RegisterPagingDevice: could not construct ThePinObjectAllocator; retval=%d",r);
5056 // Register our DPagingDevice with the Kernel
5057 r=Kern::InstallPagingDevice(pagingDevice);
5059 #ifdef __DEBUG_DEMAND_PAGING__
5060 Kern::Printf("Kern::InstallPagingDevice() r %d", r);
5065 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not install paging device"));
5066 OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT13, "< RegisterPagingDevice: could not install paging device; retval=%d", r);
5067 delete pagingDevice;
5071 // all hunky dory, save paging device and mark our media as pageable
5072 ThePagingDevices[aPrimaryMedia->iMediaId] = pagingDevice; // association created between PrimaryMedia and PagingDevice via iMediaId
5073 aPrimaryMedia->iPagingMedia = 1;
5075 // mark our drives as pageable
5077 if (aPagingType&DPagingDevice::ECode)
5079 for (i=0; i<aDriveCount; ++i)
5081 TLocDrv* pD=TheDrives[*p++];
5086 // Flags to indicate that a paging device is registered and pinning of user requests may be required
5087 aPrimaryMedia->iPagingMedia = 1;
5089 // point the primary media to the paging device
5090 aPrimaryMedia->iBody->iPagingDevice = pagingDevice;
5092 if (aPagingType & DPagingDevice::ERom)
5094 aPrimaryMedia->iRomPagingMedia = 1;
5095 TheRomPagingMedia = aPrimaryMedia;
5098 // Is data paging enabled in this ROM ?
5099 TInt memModelAttributes = Kern::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
5100 TBool dataPagingSupported = memModelAttributes & EMemModelAttrDataPaging;
5101 #ifdef __DEBUG_DEMAND_PAGING__
5102 Kern::Printf("memModelAttributes %08X", memModelAttributes);
5103 Kern::Printf("DataPagingSupported %d", dataPagingSupported);
5105 if (!dataPagingSupported)
5107 #ifdef __DEBUG_DEMAND_PAGING__
5108 if (aPagingType & DPagingDevice::EData)
5110 Kern::Printf("Disabling data paging, not supported in this ROM");
5113 aPagingType&= ~DPagingDevice::EData;
5117 if (aPagingType & DPagingDevice::EData)
5119 DataPagingDeviceRegistered = ETrue;
5120 aPrimaryMedia->iDataPagingMedia = 1;
5121 TheDataPagingMedia = aPrimaryMedia;
5124 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("< RegisterPagingDevice"));
5125 OstTraceFunctionExit0( LOCDRV_REGISTERPAGINGDEVICE_EXIT14 );
5129 #else //__DEMAND_PAGING__
5131 #if !defined(__WINS__)
5132 EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* , const TInt* , TInt , TUint , TInt , TUint )
5134 return KErrNotSupported;
5135 } // stub for def file
5138 #endif //__DEMAND_PAGING__
5142 Registers a media device with physical memory addressing capabilities with the
5143 Local Media Subsystem.
5145 @param aPrimaryMedia A pointer to the primary DPrimaryMedia object associated
5146 with the media device.
5147 @param aMediaBlockSize The Minimum transfer size (bytes) for the media device.
5148 @param aDmaMaxAddressable The Maximum Addressing Range for the media device's DMA controller, 0 if None.
5149 @param aDmaAlignment The required memory alignment for the media device's DMA controller.
5151 @return KErrNone, Always;
5153 EXPORT_C TInt LocDrv::RegisterDmaDevice(DPrimaryMediaBase* aPrimaryMedia,
5154 TInt aMediaBlockSize, // Minimum transfer size (bytes) for the media
5155 TInt aDmaMaxAddressable, // Max Addressing Range for DMA controller, 0 if None.
5156 TInt aDmaAlignment) // DMA Alignment e.g. word alignment required = 2
5158 OstTraceFunctionEntry0( LOCDRV_REGISTERDMADEVICE_ENTRY );
5160 __KTRACE_OPT(KBOOT ,Kern::Printf("RegisterPhysicalAddrDevice: PM=0x%x BS=%d MaxAddr=%d DMA=%d",
5161 aPrimaryMedia, aMediaBlockSize, aDmaMaxAddressable, aDmaAlignment));
5162 OstTraceExt4( TRACE_INTERNALS, LOCDRV_REGISTERDMADEVICE, "aPrimaryMedia=0x%x; aMediaBlockSize=%d; aDmaMaxAddressable=%d; aDmaAlignment=%d", (TUint) aPrimaryMedia, (TInt) aMediaBlockSize, (TInt) aDmaMaxAddressable, (TInt) aDmaAlignment );
5164 for (TInt i=0; i<KMaxLocalDrives; ++i)
5166 TLocDrv* pL=TheDrives[i];
5167 if (pL && pL->iPrimaryMedia == aPrimaryMedia && pL->iDmaHelper == NULL)
5169 pL->iDmaHelper = new DDmaHelper;
5170 __ASSERT_ALWAYS(pL != NULL, LOCM_FAULT());
5172 // if no limit stated on addressing range use 1MB
5173 TInt MaxAddress = aDmaMaxAddressable ? (1024*1024) : aDmaMaxAddressable;
5175 TInt r = pL->iDmaHelper->Construct(MaxAddress, aMediaBlockSize, aDmaAlignment);
5176 __ASSERT_ALWAYS(r == KErrNone, LOCM_FAULT());
5180 OstTraceFunctionExit0( LOCDRV_REGISTERDMADEVICE_EXIT );
5184 void GetDriveInfo(TDriveInfoV1& info)
5186 OstTraceFunctionEntry1( GETDRIVEINFO_ENTRY, ( TUint )&( info ) );
5189 TUint32 sock_mask=0;
5192 info.iRegisteredDriveBitmask = 0;
5194 for (i=0; i<KMaxPBusSockets; ++i)
5195 info.iSocketName[i].Zero();
5196 for (i=0; i<KMaxLocalDrives; ++i)
5198 TLocDrv* pL=TheDrives[i];
5203 DPrimaryMediaBase* pM=pL->iPrimaryMedia;
5204 if (pM->IsRemovableDevice(sockNum))
5206 if (!(sock_mask & (1<<sockNum)))
5208 info.iSocketName[sockNum]=*DriveNames[i];
5209 __KTRACE_OPT(KLOCDRV,Kern::Printf("Socket %d device %d name %lS", sockNum, pM->iDevice, DriveNames[i]));
5210 OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO1, "Socket=%d; device=%d", sockNum, (TUint) pM->iDevice );
5211 if ( (sockNum + 1) > sockets )
5212 sockets = sockNum + 1;
5214 sock_mask |= (1<<sockNum);
5216 info.iDriveName[i]=*DriveNames[i];
5217 __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d device %d name %lS",i,pM->iDevice,DriveNames[i]));
5218 OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO2, "Drive=%d; device=%d", i, (TUint) pM->iDevice );
5220 info.iRegisteredDriveBitmask |= (0x01 << i);
5223 info.iTotalSupportedDrives=drives;
5224 info.iTotalSockets=sockets;
5225 info.iRuggedFileSystem=ETrue;
5226 __KTRACE_OPT(KLOCDRV,Kern::Printf("Total drives=%d, sockets=%d",drives,sockets));
5227 OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO3, "Total drives=%d; sockets=%d", drives, sockets );
5228 OstTraceFunctionExit0( GETDRIVEINFO_EXIT );
5231 #if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__)
5232 void ResetConcurrencyStats(DMediaPagingDevice* aDevice, TMediaPagingStats aStats)
5234 NKern::FMWait(&aDevice->iInstrumentationLock);
5237 case EMediaPagingStatsRom:
5238 aDevice->iServicingROM=0;
5239 memclr(&aDevice->iROMStats,sizeof(SMediaROMPagingConcurrencyInfo));
5241 case EMediaPagingStatsCode:
5242 aDevice->iServicingCode=0;
5243 memclr(&aDevice->iCodeStats,sizeof(SMediaCodePagingConcurrencyInfo));
5245 case EMediaPagingStatsDataIn:
5246 aDevice->iServicingDataIn=0;
5247 memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo));
5249 case EMediaPagingStatsDataOut:
5250 aDevice->iServicingDataOut=0;
5251 memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo));
5253 case EMediaPagingStatsAll:
5254 aDevice->iServicingROM=0;
5255 aDevice->iServicingCode=0;
5256 aDevice->iServicingDataIn=0;
5257 aDevice->iServicingDataOut=0;
5258 memclr(&aDevice->iROMStats,sizeof(SMediaROMPagingConcurrencyInfo));
5259 memclr(&aDevice->iCodeStats,sizeof(SMediaCodePagingConcurrencyInfo));
5260 memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo));
5263 NKern::FMSignal(&aDevice->iInstrumentationLock);
5266 #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
5267 void ResetBenchmarkStats(DMediaPagingDevice* aDevice, TMediaPagingStats aStats)
5269 NKern::FMWait(&aDevice->iInstrumentationLock);
5272 case EMediaPagingStatsRom:
5273 aDevice->iROMBenchmarkData.iCount = 0;
5274 aDevice->iROMBenchmarkData.iTotalTime = 0;
5275 aDevice->iROMBenchmarkData.iMaxTime = 0;
5276 aDevice->iROMBenchmarkData.iMinTime = KMaxTInt;
5278 case EMediaPagingStatsCode:
5279 aDevice->iCodeBenchmarkData.iCount = 0;
5280 aDevice->iCodeBenchmarkData.iTotalTime = 0;
5281 aDevice->iCodeBenchmarkData.iMaxTime = 0;
5282 aDevice->iCodeBenchmarkData.iMinTime = KMaxTInt;
5284 case EMediaPagingStatsDataIn:
5285 aDevice->iDataInBenchmarkData.iCount = 0;
5286 aDevice->iDataInBenchmarkData.iTotalTime = 0;
5287 aDevice->iDataInBenchmarkData.iMaxTime = 0;
5288 aDevice->iDataInBenchmarkData.iMinTime = KMaxTInt;
5290 case EMediaPagingStatsDataOut:
5291 aDevice->iDataOutBenchmarkData.iCount = 0;
5292 aDevice->iDataOutBenchmarkData.iTotalTime = 0;
5293 aDevice->iDataOutBenchmarkData.iMaxTime = 0;
5294 aDevice->iDataOutBenchmarkData.iMinTime = KMaxTInt;
5296 case EMediaPagingStatsAll:
5297 aDevice->iDataInBenchmarkData.iCount = 0;
5298 aDevice->iDataInBenchmarkData.iTotalTime = 0;
5299 aDevice->iDataInBenchmarkData.iMaxTime = 0;
5300 aDevice->iDataInBenchmarkData.iMinTime = KMaxTInt;
5302 aDevice->iDataOutBenchmarkData.iCount = 0;
5303 aDevice->iDataOutBenchmarkData.iTotalTime = 0;
5304 aDevice->iDataOutBenchmarkData.iMaxTime = 0;
5305 aDevice->iDataOutBenchmarkData.iMinTime = KMaxTInt;
5307 aDevice->iROMBenchmarkData.iCount = 0;
5308 aDevice->iROMBenchmarkData.iTotalTime = 0;
5309 aDevice->iROMBenchmarkData.iMaxTime = 0;
5310 aDevice->iROMBenchmarkData.iMinTime = KMaxTInt;
5312 aDevice->iCodeBenchmarkData.iCount = 0;
5313 aDevice->iCodeBenchmarkData.iTotalTime = 0;
5314 aDevice->iCodeBenchmarkData.iMaxTime = 0;
5315 aDevice->iCodeBenchmarkData.iMinTime = KMaxTInt;
5318 NKern::FMSignal(&aDevice->iInstrumentationLock);
5322 TInt MediaHalFunction(TAny*, TInt aFunction, TAny* a1, TAny* a2)
5324 TInt r=KErrNotSupported;
5327 case EMediaHalDriveInfo:
5330 TDriveInfoV1Buf infoBuf;
5331 TDriveInfoV1& info=infoBuf();
5333 Kern::InfoCopy(*(TDes8*)a1,infoBuf);
5337 #if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__)
5338 case EMediaHalGetROMConcurrencyInfo:
5340 TInt drvNo=(TInt)a1;
5341 TLocDrv* drv=TheDrives[drvNo];
5344 DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice;
5347 NKern::FMWait(&device->iInstrumentationLock);
5348 SMediaROMPagingConcurrencyInfo info=device->iROMStats;
5349 NKern::FMSignal(&device->iInstrumentationLock);
5350 kumemput32(a2,&info,sizeof(info));
5354 case EMediaHalGetCodeConcurrencyInfo:
5356 TInt drvNo=(TInt)a1;
5357 TLocDrv* drv=TheDrives[drvNo];
5360 DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
5363 NKern::FMWait(&device->iInstrumentationLock);
5364 SMediaCodePagingConcurrencyInfo info=device->iCodeStats;
5365 NKern::FMSignal(&device->iInstrumentationLock);
5366 kumemput32(a2,&info,sizeof(info));
5370 case EMediaHalGetDataConcurrencyInfo:
5372 TInt drvNo=(TInt)a1;
5373 TLocDrv* drv=TheDrives[drvNo];
5376 DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice;
5379 NKern::FMWait(&device->iInstrumentationLock);
5380 SMediaDataPagingConcurrencyInfo info=device->iDataStats;
5381 NKern::FMSignal(&device->iInstrumentationLock);
5382 kumemput32(a2,&info,sizeof(info));
5386 case EMediaHalResetConcurrencyInfo:
5388 TInt drvNo=(TInt)a1;
5389 TLocDrv* drv=TheDrives[drvNo];
5392 DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
5395 TUint index=(TInt)a2;
5396 if(index>EMediaPagingStatsCode)
5398 ResetConcurrencyStats(device, (TMediaPagingStats)index);
5403 #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
5404 case EMediaHalGetROMPagingBenchmark:
5406 TInt drvNo=(TInt)a1;
5407 TLocDrv* drv=TheDrives[drvNo];
5410 DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
5413 NKern::FMWait(&device->iInstrumentationLock);
5414 SPagingBenchmarkInfo info = device->iROMBenchmarkData;
5415 NKern::FMSignal(&device->iInstrumentationLock);
5416 kumemput32(a2,&info,sizeof(info));
5420 case EMediaHalGetCodePagingBenchmark:
5422 TInt drvNo=(TInt)a1;
5423 TLocDrv* drv=TheDrives[drvNo];
5426 DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
5429 NKern::FMWait(&device->iInstrumentationLock);
5430 SPagingBenchmarkInfo info = device->iCodeBenchmarkData;
5431 NKern::FMSignal(&device->iInstrumentationLock);
5432 kumemput32(a2,&info,sizeof(info));
5436 case EMediaHalGetDataInPagingBenchmark:
5438 TInt drvNo=(TInt)a1;
5439 TLocDrv* drv=TheDrives[drvNo];
5442 DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
5445 NKern::FMWait(&device->iInstrumentationLock);
5446 SPagingBenchmarkInfo info = device->iDataInBenchmarkData;
5447 NKern::FMSignal(&device->iInstrumentationLock);
5448 kumemput32(a2,&info,sizeof(info));
5452 case EMediaHalGetDataOutPagingBenchmark:
5454 TInt drvNo=(TInt)a1;
5455 TLocDrv* drv=TheDrives[drvNo];
5458 DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
5461 NKern::FMWait(&device->iInstrumentationLock);
5462 SPagingBenchmarkInfo info = device->iDataOutBenchmarkData;
5463 NKern::FMSignal(&device->iInstrumentationLock);
5464 kumemput32(a2,&info,sizeof(info));
5468 case EMediaHalResetPagingBenchmark:
5470 TInt drvNo=(TInt)a1;
5471 TLocDrv* drv=TheDrives[drvNo];
5474 DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
5477 TUint index=(TInt)a2;
5478 if(index>EMediaPagingStatsCode)
5480 ResetBenchmarkStats(device, (TMediaPagingStats)index);
5484 case EMediaHalGetPagingInfo:
5486 TInt drvNo=(TInt)a1;
5487 TLocDrv* drv=TheDrives[drvNo];
5490 DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
5493 NKern::FMWait(&device->iInstrumentationLock);
5494 SMediaPagingInfo info = device->iMediaPagingInfo;
5495 NKern::FMSignal(&device->iInstrumentationLock);
5496 kumemput32(a2,&info,sizeof(info));
5508 /******************************************************************************
5509 Partition table scanner
5510 ******************************************************************************/
5513 #define DMEMDUMP(base,size) DbgMemDump((TLinAddr)base,size)
5514 void DbgMemDump(TLinAddr aBase, TInt aSize)
5517 const TUint8* p=(const TUint8*)aBase;
5519 for (off=0; off<aSize; off+=16, p+=16)
5521 Kern::Printf("%04x: %02x %02x %02x %02x %02x %02x %02x %02x | %02x %02x %02x %02x %02x %02x %02x %02x",
5522 off, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
5523 p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
5528 #define DMEMDUMP(base,size)
5531 EXPORT_C void TPartitionTableScanner::Set(TUint8* aSectorBuffer, TPartitionEntry* aEntry, TInt aMaxPartitions, TInt64 aMediaSize)
5533 __KTRACE_OPT(KLOCDRV, Kern::Printf("TPartitionTableScanner @ %08x : buf %08x entry %08x max %d sz %08x %08x",
5534 this, aSectorBuffer, aEntry, aMaxPartitions, I64HIGH(aMediaSize), I64LOW(aMediaSize)));
5535 OstTraceExt4( TRACE_INTERNALS, TPARTITIONTABLESCANNER_SET, "TPartitionTableScanner at 0x%08x; aSectorBuffer=0x%08x; aEntry=0x%08x; aMaxPartitions=%d", (TUint) this, (TUint) aSectorBuffer, (TUint) aEntry, aMaxPartitions );
5536 __ASSERT_ALWAYS(aMaxPartitions>0, LOCM_FAULT());
5537 memclr(this, sizeof(TPartitionTableScanner));
5539 iSectorBuffer = aSectorBuffer;
5540 iFirstEntry = aEntry;
5541 iNextEntry = aEntry;
5542 iLimit = aEntry + aMaxPartitions;
5543 iMediaSize = aMediaSize;
5546 EXPORT_C TInt TPartitionTableScanner::NumberOfPartitionsFound() const
5548 TInt n = iNextEntry - iFirstEntry;
5549 __KTRACE_OPT(KLOCDRV, Kern::Printf("TPartitionTableScanner N=%d", n));
5550 OstTrace1( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NUMBERPARTITIONS, "Number of partitions=%d", n );
5554 TPartitionTableScanner::SPart::SPart(const TUint8* a)
5558 iRSS = a[8]|(a[9]<<8)|(a[10]<<16)|(a[11]<<24);
5559 iSectors = a[12]|(a[13]<<8)|(a[14]<<16)|(a[15]<<24);
5560 __KTRACE_OPT(KLOCDRV, Kern::Printf("SPart: BI=%02x TYPE=%02x RSS=%08x SIZE=%08x", iBootInd, iType, iRSS, iSectors));
5561 OstTraceExt4(TRACE_INTERNALS, TPARTITIONTABLESCANNER_SPART_SPART, "SPart: iBootInd=%02x; iType=%02x; iRSS=%08x; iSectors=%08x", (TUint) iBootInd, (TUint) iType, (TUint) iRSS, (TUint) iSectors);
5564 TInt TPartitionTableScanner::MakeEntry(const SPart& a)
5566 OstTraceFunctionEntry1( TPARTITIONTABLESCANNER_MAKEENTRY_ENTRY, this );
5567 if (iNextEntry == iLimit)
5569 OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT1, this, KErrOverflow );
5570 return KErrOverflow;
5572 if (a.iRSS<=0 || a.iSectors<=0 || a.iRSS>=iMediaSize)
5574 OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT2, this, KErrCorrupt );
5577 if (TUint64(a.iRSS) + TUint64(a.iSectors) > TUint64(iMediaSize))
5579 OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT3, this, KErrCorrupt );
5582 iNextEntry->iBootIndicator = a.iBootInd;
5583 iNextEntry->iPartitionType = a.iType;
5584 iNextEntry->iPartitionBaseAddr = TInt64(a.iRSS)<<ESectorShift;
5585 iNextEntry->iPartitionLen = TInt64(a.iSectors)<<ESectorShift;
5587 OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT4, this, KErrNone );
5591 EXPORT_C TInt64 TPartitionTableScanner::NextLBA()
5593 OstTraceFunctionEntry0( TPARTITIONTABLESCANNER_NEXTLBA_ENTRY );
5594 __KTRACE_OPT(KLOCDRV, Kern::Printf(">TPartitionTableScanner iLBA=%08x %08x", I64HIGH(iLBA), I64LOW(iLBA)));
5595 OstTraceExt2( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NEXTLBA1, "TPartitionTableScanner iLBA=%08x %08x", I64HIGH(iLBA), I64LOW(iLBA) );
5597 TUint8* b = iSectorBuffer;
5598 TUint8* pS = b + 0x1be;
5599 TUint8* pE = pS + 64;
5601 TInt orig_sp = iStackPointer;
5608 __KTRACE_OPT(KLOCDRV,DMEMDUMP(b, ESectorSize));
5609 if (b[ESectorSize-2]!=0x55 || b[ESectorSize-1]!=0xaa)
5611 __KTRACE_OPT(KLOCDRV, Kern::Printf("Bad signature"));
5612 OstTrace0( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NEXTLBA2, "Bad signature" );
5616 if (iLBA==0 && iNextEntry==iFirstEntry)
5618 // Look for bootable partition first
5622 if (pt.iBootInd==0x80 && pt.iType && pt.iSectors>0)
5634 // Look for extended partitions
5635 for (p=pE-16; p>=pS; p-=16)
5638 if ((pt.iType==0x05 || pt.iType==0x0f) && pt.iSectors>0)
5640 // This one is an EBR
5642 if (iStackPointer == EMaxNest)
5644 if (iStackPointer == orig_sp)
5647 for(sp = orig_sp; sp<iStackPointer; ++sp)
5648 iStack[sp] = iStack[sp+1];
5650 iStack[iStackPointer].iRSS = pt.iRSS;
5651 iStack[iStackPointer].iSectors = pt.iSectors;
5654 for (sp=0; sp<iStackPointer; ++sp)
5656 const TInt64& rss = iStack[sp].iRSS;
5657 const TInt64& size = iStack[sp].iSectors;
5658 __KTRACE_OPT(KLOCDRV, Kern::Printf("Stack[%d] RSS %08x %08x SIZE %08x %08x", sp,
5659 I64HIGH(rss), I64LOW(rss), I64HIGH(size), I64LOW(size) ));
5660 OstTraceExt5(TRACE_INTERNALS, PARTITIONTABLESCANNER_NEXTLBA3, "Stack[%d] RSS 0x%x 0x%x SIZE 0x%08x 0x%08x", (TInt) sp, (TUint) I64HIGH(rss), (TUint) I64LOW(rss), (TUint) I64HIGH(size), (TUint) I64LOW(size));
5665 // Look for other data partitions
5666 for (p=pS; p<pE; p+=16)
5669 if (pt.iType && pt.iSectors>0)
5671 pt.iRSS += TUint32(iLBA); // data partitions are specified relative to the EBR they appear in
5680 // If any EBRs on stack, pop off the first and process it
5684 iLBA = iFirstEBR + iStack[iStackPointer].iRSS; // LBA of second and subsequent EBR is specified relative to first EBR
5689 iLBA = KErrEof; // finished
5692 __KTRACE_OPT(KLOCDRV, Kern::Printf("<TPartitionTableScanner iLBA=%08x %08x", I64HIGH(iLBA), I64LOW(iLBA)));
5693 OstTraceExt2( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NEXTLBA3, "TPartitionTableScanner iLBA=0x%08x 0x%08x", I64HIGH(iLBA), I64LOW(iLBA) );
5694 OstTraceFunctionExit0( TPARTITIONTABLESCANNER_NEXTLBA_EXIT );
5699 * Returns Address and Length of next contiguous Physical memory fragment
5701 * @param aAddr On success, populated with the Physical Address of the next fragment.
5702 * @param aLen On success, populated with the length in bytes of the next fragment.
5704 * @return KErrNone, if successful;
5705 * KErrNoMemory, if no more memory fragments left.
5706 * KErrNotSupported, if Physical Memory addressing is not supported by this Media.
5708 EXPORT_C TInt TLocDrvRequest::GetNextPhysicalAddress(TPhysAddr& aAddr, TInt& aLen)
5710 OstTraceExt2(TRACE_FLOW, TLOCDRVREQUEST_GETNEXTPHYSICALADDRESS_ENTRY, "> TLocDrvRequest::GetNextPhysicalAddress;aAddr=%x;aLen=%d;", (TUint) &aAddr, aLen );
5711 if (Flags() & EPhysAddr)
5713 #ifdef __DEMAND_PAGING__
5714 if (DMediaPagingDevice::PagingRequest(*this))
5716 return DDmaHelper::GetPhysicalAddress(*this, aAddr, aLen);
5719 return Drive()->iDmaHelper->GetPhysicalAddress(aAddr, aLen);
5723 OstTraceFunctionExitExt( TLOCDRVREQUEST_GETNEXTPHYSICALADDRESS_EXIT, this, KErrNotSupported );
5724 return KErrNotSupported;
5729 /******************************************************************************
5731 ******************************************************************************/
5732 DECLARE_STANDARD_EXTENSION()
5734 __KTRACE_OPT(KBOOT,Kern::Printf("Starting LOCMEDIA extension"));
5736 // install the HAL function
5737 TInt r=Kern::AddHalEntry(EHalGroupMedia,MediaHalFunction,NULL);
5738 #ifdef __DEMAND_PAGING__
5741 __KTRACE_OPT(KBOOT,Kern::Printf("Creating LocDrv device"));
5742 DLocalDriveFactory* device = new DLocalDriveFactory;
5746 r=Kern::InstallLogicalDevice(device);
5747 __KTRACE_OPT(KBOOT,Kern::Printf("Installing LocDrv device in kernel returned %d",r));
5749 #endif // __DEMAND_PAGING__