sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\drivers\locmedia\locmedia.cpp sl@0: // sl@0: // sl@0: sl@0: #include "locmedia.h" sl@0: #include sl@0: #include "dmasupport.h" sl@0: #include sl@0: sl@0: #include "OstTraceDefinitions.h" sl@0: #ifdef OST_TRACE_COMPILER_IN_USE sl@0: #include "locmedia_ost.h" sl@0: #ifdef __VC32__ sl@0: #pragma warning(disable: 4127) // disabling warning "conditional expression is constant" sl@0: #endif sl@0: #include "locmediaTraces.h" sl@0: #endif sl@0: sl@0: sl@0: #if defined(_DEBUG) && defined(__DEMAND_PAGING__) sl@0: //#define __DEBUG_DEMAND_PAGING__ sl@0: #endif sl@0: sl@0: sl@0: #if 0 sl@0: #define CHECK_RET(r) if ((r)==KErrNotSupported && (KDebugNum(KSCRATCH))) {NKern::Lock(); *(TInt*)0xfaece5=0;} sl@0: //#define CHECK_RET(r) sl@0: #else sl@0: #define CHECK_RET(r) sl@0: #endif sl@0: sl@0: _LIT(KLddName,"LocDrv"); sl@0: _LIT(KLitMediaDriverName, "Media.*"); sl@0: _LIT(KLitLocMedia,"LocMedia"); sl@0: sl@0: #define LOCM_FAULT() Kern::Fault("LOCMEDIA",__LINE__) sl@0: sl@0: const TInt KMaxLocalDriveCapsLength=256; sl@0: const TInt KMaxQueryDeviceLength=256; sl@0: sl@0: // The maximum amount of user-data which will be pinned. If a request is longer sl@0: // than this value it will be split up into a number of requests sl@0: // This value is a bit arbitrary - it needs to be sufficiently large so that transfer sl@0: // rates don't suffer too much - but it can't be too big or we'd be "stealing" too much sl@0: // memory from the demand paging pool and starving other processes sl@0: const TInt KMaxPinData = 256*1024; sl@0: sl@0: // The number of locks available for pinning shared by all the drive threads in the system. sl@0: // If all locks are in use then a single pre-allocated lock is used. sl@0: const TInt KDynamicPagingLockCount = 8; sl@0: sl@0: TLocDrv* TheDrives[KMaxLocalDrives]; sl@0: DMedia* TheMedia[KMaxLocalDrives]; sl@0: HBuf* DriveNames[KMaxLocalDrives]; sl@0: TInt UsedMedia=0; sl@0: TPasswordStore* ThePasswordStore=NULL; sl@0: sl@0: class DPrimaryMediaBase::DBody : public DBase sl@0: { sl@0: public: sl@0: TInt iPhysDevIndex; sl@0: TInt iRequestCount; sl@0: #ifdef __DEMAND_PAGING__ sl@0: DMediaPagingDevice* iPagingDevice; sl@0: TInt iPageSizeMsk; // Mask of page size (e.g. 4096-1 -> 4095) sl@0: TInt iMediaChanges; sl@0: #endif sl@0: }; sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: DMediaPagingDevice* ThePagingDevices[KMaxLocalDrives]; sl@0: DPrimaryMediaBase* TheRomPagingMedia = NULL; sl@0: DPrimaryMediaBase* TheDataPagingMedia = NULL; sl@0: TBool DataPagingDeviceRegistered = EFalse; sl@0: class DPinObjectAllocator; sl@0: DPinObjectAllocator* ThePinObjectAllocator = NULL; sl@0: sl@0: // The paging media might share a DfcQ with other non-paging media (e.g. 2 MMC/SD cards sharing the same stack) sl@0: // In this case, we need to avoid taking page faults on the non-paging media too, hence the need for these checks: sl@0: inline TBool DataPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia) sl@0: {return TheDataPagingMedia && TheDataPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;} sl@0: inline TBool RomPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia) sl@0: {return TheRomPagingMedia && TheRomPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;} sl@0: sl@0: sl@0: sl@0: /* sl@0: DPinObjectAllocator sl@0: sl@0: Internal class which contains : sl@0: (1) a queue of pre-allocated TVirtualPinObject's; sl@0: (2) a single pre-allocated DFragmentationPagingLock object: sl@0: this may be used if there are no TVirtualPinObject's available or if Kern::PinVirtualMemory() fails sl@0: */ sl@0: NONSHARABLE_CLASS(DPinObjectAllocator) : public DBase sl@0: { sl@0: public: sl@0: /* sl@0: SVirtualPinContainer sl@0: Internal class encapsulating a TVirtualPinObject. sl@0: Contains a SDblQueLink so that it may form part of a SDblQue sl@0: */ sl@0: typedef struct sl@0: { sl@0: TVirtualPinObject* iObject; sl@0: SDblQueLink iLink; sl@0: } SVirtualPinContainer; sl@0: sl@0: public: sl@0: inline DPinObjectAllocator() {}; sl@0: ~DPinObjectAllocator(); sl@0: TInt Construct(TInt aObjectCount, TUint aNumPages); sl@0: sl@0: SVirtualPinContainer* AcquirePinObject(); sl@0: void ReleasePinObject(SVirtualPinContainer* aVirtualPinObject); sl@0: sl@0: inline DFragmentationPagingLock& PreAllocatedDataLock() {return *iPreAllocatedDataLock;} sl@0: sl@0: private: sl@0: // array of SVirtualPinContainer's sl@0: SVirtualPinContainer* iVirtualPinContainers; sl@0: TInt iObjectCount; sl@0: sl@0: // queues containing SVirtualPinContainer's sl@0: SDblQue iFreeQ; sl@0: sl@0: // pre-allocated (small) buffers for locking client data should Kern::PinVirtualMemory() fail sl@0: DFragmentationPagingLock* iPreAllocatedDataLock; sl@0: sl@0: // A mutex to protect access to the pinning objects. sl@0: NFastMutex iLock; sl@0: sl@0: public: sl@0: TUint iFragmentGranularity; sl@0: }; sl@0: sl@0: sl@0: DPinObjectAllocator::~DPinObjectAllocator() sl@0: { sl@0: OstTraceFunctionEntry1( DPINOBJECTALLOCATOR_DPINOBJECTALLOCATOR_ENTRY, this ); sl@0: if (iPreAllocatedDataLock) sl@0: { sl@0: iPreAllocatedDataLock->Cleanup(); sl@0: delete iPreAllocatedDataLock; sl@0: } sl@0: sl@0: for (TInt n=0; nConstruct(aNumPages); sl@0: if (r != KErrNone) sl@0: { sl@0: OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT2, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: SVirtualPinContainer* iVirtualPinContainers = new SVirtualPinContainer[aObjectCount]; sl@0: if (iVirtualPinContainers == NULL) sl@0: { sl@0: OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT3, this, KErrNoMemory ); sl@0: return KErrNoMemory; sl@0: } sl@0: memclr(iVirtualPinContainers, sizeof(SVirtualPinContainer) * aObjectCount); sl@0: iObjectCount = aObjectCount; sl@0: sl@0: // construct the queue of dynamic paging locks sl@0: for (TInt n=0; nDeque(); sl@0: } sl@0: sl@0: sl@0: NKern::FMSignal(&iLock); sl@0: OstTraceFunctionExit1( DPINOBJECTALLOCATOR_ACQUIREPINOBJECT_EXIT, this ); sl@0: return pinContainer; sl@0: } sl@0: sl@0: /** sl@0: returns a SVirtualPinContainer object to the pool sl@0: */ sl@0: void DPinObjectAllocator::ReleasePinObject(SVirtualPinContainer* aPinContainer) sl@0: { sl@0: OstTraceFunctionEntry1( DPINOBJECTALLOCATOR_RELEASEPINOBJECT_ENTRY, this ); sl@0: NKern::FMWait(&iLock); sl@0: sl@0: iFreeQ.Add(&aPinContainer->iLink); sl@0: sl@0: NKern::FMSignal(&iLock); sl@0: OstTraceFunctionExit1( DPINOBJECTALLOCATOR_RELEASEPINOBJECT_EXIT, this ); sl@0: } sl@0: sl@0: #endif // __DEMAND_PAGING__ sl@0: sl@0: sl@0: /******************************************** sl@0: * Local drive device base class sl@0: ********************************************/ sl@0: DECLARE_EXTENSION_LDD() sl@0: { sl@0: return new DLocalDriveFactory; sl@0: } sl@0: sl@0: DLocalDriveFactory::DLocalDriveFactory() sl@0: // sl@0: // Constructor sl@0: // sl@0: { sl@0: OstTraceFunctionEntry1( DLOCALDRIVEFACTORY_DLOCALDRIVEFACTORY_ENTRY, this ); sl@0: iParseMask=KDeviceAllowUnit|KDeviceAllowInfo; sl@0: iUnitsMask=~(0xffffffff<DLocalDrive::DoClose D:%d, M:%08x",iDrive->iDriveNumber,iDrive->iMedia)); sl@0: iDrive->Disconnect(this); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("iDriveNumber,iDrive->iMedia)); sl@0: } sl@0: DThread* pC=NULL; sl@0: NKern::LockSystem(); sl@0: if (iCleanup.iThread) sl@0: { sl@0: pC=iCleanup.iThread; sl@0: iCleanup.Remove(); sl@0: iCleanup.iThread=NULL; sl@0: } sl@0: NKern::UnlockSystem(); sl@0: if (pC) // original client may already have terminated sl@0: { sl@0: if (iNotifyChangeRequest) sl@0: Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrCancel); sl@0: pC->Close(NULL); // balances Open() in DoCreate sl@0: } sl@0: if (iNotifyChangeRequest) sl@0: Kern::DestroyClientRequest(iNotifyChangeRequest); sl@0: OstTraceFunctionExit1( DLOCALDRIVE_DLOCALDRIVE_EXIT, this ); sl@0: } sl@0: sl@0: TInt DLocalDrive::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer) sl@0: { sl@0: OstTraceFunctionEntry1( DLOCALDRIVE_DOCREATE_ENTRY, this ); sl@0: sl@0: if(!Kern::CurrentThreadHasCapability(ECapabilityTCB,__PLATSEC_DIAGNOSTIC_STRING("Checked by ELOCD.LDD (Local Media Driver)"))) sl@0: { sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT1, this, KErrPermissionDenied ); sl@0: return KErrPermissionDenied; sl@0: } sl@0: if (!Kern::QueryVersionSupported(TVersion(KLocalDriveMajorVersion,KLocalDriveMinorVersion,KLocalDriveBuildVersion),aVer)) sl@0: { sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT2, this, KErrNotSupported ); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: NKern::ThreadEnterCS(); sl@0: TInt r = Kern::CreateClientDataRequest(iNotifyChangeRequest); sl@0: NKern::ThreadLeaveCS(); sl@0: if (r != KErrNone) sl@0: { sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT3, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: DThread& t=Kern::CurrentThread(); sl@0: NKern::LockSystem(); sl@0: t.AddCleanup(&iCleanup); sl@0: NKern::UnlockSystem(); sl@0: t.Open(); sl@0: iNotifyChangeRequest->SetDestPtr((TBool*) anInfo); sl@0: sl@0: iDrive=TheDrives[aUnit]; sl@0: if (!iDrive) sl@0: { sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT4, this, KErrNotSupported ); sl@0: return KErrNotSupported; sl@0: } sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DLocalDrive Create - connect to drive %d, M:%08x",iDrive->iDriveNumber,iDrive->iMedia)); sl@0: r=iDrive->Connect(this); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("iDriveNumber,iDrive->iMedia,r)); sl@0: sl@0: if (r!=KErrNone) sl@0: iDrive=NULL; // didn't connect so don't disconnect sl@0: sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_DOCREATE_EXIT5, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: #if defined(_DEBUG) sl@0: void DebugDumpDriveCaps(const TLocDrv* aDrive, const TAny* aCaps) sl@0: { sl@0: const TLocalDriveCapsV5& c=*(const TLocalDriveCapsV5*)aCaps; sl@0: Kern::Printf("Drive %d Caps:", aDrive->iDriveNumber); sl@0: Kern::Printf("Size: %lx", c.iSize); sl@0: Kern::Printf("Type: %08x", c.iType); sl@0: Kern::Printf("Bus : %08x", c.iConnectionBusType); sl@0: Kern::Printf("DAtt: %08x", c.iDriveAtt); sl@0: Kern::Printf("MAtt: %08x", c.iMediaAtt); sl@0: Kern::Printf("Base: %08x", c.iBaseAddress); sl@0: Kern::Printf("FSID: %04x", c.iFileSystemId); sl@0: Kern::Printf("PTYP: %04x", c.iPartitionType); sl@0: Kern::Printf("HIDN: %08x", c.iHiddenSectors); sl@0: Kern::Printf("EBSZ: %08x", c.iEraseBlockSize); sl@0: //---------------- V5 ------------------// sl@0: if (c.iSerialNumLength != 0) sl@0: { sl@0: Kern::Printf("SN: length is %d", c.iSerialNumLength); sl@0: TBuf8<2*KMaxSerialNumLength+20> snBuf; sl@0: snBuf.Append(_L8("SN: content is ")); sl@0: for (TUint i=0; iDLocalDrive::DoControl D:%d M:%08x F:%d A1:%08x A2:%08x", sl@0: iDrive->iDriveNumber, iDrive->iMedia, aFunction, a1, a2)); sl@0: OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST, "iMedia=0x%08x; iDriveNumber=%d; Request Id=%d", (TUint) iDrive->iMedia, (TInt) iDrive->iDriveNumber, (TInt) aFunction ); sl@0: sl@0: TInt r=KErrNotSupported; sl@0: TLocDrvRequest& m=TLocDrvRequest::Get(); sl@0: m.Flags()=0; sl@0: m.Drive()=iDrive; sl@0: switch (aFunction) sl@0: { sl@0: case RLocalDrive::EControlRead: sl@0: { sl@0: m.Id()=ERead; sl@0: r=m.ProcessMessageData(a1); sl@0: __TRACE_TIMING(1); sl@0: if (r==KErrNone) sl@0: { sl@0: __TRACE_TIMING(2); sl@0: OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READ, "ERead iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: __TRACE_TIMING(3); sl@0: OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READ_RETURN, "ERead Return iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m ); sl@0: } sl@0: m.CloseRemoteThread(); sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlWrite: sl@0: { sl@0: m.Id()=EWrite; sl@0: r=m.ProcessMessageData(a1); sl@0: if (r==KErrNone) sl@0: { sl@0: OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITE, "EWrite iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m ); sl@0: r=iDrive->Request(m); sl@0: OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITE_RETURN, "EWrite Return iDriveNumber=%d; length=0x%x; position=0x%x; TLocDrvRequest Object=0x%x", (TInt) iDrive->iDriveNumber, (TUint) m.Length(), (TUint) m.Pos(), (TUint) &m ); sl@0: } sl@0: m.CloseRemoteThread(); sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlCaps: sl@0: { sl@0: TBuf8 capsBuf; sl@0: capsBuf.SetMax(); sl@0: capsBuf.FillZ(); sl@0: m.Id()=ECaps; sl@0: m.RemoteDes()=(TAny*)capsBuf.Ptr(); // overload this sl@0: m.Length()=KMaxLocalDriveCapsLength; // for pinning sl@0: r=iDrive->Request(m); sl@0: sl@0: if(r == KErrNone && iDrive->iMedia != NULL && iDrive->iMedia->iDriver != NULL) sl@0: { sl@0: // Fill in default media size if not specified by the driver sl@0: // sl@0: // - This uses the members of TLocalDriveCapsV4 which was primarily used sl@0: // to report NAND flash characteristics, but are general enough to be sl@0: // used to report the size of any type of media without adding yet sl@0: // another extension to TLocalDriveCapsVx. sl@0: // sl@0: sl@0: TLocalDriveCapsV4& caps = *(TLocalDriveCapsV4*)capsBuf.Ptr(); sl@0: sl@0: if(caps.iSectorSizeInBytes == 0) sl@0: { sl@0: // Fill in a default value for the disk sector size sl@0: caps.iSectorSizeInBytes = 512; sl@0: sl@0: // Zero the number of sectors, as a sector count makes no sense without a sector size sl@0: // - Fault in debug mode if a sector count is provided to ensure that media driver creators sl@0: // set this value,but in release mode continue gracefully be recalculating the sector count. sl@0: __ASSERT_DEBUG(caps.iNumberOfSectors == 0, LOCM_FAULT()); sl@0: caps.iNumberOfSectors = 0; sl@0: caps.iNumPagesPerBlock = 1; // ...to ensure compatiility with NAND semantics sl@0: } sl@0: sl@0: if(caps.iNumberOfSectors == 0) sl@0: { sl@0: const Int64 totalSizeInSectors = iDrive->iMedia->iDriver->TotalSizeInBytes() / caps.iSectorSizeInBytes; sl@0: __ASSERT_DEBUG(I64HIGH(totalSizeInSectors) == 0, LOCM_FAULT()); sl@0: sl@0: if(I64HIGH(totalSizeInSectors) == 0) sl@0: { sl@0: caps.iNumberOfSectors = I64LOW(totalSizeInSectors); sl@0: } sl@0: } sl@0: } sl@0: sl@0: #if defined(OST_TRACE_COMPILER_IN_USE) && defined(_DEBUG) sl@0: const TLocalDriveCapsV5& caps=*(const TLocalDriveCapsV5*)capsBuf.Ptr(); sl@0: #endif sl@0: sl@0: OstTraceExt5( TRACE_INTERNALS, DLOCALDRIVE_REQUEST_CAPS1, "Device caps: iDriveNumber=%d; iSize=0x%x; iType=%d; iDriveAtt=%d; TLocDrvRequest Object=0x%x", (TInt)iDrive->iDriveNumber, (TUint) caps.iSize, (TInt) caps.iType, (TInt) caps.iDriveAtt, (TUint) &m); sl@0: OstTraceExt5( TRACE_INTERNALS, DLOCALDRIVE_REQUEST_CAPS2, "Device caps: iBaseAddress=0x%x; iFileSystemId=%d; iPartitionType=%d; iHiddenSectors=0x%x; iEraseBlockSize=0x%x", (TUint) caps.iBaseAddress, (TInt) caps.iFileSystemId, (TUint) caps.iPartitionType, (TUint) caps.iHiddenSectors, (TUint) caps.iEraseBlockSize); sl@0: sl@0: #if defined(_DEBUG) sl@0: __KTRACE_OPT(KLOCDRV,DebugDumpDriveCaps(iDrive,capsBuf.Ptr())); sl@0: #endif sl@0: Kern::InfoCopy(*(TDes8*)a1, capsBuf); sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlFormat: sl@0: { sl@0: m.Id()=EFormat; sl@0: r=m.ProcessMessageData(a1); sl@0: if (r==KErrNone) sl@0: { sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORMAT, "EFormat; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORMAT_RETURN, "EFormat Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: } sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlEnlarge: sl@0: if ((TInt)a1<0) sl@0: { sl@0: r=KErrArgument; sl@0: break; sl@0: } sl@0: m.Length()=(TInt)a1; sl@0: m.Id()=EEnlarge; sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_ENLARGE, "EEnlarge; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_ENLARGE_RETURN, "EEnlarge Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: break; sl@0: case RLocalDrive::EControlReduce: sl@0: { sl@0: if ((TInt)a1<0 || (TInt)a2<0) sl@0: { sl@0: r=KErrArgument; sl@0: break; sl@0: } sl@0: m.Pos()=(TInt)a1; sl@0: m.Length()=(TInt)a2; sl@0: m.Id()=EReduce; sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_REDUCE, "EReduce; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_REDUCE_RETURN, "EReduce Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlForceMediaChange: sl@0: m.Pos()=(TInt)a1; sl@0: m.Id()=EForceMediaChange; sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORCEMEDIACHANGE, "EForceMediaChange; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r = iDrive->Request(m); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_FORCEMEDIACHANGE_RETURN, "EForceMediaChange Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: break; sl@0: case RLocalDrive::EControlMediaDevice: sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLMEDIADEVICE, "EControlMediaDevice; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->iPrimaryMedia->iDevice; sl@0: break; sl@0: case RLocalDrive::EControlIsRemovable: sl@0: { sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLISREMOVABLE, "EControlIsRemovable; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: TInt sockNum; sl@0: r=iDrive->iPrimaryMedia->IsRemovableDevice(sockNum); sl@0: if (r) sl@0: kumemput32(a1,&sockNum,sizeof(TInt)); sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlControlIO: sl@0: { sl@0: TLocalDriveControlIOData d; sl@0: kumemget32(&d,a1,sizeof(d)); sl@0: sl@0: m.Id() = EControlIO; sl@0: m.iArg[0] = (TAny*) d.iCommand; sl@0: m.iArg[1] = d.iParam1; sl@0: m.iArg[2] = d.iParam2; sl@0: sl@0: // if d.iHandle is == KLocalMessageHandle (-1), sl@0: // d.aParam1 and d.aParam2 are TAny* pointers sl@0: // sl@0: // if d.iHandle is == 0, sl@0: // d.aParam1 and d.aParam2 are TInts sl@0: // sl@0: // if d.iHandle is > 0, sl@0: // d.aParam1 is a data pointer (TUint8*) sl@0: // d.aParam2 is an optional extra paramater (TInt) sl@0: // d.iHandle is a data length (TInt) sl@0: m.iArg[3] = (TAny*) d.iHandle; sl@0: sl@0: //We're highjacking fields representing sl@0: //length and position in a normal message, so sl@0: //let's not have the dispatcher function attempt sl@0: //to adjust for partition size. sl@0: m.Flags() |= TLocDrvRequest::EAdjusted; sl@0: sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLCONTROLIO, "EControlControlIO; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLCONTROLIO_RETURN, "EControlControlIO Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlSetMountInfo: sl@0: { sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLSETMOUNTINFO, "EControlSetMountInfo; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: m.Id()=ERead; sl@0: r=m.ProcessMessageData(a1); sl@0: DPrimaryMediaBase* pM=iDrive->iPrimaryMedia; sl@0: if(!pM || r!=KErrNone) sl@0: break; sl@0: sl@0: if (pM->iMountInfo.iThread) sl@0: { sl@0: NKern::ThreadEnterCS(); sl@0: //Close original thread sl@0: Kern::SafeClose((DObject*&) pM->iMountInfo.iThread,NULL); sl@0: if (m.RemoteDes()!=NULL) sl@0: { sl@0: //Set new mount info and leave setting thread open sl@0: #ifdef __DEMAND_PAGING__ sl@0: // lock the mount info if this is a data paging media - and keep it locked sl@0: if ((DataPagingDfcQ(pM)) && ((r = LockMountInfo(*pM, m)) != KErrNone)) sl@0: break; sl@0: #endif sl@0: pM->iMountInfo.iInfo=(TDesC8*)m.RemoteDes(); sl@0: pM->iMountInfo.iThread=m.RemoteThread(); sl@0: } sl@0: else sl@0: { sl@0: //Clear existing mount info and close setting thread sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: // unlock the mount info if this is a data paging media sl@0: UnlockMountInfo(*pM); sl@0: #endif sl@0: sl@0: pM->iMountInfo.iInfo=NULL; sl@0: pM->iMountInfo.iThread=NULL; sl@0: m.CloseRemoteThread(); sl@0: } sl@0: NKern::ThreadLeaveCS(); sl@0: r=KErrNone; sl@0: } sl@0: else sl@0: { sl@0: //Setting mount info for the first time sl@0: if (m.RemoteDes()==NULL) sl@0: { sl@0: // if no mount info, close setting thread opened in ProcessMessageData() sl@0: m.CloseRemoteThread(); sl@0: break; sl@0: } sl@0: sl@0: NKern::ThreadEnterCS(); sl@0: #ifdef __DEMAND_PAGING__ sl@0: // lock the mount info if this is a data paging media - and keep it locked sl@0: if ((DataPagingDfcQ(pM)) && ((r = LockMountInfo(*pM, m)) != KErrNone)) sl@0: break; sl@0: #endif sl@0: sl@0: pM->iMountInfo.iInfo=(TDesC8*)m.RemoteDes(); sl@0: pM->iMountInfo.iThread=m.RemoteThread(); sl@0: NKern::ThreadLeaveCS(); sl@0: r=KErrNone; sl@0: } sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlPasswordLock: sl@0: { sl@0: m.Id()=EPasswordLock; sl@0: m.RemoteDes() = a1; sl@0: sl@0: TMediaPassword oldPasswd; sl@0: TMediaPassword newPasswd; sl@0: TLocalDrivePasswordData pswData; sl@0: r = ReadPasswordData(m, pswData, oldPasswd, newPasswd); sl@0: sl@0: if (r == KErrNone) sl@0: { sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDLOCK, "EPasswordLock; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r = iDrive->Request(m); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDLOCK_RETURN, "EPasswordLock Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: } sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlPasswordUnlock: sl@0: { sl@0: m.Id()=EPasswordUnlock; sl@0: m.RemoteDes() = a1; sl@0: sl@0: TMediaPassword oldPasswd; sl@0: TMediaPassword newPasswd; sl@0: TLocalDrivePasswordData pswData; sl@0: r = ReadPasswordData(m, pswData, oldPasswd, newPasswd); sl@0: sl@0: if(r == KErrNone) sl@0: { sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDUNLOCK, "EPasswordUnLock; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDUNLOCK_RETURN, "EPasswordUnLock Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: } sl@0: if (r == KErrNone) sl@0: iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0; sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlPasswordClear: sl@0: { sl@0: m.Id()=EPasswordClear; sl@0: m.RemoteDes() = a1; sl@0: sl@0: TMediaPassword oldPasswd; sl@0: TMediaPassword newPasswd; sl@0: TLocalDrivePasswordData pswData; sl@0: r = ReadPasswordData(m, pswData, oldPasswd, newPasswd); sl@0: sl@0: if (r == KErrNone) sl@0: { sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDCLEAR, "EPasswordClear; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r = iDrive->Request(m); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDCLEAR_RETURN, "EPasswordClear Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: } sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlPasswordErase: sl@0: { sl@0: m.Id()=EPasswordErase; sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDERASE, "EPasswordErase; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDERASE_RETURN, "EPasswordErase Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: if(r == KErrNone) sl@0: iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0; sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlNotifyChange: sl@0: if (iCleanup.iThread != &Kern::CurrentThread()) sl@0: Kern::PanicCurrentThread(KLitLocMedia,KErrAccessDenied); sl@0: r=KErrNone; sl@0: if (!iNotifyChangeRequest->StatusPtr()) sl@0: r = iNotifyChangeRequest->SetStatus((TRequestStatus*) a1); sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLNOTIFYCHANGE, "EControlNotifyChange; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: break; sl@0: case RLocalDrive::EControlNotifyChangeCancel: sl@0: if (iCleanup.iThread != &Kern::CurrentThread()) sl@0: Kern::PanicCurrentThread(KLitLocMedia,KErrAccessDenied); sl@0: Kern::QueueRequestComplete(iCleanup.iThread,iNotifyChangeRequest,KErrCancel); sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLNOTIFYCHANGECANCEL, "EControlNotifyChangeCancel; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: break; sl@0: case RLocalDrive::EControlReadPasswordStore: sl@0: { sl@0: TUint8 passData[TPasswordStore::EMaxPasswordLength]; sl@0: m.RemoteDes() = (TAny*) passData; sl@0: m.Length() = sizeof(passData); sl@0: m.Id()=EReadPasswordStore; sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READPASSWORDSTORE, "EReadPasswordStore; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_READPASSWORDSTORE_RETURN, "EReadPasswordStore Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: if (r==KErrNone) sl@0: { sl@0: TPtr8 pData(passData, (TInt) m.Length(), TPasswordStore::EMaxPasswordLength); sl@0: m.RemoteDes()=(TDes8*)a1; sl@0: r = m.WriteRemote(&pData,0); sl@0: } sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlWritePasswordStore: sl@0: { sl@0: TUint8 passData[TPasswordStore::EMaxPasswordLength]; sl@0: TPtr8 pData(passData, TPasswordStore::EMaxPasswordLength); sl@0: sl@0: DThread* pT=m.RemoteThread(); sl@0: if (!pT) sl@0: pT=m.Client(); sl@0: sl@0: m.RemoteDes() = (TDes8*)a1; sl@0: r = Kern::ThreadGetDesLength(pT, m.RemoteDes()); sl@0: if ( r > pData.MaxLength() ) sl@0: r = KErrOverflow; sl@0: if ( r < KErrNone) sl@0: break; sl@0: sl@0: r = m.ReadRemote(&pData,0); sl@0: if (r != KErrNone) sl@0: break; sl@0: sl@0: sl@0: m.RemoteDes() = (TAny*) pData.Ptr(); sl@0: m.Length() = pData.Length(); sl@0: m.Id()=EWritePasswordStore; sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITEPASSWORDSTORE, "EWritePasswordStore; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_WRITEPASSWORDSTORE_RETURN, "EReadPasswordStore Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: if(r == KErrNone) sl@0: iDrive->iPrimaryMedia->iTotalPartitionsOpened = 0; sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlPasswordStoreLengthInBytes: sl@0: { sl@0: m.Id()=EPasswordStoreLengthInBytes; sl@0: TInt length; sl@0: m.RemoteDes() = (TAny*) &length; sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDSTORELENGTH, "EPasswordStoreLengthInBytes; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_PASSWORDSTORELENGTH_RETURN, "EPasswordStoreLengthInBytes Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: sl@0: if (r == KErrNone) sl@0: { sl@0: m.RemoteDes()=a1; sl@0: r = m.WriteRemoteRaw(&length,sizeof(TInt)); sl@0: } sl@0: sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlGetLastErrorInfo: sl@0: { sl@0: m.Id()=EGetLastErrorInfo; sl@0: m.iArg[0]=this; sl@0: TErrorInfoBuf errorInfoBuf; sl@0: errorInfoBuf.SetMax(); sl@0: errorInfoBuf.FillZ(); sl@0: m.RemoteDes()=(TAny*) errorInfoBuf.Ptr(); // overload this sl@0: m.Length() = errorInfoBuf.MaxLength(); sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_GETLASTERRORINFO, "EGetLastErrorInfo; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLGETLASTERRORINFO_RETURN, "EControlGetLastErrorInfo Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: Kern::InfoCopy(*(TDes8*)a1, errorInfoBuf); sl@0: break; sl@0: } sl@0: case RLocalDrive::EControlDeleteNotify: sl@0: { sl@0: m.Id()=EDeleteNotify; sl@0: r=m.ProcessMessageData(a1); sl@0: if (r==KErrNone) sl@0: { sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_DELETENOTIFY, "EDeleteNotify; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_DELETENOTIFY_RETURN, "EDeleteNotify Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case RLocalDrive::EControlQueryDevice: sl@0: { sl@0: TBuf8 queryBuf; sl@0: queryBuf.SetMax(); sl@0: queryBuf.FillZ(); sl@0: sl@0: m.Id() = EQueryDevice; sl@0: m.iArg[0] = a1; // RLocalDrive::TQueryDevice sl@0: m.RemoteDes() = (TAny*)queryBuf.Ptr(); // overload this sl@0: m.Length() = KMaxLocalDriveCapsLength; // for pinning sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE, "EQueryDevice; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: r=iDrive->Request(m); sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE_RETURN, "EQueryDevice Return; TLocDrvRequest Object=0x%x", (TUint) &m); sl@0: Kern::InfoCopy(*(TDes8*)a2, queryBuf); sl@0: break; sl@0: } sl@0: sl@0: } sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("iDriveNumber, iDrive->iMedia, r)); sl@0: __TRACE_TIMING(4); sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_REQUEST_EXIT, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: TInt DLocalDrive::ReadPasswordData(TLocDrvRequest& aReq, TLocalDrivePasswordData& aPswData, TMediaPassword& aOldPasswd, TMediaPassword& aNewPasswd) sl@0: { sl@0: TLocalDrivePasswordData clientData; sl@0: TInt r = aReq.ReadRemoteRaw(&clientData, sizeof(TLocalDrivePasswordData)); sl@0: sl@0: DThread* pT = aReq.RemoteThread(); sl@0: if (!pT) sl@0: pT = aReq.Client(); sl@0: sl@0: if (r == KErrNone) sl@0: r = Kern::ThreadDesRead(pT, clientData.iOldPasswd, aOldPasswd, 0 ,KChunkShiftBy0); sl@0: if (r == KErrNone) sl@0: r = Kern::ThreadDesRead(pT, clientData.iNewPasswd, aNewPasswd, 0 ,KChunkShiftBy0); sl@0: sl@0: aPswData.iStorePasswd = clientData.iStorePasswd; sl@0: aPswData.iOldPasswd = &aOldPasswd; sl@0: aPswData.iNewPasswd = &aNewPasswd; sl@0: sl@0: sl@0: aReq.RemoteDes() = (TAny*) &aPswData; sl@0: aReq.Flags()|= TLocDrvRequest::EKernelBuffer; sl@0: sl@0: return r; sl@0: } sl@0: sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: TInt DLocalDrive::LockMountInfo(DPrimaryMediaBase& aPrimaryMedia, TLocDrvRequest& aReq) sl@0: { sl@0: OstTraceExt2(TRACE_FLOW, DLOCALDRIVE_LOCKMOUNTINFO_ENTRY, "> aPrimaryMedia=%x;aReq=%x", (TUint) &aPrimaryMedia, (TUint) &aReq ); sl@0: DMediaPagingDevice* pagingDevice = aPrimaryMedia.iBody->iPagingDevice; sl@0: if (pagingDevice == NULL) sl@0: { sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT1, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: __ASSERT_DEBUG(pagingDevice->iMountInfoDataLock == NULL, LOCM_FAULT()); sl@0: __ASSERT_DEBUG(pagingDevice->iMountInfoDescHdrLock == NULL, LOCM_FAULT()); sl@0: __ASSERT_DEBUG(pagingDevice->iMountInfoDescLenLock == NULL, LOCM_FAULT()); sl@0: sl@0: DThread* pT = aReq.RemoteThread(); sl@0: if (!pT) sl@0: pT = &Kern::CurrentThread(); // e.g. when using TBusLocalDrive directly sl@0: sl@0: TInt length = 0; sl@0: TInt maxLength = 0; sl@0: TUint8* desAddress = NULL; sl@0: TInt r = Kern::ThreadGetDesInfo(pT,aReq.RemoteDes(),length,maxLength,desAddress,EFalse); // get descriptor length, maxlength and desAddress sl@0: if (r != KErrNone) sl@0: { sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT2, this, r ); sl@0: return r; sl@0: } sl@0: if (length == 0) sl@0: { sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT3, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: static const TUint8 LengthLookup[16]={4,8,12,8,12,0,0,0,0,0,0,0,0,0,0,0}; sl@0: TUint32 desHdr; sl@0: r = Kern::ThreadRawRead(pT, aReq.RemoteDes(), &desHdr, sizeof(desHdr)); sl@0: if(r!=KErrNone) sl@0: { sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT4, this, r ); sl@0: return r; sl@0: } sl@0: TInt desType = desHdr >>KShiftDesType8; sl@0: TInt desHdrLen = LengthLookup[desType]; sl@0: if(!desHdrLen) sl@0: { sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT5, this, KErrBadDescriptor ); sl@0: return KErrBadDescriptor; sl@0: } sl@0: sl@0: sl@0: pagingDevice->iMountInfoDataLock = ThePinObjectAllocator->AcquirePinObject(); sl@0: pagingDevice->iMountInfoDescHdrLock = ThePinObjectAllocator->AcquirePinObject(); sl@0: pagingDevice->iMountInfoDescLenLock = ThePinObjectAllocator->AcquirePinObject(); sl@0: sl@0: if (pagingDevice->iMountInfoDataLock == NULL || sl@0: pagingDevice->iMountInfoDescHdrLock == NULL || sl@0: pagingDevice->iMountInfoDescLenLock == NULL) sl@0: { sl@0: UnlockMountInfo(aPrimaryMedia); // tidy up sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT6, this, KErrNoMemory ); sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: sl@0: // First pin the descriptor header sl@0: DPinObjectAllocator::SVirtualPinContainer* lock; sl@0: lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock; sl@0: r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) (TUint8*) aReq.RemoteDes(), desHdrLen, pT); sl@0: if (r != KErrNone) sl@0: { sl@0: UnlockMountInfo(aPrimaryMedia); // tidy up sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT7, this, KErrNoMemory ); sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: sl@0: sl@0: // For EBufCPtr-type descriptors, need to pin the extra length before the buffer (!) sl@0: lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock; sl@0: if (desType == EBufCPtr) sl@0: { sl@0: TLinAddr extraLenAddr = TLinAddr(desAddress) - aReq.RemoteDesOffset() - sizeof(TUint32); sl@0: r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) (TUint8*) extraLenAddr, sizeof(TUint32), pT); sl@0: if (r != KErrNone) sl@0: { sl@0: UnlockMountInfo(aPrimaryMedia); // tidy up sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT8, this, KErrNoMemory ); sl@0: return KErrNoMemory; sl@0: } sl@0: } sl@0: sl@0: sl@0: // Now pin the descriptor contents sl@0: lock = (DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock; sl@0: r = Kern::PinVirtualMemory(lock->iObject, (TLinAddr) desAddress, length, pT); sl@0: if (r != KErrNone) sl@0: { sl@0: UnlockMountInfo(aPrimaryMedia); // tidy up sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT9, this, KErrNoMemory ); sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: OstTraceFunctionExitExt( DLOCALDRIVE_LOCKMOUNTINFO_EXIT10, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: void DLocalDrive::UnlockMountInfo(DPrimaryMediaBase& aPrimaryMedia) sl@0: { sl@0: OstTrace1(TRACE_FLOW, DLOCALDRIVE_UNLOCKMOUNTINFO_ENTRY, "> DLocalDrive::UnlockMountInfo;aPrimaryMedia=%x", (TUint) &aPrimaryMedia); sl@0: sl@0: DMediaPagingDevice* pagingDevice = aPrimaryMedia.iBody->iPagingDevice; sl@0: if (pagingDevice == NULL || pagingDevice->iMountInfoDataLock == NULL) sl@0: { sl@0: OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT1, this ); sl@0: return; sl@0: } sl@0: sl@0: sl@0: if (pagingDevice->iMountInfoDataLock) sl@0: { sl@0: Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock)->iObject); sl@0: ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDataLock); sl@0: pagingDevice->iMountInfoDataLock = NULL; sl@0: } sl@0: sl@0: if (pagingDevice->iMountInfoDescHdrLock) sl@0: { sl@0: Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock)->iObject); sl@0: ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescHdrLock); sl@0: pagingDevice->iMountInfoDescHdrLock = NULL; sl@0: } sl@0: sl@0: if (pagingDevice->iMountInfoDescLenLock) sl@0: { sl@0: Kern::UnpinVirtualMemory(((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock)->iObject); sl@0: ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) pagingDevice->iMountInfoDescLenLock); sl@0: pagingDevice->iMountInfoDescLenLock = NULL; sl@0: } sl@0: sl@0: OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT2, this ); sl@0: } sl@0: #endif // __DEMAND_PAGING__ sl@0: sl@0: void DLocalDrive::NotifyChange(DPrimaryMediaBase& aPrimaryMedia, TBool aMediaChange) sl@0: { sl@0: OstTraceExt2( TRACE_FLOW, DLOCALDRIVE_NOTIFYCHANGE_ENTRY, "> DLocalDrive::NotifyChange;aPrimaryMedia=%x;aMediaChange=%d", (TUint) &aPrimaryMedia, aMediaChange ); sl@0: #ifndef __DEMAND_PAGING__ sl@0: aPrimaryMedia; sl@0: #endif sl@0: sl@0: // Complete any notification request on media change or power down sl@0: if (aMediaChange) sl@0: { sl@0: DThread* pC=NULL; sl@0: NKern::LockSystem(); sl@0: if (iCleanup.iThread) sl@0: { sl@0: pC=iCleanup.iThread; sl@0: pC->Open(); sl@0: } sl@0: NKern::UnlockSystem(); sl@0: if (pC) sl@0: { sl@0: TBool b = ETrue; sl@0: // if change not yet queued, queue it now sl@0: if (iNotifyChangeRequest->IsReady()) sl@0: { sl@0: *((TBool*) iNotifyChangeRequest->Buffer()) = b; sl@0: Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrNone); sl@0: } sl@0: // If change has not even been requested by the client, maintain the pre-wdp behaviour sl@0: // and write data immediately back to client (possibly taking a page fault) sl@0: // N.B. Must NOT do this on data paging media sl@0: #ifdef __DEMAND_PAGING__ sl@0: else if (!DataPagingDfcQ(&aPrimaryMedia)) sl@0: #else sl@0: else sl@0: #endif sl@0: { sl@0: Kern::ThreadRawWrite(pC, iNotifyChangeRequest->DestPtr(), &b, sizeof(b), NULL); sl@0: } sl@0: pC->AsyncClose(); sl@0: } sl@0: } sl@0: OstTraceFunctionExit1( DLOCALDRIVE_NOTIFYCHANGE_EXIT, this ); sl@0: } sl@0: sl@0: TLocalDriveCleanup::TLocalDriveCleanup() sl@0: { sl@0: } sl@0: sl@0: // This will be called when the original client thread exits sl@0: // It is called in the context of the exiting thread with the system locked. sl@0: void TLocalDriveCleanup::Cleanup() sl@0: { sl@0: DLocalDrive& d=LocalDrive(); sl@0: d.iNotifyChangeRequest=NULL; sl@0: DThread* pC=iThread; sl@0: Remove(); sl@0: iThread=NULL; sl@0: NKern::UnlockSystem(); sl@0: pC->Close(NULL); // balances Open() in DoCreate sl@0: NKern::LockSystem(); sl@0: } sl@0: sl@0: /******************************************** sl@0: * Local drive request class sl@0: ********************************************/ sl@0: sl@0: /** sl@0: Reads data from the descriptor specified in the request, from the requesting sl@0: thread's process. sl@0: sl@0: This is used by the media driver to read data from a descriptor in the sl@0: requesting thread. The remote data is copied into the specified descriptor, sl@0: starting at the specified offset within that descriptor's data area. sl@0: sl@0: @param aDes The target descriptor into which data from the remote thread sl@0: is to be put. sl@0: @param anOffset The offset within the target descriptor data area, where data sl@0: from the remote thread is to be put. Note that this parameter sl@0: may be useful when write operations to the media must be broken sl@0: up into smaller chunks than the length requested. sl@0: sl@0: @return KErrNone,if successful, otherwise one of the other sl@0: system-wide error codes. sl@0: sl@0: @see Kern::ThreadDesRead() sl@0: */ sl@0: EXPORT_C TInt TLocDrvRequest::ReadRemote(TDes8* aDes, TInt anOffset) sl@0: { sl@0: OstTraceFunctionEntry1( TLOCDRVREQUEST_READREMOTE_ENTRY, this ); sl@0: TInt r; sl@0: DThread* pT=RemoteThread(); sl@0: if (!pT) sl@0: pT=Client(); sl@0: sl@0: #ifdef __DEMAND_PAGING__ // only if driver has its own thread, we don't support paging in MD which run in the context of their clients sl@0: if (Flags() & ETClientBuffer) sl@0: { sl@0: r = Kern::ThreadBufRead(pT, (TClientBuffer*) RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0); sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTE_EXIT1, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: __ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT()); sl@0: #endif sl@0: r = Kern::ThreadDesRead(pT,RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0); sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTE_EXIT2, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Reads data from an arbitrary descriptor in the requesting thread's process. sl@0: sl@0: This is used by the media driver to read data from a descriptor in the sl@0: requesting thread. sl@0: sl@0: NB This is NOT supported on datapaging media as there is no guarantee sl@0: that the remote descriptor won't be paged out. If this function is called and sl@0: data-paging is enabled the kernel will fault in debug mode and return sl@0: KErrNotSupported in release mode. sl@0: sl@0: @param aSrc A pointer to the source descriptor in the requesting thread's sl@0: address space. sl@0: @param aDes The target descriptor into which data from the remote thread sl@0: is to be put. sl@0: sl@0: @return KErrNone,if successful, sl@0: KErrNotSupported if data-paging is enabled sl@0: otherwise one of the other system-wide error codes. sl@0: sl@0: @see Kern::ThreadDesRead() sl@0: */ sl@0: EXPORT_C TInt TLocDrvRequest::ReadRemote(const TAny* aSrc, TDes8* aDes) sl@0: { sl@0: OstTraceFunctionEntry1( TLOCDRVREQUEST_READ_REMOTE_ENTRY, this ); sl@0: if (Flags() & TLocDrvRequest::EKernelBuffer) sl@0: { sl@0: aDes->Copy(* (TDesC8*) aSrc); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt r; sl@0: DThread* pT=RemoteThread(); sl@0: if (!pT) sl@0: pT=Client(); sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: __ASSERT_DEBUG(!DataPagingDfcQ(Drive()->iPrimaryMedia), LOCM_FAULT()); sl@0: sl@0: if (DataPagingDfcQ(Drive()->iPrimaryMedia)) sl@0: { sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_READ_REMOTE_EXIT1, this, KErrNotSupported ); sl@0: return KErrNotSupported; sl@0: } sl@0: #endif sl@0: sl@0: r = Kern::ThreadDesRead(pT,aSrc,*aDes,0,KChunkShiftBy0); sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_READ_REMOTE_EXIT2, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Reads raw data from the requesting thread's process. sl@0: sl@0: This is used by the media driver to read raw data from a location in requesting sl@0: thread's address space. The remote data is copied into the specified sl@0: buffer. sl@0: sl@0: @param aDest A pointer to the buffer where the data is to be written. sl@0: @param aSize The number of bytes to read. sl@0: sl@0: @return KErrNone,if successful, otherwise one of the other sl@0: system-wide error codes. sl@0: sl@0: @see Kern::ThreadRawRead() sl@0: */ sl@0: EXPORT_C TInt TLocDrvRequest::ReadRemoteRaw(TAny* aDest, TInt aSize) sl@0: { sl@0: OstTraceFunctionEntry1( TLOCDRVREQUEST_READREMOTERAW_ENTRY, this ); sl@0: if (Flags() & TLocDrvRequest::EKernelBuffer) sl@0: { sl@0: (void)memcpy(aDest, (TAny*) RemoteDes(), aSize); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt r; sl@0: DThread* pT=RemoteThread(); sl@0: if (!pT) sl@0: pT=Client(); sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: __ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT()); sl@0: #endif sl@0: sl@0: r = Kern::ThreadRawRead(pT,RemoteDes(),aDest,aSize); sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_READREMOTERAW_EXIT, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Writes data to a descriptor in the requesting thread's process. sl@0: sl@0: This is used by the media driver to write data to a descriptor in the requesting sl@0: thread. Data is copied from the specified descriptor, starting at the specified sl@0: offset within that descriptor's data area. sl@0: sl@0: @param aDes The source descriptor from which data is to be written to sl@0: the remote thread. sl@0: sl@0: @param anOffset The offset within the source descriptor data area, from where data sl@0: is to be written to the remote thread. Note that this parameter sl@0: may be useful when read operations from the media must be broken sl@0: up into smaller chunks than the length requested. sl@0: sl@0: @return KErrNone,if successful, otherwise one of the other sl@0: system-wide error codes. sl@0: sl@0: @see Kern::ThreadDesWrite() sl@0: */ sl@0: EXPORT_C TInt TLocDrvRequest::WriteRemote(const TDesC8* aDes, TInt anOffset) sl@0: { sl@0: OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITEREMOTE_ENTRY, this ); sl@0: TInt r; sl@0: DThread* pC=Client(); sl@0: DThread* pT=RemoteThread(); sl@0: if (!pT) sl@0: pT=pC; sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: if (Flags() & ETClientBuffer) sl@0: { sl@0: r = Kern::ThreadBufWrite(pT, (TClientBuffer*) RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC); sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT1, this, r ); sl@0: return r; sl@0: } sl@0: #endif sl@0: r = Kern::ThreadDesWrite(pT,RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC); sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT2, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Writes raw data to the requesting thread's process. sl@0: sl@0: This is used by the media driver to write raw data to a location in the sl@0: requesting thread's address space. sl@0: sl@0: @param aSrc The source addres from which data is to be written to sl@0: the remote thread. sl@0: sl@0: @param aSize The number of bytes to write. sl@0: sl@0: @return KErrNone,if successful, otherwise one of the other sl@0: system-wide error codes. sl@0: sl@0: @see Kern::ThreadRawWrite() sl@0: */ sl@0: EXPORT_C TInt TLocDrvRequest::WriteRemoteRaw(const TAny* aSrc, TInt aSize) sl@0: { sl@0: OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITEREMOTERAW_ENTRY, this ); sl@0: TInt r; sl@0: DThread* pC=Client(); sl@0: DThread* pT=RemoteThread(); sl@0: if (!pT) sl@0: pT=pC; sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: __ASSERT_ALWAYS((Flags() & ETClientBuffer) == 0, LOCM_FAULT()); sl@0: #endif sl@0: r = Kern::ThreadRawWrite(pT,RemoteDes(),aSrc,aSize,pC); sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTERAW_EXIT, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: TInt TLocDrvRequest::ProcessMessageData(TAny* aPtr) sl@0: // sl@0: // Get read/write parameters from client and open remote thread sl@0: // sl@0: { sl@0: OstTraceFunctionEntry1( TLOCDRVREQUEST_PROCESSMESSAGEDATA_ENTRY, this ); sl@0: RemoteThread()=NULL; sl@0: DThread& t=Kern::CurrentThread(); sl@0: TLocalDriveMessageData d; sl@0: kumemget32(&d,aPtr,sizeof(d)); sl@0: OstTrace1( TRACE_INTERNALS, TLOCDRVREQUEST_PROCESSMESSAGEDATA, "Message handle=%d", d.iHandle ); sl@0: if (d.iHandle!=KLocalMessageHandle && Id()!=DLocalDrive::EFormat) sl@0: { sl@0: NKern::LockSystem(); sl@0: DThread* pT = RMessageK::MessageK(d.iHandle)->iClient; sl@0: if (!pT || pT->Open()!=KErrNone) sl@0: { sl@0: NKern::UnlockSystem(); sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT1, this, KErrBadHandle ); sl@0: return KErrBadHandle; sl@0: } sl@0: t.iExtTempObj=pT; sl@0: RemoteThread()=pT; sl@0: NKern::UnlockSystem(); sl@0: } sl@0: Pos()=d.iPos; sl@0: Length()=d.iLength; sl@0: RemoteDes()=(TAny*)d.iPtr; sl@0: RemoteDesOffset()=d.iOffset; sl@0: DriverFlags()=d.iFlags; sl@0: if (Pos()<0 || Length()<0) sl@0: { sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT2, this, KErrArgument ); sl@0: return KErrArgument; sl@0: } sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT3, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void TLocDrvRequest::CloseRemoteThread() sl@0: { sl@0: OstTraceFunctionEntry1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_ENTRY, this ); sl@0: sl@0: if (!RemoteThread()) sl@0: { sl@0: OstTraceFunctionExit1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_EXIT1, this ); sl@0: return; sl@0: } sl@0: NKern::ThreadEnterCS(); sl@0: DThread& t=Kern::CurrentThread(); sl@0: RemoteThread()=NULL; sl@0: Kern::SafeClose((DObject*&)t.iExtTempObj,NULL); sl@0: NKern::ThreadLeaveCS(); sl@0: OstTraceFunctionExit1( TLOCDRVREQUEST_CLOSEREMOTETHREAD_EXIT2, this ); sl@0: } sl@0: sl@0: EXPORT_C TInt TLocDrvRequest::CheckAndAdjustForPartition() sl@0: { sl@0: OstTraceFunctionEntry1( TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION_ENTRY, this ); sl@0: TLocDrv& d=*Drive(); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("CheckAndAdjustForPartition drive %d partition len %lx",d.iDriveNumber,d.iPartitionLen)); sl@0: OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION1, "iDriveNumber=%d; partition length=0x%lx", d.iDriveNumber, (TInt) d.iPartitionLen ); sl@0: Flags() |= EAdjusted; sl@0: TInt r; sl@0: switch (Id()) sl@0: { sl@0: case DLocalDrive::ECaps: sl@0: case DLocalDrive::EForceMediaChange: sl@0: case DLocalDrive::EPasswordLock: sl@0: case DLocalDrive::EPasswordUnlock: sl@0: case DLocalDrive::EPasswordClear: sl@0: case DLocalDrive::EPasswordErase: sl@0: case DLocalDrive::EReadPasswordStore: sl@0: case DLocalDrive::EWritePasswordStore: sl@0: case DLocalDrive::EPasswordStoreLengthInBytes: sl@0: case DLocalDrive::EQueryDevice: sl@0: { sl@0: r = KErrNone; sl@0: break; sl@0: } sl@0: case DLocalDrive::EEnlarge: sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("Enlarge request %lx",Length())); sl@0: OstTrace1( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION2, "Enlarge request=0x%lx", Length() ); sl@0: if (Length()>KMaxTInt) sl@0: r = KErrArgument; sl@0: else sl@0: r = KErrNone; sl@0: break; sl@0: case DLocalDrive::EReduce: sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("Reduce request %lx@%lx",Length(),Pos())); sl@0: OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION3, "Reduce request length=0x%lx; position=0x%lx", (TUint) Length(), (TUint) Pos() ); sl@0: if (Pos()+Length()>d.iPartitionLen) sl@0: r = KErrArgument; sl@0: else sl@0: r = KErrNone; sl@0: break; sl@0: case DLocalDrive::EFormat: sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("Format request %lx@%lx",Length(),Pos())); sl@0: OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION4, "Format request length=0x%lx; position=0x%lx", (TUint) Length(), (TUint) Pos() ); sl@0: if (!(DriverFlags() & RLocalDrive::ELocDrvWholeMedia)) sl@0: { sl@0: if (Pos()>d.iPartitionLen) sl@0: { sl@0: Length()=0; sl@0: r = KErrEof; sl@0: break; sl@0: } sl@0: Int64 left=d.iPartitionLen-Pos(); sl@0: if (leftd.iPartitionLen) sl@0: { sl@0: r = KErrArgument; sl@0: break; sl@0: } sl@0: Pos()+=d.iPartitionBaseAddr; sl@0: r = KErrNone; sl@0: break; sl@0: #endif sl@0: sl@0: default: // read or write or fragment sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("R/W request %lx@%lx",Length(),Pos())); sl@0: OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION6, "Read/Write request length=0x%x; position=0x%x", (TUint) Length(), (TUint) Pos() ); sl@0: if (DriverFlags() & RLocalDrive::ELocDrvWholeMedia) sl@0: { sl@0: if (d.iMedia && d.iMedia->iDriver && Pos()+Length() > d.iMedia->iDriver->iTotalSizeInBytes) sl@0: { sl@0: r = KErrArgument; sl@0: break; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if (Pos()+Length() > d.iPartitionLen) sl@0: { sl@0: r = KErrArgument; sl@0: break; sl@0: } sl@0: Pos()+=d.iPartitionBaseAddr; sl@0: } sl@0: r = KErrNone; sl@0: } sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION_EXIT, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: /******************************************** sl@0: * Local drive class sl@0: ********************************************/ sl@0: TLocDrv::TLocDrv(TInt aDriveNumber) sl@0: { sl@0: OstTraceFunctionEntryExt( TLOCDRV_TLOCDRV_ENTRY, this ); sl@0: memclr(this, sizeof(TLocDrv)); sl@0: iDriveNumber=aDriveNumber; sl@0: iPartitionNumber=-1; sl@0: OstTraceFunctionExit1( TLOCDRV_TLOCDRV_EXIT, this ); sl@0: } sl@0: sl@0: /** sl@0: Initialises the DMedia entity with the media device number and ID. sl@0: sl@0: @param aDevice The unique ID for this device. This can take one of the sl@0: enumerated values defined in TMediaDevice enum. sl@0: sl@0: @param aMediaId The unique ID to associate with this media entity. sl@0: sl@0: @return KErrNone,if successful, otherwise one of the other sl@0: system-wide error codes. sl@0: sl@0: @see TMediaDevice sl@0: */ sl@0: EXPORT_C TInt DMedia::Create(TMediaDevice aDevice, TInt aMediaId, TInt) sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIA_CREATE_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DMedia::Create media %d device %d",aMediaId,aDevice)); sl@0: OstTraceExt2(TRACE_INTERNALS, DMEDIA_CREATE, "media=%d; device=%d", aMediaId, (TUint) aDevice); sl@0: iMediaId=aMediaId; sl@0: iDevice=aDevice; sl@0: OstTraceFunctionExitExt( DMEDIA_CREATE_EXIT, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: /******************************************** sl@0: * Primary Media Class sl@0: ********************************************/ sl@0: void asyncDfc(TAny* aPtr) sl@0: { sl@0: OstTraceFunctionEntry0( _ASYNCDFC_ENTRY ); sl@0: DPrimaryMediaBase* pM=(DPrimaryMediaBase*)aPtr; sl@0: if (pM->iState==DMedia::EOpening) sl@0: pM->DoOpenMediaDriverComplete(pM->iAsyncErrorCode); sl@0: else if (pM->iState==DMedia::EReadPartitionInfo) sl@0: pM->DoPartitionInfoComplete(pM->iAsyncErrorCode); sl@0: OstTraceFunctionExit0( _ASYNCDFC_EXIT ); sl@0: } sl@0: sl@0: void handleMsg(TAny* aPtr) sl@0: { sl@0: OstTraceFunctionEntry0( _HANDLEMSG_ENTRY ); sl@0: DPrimaryMediaBase* primaryMedia=(DPrimaryMediaBase*)aPtr; sl@0: sl@0: for(TLocDrvRequest* m = (TLocDrvRequest*) primaryMedia->iMsgQ.iMessage; sl@0: m != NULL; sl@0: m = (TLocDrvRequest*) primaryMedia->iMsgQ.Poll()) sl@0: { sl@0: #if defined(_DEBUG) sl@0: if (!primaryMedia->iMsgQ.iQ.IsEmpty()) sl@0: __KTRACE_OPT(KLOCDRV, Kern::Printf("TRACE: handleMsg, queue not empty %08X", m)); sl@0: #endif sl@0: primaryMedia->HandleMsg(*m); sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: // don't empty the queue if this media is paging as there sl@0: // may be a (higher-priority) paging DFC waiting to run... sl@0: if (primaryMedia->iPagingMedia) sl@0: break; sl@0: #endif sl@0: } sl@0: sl@0: sl@0: primaryMedia->iMsgQ.Receive(); // allow reception of more messages sl@0: OstTraceFunctionExit0( _HANDLEMSG_EXIT ); sl@0: } sl@0: sl@0: EXPORT_C DPrimaryMediaBase::DPrimaryMediaBase() sl@0: : iMsgQ(handleMsg, this, NULL, 1), sl@0: iDeferred(NULL, NULL, NULL, 0), // callback never used sl@0: iWaitMedChg(NULL, NULL, NULL, 0), // callback never used sl@0: iAsyncDfc(asyncDfc, this, 1) sl@0: /** sl@0: Constructor of DPrimaryMediaBase class. sl@0: Initialises the media state as closed. sl@0: */ sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DPRIMARYMEDIABASE_ENTRY, this ); sl@0: iState = EClosed; sl@0: } sl@0: sl@0: sl@0: sl@0: EXPORT_C TInt DPrimaryMediaBase::Create(TMediaDevice aDevice, TInt aMediaId, TInt aLastMediaId) sl@0: /** sl@0: Called from LocDrv::RegisterMediaDevice() function. sl@0: Calls DMedia::Create() sl@0: sl@0: @param aDevice Local media ID sl@0: @param aMediaId Media Id (unique for a media subsystem) sl@0: @param aLastMediaId This indicates number of used media ids+ number of DMedia objects to be associated with the media driver. sl@0: sl@0: @return KErrNone sl@0: @see TMediaDevice sl@0: sl@0: */ sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_CREATE_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase::Create media %d-%d device %d",aMediaId,aLastMediaId,aDevice)); sl@0: OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_CREATE, "aMediaId=%d; aLastMediaId=%d; aDevice=%d ", aMediaId, aLastMediaId, (TUint) aDevice ); sl@0: TInt r=DMedia::Create(aDevice,aMediaId,0); sl@0: sl@0: if (r != KErrNone) sl@0: { sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT1, this, r ); sl@0: return r; sl@0: } sl@0: iBody = new DBody; sl@0: if (iBody == NULL) sl@0: { sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT2, this, KErrNoMemory ); sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: TInt pageSize = Kern::RoundToPageSize(1); sl@0: iBody->iPageSizeMsk = pageSize-1; sl@0: #endif sl@0: sl@0: iLastMediaId=aLastMediaId; sl@0: if (r==KErrNone && iDfcQ) sl@0: { sl@0: iMsgQ.SetDfcQ(iDfcQ); sl@0: iDeferred.SetDfcQ(iDfcQ); sl@0: iWaitMedChg.SetDfcQ(iDfcQ); sl@0: iAsyncDfc.SetDfcQ(iDfcQ); sl@0: } sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT3, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: EXPORT_C TInt DPrimaryMediaBase::Connect(DLocalDrive* aLocalDrive) sl@0: /** sl@0: Connects to a local drive sl@0: sl@0: @param aLocalDrive Local drive logical channel abstraction sl@0: sl@0: @pre Kernel must be unlocked sl@0: @pre Current thread in critical section sl@0: sl@0: @post Kernel must be unlocked sl@0: sl@0: @return KErrNone, if successful sl@0: KErrNotFound, If no PDD matches criteria while getting driver list sl@0: KErrNoMemory, If the array could not be expanded at some point while getting driver list or ran out of memory while opening media driver sl@0: KErrNotReady, If not ready when trying to open media driver sl@0: otherwise, one of the other system wide error codes. sl@0: sl@0: @see DLocalDrive sl@0: */ sl@0: { sl@0: OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_CONNECT_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Connect %O",iMediaId,aLocalDrive)); sl@0: OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CONNECT, "iMediaId=%d; iDriveNumber=%d", iMediaId, aLocalDrive->iDrive->iDriveNumber ); sl@0: sl@0: TInt r=KErrNone; sl@0: sl@0: if (iDfcQ) sl@0: { sl@0: TThreadMessage& m=Kern::Message(); sl@0: m.iValue=EConnect; sl@0: m.iArg[0]=aLocalDrive; sl@0: r=m.SendReceive(&iMsgQ); sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CONNECT_EXIT1, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: // If no DFC queue, must be a fixed media device sl@0: // If this is the first connection, open media driver now sl@0: // Assume no non-primary media exist on this device sl@0: sl@0: NKern::LockSystem(); sl@0: TBool first=iConnectionQ.IsEmpty(); sl@0: iConnectionQ.Add(&aLocalDrive->iLink); sl@0: NKern::UnlockSystem(); sl@0: if (first) sl@0: { sl@0: r=OpenMediaDriver(); sl@0: if (r!=KErrNone) sl@0: { sl@0: NKern::LockSystem(); sl@0: aLocalDrive->Deque(); sl@0: NKern::UnlockSystem(); sl@0: } sl@0: } sl@0: sl@0: if (r==KErrNone) sl@0: aLocalDrive->iDrive->iMedia=this; sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CONNECT_EXIT2, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::Disconnect(DLocalDrive* aLocalDrive) sl@0: /** sl@0: Disconnects from a local drive sl@0: sl@0: @param aLocalDrive Local drive logical channel abstraction sl@0: sl@0: @pre Kernel must be unlocked sl@0: @pre Current thread in critical section sl@0: sl@0: @post Kernel must be unlocked sl@0: @see DLocalDrive sl@0: */ sl@0: sl@0: { sl@0: OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_DISCONNECT_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Disconnect %O",iMediaId,aLocalDrive)); sl@0: OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_DISCONNECT, "iMediaId=%d; iDriveNumber=%d", iMediaId, aLocalDrive->iDrive->iDriveNumber ); sl@0: sl@0: if (iDfcQ) sl@0: { sl@0: TThreadMessage& m=Kern::Message(); sl@0: m.iValue=EDisconnect; sl@0: m.iArg[0]=aLocalDrive; sl@0: m.SendReceive(&iMsgQ); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_DISCONNECT_EXIT1, this ); sl@0: return; sl@0: } sl@0: sl@0: // If no DFC queue, must be a fixed media device sl@0: // If this is the last connection, close media driver now sl@0: // Assume no non-primary media exist on this device sl@0: DMediaDriver* pD=NULL; sl@0: NKern::LockSystem(); sl@0: aLocalDrive->iDrive->iMedia=NULL; sl@0: aLocalDrive->Deque(); sl@0: if (iConnectionQ.IsEmpty()) sl@0: { sl@0: pD=iDriver; sl@0: iDriver=NULL; sl@0: } sl@0: NKern::UnlockSystem(); sl@0: if (pD) sl@0: pD->Close(); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_DISCONNECT_EXIT2, this ); sl@0: } sl@0: sl@0: EXPORT_C TInt DPrimaryMediaBase::Request(TLocDrvRequest& aReq) sl@0: /** sl@0: Issues a local drive request. It is called from TLocDrv::Request() function . sl@0: Each local drive request is encapsulated as a TLocDrvRequest- a class derived from TThreadMessage, the kernel message class. sl@0: TLocDrvRequest contains information pertaining to the request, including the ID and any associated parameters such as drive position, length and source/destination location. sl@0: Passes the request through to the media driver. sl@0: sl@0: @param m Encapsulates the request information received from the client sl@0: sl@0: @pre Enter with kernel unlocked sl@0: sl@0: @post Leave with Kernel unlocked sl@0: sl@0: @return KErrNone,if successful sl@0: KErrBadDescriptor, if request encapsulates a bad descriptor sl@0: Otherwise, one of the other system wide error codes. sl@0: sl@0: @see TLocDrvRequest sl@0: */ sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_REQUEST_ENTRY, this ); sl@0: sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Request(%08x)",iMediaId,&aReq)); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("this=%x, ReqId=%d, Pos=%lx, Len=%lx, remote thread %O",this,aReq.Id(),aReq.Pos(),aReq.Length(),aReq.RemoteThread())); sl@0: sl@0: OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_REQUEST, "reqId=%d; length=0x%lx; position=0x%lx; remote thread=0x%x", (TInt) aReq.Id(), (TUint) aReq.Length(), (TUint) aReq.Pos(), (TUint) aReq.RemoteThread()); sl@0: sl@0: TInt reqId = aReq.Id(); sl@0: sl@0: if (reqId == DLocalDrive::ECaps) sl@0: DefaultDriveCaps(*(TLocalDriveCapsV2*)aReq.RemoteDes()); // fill in stuff we know even if no media present sl@0: sl@0: TInt r = QuickCheckStatus(); sl@0: if (r != KErrNone && aReq.Id()!=DLocalDrive::EForceMediaChange && // EForceMediaChange, and sl@0: aReq.Id()!=DLocalDrive::EReadPasswordStore && // Password store operations sl@0: aReq.Id()!=DLocalDrive::EWritePasswordStore && // do not require the media sl@0: aReq.Id()!=DLocalDrive::EPasswordStoreLengthInBytes) // to be ready.) sl@0: { sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: // for ERead & EWrite requests, get the linear address for pinning & DMA sl@0: TUint8* linAddress = NULL; sl@0: TClientBuffer clientBuffer; sl@0: DThread* pT = NULL; sl@0: sl@0: if (reqId == DLocalDrive::ERead || reqId == DLocalDrive::EWrite) sl@0: { sl@0: pT = aReq.RemoteThread(); sl@0: if (!pT) sl@0: pT = &Kern::CurrentThread(); // e.g. when using TBusLocalDrive directly sl@0: sl@0: // for silly zero-length requests, return immediately, setting the client sl@0: // descriptor length to zero if it's a read request sl@0: if (aReq.Length() == 0) sl@0: { sl@0: DThread* pC = &Kern::CurrentThread(); sl@0: r = KErrNone; sl@0: if (reqId == DLocalDrive::ERead) sl@0: { sl@0: TPtrC8 ptr(NULL, 0); sl@0: r = Kern::ThreadDesWrite(pT, aReq.RemoteDes(), ptr, aReq.RemoteDesOffset(), KChunkShiftBy0,pC); sl@0: } sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT2, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: clientBuffer.SetFromDescriptor(aReq.RemoteDes(), pT); sl@0: sl@0: TInt length = 0; sl@0: TInt maxLength = 0; sl@0: TInt r = Kern::ThreadGetDesInfo(pT,aReq.RemoteDes(),length,maxLength,linAddress,EFalse); // get descriptor length, maxlength and linAddress sl@0: if (r != KErrNone) sl@0: { sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT3, this, r ); sl@0: return r; sl@0: } sl@0: linAddress+= aReq.RemoteDesOffset(); sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: // NB change in behavior IF DATA PAGING IS ENABLED: TLocDrvRequest::RemoteDes() points sl@0: // to a TClientBuffer rather than the client's remote descriptor sl@0: if (DataPagingDeviceRegistered) sl@0: { sl@0: aReq.RemoteDes() = &clientBuffer; sl@0: aReq.Flags() |= TLocDrvRequest::ETClientBuffer; sl@0: } sl@0: #endif sl@0: } sl@0: sl@0: if (iDfcQ) sl@0: { sl@0: __TRACE_TIMING(0x10); sl@0: sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: // If this is a ROM/Code paging media, pin writes sl@0: // If there is a Data paging media registered, pin all requests with descriptors sl@0: if ( (DataPagingDeviceRegistered) || (reqId == DLocalDrive::EWrite && RomPagingDfcQ(this)) ) sl@0: { sl@0: r = PinSendReceive(aReq, (TLinAddr) linAddress); sl@0: } sl@0: else sl@0: #endif // __DEMAND_PAGING__ sl@0: r = SendReceive(aReq, (TLinAddr) linAddress); sl@0: } sl@0: else sl@0: { sl@0: // If no DFC queue, must be a fixed media device sl@0: // Media driver must already have been opened sl@0: // Assume no non-primary media exist on this device sl@0: // Just pass request straight through to media driver sl@0: r = aReq.CheckAndAdjustForPartition(); sl@0: if (r == KErrNone) sl@0: r = iDriver->Request(aReq); sl@0: } sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: // NB change in behavior IF DATA PAGING IS ENABLED: TLocDrvRequest::RemoteDes() points sl@0: // to a TClientBuffer rather than the client's remote descriptor sl@0: if (reqId == DLocalDrive::ERead && DataPagingDeviceRegistered && r == KErrNone) sl@0: { sl@0: r = clientBuffer.UpdateDescriptorLength(pT); sl@0: } sl@0: #endif sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT4, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: TInt DPrimaryMediaBase::PinSendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress) sl@0: { sl@0: OstTraceExt2(TRACE_FLOW, DPRIMARYMEDIABASE_PINSENDRECEIVE_ENTRY, "> DPrimaryMediaBase::PinSendReceive;aReq=%x;aLinAddress=%x;", (TUint) &aReq, (TUint) &aLinAddress ); sl@0: sl@0: __ASSERT_DEBUG(ThePinObjectAllocator, LOCM_FAULT()); sl@0: sl@0: sl@0: TInt msgId = aReq.Id(); sl@0: TInt r; sl@0: sl@0: switch(msgId) sl@0: { sl@0: case DLocalDrive::EControlIO: sl@0: { sl@0: TInt controlIoType = aReq.Int3(); sl@0: switch(controlIoType) sl@0: { sl@0: case KLocalMessageHandle: sl@0: // ControlIo is not supported if either of the two bare (TAny*) pointers are non-NULL sl@0: // as it's not possible to determine what the pointers are pointing at... sl@0: if (aReq.Int1() || aReq.Int2()) sl@0: { sl@0: __KTRACE_OPT(KDATAPAGEWARN, Kern::Printf("Data paging: Naked EControlIO not supported on paging device: fn=%x", aReq.Int0())); sl@0: r = KErrNotSupported; sl@0: break; sl@0: } sl@0: // fall into... sl@0: case 0: sl@0: r = SendReceive(aReq); sl@0: break; sl@0: sl@0: default: sl@0: // if Int3() is > 0, Int1() is a data pointer, and Int3() is a length sl@0: if (controlIoType > (TInt) ThePinObjectAllocator->iFragmentGranularity) sl@0: { sl@0: r = KErrTooBig; sl@0: break; sl@0: } sl@0: if (controlIoType < 0) sl@0: { sl@0: r = KErrArgument; sl@0: break; sl@0: } sl@0: r = PinFragmentSendReceive(aReq, (TLinAddr) aReq.Ptr1(), controlIoType); sl@0: break; sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case DLocalDrive::ERead: sl@0: case DLocalDrive::EWrite: sl@0: { sl@0: r = PinFragmentSendReceive(aReq, aLinAddress, aReq.Length()); sl@0: break; sl@0: } sl@0: sl@0: // For all these requests, aReq.RemoteDes() points to a buffer on the stack in DLocalDrive::Request() sl@0: // This is a kernel stack & so should be unpaged & not require pinning... sl@0: case DLocalDrive::ECaps: sl@0: case DLocalDrive::EGetLastErrorInfo: sl@0: case DLocalDrive::EQueryDevice: sl@0: case DLocalDrive::EPasswordLock: sl@0: case DLocalDrive::EPasswordUnlock: sl@0: case DLocalDrive::EPasswordClear: sl@0: case DLocalDrive::EReadPasswordStore: sl@0: case DLocalDrive::EWritePasswordStore: sl@0: case DLocalDrive::EPasswordStoreLengthInBytes: sl@0: case DLocalDrive::EPasswordErase: sl@0: sl@0: default: sl@0: r = SendReceive(aReq); sl@0: } sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_PINSENDRECEIVE_EXIT, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: TInt DPrimaryMediaBase::PinFragmentSendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress, TInt aLength) sl@0: { sl@0: OstTraceExt3(TRACE_FLOW, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE_ENTRY, "> DPrimaryMediaBase::PinFragmentSendReceive;aReq=%x;aLinAddress=%x;aLength=%d;", (TUint) &aReq, (TUint) &aLinAddress, aLength ); sl@0: sl@0: TLocDrvRequest fragment = aReq; // create a request on the stack for use during fragmentation, pre-fill with the original req args, leave original Kernel message as repository (thread will block, message contents won't change) sl@0: TInt r = KErrNone; sl@0: sl@0: // Kern::Printf(">PFSR %02X aReq %08X aLinAddress %08X aLen %08X offset %08X", aReq.Id(), &aReq, aLinAddress, aLength, aReq.RemoteDesOffset()); sl@0: sl@0: DThread* pT = aReq.RemoteThread(); sl@0: if (!pT) sl@0: pT=&Kern::CurrentThread(); // e.g. when using TBusLocalDrive directly sl@0: sl@0: __KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Fragmenting Read/Write Request(0x%08x) on drive(%d), remote des(0x%x), offset into des(0x%x), original req Length(0x%x)",&aReq,aReq.Drive()->iDriveNumber,(TInt)(aReq.RemoteDes()),aReq.RemoteDesOffset(),aLength)); sl@0: __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Remote thread(0x%08x), current thread(0x%08x), start of data to write(0x%08x)",aReq.RemoteThread(),&Kern::CurrentThread(),(TInt)aLinAddress)); sl@0: OstTraceDefExt5(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE1, "Fragmenting Read/Write Request=0x%08x; drive=%d; remote des=0x%x; offset into des=0x%x; original length=0x%x", (TUint) &aReq, (TUint) aReq.Drive()->iDriveNumber, (TInt) (aReq.RemoteDes()), (TInt) aReq.RemoteDesOffset(), (TInt) aLength ); sl@0: OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE2, "Remote Thread=0x%08x; current Thread=0x%x; start of data to write=0x%08x", (TUint) aReq.RemoteThread(), (TUint) &Kern::CurrentThread(),(TUint)aLinAddress ); sl@0: sl@0: // don't want this thread to be terminated until last fragment is sent to MD and mem can be free'd up sl@0: NKern::ThreadEnterCS(); sl@0: sl@0: __ASSERT_DEBUG(ThePinObjectAllocator, LOCM_FAULT()); sl@0: sl@0: TUint fragmentGranularity = ThePinObjectAllocator->iFragmentGranularity; sl@0: TInt dataLockResult = 0; sl@0: // fragmentation only allowed for read/write requests sl@0: __ASSERT_DEBUG(aLength <= (TInt) fragmentGranularity || (aReq.Id() == DLocalDrive::EWrite || aReq.Id() == DLocalDrive::ERead), LOCM_FAULT()); sl@0: sl@0: // Pin the client buffer sl@0: TInt pinnedLen; sl@0: for (TInt pos = 0; pos < aLength; pos+= pinnedLen, aLinAddress+= pinnedLen) sl@0: { sl@0: pinnedLen = 0; sl@0: sl@0: // pin memory sl@0: TInt remainingLen = aLength - pos; // remaining length sl@0: sl@0: // first attempt to pin memory with no pre-allocated buffers (which may fail) sl@0: DPinObjectAllocator::SVirtualPinContainer* pinDataObject = ThePinObjectAllocator->AcquirePinObject(); sl@0: sl@0: if (pinDataObject) sl@0: { sl@0: TInt lenToPin = Min(KMaxPinData, remainingLen); sl@0: sl@0: TInt r = Kern::PinVirtualMemory(pinDataObject->iObject, aLinAddress, lenToPin, pT); sl@0: if (r == KErrNone) sl@0: { sl@0: pinnedLen = lenToPin; sl@0: } sl@0: else sl@0: { sl@0: #ifdef __DEBUG_DEMAND_PAGING__ sl@0: Kern::Printf("Kern::PinVirtualMemory() error %d", r); sl@0: #endif sl@0: // pin failed, so use preallocated buffer instead sl@0: ThePinObjectAllocator->ReleasePinObject(pinDataObject); sl@0: pinDataObject = NULL; sl@0: } sl@0: } sl@0: sl@0: if (!pinDataObject) sl@0: { sl@0: ThePinObjectAllocator->PreAllocatedDataLock().LockFragmentation(); sl@0: sl@0: TLinAddr start = aLinAddress; sl@0: do sl@0: { sl@0: TInt lenToPin = Min((TInt) fragmentGranularity, remainingLen - pinnedLen); sl@0: sl@0: #ifdef __DEBUG_DEMAND_PAGING__ sl@0: Kern::Printf(">SR PinS Id %d aLinAddress %08X lenToPin %08X offset %08X", aReq.Id(), aLinAddress, lenToPin); sl@0: #endif sl@0: sl@0: dataLockResult = ThePinObjectAllocator->PreAllocatedDataLock().Lock(pT, start, lenToPin); sl@0: sl@0: #ifdef __DEBUG_DEMAND_PAGING__ sl@0: Kern::Printf(" 0) release it after calling SendReceive() sl@0: if (dataLockResult <= 0) sl@0: ThePinObjectAllocator->PreAllocatedDataLock().UnlockFragmentation(); sl@0: sl@0: #ifdef __DEBUG_DEMAND_PAGING__ sl@0: if (dataLockResult < 0) sl@0: Kern::Printf("DFragmentationPagingLock::Lock() %d", dataLockResult); sl@0: #endif sl@0: sl@0: if (dataLockResult < 0) // if lock returned an error then give up sl@0: { sl@0: r = dataLockResult; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: // fragment request Id defaults to same as original request sl@0: fragment.Id() = aReq.Id(); sl@0: fragment.Length() = Int64(pinnedLen); sl@0: fragment.RemoteDesOffset() = aReq.RemoteDesOffset() + pos; sl@0: fragment.Pos() = aReq.Pos() + pos; sl@0: fragment.Flags() = aReq.Flags(); sl@0: sl@0: __KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Send fragment (0x%08x) type(%d), length(0x%x), offset within original req(0x%x), pos in media(0x%lx)",&fragment,fragment.Id(), pinnedLen, pos, fragment.Pos())); sl@0: OstTraceDefExt5(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_PINFRAGMENTSENDRECEIVE3, "Send fragment 0x%08x; type=%d; length=0x%x; offset within original req=0x%x; position in media=0x%lx", (TUint) &fragment, (TInt) fragment.Id(), (TUint) pinnedLen, (TUint) pos, (TUint) fragment.Pos()); sl@0: sl@0: #ifdef BTRACE_PAGING_MEDIA sl@0: TInt buf[4]; sl@0: buf[0] = pinnedLen; // fragment length sl@0: buf[1] = pos; // offset within original request sl@0: buf[2] = fragment.Pos(); // offset in media sl@0: buf[3] = (TInt)&pT->iNThread; // thread that issued the original write req sl@0: BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedFragmentBegin,&fragment,fragment.Id(),buf,sizeof(buf)); sl@0: #endif sl@0: r = SendReceive(fragment, aLinAddress); // only come back here when message (fragment) has been completed sl@0: sl@0: // unpin memory sl@0: if (pinDataObject) sl@0: { sl@0: Kern::UnpinVirtualMemory(pinDataObject->iObject); sl@0: ThePinObjectAllocator->ReleasePinObject(pinDataObject); sl@0: } sl@0: else if (dataLockResult > 0) // pinDataObject = NULL sl@0: { sl@0: __ASSERT_DEBUG(dataLockResult == 1, LOCM_FAULT()); sl@0: ThePinObjectAllocator->PreAllocatedDataLock().Unlock(); sl@0: ThePinObjectAllocator->PreAllocatedDataLock().UnlockFragmentation(); sl@0: } sl@0: sl@0: #ifdef BTRACE_PAGING_MEDIA sl@0: BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedFragmentEnd,&fragment,r); sl@0: #endif sl@0: sl@0: if (r != KErrNone) sl@0: break; sl@0: } sl@0: sl@0: NKern::ThreadLeaveCS(); sl@0: sl@0: // Kern::Printf(" DPrimaryMediaBase::SendReceive;aReq=%x;aLinAddress=%x", (TUint) &aReq, (TUint) &aLinAddress ); sl@0: sl@0: DDmaHelper* dmaHelper = aReq.Drive()->iDmaHelper; sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: RequestCountInc(); sl@0: #endif sl@0: sl@0: TInt r; sl@0: sl@0: if (dmaHelper) sl@0: r = dmaHelper->SendReceive(aReq, aLinAddress); sl@0: else sl@0: { sl@0: r = aReq.SendReceive(&iMsgQ); sl@0: } sl@0: #ifdef __DEMAND_PAGING__ sl@0: RequestCountDec(); sl@0: #endif sl@0: sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_SENDRECEIVE_EXIT, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: sl@0: EXPORT_C TInt DPrimaryMediaBase::ForceMediaChange(TInt) sl@0: /** sl@0: Forces a media change.The method can be overridden in the derived classes. sl@0: @param mode Media change mode sl@0: sl@0: @return KErrNotSupported, in the default implementation sl@0: KErrNone, if successful sl@0: Otherwise, one of the other system wide error codes. sl@0: sl@0: */ sl@0: { sl@0: // default implementation sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: EXPORT_C TInt DPrimaryMediaBase::InitiatePowerUp() sl@0: /** sl@0: Initiates Power up sequence sl@0: @return KErrCompletion, operation is complete successfully or otherwise sl@0: KErrNone, if successful sl@0: Otherwise, one of the other system wide error codes. sl@0: sl@0: */ sl@0: { sl@0: // default implementation, this is the default implementation. sl@0: return KErrCompletion; sl@0: } sl@0: sl@0: EXPORT_C TInt DPrimaryMediaBase::QuickCheckStatus() sl@0: /** sl@0: Checks the status of the media device, whether the device is present,absent,not ready,etc. sl@0: The function can be overridden in the derived classes sl@0: sl@0: @return KErrNone, if successful sl@0: Otherwise, one of the other system wide error codes. sl@0: sl@0: */ sl@0: { sl@0: // default implementation sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::DefaultDriveCaps(TLocalDriveCapsV2& aCaps) sl@0: /** sl@0: Fills in the default drive capabilities in TLocalDriveCapsV2 . sl@0: It initializes media type of drive as unknown and has to be overridden in the derived class. Called from the Request ( ) function of the same class. sl@0: sl@0: @param aCaps Media drive capability fields. Extension to Capabilities fields(i.e) in addition to TLocalDriveCaps mainly to support Nor flash sl@0: @see TLocalDriveCapsV2 sl@0: */ sl@0: sl@0: { sl@0: // default implementation sl@0: // aCaps is zeroed beforehand sl@0: aCaps.iType = EMediaUnknown; sl@0: } sl@0: sl@0: EXPORT_C TBool DPrimaryMediaBase::IsRemovableDevice(TInt& /*aSocketNum*/) sl@0: /** sl@0: Checks whether it is a removable device or not sl@0: @param aSocketNum Socket number sl@0: @return ETrue=Removable Device sl@0: EFalse=Non-Removable device, default implementation sl@0: sl@0: */ sl@0: { sl@0: // default implementation sl@0: return(EFalse); sl@0: } sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::HandleMsg(TLocDrvRequest& m) sl@0: /** sl@0: It handles the drive request encapsulated in TLocDrvRequest depending on the message id. sl@0: sl@0: @param aRequest Encapsulates the request information received from the client sl@0: @see TLocDrvRequest sl@0: */ sl@0: { sl@0: OstTrace1( TRACE_FLOW, DPRIMARYMEDIABASE_HANDLEMSG_ENTRY, "> DPrimaryMediaBase::HandleMsg;m=%x;", (TUint) &m); sl@0: sl@0: switch (m.iValue) sl@0: { sl@0: case EConnect: sl@0: { sl@0: DLocalDrive* pD=(DLocalDrive*)m.Ptr0(); sl@0: iConnectionQ.Add(&pD->iLink); sl@0: m.Complete(KErrNone, EFalse); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT1, this ); sl@0: return; sl@0: } sl@0: case EDisconnect: sl@0: { sl@0: DLocalDrive* pD=(DLocalDrive*)m.Ptr0(); sl@0: TLocDrv* pL=pD->iDrive; sl@0: DMedia* media=pL->iMedia; sl@0: if (iState==EReady && media && media->iDriver) sl@0: media->iDriver->Disconnect(pD,&m); sl@0: else sl@0: { sl@0: pD->Deque(); sl@0: m.Complete(KErrNone, EFalse); sl@0: } sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT2, this ); sl@0: return; sl@0: } sl@0: case DLocalDrive::EForceMediaChange: sl@0: { sl@0: TUint flags = (TUint) m.Pos(); sl@0: sl@0: // if KForceMediaChangeReOpenDriver specified wait for power up, sl@0: // and then re-open this drive's media driver sl@0: __KTRACE_OPT(KLOCDRV, Kern::Printf("EForceMediaChange, flags %08X\n", flags)); sl@0: if (flags == (TUint) KForceMediaChangeReOpenMediaDriver) sl@0: { sl@0: TInt sock; sl@0: if (!IsRemovableDevice(sock)) sl@0: { sl@0: CompleteRequest(m, KErrNotSupported); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT3, this ); sl@0: return; sl@0: } sl@0: // wait for power up and then call DPrimaryMediaBase::DoRequest() sl@0: break; sl@0: } sl@0: sl@0: TInt r=ForceMediaChange(flags); sl@0: if (r==KErrNone) sl@0: { sl@0: // wait for media change notification to complete message sl@0: m.Forward(&iWaitMedChg,EFalse); sl@0: } sl@0: else sl@0: { sl@0: if (r==KErrNotSupported || r==KErrCompletion) sl@0: r=KErrNone; sl@0: CompleteRequest(m, r); sl@0: } sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT4, this ); sl@0: return; sl@0: } sl@0: case DLocalDrive::ECaps: sl@0: if (iState==EPoweredDown) sl@0: { sl@0: // The media is powered down, but the media driver still exists. sl@0: // - Issue the ECaps request without powering the media back up. sl@0: DoRequest(m); sl@0: __TRACE_TIMING(0x101); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT5, this ); sl@0: return; sl@0: } sl@0: break; sl@0: sl@0: case DLocalDrive::ERead: sl@0: case DLocalDrive::EWrite: sl@0: case DLocalDrive::EFormat: sl@0: case DLocalDrive::EEnlarge: sl@0: case DLocalDrive::EReduce: sl@0: case DLocalDrive::EPasswordLock: sl@0: case DLocalDrive::EPasswordUnlock: sl@0: case DLocalDrive::EPasswordClear: sl@0: case DLocalDrive::EPasswordErase: sl@0: case DLocalDrive::EControlIO: sl@0: case DLocalDrive::EDeleteNotify: sl@0: case DLocalDrive::EQueryDevice: sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: case DMediaPagingDevice::ERomPageInRequest: sl@0: case DMediaPagingDevice::ECodePageInRequest: sl@0: #endif sl@0: break; sl@0: case DLocalDrive::EGetLastErrorInfo: sl@0: { sl@0: DLocalDrive* pD=(DLocalDrive*)m.Ptr0(); sl@0: TLocDrv* pL=pD->iDrive; sl@0: *((TErrorInfo*) m.RemoteDes()) = pL->iLastErrorInfo; sl@0: CompleteRequest(m, KErrNone); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT6, this ); sl@0: return; sl@0: } sl@0: case DLocalDrive::EReadPasswordStore: sl@0: { sl@0: TPtr8 pswData ((TUint8*) m.RemoteDes(), (TInt) m.Length()); sl@0: TInt r = ThePasswordStore->ReadPasswordData(pswData); sl@0: m.Length() = pswData.Length(); sl@0: CompleteRequest(m, r); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT7, this ); sl@0: return; sl@0: } sl@0: case DLocalDrive::EWritePasswordStore: sl@0: { sl@0: TPtrC8 pData((TUint8*) m.RemoteDes(), (TInt) m.Length()); sl@0: TInt r = ThePasswordStore->WritePasswordData(pData); sl@0: sl@0: if(r != KErrNone) sl@0: { sl@0: CompleteRequest(m, r); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT8, this ); sl@0: return; sl@0: } sl@0: sl@0: r = QuickCheckStatus(); sl@0: if(r != KErrNone) sl@0: { sl@0: // Don't try to power up the device if it's not ready. sl@0: // - Note that this isn't an error that needs to be returned to the client. sl@0: CompleteRequest(m, KErrNone); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT9, this ); sl@0: return; sl@0: } sl@0: sl@0: break; sl@0: } sl@0: case DLocalDrive::EPasswordStoreLengthInBytes: sl@0: { sl@0: TInt length = ThePasswordStore->PasswordStoreLengthInBytes(); sl@0: *(TInt*) m.RemoteDes() = length; sl@0: CompleteRequest(m, KErrNone); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT10, this ); sl@0: return; sl@0: } sl@0: default: sl@0: CHECK_RET(KErrNotSupported); sl@0: CompleteRequest(m, KErrNotSupported); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT11, this ); sl@0: return; sl@0: } sl@0: sl@0: __KTRACE_OPT(KFAIL,Kern::Printf("mdrq %d",m.Id())); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::HandleMsg state %d req %d",iMediaId,iState,m.Id())); sl@0: sl@0: OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_HANDLEMSG2, "iMediaId=%d; iState=%d; req Id=%d", iMediaId, iState, m.Id()); sl@0: sl@0: // if media driver already open, pass request through sl@0: if (iState==EReady) sl@0: { sl@0: DoRequest(m); sl@0: __TRACE_TIMING(0x101); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT12, this ); sl@0: return; sl@0: } sl@0: sl@0: // if open or close in progress, defer this message sl@0: if (iState!=EClosed && iState!=EPoweredDown) sl@0: { sl@0: #ifdef __DEMAND_PAGING__ sl@0: if (DMediaPagingDevice::PagingRequest(m)) sl@0: { sl@0: __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT()); sl@0: __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT()); sl@0: __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT()); sl@0: sl@0: __KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Deferring PageIn request 0x%08x because opening or closing",&m)); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_HANDLEMSG3, "Deferring PageIn request 0x%08x because opening or closing", &m); sl@0: iBody->iPagingDevice->SendToDeferredQ(&m); sl@0: } sl@0: else sl@0: #endif sl@0: m.Forward(&iDeferred,EFalse); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT13, this ); sl@0: return; sl@0: } sl@0: sl@0: // nothing is open, so try to open something sl@0: __ASSERT_ALWAYS(!iCurrentReq,LOCM_FAULT()); sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: sl@0: #ifdef BTRACE_PAGING_MEDIA sl@0: if (DMediaPagingDevice::PagingRequest(m)) sl@0: BTraceContext12(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInQuietlyDeferred,&m,iState,m.iValue); sl@0: #endif // BTRACE_PAGING_MEDIA sl@0: sl@0: #ifdef _DEBUG sl@0: __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT()); sl@0: sl@0: if (DMediaPagingDevice::PagingRequest(m)) sl@0: { sl@0: __ASSERT_DEBUG(iPagingMedia,LOCM_FAULT()); sl@0: __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT()); sl@0: __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Page request 0x%08x received -> opening MD",&m)); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_HANDLEMSG4, "Page request 0x%08x received; opening MD", &m); sl@0: } sl@0: #endif // _DEBUG sl@0: sl@0: #endif // __DEMAND_PAGING__ sl@0: sl@0: iCurrentReq=&m; sl@0: if(iState == EClosed) sl@0: { sl@0: iState=EPoweringUp1; sl@0: } sl@0: else if (iState == EPoweredDown) sl@0: { sl@0: iState=EPoweringUp2; sl@0: } sl@0: sl@0: TInt r=InitiatePowerUp(); sl@0: if (r==KErrNone || r==KErrServerBusy) sl@0: { sl@0: // wait for completion of power up request sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT14, this ); sl@0: return; sl@0: } sl@0: if (r==KErrCompletion) sl@0: r=KErrNone; // device already powered up sl@0: PowerUpComplete(r); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT15, this ); sl@0: } sl@0: sl@0: EXPORT_C TInt DPrimaryMediaBase::DoRequest(TLocDrvRequest& m) sl@0: /** sl@0: If the media exists, it tries to get the partition information if not there. sl@0: It then passes on the request to the media driver by calling its Request( ) function. sl@0: Then it completes the kernel thread message and the reference count of the thread is closed asynchronously. sl@0: sl@0: @param aRequest Encapsulates the request information received from the client sl@0: sl@0: @return KErrNone, if successful sl@0: KErrNotReady, if missing partitions on removable media sl@0: KErrNotSupported, if missing partitions on fixed media sl@0: KErrArgument Out of range argument ,encapsulated in Local drive request , passed while checking and adjusting for partition sl@0: KErrEOF, Reached the end of file sl@0: KErrBadDescriptor, if request encapsulates a bad descriptor sl@0: Otherwise, one of the other system wide error codes. sl@0: sl@0: */ sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOREQUEST_ENTRY, this ); sl@0: __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DPrimaryMediaBase::DoRequest %d",m.Id())); sl@0: TLocDrv* pL=m.Drive(); sl@0: DMedia* media=pL->iMedia; sl@0: TInt r=KErrNone; sl@0: sl@0: OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_DOREQUEST, "req Id=%d; length=0x%x; position=0x%x", (TInt) m.Id(), (TInt) m.Length(), (TInt) m.Pos()); sl@0: sl@0: // re-open this drive's media driver ? sl@0: if (m.iValue == DLocalDrive::EForceMediaChange) sl@0: { sl@0: __ASSERT_DEBUG(((TUint) m.Pos()) == (TUint) KForceMediaChangeReOpenMediaDriver, LOCM_FAULT()); sl@0: sl@0: iCurrentReq=NULL; sl@0: sl@0: TLocDrv* pL = m.Drive(); sl@0: DMedia* media = pL->iMedia; sl@0: if (media && media->iDriver) sl@0: CloseMediaDrivers(media); sl@0: sl@0: iState=EOpening; sl@0: StartOpenMediaDrivers(); sl@0: sl@0: NotifyClients(ETrue,pL); sl@0: CompleteRequest(m, r); sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: if (!media || !media->iDriver || iState == EClosed) sl@0: { sl@0: // Return KErrNotReady for missing partitions on removable media sl@0: // as opposed to KErrNotSupported for missing partitions on fixed media sl@0: // since the latter don't exist whereas the former might exist at some time. sl@0: TInt sock; sl@0: r=IsRemovableDevice(sock) ? KErrNotReady : KErrNotSupported; sl@0: } sl@0: sl@0: iCurrentReq=&m; sl@0: if (r==KErrNone) sl@0: { sl@0: if(iTotalPartitionsOpened == 0) sl@0: { sl@0: UpdatePartitionInfo(); sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT2, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: if (!(m.Flags() & TLocDrvRequest::EAdjusted)) sl@0: { sl@0: // If this isn't the only partition, don't allow access to the whole media sl@0: if (iTotalPartitionsOpened > 1) sl@0: m.DriverFlags() &= ~RLocalDrive::ELocDrvWholeMedia; sl@0: r=m.CheckAndAdjustForPartition(); sl@0: } sl@0: if (r==KErrNone) sl@0: { sl@0: OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_INTERNALS, DPRIMARYMEDIABASE_DOREQUEST_START, "req Id=%d; Remote Thread=0x%x", (TInt) m.Id(), (TUint) m.RemoteThread()); sl@0: r=media->iDriver->Request(m); sl@0: if (r>0) sl@0: { sl@0: // defer request sl@0: #ifdef __DEMAND_PAGING__ sl@0: if (DMediaPagingDevice::PagingRequest(m)) sl@0: { sl@0: __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT()); sl@0: __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT()); sl@0: __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT()); sl@0: __KTRACE_OPT2(KLOCDPAGING,KLOCDRV,Kern::Printf("Defer PageIn request 0x%08x",&m)); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOREQUEST2, "Defer PageIn request 0x%08x", &m); sl@0: DMediaPagingDevice* pagingdevice=iBody->iPagingDevice; sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: TInt id=m.iValue; sl@0: if (id==DMediaPagingDevice::ERomPageInRequest) sl@0: { sl@0: NKern::FMWait(&pagingdevice->iInstrumentationLock); sl@0: if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ) sl@0: pagingdevice->iROMStats.iTotalReDeferrals++; sl@0: else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ) sl@0: pagingdevice->iROMStats.iTotalSynchDeferredFromMainQ++; sl@0: NKern::FMSignal(&pagingdevice->iInstrumentationLock); sl@0: } sl@0: else if (m.Flags() & TLocDrvRequest::ECodePaging) sl@0: { sl@0: NKern::FMWait(&pagingdevice->iInstrumentationLock); sl@0: if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ) sl@0: pagingdevice->iCodeStats.iTotalReDeferrals++; sl@0: else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ) sl@0: pagingdevice->iCodeStats.iTotalSynchDeferredFromMainQ++; sl@0: NKern::FMSignal(&pagingdevice->iInstrumentationLock); sl@0: } sl@0: else if (m.Flags() & TLocDrvRequest::EDataPaging) sl@0: { sl@0: NKern::FMWait(&pagingdevice->iInstrumentationLock); sl@0: if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ) sl@0: pagingdevice->iDataStats.iTotalReDeferrals++; sl@0: else if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ) sl@0: pagingdevice->iDataStats.iTotalSynchDeferredFromMainQ++; sl@0: NKern::FMSignal(&pagingdevice->iInstrumentationLock); sl@0: } sl@0: #endif sl@0: pagingdevice->SendToDeferredQ(&m); sl@0: } sl@0: else sl@0: #endif sl@0: m.Forward(&iDeferred,EFalse); sl@0: r=KErrNone; sl@0: } sl@0: #if defined(__DEMAND_PAGING__) && defined(_DEBUG) sl@0: else if (r == KErrNone && DMediaPagingDevice::PagingRequest(m)) sl@0: { sl@0: __KTRACE_OPT(KLOCDPAGING,Kern::Printf("PageIn req 0x%08x completing asynchronously",&m)); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOREQUEST3, "PageIn req 0x%08x completing asynchronously", &m); sl@0: } sl@0: #endif sl@0: } sl@0: } sl@0: sl@0: if (r!=KErrNone && iCurrentReq) sl@0: { sl@0: TInt s=(r==KErrCompletion)?KErrNone:r; sl@0: CHECK_RET(s); sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: // got here because media driver cannot service or defer this request or did service it synchronously sl@0: if (DMediaPagingDevice::PagingRequest(m)) sl@0: { sl@0: __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT()); sl@0: __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT()); sl@0: __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT()); sl@0: __KTRACE_OPT(KLOCDPAGING,Kern::Printf("media driver cannot service or defer PageIn request 0x%08x or serviced it synchronously (%d)",&m, s)); sl@0: OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOREQUEST4, "Media driver cannot service or defer PageIn request 0x%08x or serviced it synchronously; retval=%d",(TUint) &m, s); sl@0: iBody->iPagingDevice->CompleteRequest(&m, s); sl@0: } sl@0: else sl@0: #endif sl@0: sl@0: CompleteRequest(m, s); sl@0: OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_INTERNALS, DPRIMARYMEDIABASE_DOREQUEST_RETURN, "Return req Id=%d; Remote Thread=0x%x; retval=%d", (TInt) m.Id(), (TUint) m.RemoteThread(), (TInt) s); sl@0: } sl@0: sl@0: iCurrentReq=NULL; sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT3, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::PowerUpComplete(TInt anError) sl@0: /** sl@0: Called after the device is powered up or there is some error while powering up the device. sl@0: If there is an error powering up the devices then it just completes the current running requests with an error sl@0: and also completes the outstanding requests on the iDeferred message queue by calling SetClosed( ). sl@0: If the device is powered up OK then it either opens the media drivers sl@0: and if they are already open then it handles the current/pending requests. sl@0: sl@0: @param anError Error code to be passed on while completing outstanding requests. sl@0: */ sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase(%d)::PowerUpComplete err %d iState %d",iMediaId,anError,iState)); sl@0: sl@0: OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_POWERUPCOMPLETE, "iMediaId=%d; anError=%d; iState=%d", iMediaId, anError, iState ); sl@0: sl@0: if (anError!=KErrNone) sl@0: { sl@0: // error powering up device sl@0: if (iState==EPoweringUp1 || iState==EPoweringUp2) sl@0: SetClosed(anError); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_EXIT, this ); sl@0: return; sl@0: } sl@0: sl@0: // Powered up OK - now open media drivers sl@0: if (iState==EPoweringUp1) sl@0: { sl@0: iState=EOpening; sl@0: StartOpenMediaDrivers(); sl@0: } sl@0: else if (iState==EPoweringUp2) sl@0: { sl@0: // media is powered up and ready, so handle the current/pending requests sl@0: MediaReadyHandleRequest(); sl@0: } sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_POWERUPCOMPLETE_EXIT2, this ); sl@0: } sl@0: sl@0: void DPrimaryMediaBase::CloseMediaDrivers(DMedia* aMedia) sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase(%d)::CloseMediaDrivers",iMediaId)); sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS1, "DPrimaryMediaBase iMediaId=%d", iMediaId ); sl@0: sl@0: // we mustn't ever close the media driver if it's responsible for data paging as re-opening the drive sl@0: // would involve memory allocation which might cause deadlock if the kernel heap were to grow sl@0: #ifdef __DEMAND_PAGING__ sl@0: if (DataPagingDfcQ(this)) sl@0: { sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for data paging media %08X", this)); sl@0: OstTrace1(TRACE_FLOW, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT1, "CloseMediaDrivers aborting for data paging media 0x%08x", this); sl@0: return; sl@0: } sl@0: #endif sl@0: sl@0: TInt i; sl@0: for (i=0; iiPrimaryMedia==this) sl@0: { sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",i)); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", i ); sl@0: if (aMedia == NULL || pL->iMedia == aMedia) sl@0: { sl@0: pL->iMedia=NULL; sl@0: } sl@0: } sl@0: } sl@0: for (i=iLastMediaId; i>=iMediaId; i--) sl@0: { sl@0: DMedia* pM=TheMedia[i]; sl@0: if (aMedia == NULL || pM == aMedia) sl@0: { sl@0: DMediaDriver* pD=pM->iDriver; sl@0: pM->iDriver=NULL; sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DMedia[%d] @ %08x Driver @ %08x",i,pM,pD)); sl@0: OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS3, "MediaId=%d; DMedia=0x%08x; MediaDriver=0x%08x", (TInt) i, (TUint) pM, (TUint) pD ); sl@0: if (pD) sl@0: pD->Close(); sl@0: } sl@0: } sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("iPhysDevIndex=iPhysDevArray.Count()-1; sl@0: iTotalPartitionsOpened=0; sl@0: iMediaDriversOpened=0; sl@0: iNextMediaDriver=NULL; sl@0: OpenNextMediaDriver(); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_STARTOPENMEDIADRIVERS_EXIT2, this ); sl@0: } sl@0: sl@0: void DPrimaryMediaBase::OpenNextMediaDriver() sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::OpenNextMediaDriver, this %x mediaId %d iBody->iPhysDevIndex %d",iNextMediaId, this, iMediaId, iBody->iPhysDevIndex)); sl@0: OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER, "DPrimaryMediaBase iNextMediaId=%d; this=%x; imediaId=%d; iBody->iPhysDevIndex=%d",iNextMediaId, (TUint) this, iMediaId, iBody->iPhysDevIndex); sl@0: sl@0: TVersion ver(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion); sl@0: SPhysicalDeviceEntry& e=iPhysDevArray[iBody->iPhysDevIndex]; sl@0: DPhysicalDevice* pD=e.iPhysicalDevice; sl@0: sl@0: iState = EOpening; sl@0: sl@0: DMedia* pM=TheMedia[iNextMediaId]; sl@0: if (pM && pM->iDriver != NULL) sl@0: { sl@0: iNextMediaDriver = pM->iDriver; sl@0: DoOpenMediaDriverComplete(KErrNone); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_EXIT1, this ); sl@0: return; sl@0: } sl@0: sl@0: // this may be asynchronous sl@0: TInt s=pD->Create( (DBase*&)iNextMediaDriver, iMediaId, (TDesC8*) &iMountInfo, ver); sl@0: sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("Media:Open-Opening %o(PRI:%d)-%d",pD,e.iPriority,s)); sl@0: if (s!=KErrNone) sl@0: { sl@0: iAsyncErrorCode=s; sl@0: iAsyncDfc.Enque(); sl@0: } sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_OPENNEXTMEDIADRIVER_EXIT2, this ); sl@0: } sl@0: sl@0: // Called when a media driver has responded to the Open request sl@0: void DPrimaryMediaBase::DoOpenMediaDriverComplete(TInt anError) sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::DoOpenMediaDriverComplete error %d iNextMediaDriver %x",iNextMediaId,anError,iNextMediaDriver)); sl@0: OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE, "iMediaId=%d; anError=%d; iNextMediaDriver=0x%x", (TInt) iNextMediaId, (TInt) anError, (TUint) iNextMediaDriver); sl@0: sl@0: sl@0: if (anError!=KErrNone) sl@0: { sl@0: DMediaDriver* md = iNextMediaDriver; sl@0: iNextMediaDriver = NULL; sl@0: if (md) sl@0: md->Close(); sl@0: } sl@0: if (anError==KErrNotReady || anError==KErrNoMemory) sl@0: { sl@0: // if it's not ready or we're out of memory, abort sl@0: CloseMediaDrivers(); sl@0: SetClosed(anError); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_EXIT1, this ); sl@0: return; sl@0: } sl@0: if (anError==KErrNone) sl@0: { sl@0: DMedia* pM=TheMedia[iNextMediaId]; sl@0: pM->iDriver=iNextMediaDriver; sl@0: DPhysicalDevice*& pD=iPhysDevArray[iBody->iPhysDevIndex].iPhysicalDevice; sl@0: iNextMediaDriver->iPhysicalDevice=pD; sl@0: pD=NULL; // so it won't be closed when we tidy up sl@0: ++iMediaDriversOpened; sl@0: } sl@0: sl@0: sl@0: // if no error, read partition info on media sl@0: iState = EReadPartitionInfo; sl@0: sl@0: if (anError == KErrNone) sl@0: { sl@0: DMedia* pM=TheMedia[iNextMediaId]; sl@0: TInt r = pM->iDriver->PartitionInfo(pM->iPartitionInfo); sl@0: if (r!=KErrNone) sl@0: { sl@0: if (r==KErrCompletion) sl@0: r=KErrNone; sl@0: DoPartitionInfoComplete(r); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: DoPartitionInfoComplete(anError); sl@0: } sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOOPENMEDIADRIVERCOMPLETE_EXIT2, this ); sl@0: } sl@0: sl@0: void DPrimaryMediaBase::DoPartitionInfoComplete(TInt anError) sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::DoPartitionInfoComplete error %d",iNextMediaId,anError)); sl@0: sl@0: OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE1, "iNextMediaId=%d; anError=%d", iNextMediaId, anError ); sl@0: sl@0: DMedia* pM=TheMedia[iNextMediaId]; sl@0: if (anError==KErrNone || anError == KErrLocked) sl@0: { sl@0: // successfully read partition info sl@0: iTotalPartitionsOpened+=pM->PartitionCount(); sl@0: } sl@0: else sl@0: { sl@0: // couldn't read partition info or driver failed to open sl@0: if (pM->iDriver) sl@0: { sl@0: #ifdef __DEMAND_PAGING__ sl@0: if (DataPagingDfcQ(this)) sl@0: { sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DoPartitionInfoComplete(%d) Close Media Driver aborted for data paging media %08X", this)); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE2, "Close Media Driver for data paging media 0x%08x", this); sl@0: } sl@0: else sl@0: #endif sl@0: { sl@0: pM->iDriver->Close(); sl@0: pM->iDriver=NULL; sl@0: } sl@0: } sl@0: if (anError==KErrNotReady || anError==KErrNoMemory) sl@0: { sl@0: // if it's not ready or we're out of memory, or the drive is locked, abort sl@0: CloseMediaDrivers(); sl@0: SetClosed(anError); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT, this ); sl@0: return; sl@0: } sl@0: } sl@0: sl@0: // Open next media driver, if there is one sl@0: TBool complete = EFalse; sl@0: if (++iNextMediaId>iLastMediaId) sl@0: complete=ETrue; sl@0: if (iBody->iPhysDevIndex==0) sl@0: complete=ETrue; sl@0: else sl@0: iBody->iPhysDevIndex--; sl@0: if (!complete) sl@0: { sl@0: OpenNextMediaDriver(); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT2, this ); sl@0: return; sl@0: } sl@0: sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase %d All media drivers open & partitions read",iMediaId)); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("%d media drivers opened",iMediaDriversOpened)); sl@0: OstTrace1( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE3, "iMediaDriversOpened=%d", iMediaDriversOpened ); sl@0: if (iMediaDriversOpened==0) sl@0: { sl@0: SetClosed(KErrNotSupported); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT3, this ); sl@0: return; sl@0: } sl@0: sl@0: // we are now finished with media driver list sl@0: iPhysDevArray.Close(); sl@0: sl@0: // Finished reading partition info sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase %d Read partition info complete",iMediaId)); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("%d total partitions",iTotalPartitionsOpened)); sl@0: OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE4, "Read partition info complete iMediaId=%d; iPartitionsOpened=%d", iMediaId, iTotalPartitionsOpened ); sl@0: if (iTotalPartitionsOpened==0) sl@0: { sl@0: SetClosed(KErrNotSupported); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT4, this ); sl@0: return; sl@0: } sl@0: sl@0: // work out mapping of drives to partitions/media sl@0: TInt totalPartitions=iTotalPartitionsOpened; sl@0: TInt id=iMediaId; // start with primary media sl@0: TInt partitionsOnThisMedia=PartitionCount(); sl@0: TInt partition=0; sl@0: TInt j; sl@0: for (j=0; jiPrimaryMedia==this) sl@0: { sl@0: if (totalPartitions==0) sl@0: { sl@0: pD->iMedia=NULL; sl@0: continue; sl@0: } sl@0: if (partition==partitionsOnThisMedia) sl@0: { sl@0: id++; sl@0: partition=0; sl@0: partitionsOnThisMedia=TheMedia[id]->PartitionCount(); sl@0: } sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d = Media %d Partition %d",j,id,partition)); sl@0: OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE5, "Local Drive=%d; iMediaId=%d; partition=%d", j, id, partition ); sl@0: sl@0: pD->iMedia=TheMedia[id]; sl@0: pD->iPartitionNumber=partition; sl@0: memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry)); sl@0: partition++; sl@0: totalPartitions--; sl@0: } sl@0: } sl@0: sl@0: // media is now ready - handle current or deferred requests sl@0: MediaReadyHandleRequest(); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE_EXIT5, this ); sl@0: } sl@0: sl@0: void DPrimaryMediaBase::MediaReadyHandleRequest() sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_MEDIAREADYHANDLEREQUEST_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase::MediaReadyHandleRequest() this %x", this)); sl@0: iState = EReady; sl@0: sl@0: // now we can process the current request sl@0: // careful - thread may have exited while we were powering up sl@0: if (iCurrentReq) sl@0: { sl@0: DoRequest(*iCurrentReq); // this sets iCurrentReq=NULL sl@0: } sl@0: sl@0: // see if we can process any other requests concurrently sl@0: RunDeferred(); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_MEDIAREADYHANDLEREQUEST_EXIT, this ); sl@0: } sl@0: sl@0: void DPrimaryMediaBase::UpdatePartitionInfo() sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_UPDATEPARTITIONINFO_ENTRY, this ); sl@0: iState=EReadPartitionInfo; sl@0: iNextMediaId=iMediaId; sl@0: DMedia* pM=TheMedia[iNextMediaId]; sl@0: TInt r=pM->iDriver->PartitionInfo(pM->iPartitionInfo); sl@0: if (r!=KErrNone) sl@0: { sl@0: if (r==KErrCompletion) sl@0: r=KErrNone; sl@0: DoPartitionInfoComplete(r); sl@0: } sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_UPDATEPARTITIONINFO_EXIT, this ); sl@0: } sl@0: sl@0: void DPrimaryMediaBase::CompleteCurrent(TInt anError) sl@0: { sl@0: OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_COMPLETECURRENT_ENTRY, this ); sl@0: if (iCurrentReq) sl@0: { sl@0: CHECK_RET(anError); sl@0: #ifdef __DEMAND_PAGING__ sl@0: // got here because it was powered down when powering up, or failed powering up or failed opening MD or got media change sl@0: if (DMediaPagingDevice::PagingRequest(*iCurrentReq)) sl@0: { sl@0: __ASSERT_ALWAYS(iPagingMedia,LOCM_FAULT()); sl@0: __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT()); sl@0: __ASSERT_ALWAYS( ((iCurrentReq->Flags() & TLocDrvRequest::ECodePaging) == 0) || (iCurrentReq->Drive()->iPagingDrv), LOCM_FAULT()); sl@0: sl@0: __KTRACE_OPT2(KLOCDPAGING,KFAIL,Kern::Printf("Got here because it was powered down when powering up, or failed powering up or failed opening MD or got media change")); sl@0: OstTraceDef0(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_COMPLETECURRENT, "Completed request due to powered down when powering up, or failed powering up or failed opening MD or got media change"); sl@0: iBody->iPagingDevice->CompleteRequest(iCurrentReq, anError); sl@0: } sl@0: else sl@0: #endif sl@0: CompleteRequest(*iCurrentReq, anError); sl@0: iCurrentReq=NULL; sl@0: } sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_COMPLETECURRENT_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: void DPrimaryMediaBase::CompleteRequest(TLocDrvRequest& aMsg, TInt aResult) sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_COMPLETEREQUEST_ENTRY, this ); sl@0: OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_COMPLETEREQUEST1, "TLocDrvRequest Object=0x%x; aResult=%d", (TUint) &aMsg, aResult); sl@0: aMsg.Complete(aResult,EFalse); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_COMPLETEREQUEST_EXIT, this ); sl@0: } sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::RunDeferred() sl@0: /** sl@0: Runs deferred Requests. Initiated from DPrimaryMediaBase::PowerUpComplete() function sl@0: to see if any other requests can be processed concurrently. sl@0: Can also be called from DPrimaryMediaBase::NotifyPowerDown sl@0: or DPrimaryMediaBase::NotifyEmergencyPowerDown() function or DMediaDriver::Complete() sl@0: */ sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_RUNDEFERRED_ENTRY, this ); sl@0: // Do nothing if an open or close is in progress - this might be the case, for example, sl@0: // if a EForceMediaChange request (with the KForceMediaChangeReOpenMediaDriver flag) sl@0: // has recently been processed sl@0: if (iState!=EReady && iState!=EClosed && iState!=EPoweredDown) sl@0: { sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT1, this ); sl@0: return; sl@0: } sl@0: sl@0: // rerun deferred requests; sl@0: #ifdef __DEMAND_PAGING__ sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: TInt countROM=0; sl@0: TInt countCode=0; sl@0: #endif sl@0: sl@0: if(iPagingMedia) sl@0: { sl@0: __ASSERT_DEBUG(iBody->iPagingDevice,LOCM_FAULT()); sl@0: if(iBody->iPagingDevice->iEmptyingQ & DMediaPagingDevice::EDeferredQ) // if already emptying deferred page in queue, don't reenter sl@0: { sl@0: __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Already emptying deferred queue")); sl@0: OstTrace0(TRACE_FLOW, DPRIMARYMEDIABASE_RUNDEFERRED_EXIT2, "< Already emptying deferred queue"); sl@0: return; sl@0: } sl@0: sl@0: DMediaPagingDevice* pagingdevice=iBody->iPagingDevice; sl@0: TLocDrvRequest* pL = (TLocDrvRequest*) pagingdevice->iDeferredQ.Last(); sl@0: if(pL) sl@0: { sl@0: pagingdevice->iEmptyingQ|= DMediaPagingDevice::EDeferredQ; // prevent reentering when already emptying this queue sl@0: TLocDrvRequest* pM=NULL; sl@0: while (pM != pL && (pM = (TLocDrvRequest*) pagingdevice->iDeferredQ.Poll()) != NULL) // synchronously empty deferred queue but ignore re-deferrals sl@0: { sl@0: __ASSERT_ALWAYS( DMediaPagingDevice::PagingRequest(*pL), LOCM_FAULT() ); sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: (pM->iValue==DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++); sl@0: if(pM==pL) sl@0: { sl@0: NKern::FMWait(&pagingdevice->iInstrumentationLock); sl@0: if(pM->iValue==DMediaPagingDevice::ERomPageInRequest && pagingdevice->iROMStats.iMaxReqsInDeferrediROMStats.iMaxReqsInDeferred=countROM; sl@0: else if ((pM->Flags() & TLocDrvRequest::ECodePaging) && pagingdevice->iCodeStats.iMaxReqsInDeferrediCodeStats.iMaxReqsInDeferred=countCode; sl@0: else if ((pM->Flags() & TLocDrvRequest::EDataPaging) && pagingdevice->iDataStats.iMaxReqsInDeferrediDataStats.iMaxReqsInDeferred=countCode; sl@0: NKern::FMSignal(&pagingdevice->iInstrumentationLock); sl@0: } sl@0: #endif sl@0: __KTRACE_OPT(KLOCDPAGING,Kern::Printf("RunDeferred: process req 0x%08x, last in deferred queue 0x%08x",pM,pL)); sl@0: OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_RUNDEFERRED2, "process req=0x%08x; last in deferred queue=0x%08x",(TUint) pM, (TUint) pL); sl@0: #ifdef BTRACE_PAGING_MEDIA sl@0: BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInDeferredReposted,pM,pM->iValue); sl@0: #endif sl@0: // if Page In requests are synchronous this services them all in sequence, sl@0: // if they're asynch it re-defers them sl@0: DoRequest(*(TLocDrvRequest*)pM); sl@0: } sl@0: pagingdevice->iEmptyingQ&= ~DMediaPagingDevice::EDeferredQ; sl@0: } sl@0: sl@0: // the reason we now try an empty the main Page In queue is there is at least one type of Page In request sl@0: // serviced synchronously in which case when we empty the deferred Page In queue as above, received Page In sl@0: // requests are left in the main queue (not deferred) and we don't want to start processing deferred normal sl@0: // requests before these Page In requests. If all deferred normal requests are synchronous, the received Page sl@0: // In requests will have to wait until all are serviced. NB: requests may be deferred even if the MD services sl@0: // all requests synchronously, but runs background tasks that cannot be interrupted. In this last case the sl@0: // normal deferred queue may have some very long latency requests. sl@0: if(pagingdevice->iEmptyingQ & DMediaPagingDevice::EMainQ) // already emptying main Page In queue, skip (any Page In requests will be deferred) sl@0: { sl@0: __KTRACE_OPT(KLOCDPAGING,Kern::Printf("Already emptying main queue")); sl@0: OstTrace0(TRACE_FLOW, DPRIMARYMEDIABASE_RUNDEFERRED_EXIT3, "< Already emptying main queue"); sl@0: return; sl@0: } sl@0: sl@0: TLocDrvRequest* pM=NULL; sl@0: if (!pagingdevice->iMainQ.iReady) // if it's ready, then queue is empty sl@0: { sl@0: pM = (TLocDrvRequest*) pagingdevice->iMainQ.iMessage; sl@0: pagingdevice->iMainQ.iMessage = NULL; sl@0: if (pM == NULL) sl@0: pM = (TLocDrvRequest*) pagingdevice->iMainQ.Poll(); sl@0: } sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: countROM = countCode=0; sl@0: #endif sl@0: if(pM) sl@0: { sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: __e32_atomic_add_ord32(&pagingdevice->iROMStats.iTotalSynchEmptiedMainQ, 1); sl@0: #endif sl@0: pagingdevice->iEmptyingQ|=DMediaPagingDevice::EMainQ; sl@0: for ( ; pM != NULL; pM = (TLocDrvRequest*) pagingdevice->iMainQ.Poll()) sl@0: { sl@0: __ASSERT_ALWAYS(DMediaPagingDevice::PagingRequest(*pM), LOCM_FAULT()); sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: (pM->iValue==DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++); sl@0: #endif sl@0: sl@0: __KTRACE_OPT(KLOCDPAGING,Kern::Printf("RunDeferred: process req 0x%08x",pM)); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_RUNDEFERRED4, "process req=0x%08x", pM); sl@0: DoRequest(*(TLocDrvRequest*)pM); // if Page In requests are synchronous this services them all in sequence, if they're asynch it defers them sl@0: } sl@0: sl@0: pagingdevice->iEmptyingQ&= ~DMediaPagingDevice::EMainQ; sl@0: sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: NKern::FMWait(&pagingdevice->iInstrumentationLock); sl@0: pagingdevice->iROMStats.iTotalSynchServicedFromMainQ+=countROM; sl@0: if(pagingdevice->iROMStats.iMaxReqsInPendingiROMStats.iMaxReqsInPending=countROM; sl@0: pagingdevice->iCodeStats.iTotalSynchServicedFromMainQ+=countCode; sl@0: if(pagingdevice->iCodeStats.iMaxReqsInPendingiCodeStats.iMaxReqsInPending=countCode; sl@0: NKern::FMSignal(&pagingdevice->iInstrumentationLock); sl@0: #endif sl@0: } // if (pM) sl@0: } // if(iPagingMedia) sl@0: #endif sl@0: if (iRunningDeferred) sl@0: { sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT4, this ); sl@0: return; sl@0: } sl@0: TMessageBase* pL = iDeferred.Last(); sl@0: if (!pL) sl@0: { sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT5, this ); sl@0: return; // no deferred requests sl@0: } sl@0: iRunningDeferred=1; sl@0: TMessageBase* pM=NULL; sl@0: sl@0: while( pM != pL && (pM=iDeferred.Poll()) != NULL) // stop after processing last one (requests may be re-deferred) sl@0: DoRequest(*(TLocDrvRequest*)pM); sl@0: iRunningDeferred=0; sl@0: sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_RUNDEFERRED_EXIT6, this ); sl@0: } sl@0: sl@0: void DPrimaryMediaBase::SetClosed(TInt anError) sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_SETCLOSED_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::SetClosed error %d",iMediaId,anError)); sl@0: OstTraceExt2( TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_SETCLOSED, "iMediaId=%d; anError=%d", iMediaId, anError ); sl@0: CHECK_RET(anError); sl@0: sl@0: // cancel DMediaDriver::OpenMediaDriverComplete() / DMediaDriver::PartitionInfoComplete() DFC sl@0: iAsyncDfc.Cancel(); sl@0: sl@0: iDeferred.CompleteAll(anError); sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: if(iPagingMedia) sl@0: iBody->iPagingDevice->iDeferredQ.CompleteAll(anError); sl@0: #endif sl@0: sl@0: CompleteCurrent(anError); sl@0: sl@0: sl@0: sl@0: if (iState==EOpening) sl@0: iPhysDevArray.Close(); sl@0: sl@0: iState = EClosed; sl@0: sl@0: iWaitMedChg.CompleteAll(KErrNone); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_SETCLOSED_EXIT, this ); sl@0: } sl@0: sl@0: void DPrimaryMediaBase::NotifyClients(TBool aMediaChange,TLocDrv* aLocDrv) sl@0: sl@0: // sl@0: // Notify all clients of a media change or power-down event sl@0: // sl@0: { sl@0: OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_NOTIFYCLIENTS_ENTRY, this ); sl@0: sl@0: SDblQueLink* pL=iConnectionQ.iA.iNext; sl@0: while (pL!=&iConnectionQ.iA) sl@0: { sl@0: DLocalDrive* pD=_LOFF(pL,DLocalDrive,iLink); sl@0: // Issue the notification if the caller wants to notify all drives (aLocDrv == NULL) or sl@0: // the specified drive matches this one sl@0: if (aLocDrv == NULL || aLocDrv == pD->iDrive) sl@0: pD->NotifyChange(*this, aMediaChange); sl@0: pL=pL->iNext; sl@0: } sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYCLIENTS_EXIT, this ); sl@0: } sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::NotifyMediaChange() sl@0: /** sl@0: Closes all media drivers on this device and notifies all connections that media change has occurred sl@0: and completes any outstanding requests with KErrNotReady. sl@0: This also completes any force media change requests with KErrNone. sl@0: */ sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaChange state %d",iMediaId,iState)); sl@0: sl@0: OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE, "iMediaId=%d; iState=%d", iMediaId, iState ); sl@0: sl@0: TInt state=iState; sl@0: sl@0: __ASSERT_DEBUG(iBody, LOCM_FAULT()); sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: iBody->iMediaChanges++; sl@0: sl@0: // As data paging media never close, need to ensure the media driver cancels sl@0: // any requests it owns as the stack may be powered down by DPBusPrimaryMedia::ForceMediaChange(). sl@0: // DMediaDriver::NotifyPowerDown() should do this sl@0: if(DataPagingDfcQ(this)) sl@0: NotifyPowerDown(); sl@0: #endif sl@0: sl@0: // complete any outstanding requests with KErrNotReady sl@0: // and any force media change requests with KErrNone sl@0: SetClosed(KErrNotReady); sl@0: sl@0: // close all media drivers on this device sl@0: if (state>=EOpening) sl@0: { sl@0: CloseMediaDrivers(); sl@0: } sl@0: sl@0: // notify all connections that media change has occurred sl@0: NotifyClients(ETrue); sl@0: sl@0: // complete any force media change requests sl@0: iWaitMedChg.CompleteAll(KErrNone); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::NotifyPowerDown() sl@0: /** sl@0: Called on machine power-down. Notifies all media drivers on this device. sl@0: If device is not ready then it completes current requests but leaves other outstanding requests sl@0: If ready, media driver should complete current request. sl@0: sl@0: */ sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyPowerDown state %d",iMediaId,iState)); sl@0: sl@0: OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPOWERDOWN, "iMediaId=%d; iState=%d", iMediaId, iState ); sl@0: sl@0: TInt id; sl@0: TBool allPersistent = ETrue; sl@0: TBool allOpen = ETrue; sl@0: sl@0: // notify all media drivers on this device sl@0: for (id=iMediaId; id<=iLastMediaId; id++) sl@0: { sl@0: DMedia* pM = TheMedia[id]; sl@0: DMediaDriver* pD = pM->iDriver; sl@0: sl@0: if ((pD) && (iState==EReady || iState==EReadPartitionInfo || iState==EOpening || iState==EPoweringUp2 || iState==ERecovering)) sl@0: pD->NotifyPowerDown(); sl@0: sl@0: if (pD == NULL || pD->iPhysicalDevice == NULL) sl@0: allOpen = EFalse; sl@0: else if (pD->iPhysicalDevice->Info(DPhysicalDevice::EMediaDriverPersistent, NULL) != KErrNone) sl@0: { sl@0: // We must NOT destroy the media driver if this media is responsible for data paging as sl@0: // re-opening the media driver would involve memory allocation which might cause a deadlock sl@0: #ifdef __DEMAND_PAGING__ sl@0: __ASSERT_ALWAYS(!DataPagingDfcQ(this), LOCM_FAULT()); sl@0: #endif sl@0: allPersistent = EFalse; sl@0: } sl@0: } sl@0: sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("allPersistent(%d)::allOpen %d",allPersistent, allOpen)); sl@0: OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPOWERDOWN2, "allPersistent=%d; allOpen=%d", allPersistent, allOpen ); sl@0: sl@0: if (allPersistent && allOpen && iState == EReady) sl@0: { sl@0: // sl@0: // The EPoweredDown state indicates that the media is powered down, but the media driver still exists. sl@0: // sl@0: // - This allows the media driver to still be accessed (ie - to determine driver capabilities) without sl@0: // the need to power up the device, which can be a lengthy operation. sl@0: // sl@0: // - NOTE : This will need re-visiting if we ever re-enable standby mode on a platform that is not capable sl@0: // of detecting door interrupts while in standby. In such a scenario, problems could occur as sl@0: // the device capabilities may change without the local media subsystem recognising. sl@0: // sl@0: iState=EPoweredDown; sl@0: } sl@0: else sl@0: { sl@0: CloseMediaDrivers(); sl@0: SetClosed(KErrNotReady); sl@0: } sl@0: sl@0: NotifyClients(EFalse); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::NotifyPsuFault(TInt anError) sl@0: /** sl@0: Closes all media drivers on this device and completes any outstanding requests with error code. sl@0: @param anError Error code to be passed on while closing media drivers and completing outstanding requests. sl@0: */ sl@0: sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYPSUFAULT_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyPsuFault state %d, err %d",iMediaId,iState,anError)); sl@0: OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYPSUFAULT, "iMediaId=%d; iState=%d; anError=%d", iMediaId, iState, anError ); sl@0: sl@0: if (iState>=EOpening) sl@0: { sl@0: CloseMediaDrivers(); sl@0: } sl@0: sl@0: // complete any outstanding requests with error sl@0: SetClosed(anError); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPSUFAULT_EXIT, this ); sl@0: } sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::NotifyEmergencyPowerDown() sl@0: /** sl@0: Called on emergency power down. Notifies all media drivers on this device. sl@0: If it is not in a ready state then it completes the current request but leaves other outstanding requests. sl@0: If it is ready then the media driver should complete the current request. sl@0: It closes all media drivers and notifies all clients of a power down event. sl@0: */ sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyEmergencyPowerDown state %d",iMediaId,iState)); sl@0: OstTraceExt2( TRACE_INTERNALS, DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN, "iMediaId=%d; iState=%d", iMediaId, iState ); sl@0: sl@0: TBool recover=EFalse; sl@0: if (iState==EReady && iCritical!=0) sl@0: { sl@0: // check if emergency power recovery supported sl@0: ; sl@0: } sl@0: if (recover) sl@0: { sl@0: } sl@0: sl@0: // else just return KErrAbort sl@0: // notify all media drivers on this device sl@0: if (iState==EReady || iState==EOpening || iState==EPoweringUp2 || iState==ERecovering) sl@0: { sl@0: TInt id; sl@0: for (id=iMediaId; id<=iLastMediaId; id++) sl@0: { sl@0: DMedia* pM=TheMedia[id]; sl@0: DMediaDriver* pD=pM->iDriver; sl@0: if (pD) sl@0: pD->NotifyEmergencyPowerDown(); sl@0: } sl@0: } sl@0: sl@0: if (iState!=EReady) sl@0: { sl@0: // complete current request but leave other outstanding requests sl@0: // if ready, media driver should complete current request sl@0: CompleteCurrent(KErrNotReady); sl@0: } sl@0: CloseMediaDrivers(); sl@0: SetClosed(KErrNotReady); sl@0: NotifyClients(EFalse); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_EXIT, this ); sl@0: } sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::NotifyMediaPresent() sl@0: /** sl@0: Notifies clients of a media change by calling NotifyClients ( ) function to indicate that media is present. sl@0: */ sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_ENTRY, this ); sl@0: NotifyClients(ETrue); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_EXIT, this ); sl@0: } sl@0: sl@0: EXPORT_C TInt DPrimaryMediaBase::DoInCritical() sl@0: /** sl@0: Flags the media driver as entering a critical part of its processing. sl@0: sl@0: In this context, critical means that the driver must be allowed to complete sl@0: its current activity. sl@0: For example, a request to power down the device must be deferred until sl@0: the driver exits the critical part. sl@0: sl@0: @return KErrNone, if the driver has been successfully flagged as being in sl@0: a critical part; otherwise, one of the other system-wide error codes. sl@0: The default implementation just returns KErrNone and can be overridden in the derived class sl@0: @see DPrimaryMediaBase::DoEndInCritical() sl@0: */ sl@0: sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::DoEndInCritical() sl@0: /** sl@0: Flags the media driver as leaving a critical part of its processing. sl@0: sl@0: Default implementation does nothing sl@0: @see DPrimaryMediaBase::DoEndInCritical() sl@0: */ sl@0: { sl@0: } sl@0: sl@0: TInt DPrimaryMediaBase::InCritical() sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_INCRITICAL_ENTRY, this ); sl@0: if (iCritical==0) sl@0: { sl@0: TInt r=DoInCritical(); sl@0: if (r!=KErrNone) sl@0: { sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_INCRITICAL_EXIT1, this, r ); sl@0: return r; sl@0: } sl@0: } sl@0: ++iCritical; sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_INCRITICAL_EXIT2, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DPrimaryMediaBase::EndInCritical() sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_ENDINCRITICAL_ENTRY, this ); sl@0: if (--iCritical==0) sl@0: DoEndInCritical(); sl@0: OstTraceFunctionExit1( DPRIMARYMEDIABASE_ENDINCRITICAL_EXIT, this ); sl@0: } sl@0: sl@0: EXPORT_C void DPrimaryMediaBase::DeltaCurrentConsumption(TInt /*aCurrent*/) sl@0: /** sl@0: Sets the incremental value of current consumption to aCurrent. sl@0: The default implementation does nothing . sl@0: sl@0: @param aCurrent Delta Current in Milliamps sl@0: */ sl@0: { sl@0: // default implementation sl@0: } sl@0: sl@0: TInt DPrimaryMediaBase::OpenMediaDriver() sl@0: // sl@0: // Synchronous open for devices with no DFC queue (e.g. IRAM) sl@0: // sl@0: { sl@0: OstTraceFunctionEntry1( DPRIMARYMEDIABASE_OPENMEDIADRIVER_ENTRY, this ); sl@0: sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf(">DPrimaryMediaBase:OpenMediaDriver-%d",iMediaId)); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_OPENMEDIADRIVER1, "iMediaId=%d", iMediaId); sl@0: sl@0: TVersion ver(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion); sl@0: sl@0: // Get a list of all currently loaded media drivers sl@0: // Most media drivers do not make use of the pointer iMountInfo.iInfo when sl@0: // their Validate() procedures are called from RPhysicalDeviceArray::GetDriverList(). sl@0: // However, a group of media drivers sharing the same id (passed in iDevice) may use sl@0: // the additional information pointed to by iMountInfo.iInfo to distinguish sl@0: // group members. This information is passed when the media driver is registered sl@0: // using LocDrv::RegisterMediaDevice(). sl@0: TInt r=iPhysDevArray.GetDriverList(KLitMediaDriverName,iDevice,iMountInfo.iInfo,ver); sl@0: if (r!=KErrNone) sl@0: { sl@0: OstTraceFunctionExitExt( DPRIMARYMEDIABASE_OPENMEDIADRIVER_EXIT1, this, r ); sl@0: return r; sl@0: } sl@0: // Go through them starting with highest priority sl@0: TInt totalPartitions=0; sl@0: TInt c=iPhysDevArray.Count(); // can't be zero sl@0: TInt i=c-1; sl@0: r=KErrNotSupported; sl@0: for (iNextMediaId=iMediaId; i>=0 && iNextMediaId<=iLastMediaId && r!=KErrNotReady; i--) sl@0: { sl@0: DPhysicalDevice* pD=iPhysDevArray[i].iPhysicalDevice; sl@0: DMediaDriver *pM=NULL; sl@0: sl@0: // try to open media driver sl@0: TInt s=pD->Create( (DBase*&)pM, iMediaId, NULL, ver); sl@0: sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("Media:Open-Opening %o(PRI:%d)-%d",pD,iPhysDevArray[i].iPriority,s)); sl@0: OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_OPENMEDIADRIVER2, "Media:Open-Opening 0x%x iPriority=%d; retval=%d", (TUint) pD, (TUint) iPhysDevArray[i].iPriority, (TUint) s); sl@0: if (s!=KErrNone && pM) sl@0: { sl@0: pM->Close(); sl@0: pM=NULL; sl@0: } sl@0: if (s==KErrNotReady) sl@0: { sl@0: r=KErrNotReady; // If it isn't ready - nothing will open. sl@0: break; sl@0: } sl@0: if (s==KErrNoMemory) sl@0: { sl@0: r=KErrNoMemory; // If we are out of memory, give up now sl@0: break; sl@0: } sl@0: if (s==KErrNone) sl@0: { sl@0: // Found a media driver for this device - check for valid partitions. sl@0: DMedia* media=TheMedia[iNextMediaId]; sl@0: s=pM->PartitionInfo(media->iPartitionInfo); sl@0: if (s==KErrNone) sl@0: { sl@0: r=KErrNone; sl@0: media->iDriver=pM; sl@0: pM->iPhysicalDevice=pD; sl@0: iPhysDevArray[i].iPhysicalDevice=NULL; // so it won't be closed when we tidy up sl@0: totalPartitions+=media->PartitionCount(); sl@0: } sl@0: else sl@0: pM->Close(); sl@0: } sl@0: } sl@0: sl@0: // we are now finished with media driver list sl@0: iPhysDevArray.Close(); sl@0: sl@0: // if driver opened OK, work out mapping of drives to partitions/media sl@0: if (r==KErrNone) sl@0: { sl@0: TInt id=iMediaId; // start with primary media sl@0: TInt partitionsOnThisMedia=PartitionCount(); sl@0: TInt partition=0; sl@0: TInt j; sl@0: for (j=0; jiPrimaryMedia==this) sl@0: { sl@0: if (totalPartitions==0) sl@0: { sl@0: pD->iMedia=NULL; sl@0: continue; sl@0: } sl@0: if (partition==partitionsOnThisMedia) sl@0: { sl@0: id++; sl@0: partition=0; sl@0: partitionsOnThisMedia=TheMedia[id]->PartitionCount(); sl@0: } sl@0: pD->iMedia=TheMedia[id]; sl@0: pD->iPartitionNumber=partition; sl@0: memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry)); sl@0: partition++; sl@0: totalPartitions--; sl@0: } sl@0: } sl@0: } sl@0: sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("iRequestCount, (TUint) 1); sl@0: //Kern::Printf("RCINC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal); sl@0: sl@0: OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTINC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal ); sl@0: sl@0: if (oldVal == 0 && iBody->iPagingDevice) sl@0: { sl@0: //Kern::Printf("RCINC: NotifyBusy()"); sl@0: iBody->iPagingDevice->NotifyBusy(); sl@0: } sl@0: } sl@0: sl@0: // RequestCountDec() sl@0: // sl@0: // Counts the number of outstanding requests sl@0: // For data-paging media, calls DPagingDevice::NotifyIdle() when count reaches zero sl@0: // sl@0: void DPrimaryMediaBase::RequestCountDec() sl@0: { sl@0: __ASSERT_DEBUG(iBody, LOCM_FAULT()); sl@0: TInt oldVal = (TInt) __e32_atomic_add_ord32(&iBody->iRequestCount, (TUint) -1); sl@0: //Kern::Printf("RCDEC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal); sl@0: sl@0: OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTDEC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal ); sl@0: sl@0: if (oldVal == 1 && iBody->iPagingDevice) sl@0: { sl@0: //Kern::Printf("RCDEC: NotifyIdle()"); sl@0: iBody->iPagingDevice->NotifyIdle(); sl@0: } sl@0: __ASSERT_DEBUG(iBody->iRequestCount >= 0, LOCM_FAULT()); sl@0: } sl@0: #endif // __DEMAND_PAGING__ sl@0: sl@0: TPartitionInfo::TPartitionInfo() sl@0: // sl@0: // Constructor sl@0: // sl@0: { sl@0: memclr(this, sizeof(TPartitionInfo)); sl@0: } sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: sl@0: void pageInDfc(TAny* aPtr) sl@0: { sl@0: OstTraceFunctionEntry0( _PAGEINDFC_ENTRY ); sl@0: __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("pageInDfc")); sl@0: DPrimaryMediaBase* primaryMedia=(DPrimaryMediaBase*)aPtr; sl@0: __ASSERT_ALWAYS(primaryMedia && primaryMedia->iPagingMedia && primaryMedia->iBody->iPagingDevice,LOCM_FAULT()); sl@0: DMediaPagingDevice* pagingdevice=primaryMedia->iBody->iPagingDevice; sl@0: sl@0: TLocDrvRequest* m = (TLocDrvRequest*) pagingdevice->iMainQ.iMessage; sl@0: pagingdevice->iMainQ.iMessage = NULL; sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: if (!m) sl@0: __e32_atomic_add_ord8(&pagingdevice->iROMStats.iTotalRunDry, 1); sl@0: #endif sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: TInt countROM=0; sl@0: TInt countCode=0; sl@0: #endif sl@0: sl@0: for ( ; m != NULL; m = (TLocDrvRequest*) pagingdevice->iMainQ.Poll()) sl@0: { sl@0: __ASSERT_ALWAYS(DMediaPagingDevice::PagingRequest(*m), LOCM_FAULT()); sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: (m->iValue == DMediaPagingDevice::ERomPageInRequest)?(countROM++):(countCode++); sl@0: #endif sl@0: __KTRACE_OPT(KLOCDPAGING, Kern::Printf("pageInDfc: process request 0x%08x, last in queue 0x%08x",m, pagingdevice->iMainQ.Last()) ); sl@0: OstTraceDefExt2(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, PAGEINDFC2, "process request=0x%08x; last in queue=0x%08x",(TUint) m, (TUint) pagingdevice->iMainQ.Last()); sl@0: sl@0: primaryMedia->HandleMsg(*m); sl@0: } sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: NKern::FMWait(&pagingdevice->iInstrumentationLock); sl@0: if (pagingdevice->iROMStats.iMaxReqsInPendingiROMStats.iMaxReqsInPending=countROM; sl@0: if (pagingdevice->iCodeStats.iMaxReqsInPendingiCodeStats.iMaxReqsInPending=countCode; sl@0: NKern::FMSignal(&pagingdevice->iInstrumentationLock); sl@0: #endif sl@0: sl@0: pagingdevice->iMainQ.Receive(); // allow reception of more messages sl@0: OstTraceFunctionExit0( _PAGEINDFC_EXIT ); sl@0: } sl@0: sl@0: DMediaPagingDevice::DMediaPagingDevice(DPrimaryMediaBase* aPtr) sl@0: : iMainQ(pageInDfc, aPtr, NULL, KMaxDfcPriority), sl@0: iDeferredQ(NULL, NULL, NULL, 0), // callback never used sl@0: iEmptyingQ(NULL), sl@0: iInstrumentationLock() sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: ,iServicingROM(NULL), iServicingCode(NULL) sl@0: #endif sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_CONSTRUCTOR_ENTRY, this ); sl@0: iPrimaryMedia = aPtr; sl@0: if (iPrimaryMedia->iDfcQ) // media driver has its own thread sl@0: { sl@0: iMainQ.SetDfcQ(iPrimaryMedia->iDfcQ); sl@0: } sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: memclr((TAny*)&iROMStats,sizeof(SMediaROMPagingConcurrencyInfo)+sizeof(SMediaCodePagingConcurrencyInfo)); sl@0: #endif sl@0: #ifdef __DEMAND_PAGING_BENCHMARKS__ sl@0: iROMBenchmarkData.iCount=iROMBenchmarkData.iTotalTime=iROMBenchmarkData.iMaxTime=0; sl@0: iROMBenchmarkData.iMinTime = KMaxTInt; sl@0: iCodeBenchmarkData.iCount=iCodeBenchmarkData.iTotalTime=iCodeBenchmarkData.iMaxTime=0; sl@0: iCodeBenchmarkData.iMinTime = KMaxTInt; sl@0: iDataInBenchmarkData.iCount=iDataInBenchmarkData.iTotalTime=iDataInBenchmarkData.iMaxTime=0; sl@0: iDataInBenchmarkData.iMinTime = KMaxTInt; sl@0: iDataOutBenchmarkData.iCount=iDataOutBenchmarkData.iTotalTime=iDataOutBenchmarkData.iMaxTime=0; sl@0: iDataOutBenchmarkData.iMinTime = KMaxTInt; sl@0: #endif sl@0: sl@0: iMainQ.Receive(); sl@0: OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_CONSTRUCTOR_EXIT, this ); sl@0: } sl@0: sl@0: DMediaPagingDevice::~DMediaPagingDevice() sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_DESTRUCTOR_ENTRY, this ); sl@0: sl@0: if (iMountInfoDataLock) sl@0: ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDataLock); sl@0: sl@0: if (iMountInfoDescHdrLock) sl@0: ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDescHdrLock); sl@0: sl@0: if (iMountInfoDescLenLock) sl@0: ThePinObjectAllocator->ReleasePinObject((DPinObjectAllocator::SVirtualPinContainer*) iMountInfoDescLenLock); sl@0: OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_DMEDIAPAGINGDEVICE_DESTRUCTOR_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: void DMediaPagingDevice::SendToMainQueueDfcAndBlock(TThreadMessage* aMsg) sl@0: { sl@0: OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_SENDTOMAINQUEUEDFCANDBLOCK_ENTRY, this ); sl@0: __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("Send request 0x%08x to main queue",aMsg)); sl@0: __ASSERT_ALWAYS(aMsg->iState==TMessageBase::EFree,LOCM_FAULT()); // check that message was previously completed or never queued sl@0: sl@0: // if drive supports DMA, turn on Physical memory flag & sync memory sl@0: TLocDrvRequest& m=*(TLocDrvRequest*)(aMsg); sl@0: sl@0: TLinAddr addr = (TLinAddr) m.RemoteDes(); sl@0: TInt len = I64LOW(m.Length()); sl@0: sl@0: TBool needSyncAfterRead = EFalse; sl@0: if (m.Drive()->iDmaHelper) sl@0: { sl@0: m.Flags() |= TLocDrvRequest::EPhysAddr; sl@0: if (m.Id() == DLocalDrive::EWrite) sl@0: { sl@0: Cache::SyncMemoryBeforeDmaWrite(addr, len); sl@0: } sl@0: else sl@0: { sl@0: Cache::SyncMemoryBeforeDmaRead(addr, len); sl@0: needSyncAfterRead = ETrue; sl@0: } sl@0: } sl@0: sl@0: // Count the number of outstanding requests if this is the data-paging media, so that sl@0: // we can call DPagingDevice::NotifyBusy() / DPagingDevice::NotifyIdle() sl@0: if ((m.Flags() & TLocDrvRequest::EBackgroundPaging) == 0) sl@0: iPrimaryMedia->RequestCountInc(); sl@0: sl@0: aMsg->SendReceive(&iMainQ); sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: if ((m.Flags() & TLocDrvRequest::EBackgroundPaging) == 0) sl@0: iPrimaryMedia->RequestCountDec(); sl@0: #endif sl@0: sl@0: if (needSyncAfterRead) sl@0: { sl@0: Cache::SyncMemoryAfterDmaRead(addr, len); sl@0: } sl@0: sl@0: sl@0: // come back here when request is completed sl@0: __ASSERT_DEBUG(aMsg->iState==TMessageBase::EFree,LOCM_FAULT()); // check message has been completed sl@0: OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_SENDTOMAINQUEUEDFCANDBLOCK_EXIT, this ); sl@0: } sl@0: sl@0: void DMediaPagingDevice::SendToDeferredQ(TThreadMessage* aMsg) sl@0: { sl@0: OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_SENDTODEFERREDQ_ENTRY, this ); sl@0: // This queue is only accessed from MD thread sl@0: __ASSERT_ALWAYS(aMsg->iState==TMessageBase::EAccepted,LOCM_FAULT()); // check that message was previously dequeued sl@0: #ifdef BTRACE_PAGING_MEDIA sl@0: if(iEmptyingQ&DMediaPagingDevice::EDeferredQ) // already deferring sl@0: BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInReDeferred,aMsg,aMsg->iValue); sl@0: else sl@0: BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInDeferred,aMsg,aMsg->iValue); sl@0: #endif sl@0: sl@0: aMsg->Forward(&iDeferredQ, EFalse); sl@0: OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_SENDTODEFERREDQ_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: void DMediaPagingDevice::CompleteRequest(TThreadMessage* aMsg, TInt aResult) sl@0: { sl@0: OstTraceFunctionEntryExt( DMEDIAPAGINGDEVICE_COMPLETEREQUEST_ENTRY, this ); sl@0: __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("DMediaPagingDevice::CompleteRequest, request 0x%08x result %d", aMsg, aResult)); sl@0: __ASSERT_DEBUG(aMsg->iState==TMessageBase::EAccepted,LOCM_FAULT()); sl@0: sl@0: #ifdef BTRACE_PAGING_MEDIA sl@0: BTraceContext12(BTrace::EPagingMedia,BTrace::EPagingMediaLocMedPageInPagedIn,aMsg,aResult,aMsg->iValue); sl@0: #endif sl@0: sl@0: iPrimaryMedia->CompleteRequest(*((TLocDrvRequest*) aMsg), aResult); sl@0: OstTraceFunctionExit1( DMEDIAPAGINGDEVICE_COMPLETEREQUEST_EXIT, this ); sl@0: } sl@0: sl@0: TInt DMediaPagingDevice::Read(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt aDrvNumber) sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_READ_ENTRY, this ); sl@0: __ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT()); // that would lock up the system, thus better die now sl@0: __ASSERT_ALWAYS(aReq,LOCM_FAULT()); sl@0: __ASSERT_CRITICAL sl@0: sl@0: #ifdef __DEMAND_PAGING_BENCHMARKS__ sl@0: TUint32 bmStart = NKern::FastCounter(); sl@0: #endif sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: TUint8* servicingCount; sl@0: NKern::FMWait(&iInstrumentationLock); sl@0: if(aDrvNumber == EDriveRomPaging) // ROM paging sl@0: { sl@0: servicingCount = &iServicingROM; sl@0: if(iServicingROM) sl@0: iROMStats.iTotalConcurrentReqs++; sl@0: if(!(++iServicingROM)) sl@0: { sl@0: iServicingROM=1; // overflow... sl@0: iROMStats.iTotalConcurrentReqs=0; // ...reset this sl@0: } sl@0: TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty(); sl@0: if(!empty) sl@0: iROMStats.iTotalReqIssuedNonEmptyQ++; sl@0: } sl@0: else if (aDrvNumber == EDriveDataPaging) // Data paging sl@0: { sl@0: servicingCount = &iServicingDataIn; sl@0: if(iServicingDataIn) sl@0: iDataStats.iTotalConcurrentReqs++; sl@0: if(!(++iServicingDataIn)) sl@0: { sl@0: iServicingDataIn=1; // overflow... sl@0: iDataStats.iTotalConcurrentReqs=0; // ...reset this sl@0: } sl@0: TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty(); sl@0: if(!empty) sl@0: iDataStats.iTotalReqIssuedNonEmptyQ++; sl@0: } sl@0: else sl@0: { sl@0: servicingCount = &iServicingCode; sl@0: if(iServicingCode) sl@0: iCodeStats.iTotalConcurrentReqs++; sl@0: if(!(++iServicingCode)) sl@0: { sl@0: iServicingCode=1; // overflow... sl@0: iCodeStats.iTotalConcurrentReqs=0; // ...reset this sl@0: } sl@0: TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty(); sl@0: if(!empty) sl@0: iCodeStats.iTotalReqIssuedNonEmptyQ++; sl@0: } sl@0: NKern::FMSignal(&iInstrumentationLock); sl@0: #endif sl@0: sl@0: TUint offset=aOffset<iDfcQ) sl@0: { sl@0: LOCM_FAULT(); // don't allow paging sl@0: OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_READ_EXIT, this, KErrNone ); sl@0: return KErrNone; // keep compiler happy sl@0: } sl@0: sl@0: sl@0: TLocDrvRequest& m=*(TLocDrvRequest*)(aReq); sl@0: sl@0: sl@0: #ifdef __DEMAND_PAGING_BENCHMARKS__ sl@0: SPagingBenchmarkInfo* info = NULL; sl@0: #endif sl@0: sl@0: sl@0: // Read from the media and allow for retries in the unlikely event of an error. sl@0: const TInt KPageInRetries = 5; sl@0: TInt retVal = KErrGeneral; sl@0: for (TInt i=0; retVal != KErrNone && i < KPageInRetries; i++) sl@0: { sl@0: m.Flags() = TLocDrvRequest::EPaging; sl@0: TLocDrv* pL=NULL; sl@0: if(aDrvNumber == EDriveRomPaging) // ROM paging sl@0: { sl@0: m.Id() = DMediaPagingDevice::ERomPageInRequest; sl@0: if (iRomPagingDriveNumber == KErrNotFound) sl@0: { sl@0: // ROM partition has not been reported by the media driver sl@0: // it is assumed that the media driver will adjust the request accordingly sl@0: m.Flags() |= TLocDrvRequest::EAdjusted; sl@0: // Use a media drive number so the request reaches the correct media... sl@0: m.Drive() = TheDrives[iFirstLocalDriveNumber]; sl@0: } sl@0: else sl@0: { sl@0: //ROM partition has been reported sl@0: //Set drive for use with CheckAndAdjustForPartition sl@0: m.Drive() = TheDrives[iRomPagingDriveNumber]; sl@0: } sl@0: #ifdef __DEMAND_PAGING_BENCHMARKS__ sl@0: __e32_atomic_add_ord32(&iMediaPagingInfo.iRomPageInCount, (TUint) 1); sl@0: info = &iROMBenchmarkData; sl@0: #endif sl@0: } sl@0: else if(aDrvNumber == EDriveDataPaging) // Data paging sl@0: { sl@0: m.Id() = DLocalDrive::ERead; sl@0: m.Flags() |= TLocDrvRequest::EDataPaging; sl@0: m.Drive() = TheDrives[iDataPagingDriveNumber]; sl@0: #ifdef __DEMAND_PAGING_BENCHMARKS__ sl@0: __e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageInCount, (TUint) 1); sl@0: info = &iDataInBenchmarkData; sl@0: #endif sl@0: } sl@0: else if ((aDrvNumber >=0) && (aDrvNumberiPrimaryMedia==iPrimaryMedia),LOCM_FAULT()); // valid drive number? sl@0: m.Drive()=pL; sl@0: #ifdef __DEMAND_PAGING_BENCHMARKS__ sl@0: __e32_atomic_add_ord32(&iMediaPagingInfo.iCodePageInCount, (TUint) 1); sl@0: info = &iCodeBenchmarkData; sl@0: #endif sl@0: } sl@0: else sl@0: LOCM_FAULT(); // invalid drive number sl@0: sl@0: m.RemoteThread()=NULL; sl@0: m.Pos()=offset; sl@0: m.Length()=Int64(size); sl@0: m.RemoteDes()=(TAny*)aBuffer; sl@0: m.RemoteDesOffset()=0; // pre-aligned sl@0: m.DriverFlags()=0; sl@0: __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("ReqId=%d, Pos=0x%lx, Len=0x%lx, remote Des 0x%x",m.Id(),m.Pos(),m.Length(),m.RemoteDes())); sl@0: OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_READ2, "reqId=%d; position=0x%lx; length=0x%x; remote Des=0x%x", (TInt) m.Id(), (TUint) m.Pos(), (TUint) m.Length(), (TUint) m.RemoteDes()); sl@0: sl@0: __ASSERT_DEBUG(iPrimaryMedia->iBody, LOCM_FAULT()); sl@0: TInt mediaChanges = iPrimaryMedia->iBody->iMediaChanges; sl@0: sl@0: SendToMainQueueDfcAndBlock(&m); // queues request, sets and opens client thread, queues dfc and blocks thread until request is completed sl@0: retVal = m.iValue; sl@0: sl@0: #ifdef __DEBUG_DEMAND_PAGING__ sl@0: if (retVal != KErrNone) sl@0: { sl@0: Kern::Printf("Pagin Failure %d, retry %d", retVal, i); sl@0: } sl@0: #endif sl@0: sl@0: // reset retry count if there's ben a media change sl@0: if (retVal != KErrNone && mediaChanges != iPrimaryMedia->iBody->iMediaChanges) sl@0: i = 0; sl@0: } // for () sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: NKern::FMWait(&iInstrumentationLock); sl@0: if (*servicingCount) sl@0: (*servicingCount)--; sl@0: NKern::FMSignal(&iInstrumentationLock); sl@0: #endif sl@0: sl@0: #ifdef __DEMAND_PAGING_BENCHMARKS__ sl@0: TUint32 bmEnd = NKern::FastCounter(); sl@0: ++info->iCount; sl@0: #if !defined(HIGHIGH_RES_TIMER) || defined(HIGH_RES_TIMER_COUNTS_UP) sl@0: TInt64 elapsed=bmEnd-bmStart; sl@0: #else sl@0: TInt64 elapsed=bmStart-bmEnd; sl@0: #endif sl@0: info->iTotalTime += elapsed; sl@0: if (elapsed > info->iMaxTime) sl@0: info->iMaxTime = elapsed; sl@0: if (elapsed < info->iMinTime) sl@0: info->iMinTime = elapsed; sl@0: #endif // __DEMAND_PAGING_BENCHMARKS__ sl@0: OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_READ_EXIT2, this, retVal ); sl@0: return retVal; sl@0: } sl@0: sl@0: TInt DMediaPagingDevice::Write(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TBool aBackground) sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_WRITE_ENTRY, this ); sl@0: __ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT()); // that would lock up the system, thus better die now sl@0: __ASSERT_ALWAYS(aReq,LOCM_FAULT()); sl@0: __ASSERT_CRITICAL sl@0: sl@0: #ifdef __DEMAND_PAGING_BENCHMARKS__ sl@0: TUint32 bmStart = NKern::FastCounter(); sl@0: #endif sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: NKern::FMWait(&iInstrumentationLock); sl@0: if(iServicingDataOut) sl@0: iDataStats.iTotalConcurrentReqs++; sl@0: if(!(++iServicingDataOut)) sl@0: { sl@0: iServicingDataOut=1; // overflow... sl@0: iDataStats.iTotalConcurrentReqs=0; // ...reset this sl@0: } sl@0: TBool empty = iMainQ.iReady && iDeferredQ.iQ.IsEmpty(); sl@0: if(!empty) sl@0: iDataStats.iTotalReqIssuedNonEmptyQ++; sl@0: NKern::FMSignal(&iInstrumentationLock); sl@0: #endif sl@0: sl@0: TUint offset=aOffset<iDfcQ) sl@0: { sl@0: LOCM_FAULT(); // don't allow paging sl@0: OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_WRITE_EXIT, this, KErrNone ); sl@0: return KErrNone; // keep compiler happy sl@0: } sl@0: sl@0: sl@0: TLocDrvRequest& m=*(TLocDrvRequest*)(aReq); sl@0: sl@0: #ifdef __DEMAND_PAGING_BENCHMARKS__ sl@0: __e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageOutCount, (TUint) 1); sl@0: if (aBackground) sl@0: __e32_atomic_add_ord32(&iMediaPagingInfo.iDataPageOutBackgroundCount, (TUint) 1); sl@0: #endif sl@0: sl@0: // Write to the media and allow for retries in the unlikely event of an error. sl@0: const TInt KPageOutRetries = 5; sl@0: TInt retVal = KErrGeneral; sl@0: for (TInt i=0; retVal != KErrNone && i < KPageOutRetries; i++) sl@0: { sl@0: m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging | (aBackground ? TLocDrvRequest::EBackgroundPaging : 0); sl@0: sl@0: m.Id() = DLocalDrive::EWrite; sl@0: m.Drive() = TheDrives[iDataPagingDriveNumber]; sl@0: sl@0: m.RemoteThread()=NULL; sl@0: m.Pos()=offset; sl@0: m.Length()=Int64(size); sl@0: m.RemoteDes()=(TAny*)aBuffer; sl@0: m.RemoteDesOffset()=0; // pre-aligned sl@0: m.DriverFlags()=0; sl@0: __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("ReqId=%d, Pos=0x%lx, Len=0x%lx, remote Des 0x%x",m.Id(),m.Pos(),m.Length(),m.RemoteDes())); sl@0: OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_WRITE2, "reqId=%d; position=0x%lx; length=0x%lx; remote Des=0x%x", (TInt) m.Id(), (TUint) m.Pos(), (TUint) m.Length(), (TUint) m.RemoteDes()); sl@0: sl@0: __ASSERT_DEBUG(iPrimaryMedia->iBody, LOCM_FAULT()); sl@0: TInt mediaChanges = iPrimaryMedia->iBody->iMediaChanges; sl@0: sl@0: SendToMainQueueDfcAndBlock(&m); // queues request, sets and opens client thread, queues dfc and blocks thread until request is completed sl@0: sl@0: retVal = m.iValue; sl@0: sl@0: #ifdef __DEBUG_DEMAND_PAGING__ sl@0: if (retVal != KErrNone) sl@0: Kern::Printf("Pagout Failure %d, retry %d", retVal, i); sl@0: #endif sl@0: // reset retry count if there's ben a media change sl@0: if (retVal != KErrNone && mediaChanges != iPrimaryMedia->iBody->iMediaChanges) sl@0: i = 0; sl@0: } // for () sl@0: sl@0: #ifdef __CONCURRENT_PAGING_INSTRUMENTATION__ sl@0: NKern::FMWait(&iInstrumentationLock); sl@0: if (iServicingDataOut) sl@0: iServicingDataOut--; sl@0: NKern::FMSignal(&iInstrumentationLock); sl@0: #endif sl@0: sl@0: #ifdef __DEMAND_PAGING_BENCHMARKS__ sl@0: SPagingBenchmarkInfo& info = iDataOutBenchmarkData; sl@0: TUint32 bmEnd = NKern::FastCounter(); sl@0: ++info.iCount; sl@0: #if !defined(HIGHIGH_RES_TIMER) || defined(HIGH_RES_TIMER_COUNTS_UP) sl@0: TInt64 elapsed=bmEnd-bmStart; sl@0: #else sl@0: TInt64 elapsed=bmStart-bmEnd; sl@0: #endif sl@0: info.iTotalTime += elapsed; sl@0: if (elapsed > info.iMaxTime) sl@0: info.iMaxTime = elapsed; sl@0: if (elapsed < info.iMinTime) sl@0: info.iMinTime = elapsed; sl@0: #endif // __DEMAND_PAGING_BENCHMARKS__ sl@0: sl@0: OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_WRITE_EXIT2, this, retVal ); sl@0: return retVal; sl@0: } sl@0: sl@0: sl@0: TInt DMediaPagingDevice::DeleteNotify(TThreadMessage* aReq,TUint aOffset,TUint aSize) sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_DELETENOTIFY_ENTRY, this ); sl@0: if (iDeleteNotifyNotSupported) sl@0: { sl@0: OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT1, this, KErrNotSupported ); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: __ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT()); // that would lock up the system, thus better die now sl@0: __ASSERT_ALWAYS(aReq,LOCM_FAULT()); sl@0: __ASSERT_ALWAYS(DataPagingDfcQ(iPrimaryMedia),LOCM_FAULT()); sl@0: __ASSERT_CRITICAL sl@0: sl@0: TUint offset = aOffset<iDfcQ) sl@0: { sl@0: LOCM_FAULT(); // don't allow paging sl@0: OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT2, this, KErrNone ); sl@0: return KErrNone; // keep compiler happy sl@0: } sl@0: sl@0: TLocDrvRequest& m=*(TLocDrvRequest*)(aReq); sl@0: sl@0: sl@0: m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging; sl@0: m.Id() = DLocalDrive::EDeleteNotify; sl@0: m.Drive() = TheDrives[iDataPagingDriveNumber]; sl@0: sl@0: m.RemoteThread() = NULL; sl@0: m.Pos() = offset; sl@0: m.Length() = Int64(size); sl@0: m.RemoteDes() = NULL; sl@0: m.RemoteDesOffset() = 0; // pre-aligned sl@0: m.DriverFlags()=0; sl@0: __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("ReqId=%d, Pos=0x%lx, Len=0x%lx, remote Des 0x%x",m.Id(),m.Pos(),m.Length(),m.RemoteDes())); sl@0: OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_DELETENOTIFY2 , "reqId=%d; position=0x%lx; length=0x%lx; remote Des=0x%x", m.Id(), m.Pos(), m.Length(), (TUint) m.RemoteDes()); sl@0: sl@0: // send request aynchronously as we don't particularly care about the result sl@0: // and waiting would slow down the thread taking the page fault sl@0: iPrimaryMedia->RequestCountInc(); sl@0: sl@0: m.SendReceive(&iMainQ); // send request synchronously sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: iPrimaryMedia->RequestCountDec(); sl@0: #endif sl@0: sl@0: TInt retVal = m.iValue; sl@0: sl@0: if (retVal == KErrNotSupported) sl@0: iDeleteNotifyNotSupported = ETrue; sl@0: sl@0: OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT3, this, retVal ); sl@0: return retVal; sl@0: } sl@0: sl@0: sl@0: sl@0: EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* aSrc, TInt aSize, TInt anOffset) sl@0: { sl@0: OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITETOPAGEHANDLER_ENTRY, this ); sl@0: #ifdef BTRACE_PAGING_MEDIA sl@0: TMediaDevice medDev=Drive()->iMedia->iDevice; sl@0: TInt buf[3]; sl@0: buf[0]=(TUint32)RemoteDes(); sl@0: buf[1]=anOffset; sl@0: buf[2]=aSize; sl@0: BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaMedDrvWriteBack,medDev,this,buf,sizeof(buf)); sl@0: #endif sl@0: __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("TLocDrvRequest::WriteToPageHandler, memcpy((aTrg)%08x, (aSrc)%08x, (aLength)%08x)",(TUint32)RemoteDes()+anOffset,aSrc,aSize)); sl@0: (void)memcpy((TAny*)((TUint32)RemoteDes()+anOffset), aSrc, aSize); // maybe in later versions this could be something else sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITETOPAGEHANDLER_EXIT, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt TLocDrvRequest::ReadFromPageHandler(TAny* aDst, TInt aSize, TInt anOffset) sl@0: { sl@0: OstTraceFunctionEntry1( TLOCDRVREQUEST_READFROMPAGEHANDLER_ENTRY, this ); sl@0: #ifdef BTRACE_PAGING_MEDIA sl@0: TMediaDevice medDev=Drive()->iMedia->iDevice; sl@0: TInt buf[3]; sl@0: buf[0]=(TUint32)RemoteDes(); sl@0: buf[1]=anOffset; sl@0: buf[2]=aSize; sl@0: BTraceContextN(BTrace::EPagingMedia,BTrace::EPagingMediaMedDrvRead,medDev,this,buf,sizeof(buf)); sl@0: #endif sl@0: __KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("TLocDrvRequest::ReadFromPageHandler, memcpy((aDst)%08x, (aTrg)%08x, (aLength)%08x)",aDst,(TUint32)RemoteDes()+anOffset,aSize)); sl@0: (void)memcpy(aDst, (TAny*)((TUint32)RemoteDes()+anOffset), aSize); // maybe in later versions this could be something else sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_READFROMPAGEHANDLER_EXIT, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: _LIT(KLitFragmentationMutexName, "FRAGMENTATION_MUTEX"); sl@0: sl@0: TInt DFragmentationPagingLock::Construct(TUint aNumPages) sl@0: { sl@0: OstTraceFunctionEntryExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_ENTRY, this ); sl@0: TInt r=KErrNone; sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation Lock: creating Mutex")); sl@0: r=Kern::MutexCreate(this->iFragmentationMutex, KLitFragmentationMutexName, KMutexOrdNone); sl@0: if (r!=KErrNone) sl@0: { sl@0: OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT1, this, r ); sl@0: return r; sl@0: } sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation Lock: Mutex created OK")); sl@0: OstTraceDef0(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DFRAGMENTATIONPAGINGLOCK_CONSTRUCT1 , "Fragmentation Lock: Mutex created OK"); sl@0: sl@0: iFragmentGranularity = 0; sl@0: if (aNumPages == 0) sl@0: { sl@0: OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT2, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: // in CS sl@0: TInt pageSize=Kern::RoundToPageSize(1); sl@0: LockFragmentation(); sl@0: r=Alloc(pageSize*aNumPages); // alloc pages sl@0: UnlockFragmentation(); sl@0: sl@0: if(r==KErrNone) sl@0: { sl@0: iFragmentGranularity = pageSize * aNumPages; sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Fragmentation granularity set to 0x%x", iFragmentGranularity)); sl@0: OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DFRAGMENTATIONPAGINGLOCK_CONSTRUCT2, "Fragmentation granularity=0x%x", iFragmentGranularity); sl@0: } sl@0: sl@0: OstTraceFunctionExitExt( DFRAGMENTATIONPAGINGLOCK_CONSTRUCT_EXIT3, this, r ); sl@0: return r; sl@0: } sl@0: sl@0: void DFragmentationPagingLock::Cleanup() sl@0: { sl@0: OstTraceFunctionEntry1( DFRAGMENTATIONPAGINGLOCK_CLEANUP_ENTRY, this ); sl@0: // in CS sl@0: if (iFragmentationMutex) sl@0: { sl@0: LockFragmentation(); sl@0: Free(); // at last! sl@0: UnlockFragmentation(); sl@0: Kern::SafeClose((DObject*&)iFragmentationMutex,NULL); sl@0: } sl@0: OstTraceFunctionExit1( DFRAGMENTATIONPAGINGLOCK_CLEANUP_EXIT, this ); sl@0: } sl@0: sl@0: #else sl@0: #if !defined(__WINS__) sl@0: EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* , TInt , TInt) sl@0: { sl@0: return KErrNone; // stub for def file sl@0: } sl@0: #endif // __WINS__ sl@0: #endif //__DEMAND_PAGING__ sl@0: /******************************************** sl@0: * Media driver base class sl@0: ********************************************/ sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Constructor. sl@0: sl@0: This is called, typically, by a derived class constructor in its ctor list. sl@0: sl@0: @param aMediaId The value of the unique media ID assigned when the media sl@0: driver is registered. sl@0: sl@0: @see LocDrv::RegisterMediaDevice() sl@0: */ sl@0: EXPORT_C DMediaDriver::DMediaDriver(TInt aMediaId) sl@0: { sl@0: OstTraceFunctionEntryExt( DMEDIADRIVER_DMEDIADRIVER_ENTRY, this ); sl@0: sl@0: // iPhysicalDevice=NULL; sl@0: // iTotalSizeInBytes=0; sl@0: // iCurrentConsumption=0; sl@0: // iPrimaryMedia=NULL; sl@0: // iCritical=EFalse; sl@0: iPrimaryMedia=(DPrimaryMediaBase*)TheMedia[aMediaId]; sl@0: OstTraceFunctionExit1( DMEDIADRIVER_DMEDIADRIVER_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Destructor. sl@0: sl@0: Sets the device's current consumption to zero, and calls Close() on sl@0: the PDD factory object. sl@0: sl@0: @see DObject::Close() sl@0: */ sl@0: EXPORT_C DMediaDriver::~DMediaDriver() sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIADRIVER_DMEDIADRIVER_DESTRUCTOR_ENTRY, this ); sl@0: SetCurrentConsumption(0); sl@0: Kern::SafeClose((DObject*&)iPhysicalDevice,NULL); sl@0: OstTraceFunctionExit1( DMEDIADRIVER_DMEDIADRIVER_DESTRUCTOR_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Closes the media driver. sl@0: sl@0: This default implementation simply deletes this DMediaDriver object. sl@0: sl@0: Media drivers can provide their own implementation, which gives them sl@0: the opportunity to clean up resources before closure; for example, sl@0: cancelling a DFC. sl@0: Any replacement function must call this base class function as sl@0: the last instruction. sl@0: */ sl@0: EXPORT_C void DMediaDriver::Close() sl@0: { sl@0: delete this; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Sets the total size of the media device. sl@0: sl@0: The function must be called by the media driver's implementation of PartitionInfo(). sl@0: sl@0: @param aTotalSizeInBytes The total size of the media, in bytes. sl@0: @param aLocDrv This is not used by media drivers; the class sl@0: definition provides a default value. sl@0: sl@0: @see DMediaDriver::PartitionInfo() sl@0: */ sl@0: EXPORT_C void DMediaDriver::SetTotalSizeInBytes(Int64 aTotalSizeInBytes, TLocDrv* aLocDrv) sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIADRIVER_SETTOTALSIZEINBYTES_ENTRY, this ); sl@0: iTotalSizeInBytes=aTotalSizeInBytes; sl@0: if (aLocDrv) sl@0: aLocDrv->iPartitionLen=aTotalSizeInBytes; sl@0: OstTraceFunctionExit1( DMEDIADRIVER_SETTOTALSIZEINBYTES_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Gets the total size of the media. sl@0: sl@0: @return The total size of the media, in bytes. sl@0: sl@0: @see DMediaDriver::SetTotalSizeInBytes() sl@0: */ sl@0: EXPORT_C Int64 DMediaDriver::TotalSizeInBytes() sl@0: { sl@0: return iTotalSizeInBytes; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Flags the media driver as entering a critical part of its processing. sl@0: sl@0: In this context, critical means that the driver must be allowed to complete sl@0: its current activity. sl@0: For example, a request to power down the device must be deferred until sl@0: the driver exits the critical part. sl@0: sl@0: @return KErrNone, if the driver has been successfully flagged as being in sl@0: a critical part; otherwise, one of the other system-wide error codes. sl@0: sl@0: @see DMediaDriver::EndInCritical() sl@0: */ sl@0: EXPORT_C TInt DMediaDriver::InCritical() sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIADRIVER_INCRITICAL_ENTRY, this ); sl@0: if (!iCritical) sl@0: { sl@0: TInt r=iPrimaryMedia->InCritical(); sl@0: if (r!=KErrNone) sl@0: { sl@0: OstTraceFunctionExitExt( DMEDIADRIVER_INCRITICAL_EXIT, this, r ); sl@0: return r; sl@0: } sl@0: iCritical=ETrue; sl@0: } sl@0: OstTraceFunctionExitExt( DMEDIADRIVER_INCRITICAL_EXIT2, this, KErrNone ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Flags the media driver as leaving a critical part of its processing. sl@0: sl@0: @see DMediaDriver::InCritical() sl@0: */ sl@0: EXPORT_C void DMediaDriver::EndInCritical() sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIADRIVER_ENDINCRITICAL_ENTRY, this ); sl@0: if (iCritical) sl@0: { sl@0: iCritical=EFalse; sl@0: iPrimaryMedia->EndInCritical(); sl@0: } sl@0: OstTraceFunctionExit1( DMEDIADRIVER_ENDINCRITICAL_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: EXPORT_C void DMediaDriver::SetCurrentConsumption(TInt aValue) sl@0: { sl@0: OstTraceFunctionEntryExt( DMEDIADRIVER_SETCURRENTCONSUMPTION_ENTRY, this ); sl@0: TInt old = (TInt)__e32_atomic_swp_ord32(&iCurrentConsumption, aValue); sl@0: TInt delta = aValue - old; sl@0: iPrimaryMedia->DeltaCurrentConsumption(delta); sl@0: OstTraceFunctionExit1( DMEDIADRIVER_SETCURRENTCONSUMPTION_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Informs the media driver subsystem that an asynchronous request is complete. sl@0: sl@0: @param m The request that this call is completing. sl@0: @param aResult The return code for the asynchronous request. Typically, this sl@0: is KErrNone to report success, or one of the other system-wide sl@0: error codes to report failure or other problems. sl@0: */ sl@0: EXPORT_C void DMediaDriver::Complete(TLocDrvRequest& m, TInt aResult) sl@0: { sl@0: OstTraceExt2( TRACE_FLOW, DMEDIADRIVER_COMPLETE_ENTRY, "m=%x;aResult=%d", (TUint) &m, aResult ); sl@0: CHECK_RET(aResult); sl@0: #ifdef __DEMAND_PAGING__ sl@0: if (DMediaPagingDevice::PagingRequest(m)) sl@0: { sl@0: __ASSERT_ALWAYS(iPrimaryMedia && iPrimaryMedia->iPagingMedia && iPrimaryMedia->iBody->iPagingDevice,LOCM_FAULT()); sl@0: __ASSERT_ALWAYS( ((m.Flags() & TLocDrvRequest::ECodePaging) == 0) || (m.Drive()->iPagingDrv), LOCM_FAULT()); sl@0: DMediaPagingDevice* pagingdevice = iPrimaryMedia->iBody->iPagingDevice; sl@0: pagingdevice->CompleteRequest(&m, aResult); sl@0: } sl@0: else sl@0: #endif sl@0: iPrimaryMedia->CompleteRequest(m, aResult); sl@0: sl@0: if (&m == iPrimaryMedia->iCurrentReq) // Complete() called on request serviced synchronously sl@0: iPrimaryMedia->iCurrentReq = NULL; sl@0: sl@0: iPrimaryMedia->RunDeferred(); sl@0: OstTraceFunctionExit1( DMEDIADRIVER_COMPLETE_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Informs the media driver subsystem that the media driver is open sl@0: and has been initialised. sl@0: sl@0: This can be called from the PDD factory function Create(), if opening and sl@0: initialising the media driver is synchronous, otherwise it should be called by sl@0: the asynchronous media driver function that is responsible for opening and sl@0: initialising the driver. sl@0: sl@0: @param anError KErrNone if successful, otherwise one of the other system wide sl@0: error codes. sl@0: */ sl@0: EXPORT_C void DMediaDriver::OpenMediaDriverComplete(TInt anError) sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DMediaDriver::OpenMediaDriverComplete(%d) this %x iPrimaryMedia %x", anError, this, iPrimaryMedia)); sl@0: OstTraceDefExt3(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE, "anError %d this 0x%x iPrimaryMedia 0x%x", anError, (TUint) this, (TUint) iPrimaryMedia); sl@0: DPrimaryMediaBase* pM=iPrimaryMedia; sl@0: pM->iAsyncErrorCode=anError; sl@0: pM->iAsyncDfc.Enque(); sl@0: OstTraceFunctionExit1( DMEDIADRIVER_OPENMEDIADRIVERCOMPLETE_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Informs the media driver subsystem that the media driver has completed sl@0: the provision of partition information. sl@0: sl@0: The media driver provides partition information in its implementation sl@0: of PartitionInfo(). sl@0: sl@0: @param anError KErrNone if successful, otherwise one of the other system wide sl@0: error codes. sl@0: sl@0: @see DMediaDriver::PartitionInfo() sl@0: */ sl@0: EXPORT_C void DMediaDriver::PartitionInfoComplete(TInt anError) sl@0: { sl@0: OstTraceFunctionEntry1( DMEDIADRIVER_PARTITIONINFOCOMPLETE_ENTRY, this ); sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("DMediaDriver::PartitionInfoComplete(%d) anError %d this %x iPrimaryMedia %x", anError, this, iPrimaryMedia)); sl@0: OstTraceExt3( TRACE_INTERNALS, DMDEDIADRIVER_PARTITIONINFOCOMPLETE, "anError=%d; this=%x; iPrimaryMedia=%x", anError, (TUint) this, (TUint) iPrimaryMedia ); sl@0: DPrimaryMediaBase* pM=iPrimaryMedia; sl@0: pM->iAsyncErrorCode=anError; sl@0: pM->iAsyncDfc.Enque(); sl@0: OstTraceFunctionExit1( DMEDIADRIVER_PARTITIONINFOCOMPLETE_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: // Default implementation sl@0: EXPORT_C void DMediaDriver::Disconnect(DLocalDrive* aLocalDrive, TThreadMessage* aMsg) sl@0: { sl@0: OstTraceFunctionEntryExt( DMEDIADRIVER_DISCONNECT_ENTRY, this ); sl@0: // don't need to worry about DLocalDrive going away sl@0: aLocalDrive->Deque(); sl@0: sl@0: aMsg->Complete(KErrNone, EFalse); sl@0: OstTraceFunctionExit1( DMEDIADRIVER_DISCONNECT_EXIT, this ); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Registers a media driver with the Local Media Subsystem, and provides sl@0: information about the number of supported drives, partitions, sl@0: names and drive numbers. sl@0: sl@0: @param aDevice The unique Media ID for this device. sl@0: This can take one of the enumerated values defined sl@0: by the TMediaDevice enum. sl@0: @param aDriveCount Specifies the number of local drive objects to be assigned sl@0: to the media driver. Drives that support more than one sl@0: partition must specify a number greater than 1. sl@0: @param aDriveList A pointer to an array of TInt values, which define sl@0: the drive numbers that are to be allocated to each partition. sl@0: 0 signifies Drive C, 1 signifies drive D, etc. For example, sl@0: to allocate drive letters J and K, specify an array sl@0: containing the values [7,8]. sl@0: Note that the size of this array must be the same as the value sl@0: specified by aDriveCount. sl@0: @param aPrimaryMedia A pointer to the primary DPrimaryMedia object to be sl@0: associated with the media. This object is responsible for sl@0: the overall state of the media, i.e. powering up, reading sl@0: partition information etc. It also has overall control over sl@0: all partitions as represented by the additional (aNumMedia-1) sl@0: DMedia objects. sl@0: @param aNumMedia Specifies the total number of DMedia objects to be sl@0: associated with the media driver. This number includes the sl@0: primary DPrimaryMedia object referred to by aPrimaryMedia, sl@0: plus all of the DMedia objects that are created for each sl@0: additional drive, and which hold basic information about sl@0: partitions. sl@0: @param aName The name of the media driver, for example: PCCard sl@0: sl@0: @return KErrNone, if successful; sl@0: KErrInUse, if a drive is already in use; sl@0: KErrNoMemory, if there is insufficient memory; sl@0: or one of the other system-wide error codes. sl@0: */ sl@0: EXPORT_C TInt LocDrv::RegisterMediaDevice(TMediaDevice aDevice, TInt aDriveCount, const TInt* aDriveList, DPrimaryMediaBase* aPrimaryMedia, TInt aNumMedia, const TDesC& aName) sl@0: { sl@0: OstTraceFunctionEntry0( LOCDRV_REGISTERMEDIADEVICE_ENTRY ); sl@0: // Create TLocDrv / DMedia objects to handle a media device sl@0: __KTRACE_OPT(KBOOT,Kern::Printf("RegisterMediaDevice %lS dev=%1d #drives=%d 1st=%d PM=%08x #media=%d",&aName,aDevice,aDriveCount,*aDriveList,aPrimaryMedia,aNumMedia)); sl@0: OstTraceExt5( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE1, "aDevice=%d; aDriveCount=%d; aDriveList=%d; aPrimaryMedia=0x%08x; aNumMedia=%d", (TInt) aDevice, (TInt) aDriveCount, (TInt) *aDriveList, (TUint) aPrimaryMedia, (TInt) aNumMedia ); sl@0: sl@0: const TInt* p=aDriveList; sl@0: TInt i; sl@0: TInt r=0; sl@0: if (UsedMedia+aNumMedia>KMaxLocalDrives) sl@0: { sl@0: OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT1, "< KErrInUse"); sl@0: return KErrInUse; sl@0: } sl@0: for (i=0; iCreate(aDevice,i,lastMedia); sl@0: __KTRACE_OPT(KBOOT,Kern::Printf("Media %d Create() returns %d",i,r)); sl@0: OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE3, "Media=%d Create(); retval=%d", i, r ); sl@0: if (r!=KErrNone) sl@0: { sl@0: OstTrace1(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT5, "< retval=%d", r); sl@0: return r; sl@0: } sl@0: } sl@0: sl@0: __KTRACE_OPT(KBOOT,Kern::Printf("FirstMedia %d LastMedia %d",UsedMedia,lastMedia)); sl@0: OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE4, "FirstMedia=%d; LastMedia=%d", UsedMedia, lastMedia ); sl@0: UsedMedia+=aNumMedia; sl@0: p=aDriveList; sl@0: for (i=0; iiPrimaryMedia=aPrimaryMedia; sl@0: __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pL)); sl@0: OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE5, "Drive=%d; TLocDrv 0x%08x;", (TInt) drv, (TUint) pL ); sl@0: } sl@0: sl@0: OstTraceFunctionExit0( LOCDRV_REGISTERMEDIADEVICE_EXIT7 ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: A utility function that is used internally to register the specified sl@0: password store. sl@0: sl@0: The password store is used to save passwords for local media. sl@0: sl@0: @param aStore A pointer to the password store to be registered. sl@0: sl@0: @return KErrNone, if successful; sl@0: KErrAlreadyExists, if a password store has already been registered. sl@0: */ sl@0: EXPORT_C TInt LocDrv::RegisterPasswordStore(TPasswordStore* aStore) sl@0: { sl@0: OstTraceFunctionEntry0( LOCDRV_REGISTERPASSWORDSTORE_ENTRY ); sl@0: // Create TLocDrv / DMedia objects to handle a media device sl@0: __KTRACE_OPT(KBOOT,Kern::Printf("RegisterPasswordStore")); sl@0: sl@0: TInt r = KErrNone; sl@0: sl@0: if(ThePasswordStore == NULL) sl@0: ThePasswordStore = aStore; sl@0: else sl@0: r = KErrAlreadyExists; sl@0: OstTrace1(TRACE_INTERNALS, LOCDRV_REGISTERPASSWORDSTORE, "retval=%d", r); sl@0: OstTraceFunctionExit0( LOCDRV_REGISTERPASSWORDSTORE_EXIT ); sl@0: return r; sl@0: } sl@0: sl@0: /** sl@0: Returns a pointer to the registered password store. sl@0: sl@0: The password store is used to save passwords for local media. sl@0: sl@0: @return A pointer to the registered password store. sl@0: */ sl@0: EXPORT_C TPasswordStore* LocDrv::PasswordStore() sl@0: { sl@0: return ThePasswordStore; sl@0: } sl@0: sl@0: #ifdef __DEMAND_PAGING__ sl@0: /** sl@0: Registers a paging device with the Local Media Subsystem, and provides sl@0: information about drive numbers used in Code Paging. sl@0: sl@0: @param aPrimaryMedia A pointer to the primary DPrimaryMedia object associated sl@0: with the media. sl@0: @param aPagingDriveList A pointer to an array of TInt values, which define sl@0: the drive numbers used as Code backup in Code Paging, which sl@0: are the target of Page In requests. For NAND these will sl@0: will be usually associated with ROFS and/or User Data drives. sl@0: In ROM pagigng systems no drive is specified, it is assumed sl@0: a fixed media for which no non-primary media exists, will be sl@0: used. sl@0: @param aDriveCount Specifies the number of local drives associated with this sl@0: media device which can be used for code paging. sl@0: @param aPagingType Identifies the type of Paging this media device is capable sl@0: of servicing. sl@0: @param aReadShift Log2 of the read unit size. A read unit is the number of bytes sl@0: which the device can optimally read from the underlying media. sl@0: E.g. for small block NAND, a read unit would be equal to the sl@0: page size, 512 bytes, therefore iReadShift would be set to 9. sl@0: @param aNumPages The number of pages to alloc for each drive associated with this sl@0: media driver. The pages are used in request fragmentation. sl@0: sl@0: @return KErrNone, if successful; sl@0: KErrNotFound, if at least one of the drive numbers sl@0: specified has not yet been mapped. sl@0: KErrArgument, if the passed in an invalid argument. sl@0: KErrNotSupported, if at least one of the drive numbers sl@0: specifed is not associated with this Primary Media. sl@0: KErrNoMemory, if there is insufficient memory; sl@0: or one of the other system-wide error codes. sl@0: */ sl@0: EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* aPrimaryMedia, const TInt* aPagingDriveList, TInt aDriveCount, TUint aPagingType, TInt aReadShift, TUint aNumPages) sl@0: { sl@0: OstTraceFunctionEntry0( LOCDRV_REGISTERPAGINGDEVICE_ENTRY ); sl@0: sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf(">RegisterPagingDevice: paging type=%d PM=0x%x read shift=%d",aPagingType,aPrimaryMedia,aReadShift)); sl@0: OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE1, "aPagingType=%d; aPrimaryMedia=0x%x; aReadShift=%d", (TInt) aPagingType, (TUint) aPrimaryMedia, (TInt) aReadShift); sl@0: sl@0: TInt i; sl@0: sl@0: if(!aPagingType || (aPagingType&~(DPagingDevice::ERom | DPagingDevice::ECode | DPagingDevice::EData))) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Unsupported paging type, exiting")); sl@0: OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT1, "< Unsupported paging type; KErrArgument"); sl@0: return KErrArgument; sl@0: } sl@0: sl@0: sl@0: sl@0: for(i=0; iiType&DPagingDevice::ERom) && (aPagingType & DPagingDevice::ERom)) sl@0: { sl@0: aPagingType&=~DPagingDevice::ERom; // already have a ROM paging device sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has ROM pager on locdrv no %d",i)); sl@0: } sl@0: if ((ThePagingDevices[i]->iType&DPagingDevice::EData) && (aPagingType & DPagingDevice::EData)) sl@0: { sl@0: aPagingType&=~DPagingDevice::EData; // already have a Data paging device sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has Data pager on locdrv no %d",i)); sl@0: } sl@0: } sl@0: sl@0: sl@0: if (aPagingType == 0) sl@0: { sl@0: // there's already a ROM or Data paging device & this doesn't support code paging so quietly exit without further addo sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Nothing left to register on locdrv no %d, exiting",i)); sl@0: OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT2, "< Nothing left to register on locdrv no %d; KErrNone",i); sl@0: return KErrNone; sl@0: } sl@0: sl@0: const TInt* p=aPagingDriveList; sl@0: if(aPagingType&DPagingDevice::ECode) // supports code paging, do argument check sl@0: { sl@0: if(!aDriveCount || (aDriveCount>=KMaxLocalDrives)) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive count: %d", aDriveCount)); sl@0: OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT3, "< Invalid code paging drive count=%d; KErrArgument", aDriveCount); sl@0: return KErrArgument; sl@0: } sl@0: sl@0: TInt drvCount=0; sl@0: for(i=0; iiPrimaryMedia==aPrimaryMedia) sl@0: drvCount++; sl@0: if(aDriveCount>drvCount) // can't exceed number of drives registered by this device sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive count=%d; total=%d", aDriveCount, drvCount)); sl@0: OstTraceExt2(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT4, "< Invalid code paging drive count=%d; total=%d; KErrArgument", aDriveCount, drvCount); sl@0: return KErrArgument; sl@0: } sl@0: sl@0: for (i=0; i=KMaxLocalDrives) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Invalid code paging drive number: %d", drv)); sl@0: OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT5, "< Invalid code paging drive number=%d; KErrArgument", drv); sl@0: return KErrArgument; sl@0: } sl@0: TLocDrv* pD=TheDrives[drv]; sl@0: if (!pD) sl@0: { sl@0: OstTrace0(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT6, "< KErrNotFound"); sl@0: return KErrNotFound; sl@0: } sl@0: if (pD->iPrimaryMedia!=aPrimaryMedia) sl@0: { sl@0: OstTrace0(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT7, "< KErrNotSupported"); sl@0: return KErrNotSupported; sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: TInt firstLocalDriveNumber = KErrNotFound; sl@0: TInt romPagingDriveNumber = KErrNotFound; sl@0: sl@0: TInt dataPagingDriveNumber = KErrNotFound; sl@0: TInt swapSize = 0; sl@0: sl@0: // find the local drive assocated with the primary media sl@0: for (i=0; iiPrimaryMedia == aPrimaryMedia) sl@0: { sl@0: firstLocalDriveNumber = i; sl@0: break; sl@0: } sl@0: } sl@0: __ASSERT_ALWAYS(i < KMaxLocalDrives, LOCM_FAULT()); sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("DMediaPagingDevice(), firstLocalDriveNumber %d", firstLocalDriveNumber)); sl@0: OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE3, "firstLocalDriveNumber=%d", firstLocalDriveNumber ); sl@0: sl@0: // Send an ECaps message to wake up the media driver & ensure all partitions are sl@0: // reported, then search for paged-data or paged-ROM partitions sl@0: if ((aPagingType & DPagingDevice::EData) || sl@0: (aPagingType & DPagingDevice::ERom && aPrimaryMedia->iDfcQ && aPrimaryMedia->iMsgQ.iReady)) sl@0: { sl@0: // the message queue must have been started already (by the media driver calling iMsgQ.Receive()) sl@0: // otherwise we can't send the DLocalDrive::EQueryDevice request sl@0: if (aPrimaryMedia->iDfcQ && !aPrimaryMedia->iMsgQ.iReady) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Message queue not started")); sl@0: OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT8, "< RegisterPagingDevice: Message queue not started; KErrNotReady"); sl@0: return KErrNotReady; sl@0: } sl@0: sl@0: sl@0: TLocDrvRequest m; sl@0: memclr(&m, sizeof(m)); sl@0: sl@0: sl@0: // Get the Caps from the device. NB for MMC/SD we may need to retry as some PSLs start up sl@0: // in "door open" or "media not present" state which can result in the cancellation of requests sl@0: TInt i; sl@0: const TInt KRetries = 5; sl@0: TInt r = KErrNotReady; sl@0: for (i=0; r == KErrNotReady && i < KRetries; i++) sl@0: { sl@0: TBuf8 capsBuf; sl@0: capsBuf.SetMax(); sl@0: capsBuf.FillZ(); sl@0: m.Drive() = TheDrives[firstLocalDriveNumber]; sl@0: m.Id() = DLocalDrive::ECaps; sl@0: m.RemoteDes() = (TAny*)capsBuf.Ptr(); // overload this sl@0: m.Length() = KMaxLocalDriveCapsLength; // for pinning sl@0: r = aPrimaryMedia->Request(m); sl@0: sl@0: //Kern::Printf("EQueryPageDeviceInfo: i %d: r %d ", i, r); sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Paging device ECaps: i %d: r %d ", i, r)); sl@0: OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE4, "Paging device ECaps: i %d retval=%d", i, r); sl@0: } sl@0: sl@0: if (r != KErrNone) sl@0: { sl@0: OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< retval=%d",r); sl@0: return r; sl@0: } sl@0: sl@0: TLocDrv* drive; sl@0: for (i=0; iiPrimaryMedia == aPrimaryMedia) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("RegisterPagingDevice: local drive %d, partition type %x size %x", i, drive->iPartitionType, I64LOW(drive->iPartitionLen))); sl@0: // ROM partition ? sl@0: if ((romPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypeROM)) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found ROM partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen))); sl@0: OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE5, "Found ROM partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen)); sl@0: romPagingDriveNumber = i; sl@0: } sl@0: // swap partition ? sl@0: else if ((dataPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypePagedData)) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found swap partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen))); sl@0: OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE6, "Found SWAP partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen) ); sl@0: dataPagingDriveNumber = i; sl@0: swapSize = drive->iPartitionLen >> aReadShift; sl@0: } sl@0: } sl@0: } sl@0: sl@0: if (swapSize == 0) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Disabling data paging")); sl@0: OstTraceDef0(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE7, "Disabling data paging"); sl@0: aPagingType &= ~DPagingDevice::EData; sl@0: } sl@0: sl@0: } sl@0: sl@0: sl@0: // create and set up a DPagingDevice to allow PageIn request servicing sl@0: DMediaPagingDevice* pagingDevice = new DMediaPagingDevice(aPrimaryMedia); sl@0: if(!pagingDevice) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create paging device")); sl@0: OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT_EXIT10, "< RegisterPagingDevice: could not create paging device; KErrNoMemory"); sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: pagingDevice->iType = aPagingType; sl@0: pagingDevice->iReadUnitShift = aReadShift; sl@0: sl@0: pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber; sl@0: pagingDevice->iRomPagingDriveNumber = romPagingDriveNumber; sl@0: sl@0: pagingDevice->iDataPagingDriveNumber = dataPagingDriveNumber; sl@0: pagingDevice->iSwapSize = swapSize; sl@0: sl@0: #ifdef __DEBUG_DEMAND_PAGING__ sl@0: Kern::Printf("PagingDevice :"); sl@0: Kern::Printf("iType 0x%x\n", pagingDevice->iType); sl@0: Kern::Printf("iReadUnitShift 0x%x\n", pagingDevice->iReadUnitShift); sl@0: Kern::Printf("iFirstLocalDriveNumber 0x%x\n", pagingDevice->iFirstLocalDriveNumber); sl@0: Kern::Printf("iRomPagingDriveNumber 0x%x\n", pagingDevice->iRomPagingDriveNumber); sl@0: Kern::Printf("iDataPagingDriveNumber 0x%x\n", pagingDevice->iDataPagingDriveNumber); sl@0: Kern::Printf("iSwapSize 0x%x\n", pagingDevice->iSwapSize); sl@0: #endif sl@0: sl@0: sl@0: // This table is indexed by DPagingDevice::TType sl@0: const char* DeviceName[] = sl@0: { sl@0: "Error", sl@0: "RomPagingDevice", sl@0: "CodePagingDevice", sl@0: "RomAndCodePagingDevice", sl@0: "DataPagingDevice", sl@0: "RomAndDataPagingDevice", sl@0: "CodeAndDataPagingDevice", sl@0: "RomAndCodeAndDataPagingDevice" sl@0: }; sl@0: sl@0: sl@0: if(aPagingType & DPagingDevice::ECode) sl@0: { sl@0: for (i=0; iiDrivesSupported|=(0x1<iName = DeviceName[aPagingType]; sl@0: sl@0: if (ThePinObjectAllocator == NULL) sl@0: ThePinObjectAllocator = new DPinObjectAllocator(); sl@0: if(!ThePinObjectAllocator) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator")); sl@0: OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory"); sl@0: return KErrNoMemory; sl@0: } sl@0: TInt r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages); sl@0: if (r != KErrNone) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not construct ThePinObjectAllocator")); sl@0: OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT12, "< RegisterPagingDevice: could not construct ThePinObjectAllocator; retval=%d",r); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: // Register our DPagingDevice with the Kernel sl@0: r=Kern::InstallPagingDevice(pagingDevice); sl@0: sl@0: #ifdef __DEBUG_DEMAND_PAGING__ sl@0: Kern::Printf("Kern::InstallPagingDevice() r %d", r); sl@0: #endif sl@0: sl@0: if (r!=KErrNone) sl@0: { sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not install paging device")); sl@0: OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT13, "< RegisterPagingDevice: could not install paging device; retval=%d", r); sl@0: delete pagingDevice; sl@0: return r; sl@0: } sl@0: sl@0: // all hunky dory, save paging device and mark our media as pageable sl@0: ThePagingDevices[aPrimaryMedia->iMediaId] = pagingDevice; // association created between PrimaryMedia and PagingDevice via iMediaId sl@0: aPrimaryMedia->iPagingMedia = 1; sl@0: sl@0: // mark our drives as pageable sl@0: p=aPagingDriveList; sl@0: if (aPagingType&DPagingDevice::ECode) sl@0: { sl@0: for (i=0; iiPagingDrv=1; sl@0: } sl@0: } sl@0: sl@0: // Flags to indicate that a paging device is registered and pinning of user requests may be required sl@0: aPrimaryMedia->iPagingMedia = 1; sl@0: sl@0: // point the primary media to the paging device sl@0: aPrimaryMedia->iBody->iPagingDevice = pagingDevice; sl@0: sl@0: if (aPagingType & DPagingDevice::ERom) sl@0: { sl@0: aPrimaryMedia->iRomPagingMedia = 1; sl@0: TheRomPagingMedia = aPrimaryMedia; sl@0: } sl@0: sl@0: // Is data paging enabled in this ROM ? sl@0: TInt memModelAttributes = Kern::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL); sl@0: TBool dataPagingSupported = memModelAttributes & EMemModelAttrDataPaging; sl@0: #ifdef __DEBUG_DEMAND_PAGING__ sl@0: Kern::Printf("memModelAttributes %08X", memModelAttributes); sl@0: Kern::Printf("DataPagingSupported %d", dataPagingSupported); sl@0: #endif sl@0: if (!dataPagingSupported) sl@0: { sl@0: #ifdef __DEBUG_DEMAND_PAGING__ sl@0: if (aPagingType & DPagingDevice::EData) sl@0: { sl@0: Kern::Printf("Disabling data paging, not supported in this ROM"); sl@0: } sl@0: #endif sl@0: aPagingType&= ~DPagingDevice::EData; sl@0: } sl@0: sl@0: sl@0: if (aPagingType & DPagingDevice::EData) sl@0: { sl@0: DataPagingDeviceRegistered = ETrue; sl@0: aPrimaryMedia->iDataPagingMedia = 1; sl@0: TheDataPagingMedia = aPrimaryMedia; sl@0: } sl@0: sl@0: __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("< RegisterPagingDevice")); sl@0: OstTraceFunctionExit0( LOCDRV_REGISTERPAGINGDEVICE_EXIT14 ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: #else //__DEMAND_PAGING__ sl@0: sl@0: #if !defined(__WINS__) sl@0: EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* , const TInt* , TInt , TUint , TInt , TUint ) sl@0: { sl@0: return KErrNotSupported; sl@0: } // stub for def file sl@0: #endif // __WINS__ sl@0: sl@0: #endif //__DEMAND_PAGING__ sl@0: sl@0: sl@0: /** sl@0: Registers a media device with physical memory addressing capabilities with the sl@0: Local Media Subsystem. sl@0: sl@0: @param aPrimaryMedia A pointer to the primary DPrimaryMedia object associated sl@0: with the media device. sl@0: @param aMediaBlockSize The Minimum transfer size (bytes) for the media device. sl@0: @param aDmaMaxAddressable The Maximum Addressing Range for the media device's DMA controller, 0 if None. sl@0: @param aDmaAlignment The required memory alignment for the media device's DMA controller. sl@0: sl@0: @return KErrNone, Always; sl@0: */ sl@0: EXPORT_C TInt LocDrv::RegisterDmaDevice(DPrimaryMediaBase* aPrimaryMedia, sl@0: TInt aMediaBlockSize, // Minimum transfer size (bytes) for the media sl@0: TInt aDmaMaxAddressable, // Max Addressing Range for DMA controller, 0 if None. sl@0: TInt aDmaAlignment) // DMA Alignment e.g. word alignment required = 2 sl@0: { sl@0: OstTraceFunctionEntry0( LOCDRV_REGISTERDMADEVICE_ENTRY ); sl@0: sl@0: __KTRACE_OPT(KBOOT ,Kern::Printf("RegisterPhysicalAddrDevice: PM=0x%x BS=%d MaxAddr=%d DMA=%d", sl@0: aPrimaryMedia, aMediaBlockSize, aDmaMaxAddressable, aDmaAlignment)); sl@0: OstTraceExt4( TRACE_INTERNALS, LOCDRV_REGISTERDMADEVICE, "aPrimaryMedia=0x%x; aMediaBlockSize=%d; aDmaMaxAddressable=%d; aDmaAlignment=%d", (TUint) aPrimaryMedia, (TInt) aMediaBlockSize, (TInt) aDmaMaxAddressable, (TInt) aDmaAlignment ); sl@0: sl@0: for (TInt i=0; iiPrimaryMedia == aPrimaryMedia && pL->iDmaHelper == NULL) sl@0: { sl@0: pL->iDmaHelper = new DDmaHelper; sl@0: __ASSERT_ALWAYS(pL != NULL, LOCM_FAULT()); sl@0: sl@0: // if no limit stated on addressing range use 1MB sl@0: TInt MaxAddress = aDmaMaxAddressable ? (1024*1024) : aDmaMaxAddressable; sl@0: sl@0: TInt r = pL->iDmaHelper->Construct(MaxAddress, aMediaBlockSize, aDmaAlignment); sl@0: __ASSERT_ALWAYS(r == KErrNone, LOCM_FAULT()); sl@0: } sl@0: } sl@0: sl@0: OstTraceFunctionExit0( LOCDRV_REGISTERDMADEVICE_EXIT ); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void GetDriveInfo(TDriveInfoV1& info) sl@0: { sl@0: OstTraceFunctionEntry1( GETDRIVEINFO_ENTRY, ( TUint )&( info ) ); sl@0: TInt i; sl@0: TInt drives=0; sl@0: TUint32 sock_mask=0; sl@0: TInt sockets=0; sl@0: sl@0: info.iRegisteredDriveBitmask = 0; sl@0: sl@0: for (i=0; iiPrimaryMedia; sl@0: if (pM->IsRemovableDevice(sockNum)) sl@0: { sl@0: if (!(sock_mask & (1<iDevice, DriveNames[i])); sl@0: OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO1, "Socket=%d; device=%d", sockNum, (TUint) pM->iDevice ); sl@0: if ( (sockNum + 1) > sockets ) sl@0: sockets = sockNum + 1; sl@0: } sl@0: sock_mask |= (1<iDevice,DriveNames[i])); sl@0: OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO2, "Drive=%d; device=%d", i, (TUint) pM->iDevice ); sl@0: sl@0: info.iRegisteredDriveBitmask |= (0x01 << i); sl@0: } sl@0: } sl@0: info.iTotalSupportedDrives=drives; sl@0: info.iTotalSockets=sockets; sl@0: info.iRuggedFileSystem=ETrue; sl@0: __KTRACE_OPT(KLOCDRV,Kern::Printf("Total drives=%d, sockets=%d",drives,sockets)); sl@0: OstTraceExt2( TRACE_INTERNALS, GETDRIVEINFO3, "Total drives=%d; sockets=%d", drives, sockets ); sl@0: OstTraceFunctionExit0( GETDRIVEINFO_EXIT ); sl@0: } sl@0: sl@0: #if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__) sl@0: void ResetConcurrencyStats(DMediaPagingDevice* aDevice, TMediaPagingStats aStats) sl@0: { sl@0: NKern::FMWait(&aDevice->iInstrumentationLock); sl@0: switch(aStats) sl@0: { sl@0: case EMediaPagingStatsRom: sl@0: aDevice->iServicingROM=0; sl@0: memclr(&aDevice->iROMStats,sizeof(SMediaROMPagingConcurrencyInfo)); sl@0: break; sl@0: case EMediaPagingStatsCode: sl@0: aDevice->iServicingCode=0; sl@0: memclr(&aDevice->iCodeStats,sizeof(SMediaCodePagingConcurrencyInfo)); sl@0: break; sl@0: case EMediaPagingStatsDataIn: sl@0: aDevice->iServicingDataIn=0; sl@0: memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo)); sl@0: break; sl@0: case EMediaPagingStatsDataOut: sl@0: aDevice->iServicingDataOut=0; sl@0: memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo)); sl@0: break; sl@0: case EMediaPagingStatsAll: sl@0: aDevice->iServicingROM=0; sl@0: aDevice->iServicingCode=0; sl@0: aDevice->iServicingDataIn=0; sl@0: aDevice->iServicingDataOut=0; sl@0: memclr(&aDevice->iROMStats,sizeof(SMediaROMPagingConcurrencyInfo)); sl@0: memclr(&aDevice->iCodeStats,sizeof(SMediaCodePagingConcurrencyInfo)); sl@0: memclr(&aDevice->iDataStats,sizeof(SMediaDataPagingConcurrencyInfo)); sl@0: break; sl@0: } sl@0: NKern::FMSignal(&aDevice->iInstrumentationLock); sl@0: } sl@0: #endif sl@0: #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__) sl@0: void ResetBenchmarkStats(DMediaPagingDevice* aDevice, TMediaPagingStats aStats) sl@0: { sl@0: NKern::FMWait(&aDevice->iInstrumentationLock); sl@0: switch(aStats) sl@0: { sl@0: case EMediaPagingStatsRom: sl@0: aDevice->iROMBenchmarkData.iCount = 0; sl@0: aDevice->iROMBenchmarkData.iTotalTime = 0; sl@0: aDevice->iROMBenchmarkData.iMaxTime = 0; sl@0: aDevice->iROMBenchmarkData.iMinTime = KMaxTInt; sl@0: break; sl@0: case EMediaPagingStatsCode: sl@0: aDevice->iCodeBenchmarkData.iCount = 0; sl@0: aDevice->iCodeBenchmarkData.iTotalTime = 0; sl@0: aDevice->iCodeBenchmarkData.iMaxTime = 0; sl@0: aDevice->iCodeBenchmarkData.iMinTime = KMaxTInt; sl@0: break; sl@0: case EMediaPagingStatsDataIn: sl@0: aDevice->iDataInBenchmarkData.iCount = 0; sl@0: aDevice->iDataInBenchmarkData.iTotalTime = 0; sl@0: aDevice->iDataInBenchmarkData.iMaxTime = 0; sl@0: aDevice->iDataInBenchmarkData.iMinTime = KMaxTInt; sl@0: break; sl@0: case EMediaPagingStatsDataOut: sl@0: aDevice->iDataOutBenchmarkData.iCount = 0; sl@0: aDevice->iDataOutBenchmarkData.iTotalTime = 0; sl@0: aDevice->iDataOutBenchmarkData.iMaxTime = 0; sl@0: aDevice->iDataOutBenchmarkData.iMinTime = KMaxTInt; sl@0: break; sl@0: case EMediaPagingStatsAll: sl@0: aDevice->iDataInBenchmarkData.iCount = 0; sl@0: aDevice->iDataInBenchmarkData.iTotalTime = 0; sl@0: aDevice->iDataInBenchmarkData.iMaxTime = 0; sl@0: aDevice->iDataInBenchmarkData.iMinTime = KMaxTInt; sl@0: sl@0: aDevice->iDataOutBenchmarkData.iCount = 0; sl@0: aDevice->iDataOutBenchmarkData.iTotalTime = 0; sl@0: aDevice->iDataOutBenchmarkData.iMaxTime = 0; sl@0: aDevice->iDataOutBenchmarkData.iMinTime = KMaxTInt; sl@0: sl@0: aDevice->iROMBenchmarkData.iCount = 0; sl@0: aDevice->iROMBenchmarkData.iTotalTime = 0; sl@0: aDevice->iROMBenchmarkData.iMaxTime = 0; sl@0: aDevice->iROMBenchmarkData.iMinTime = KMaxTInt; sl@0: sl@0: aDevice->iCodeBenchmarkData.iCount = 0; sl@0: aDevice->iCodeBenchmarkData.iTotalTime = 0; sl@0: aDevice->iCodeBenchmarkData.iMaxTime = 0; sl@0: aDevice->iCodeBenchmarkData.iMinTime = KMaxTInt; sl@0: break; sl@0: } sl@0: NKern::FMSignal(&aDevice->iInstrumentationLock); sl@0: } sl@0: #endif sl@0: sl@0: TInt MediaHalFunction(TAny*, TInt aFunction, TAny* a1, TAny* a2) sl@0: { sl@0: TInt r=KErrNotSupported; sl@0: switch (aFunction) sl@0: { sl@0: case EMediaHalDriveInfo: sl@0: { sl@0: (void) a2; sl@0: TDriveInfoV1Buf infoBuf; sl@0: TDriveInfoV1& info=infoBuf(); sl@0: GetDriveInfo(info); sl@0: Kern::InfoCopy(*(TDes8*)a1,infoBuf); sl@0: r=KErrNone; sl@0: break; sl@0: } sl@0: #if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__) sl@0: case EMediaHalGetROMConcurrencyInfo: sl@0: { sl@0: TInt drvNo=(TInt)a1; sl@0: TLocDrv* drv=TheDrives[drvNo]; sl@0: if(!drv) sl@0: break; sl@0: DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice; sl@0: if(!device) sl@0: break; sl@0: NKern::FMWait(&device->iInstrumentationLock); sl@0: SMediaROMPagingConcurrencyInfo info=device->iROMStats; sl@0: NKern::FMSignal(&device->iInstrumentationLock); sl@0: kumemput32(a2,&info,sizeof(info)); sl@0: r=KErrNone; sl@0: break; sl@0: } sl@0: case EMediaHalGetCodeConcurrencyInfo: sl@0: { sl@0: TInt drvNo=(TInt)a1; sl@0: TLocDrv* drv=TheDrives[drvNo]; sl@0: if(!drv) sl@0: break; sl@0: DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; sl@0: if(!device) sl@0: break; sl@0: NKern::FMWait(&device->iInstrumentationLock); sl@0: SMediaCodePagingConcurrencyInfo info=device->iCodeStats; sl@0: NKern::FMSignal(&device->iInstrumentationLock); sl@0: kumemput32(a2,&info,sizeof(info)); sl@0: r=KErrNone; sl@0: break; sl@0: } sl@0: case EMediaHalGetDataConcurrencyInfo: sl@0: { sl@0: TInt drvNo=(TInt)a1; sl@0: TLocDrv* drv=TheDrives[drvNo]; sl@0: if(!drv) sl@0: break; sl@0: DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice; sl@0: if(!device) sl@0: break; sl@0: NKern::FMWait(&device->iInstrumentationLock); sl@0: SMediaDataPagingConcurrencyInfo info=device->iDataStats; sl@0: NKern::FMSignal(&device->iInstrumentationLock); sl@0: kumemput32(a2,&info,sizeof(info)); sl@0: r=KErrNone; sl@0: break; sl@0: } sl@0: case EMediaHalResetConcurrencyInfo: sl@0: { sl@0: TInt drvNo=(TInt)a1; sl@0: TLocDrv* drv=TheDrives[drvNo]; sl@0: if(!drv) sl@0: break; sl@0: DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; sl@0: if(!device) sl@0: break; sl@0: TUint index=(TInt)a2; sl@0: if(index>EMediaPagingStatsCode) sl@0: break; sl@0: ResetConcurrencyStats(device, (TMediaPagingStats)index); sl@0: r=KErrNone; sl@0: break; sl@0: } sl@0: #endif sl@0: #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__) sl@0: case EMediaHalGetROMPagingBenchmark: sl@0: { sl@0: TInt drvNo=(TInt)a1; sl@0: TLocDrv* drv=TheDrives[drvNo]; sl@0: if(!drv) sl@0: break; sl@0: DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; sl@0: if(!device) sl@0: break; sl@0: NKern::FMWait(&device->iInstrumentationLock); sl@0: SPagingBenchmarkInfo info = device->iROMBenchmarkData; sl@0: NKern::FMSignal(&device->iInstrumentationLock); sl@0: kumemput32(a2,&info,sizeof(info)); sl@0: r=KErrNone; sl@0: break; sl@0: } sl@0: case EMediaHalGetCodePagingBenchmark: sl@0: { sl@0: TInt drvNo=(TInt)a1; sl@0: TLocDrv* drv=TheDrives[drvNo]; sl@0: if(!drv) sl@0: break; sl@0: DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; sl@0: if(!device) sl@0: break; sl@0: NKern::FMWait(&device->iInstrumentationLock); sl@0: SPagingBenchmarkInfo info = device->iCodeBenchmarkData; sl@0: NKern::FMSignal(&device->iInstrumentationLock); sl@0: kumemput32(a2,&info,sizeof(info)); sl@0: r=KErrNone; sl@0: break; sl@0: } sl@0: case EMediaHalGetDataInPagingBenchmark: sl@0: { sl@0: TInt drvNo=(TInt)a1; sl@0: TLocDrv* drv=TheDrives[drvNo]; sl@0: if(!drv) sl@0: break; sl@0: DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; sl@0: if(!device) sl@0: break; sl@0: NKern::FMWait(&device->iInstrumentationLock); sl@0: SPagingBenchmarkInfo info = device->iDataInBenchmarkData; sl@0: NKern::FMSignal(&device->iInstrumentationLock); sl@0: kumemput32(a2,&info,sizeof(info)); sl@0: r=KErrNone; sl@0: break; sl@0: } sl@0: case EMediaHalGetDataOutPagingBenchmark: sl@0: { sl@0: TInt drvNo=(TInt)a1; sl@0: TLocDrv* drv=TheDrives[drvNo]; sl@0: if(!drv) sl@0: break; sl@0: DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; sl@0: if(!device) sl@0: break; sl@0: NKern::FMWait(&device->iInstrumentationLock); sl@0: SPagingBenchmarkInfo info = device->iDataOutBenchmarkData; sl@0: NKern::FMSignal(&device->iInstrumentationLock); sl@0: kumemput32(a2,&info,sizeof(info)); sl@0: r=KErrNone; sl@0: break; sl@0: } sl@0: case EMediaHalResetPagingBenchmark: sl@0: { sl@0: TInt drvNo=(TInt)a1; sl@0: TLocDrv* drv=TheDrives[drvNo]; sl@0: if(!drv) sl@0: break; sl@0: DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; sl@0: if(!device) sl@0: break; sl@0: TUint index=(TInt)a2; sl@0: if(index>EMediaPagingStatsCode) sl@0: break; sl@0: ResetBenchmarkStats(device, (TMediaPagingStats)index); sl@0: r=KErrNone; sl@0: break; sl@0: } sl@0: case EMediaHalGetPagingInfo: sl@0: { sl@0: TInt drvNo=(TInt)a1; sl@0: TLocDrv* drv=TheDrives[drvNo]; sl@0: if(!drv) sl@0: break; sl@0: DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; sl@0: if(!device) sl@0: break; sl@0: NKern::FMWait(&device->iInstrumentationLock); sl@0: SMediaPagingInfo info = device->iMediaPagingInfo; sl@0: NKern::FMSignal(&device->iInstrumentationLock); sl@0: kumemput32(a2,&info,sizeof(info)); sl@0: r=KErrNone; sl@0: break; sl@0: } sl@0: #endif sl@0: default: sl@0: break; sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: sl@0: /****************************************************************************** sl@0: Partition table scanner sl@0: ******************************************************************************/ sl@0: sl@0: #ifdef _DEBUG sl@0: #define DMEMDUMP(base,size) DbgMemDump((TLinAddr)base,size) sl@0: void DbgMemDump(TLinAddr aBase, TInt aSize) sl@0: { sl@0: TInt off; sl@0: const TUint8* p=(const TUint8*)aBase; sl@0: NKern::Lock(); sl@0: for (off=0; off0, LOCM_FAULT()); sl@0: memclr(this, sizeof(TPartitionTableScanner)); sl@0: iLBA = -1; sl@0: iSectorBuffer = aSectorBuffer; sl@0: iFirstEntry = aEntry; sl@0: iNextEntry = aEntry; sl@0: iLimit = aEntry + aMaxPartitions; sl@0: iMediaSize = aMediaSize; sl@0: } sl@0: sl@0: EXPORT_C TInt TPartitionTableScanner::NumberOfPartitionsFound() const sl@0: { sl@0: TInt n = iNextEntry - iFirstEntry; sl@0: __KTRACE_OPT(KLOCDRV, Kern::Printf("TPartitionTableScanner N=%d", n)); sl@0: OstTrace1( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NUMBERPARTITIONS, "Number of partitions=%d", n ); sl@0: return n; sl@0: } sl@0: sl@0: TPartitionTableScanner::SPart::SPart(const TUint8* a) sl@0: { sl@0: iBootInd = a[0]; sl@0: iType = a[4]; sl@0: iRSS = a[8]|(a[9]<<8)|(a[10]<<16)|(a[11]<<24); sl@0: iSectors = a[12]|(a[13]<<8)|(a[14]<<16)|(a[15]<<24); sl@0: __KTRACE_OPT(KLOCDRV, Kern::Printf("SPart: BI=%02x TYPE=%02x RSS=%08x SIZE=%08x", iBootInd, iType, iRSS, iSectors)); sl@0: OstTraceExt4(TRACE_INTERNALS, TPARTITIONTABLESCANNER_SPART_SPART, "SPart: iBootInd=%02x; iType=%02x; iRSS=%08x; iSectors=%08x", (TUint) iBootInd, (TUint) iType, (TUint) iRSS, (TUint) iSectors); sl@0: } sl@0: sl@0: TInt TPartitionTableScanner::MakeEntry(const SPart& a) sl@0: { sl@0: OstTraceFunctionEntry1( TPARTITIONTABLESCANNER_MAKEENTRY_ENTRY, this ); sl@0: if (iNextEntry == iLimit) sl@0: { sl@0: OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT1, this, KErrOverflow ); sl@0: return KErrOverflow; sl@0: } sl@0: if (a.iRSS<=0 || a.iSectors<=0 || a.iRSS>=iMediaSize) sl@0: { sl@0: OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT2, this, KErrCorrupt ); sl@0: return KErrCorrupt; sl@0: } sl@0: if (TUint64(a.iRSS) + TUint64(a.iSectors) > TUint64(iMediaSize)) sl@0: { sl@0: OstTraceFunctionExitExt( TPARTITIONTABLESCANNER_MAKEENTRY_EXIT3, this, KErrCorrupt ); sl@0: return KErrCorrupt; sl@0: } sl@0: iNextEntry->iBootIndicator = a.iBootInd; sl@0: iNextEntry->iPartitionType = a.iType; sl@0: iNextEntry->iPartitionBaseAddr = TInt64(a.iRSS)<iPartitionLen = TInt64(a.iSectors)<TPartitionTableScanner iLBA=%08x %08x", I64HIGH(iLBA), I64LOW(iLBA))); sl@0: OstTraceExt2( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NEXTLBA1, "TPartitionTableScanner iLBA=%08x %08x", I64HIGH(iLBA), I64LOW(iLBA) ); sl@0: TInt r; sl@0: TUint8* b = iSectorBuffer; sl@0: TUint8* pS = b + 0x1be; sl@0: TUint8* pE = pS + 64; sl@0: TUint8* p = pS; sl@0: TInt orig_sp = iStackPointer; sl@0: TInt sp; sl@0: if (iLBA < 0) sl@0: { sl@0: iLBA = 0; sl@0: goto end; sl@0: } sl@0: __KTRACE_OPT(KLOCDRV,DMEMDUMP(b, ESectorSize)); sl@0: if (b[ESectorSize-2]!=0x55 || b[ESectorSize-1]!=0xaa) sl@0: { sl@0: __KTRACE_OPT(KLOCDRV, Kern::Printf("Bad signature")); sl@0: OstTrace0( TRACE_INTERNALS, TPARTITIONTABLESCANNER_NEXTLBA2, "Bad signature" ); sl@0: iLBA = KErrCorrupt; sl@0: goto end; sl@0: } sl@0: if (iLBA==0 && iNextEntry==iFirstEntry) sl@0: { sl@0: // Look for bootable partition first sl@0: for (; p0) sl@0: { sl@0: p[4] = 0; sl@0: r = MakeEntry(pt); sl@0: if (r!=KErrNone) sl@0: { sl@0: iLBA = r; sl@0: goto end; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: // Look for extended partitions sl@0: for (p=pE-16; p>=pS; p-=16) sl@0: { sl@0: SPart pt(p); sl@0: if ((pt.iType==0x05 || pt.iType==0x0f) && pt.iSectors>0) sl@0: { sl@0: // This one is an EBR sl@0: p[4] = 0; sl@0: if (iStackPointer == EMaxNest) sl@0: { sl@0: if (iStackPointer == orig_sp) sl@0: continue; sl@0: --iStackPointer; sl@0: for(sp = orig_sp; sp0) sl@0: { sl@0: pt.iRSS += TUint32(iLBA); // data partitions are specified relative to the EBR they appear in sl@0: r = MakeEntry(pt); sl@0: if (r!=KErrNone) sl@0: { sl@0: iLBA = r; sl@0: goto end; sl@0: } sl@0: } sl@0: } sl@0: // If any EBRs on stack, pop off the first and process it sl@0: if (iStackPointer) sl@0: { sl@0: --iStackPointer; sl@0: iLBA = iFirstEBR + iStack[iStackPointer].iRSS; // LBA of second and subsequent EBR is specified relative to first EBR sl@0: if (!iFirstEBR) sl@0: iFirstEBR = iLBA; sl@0: } sl@0: else sl@0: iLBA = KErrEof; // finished sl@0: sl@0: end: sl@0: __KTRACE_OPT(KLOCDRV, Kern::Printf(" TLocDrvRequest::GetNextPhysicalAddress;aAddr=%x;aLen=%d;", (TUint) &aAddr, aLen ); sl@0: if (Flags() & EPhysAddr) sl@0: { sl@0: #ifdef __DEMAND_PAGING__ sl@0: if (DMediaPagingDevice::PagingRequest(*this)) sl@0: { sl@0: return DDmaHelper::GetPhysicalAddress(*this, aAddr, aLen); sl@0: } sl@0: #endif sl@0: return Drive()->iDmaHelper->GetPhysicalAddress(aAddr, aLen); sl@0: } sl@0: else sl@0: { sl@0: OstTraceFunctionExitExt( TLOCDRVREQUEST_GETNEXTPHYSICALADDRESS_EXIT, this, KErrNotSupported ); sl@0: return KErrNotSupported; sl@0: } sl@0: } sl@0: sl@0: sl@0: /****************************************************************************** sl@0: Entry point sl@0: ******************************************************************************/ sl@0: DECLARE_STANDARD_EXTENSION() sl@0: { sl@0: __KTRACE_OPT(KBOOT,Kern::Printf("Starting LOCMEDIA extension")); sl@0: sl@0: // install the HAL function sl@0: TInt r=Kern::AddHalEntry(EHalGroupMedia,MediaHalFunction,NULL); sl@0: #ifdef __DEMAND_PAGING__ sl@0: if (r==KErrNone) sl@0: { sl@0: __KTRACE_OPT(KBOOT,Kern::Printf("Creating LocDrv device")); sl@0: DLocalDriveFactory* device = new DLocalDriveFactory; sl@0: if (device==NULL) sl@0: r=KErrNoMemory; sl@0: else sl@0: r=Kern::InstallLogicalDevice(device); sl@0: __KTRACE_OPT(KBOOT,Kern::Printf("Installing LocDrv device in kernel returned %d",r)); sl@0: } sl@0: #endif // __DEMAND_PAGING__ sl@0: return r; sl@0: } sl@0: sl@0: